mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-05-10 17:42:50 +08:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b518d6f33 | ||
|
|
78f57e7d4b | ||
|
|
f710f1bfc0 | ||
|
|
c5d4fc62e6 | ||
|
|
60606d5eb9 | ||
|
|
8751236380 | ||
|
|
2291ce3680 | ||
|
|
16ed589857 | ||
|
|
b59254ca42 | ||
|
|
6e3f9b285d | ||
|
|
8bcff774fa | ||
|
|
9b04b12dec | ||
|
|
b22d81a9e9 | ||
|
|
6c80a3a8cd | ||
|
|
059d836653 | ||
|
|
2c3ecfeb6f | ||
|
|
b07e5eecc3 | ||
|
|
1847bc90cf | ||
|
|
899aaae47c | ||
|
|
bcc05086a4 | ||
|
|
d2cc547875 | ||
|
|
c6127f440e | ||
|
|
c2849ad49f | ||
|
|
9c6ba294f9 | ||
|
|
b2a8707e91 | ||
|
|
193e3085a9 | ||
|
|
2401f38e9f | ||
|
|
4ea65727a1 | ||
|
|
3d6cfe260c | ||
|
|
4c33a09c3c | ||
|
|
8d25743680 | ||
|
|
4bc5b763a2 | ||
|
|
00ea179c90 | ||
|
|
a17d40d2d0 | ||
|
|
62ddd703f1 | ||
|
|
77ab0ccae2 | ||
|
|
f377ac3fcc | ||
|
|
a81becd77b | ||
|
|
a004f1c758 | ||
|
|
b19b015986 | ||
|
|
3f0c1213ad |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '18'
|
||||
node-version: '20'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Download Icons
|
||||
|
||||
@@ -21,14 +21,9 @@
|
||||
}
|
||||
],
|
||||
"rules": {
|
||||
"max-line-length": [
|
||||
120,
|
||||
{
|
||||
"ignore": "comments"
|
||||
}
|
||||
],
|
||||
"liberty/use-logical-spec": true,
|
||||
"selector-class-pattern": null,
|
||||
"color-function-notation": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"fix": true
|
||||
}
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -53,6 +53,7 @@
|
||||
"stylelint",
|
||||
"touchless",
|
||||
"triggerer",
|
||||
"unref",
|
||||
"vuetify"
|
||||
],
|
||||
// Extension: Comment Anchors
|
||||
@@ -104,4 +105,4 @@
|
||||
]
|
||||
},
|
||||
"vue3snippets.enable-compile-vue-file-on-did-save-code": false
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
# MoviePilot-Frontend
|
||||
|
||||
[MoviePilot](https://github.com/jxxghp/MoviePilot) 的前端项目。
|
||||
[MoviePilot](https://github.com/jxxghp/MoviePilot) 的前端项目,NodeJS版本:>= `v20.12.1`。
|
||||
|
||||
## 推荐的IDE设置
|
||||
|
||||
|
||||
322
auto-imports.d.ts
vendored
322
auto-imports.d.ts
vendored
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
export {}
|
||||
declare global {
|
||||
@@ -41,6 +42,7 @@ declare global {
|
||||
const h: typeof import('vue')['h']
|
||||
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const injectLocal: typeof import('@vueuse/core')['injectLocal']
|
||||
const isDefined: typeof import('@vueuse/core')['isDefined']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
@@ -77,6 +79,7 @@ declare global {
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const provideLocal: typeof import('@vueuse/core')['provideLocal']
|
||||
const reactify: typeof import('@vueuse/core')['reactify']
|
||||
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
@@ -105,6 +108,7 @@ declare global {
|
||||
const toReactive: typeof import('@vueuse/core')['toReactive']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const toValue: typeof import('vue')['toValue']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
|
||||
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
|
||||
@@ -143,6 +147,7 @@ declare global {
|
||||
const useCeil: typeof import('@vueuse/math')['useCeil']
|
||||
const useClamp: typeof import('@vueuse/math')['useClamp']
|
||||
const useClipboard: typeof import('@vueuse/core')['useClipboard']
|
||||
const useClipboardItems: typeof import('@vueuse/core')['useClipboardItems']
|
||||
const useCloned: typeof import('@vueuse/core')['useCloned']
|
||||
const useColorMode: typeof import('@vueuse/core')['useColorMode']
|
||||
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
|
||||
@@ -308,11 +313,13 @@ declare global {
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, InjectionKey, PropType, Ref, VNode } from 'vue'
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
|
||||
import('vue')
|
||||
}
|
||||
// for vue template auto import
|
||||
import { UnwrapRef } from 'vue'
|
||||
declare module 'vue' {
|
||||
interface GlobalComponents {}
|
||||
interface ComponentCustomProperties {
|
||||
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
|
||||
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
|
||||
@@ -351,6 +358,7 @@ declare module 'vue' {
|
||||
readonly h: UnwrapRef<typeof import('vue')['h']>
|
||||
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
|
||||
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
||||
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
|
||||
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
|
||||
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
|
||||
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
|
||||
@@ -387,6 +395,7 @@ declare module 'vue' {
|
||||
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
|
||||
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
|
||||
readonly provide: UnwrapRef<typeof import('vue')['provide']>
|
||||
readonly provideLocal: UnwrapRef<typeof import('@vueuse/core')['provideLocal']>
|
||||
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']>
|
||||
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']>
|
||||
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
|
||||
@@ -415,6 +424,7 @@ declare module 'vue' {
|
||||
readonly toReactive: UnwrapRef<typeof import('@vueuse/core')['toReactive']>
|
||||
readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
|
||||
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
|
||||
readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
|
||||
readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
|
||||
readonly tryOnBeforeMount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeMount']>
|
||||
readonly tryOnBeforeUnmount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeUnmount']>
|
||||
@@ -453,6 +463,316 @@ declare module 'vue' {
|
||||
readonly useCeil: UnwrapRef<typeof import('@vueuse/math')['useCeil']>
|
||||
readonly useClamp: UnwrapRef<typeof import('@vueuse/math')['useClamp']>
|
||||
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
|
||||
readonly useClipboardItems: UnwrapRef<typeof import('@vueuse/core')['useClipboardItems']>
|
||||
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
|
||||
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
|
||||
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
|
||||
readonly useCounter: UnwrapRef<typeof import('@vueuse/core')['useCounter']>
|
||||
readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
|
||||
readonly useCssVar: UnwrapRef<typeof import('@vueuse/core')['useCssVar']>
|
||||
readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
|
||||
readonly useCurrentElement: UnwrapRef<typeof import('@vueuse/core')['useCurrentElement']>
|
||||
readonly useCycleList: UnwrapRef<typeof import('@vueuse/core')['useCycleList']>
|
||||
readonly useDark: UnwrapRef<typeof import('@vueuse/core')['useDark']>
|
||||
readonly useDateFormat: UnwrapRef<typeof import('@vueuse/core')['useDateFormat']>
|
||||
readonly useDebounce: UnwrapRef<typeof import('@vueuse/core')['useDebounce']>
|
||||
readonly useDebounceFn: UnwrapRef<typeof import('@vueuse/core')['useDebounceFn']>
|
||||
readonly useDebouncedRefHistory: UnwrapRef<typeof import('@vueuse/core')['useDebouncedRefHistory']>
|
||||
readonly useDeviceMotion: UnwrapRef<typeof import('@vueuse/core')['useDeviceMotion']>
|
||||
readonly useDeviceOrientation: UnwrapRef<typeof import('@vueuse/core')['useDeviceOrientation']>
|
||||
readonly useDevicePixelRatio: UnwrapRef<typeof import('@vueuse/core')['useDevicePixelRatio']>
|
||||
readonly useDevicesList: UnwrapRef<typeof import('@vueuse/core')['useDevicesList']>
|
||||
readonly useDisplayMedia: UnwrapRef<typeof import('@vueuse/core')['useDisplayMedia']>
|
||||
readonly useDocumentVisibility: UnwrapRef<typeof import('@vueuse/core')['useDocumentVisibility']>
|
||||
readonly useDraggable: UnwrapRef<typeof import('@vueuse/core')['useDraggable']>
|
||||
readonly useDropZone: UnwrapRef<typeof import('@vueuse/core')['useDropZone']>
|
||||
readonly useElementBounding: UnwrapRef<typeof import('@vueuse/core')['useElementBounding']>
|
||||
readonly useElementByPoint: UnwrapRef<typeof import('@vueuse/core')['useElementByPoint']>
|
||||
readonly useElementHover: UnwrapRef<typeof import('@vueuse/core')['useElementHover']>
|
||||
readonly useElementSize: UnwrapRef<typeof import('@vueuse/core')['useElementSize']>
|
||||
readonly useElementVisibility: UnwrapRef<typeof import('@vueuse/core')['useElementVisibility']>
|
||||
readonly useEventBus: UnwrapRef<typeof import('@vueuse/core')['useEventBus']>
|
||||
readonly useEventListener: UnwrapRef<typeof import('@vueuse/core')['useEventListener']>
|
||||
readonly useEventSource: UnwrapRef<typeof import('@vueuse/core')['useEventSource']>
|
||||
readonly useEyeDropper: UnwrapRef<typeof import('@vueuse/core')['useEyeDropper']>
|
||||
readonly useFavicon: UnwrapRef<typeof import('@vueuse/core')['useFavicon']>
|
||||
readonly useFetch: UnwrapRef<typeof import('@vueuse/core')['useFetch']>
|
||||
readonly useFileDialog: UnwrapRef<typeof import('@vueuse/core')['useFileDialog']>
|
||||
readonly useFileSystemAccess: UnwrapRef<typeof import('@vueuse/core')['useFileSystemAccess']>
|
||||
readonly useFloor: UnwrapRef<typeof import('@vueuse/math')['useFloor']>
|
||||
readonly useFocus: UnwrapRef<typeof import('@vueuse/core')['useFocus']>
|
||||
readonly useFocusWithin: UnwrapRef<typeof import('@vueuse/core')['useFocusWithin']>
|
||||
readonly useFps: UnwrapRef<typeof import('@vueuse/core')['useFps']>
|
||||
readonly useFullscreen: UnwrapRef<typeof import('@vueuse/core')['useFullscreen']>
|
||||
readonly useGamepad: UnwrapRef<typeof import('@vueuse/core')['useGamepad']>
|
||||
readonly useGeolocation: UnwrapRef<typeof import('@vueuse/core')['useGeolocation']>
|
||||
readonly useIdle: UnwrapRef<typeof import('@vueuse/core')['useIdle']>
|
||||
readonly useImage: UnwrapRef<typeof import('@vueuse/core')['useImage']>
|
||||
readonly useInfiniteScroll: UnwrapRef<typeof import('@vueuse/core')['useInfiniteScroll']>
|
||||
readonly useIntersectionObserver: UnwrapRef<typeof import('@vueuse/core')['useIntersectionObserver']>
|
||||
readonly useInterval: UnwrapRef<typeof import('@vueuse/core')['useInterval']>
|
||||
readonly useIntervalFn: UnwrapRef<typeof import('@vueuse/core')['useIntervalFn']>
|
||||
readonly useKeyModifier: UnwrapRef<typeof import('@vueuse/core')['useKeyModifier']>
|
||||
readonly useLastChanged: UnwrapRef<typeof import('@vueuse/core')['useLastChanged']>
|
||||
readonly useLink: UnwrapRef<typeof import('vue-router')['useLink']>
|
||||
readonly useLocalStorage: UnwrapRef<typeof import('@vueuse/core')['useLocalStorage']>
|
||||
readonly useMagicKeys: UnwrapRef<typeof import('@vueuse/core')['useMagicKeys']>
|
||||
readonly useManualRefHistory: UnwrapRef<typeof import('@vueuse/core')['useManualRefHistory']>
|
||||
readonly useMath: UnwrapRef<typeof import('@vueuse/math')['useMath']>
|
||||
readonly useMax: UnwrapRef<typeof import('@vueuse/math')['useMax']>
|
||||
readonly useMediaControls: UnwrapRef<typeof import('@vueuse/core')['useMediaControls']>
|
||||
readonly useMediaQuery: UnwrapRef<typeof import('@vueuse/core')['useMediaQuery']>
|
||||
readonly useMemoize: UnwrapRef<typeof import('@vueuse/core')['useMemoize']>
|
||||
readonly useMemory: UnwrapRef<typeof import('@vueuse/core')['useMemory']>
|
||||
readonly useMin: UnwrapRef<typeof import('@vueuse/math')['useMin']>
|
||||
readonly useMounted: UnwrapRef<typeof import('@vueuse/core')['useMounted']>
|
||||
readonly useMouse: UnwrapRef<typeof import('@vueuse/core')['useMouse']>
|
||||
readonly useMouseInElement: UnwrapRef<typeof import('@vueuse/core')['useMouseInElement']>
|
||||
readonly useMousePressed: UnwrapRef<typeof import('@vueuse/core')['useMousePressed']>
|
||||
readonly useMutationObserver: UnwrapRef<typeof import('@vueuse/core')['useMutationObserver']>
|
||||
readonly useNavigatorLanguage: UnwrapRef<typeof import('@vueuse/core')['useNavigatorLanguage']>
|
||||
readonly useNetwork: UnwrapRef<typeof import('@vueuse/core')['useNetwork']>
|
||||
readonly useNow: UnwrapRef<typeof import('@vueuse/core')['useNow']>
|
||||
readonly useObjectUrl: UnwrapRef<typeof import('@vueuse/core')['useObjectUrl']>
|
||||
readonly useOffsetPagination: UnwrapRef<typeof import('@vueuse/core')['useOffsetPagination']>
|
||||
readonly useOnline: UnwrapRef<typeof import('@vueuse/core')['useOnline']>
|
||||
readonly usePageLeave: UnwrapRef<typeof import('@vueuse/core')['usePageLeave']>
|
||||
readonly useParallax: UnwrapRef<typeof import('@vueuse/core')['useParallax']>
|
||||
readonly useParentElement: UnwrapRef<typeof import('@vueuse/core')['useParentElement']>
|
||||
readonly usePerformanceObserver: UnwrapRef<typeof import('@vueuse/core')['usePerformanceObserver']>
|
||||
readonly usePermission: UnwrapRef<typeof import('@vueuse/core')['usePermission']>
|
||||
readonly usePointer: UnwrapRef<typeof import('@vueuse/core')['usePointer']>
|
||||
readonly usePointerLock: UnwrapRef<typeof import('@vueuse/core')['usePointerLock']>
|
||||
readonly usePointerSwipe: UnwrapRef<typeof import('@vueuse/core')['usePointerSwipe']>
|
||||
readonly usePrecision: UnwrapRef<typeof import('@vueuse/math')['usePrecision']>
|
||||
readonly usePreferredColorScheme: UnwrapRef<typeof import('@vueuse/core')['usePreferredColorScheme']>
|
||||
readonly usePreferredContrast: UnwrapRef<typeof import('@vueuse/core')['usePreferredContrast']>
|
||||
readonly usePreferredDark: UnwrapRef<typeof import('@vueuse/core')['usePreferredDark']>
|
||||
readonly usePreferredLanguages: UnwrapRef<typeof import('@vueuse/core')['usePreferredLanguages']>
|
||||
readonly usePreferredReducedMotion: UnwrapRef<typeof import('@vueuse/core')['usePreferredReducedMotion']>
|
||||
readonly usePrevious: UnwrapRef<typeof import('@vueuse/core')['usePrevious']>
|
||||
readonly useProjection: UnwrapRef<typeof import('@vueuse/math')['useProjection']>
|
||||
readonly useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']>
|
||||
readonly useRefHistory: UnwrapRef<typeof import('@vueuse/core')['useRefHistory']>
|
||||
readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']>
|
||||
readonly useRound: UnwrapRef<typeof import('@vueuse/math')['useRound']>
|
||||
readonly useRoute: UnwrapRef<typeof import('vue-router')['useRoute']>
|
||||
readonly useRouter: UnwrapRef<typeof import('vue-router')['useRouter']>
|
||||
readonly useScreenOrientation: UnwrapRef<typeof import('@vueuse/core')['useScreenOrientation']>
|
||||
readonly useScreenSafeArea: UnwrapRef<typeof import('@vueuse/core')['useScreenSafeArea']>
|
||||
readonly useScriptTag: UnwrapRef<typeof import('@vueuse/core')['useScriptTag']>
|
||||
readonly useScroll: UnwrapRef<typeof import('@vueuse/core')['useScroll']>
|
||||
readonly useScrollLock: UnwrapRef<typeof import('@vueuse/core')['useScrollLock']>
|
||||
readonly useSessionStorage: UnwrapRef<typeof import('@vueuse/core')['useSessionStorage']>
|
||||
readonly useShare: UnwrapRef<typeof import('@vueuse/core')['useShare']>
|
||||
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
|
||||
readonly useSorted: UnwrapRef<typeof import('@vueuse/core')['useSorted']>
|
||||
readonly useSpeechRecognition: UnwrapRef<typeof import('@vueuse/core')['useSpeechRecognition']>
|
||||
readonly useSpeechSynthesis: UnwrapRef<typeof import('@vueuse/core')['useSpeechSynthesis']>
|
||||
readonly useStepper: UnwrapRef<typeof import('@vueuse/core')['useStepper']>
|
||||
readonly useStorage: UnwrapRef<typeof import('@vueuse/core')['useStorage']>
|
||||
readonly useStorageAsync: UnwrapRef<typeof import('@vueuse/core')['useStorageAsync']>
|
||||
readonly useStore: UnwrapRef<typeof import('vuex')['useStore']>
|
||||
readonly useStyleTag: UnwrapRef<typeof import('@vueuse/core')['useStyleTag']>
|
||||
readonly useSum: UnwrapRef<typeof import('@vueuse/math')['useSum']>
|
||||
readonly useSupported: UnwrapRef<typeof import('@vueuse/core')['useSupported']>
|
||||
readonly useSwipe: UnwrapRef<typeof import('@vueuse/core')['useSwipe']>
|
||||
readonly useTemplateRefsList: UnwrapRef<typeof import('@vueuse/core')['useTemplateRefsList']>
|
||||
readonly useTextDirection: UnwrapRef<typeof import('@vueuse/core')['useTextDirection']>
|
||||
readonly useTextSelection: UnwrapRef<typeof import('@vueuse/core')['useTextSelection']>
|
||||
readonly useTextareaAutosize: UnwrapRef<typeof import('@vueuse/core')['useTextareaAutosize']>
|
||||
readonly useThrottle: UnwrapRef<typeof import('@vueuse/core')['useThrottle']>
|
||||
readonly useThrottleFn: UnwrapRef<typeof import('@vueuse/core')['useThrottleFn']>
|
||||
readonly useThrottledRefHistory: UnwrapRef<typeof import('@vueuse/core')['useThrottledRefHistory']>
|
||||
readonly useTimeAgo: UnwrapRef<typeof import('@vueuse/core')['useTimeAgo']>
|
||||
readonly useTimeout: UnwrapRef<typeof import('@vueuse/core')['useTimeout']>
|
||||
readonly useTimeoutFn: UnwrapRef<typeof import('@vueuse/core')['useTimeoutFn']>
|
||||
readonly useTimeoutPoll: UnwrapRef<typeof import('@vueuse/core')['useTimeoutPoll']>
|
||||
readonly useTimestamp: UnwrapRef<typeof import('@vueuse/core')['useTimestamp']>
|
||||
readonly useTitle: UnwrapRef<typeof import('@vueuse/core')['useTitle']>
|
||||
readonly useToNumber: UnwrapRef<typeof import('@vueuse/core')['useToNumber']>
|
||||
readonly useToString: UnwrapRef<typeof import('@vueuse/core')['useToString']>
|
||||
readonly useToggle: UnwrapRef<typeof import('@vueuse/core')['useToggle']>
|
||||
readonly useTransition: UnwrapRef<typeof import('@vueuse/core')['useTransition']>
|
||||
readonly useTrunc: UnwrapRef<typeof import('@vueuse/math')['useTrunc']>
|
||||
readonly useUrlSearchParams: UnwrapRef<typeof import('@vueuse/core')['useUrlSearchParams']>
|
||||
readonly useUserMedia: UnwrapRef<typeof import('@vueuse/core')['useUserMedia']>
|
||||
readonly useVModel: UnwrapRef<typeof import('@vueuse/core')['useVModel']>
|
||||
readonly useVModels: UnwrapRef<typeof import('@vueuse/core')['useVModels']>
|
||||
readonly useVibrate: UnwrapRef<typeof import('@vueuse/core')['useVibrate']>
|
||||
readonly useVirtualList: UnwrapRef<typeof import('@vueuse/core')['useVirtualList']>
|
||||
readonly useWakeLock: UnwrapRef<typeof import('@vueuse/core')['useWakeLock']>
|
||||
readonly useWebNotification: UnwrapRef<typeof import('@vueuse/core')['useWebNotification']>
|
||||
readonly useWebSocket: UnwrapRef<typeof import('@vueuse/core')['useWebSocket']>
|
||||
readonly useWebWorker: UnwrapRef<typeof import('@vueuse/core')['useWebWorker']>
|
||||
readonly useWebWorkerFn: UnwrapRef<typeof import('@vueuse/core')['useWebWorkerFn']>
|
||||
readonly useWindowFocus: UnwrapRef<typeof import('@vueuse/core')['useWindowFocus']>
|
||||
readonly useWindowScroll: UnwrapRef<typeof import('@vueuse/core')['useWindowScroll']>
|
||||
readonly useWindowSize: UnwrapRef<typeof import('@vueuse/core')['useWindowSize']>
|
||||
readonly watch: UnwrapRef<typeof import('vue')['watch']>
|
||||
readonly watchArray: UnwrapRef<typeof import('@vueuse/core')['watchArray']>
|
||||
readonly watchAtMost: UnwrapRef<typeof import('@vueuse/core')['watchAtMost']>
|
||||
readonly watchDebounced: UnwrapRef<typeof import('@vueuse/core')['watchDebounced']>
|
||||
readonly watchDeep: UnwrapRef<typeof import('@vueuse/core')['watchDeep']>
|
||||
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
|
||||
readonly watchIgnorable: UnwrapRef<typeof import('@vueuse/core')['watchIgnorable']>
|
||||
readonly watchImmediate: UnwrapRef<typeof import('@vueuse/core')['watchImmediate']>
|
||||
readonly watchOnce: UnwrapRef<typeof import('@vueuse/core')['watchOnce']>
|
||||
readonly watchPausable: UnwrapRef<typeof import('@vueuse/core')['watchPausable']>
|
||||
readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
|
||||
readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']>
|
||||
readonly watchThrottled: UnwrapRef<typeof import('@vueuse/core')['watchThrottled']>
|
||||
readonly watchTriggerable: UnwrapRef<typeof import('@vueuse/core')['watchTriggerable']>
|
||||
readonly watchWithFilter: UnwrapRef<typeof import('@vueuse/core')['watchWithFilter']>
|
||||
readonly whenever: UnwrapRef<typeof import('@vueuse/core')['whenever']>
|
||||
}
|
||||
}
|
||||
declare module '@vue/runtime-core' {
|
||||
interface GlobalComponents {}
|
||||
interface ComponentCustomProperties {
|
||||
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
|
||||
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
|
||||
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
|
||||
readonly computed: UnwrapRef<typeof import('vue')['computed']>
|
||||
readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']>
|
||||
readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']>
|
||||
readonly computedInject: UnwrapRef<typeof import('@vueuse/core')['computedInject']>
|
||||
readonly computedWithControl: UnwrapRef<typeof import('@vueuse/core')['computedWithControl']>
|
||||
readonly controlledComputed: UnwrapRef<typeof import('@vueuse/core')['controlledComputed']>
|
||||
readonly controlledRef: UnwrapRef<typeof import('@vueuse/core')['controlledRef']>
|
||||
readonly createApp: UnwrapRef<typeof import('vue')['createApp']>
|
||||
readonly createEventHook: UnwrapRef<typeof import('@vueuse/core')['createEventHook']>
|
||||
readonly createGenericProjection: UnwrapRef<typeof import('@vueuse/math')['createGenericProjection']>
|
||||
readonly createGlobalState: UnwrapRef<typeof import('@vueuse/core')['createGlobalState']>
|
||||
readonly createInjectionState: UnwrapRef<typeof import('@vueuse/core')['createInjectionState']>
|
||||
readonly createLogger: UnwrapRef<typeof import('vuex')['createLogger']>
|
||||
readonly createNamespacedHelpers: UnwrapRef<typeof import('vuex')['createNamespacedHelpers']>
|
||||
readonly createProjection: UnwrapRef<typeof import('@vueuse/math')['createProjection']>
|
||||
readonly createReactiveFn: UnwrapRef<typeof import('@vueuse/core')['createReactiveFn']>
|
||||
readonly createReusableTemplate: UnwrapRef<typeof import('@vueuse/core')['createReusableTemplate']>
|
||||
readonly createSharedComposable: UnwrapRef<typeof import('@vueuse/core')['createSharedComposable']>
|
||||
readonly createStore: UnwrapRef<typeof import('vuex')['createStore']>
|
||||
readonly createTemplatePromise: UnwrapRef<typeof import('@vueuse/core')['createTemplatePromise']>
|
||||
readonly createUnrefFn: UnwrapRef<typeof import('@vueuse/core')['createUnrefFn']>
|
||||
readonly customRef: UnwrapRef<typeof import('vue')['customRef']>
|
||||
readonly debouncedRef: UnwrapRef<typeof import('@vueuse/core')['debouncedRef']>
|
||||
readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']>
|
||||
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
|
||||
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
|
||||
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
|
||||
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
|
||||
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
|
||||
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
|
||||
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
|
||||
readonly h: UnwrapRef<typeof import('vue')['h']>
|
||||
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
|
||||
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
||||
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>
|
||||
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']>
|
||||
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
|
||||
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
|
||||
readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
|
||||
readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
|
||||
readonly logicAnd: UnwrapRef<typeof import('@vueuse/math')['logicAnd']>
|
||||
readonly logicNot: UnwrapRef<typeof import('@vueuse/math')['logicNot']>
|
||||
readonly logicOr: UnwrapRef<typeof import('@vueuse/math')['logicOr']>
|
||||
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
|
||||
readonly mapActions: UnwrapRef<typeof import('vuex')['mapActions']>
|
||||
readonly mapGetters: UnwrapRef<typeof import('vuex')['mapGetters']>
|
||||
readonly mapMutations: UnwrapRef<typeof import('vuex')['mapMutations']>
|
||||
readonly mapState: UnwrapRef<typeof import('vuex')['mapState']>
|
||||
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
|
||||
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
|
||||
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
|
||||
readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
|
||||
readonly onBeforeRouteLeave: UnwrapRef<typeof import('vue-router')['onBeforeRouteLeave']>
|
||||
readonly onBeforeRouteUpdate: UnwrapRef<typeof import('vue-router')['onBeforeRouteUpdate']>
|
||||
readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']>
|
||||
readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
|
||||
readonly onClickOutside: UnwrapRef<typeof import('@vueuse/core')['onClickOutside']>
|
||||
readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']>
|
||||
readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']>
|
||||
readonly onKeyStroke: UnwrapRef<typeof import('@vueuse/core')['onKeyStroke']>
|
||||
readonly onLongPress: UnwrapRef<typeof import('@vueuse/core')['onLongPress']>
|
||||
readonly onMounted: UnwrapRef<typeof import('vue')['onMounted']>
|
||||
readonly onRenderTracked: UnwrapRef<typeof import('vue')['onRenderTracked']>
|
||||
readonly onRenderTriggered: UnwrapRef<typeof import('vue')['onRenderTriggered']>
|
||||
readonly onScopeDispose: UnwrapRef<typeof import('vue')['onScopeDispose']>
|
||||
readonly onServerPrefetch: UnwrapRef<typeof import('vue')['onServerPrefetch']>
|
||||
readonly onStartTyping: UnwrapRef<typeof import('@vueuse/core')['onStartTyping']>
|
||||
readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
|
||||
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
|
||||
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
|
||||
readonly provide: UnwrapRef<typeof import('vue')['provide']>
|
||||
readonly provideLocal: UnwrapRef<typeof import('@vueuse/core')['provideLocal']>
|
||||
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']>
|
||||
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']>
|
||||
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
|
||||
readonly reactiveComputed: UnwrapRef<typeof import('@vueuse/core')['reactiveComputed']>
|
||||
readonly reactiveOmit: UnwrapRef<typeof import('@vueuse/core')['reactiveOmit']>
|
||||
readonly reactivePick: UnwrapRef<typeof import('@vueuse/core')['reactivePick']>
|
||||
readonly readonly: UnwrapRef<typeof import('vue')['readonly']>
|
||||
readonly ref: UnwrapRef<typeof import('vue')['ref']>
|
||||
readonly refAutoReset: UnwrapRef<typeof import('@vueuse/core')['refAutoReset']>
|
||||
readonly refDebounced: UnwrapRef<typeof import('@vueuse/core')['refDebounced']>
|
||||
readonly refDefault: UnwrapRef<typeof import('@vueuse/core')['refDefault']>
|
||||
readonly refThrottled: UnwrapRef<typeof import('@vueuse/core')['refThrottled']>
|
||||
readonly refWithControl: UnwrapRef<typeof import('@vueuse/core')['refWithControl']>
|
||||
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
|
||||
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
|
||||
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
|
||||
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
|
||||
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
|
||||
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
|
||||
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']>
|
||||
readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']>
|
||||
readonly templateRef: UnwrapRef<typeof import('@vueuse/core')['templateRef']>
|
||||
readonly throttledRef: UnwrapRef<typeof import('@vueuse/core')['throttledRef']>
|
||||
readonly throttledWatch: UnwrapRef<typeof import('@vueuse/core')['throttledWatch']>
|
||||
readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']>
|
||||
readonly toReactive: UnwrapRef<typeof import('@vueuse/core')['toReactive']>
|
||||
readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
|
||||
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
|
||||
readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
|
||||
readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
|
||||
readonly tryOnBeforeMount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeMount']>
|
||||
readonly tryOnBeforeUnmount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeUnmount']>
|
||||
readonly tryOnMounted: UnwrapRef<typeof import('@vueuse/core')['tryOnMounted']>
|
||||
readonly tryOnScopeDispose: UnwrapRef<typeof import('@vueuse/core')['tryOnScopeDispose']>
|
||||
readonly tryOnUnmounted: UnwrapRef<typeof import('@vueuse/core')['tryOnUnmounted']>
|
||||
readonly unref: UnwrapRef<typeof import('vue')['unref']>
|
||||
readonly unrefElement: UnwrapRef<typeof import('@vueuse/core')['unrefElement']>
|
||||
readonly until: UnwrapRef<typeof import('@vueuse/core')['until']>
|
||||
readonly useAbs: UnwrapRef<typeof import('@vueuse/math')['useAbs']>
|
||||
readonly useActiveElement: UnwrapRef<typeof import('@vueuse/core')['useActiveElement']>
|
||||
readonly useAnimate: UnwrapRef<typeof import('@vueuse/core')['useAnimate']>
|
||||
readonly useArrayDifference: UnwrapRef<typeof import('@vueuse/core')['useArrayDifference']>
|
||||
readonly useArrayEvery: UnwrapRef<typeof import('@vueuse/core')['useArrayEvery']>
|
||||
readonly useArrayFilter: UnwrapRef<typeof import('@vueuse/core')['useArrayFilter']>
|
||||
readonly useArrayFind: UnwrapRef<typeof import('@vueuse/core')['useArrayFind']>
|
||||
readonly useArrayFindIndex: UnwrapRef<typeof import('@vueuse/core')['useArrayFindIndex']>
|
||||
readonly useArrayFindLast: UnwrapRef<typeof import('@vueuse/core')['useArrayFindLast']>
|
||||
readonly useArrayIncludes: UnwrapRef<typeof import('@vueuse/core')['useArrayIncludes']>
|
||||
readonly useArrayJoin: UnwrapRef<typeof import('@vueuse/core')['useArrayJoin']>
|
||||
readonly useArrayMap: UnwrapRef<typeof import('@vueuse/core')['useArrayMap']>
|
||||
readonly useArrayReduce: UnwrapRef<typeof import('@vueuse/core')['useArrayReduce']>
|
||||
readonly useArraySome: UnwrapRef<typeof import('@vueuse/core')['useArraySome']>
|
||||
readonly useArrayUnique: UnwrapRef<typeof import('@vueuse/core')['useArrayUnique']>
|
||||
readonly useAsyncQueue: UnwrapRef<typeof import('@vueuse/core')['useAsyncQueue']>
|
||||
readonly useAsyncState: UnwrapRef<typeof import('@vueuse/core')['useAsyncState']>
|
||||
readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']>
|
||||
readonly useAverage: UnwrapRef<typeof import('@vueuse/math')['useAverage']>
|
||||
readonly useBase64: UnwrapRef<typeof import('@vueuse/core')['useBase64']>
|
||||
readonly useBattery: UnwrapRef<typeof import('@vueuse/core')['useBattery']>
|
||||
readonly useBluetooth: UnwrapRef<typeof import('@vueuse/core')['useBluetooth']>
|
||||
readonly useBreakpoints: UnwrapRef<typeof import('@vueuse/core')['useBreakpoints']>
|
||||
readonly useBroadcastChannel: UnwrapRef<typeof import('@vueuse/core')['useBroadcastChannel']>
|
||||
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']>
|
||||
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']>
|
||||
readonly useCeil: UnwrapRef<typeof import('@vueuse/math')['useCeil']>
|
||||
readonly useClamp: UnwrapRef<typeof import('@vueuse/math')['useClamp']>
|
||||
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']>
|
||||
readonly useClipboardItems: UnwrapRef<typeof import('@vueuse/core')['useClipboardItems']>
|
||||
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']>
|
||||
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']>
|
||||
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']>
|
||||
|
||||
4
components.d.ts
vendored
4
components.d.ts
vendored
@@ -3,11 +3,9 @@
|
||||
// @ts-nocheck
|
||||
// Generated by unplugin-vue-components
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import '@vue/runtime-core'
|
||||
|
||||
export {}
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
DialogCloseBtn: typeof import('./src/@core/components/DialogCloseBtn.vue')['default']
|
||||
ErrorHeader: typeof import('./src/@core/components/ErrorHeader.vue')['default']
|
||||
|
||||
62
package.json
62
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "moviepilot",
|
||||
"version": "1.7.9-1",
|
||||
"version": "1.8.1-3",
|
||||
"private": true,
|
||||
"bin": "dist/service.js",
|
||||
"scripts": {
|
||||
@@ -21,18 +21,19 @@
|
||||
"dependencies": {
|
||||
"@casl/ability": "^6.2.0",
|
||||
"@casl/vue": "^2.2.0",
|
||||
"@floating-ui/dom": "1.2.8",
|
||||
"@floating-ui/dom": "1.6.3",
|
||||
"@iconify/utils": "^2.1.22",
|
||||
"@vueuse/core": "^10.1.2",
|
||||
"@vueuse/math": "^10.1.2",
|
||||
"ace-builds": "^1.32.6",
|
||||
"apexcharts-clevision": "^3.28.5",
|
||||
"axios": "1.4.0",
|
||||
"axios": "1.6.8",
|
||||
"axios-mock-adapter": "^1.21.4",
|
||||
"chart.js": "^4.1.2",
|
||||
"colorthief": "^2.4.0",
|
||||
"express": "^4.18.2",
|
||||
"express-http-proxy": "^2.0.0",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"postcss-purgecss": "^5.0.0",
|
||||
"prismjs": "^1.29.0",
|
||||
@@ -42,25 +43,25 @@
|
||||
"sass": "^1.59.3",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"unplugin-vue-define-options": "^1.3.5",
|
||||
"vite-plugin-pwa": "^0.16.4",
|
||||
"vite-plugin-pwa": "^0.19.8",
|
||||
"vue": "^3.3.2",
|
||||
"vue-chartjs": "^5.2.0",
|
||||
"vue-flatpickr-component": "11.0.3",
|
||||
"vue-flatpickr-component": "11.0.5",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-prism-component": "^2.0.0",
|
||||
"vue-router": "^4.2.0",
|
||||
"vue-toast-notification": "^3",
|
||||
"vue3-ace-editor": "^2.2.4",
|
||||
"vue3-apexcharts": "^1.4.1",
|
||||
"vue3-perfect-scrollbar": "^1.6.0",
|
||||
"vuetify": "3.5.7",
|
||||
"vue3-perfect-scrollbar": "^2.0.0",
|
||||
"vuetify": "3.5.14",
|
||||
"vuetify-use-dialog": "^0.6.0",
|
||||
"vuex": "^4.1.0",
|
||||
"vuex-persistedstate": "^4.1.0",
|
||||
"webfontloader": "^1.6.28"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config-vue": "^0.38.6",
|
||||
"@antfu/eslint-config-vue": "^0.43.1",
|
||||
"@fullcalendar/core": "^6.1.8",
|
||||
"@fullcalendar/daygrid": "^6.1.8",
|
||||
"@fullcalendar/interaction": "^6.1.7",
|
||||
@@ -68,43 +69,44 @@
|
||||
"@fullcalendar/timegrid": "^6.1.7",
|
||||
"@fullcalendar/vue3": "^6.1.8",
|
||||
"@iconify-json/mdi": "^1.1.52",
|
||||
"@iconify/tools": "^2.2.0",
|
||||
"@iconify/tools": "^4.0.4",
|
||||
"@iconify/vue": "4.1.1",
|
||||
"@intlify/unplugin-vue-i18n": "^0.10.0",
|
||||
"@intlify/unplugin-vue-i18n": "^4.0.0",
|
||||
"@tailwindcss/aspect-ratio": "^0.4.2",
|
||||
"@types/lodash": "^4.14.197",
|
||||
"@types/node": "^20.1.4",
|
||||
"@types/webfontloader": "^1.6.34",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.5",
|
||||
"@typescript-eslint/parser": "^5.59.5",
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@typescript-eslint/eslint-plugin": "^7.5.0",
|
||||
"@typescript-eslint/parser": "^7.5.0",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@vitejs/plugin-vue-jsx": "^3.0.0",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"eslint": "^8.40.0",
|
||||
"eslint": "^9.0.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-promise": "^6.0.1",
|
||||
"eslint-plugin-regex": "^1.10.0",
|
||||
"eslint-plugin-sonarjs": "^0.19.0",
|
||||
"eslint-plugin-unicorn": "^47.0.0",
|
||||
"eslint-plugin-sonarjs": "^0.25.1",
|
||||
"eslint-plugin-unicorn": "^52.0.0",
|
||||
"eslint-plugin-vue": "^9.12.0",
|
||||
"postcss": "^8.4.24",
|
||||
"lodash": "^4.17.21",
|
||||
"postcss": "8",
|
||||
"postcss-html": "^1.5.0",
|
||||
"stylelint": "14.15.0",
|
||||
"stylelint-config-idiomatic-order": "9.0.0",
|
||||
"stylelint-config-standard-scss": "6.1.0",
|
||||
"stylelint-use-logical-spec": "4.1.0",
|
||||
"type-fest": "^3.10.0",
|
||||
"stylelint": "16.3.1",
|
||||
"stylelint-config-idiomatic-order": "10.0.0",
|
||||
"stylelint-config-standard-scss": "13.1.0",
|
||||
"stylelint-use-logical-spec": "5.0.1",
|
||||
"type-fest": "^4.15.0",
|
||||
"typescript": "^5.0.4",
|
||||
"unplugin-auto-import": "^0.15.1",
|
||||
"unplugin-vue-components": "^0.24.1",
|
||||
"vite": "^4.3.5",
|
||||
"vite-plugin-pages": "^0.29.0",
|
||||
"vite-plugin-vue-layouts": "^0.8.0",
|
||||
"vite-plugin-vuetify": "1.0.2",
|
||||
"unplugin-auto-import": "^0.17.5",
|
||||
"unplugin-vue-components": "^0.26.0",
|
||||
"vite": "^5.2.8",
|
||||
"vite-plugin-pages": "^0.32.1",
|
||||
"vite-plugin-vue-layouts": "^0.11.0",
|
||||
"vite-plugin-vuetify": "2.0.3",
|
||||
"vue-shepherd": "^3.0.0",
|
||||
"vue-tsc": "^1.6.5"
|
||||
"vue-tsc": "^2.0.10"
|
||||
},
|
||||
"packageManager": "yarn@1.22.18",
|
||||
"resolutions": {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import type { Component } from 'vue'
|
||||
import { PerfectScrollbar } from 'vue3-perfect-scrollbar'
|
||||
import { useDisplay } from 'vuetify'
|
||||
import logo from '@images/logo.svg?raw'
|
||||
|
||||
@@ -85,6 +84,7 @@ function handleNavScroll(evt: Event) {
|
||||
.visible {
|
||||
visibility: visible !important;
|
||||
}
|
||||
|
||||
// 👉 Vertical Nav
|
||||
.layout-vertical-nav {
|
||||
position: fixed;
|
||||
@@ -96,8 +96,8 @@ function handleNavScroll(evt: Event) {
|
||||
inset-block-start: 0;
|
||||
inset-inline-start: 0;
|
||||
transition: transform 0.25s ease-in-out, inline-size 0.25s ease-in-out, box-shadow 0.25s ease-in-out;
|
||||
will-change: transform, inline-size;
|
||||
visibility: hidden;
|
||||
will-change: transform, inline-size;
|
||||
|
||||
&:not(.overlay-nav) {
|
||||
visibility: visible;
|
||||
|
||||
@@ -52,7 +52,7 @@ export default defineComponent({
|
||||
'main',
|
||||
{ class: 'layout-page-content' },
|
||||
h(Transition, { name: 'fade-slide', mode: 'out-in', appear: true },
|
||||
h('section', { class: 'page-content-container' }, slots.default?.()),
|
||||
() => h('section', { class: 'page-content-container' }, slots.default?.()),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
@use "_global";
|
||||
@use "vue3-perfect-scrollbar/dist/vue3-perfect-scrollbar.min.css";
|
||||
@use "_classes";
|
||||
|
||||
@@ -4,6 +4,11 @@ import { useTheme } from 'vuetify'
|
||||
|
||||
import store from './store'
|
||||
|
||||
import { fixArrayAt } from '@/@core/utils/compatibility'
|
||||
|
||||
// 修复低版本Safari等浏览器数组不支持at函数的问题
|
||||
fixArrayAt()
|
||||
|
||||
// 提示框
|
||||
const $toast = useToast()
|
||||
|
||||
|
||||
@@ -612,6 +612,9 @@ export interface Plugin {
|
||||
|
||||
// 插件仓库地址
|
||||
repo_url?: string
|
||||
|
||||
// 变更历史
|
||||
history?: { [key: string]: string }
|
||||
}
|
||||
|
||||
// 种子信息
|
||||
|
||||
@@ -25,7 +25,7 @@ function goPlay() {
|
||||
// 计算图片地址
|
||||
const getImgUrl = computed(() => {
|
||||
const image = props.media?.image || ''
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/${encodeURIComponent(image)}/0`
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/0/${encodeURIComponent(image).replace(/%2F/g, '/')}`
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ function goPersonDetail() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VHover v-bind="personProps">
|
||||
<VHover>
|
||||
<template #default="hover">
|
||||
<VCard
|
||||
v-bind="hover.props"
|
||||
|
||||
@@ -30,7 +30,7 @@ function goPersonDetail() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VHover v-bind="personProps">
|
||||
<VHover>
|
||||
<template #default="hover">
|
||||
<VCard
|
||||
v-bind="hover.props"
|
||||
|
||||
@@ -56,7 +56,7 @@ function getImgUrl(url: string) {
|
||||
if (!url)
|
||||
return getDefaultImage()
|
||||
else
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/${encodeURIComponent(url)}/0`
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/0/${encodeURIComponent(url).replace(/%2F/g, '/')}`
|
||||
}
|
||||
|
||||
// 根据多张图片生成媒体库封面
|
||||
@@ -68,7 +68,7 @@ async function drawImages(imageList: string[]) {
|
||||
|
||||
// 为所有图片添加system/img前缀
|
||||
for (let i = 0; i < IMAGES.length; i++)
|
||||
IMAGES[i] = `${import.meta.env.VITE_API_BASE_URL}system/img/${encodeURIComponent(IMAGES[i])}/0`
|
||||
IMAGES[i] = `${import.meta.env.VITE_API_BASE_URL}system/img/0/${encodeURIComponent(IMAGES[i]).replace(/%2F/g, '/')}`
|
||||
|
||||
// canvas
|
||||
const canvas = canvasRef.value
|
||||
|
||||
@@ -166,8 +166,9 @@ async function addSubscribe(season = 0) {
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
doneNProgress()
|
||||
}
|
||||
doneNProgress()
|
||||
}
|
||||
|
||||
// 弹出添加订阅提示
|
||||
@@ -381,6 +382,7 @@ function handleSearch() {
|
||||
keyword: getMediaId(),
|
||||
type: props.media?.type,
|
||||
area: 'title',
|
||||
season: props.media?.season,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -427,7 +429,7 @@ function getYear(airDate: string) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VHover v-bind="props">
|
||||
<VHover>
|
||||
<template #default="hover">
|
||||
<VCard
|
||||
v-bind="hover.props"
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import { useToast } from 'vue-toast-notification'
|
||||
import VersionHistory from '../misc/VersionHistory.vue'
|
||||
import api from '@/api'
|
||||
import type { Plugin } from '@/api/types'
|
||||
import noImage from '@images/logos/plugin.png'
|
||||
import { getDominantColor } from '@/@core/utils/image'
|
||||
import { isNullOrEmptyObject } from '@/@core/utils'
|
||||
|
||||
// 输入参数
|
||||
const props = defineProps({
|
||||
@@ -37,6 +39,9 @@ const isImageLoaded = ref(false)
|
||||
// 图片是否加载失败
|
||||
const imageLoadError = ref(false)
|
||||
|
||||
// 更新日志弹窗
|
||||
const releaseDialog = ref(false)
|
||||
|
||||
// 图片加载完成
|
||||
async function imageLoaded() {
|
||||
isImageLoaded.value = true
|
||||
@@ -86,7 +91,7 @@ const iconPath: Ref<string> = computed(() => {
|
||||
return noImage
|
||||
// 如果是网络图片则使用代理后返回
|
||||
if (props.plugin?.plugin_icon?.startsWith('http'))
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/${encodeURIComponent(props.plugin?.plugin_icon)}/1`
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/1/${encodeURIComponent(props.plugin?.plugin_icon).replace(/%2F/g, '/')}`
|
||||
|
||||
return `./plugin_icon/${props.plugin?.plugin_icon}`
|
||||
})
|
||||
@@ -118,15 +123,29 @@ function visitPluginPage() {
|
||||
window.open(repoUrl, '_blank')
|
||||
}
|
||||
|
||||
// 显示更新日志
|
||||
function showUpdateHistory() {
|
||||
releaseDialog.value = true
|
||||
}
|
||||
|
||||
// 弹出菜单
|
||||
const dropdownItems = ref([
|
||||
{
|
||||
title: '查看详情',
|
||||
title: '项目主页',
|
||||
value: 1,
|
||||
show: true,
|
||||
props: {
|
||||
prependIcon: 'mdi-information-outline',
|
||||
prependIcon: 'mdi-github',
|
||||
click: visitPluginPage,
|
||||
},
|
||||
}, {
|
||||
title: '更新说明',
|
||||
value: 2,
|
||||
show: !isNullOrEmptyObject(props.plugin?.history || {}),
|
||||
props: {
|
||||
prependIcon: 'mdi-update',
|
||||
click: showUpdateHistory,
|
||||
},
|
||||
},
|
||||
])
|
||||
</script>
|
||||
@@ -151,6 +170,7 @@ const dropdownItems = ref([
|
||||
<VList>
|
||||
<VListItem
|
||||
v-for="(item, i) in dropdownItems"
|
||||
v-show="item.show"
|
||||
:key="i"
|
||||
variant="plain"
|
||||
@click="item.props.click"
|
||||
@@ -221,6 +241,19 @@ const dropdownItems = ref([
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
<!-- 更新日志 -->
|
||||
<VDialog
|
||||
v-if="releaseDialog"
|
||||
v-model="releaseDialog"
|
||||
width="600"
|
||||
scrollable
|
||||
>
|
||||
<VCard>
|
||||
<DialogCloseBtn @click="releaseDialog = false" />
|
||||
<VCardTitle>{{ props.plugin?.plugin_name }} 更新说明</VCardTitle>
|
||||
<VersionHistory :history="props.plugin?.history" />
|
||||
</VCard>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -6,6 +6,7 @@ import api from '@/api'
|
||||
import type { Plugin } from '@/api/types'
|
||||
import FormRender from '@/components/render/FormRender.vue'
|
||||
import PageRender from '@/components/render/PageRender.vue'
|
||||
import VersionHistory from '@/components/misc/VersionHistory.vue'
|
||||
import { isNullOrEmptyObject } from '@core/utils'
|
||||
import noImage from '@images/logos/plugin.png'
|
||||
import { getDominantColor } from '@/@core/utils/image'
|
||||
@@ -65,6 +66,9 @@ const isImageLoaded = ref(false)
|
||||
// 图片是否加载失败
|
||||
const imageLoadError = ref(false)
|
||||
|
||||
// 更新日志弹窗
|
||||
const releaseDialog = ref(false)
|
||||
|
||||
// 监听动作标识,如为true则打开详情
|
||||
watch(() => props.action, (newAction, oldAction) => {
|
||||
if (newAction && !oldAction) {
|
||||
@@ -81,6 +85,16 @@ async function imageLoaded() {
|
||||
backgroundColor.value = await getDominantColor(imageElement)
|
||||
}
|
||||
|
||||
// 显示更新日志
|
||||
function showUpdateHistory() {
|
||||
// 检查当前版本是否有更新日志
|
||||
if (isNullOrEmptyObject(props.plugin?.history)) {
|
||||
updatePlugin()
|
||||
} else{
|
||||
releaseDialog.value = true
|
||||
}
|
||||
}
|
||||
|
||||
// 调用API卸载插件
|
||||
async function uninstallPlugin() {
|
||||
const isConfirmed = await createConfirm({
|
||||
@@ -209,7 +223,7 @@ const iconPath: Ref<string> = computed(() => {
|
||||
return noImage
|
||||
// 如果是网络图片则使用代理后返回
|
||||
if (props.plugin?.plugin_icon?.startsWith('http'))
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/${encodeURIComponent(props.plugin?.plugin_icon)}/1`
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/1/${encodeURIComponent(props.plugin?.plugin_icon).replace(/%2F/g, '/')}`
|
||||
|
||||
return `./plugin_icon/${props.plugin?.plugin_icon}`
|
||||
})
|
||||
@@ -251,6 +265,7 @@ async function resetPlugin() {
|
||||
// 更新插件
|
||||
async function updatePlugin() {
|
||||
try {
|
||||
releaseDialog.value = false
|
||||
// 显示等待提示框
|
||||
progressDialog.value = true
|
||||
progressText.value = `正在更新 ${props.plugin?.plugin_name} ...`
|
||||
@@ -330,7 +345,7 @@ const dropdownItems = ref([
|
||||
props: {
|
||||
prependIcon: 'mdi-arrow-up-circle-outline',
|
||||
color: 'success',
|
||||
click: updatePlugin,
|
||||
click: showUpdateHistory,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -544,6 +559,30 @@ watch(() => props.plugin?.has_update, (newHasUpdate, oldHasUpdate) => {
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
<!-- 更新日志 -->
|
||||
<VDialog
|
||||
v-if="releaseDialog"
|
||||
v-model="releaseDialog"
|
||||
width="600"
|
||||
scrollable
|
||||
>
|
||||
<VCard>
|
||||
<DialogCloseBtn @click="releaseDialog = false" />
|
||||
<VCardTitle>{{ props.plugin?.plugin_name }} 更新说明</VCardTitle>
|
||||
<VersionHistory :history="props.plugin?.history" />
|
||||
<VCardText>
|
||||
<VBtn
|
||||
@click="updatePlugin"
|
||||
block
|
||||
>
|
||||
<template #prepend>
|
||||
<VIcon icon="mdi-arrow-up-circle-outline" />
|
||||
</template>
|
||||
更新到最新版本
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -31,7 +31,7 @@ const getImgUrl = computed(() => {
|
||||
if (imageLoadError.value)
|
||||
return noImage
|
||||
const image = props.media?.image || ''
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/${encodeURIComponent(image)}/0`
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/0/${encodeURIComponent(image).replace(/%2F/g, '/')}`
|
||||
})
|
||||
|
||||
// 跳转播放
|
||||
@@ -69,8 +69,9 @@ function goPlay() {
|
||||
<VSkeletonLoader class="object-cover aspect-w-2 aspect-h-3" />
|
||||
</div>
|
||||
</template>
|
||||
<!-- 类型角标 -->
|
||||
<VChip
|
||||
</VImg>
|
||||
<!-- 类型角标 -->
|
||||
<VChip
|
||||
v-show="isImageLoaded"
|
||||
variant="elevated"
|
||||
size="small"
|
||||
@@ -89,7 +90,6 @@ function goPlay() {
|
||||
{{ props.media?.title }}
|
||||
</h1>
|
||||
</VCardText>
|
||||
</VImg>
|
||||
</VCard>
|
||||
</template>
|
||||
</VHover>
|
||||
|
||||
@@ -150,7 +150,7 @@ onMounted(() => {
|
||||
<VCard
|
||||
:height="cardProps.height"
|
||||
:width="cardProps.width"
|
||||
:flat="!cardProps.site?.is_active"
|
||||
:variant="cardProps.site?.is_active ? 'elevated' : 'outlined'"
|
||||
class="overflow-hidden"
|
||||
@click="siteEditDialog = true"
|
||||
>
|
||||
|
||||
@@ -36,7 +36,7 @@ function goPersonDetail() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VHover v-bind="personProps">
|
||||
<VHover>
|
||||
<template #default="hover">
|
||||
<VCard
|
||||
v-bind="hover.props"
|
||||
@@ -61,7 +61,6 @@ function goPersonDetail() {
|
||||
}"
|
||||
>
|
||||
<VImg
|
||||
v-img
|
||||
:src="getPersonImage()"
|
||||
cover
|
||||
@load="isImageLoaded = true"
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useConfirm } from 'vuetify-use-dialog'
|
||||
import { formatFileSize } from '@/@core/utils/formatters'
|
||||
import api from '@/api'
|
||||
import { doneNProgress, startNProgress } from '@/api/nprogress'
|
||||
import type { Context } from '@/api/types'
|
||||
import type { Context, MediaInfo, TorrentInfo } from '@/api/types'
|
||||
|
||||
// 输入参数
|
||||
const props = defineProps({
|
||||
@@ -36,6 +36,9 @@ const meta = ref(props.torrent?.meta_info)
|
||||
// 站点图标
|
||||
const siteIcon = ref('')
|
||||
|
||||
// 存储是否已经下载过的记录
|
||||
const downloaded = ref<String[]>([])
|
||||
|
||||
// 查询站点图标
|
||||
async function getSiteIcon() {
|
||||
try {
|
||||
@@ -76,7 +79,7 @@ async function handleAddDownload(_site: any = undefined,
|
||||
}
|
||||
|
||||
// 添加下载
|
||||
async function addDownload(_media: any, _torrent: any) {
|
||||
async function addDownload(_media: MediaInfo, _torrent: TorrentInfo) {
|
||||
startNProgress()
|
||||
try {
|
||||
const result: { [key: string]: any } = await api.post('download/', {
|
||||
@@ -87,6 +90,7 @@ async function addDownload(_media: any, _torrent: any) {
|
||||
if (result.success) {
|
||||
// 添加下载成功
|
||||
$toast.success(`${_torrent?.site_name} ${_torrent?.title} 添加下载成功!`)
|
||||
downloaded.value.push(_torrent?.enclosure || '')
|
||||
}
|
||||
else {
|
||||
// 添加下载失败
|
||||
@@ -131,6 +135,7 @@ onMounted(() => {
|
||||
<VCard
|
||||
:width="props.width"
|
||||
:height="props.height"
|
||||
:variant="downloaded.includes(torrent?.enclosure || '') ? 'outlined' : 'elevated'"
|
||||
@click="handleAddDownload"
|
||||
>
|
||||
<template
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useConfirm } from 'vuetify-use-dialog'
|
||||
import { formatFileSize } from '@/@core/utils/formatters'
|
||||
import api from '@/api'
|
||||
import { doneNProgress, startNProgress } from '@/api/nprogress'
|
||||
import type { Context } from '@/api/types'
|
||||
import type { Context, MediaInfo, TorrentInfo } from '@/api/types'
|
||||
|
||||
// 输入参数
|
||||
const props = defineProps({
|
||||
@@ -33,6 +33,9 @@ const meta = ref(props.torrent?.meta_info)
|
||||
// 站点图标
|
||||
const siteIcon = ref('')
|
||||
|
||||
// 存储是否已经下载过的记录
|
||||
const downloaded = ref<String[]>([])
|
||||
|
||||
// 查询站点图标
|
||||
async function getSiteIcon() {
|
||||
try {
|
||||
@@ -73,7 +76,7 @@ async function handleAddDownload(_site: any = undefined,
|
||||
}
|
||||
|
||||
// 添加下载
|
||||
async function addDownload(_media: any, _torrent: any) {
|
||||
async function addDownload(_media: MediaInfo, _torrent: TorrentInfo) {
|
||||
startNProgress()
|
||||
try {
|
||||
const result: { [key: string]: any } = await api.post('download/', {
|
||||
@@ -84,6 +87,7 @@ async function addDownload(_media: any, _torrent: any) {
|
||||
if (result.success) {
|
||||
// 添加下载成功
|
||||
$toast.success(`${_torrent?.site_name} ${_torrent?.title} 添加下载成功!`)
|
||||
downloaded.value.push(_torrent?.enclosure || '')
|
||||
}
|
||||
else {
|
||||
// 添加下载失败
|
||||
@@ -125,7 +129,10 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VListItem @click="handleAddDownload">
|
||||
<VListItem
|
||||
@click="handleAddDownload"
|
||||
:variant="downloaded.includes(torrent?.enclosure || '') ? 'outlined' : 'flat'"
|
||||
>
|
||||
<template
|
||||
v-if="!showMoreTorrents"
|
||||
#prepend
|
||||
|
||||
@@ -579,12 +579,14 @@ onMounted(() => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.v-card {
|
||||
height: 100%;
|
||||
block-size: 100%;
|
||||
}
|
||||
|
||||
.v-toolbar{
|
||||
background: rgb(var(--v-table-header-background));
|
||||
}
|
||||
|
||||
.virtual-scroll-div {
|
||||
height: calc(100vh - 230px);
|
||||
block-size: calc(100vh - 14rem);
|
||||
}
|
||||
</style>
|
||||
|
||||
24
src/components/misc/VersionHistory.vue
Normal file
24
src/components/misc/VersionHistory.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue'
|
||||
|
||||
// 输入参数
|
||||
const props = defineProps({
|
||||
history: Object as PropType<{ [key: string]: string }>,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCardItem>
|
||||
<VList>
|
||||
<VListItem
|
||||
v-for="(value, key) in props.history"
|
||||
:key="key"
|
||||
>
|
||||
<VListItemTitle>{{ key }}</VListItemTitle>
|
||||
<div class="text-gray-500">
|
||||
{{ value }}
|
||||
</div>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VCardItem>
|
||||
</template>
|
||||
@@ -1,12 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import SlideViewTitle from '@/components/slide/SlideViewTitle.vue'
|
||||
|
||||
// 输入参数
|
||||
const props = defineProps({
|
||||
linkurl: String,
|
||||
title: String,
|
||||
})
|
||||
|
||||
// 元素
|
||||
const slideview_content = ref()
|
||||
// 分页切换状态
|
||||
@@ -95,7 +89,7 @@ onActivated(() => {
|
||||
<template>
|
||||
<div class="flex justify-between mt-3">
|
||||
<slot name="title">
|
||||
<SlideViewTitle v-bind="props" />
|
||||
<SlideViewTitle />
|
||||
</slot>
|
||||
<div v-if="disabled !== 3" class="me-1 d-none d-md-flex">
|
||||
<VBtn
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
// 输入参数
|
||||
const props = defineProps({
|
||||
linkurl: String,
|
||||
title: String,
|
||||
})
|
||||
const props = inject('rankingPropsKey')
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -242,6 +242,7 @@ onMounted(() => {
|
||||
</VMenu>
|
||||
<!-- 名称测试弹窗 -->
|
||||
<VDialog
|
||||
v-if="nameTestDialog"
|
||||
v-model="nameTestDialog"
|
||||
max-width="50rem"
|
||||
>
|
||||
@@ -254,6 +255,7 @@ onMounted(() => {
|
||||
</VDialog>
|
||||
<!-- 网络测试弹窗 -->
|
||||
<VDialog
|
||||
v-if="netTestDialog"
|
||||
v-model="netTestDialog"
|
||||
max-width="35rem"
|
||||
>
|
||||
@@ -266,6 +268,7 @@ onMounted(() => {
|
||||
</VDialog>
|
||||
<!-- 实时日志弹窗 -->
|
||||
<VDialog
|
||||
v-if="loggingDialog"
|
||||
v-model="loggingDialog"
|
||||
class="w-full lg:w-4/5"
|
||||
scrollable
|
||||
@@ -290,6 +293,7 @@ onMounted(() => {
|
||||
</VDialog>
|
||||
<!-- 规则测试弹窗 -->
|
||||
<VDialog
|
||||
v-if="ruleTestDialog"
|
||||
v-model="ruleTestDialog"
|
||||
max-width="50rem"
|
||||
scrollable
|
||||
@@ -303,6 +307,7 @@ onMounted(() => {
|
||||
</VDialog>
|
||||
<!-- 系统健康检查弹窗 -->
|
||||
<VDialog
|
||||
v-if="systemTestDialog"
|
||||
v-model="systemTestDialog"
|
||||
max-width="50rem"
|
||||
scrollable
|
||||
@@ -316,6 +321,7 @@ onMounted(() => {
|
||||
</VDialog>
|
||||
<!-- 消息中心弹窗 -->
|
||||
<VDialog
|
||||
v-if="messageDialog"
|
||||
v-model="messageDialog"
|
||||
max-width="60rem"
|
||||
scrollable
|
||||
|
||||
@@ -15,6 +15,8 @@ import '@core/scss/template/index.scss'
|
||||
import '@layouts/styles/index.scss'
|
||||
import '@styles/styles.scss'
|
||||
import 'vue-toast-notification/dist/theme-bootstrap.css'
|
||||
import { PerfectScrollbarPlugin } from 'vue3-perfect-scrollbar';
|
||||
import 'vue3-perfect-scrollbar/style.css';
|
||||
|
||||
loadFonts()
|
||||
|
||||
@@ -34,5 +36,6 @@ app
|
||||
position: 'bottom-right',
|
||||
})
|
||||
.use(VuetifyUseDialog)
|
||||
.use(PerfectScrollbarPlugin)
|
||||
.mount('#app')
|
||||
.$nextTick(() => removeEl('#loading-bg'))
|
||||
|
||||
@@ -1,85 +1,82 @@
|
||||
<script setup lang="ts">
|
||||
import MediaCardSlideView from '@/views/discover/MediaCardSlideView.vue'
|
||||
|
||||
const viewList = reactive<{apipath: string, linkurl: string, title: string}[]>([
|
||||
{
|
||||
apipath: 'tmdb/trending',
|
||||
linkurl: "/browse/tmdb/trending?title=流行趋势",
|
||||
title: "流行趋势",
|
||||
},
|
||||
{
|
||||
apipath: "douban/showing",
|
||||
linkurl: "/browse/douban/showing?title=正在热映",
|
||||
title: "正在热映"
|
||||
},
|
||||
{
|
||||
apipath: "bangumi/calendar",
|
||||
linkurl: "/browse/bangumi/calendar?title=Bangumi每日放送",
|
||||
title: "Bangumi每日放送"
|
||||
},
|
||||
{
|
||||
apipath: "tmdb/movies",
|
||||
linkurl: "/browse/tmdb/movies?title=热门电影",
|
||||
title: "热门电影"
|
||||
},
|
||||
{
|
||||
apipath: "tmdb/tvs?with_original_language=zh|en|ja|ko",
|
||||
linkurl: "/browse/tmdb/tvs??with_original_language=zh|en|ja|ko&title=热门电视剧",
|
||||
title: "热门电视剧"
|
||||
},
|
||||
{
|
||||
apipath: "douban/movie_hot",
|
||||
linkurl: "/browse/douban/movie_hot?title=热门电影",
|
||||
title: "热门电影"
|
||||
},
|
||||
{
|
||||
apipath: "douban/tv_hot",
|
||||
linkurl: "/browse/douban/tv_hot?title=热门电视剧",
|
||||
title: "热门电视剧"
|
||||
},
|
||||
{
|
||||
apipath: "douban/tv_animation",
|
||||
linkurl: "/browse/douban/tv_animation?title=热门动漫",
|
||||
title: "热门动漫"
|
||||
},
|
||||
{
|
||||
apipath: "douban/movies",
|
||||
linkurl: "/browse/douban/movies?title=最新电影",
|
||||
title: "最新电影"
|
||||
},
|
||||
{
|
||||
apipath: "douban/tvs",
|
||||
linkurl: "/browse/douban/tvs?title=最新电视剧",
|
||||
title: "最新电视剧"
|
||||
},
|
||||
{
|
||||
apipath: "douban/movie_top250",
|
||||
linkurl: "/browse/douban/movie_top250?title=电影TOP250",
|
||||
title: "电影TOP250"
|
||||
},
|
||||
{
|
||||
apipath: "douban/tv_weekly_chinese",
|
||||
linkurl: "/browse/douban/tv_weekly_chinese?title=国产剧集榜",
|
||||
title: "国产剧集榜"
|
||||
},
|
||||
{
|
||||
apipath: "douban/tv_weekly_global",
|
||||
linkurl: "/browse/douban/tv_weekly_global?title=全球剧集榜",
|
||||
title: "全球剧集榜"
|
||||
}
|
||||
])
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<MediaCardSlideView
|
||||
apipath="tmdb/trending"
|
||||
linkurl="/browse/tmdb/trending?title=流行趋势"
|
||||
title="流行趋势"
|
||||
/>
|
||||
|
||||
<MediaCardSlideView
|
||||
apipath="douban/showing"
|
||||
linkurl="/browse/douban/showing?title=正在热映"
|
||||
title="正在热映"
|
||||
/>
|
||||
|
||||
<MediaCardSlideView
|
||||
apipath="bangumi/calendar"
|
||||
linkurl="/browse/bangumi/calendar?title=Bangumi每日放送"
|
||||
title="Bangumi每日放送"
|
||||
/>
|
||||
|
||||
<MediaCardSlideView
|
||||
apipath="tmdb/movies"
|
||||
linkurl="/browse/tmdb/movies?title=热门电影"
|
||||
title="热门电影"
|
||||
/>
|
||||
|
||||
<MediaCardSlideView
|
||||
apipath="tmdb/tvs?with_original_language=zh|en|ja|ko"
|
||||
linkurl="/browse/tmdb/tvs??with_original_language=zh|en|ja|ko&title=热门电视剧"
|
||||
title="热门电视剧"
|
||||
/>
|
||||
|
||||
<MediaCardSlideView
|
||||
apipath="douban/movie_hot"
|
||||
linkurl="/browse/douban/movie_hot?title=热门电影"
|
||||
title="热门电影"
|
||||
/>
|
||||
|
||||
<MediaCardSlideView
|
||||
apipath="douban/tv_hot"
|
||||
linkurl="/browse/douban/tv_hot?title=热门电视剧"
|
||||
title="热门电视剧"
|
||||
/>
|
||||
|
||||
<MediaCardSlideView
|
||||
apipath="douban/tv_animation"
|
||||
linkurl="/browse/douban/tv_animation?title=热门动漫"
|
||||
title="热门动漫"
|
||||
/>
|
||||
|
||||
<MediaCardSlideView
|
||||
apipath="douban/movies"
|
||||
linkurl="/browse/douban/movies?title=最新电影"
|
||||
title="最新电影"
|
||||
/>
|
||||
|
||||
<MediaCardSlideView
|
||||
apipath="douban/tvs"
|
||||
linkurl="/browse/douban/tvs?title=最新电视剧"
|
||||
title="最新电视剧"
|
||||
/>
|
||||
|
||||
<MediaCardSlideView
|
||||
apipath="douban/movie_top250"
|
||||
linkurl="/browse/douban/movie_top250?title=电影TOP250"
|
||||
title="电影TOP250"
|
||||
/>
|
||||
|
||||
<MediaCardSlideView
|
||||
apipath="douban/tv_weekly_chinese"
|
||||
linkurl="/browse/douban/tv_weekly_chinese?title=国产剧集榜"
|
||||
title="国产剧集榜"
|
||||
/>
|
||||
|
||||
<MediaCardSlideView
|
||||
apipath="douban/tv_weekly_global"
|
||||
linkurl="/browse/douban/tv_weekly_global?title=全球剧集榜"
|
||||
title="全球剧集榜"
|
||||
<MediaCardSlideView
|
||||
v-for="item in viewList"
|
||||
:key="item.apipath"
|
||||
v-bind="item"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -18,6 +18,9 @@ const type = route.query?.type?.toString() ?? ''
|
||||
// 搜索字段
|
||||
const area = route.query?.area?.toString() ?? ''
|
||||
|
||||
// 搜索季
|
||||
const season = route.query?.season?.toString() ?? ''
|
||||
|
||||
// 视图类型,从localStorage中读取
|
||||
const viewType = ref<string>(localStorage.getItem('MPTorrentsViewType') ?? 'card')
|
||||
|
||||
@@ -36,6 +39,12 @@ const progressValue = ref(0)
|
||||
// 加载进度SSE
|
||||
const progressEventSource = ref<EventSource>()
|
||||
|
||||
// 错误标题
|
||||
const errorTitle = ref('没有数据')
|
||||
|
||||
// 错误描述
|
||||
const errorDescription = ref('未搜索到任何资源')
|
||||
|
||||
// 使用SSE监听加载进度
|
||||
function startLoadingProgress() {
|
||||
progressText.value = '正在搜索,请稍候...'
|
||||
@@ -76,12 +85,18 @@ async function fetchData() {
|
||||
startLoadingProgress()
|
||||
// 优先按TMDBID精确查询
|
||||
if (keyword?.startsWith('tmdb:') || keyword?.startsWith('douban:') || keyword?.startsWith('bangumi:')) {
|
||||
dataList.value = await api.get(`search/media/${keyword}`, {
|
||||
const result: {[key: string]: any} = await api.get(`search/media/${keyword}`, {
|
||||
params: {
|
||||
mtype: type,
|
||||
area,
|
||||
season,
|
||||
},
|
||||
})
|
||||
if (result.success){
|
||||
dataList.value = result.data
|
||||
} else {
|
||||
errorDescription.value = result.message
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 按标题模糊查询
|
||||
@@ -112,9 +127,8 @@ onMounted(() => {
|
||||
</div>
|
||||
<NoDataFound
|
||||
v-if="dataList.length === 0 && isRefreshed"
|
||||
error-code="404"
|
||||
error-title="没有资源"
|
||||
error-description="没有搜索到符合条件的资源。"
|
||||
:error-title="errorTitle"
|
||||
:error-description="errorDescription"
|
||||
/>
|
||||
<div v-if="dataList.length > 0">
|
||||
<TorrentRowListView
|
||||
|
||||
@@ -5,39 +5,37 @@
|
||||
|
||||
#nprogress .bar {
|
||||
background: rgb(var(--v-theme-primary)) !important;
|
||||
top: env(safe-area-inset-top) !important;
|
||||
inset-block-start: env(safe-area-inset-top) !important;
|
||||
}
|
||||
|
||||
#nprogress .peg {
|
||||
box-shadow: 0 0 10px rgb(var(--v-theme-primary)), 0 0 5px rgb(var(--v-theme-primary)) !important;
|
||||
-webkit-transform: rotate(0deg) translate(0px, -1px);
|
||||
-ms-transform: rotate(0deg) translate(0px, -1px);
|
||||
transform: rotate(0deg) translate(0px, -1px);
|
||||
transform: rotate(0deg) translate(0, -1px);
|
||||
}
|
||||
|
||||
.v-toast--bottom {
|
||||
margin-bottom: env(safe-area-inset-bottom);
|
||||
z-index: 2500;
|
||||
margin-block-end: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.v-toast--top {
|
||||
margin-top: env(safe-area-inset-top);
|
||||
z-index: 2500;
|
||||
margin-block-start: env(safe-area-inset-top);
|
||||
}
|
||||
|
||||
.v-dialog > .v-overlay__content {
|
||||
margin-top: calc(env(safe-area-inset-top) + 1rem);
|
||||
max-height: calc(100% - env(safe-area-inset-top) - 1rem);
|
||||
margin-block-start: calc(env(safe-area-inset-top) + 1rem);
|
||||
max-block-size: calc(100% - env(safe-area-inset-top) - 1rem);
|
||||
}
|
||||
|
||||
.v-dialog > .v-overlay__content{
|
||||
width: calc(100% - 1rem);
|
||||
inline-size: calc(100% - 1rem);
|
||||
}
|
||||
|
||||
.v-dialog--fullscreen > .v-overlay__content{
|
||||
margin-top: env(safe-area-inset-top);
|
||||
max-height: calc(100% - env(safe-area-inset-top));
|
||||
width: 100%;
|
||||
inline-size: 100%;
|
||||
margin-block-start: env(safe-area-inset-top);
|
||||
max-block-size: calc(100% - env(safe-area-inset-top));
|
||||
}
|
||||
|
||||
/* router view transition fade-slide */
|
||||
@@ -62,21 +60,20 @@
|
||||
}
|
||||
|
||||
.text-moviepilot {
|
||||
background-clip: text;
|
||||
background-image: linear-gradient(to bottom right,var(--tw-gradient-stops));
|
||||
color: transparent;
|
||||
|
||||
--tw-gradient-from: #818cf8;
|
||||
--tw-gradient-to: rgba(129,140,248,0);
|
||||
--tw-gradient-to: rgba(129,140,248,0%);
|
||||
--tw-gradient-stops: var(--tw-gradient-from),var(--tw-gradient-to);
|
||||
--tw-gradient-to: #c084fc;
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.slider-header {
|
||||
position: relative;
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
margin-block: 1.5rem 1rem;
|
||||
}
|
||||
|
||||
.slider-title {
|
||||
@@ -87,25 +84,27 @@
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
@media (min-width: 640px){
|
||||
@media (width >= 640px){
|
||||
.slider-title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 1.5rem;
|
||||
line-height: 2.25rem;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
// 美化滚动条
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
block-size: 8px;
|
||||
inline-size: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 3px;
|
||||
background: rgb(var(--v-theme-perfect-scrollbar-thumb));
|
||||
-webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.2);
|
||||
box-shadow: inset 0 0 10px rgba(0,0,0,20%);
|
||||
|
||||
@media(hover){
|
||||
&:hover{
|
||||
background: #a1a1a1;
|
||||
@@ -120,10 +119,14 @@
|
||||
|
||||
.backdrop-blur {
|
||||
--tw-backdrop-blur: blur(8px)!important;
|
||||
-webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)!important;
|
||||
|
||||
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)!important;
|
||||
}
|
||||
|
||||
.v-toolbar{
|
||||
background: rgb(var(--v-table-header-background));
|
||||
}
|
||||
|
||||
.v-toast {
|
||||
z-index: 2500 !important;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ const props = defineProps({
|
||||
title: String,
|
||||
})
|
||||
|
||||
provide('rankingPropsKey', reactive({...props}))
|
||||
|
||||
// 组件加载完成
|
||||
const componentLoaded = ref(false)
|
||||
|
||||
@@ -39,7 +41,6 @@ onMounted(fetchData)
|
||||
<template>
|
||||
<SlideView
|
||||
v-if="componentLoaded"
|
||||
v-bind="props"
|
||||
>
|
||||
<template #content>
|
||||
<template
|
||||
|
||||
@@ -425,6 +425,7 @@ function handleSearch(area: string) {
|
||||
keyword,
|
||||
type: mediaDetail.value.type,
|
||||
area,
|
||||
season: mediaDetail.value.season,
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -890,7 +891,7 @@ onBeforeMount(() => {
|
||||
padding-block-start: 1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
@media (width >= 1280px) {
|
||||
.media-header {
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
@@ -900,65 +901,66 @@ onBeforeMount(() => {
|
||||
.media-overview {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 2rem;
|
||||
padding-bottom: 1rem;
|
||||
padding-block: 2rem 1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
@media (width >= 1024px) {
|
||||
.media-overview {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
.media-poster {
|
||||
width: 8rem;
|
||||
overflow: hidden;
|
||||
border-radius: .25rem;
|
||||
--tw-shadow: 0 1px 3px 0 rgba(0, 0, 0, .1), 0 1px 2px -1px rgba(0, 0, 0, .1);
|
||||
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
inline-size: 8rem;
|
||||
|
||||
--tw-shadow: 0 1px 3px 0 rgba(0, 0, 0, 10%), 0 1px 2px -1px rgba(0, 0, 0, 10%);
|
||||
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
@media (width >= 1280px) {
|
||||
.media-poster {
|
||||
margin-right: 1rem;
|
||||
width: 13rem;
|
||||
inline-size: 13rem;
|
||||
margin-inline-end: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
@media (width >= 768px) {
|
||||
.media-poster {
|
||||
width: 11rem;
|
||||
border-radius: .5rem;
|
||||
--tw-shadow: 0 25px 50px -12px rgba(0, 0, 0, .25);
|
||||
--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
inline-size: 11rem;
|
||||
|
||||
--tw-shadow: 0 25px 50px -12px rgba(0, 0, 0, 25%);
|
||||
--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);
|
||||
}
|
||||
}
|
||||
|
||||
.media-title {
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
flex: 1 1 0%;
|
||||
flex-direction: column;
|
||||
margin-block-start: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
@media (width >= 1280px) {
|
||||
.media-title {
|
||||
margin-right: 1rem;
|
||||
margin-top: 0;
|
||||
text-align: left;
|
||||
margin-block-start: 0;
|
||||
margin-inline-end: 1rem;
|
||||
text-align: start;
|
||||
}
|
||||
}
|
||||
|
||||
.media-title>h1 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
font-weight: 700;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
@media (width >= 1280px) {
|
||||
.media-title>h1 {
|
||||
font-size: 2.25rem;
|
||||
line-height: 2.5rem;
|
||||
@@ -966,23 +968,23 @@ onBeforeMount(() => {
|
||||
}
|
||||
|
||||
ul.media-crew {
|
||||
margin-top: 1.5rem;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2,minmax(0,1fr));
|
||||
gap: 1.5rem;
|
||||
grid-template-columns: repeat(2,minmax(0,1fr));
|
||||
margin-block-start: 1.5rem;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
@media (width >= 640px) {
|
||||
ul.media-crew {
|
||||
grid-template-columns: repeat(3,minmax(0,1fr));
|
||||
}
|
||||
}
|
||||
|
||||
ul.media-crew>li {
|
||||
grid-column: span 1/span 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-weight: 700;
|
||||
grid-column: span 1/span 1;
|
||||
}
|
||||
|
||||
a.crew-name {
|
||||
@@ -990,27 +992,27 @@ a.crew-name {
|
||||
}
|
||||
|
||||
.media-status {
|
||||
margin-bottom: .5rem;
|
||||
margin-block-end: .5rem;
|
||||
}
|
||||
|
||||
.media-attributes {
|
||||
margin-top: .25rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-block-start: .25rem;
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
@media (width >= 1280px) {
|
||||
.media-attributes {
|
||||
margin-top: 0;
|
||||
justify-content: flex-start;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
margin-block-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
@media (width >= 640px) {
|
||||
.media-attributes {
|
||||
font-size: .875rem;
|
||||
line-height: 1.25rem;
|
||||
@@ -1019,21 +1021,21 @@ a.crew-name {
|
||||
|
||||
.media-actions {
|
||||
position: relative;
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-block-start: 1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
@media (width >= 1280px) {
|
||||
.media-actions {
|
||||
margin-top: 0;
|
||||
margin-block-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
@media (width >= 640px) {
|
||||
.media-actions {
|
||||
flex-wrap: nowrap;
|
||||
justify-content: flex-end;
|
||||
@@ -1044,42 +1046,45 @@ a.crew-name {
|
||||
flex: 1 1 0%;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
@media (width >= 1024px) {
|
||||
.media-overview-left {
|
||||
margin-right: 2rem;
|
||||
margin-inline-end: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.media-overview-right {
|
||||
margin-top: 2rem;
|
||||
width: 100%;
|
||||
inline-size: 100%;
|
||||
margin-block-start: 2rem;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
@media (width >= 1024px) {
|
||||
.media-overview-right {
|
||||
margin-top: 0;
|
||||
width: 20rem;
|
||||
inline-size: 20rem;
|
||||
margin-block-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.media-facts {
|
||||
border-radius: 0.5rem;
|
||||
border-width: 1px;
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(55 65 81/var(--tw-border-opacity));
|
||||
--tw-bg-opacity: 1;
|
||||
border-radius: 0.5rem;
|
||||
font-size: .875rem;
|
||||
line-height: 1.25rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.25rem;
|
||||
|
||||
--tw-border-opacity: 1;
|
||||
--tw-bg-opacity: 1;
|
||||
--tw-text-opacity: 1;
|
||||
}
|
||||
|
||||
.media-ratings {
|
||||
border-bottom-width: 1px;
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(55 65 81/var(--tw-border-opacity));
|
||||
padding: 0.5rem 1rem;
|
||||
border-block-end-width: 1px;
|
||||
font-weight: 500;
|
||||
padding-block: 0.5rem;
|
||||
padding-inline: 1rem;
|
||||
|
||||
--tw-border-opacity: 1;
|
||||
}
|
||||
|
||||
.media-ratings {
|
||||
@@ -1091,19 +1096,21 @@ a.crew-name {
|
||||
.media-fact {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-bottom-width: 1px;
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(55 65 81/var(--tw-border-opacity));
|
||||
padding: 0.5rem 1rem;
|
||||
border-block-end-width: 1px;
|
||||
padding-block: 0.5rem;
|
||||
padding-inline: 1rem;
|
||||
|
||||
--tw-border-opacity: 1;
|
||||
}
|
||||
|
||||
.media-overview h2 {
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.75rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
@media (width >= 640px) {
|
||||
.media-overview h2 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
@@ -1111,13 +1118,13 @@ a.crew-name {
|
||||
}
|
||||
|
||||
.tagline {
|
||||
margin-bottom: 1rem;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.75rem;
|
||||
font-style: italic;
|
||||
line-height: 1.75rem;
|
||||
margin-block-end: 1rem;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
@media (width >= 1024px) {
|
||||
.tagline {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
|
||||
@@ -13,6 +13,8 @@ const props = defineProps({
|
||||
type: String,
|
||||
})
|
||||
|
||||
provide('rankingPropsKey', reactive({...props}))
|
||||
|
||||
// 组件加载完成
|
||||
const componentLoaded = ref(false)
|
||||
|
||||
@@ -41,7 +43,6 @@ onMounted(fetchData)
|
||||
<template>
|
||||
<SlideView
|
||||
v-if="componentLoaded"
|
||||
v-bind="props"
|
||||
>
|
||||
<template #content>
|
||||
<template
|
||||
|
||||
@@ -104,16 +104,16 @@ onMounted(() => {
|
||||
<template>
|
||||
<VRow>
|
||||
<VCol>
|
||||
<VList v-if="dataList.length === 0" lines="three" class="rounded">
|
||||
<VList v-if="dataList.length === 0" lines="three" class="rounded p-0">
|
||||
<VListItem>
|
||||
<VListItemTitle>没有附合当前过滤条件的资源。</VListItemTitle>
|
||||
</VListItem>
|
||||
</VList>
|
||||
<div>
|
||||
<VList v-if="dataList.length !== 0" lines="three" class="rounded p-0">
|
||||
<div v-for="(item, index) in dataList" :key="`${index}_${item.torrent_info.title}_${item.torrent_info.site}`">
|
||||
<TorrentItem v-if="defer(index)" :torrent="item" />
|
||||
</div>
|
||||
</div>
|
||||
</VList>
|
||||
</VCol>
|
||||
<VCol xl="2" md="3" class="d-none d-md-block">
|
||||
<VList lines="one" class="rounded">
|
||||
|
||||
@@ -117,7 +117,7 @@ function pluginIcon(item: Plugin) {
|
||||
return noImage
|
||||
// 如果是网络图片则使用代理后返回
|
||||
if (item?.plugin_icon?.startsWith('http'))
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/${encodeURIComponent(item?.plugin_icon)}/1`
|
||||
return `${import.meta.env.VITE_API_BASE_URL}system/img/1/${encodeURIComponent(item?.plugin_icon).replace(/%2F/g, '/')}`
|
||||
|
||||
return `./plugin_icon/${item?.plugin_icon}`
|
||||
}
|
||||
@@ -167,6 +167,7 @@ async function fetchUninstalledPlugins() {
|
||||
if (uninstalled.id === data.id) {
|
||||
data.has_update = true
|
||||
data.repo_url = uninstalled.repo_url
|
||||
data.history = uninstalled.history
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,7 +244,17 @@ onBeforeMount(() => {
|
||||
error-description="点击右下角按钮,前往插件市场安装插件。"
|
||||
/>
|
||||
<!-- App市场 -->
|
||||
<VFab
|
||||
icon="mdi-store-plus"
|
||||
location="bottom end"
|
||||
size="x-large"
|
||||
fixed
|
||||
app
|
||||
appear
|
||||
@click="PluginAppDialog = true"
|
||||
/>
|
||||
<VDialog
|
||||
v-if="PluginAppDialog"
|
||||
v-model="PluginAppDialog"
|
||||
fullscreen
|
||||
scrollable
|
||||
@@ -251,19 +262,6 @@ onBeforeMount(() => {
|
||||
:z-index="1010"
|
||||
transition="dialog-bottom-transition"
|
||||
>
|
||||
<!-- Dialog Activator -->
|
||||
<template #activator="{ props }">
|
||||
<VFab
|
||||
v-bind="props"
|
||||
icon="mdi-store-plus"
|
||||
location="bottom end"
|
||||
size="x-large"
|
||||
fixed
|
||||
app
|
||||
appear
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- Dialog Content -->
|
||||
<VCard>
|
||||
<!-- Toolbar -->
|
||||
@@ -318,27 +316,25 @@ onBeforeMount(() => {
|
||||
</VDialog>
|
||||
|
||||
<!-- 插件搜索 -->
|
||||
<VFab
|
||||
icon="mdi-magnify"
|
||||
color="info"
|
||||
location="bottom end"
|
||||
class="mb-2"
|
||||
size="x-large"
|
||||
fixed
|
||||
app
|
||||
appear
|
||||
@click="SearchDialog = true"
|
||||
/>
|
||||
<VDialog
|
||||
v-if="SearchDialog"
|
||||
v-model="SearchDialog"
|
||||
scrollable
|
||||
:z-index="1010"
|
||||
max-width="40rem"
|
||||
max-height="85vh"
|
||||
>
|
||||
<!-- Dialog Activator -->
|
||||
<template #activator="{ props }">
|
||||
<VFab
|
||||
v-bind="props"
|
||||
icon="mdi-magnify"
|
||||
color="info"
|
||||
location="bottom end"
|
||||
class="mb-2"
|
||||
size="x-large"
|
||||
fixed
|
||||
app
|
||||
appear
|
||||
/>
|
||||
</template>
|
||||
<VCard
|
||||
class="mx-auto"
|
||||
width="100%"
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, unref } from 'vue'
|
||||
import { useToast } from 'vue-toast-notification'
|
||||
import api from '@/api'
|
||||
import type { TransferHistory } from '@/api/types'
|
||||
import ReorganizeForm from '@/components/form/ReorganizeForm.vue'
|
||||
import { fixArrayAt } from '@/@core/utils/compatibility'
|
||||
|
||||
// 提示框
|
||||
const $toast = useToast()
|
||||
@@ -58,6 +57,13 @@ const headers = [
|
||||
},
|
||||
]
|
||||
|
||||
const pageRange = [
|
||||
{title: '25', value: 25},
|
||||
{title: '50', value: 50},
|
||||
{title: '100', value: 100},
|
||||
{title: '1000', value: 1000},
|
||||
{title: 'All', value: -1}]
|
||||
|
||||
// 数据列表
|
||||
const dataList = ref<TransferHistory[]>([])
|
||||
|
||||
@@ -94,22 +100,53 @@ const deleteConfirmDialog = ref(false)
|
||||
// 确认框标题
|
||||
const confirmTitle = ref('')
|
||||
|
||||
// 转移方式字典
|
||||
const TransferDict: { [key: string]: string } = {
|
||||
copy: '复制',
|
||||
move: '移动',
|
||||
link: '硬链接',
|
||||
softlink: '软链接',
|
||||
rclone_copy: 'Rclone复制',
|
||||
rclone_move: 'Rclone移动',
|
||||
}
|
||||
|
||||
// 分页提示
|
||||
const pageTip = computed(() => {
|
||||
const begin = unref(itemsPerPage) * (unref(currentPage) - 1) + 1
|
||||
const end = unref(itemsPerPage) * unref(currentPage) === -1 ? 'ALL' : unref(itemsPerPage) * unref(currentPage)
|
||||
return {
|
||||
begin,
|
||||
end
|
||||
}
|
||||
})
|
||||
|
||||
// 分页总数
|
||||
const totalPage = computed(() => {
|
||||
const total = Math.ceil(unref(totalItems) /unref(itemsPerPage))
|
||||
return total
|
||||
})
|
||||
|
||||
// 切换页签和搜索词
|
||||
watch(
|
||||
[() => currentPage.value, () => itemsPerPage.value, () => search.value],
|
||||
async () => {
|
||||
await fetchData()
|
||||
})
|
||||
|
||||
// 获取订阅列表数据
|
||||
async function fetchData({ page, itemsPerPage }: { page: number; itemsPerPage: number }) {
|
||||
async function fetchData(page = currentPage.value, count = itemsPerPage.value) {
|
||||
loading.value = true
|
||||
try {
|
||||
currentPage.value = page
|
||||
|
||||
const result: { [key: string]: any } = await api.get('history/transfer', {
|
||||
params: {
|
||||
page,
|
||||
count: itemsPerPage,
|
||||
count,
|
||||
title: search.value,
|
||||
},
|
||||
})
|
||||
|
||||
dataList.value = result.data.list
|
||||
totalItems.value = result.data.total
|
||||
dataList.value = result.data?.list
|
||||
totalItems.value = result.data?.total
|
||||
searchHintList.value = ['失败', '成功', ...new Set(dataList.value.map(item => item.title || ''))].filter(
|
||||
title => title !== '',
|
||||
)
|
||||
@@ -130,16 +167,6 @@ function getIcon(type: string) {
|
||||
return 'mdi-help-circle'
|
||||
}
|
||||
|
||||
// 转移方式字典
|
||||
const TransferDict: { [key: string]: string } = {
|
||||
copy: '复制',
|
||||
move: '移动',
|
||||
link: '硬链接',
|
||||
softlink: '软链接',
|
||||
rclone_copy: 'Rclone复制',
|
||||
rclone_move: 'Rclone移动',
|
||||
}
|
||||
|
||||
// 删除历史记录
|
||||
async function removeHistory(item: TransferHistory) {
|
||||
currentHistory.value = item
|
||||
@@ -175,10 +202,7 @@ async function removeSingle(deleteSrc: boolean, deleteDest: boolean) {
|
||||
// 删除
|
||||
await remove(currentHistory.value, deleteSrc, deleteDest)
|
||||
// 刷新
|
||||
fetchData({
|
||||
page: currentPage.value,
|
||||
itemsPerPage: itemsPerPage.value,
|
||||
})
|
||||
fetchData()
|
||||
}
|
||||
|
||||
// 批量删除记录
|
||||
@@ -208,10 +232,7 @@ async function removeBatch(deleteSrc: boolean, deleteDest: boolean) {
|
||||
// 隐藏进度条
|
||||
progressDialog.value = false
|
||||
// 重新获取数据
|
||||
fetchData({
|
||||
page: currentPage.value,
|
||||
itemsPerPage: itemsPerPage.value,
|
||||
})
|
||||
fetchData()
|
||||
}
|
||||
|
||||
// 响应删除操作
|
||||
@@ -306,27 +327,28 @@ const dropdownItems = ref([
|
||||
},
|
||||
])
|
||||
|
||||
// 修复低版本Safari等浏览器数组不支持at函数的问题
|
||||
fixArrayAt()
|
||||
// 初始加载数据
|
||||
onMounted(fetchData)
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard class="pb-5">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
<VRow>
|
||||
<VCol cols="4" md="6">
|
||||
历史记录
|
||||
</VCol>
|
||||
<VCol cols="8" md="6">
|
||||
<VCol cols="8" md="6" class="flex">
|
||||
<VCombobox
|
||||
key="search_navbar"
|
||||
v-model="search"
|
||||
:items="searchHintList"
|
||||
class="text-disabled"
|
||||
density="compact"
|
||||
label="搜索标题、状态"
|
||||
append-inner-icon="mdi-magnify"
|
||||
label="搜索目录、状态"
|
||||
prepend-inner-icon="mdi-magnify"
|
||||
variant="solo-filled"
|
||||
single-line
|
||||
hide-details
|
||||
@@ -338,24 +360,17 @@ fixArrayAt()
|
||||
</VRow>
|
||||
</VCardTitle>
|
||||
</VCardItem>
|
||||
<VDataTableServer
|
||||
<VDataTableVirtual
|
||||
v-model="selected"
|
||||
v-model:items-per-page="itemsPerPage"
|
||||
:headers="headers"
|
||||
:items="dataList"
|
||||
:items-length="totalItems"
|
||||
:search="search"
|
||||
:loading="loading"
|
||||
density="compact"
|
||||
item-value="id"
|
||||
return-object
|
||||
fixed-header
|
||||
show-select
|
||||
items-per-page-text="每页条数"
|
||||
page-text="{0}-{1} 共 {2} 条"
|
||||
loading-text="加载中..."
|
||||
class="data-table-div"
|
||||
@update:options="fetchData"
|
||||
>
|
||||
<template #item.title="{ item }">
|
||||
<div class="d-flex align-center">
|
||||
@@ -363,7 +378,7 @@ fixArrayAt()
|
||||
<VIcon :icon="getIcon(item.type || '')" />
|
||||
</VAvatar>
|
||||
<div class="d-flex flex-column ms-1">
|
||||
<span class="d-block text-high-emphasis">
|
||||
<span class="d-block text-high-emphasis min-w-20">
|
||||
{{ item?.title }} {{ item?.seasons }}{{ item?.episodes }}
|
||||
</span>
|
||||
<small>{{ item?.category }}</small>
|
||||
@@ -417,7 +432,28 @@ fixArrayAt()
|
||||
<template #no-data>
|
||||
没有数据
|
||||
</template>
|
||||
</VDataTableServer>
|
||||
</VDataTableVirtual>
|
||||
<div class="flex items-center justify-end">
|
||||
<div class="w-auto">
|
||||
<VSelect
|
||||
v-model="itemsPerPage"
|
||||
:items="pageRange"
|
||||
density="compact"
|
||||
variant="solo"
|
||||
flat
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
<div class="w-auto text-sm">{{pageTip.begin}}-{{pageTip.end}} / {{totalItems}}</div>
|
||||
<VPagination
|
||||
v-model="currentPage"
|
||||
show-first-last-page
|
||||
:length="totalPage"
|
||||
@next="currentPage + 1"
|
||||
@prev="currentPage - 1"
|
||||
>
|
||||
</VPagination>
|
||||
</div>
|
||||
</VCard>
|
||||
<!-- 底部弹窗 -->
|
||||
<VBottomSheet v-model="deleteConfirmDialog" inset>
|
||||
@@ -444,6 +480,7 @@ fixArrayAt()
|
||||
</VBottomSheet>
|
||||
<!-- 文件整理弹窗 -->
|
||||
<ReorganizeForm
|
||||
v-if="redoDialog"
|
||||
v-model="redoDialog"
|
||||
:logids="redoIds"
|
||||
:target="redoTarget"
|
||||
@@ -454,10 +491,7 @@ fixArrayAt()
|
||||
currentHistory = undefined
|
||||
selected = []
|
||||
// 刷新
|
||||
fetchData({
|
||||
page: currentPage,
|
||||
itemsPerPage,
|
||||
})
|
||||
fetchData()
|
||||
}
|
||||
"
|
||||
@close="redoDialog = false"
|
||||
@@ -493,7 +527,8 @@ fixArrayAt()
|
||||
.v-table th {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.data-table-div {
|
||||
height: calc(100vh - 200px);
|
||||
block-size: calc(100vh - 14rem);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -96,7 +96,7 @@ async function loadNotificationSettings() {
|
||||
try {
|
||||
const result1: { [key: string]: any } = await api.get('system/setting/MESSAGER')
|
||||
if (result1.success)
|
||||
selectedChannels.value = result1.data?.value?.split(',')
|
||||
selectedChannels.value = result1.data && result1.data.value ? result1.data.value.split(',') : []
|
||||
|
||||
const result2: { [key: string]: any } = await api.get('system/env')
|
||||
if (result2.success) {
|
||||
|
||||
Reference in New Issue
Block a user