mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-05-10 17:42:50 +08:00
Compare commits
22 Commits
v2.0.0-bet
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fdbc8104c | ||
|
|
433c14679c | ||
|
|
fcaa4476f0 | ||
|
|
85c5c3058c | ||
|
|
035122a08e | ||
|
|
0a76875f8e | ||
|
|
218eac54ce | ||
|
|
84deeff4f5 | ||
|
|
0c72d026f6 | ||
|
|
aec9ea83c5 | ||
|
|
effd13aedd | ||
|
|
42b43d65d7 | ||
|
|
c501d824dd | ||
|
|
384ac2faf1 | ||
|
|
dd2c4dd24b | ||
|
|
356ffddb1c | ||
|
|
de69be7c4e | ||
|
|
e962f555ae | ||
|
|
1987246585 | ||
|
|
393264f66b | ||
|
|
9b50020b3b | ||
|
|
5e5545fe01 |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "moviepilot",
|
"name": "moviepilot",
|
||||||
"version": "1.9.10",
|
"version": "1.9.17",
|
||||||
"private": true,
|
"private": true,
|
||||||
"bin": "dist/service.js",
|
"bin": "dist/service.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import modeYamlUrl from 'ace-builds/src-noconflict/mode-yaml?url'
|
|||||||
|
|
||||||
import modeCssUrl from 'ace-builds/src-noconflict/mode-css?url'
|
import modeCssUrl from 'ace-builds/src-noconflict/mode-css?url'
|
||||||
|
|
||||||
|
import modePythonUrl from 'ace-builds/src-noconflict/mode-python?url'
|
||||||
|
|
||||||
import themeGithubUrl from 'ace-builds/src-noconflict/theme-github?url'
|
import themeGithubUrl from 'ace-builds/src-noconflict/theme-github?url'
|
||||||
|
|
||||||
import themeChromeUrl from 'ace-builds/src-noconflict/theme-chrome?url'
|
import themeChromeUrl from 'ace-builds/src-noconflict/theme-chrome?url'
|
||||||
@@ -38,6 +40,8 @@ import snippetsJsonUrl from 'ace-builds/src-noconflict/snippets/json?url'
|
|||||||
|
|
||||||
import snippertsCssUrl from 'ace-builds/src-noconflict/snippets/css?url'
|
import snippertsCssUrl from 'ace-builds/src-noconflict/snippets/css?url'
|
||||||
|
|
||||||
|
import snippetsPythonUrl from 'ace-builds/src-noconflict/snippets/python?url'
|
||||||
|
|
||||||
import 'ace-builds/src-noconflict/ext-language_tools'
|
import 'ace-builds/src-noconflict/ext-language_tools'
|
||||||
|
|
||||||
ace.config.setModuleUrl('ace/mode/json', modeJsonUrl)
|
ace.config.setModuleUrl('ace/mode/json', modeJsonUrl)
|
||||||
@@ -45,6 +49,7 @@ ace.config.setModuleUrl('ace/mode/javascript', modeJavascriptUrl)
|
|||||||
ace.config.setModuleUrl('ace/mode/html', modeHtmlUrl)
|
ace.config.setModuleUrl('ace/mode/html', modeHtmlUrl)
|
||||||
ace.config.setModuleUrl('ace/mode/yaml', modeYamlUrl)
|
ace.config.setModuleUrl('ace/mode/yaml', modeYamlUrl)
|
||||||
ace.config.setModuleUrl('ace/mode/css', modeCssUrl)
|
ace.config.setModuleUrl('ace/mode/css', modeCssUrl)
|
||||||
|
ace.config.setModuleUrl('ace/mode/python', modePythonUrl)
|
||||||
ace.config.setModuleUrl('ace/theme/github', themeGithubUrl)
|
ace.config.setModuleUrl('ace/theme/github', themeGithubUrl)
|
||||||
ace.config.setModuleUrl('ace/theme/chrome', themeChromeUrl)
|
ace.config.setModuleUrl('ace/theme/chrome', themeChromeUrl)
|
||||||
ace.config.setModuleUrl('ace/theme/monokai', themeMonokaiUrl)
|
ace.config.setModuleUrl('ace/theme/monokai', themeMonokaiUrl)
|
||||||
@@ -59,5 +64,6 @@ ace.config.setModuleUrl('ace/snippets/javascript', snippetsJsUrl)
|
|||||||
ace.config.setModuleUrl('ace/snippets/javascript', snippetsYamlUrl)
|
ace.config.setModuleUrl('ace/snippets/javascript', snippetsYamlUrl)
|
||||||
ace.config.setModuleUrl('ace/snippets/json', snippetsJsonUrl)
|
ace.config.setModuleUrl('ace/snippets/json', snippetsJsonUrl)
|
||||||
ace.config.setModuleUrl('ace/snippets/css', snippertsCssUrl)
|
ace.config.setModuleUrl('ace/snippets/css', snippertsCssUrl)
|
||||||
|
ace.config.setModuleUrl('ace/snippets/python', snippetsPythonUrl)
|
||||||
|
|
||||||
ace.require('ace/ext/language_tools')
|
ace.require('ace/ext/language_tools')
|
||||||
|
|||||||
@@ -21,6 +21,14 @@ function filtersChanged(value: string[]) {
|
|||||||
emit('changed', props.pri, value)
|
emit('changed', props.pri, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 清洗规则中的换行符和多余空格,并在前后添加空格
|
||||||
|
const cleanedRules = computed(() => {
|
||||||
|
return props.rules.map(rule => {
|
||||||
|
rule = rule ?? ''
|
||||||
|
return ` ${rule.replace(/[\r\n]/g, '').replace(/\s+/g, '')} `
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
// 过滤规则下拉框
|
// 过滤规则下拉框
|
||||||
const selectFilterOptions = ref<{ [key: string]: string }[]>([
|
const selectFilterOptions = ref<{ [key: string]: string }[]>([
|
||||||
{ title: '特效字幕', value: ' SPECSUB ' },
|
{ title: '特效字幕', value: ' SPECSUB ' },
|
||||||
@@ -77,7 +85,7 @@ const selectFilterOptions = ref<{ [key: string]: string }[]>([
|
|||||||
<VRow>
|
<VRow>
|
||||||
<VCol>
|
<VCol>
|
||||||
<VSelect
|
<VSelect
|
||||||
v-model="props.rules"
|
v-model="cleanedRules"
|
||||||
variant="underlined"
|
variant="underlined"
|
||||||
:items="selectFilterOptions"
|
:items="selectFilterOptions"
|
||||||
chips
|
chips
|
||||||
|
|||||||
@@ -150,55 +150,61 @@ const dropdownItems = ref([
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VCard :width="props.width" :height="props.height" @click="installPlugin" class="flex flex-col">
|
<VCard :width="props.width" :height="props.height" @click="installPlugin" class="flex flex-col">
|
||||||
<div class="relative pa-3 text-center card-cover-blurred" :style="{ background: `${backgroundColor}` }">
|
<div class="me-n3 absolute bottom-0 right-3">
|
||||||
<div class="me-n3 absolute top-0 right-3">
|
<IconBtn>
|
||||||
<IconBtn>
|
<VIcon icon="mdi-dots-vertical" />
|
||||||
<VIcon icon="mdi-dots-vertical" class="text-white" />
|
<VMenu activator="parent" close-on-content-click>
|
||||||
<VMenu activator="parent" close-on-content-click>
|
<VList>
|
||||||
<VList>
|
<VListItem
|
||||||
<VListItem
|
v-for="(item, i) in dropdownItems"
|
||||||
v-for="(item, i) in dropdownItems"
|
v-show="item.show"
|
||||||
v-show="item.show"
|
:key="i"
|
||||||
:key="i"
|
variant="plain"
|
||||||
variant="plain"
|
@click="item.props.click"
|
||||||
@click="item.props.click"
|
>
|
||||||
>
|
<template #prepend>
|
||||||
<template #prepend>
|
<VIcon :icon="item.props.prependIcon" />
|
||||||
<VIcon :icon="item.props.prependIcon" />
|
</template>
|
||||||
</template>
|
<VListItemTitle v-text="item.title" />
|
||||||
<VListItemTitle v-text="item.title" />
|
</VListItem>
|
||||||
</VListItem>
|
</VList>
|
||||||
</VList>
|
</VMenu>
|
||||||
</VMenu>
|
</IconBtn>
|
||||||
</IconBtn>
|
|
||||||
</div>
|
|
||||||
<VAvatar size="6rem">
|
|
||||||
<VImg
|
|
||||||
ref="imageRef"
|
|
||||||
:src="iconPath"
|
|
||||||
aspect-ratio="4/3"
|
|
||||||
cover
|
|
||||||
:class="{ shadow: isImageLoaded }"
|
|
||||||
@load="imageLoaded"
|
|
||||||
@error="imageLoadError = true"
|
|
||||||
/>
|
|
||||||
</VAvatar>
|
|
||||||
</div>
|
</div>
|
||||||
<VCardTitle>
|
<div
|
||||||
{{ props.plugin?.plugin_name }}
|
class="relative flex flex-row items-start pa-3 justify-between grow"
|
||||||
<span class="text-sm text-gray-500">v{{ props.plugin?.plugin_version }}</span>
|
:style="{ background: `${backgroundColor}` }"
|
||||||
</VCardTitle>
|
>
|
||||||
<VCardText class="pb-2">
|
<div
|
||||||
<div>{{ props.plugin?.plugin_desc }}</div>
|
class="absolute inset-0 bg-cover bg-center"
|
||||||
<div>
|
:style="{ background: `${backgroundColor}`, filter: 'brightness(0.7)' }"
|
||||||
<VChip v-for="label in pluginLabels" variant="tonal" size="small" class="me-1 my-1" color="info" label>
|
></div>
|
||||||
{{ label }}
|
<div class="relative flex-1 min-w-0">
|
||||||
</VChip>
|
<VCardTitle class="text-white px-2 text-shadow whitespace-nowrap overflow-hidden text-ellipsis">
|
||||||
|
{{ props.plugin?.plugin_name }}
|
||||||
|
<span class="text-sm text-gray-200">v{{ props.plugin?.plugin_version }}</span>
|
||||||
|
</VCardTitle>
|
||||||
|
<VCardText class="text-white px-2 py-1 text-shadow line-clamp-3">
|
||||||
|
{{ props.plugin?.plugin_desc }}
|
||||||
|
</VCardText>
|
||||||
</div>
|
</div>
|
||||||
</VCardText>
|
<div class="relative flex-shrink-0 self-center">
|
||||||
<VCardText class="flex align-self-baseline pb-2 w-full align-end">
|
<VAvatar size="64">
|
||||||
|
<VImg
|
||||||
|
ref="imageRef"
|
||||||
|
:src="iconPath"
|
||||||
|
aspect-ratio="4/3"
|
||||||
|
cover
|
||||||
|
:class="{ shadow: isImageLoaded }"
|
||||||
|
@load="imageLoaded"
|
||||||
|
@error="imageLoadError = true"
|
||||||
|
/>
|
||||||
|
</VAvatar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<VCardText class="flex flex-none align-self-baseline py-3 w-full align-end">
|
||||||
<span>
|
<span>
|
||||||
<VIcon icon="mdi-account" class="me-1" />
|
<VIcon icon="mdi-github" class="me-1" />
|
||||||
<a :href="props.plugin?.author_url" target="_blank" @click.stop>
|
<a :href="props.plugin?.author_url" target="_blank" @click.stop>
|
||||||
{{ props.plugin?.plugin_author }}
|
{{ props.plugin?.plugin_author }}
|
||||||
</a>
|
</a>
|
||||||
@@ -220,15 +226,3 @@ const dropdownItems = ref([
|
|||||||
</VCard>
|
</VCard>
|
||||||
</VDialog>
|
</VDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.card-cover-blurred::before {
|
|
||||||
position: absolute;
|
|
||||||
/* stylelint-disable-next-line property-no-vendor-prefix */
|
|
||||||
-webkit-backdrop-filter: blur(2px);
|
|
||||||
backdrop-filter: blur(2px);
|
|
||||||
background: rgba(29, 39, 59, 48%);
|
|
||||||
content: '';
|
|
||||||
inset: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -383,60 +383,75 @@ watch(
|
|||||||
<template>
|
<template>
|
||||||
<!-- 插件卡片 -->
|
<!-- 插件卡片 -->
|
||||||
<VCard v-if="isVisible" :width="props.width" :height="props.height" @click="openPluginDetail" class="flex flex-col">
|
<VCard v-if="isVisible" :width="props.width" :height="props.height" @click="openPluginDetail" class="flex flex-col">
|
||||||
<div class="relative pa-3 text-center card-cover-blurred" :style="{ background: `${backgroundColor}` }">
|
<div class="me-n3 absolute bottom-0 right-3">
|
||||||
<div v-if="props.plugin?.has_update" class="me-n3 absolute top-0 left-1">
|
<IconBtn>
|
||||||
<VIcon icon="mdi-new-box" class="text-white" />
|
<VIcon icon="mdi-dots-vertical" />
|
||||||
</div>
|
<VMenu activator="parent" close-on-content-click>
|
||||||
<div class="me-n3 absolute top-0 right-3">
|
<VList>
|
||||||
<IconBtn>
|
<VListItem
|
||||||
<VIcon icon="mdi-dots-vertical" class="text-white" />
|
v-for="(item, i) in dropdownItems"
|
||||||
<VMenu activator="parent" close-on-content-click>
|
v-show="item.show"
|
||||||
<VList>
|
:key="i"
|
||||||
<VListItem
|
variant="plain"
|
||||||
v-for="(item, i) in dropdownItems"
|
:base-color="item.props.color"
|
||||||
v-show="item.show"
|
@click="item.props.click"
|
||||||
:key="i"
|
>
|
||||||
variant="plain"
|
<template #prepend>
|
||||||
:base-color="item.props.color"
|
<VIcon :icon="item.props.prependIcon" />
|
||||||
@click="item.props.click"
|
</template>
|
||||||
>
|
<VListItemTitle v-text="item.title" />
|
||||||
<template #prepend>
|
</VListItem>
|
||||||
<VIcon :icon="item.props.prependIcon" />
|
</VList>
|
||||||
</template>
|
</VMenu>
|
||||||
<VListItemTitle v-text="item.title" />
|
</IconBtn>
|
||||||
</VListItem>
|
|
||||||
</VList>
|
|
||||||
</VMenu>
|
|
||||||
</IconBtn>
|
|
||||||
</div>
|
|
||||||
<VAvatar size="6rem">
|
|
||||||
<VImg
|
|
||||||
ref="imageRef"
|
|
||||||
:src="iconPath"
|
|
||||||
aspect-ratio="4/3"
|
|
||||||
cover
|
|
||||||
:class="{ shadow: isImageLoaded }"
|
|
||||||
@load="imageLoaded"
|
|
||||||
@error="imageLoadError = true"
|
|
||||||
/>
|
|
||||||
</VAvatar>
|
|
||||||
</div>
|
</div>
|
||||||
<VCardItem class="py-2">
|
<div
|
||||||
<VCardTitle class="flex items-center flex-row">
|
class="relative flex flex-row items-start pa-3 justify-between grow"
|
||||||
<VBadge v-if="props.plugin?.state" dot inline color="success" class="me-1 mb-1" />
|
:style="{ background: `${backgroundColor}` }"
|
||||||
{{ props.plugin?.plugin_name }}
|
>
|
||||||
<span class="text-sm ms-2 mt-1 text-gray-500">v{{ props.plugin?.plugin_version }}</span>
|
<div
|
||||||
</VCardTitle>
|
class="absolute inset-0 bg-cover bg-center"
|
||||||
</VCardItem>
|
:style="{ background: `${backgroundColor}`, filter: 'brightness(0.7)' }"
|
||||||
<VCardText class="pb-1">
|
/>
|
||||||
{{ props.plugin?.plugin_desc }}
|
<div class="relative flex-1 min-w-0">
|
||||||
</VCardText>
|
<VCardTitle class="text-white px-2 text-shadow whitespace-nowrap overflow-hidden text-ellipsis">
|
||||||
<VCardText class="flex justify-end align-self-baseline p-1 w-full align-end">
|
<VBadge v-if="props.plugin?.state" dot inline color="success" />
|
||||||
|
{{ props.plugin?.plugin_name }}
|
||||||
|
<span class="text-sm mt-1 text-gray-200">v{{ props.plugin?.plugin_version }}</span>
|
||||||
|
</VCardTitle>
|
||||||
|
<VCardText class="px-2 py-1 text-white text-shadow line-clamp-3">
|
||||||
|
{{ props.plugin?.plugin_desc }}
|
||||||
|
</VCardText>
|
||||||
|
</div>
|
||||||
|
<div class="relative flex-shrink-0 self-center">
|
||||||
|
<VAvatar size="64">
|
||||||
|
<VImg
|
||||||
|
ref="imageRef"
|
||||||
|
:src="iconPath"
|
||||||
|
aspect-ratio="4/3"
|
||||||
|
cover
|
||||||
|
:class="{ shadow: isImageLoaded }"
|
||||||
|
@load="imageLoaded"
|
||||||
|
@error="imageLoadError = true"
|
||||||
|
/>
|
||||||
|
</VAvatar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<VCardText class="flex flex-none align-self-baseline py-3 w-full align-end">
|
||||||
|
<span>
|
||||||
|
<VIcon icon="mdi-github" class="me-1" />
|
||||||
|
<a :href="props.plugin?.author_url" target="_blank" @click.stop>
|
||||||
|
{{ props.plugin?.plugin_author }}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
<span v-if="props.count" class="ms-3">
|
<span v-if="props.count" class="ms-3">
|
||||||
<VIcon icon="mdi-fire" />
|
<VIcon icon="mdi-download" />
|
||||||
<span class="text-sm ms-1">{{ props.count?.toLocaleString() }}</span>
|
<span class="text-sm ms-1 mt-1">{{ props.count?.toLocaleString() }}</span>
|
||||||
</span>
|
</span>
|
||||||
</VCardText>
|
</VCardText>
|
||||||
|
<div v-if="props.plugin?.has_update" class="me-n3 absolute top-0 right-5">
|
||||||
|
<VIcon icon="mdi-new-box" class="text-white" />
|
||||||
|
</div>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
|
||||||
<!-- 插件配置页面 -->
|
<!-- 插件配置页面 -->
|
||||||
|
|||||||
@@ -223,9 +223,9 @@ watch(
|
|||||||
<div class="absolute inset-0 subscribe-card-background"></div>
|
<div class="absolute inset-0 subscribe-card-background"></div>
|
||||||
</VImg>
|
</VImg>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="imageLoaded">
|
<div>
|
||||||
<VCardText class="flex items-center">
|
<VCardText class="flex items-center">
|
||||||
<div class="h-auto w-12 flex-shrink-0 overflow-hidden rounded-md shadow-lg">
|
<div class="h-auto w-12 flex-shrink-0 overflow-hidden rounded-md shadow-lg" v-if="imageLoaded">
|
||||||
<VImg :src="props.media?.poster" aspect-ratio="2/3" cover @click.stop="viewMediaDetail">
|
<VImg :src="props.media?.poster" aspect-ratio="2/3" cover @click.stop="viewMediaDetail">
|
||||||
<template #placeholder>
|
<template #placeholder>
|
||||||
<div class="w-full h-full">
|
<div class="w-full h-full">
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ const props = defineProps({
|
|||||||
root: {
|
root: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '/',
|
default: '/',
|
||||||
required: true,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import * as Mousetrap from 'mousetrap'
|
import * as Mousetrap from 'mousetrap'
|
||||||
import SearchBarView from '@/views/system/SearchBarView.vue'
|
import SearchBarView from '@/views/system/SearchBarView.vue'
|
||||||
import { useDisplay } from 'vuetify'
|
import { useDisplay } from 'vuetify'
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
|
||||||
const display = useDisplay()
|
const display = useDisplay()
|
||||||
|
|
||||||
@@ -15,6 +16,14 @@ function openSearchDialog() {
|
|||||||
searchDialog.value = true
|
searchDialog.value = true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检测操作系统是否是Mac
|
||||||
|
function isMac() {
|
||||||
|
return navigator.platform.toUpperCase().indexOf('MAC') >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算属性:根据操作系统显示不同的按键提示
|
||||||
|
const metaKey = computed(() => (isMac() ? '⌘+K' : 'Ctrl+K'))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -25,12 +34,13 @@ function openSearchDialog() {
|
|||||||
</IconBtn>
|
</IconBtn>
|
||||||
<span v-if="display.lgAndUp.value" class="flex align-center text-disabled ms-2" @click="openSearchDialog">
|
<span v-if="display.lgAndUp.value" class="flex align-center text-disabled ms-2" @click="openSearchDialog">
|
||||||
<span class="me-3">搜索</span>
|
<span class="me-3">搜索</span>
|
||||||
<span class="meta-key">⌘K</span>
|
<span class="meta-key">{{ metaKey }}</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- 搜索弹窗 -->
|
<!-- 搜索弹窗 -->
|
||||||
<SearchBarView v-model="searchDialog" v-if="searchDialog" @close="searchDialog = false" />
|
<SearchBarView v-model="searchDialog" v-if="searchDialog" @close="searchDialog = false" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style type="scss" scoped>
|
<style type="scss" scoped>
|
||||||
.meta-key {
|
.meta-key {
|
||||||
border: thin solid rgba(var(--v-border-color), var(--v-border-opacity));
|
border: thin solid rgba(var(--v-border-color), var(--v-border-opacity));
|
||||||
@@ -39,4 +49,4 @@ function openSearchDialog() {
|
|||||||
padding-block: 0.1rem;
|
padding-block: 0.1rem;
|
||||||
padding-inline: 0.25rem;
|
padding-inline: 0.25rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -32,8 +32,10 @@ function jumpTab(tab: string) {
|
|||||||
@click="jumpTab(item.tab)"
|
@click="jumpTab(item.tab)"
|
||||||
selected-class="v-slide-group-item--active v-tab--selected"
|
selected-class="v-slide-group-item--active v-tab--selected"
|
||||||
>
|
>
|
||||||
<VIcon size="20" start :icon="item.icon" />
|
<div>
|
||||||
{{ item.title }}
|
<VIcon size="20" start :icon="item.icon" />
|
||||||
|
{{ item.title }}
|
||||||
|
</div>
|
||||||
</VTab>
|
</VTab>
|
||||||
</VTabs>
|
</VTabs>
|
||||||
|
|
||||||
@@ -41,70 +43,90 @@ function jumpTab(tab: string) {
|
|||||||
<!-- 用户 -->
|
<!-- 用户 -->
|
||||||
<VWindowItem value="account">
|
<VWindowItem value="account">
|
||||||
<transition name="fade-slide" appear>
|
<transition name="fade-slide" appear>
|
||||||
<AccountSettingAccount />
|
<div>
|
||||||
|
<AccountSettingAccount />
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</VWindowItem>
|
</VWindowItem>
|
||||||
|
|
||||||
<!-- 连接 -->
|
<!-- 连接 -->
|
||||||
<VWindowItem value="system">
|
<VWindowItem value="system">
|
||||||
<transition name="fade-slide" appear>
|
<transition name="fade-slide" appear>
|
||||||
<AccountSettingSystem />
|
<div>
|
||||||
|
<AccountSettingSystem />
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</VWindowItem>
|
</VWindowItem>
|
||||||
|
|
||||||
<!-- 目录 -->
|
<!-- 目录 -->
|
||||||
<VWindowItem value="directory">
|
<VWindowItem value="directory">
|
||||||
<transition name="fade-slide" appear>
|
<transition name="fade-slide" appear>
|
||||||
<AccountSettingDirectory />
|
<div>
|
||||||
|
<AccountSettingDirectory />
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</VWindowItem>
|
</VWindowItem>
|
||||||
|
|
||||||
<!-- 站点 -->
|
<!-- 站点 -->
|
||||||
<VWindowItem value="site">
|
<VWindowItem value="site">
|
||||||
<transition name="fade-slide" appear>
|
<transition name="fade-slide" appear>
|
||||||
<AccountSettingSite />
|
<div>
|
||||||
|
<AccountSettingSite />
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</VWindowItem>
|
</VWindowItem>
|
||||||
|
|
||||||
<!-- 搜索 -->
|
<!-- 搜索 -->
|
||||||
<VWindowItem value="search">
|
<VWindowItem value="search">
|
||||||
<transition name="fade-slide" appear>
|
<transition name="fade-slide" appear>
|
||||||
<AccountSettingSearch />
|
<div>
|
||||||
|
<AccountSettingSearch />
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</VWindowItem>
|
</VWindowItem>
|
||||||
|
|
||||||
<!-- 订阅 -->
|
<!-- 订阅 -->
|
||||||
<VWindowItem value="subscribe">
|
<VWindowItem value="subscribe">
|
||||||
<transition name="fade-slide" appear>
|
<transition name="fade-slide" appear>
|
||||||
<AccountSettingSubscribe />
|
<div>
|
||||||
|
<AccountSettingSubscribe />
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</VWindowItem>
|
</VWindowItem>
|
||||||
|
|
||||||
<!-- 服务 -->
|
<!-- 服务 -->
|
||||||
<VWindowItem value="service">
|
<VWindowItem value="service">
|
||||||
<transition name="fade-slide" appear>
|
<transition name="fade-slide" appear>
|
||||||
<AccountSettingService />
|
<div>
|
||||||
|
<AccountSettingService />
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</VWindowItem>
|
</VWindowItem>
|
||||||
|
|
||||||
<!-- 通知 -->
|
<!-- 通知 -->
|
||||||
<VWindowItem value="notification">
|
<VWindowItem value="notification">
|
||||||
<transition name="fade-slide" appear>
|
<transition name="fade-slide" appear>
|
||||||
<AccountSettingNotification />
|
<div>
|
||||||
|
<AccountSettingNotification />
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</VWindowItem>
|
</VWindowItem>
|
||||||
|
|
||||||
<!-- 词表 -->
|
<!-- 词表 -->
|
||||||
<VWindowItem value="words">
|
<VWindowItem value="words">
|
||||||
<transition name="fade-slide" appear>
|
<transition name="fade-slide" appear>
|
||||||
<AccountSettingWords />
|
<div>
|
||||||
|
<AccountSettingWords />
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</VWindowItem>
|
</VWindowItem>
|
||||||
|
|
||||||
<!-- 关于 -->
|
<!-- 关于 -->
|
||||||
<VWindowItem value="about">
|
<VWindowItem value="about">
|
||||||
<transition name="fade-slide" appear>
|
<transition name="fade-slide" appear>
|
||||||
<AccountSettingAbout />
|
<div>
|
||||||
|
<AccountSettingAbout />
|
||||||
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</VWindowItem>
|
</VWindowItem>
|
||||||
</VWindow>
|
</VWindow>
|
||||||
|
|||||||
@@ -156,7 +156,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.grid-plugin-card {
|
.grid-plugin-card {
|
||||||
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
|
||||||
padding-block-end: 1rem;
|
padding-block-end: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,13 @@ const options = controlledComputed(
|
|||||||
fontSize: '12px',
|
fontSize: '12px',
|
||||||
},
|
},
|
||||||
|
|
||||||
formatter: (value: number) => (value > 999 ? (value / 1000).toFixed(0) : value),
|
formatter: (value: number) => {
|
||||||
|
if (value > 999) {
|
||||||
|
return (value / 1000).toFixed(1) + 'k'
|
||||||
|
} else {
|
||||||
|
return value.toString()
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -347,7 +347,7 @@ onBeforeMount(async () => {
|
|||||||
<transition name="fade-slide" appear>
|
<transition name="fade-slide" appear>
|
||||||
<div>
|
<div>
|
||||||
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
|
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
|
||||||
<div v-if="dataList.length > 0" class="grid gap-4 grid-plugin-card items-start">
|
<div v-if="dataList.length > 0" class="grid gap-4 grid-plugin-card">
|
||||||
<template v-for="(data, index) in dataList" :key="`${data.id}_v${data.plugin_version}`">
|
<template v-for="(data, index) in dataList" :key="`${data.id}_v${data.plugin_version}`">
|
||||||
<PluginCard
|
<PluginCard
|
||||||
:count="PluginStatistics[data.id || '0']"
|
:count="PluginStatistics[data.id || '0']"
|
||||||
@@ -417,7 +417,7 @@ onBeforeMount(async () => {
|
|||||||
</VCol>
|
</VCol>
|
||||||
</VRow>
|
</VRow>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="isAppMarketLoaded" class="grid gap-4 grid-plugin-card items-start">
|
<div v-if="isAppMarketLoaded" class="grid gap-4 grid-plugin-card">
|
||||||
<template v-for="(data, index) in sortedUninstalledList" :key="`${data.id}_v${data.plugin_version}`">
|
<template v-for="(data, index) in sortedUninstalledList" :key="`${data.id}_v${data.plugin_version}`">
|
||||||
<PluginAppCard :plugin="data" :count="PluginStatistics[data.id || '0']" @install="pluginInstalled" />
|
<PluginAppCard :plugin="data" :count="PluginStatistics[data.id || '0']" @install="pluginInstalled" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -148,12 +148,19 @@ const totalPage = computed(() => {
|
|||||||
|
|
||||||
// 切换页签和搜索词
|
// 切换页签和搜索词
|
||||||
watch(
|
watch(
|
||||||
[() => currentPage.value, () => itemsPerPage.value, () => search.value],
|
[() => currentPage.value, () => itemsPerPage.value],
|
||||||
debounce(async () => {
|
debounce(async () => {
|
||||||
reloadPage()
|
reloadPage()
|
||||||
}, 1000),
|
}, 1000),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
[() => search.value],
|
||||||
|
debounce(async () => {
|
||||||
|
reloadPage(true)
|
||||||
|
}, 1000),
|
||||||
|
)
|
||||||
|
|
||||||
// 获取订阅列表数据
|
// 获取订阅列表数据
|
||||||
async function fetchData(page = currentPage.value, count = itemsPerPage.value) {
|
async function fetchData(page = currentPage.value, count = itemsPerPage.value) {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@@ -335,7 +342,7 @@ function addUrlQuery(url: string, name: string, value: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 重载页面
|
// 重载页面
|
||||||
function reloadPage() {
|
function reloadPage(resetPage = false) {
|
||||||
let url = '/history'
|
let url = '/history'
|
||||||
if (search.value) {
|
if (search.value) {
|
||||||
url = addUrlQuery(url, 'search', search.value)
|
url = addUrlQuery(url, 'search', search.value)
|
||||||
@@ -344,7 +351,7 @@ function reloadPage() {
|
|||||||
url = addUrlQuery(url, 'itemsPerPage', itemsPerPage.value)
|
url = addUrlQuery(url, 'itemsPerPage', itemsPerPage.value)
|
||||||
}
|
}
|
||||||
if (currentPage.value) {
|
if (currentPage.value) {
|
||||||
url = addUrlQuery(url, 'currentPage', currentPage.value)
|
url = addUrlQuery(url, 'currentPage', resetPage ? 1 : currentPage.value)
|
||||||
}
|
}
|
||||||
router.push(url)
|
router.push(url)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ function addDownloadDirectory() {
|
|||||||
downloadDirectories.value.push({
|
downloadDirectories.value.push({
|
||||||
name: `下载目录${downloadDirectories.value.length + 1}`,
|
name: `下载目录${downloadDirectories.value.length + 1}`,
|
||||||
path: '',
|
path: '',
|
||||||
media_type: '全部',
|
media_type: '',
|
||||||
category: '',
|
category: '',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -181,7 +181,7 @@ function addLibraryDirectory() {
|
|||||||
libraryDirectories.value.push({
|
libraryDirectories.value.push({
|
||||||
name: `媒体库目录${libraryDirectories.value.length + 1}`,
|
name: `媒体库目录${libraryDirectories.value.length + 1}`,
|
||||||
path: '',
|
path: '',
|
||||||
media_type: '全部',
|
media_type: '',
|
||||||
category: '',
|
category: '',
|
||||||
scrape: true,
|
scrape: true,
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user