mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 15:36:49 +08:00
fix pwa
This commit is contained in:
+63
-35
@@ -4,51 +4,79 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover, user-scalable=0" />
|
||||||
<title>MoviePilot</title>
|
<title>MoviePilot</title>
|
||||||
<meta name="Robots" content="noindex,nofollow,noarchive">
|
<meta name="Robots" content="noindex,nofollow,noarchive">
|
||||||
<link rel="icon" type="image/png" href="/logo.png">
|
<link rel="icon" type="image/png" href="/logo.png">
|
||||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2048-2732.png" media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-750-1334.png">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2732-2048.png" media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2048-2732.png"
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1668-2388.png" media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2388-1668.png" media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2732-2048.png"
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1536-2048.png" media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2048-1536.png" media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1668-2388.png"
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1668-2224.png" media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2224-1668.png" media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2388-1668.png"
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1620-2160.png" media="(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2160-1620.png" media="(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1536-2048.png"
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1284-2778.png" media="(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
|
media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2778-1284.png" media="(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2048-1536.png"
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1170-2532.png" media="(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
|
media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2532-1170.png" media="(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1668-2224.png"
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1125-2436.png" media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
|
media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2436-1125.png" media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2224-1668.png"
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1242-2688.png" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
|
media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2688-1242.png" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1620-2160.png"
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-828-1792.png" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
media="(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1792-828.png" media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2160-1620.png"
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1242-2208.png" media="(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
|
media="(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2208-1242.png" media="(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1284-2778.png"
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-750-1334.png" media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
media="(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1334-750.png" media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2778-1284.png"
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-640-1136.png" media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
media="(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
|
||||||
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1136-640.png" media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1170-2532.png"
|
||||||
|
media="(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
|
||||||
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2532-1170.png"
|
||||||
|
media="(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
|
||||||
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1125-2436.png"
|
||||||
|
media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
|
||||||
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2436-1125.png"
|
||||||
|
media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
|
||||||
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1242-2688.png"
|
||||||
|
media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
|
||||||
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2688-1242.png"
|
||||||
|
media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
|
||||||
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-828-1792.png"
|
||||||
|
media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
||||||
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1792-828.png"
|
||||||
|
media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
||||||
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1242-2208.png"
|
||||||
|
media="(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)">
|
||||||
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-2208-1242.png"
|
||||||
|
media="(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)">
|
||||||
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-750-1334.png"
|
||||||
|
media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
||||||
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1334-750.png"
|
||||||
|
media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
||||||
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-640-1136.png"
|
||||||
|
media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)">
|
||||||
|
<link rel="apple-touch-startup-image" href="/splash/apple-splash-1136-640.png"
|
||||||
|
media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)">
|
||||||
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
|
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
|
||||||
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
|
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
|
||||||
<meta name="mobile-web-app-capable" content="yes"/>
|
<meta name="mobile-web-app-capable" content="yes" />
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||||
<meta name="apple-mobile-web-app-title" content="NAStool">
|
<meta name="apple-mobile-web-app-title" content="NAStool">
|
||||||
<meta name="description" content="MoviePilot">
|
<meta name="description" content="MoviePilot">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
<meta name="referrer" content="never">
|
<meta name="referrer" content="never">
|
||||||
<meta name="msapplication-TileColor" content="#F4F5FA"/>
|
<meta name="msapplication-TileColor" content="#F1F2F9" />
|
||||||
<meta name="theme-color" content="#28243D" media="(prefers-color-scheme: dark)">
|
<meta name="theme-color" content="#1E1A2E" media="(prefers-color-scheme: dark)">
|
||||||
<meta name="theme-color" content="#F4F5FA" media="(prefers-color-scheme: light)">
|
<meta name="theme-color" content="#F1F2F9" media="(prefers-color-scheme: light)">
|
||||||
<meta name="HandheldFriendly" content="True"/>
|
<meta name="HandheldFriendly" content="True" />
|
||||||
<meta name="MobileOptimized" content="320"/>
|
<meta name="MobileOptimized" content="320" />
|
||||||
<link rel="stylesheet" type="text/css" href="/loader.css" />
|
<link rel="stylesheet" type="text/css" href="/loader.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@@ -93,4 +121,4 @@
|
|||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -28,8 +28,8 @@
|
|||||||
"purpose": "maskable"
|
"purpose": "maskable"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"theme_color": "#28243D",
|
"theme_color": "#7D34FD",
|
||||||
"background_color": "#28243D",
|
"background_color": "#1E1A2E",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"shortcuts": [
|
"shortcuts": [
|
||||||
{
|
{
|
||||||
@@ -77,4 +77,4 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ $card-spacer-content: 16px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bg-var-theme-background {
|
.bg-var-theme-background {
|
||||||
background-color: rgba(var(--v-theme-on-background), var(--v-hover-opacity)) !important;
|
background-color: rgba(var(--v-theme-background), var(--v-hover-opacity)) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
// [/^bg-light-(\w+)$/, ([, w]) => ({ backgroundColor: `rgba(var(--v-theme-${w}), var(--v-activated-opacity))` })],
|
// [/^bg-light-(\w+)$/, ([, w]) => ({ backgroundColor: `rgba(var(--v-theme-${w}), var(--v-activated-opacity))` })],
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ h6,
|
|||||||
color: rgba(var(--v-theme-on-background), var(--v-high-emphasis-opacity));
|
color: rgba(var(--v-theme-on-background), var(--v-high-emphasis-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-application,
|
|
||||||
.text-body-1,
|
.text-body-1,
|
||||||
.text-body-2,
|
.text-body-2,
|
||||||
.text-subtitle-1,
|
.text-subtitle-1,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
// If navbar is contained => Squeeze navbar content on scroll
|
// If navbar is contained => Squeeze navbar content on scroll
|
||||||
@if variables.$layout-vertical-nav-navbar-is-contained {
|
@if variables.$layout-vertical-nav-navbar-is-contained {
|
||||||
padding-inline: 1.2rem;
|
padding-inline: 1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ h6,
|
|||||||
color: rgba(var(--v-theme-on-background), var(--v-high-emphasis-opacity));
|
color: rgba(var(--v-theme-on-background), var(--v-high-emphasis-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-application,
|
|
||||||
.text-body-1,
|
.text-body-1,
|
||||||
.text-body-2,
|
.text-body-2,
|
||||||
.text-subtitle-1,
|
.text-subtitle-1,
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import VerticalNav from '@layouts/components/VerticalNav.vue'
|
import VerticalNav from "@layouts/components/VerticalNav.vue";
|
||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from "vuetify";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
setup(props, { slots }) {
|
setup(props, { slots }) {
|
||||||
const isOverlayNavActive = ref(false)
|
const isOverlayNavActive = ref(false);
|
||||||
const isLayoutOverlayVisible = ref(false)
|
const isLayoutOverlayVisible = ref(false);
|
||||||
const toggleIsOverlayNavActive = useToggle(isOverlayNavActive)
|
const toggleIsOverlayNavActive = useToggle(isOverlayNavActive);
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute();
|
||||||
const { mdAndDown } = useDisplay()
|
const { mdAndDown } = useDisplay();
|
||||||
|
|
||||||
// ℹ️ This is alternative to below two commented watcher
|
// ℹ️ This is alternative to below two commented watcher
|
||||||
// We want to show overlay if overlay nav is visible and want to hide overlay if overlay is hidden and vice versa.
|
// We want to show overlay if overlay nav is visible and want to hide overlay if overlay is hidden and vice versa.
|
||||||
syncRef(isOverlayNavActive, isLayoutOverlayVisible)
|
syncRef(isOverlayNavActive, isLayoutOverlayVisible);
|
||||||
|
|
||||||
const scrollDistance = ref(window.scrollY)
|
const scrollDistance = ref(window.scrollY);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
window.addEventListener('scroll', () => {
|
window.addEventListener("scroll", () => {
|
||||||
scrollDistance.value = window.scrollY
|
scrollDistance.value = window.scrollY;
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
// 👉 Vertical nav
|
// 👉 Vertical nav
|
||||||
@@ -29,84 +29,63 @@ export default defineComponent({
|
|||||||
VerticalNav,
|
VerticalNav,
|
||||||
{ isOverlayNavActive: isOverlayNavActive.value, toggleIsOverlayNavActive },
|
{ isOverlayNavActive: isOverlayNavActive.value, toggleIsOverlayNavActive },
|
||||||
{
|
{
|
||||||
'nav-header': () => slots['vertical-nav-header']?.(),
|
"nav-header": () => slots["vertical-nav-header"]?.(),
|
||||||
'before-nav-items': () => slots['before-vertical-nav-items']?.(),
|
"before-nav-items": () => slots["before-vertical-nav-items"]?.(),
|
||||||
'default': () => slots['vertical-nav-content']?.(),
|
default: () => slots["vertical-nav-content"]?.(),
|
||||||
'after-nav-items': () => slots['after-vertical-nav-items']?.(),
|
"after-nav-items": () => slots["after-vertical-nav-items"]?.(),
|
||||||
},
|
}
|
||||||
)
|
);
|
||||||
|
|
||||||
// 👉 Navbar
|
// 👉 Navbar
|
||||||
const navbar = h(
|
const navbar = h("header", { class: ["layout-navbar navbar-blur"] }, [
|
||||||
'header',
|
h(
|
||||||
{ class: ['layout-navbar navbar-blur'] },
|
"div",
|
||||||
[
|
{ class: "navbar-content-container" },
|
||||||
h(
|
slots.navbar?.({
|
||||||
'div',
|
toggleVerticalOverlayNavActive: toggleIsOverlayNavActive,
|
||||||
{ class: 'navbar-content-container' },
|
})
|
||||||
slots.navbar?.({
|
),
|
||||||
toggleVerticalOverlayNavActive: toggleIsOverlayNavActive,
|
]);
|
||||||
}),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
const main = h(
|
const main = h(
|
||||||
'main',
|
"main",
|
||||||
{ class: 'layout-page-content' },
|
{ class: "layout-page-content" },
|
||||||
h('div', { class: 'page-content-container' }, slots.default?.()),
|
h("div", { class: "page-content-container" }, slots.default?.())
|
||||||
)
|
);
|
||||||
|
|
||||||
// 👉 Footer
|
// 👉 Footer
|
||||||
const footer = h(
|
const footer = h("footer", { class: "layout-footer" }, [
|
||||||
'footer',
|
h("div", { class: "footer-content-container" }, slots.footer?.()),
|
||||||
{ class: 'layout-footer' },
|
]);
|
||||||
[
|
|
||||||
h(
|
|
||||||
'div',
|
|
||||||
{ class: 'footer-content-container' },
|
|
||||||
slots.footer?.(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
// 👉 Overlay
|
// 👉 Overlay
|
||||||
const layoutOverlay = h(
|
const layoutOverlay = h("div", {
|
||||||
'div',
|
class: ["layout-overlay", { visible: isLayoutOverlayVisible.value }],
|
||||||
{
|
onClick: () => {
|
||||||
class: ['layout-overlay', { visible: isLayoutOverlayVisible.value }],
|
isLayoutOverlayVisible.value = !isLayoutOverlayVisible.value;
|
||||||
onClick: () => { isLayoutOverlayVisible.value = !isLayoutOverlayVisible.value },
|
|
||||||
},
|
},
|
||||||
)
|
});
|
||||||
|
|
||||||
return h(
|
return h(
|
||||||
'div',
|
"div",
|
||||||
{
|
{
|
||||||
class: [
|
class: [
|
||||||
'layout-wrapper layout-nav-type-vertical layout-navbar-static layout-footer-static layout-content-width-fluid',
|
"layout-wrapper layout-nav-type-vertical layout-navbar-static layout-footer-static layout-content-width-fluid",
|
||||||
'layout-navbar-sticky',
|
"layout-navbar-sticky",
|
||||||
mdAndDown.value && 'layout-overlay-nav',
|
mdAndDown.value && "layout-overlay-nav",
|
||||||
route.meta.layoutWrapperClasses,
|
route.meta.layoutWrapperClasses,
|
||||||
(scrollDistance.value > 20) && 'window-scrolled',
|
scrollDistance.value > 20 && "window-scrolled",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
verticalNav,
|
verticalNav,
|
||||||
h(
|
h("div", { class: "layout-content-wrapper" }, [navbar, main, footer]),
|
||||||
'div',
|
|
||||||
{ class: 'layout-content-wrapper' },
|
|
||||||
[
|
|
||||||
navbar,
|
|
||||||
main,
|
|
||||||
footer,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
layoutOverlay,
|
layoutOverlay,
|
||||||
],
|
]
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -5,11 +5,17 @@
|
|||||||
@use "@configured-variables" as variables;
|
@use "@configured-variables" as variables;
|
||||||
|
|
||||||
html {
|
html {
|
||||||
min-height: calc(100% + env(safe-area-inset-top))
|
min-height: calc(100% + env(safe-area-inset-top));
|
||||||
}
|
}
|
||||||
|
|
||||||
body, #app {
|
body,
|
||||||
min-block-size: 100%;
|
#app,
|
||||||
|
.v-application {
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-vertical-nav, .layout-navbar {
|
||||||
|
padding-top: env(safe-area-inset-top);
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-page-content {
|
.layout-page-content {
|
||||||
|
|||||||
@@ -7,4 +7,5 @@
|
|||||||
|
|
||||||
html {
|
html {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
min-height: calc(100% + env(safe-area-inset-top))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import UserProfile from "@/layouts/components/UserProfile.vue";
|
|||||||
<template #navbar="{ toggleVerticalOverlayNavActive }">
|
<template #navbar="{ toggleVerticalOverlayNavActive }">
|
||||||
<div class="d-flex h-100 align-center">
|
<div class="d-flex h-100 align-center">
|
||||||
<!-- 👉 Vertical nav toggle in overlay mode -->
|
<!-- 👉 Vertical nav toggle in overlay mode -->
|
||||||
<IconBtn class="ms-n3 d-lg-none" @click="toggleVerticalOverlayNavActive(true)">
|
<IconBtn class="ms-n2 d-lg-none" @click="toggleVerticalOverlayNavActive(true)">
|
||||||
<VIcon icon="mdi-menu" />
|
<VIcon icon="mdi-menu" />
|
||||||
</IconBtn>
|
</IconBtn>
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ import UserProfile from "@/layouts/components/UserProfile.vue";
|
|||||||
</IconBtn>
|
</IconBtn>
|
||||||
|
|
||||||
<span class="d-none d-md-flex align-center text-disabled">
|
<span class="d-none d-md-flex align-center text-disabled">
|
||||||
<span class="me-3">Search</span>
|
<span class="me-3">搜索</span>
|
||||||
<span class="meta-key">⌘K</span>
|
<span class="meta-key">⌘K</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+51
-81
@@ -1,119 +1,111 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { requiredValidator } from '@/@validators';
|
import { requiredValidator } from "@/@validators";
|
||||||
import api from '@/api';
|
import api from "@/api";
|
||||||
import router from '@/router';
|
import router from "@/router";
|
||||||
import logo from '@images/logo.svg?raw';
|
import logo from "@images/logo.svg?raw";
|
||||||
import type { VForm } from 'vuetify/components/VForm';
|
import type { VForm } from "vuetify/components/VForm";
|
||||||
import { useStore } from 'vuex';
|
import { useStore } from "vuex";
|
||||||
|
|
||||||
// Vuex Store
|
// Vuex Store
|
||||||
const store = useStore()
|
const store = useStore();
|
||||||
|
|
||||||
// 表单
|
// 表单
|
||||||
const form = ref({
|
const form = ref({
|
||||||
username: '',
|
username: "",
|
||||||
password: '',
|
password: "",
|
||||||
remember: true,
|
remember: true,
|
||||||
})
|
});
|
||||||
const refForm = ref<InstanceType<typeof VForm> | null>(null)
|
const refForm = ref<InstanceType<typeof VForm> | null>(null);
|
||||||
|
|
||||||
// 密码输入
|
// 密码输入
|
||||||
const isPasswordVisible = ref(false)
|
const isPasswordVisible = ref(false);
|
||||||
|
|
||||||
// 错误信息
|
// 错误信息
|
||||||
const errorMessage = ref('')
|
const errorMessage = ref("");
|
||||||
|
|
||||||
// 背景图片
|
// 背景图片
|
||||||
const backgroundImageUrl = ref('')
|
const backgroundImageUrl = ref("");
|
||||||
|
|
||||||
// 获取背景图片
|
// 获取背景图片
|
||||||
const fetchBackgroundImage = async () => {
|
const fetchBackgroundImage = async () => {
|
||||||
api
|
api
|
||||||
.get('/login/wallpaper')
|
.get("/login/wallpaper")
|
||||||
.then((response: any) => {
|
.then((response: any) => {
|
||||||
backgroundImageUrl.value = response.message
|
backgroundImageUrl.value = response.message;
|
||||||
})
|
})
|
||||||
.catch((error: any) => {
|
.catch((error: any) => {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// 登录获取token事件
|
// 登录获取token事件
|
||||||
const login = () => {
|
const login = () => {
|
||||||
errorMessage.value = ''
|
errorMessage.value = "";
|
||||||
// 进行表单校验
|
// 进行表单校验
|
||||||
if (!form.value.username || !form.value.password) {
|
if (!form.value.username || !form.value.password) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户名密码
|
// 用户名密码
|
||||||
const formData = new FormData()
|
const formData = new FormData();
|
||||||
|
|
||||||
formData.append('username', form.value.username)
|
formData.append("username", form.value.username);
|
||||||
formData.append('password', form.value.password)
|
formData.append("password", form.value.password);
|
||||||
|
|
||||||
// 请求token
|
// 请求token
|
||||||
api
|
api
|
||||||
.post('/login/access-token', formData, {
|
.post("/login/access-token", formData, {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json', // 设置 Accept 类型
|
Accept: "application/json", // 设置 Accept 类型
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((response: any) => {
|
.then((response: any) => {
|
||||||
// 获取token
|
// 获取token
|
||||||
const token = response.access_token
|
const token = response.access_token;
|
||||||
|
|
||||||
// 更新token和remember状态到Vuex Store
|
// 更新token和remember状态到Vuex Store
|
||||||
store.dispatch('auth/updateToken', token)
|
store.dispatch("auth/updateToken", token);
|
||||||
store.dispatch('auth/updateRemember', form.value.remember)
|
store.dispatch("auth/updateRemember", form.value.remember);
|
||||||
|
|
||||||
// 跳转到首页
|
// 跳转到首页
|
||||||
router.push('/')
|
router.push("/");
|
||||||
})
|
})
|
||||||
.catch((error: any) => {
|
.catch((error: any) => {
|
||||||
// 登录失败,显示错误提示
|
// 登录失败,显示错误提示
|
||||||
if (!error.response)
|
if (!error.response) errorMessage.value = "登录失败,请检查网络连接";
|
||||||
errorMessage.value = '登录失败,请检查网络连接'
|
|
||||||
|
|
||||||
else if (error.response.status === 401)
|
else if (error.response.status === 401)
|
||||||
errorMessage.value = '登录失败,请检查用户名和密码是否正确'
|
errorMessage.value = "登录失败,请检查用户名和密码是否正确";
|
||||||
|
|
||||||
else if (error.response.status === 403)
|
else if (error.response.status === 403)
|
||||||
errorMessage.value = '登录失败,您没有权限访问'
|
errorMessage.value = "登录失败,您没有权限访问";
|
||||||
|
else if (error.response.status === 500) errorMessage.value = "登录失败,服务器错误";
|
||||||
else if (error.response.status === 500)
|
|
||||||
errorMessage.value = '登录失败,服务器错误'
|
|
||||||
|
|
||||||
else
|
else
|
||||||
errorMessage.value = `登录失败 ${error.response.status},请检查用户名和密码是否正确`
|
errorMessage.value = `登录失败 ${error.response.status},请检查用户名和密码是否正确`;
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// 自动登录
|
// 自动登录
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 从Vuex Store中获取token和remember状态
|
// 从Vuex Store中获取token和remember状态
|
||||||
const token = store.state.auth.token
|
const token = store.state.auth.token;
|
||||||
const remember = store.state.auth.remember
|
const remember = store.state.auth.remember;
|
||||||
|
|
||||||
// 如果token存在,且保持登录状态为true,则跳转到首页
|
// 如果token存在,且保持登录状态为true,则跳转到首页
|
||||||
if (token && remember) {
|
if (token && remember) {
|
||||||
router.push('/')
|
router.push("/");
|
||||||
|
} else {
|
||||||
|
// 获取背景图片
|
||||||
|
fetchBackgroundImage();
|
||||||
}
|
}
|
||||||
else {
|
});
|
||||||
// 获取背景图片
|
|
||||||
fetchBackgroundImage()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="auth-wrapper d-flex align-center justify-center pa-4 fade-in"
|
class="auth-wrapper d-flex align-center justify-center pa-4 fade-in w-full h-full overflow-hidden"
|
||||||
:style="{ backgroundImage: `url(${backgroundImageUrl})` }"
|
:style="{ backgroundImage: `url(${backgroundImageUrl})` }"
|
||||||
>
|
>
|
||||||
<VCard class="auth-card pa-7">
|
<VCard class="auth-card pa-7" width="25rem">
|
||||||
<VCardItem class="justify-center">
|
<VCardItem class="justify-center mb-7">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<div v-html="logo" />
|
<div v-html="logo" />
|
||||||
@@ -125,17 +117,8 @@ onMounted(() => {
|
|||||||
</VCardTitle>
|
</VCardTitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
|
|
||||||
<VCardText class="pt-2">
|
|
||||||
<h5 class="text-h5 font-weight-semibold mb-1">
|
|
||||||
欢迎使用 MoviePilot! 👋🏻
|
|
||||||
</h5>
|
|
||||||
<p class="mb-0">
|
|
||||||
请输入用户名密码登录
|
|
||||||
</p>
|
|
||||||
</VCardText>
|
|
||||||
|
|
||||||
<VCardText>
|
<VCardText>
|
||||||
<VForm @submit.prevent="()=>{}" ref="refForm">
|
<VForm @submit.prevent="() => {}" ref="refForm">
|
||||||
<VRow>
|
<VRow>
|
||||||
<!-- username -->
|
<!-- username -->
|
||||||
<VCol cols="12">
|
<VCol cols="12">
|
||||||
@@ -160,30 +143,17 @@ onMounted(() => {
|
|||||||
@click:append-inner="isPasswordVisible = !isPasswordVisible"
|
@click:append-inner="isPasswordVisible = !isPasswordVisible"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div v-if="errorMessage" class="text-error mt-1">
|
||||||
v-if="errorMessage"
|
|
||||||
class="text-error mt-1"
|
|
||||||
>
|
|
||||||
{{ errorMessage }}
|
{{ errorMessage }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- remember me checkbox -->
|
<!-- remember me checkbox -->
|
||||||
<div class="d-flex align-center justify-space-between flex-wrap mt-1 mb-4">
|
<div class="d-flex align-center justify-space-between flex-wrap mt-1 mb-4">
|
||||||
<VCheckbox
|
<VCheckbox v-model="form.remember" label="保持登录" required />
|
||||||
v-model="form.remember"
|
|
||||||
label="保持登录"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- login button -->
|
<!-- login button -->
|
||||||
<VBtn
|
<VBtn block type="submit" @click="login"> 登录 </VBtn>
|
||||||
block
|
|
||||||
type="submit"
|
|
||||||
@click="login"
|
|
||||||
>
|
|
||||||
登录
|
|
||||||
</VBtn>
|
|
||||||
</VCol>
|
</VCol>
|
||||||
</VRow>
|
</VRow>
|
||||||
</VForm>
|
</VForm>
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ export default defineConfig({
|
|||||||
imports: ['vue', 'vue-router', '@vueuse/core', '@vueuse/math', 'vuex'],
|
imports: ['vue', 'vue-router', '@vueuse/core', '@vueuse/math', 'vuex'],
|
||||||
vueTemplate: true,
|
vueTemplate: true,
|
||||||
}),
|
}),
|
||||||
VitePWA({ registerType: 'autoUpdate', injectRegister: 'auto', srcDir: 'public' }),
|
VitePWA({ registerType: 'autoUpdate', injectRegister: 'auto', srcDir: 'public'}),
|
||||||
],
|
],
|
||||||
define: { 'process.env': {} },
|
define: { 'process.env': {} },
|
||||||
resolve: {
|
resolve: {
|
||||||
|
|||||||
Reference in New Issue
Block a user