重构对话框组件,将所有 DialogWrapper 替换为 VDialog,并更新缓存版本至 v1.1.0

This commit is contained in:
jxxghp
2025-08-23 18:55:34 +08:00
parent 6e50acf106
commit 472d1960d9
66 changed files with 163 additions and 637 deletions
+1 -1
View File
@@ -10,7 +10,6 @@ declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
ConfirmDialog: typeof import('./src/@core/components/ConfirmDialog.vue')['default'] ConfirmDialog: typeof import('./src/@core/components/ConfirmDialog.vue')['default']
DialogCloseBtn: typeof import('./src/@core/components/DialogCloseBtn.vue')['default'] DialogCloseBtn: typeof import('./src/@core/components/DialogCloseBtn.vue')['default']
DialogWrapper: typeof import('./src/@core/components/DialogWrapper.vue')['default']
ErrorHeader: typeof import('./src/@core/components/ErrorHeader.vue')['default'] ErrorHeader: typeof import('./src/@core/components/ErrorHeader.vue')['default']
ExistIcon: typeof import('./src/@core/components/ExistIcon.vue')['default'] ExistIcon: typeof import('./src/@core/components/ExistIcon.vue')['default']
LoadingBanner: typeof import('./src/@core/components/LoadingBanner.vue')['default'] LoadingBanner: typeof import('./src/@core/components/LoadingBanner.vue')['default']
@@ -20,5 +19,6 @@ declare module 'vue' {
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
ScrollToTopBtn: typeof import('./src/@core/components/ScrollToTopBtn.vue')['default'] ScrollToTopBtn: typeof import('./src/@core/components/ScrollToTopBtn.vue')['default']
StatIcon: typeof import('./src/@core/components/StatIcon.vue')['default'] StatIcon: typeof import('./src/@core/components/StatIcon.vue')['default']
VDialog: typeof import('./src/@core/components/VDialog.vue')['default']
} }
} }
+2 -2
View File
@@ -59,7 +59,7 @@ function handleCancel() {
</script> </script>
<template> <template>
<DialogWrapper :model-value="modelValue" @update:model-value="emit('update:modelValue', $event)" :max-width="width"> <VDialog :model-value="modelValue" @update:model-value="emit('update:modelValue', $event)" :max-width="width">
<VCard> <VCard>
<VCardItem> <VCardItem>
<div class="d-flex align-center justify-start mt-3"> <div class="d-flex align-center justify-start mt-3">
@@ -82,5 +82,5 @@ function handleCancel() {
</VCardActions> </VCardActions>
<VDialogCloseBtn @click="handleCancel" /> <VDialogCloseBtn @click="handleCancel" />
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
-70
View File
@@ -1,70 +0,0 @@
<template>
<VDialog v-model="dialogModel" v-bind="$attrs" @update:model-value="handleDialogChange">
<slot />
</VDialog>
</template>
<script setup lang="ts">
import { computed, watch, onBeforeUnmount } from 'vue'
import { useScrollLockWithWatch } from '@/composables/useScrollLock'
// Props
interface Props {
modelValue?: boolean
// 滚动锁定配置
scrollLock?: boolean
preserveScrollPosition?: boolean
preventTouchScroll?: boolean
}
const props = withDefaults(defineProps<Props>(), {
scrollLock: true,
preserveScrollPosition: true,
preventTouchScroll: true,
})
// Emits
const emit = defineEmits<{
'update:modelValue': [value: boolean]
}>()
// 计算属性
const dialogModel = computed({
get: () => props.modelValue || false,
set: (value: boolean) => emit('update:modelValue', value),
})
// 使用滚动锁定
const { isLocked, lockScroll, restoreScroll } = useScrollLockWithWatch(dialogModel, {
autoRestore: true,
preserveScrollPosition: props.preserveScrollPosition,
preventTouchScroll: props.preventTouchScroll,
})
// 处理弹窗状态变化
const handleDialogChange = (value: boolean) => {
emit('update:modelValue', value)
}
// 监听弹窗状态变化
watch(
dialogModel,
newValue => {
if (props.scrollLock) {
if (newValue) {
lockScroll()
} else {
restoreScroll()
}
}
},
{ immediate: true },
)
// 组件卸载时确保恢复滚动
onBeforeUnmount(() => {
if (isLocked.value) {
restoreScroll()
}
})
</script>
+2 -2
View File
@@ -133,7 +133,7 @@ const instructions = computed(() => {
</Teleport> </Teleport>
<!-- 手动安装说明对话框 --> <!-- 手动安装说明对话框 -->
<DialogWrapper v-model="showInstructions" max-width="500"> <VDialog v-model="showInstructions" max-width="500">
<VCard> <VCard>
<VCardItem> <VCardItem>
<VCardTitle class="d-flex align-center"> <VCardTitle class="d-flex align-center">
@@ -170,7 +170,7 @@ const instructions = computed(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
<style scoped> <style scoped>
+2 -2
View File
@@ -116,7 +116,7 @@ function onClose() {
<VImg :src="filter_svg" cover class="mt-7" max-width="3rem" /> <VImg :src="filter_svg" cover class="mt-7" max-width="3rem" />
</VCardText> </VCardText>
</VCard> </VCard>
<DialogWrapper <VDialog
v-if="ruleInfoDialog" v-if="ruleInfoDialog"
v-model="ruleInfoDialog" v-model="ruleInfoDialog"
scrollable scrollable
@@ -222,6 +222,6 @@ function onClose() {
}}</VBtn> }}</VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</div> </div>
</template> </template>
+3 -3
View File
@@ -147,7 +147,7 @@ const { stop: stopRefresh } = useConditionalDataRefresh(
loadDownloaderInfo, loadDownloaderInfo,
shouldRefresh, // 响应式条件:只有当allowRefresh为true且downloader启用时才运行 shouldRefresh, // 响应式条件:只有当allowRefresh为true且downloader启用时才运行
3000, // 3秒间隔 3000, // 3秒间隔
true // 立即执行一次 true, // 立即执行一次
) )
onUnmounted(() => { onUnmounted(() => {
@@ -196,7 +196,7 @@ onUnmounted(() => {
</VCard> </VCard>
</VHover> </VHover>
<DialogWrapper <VDialog
v-if="downloaderInfoDialog" v-if="downloaderInfoDialog"
v-model="downloaderInfoDialog" v-model="downloaderInfoDialog"
scrollable scrollable
@@ -383,6 +383,6 @@ onUnmounted(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</div> </div>
</template> </template>
+2 -2
View File
@@ -223,7 +223,7 @@ function onClose() {
<VImg :src="filter_group_svg" cover class="mt-10" max-width="3rem" /> <VImg :src="filter_group_svg" cover class="mt-10" max-width="3rem" />
</VCardText> </VCardText>
</VCard> </VCard>
<DialogWrapper <VDialog
v-if="groupInfoDialog" v-if="groupInfoDialog"
v-model="groupInfoDialog" v-model="groupInfoDialog"
scrollable scrollable
@@ -308,7 +308,7 @@ function onClose() {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<ImportCodeDialog <ImportCodeDialog
v-if="importCodeDialog" v-if="importCodeDialog"
v-model="importCodeDialog" v-model="importCodeDialog"
+2 -2
View File
@@ -204,7 +204,7 @@ onMounted(() => {
</VCardText> </VCardText>
</VCard> </VCard>
<DialogWrapper <VDialog
v-if="mediaServerInfoDialog" v-if="mediaServerInfoDialog"
v-model="mediaServerInfoDialog" v-model="mediaServerInfoDialog"
scrollable scrollable
@@ -506,6 +506,6 @@ onMounted(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</div> </div>
</template> </template>
@@ -141,7 +141,7 @@ function onClose() {
</VCardText> </VCardText>
</VCard> </VCard>
<DialogWrapper <VDialog
v-if="notificationInfoDialog" v-if="notificationInfoDialog"
v-model="notificationInfoDialog" v-model="notificationInfoDialog"
scrollable scrollable
@@ -476,6 +476,6 @@ function onClose() {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</div> </div>
</template> </template>
+7 -5
View File
@@ -106,7 +106,9 @@ const iconPath: Ref<string> = computed(() => {
if (imageLoadError.value) return noImage if (imageLoadError.value) return noImage
// 如果是网络图片则使用代理后返回 // 如果是网络图片则使用代理后返回
if (props.plugin?.plugin_icon?.startsWith('http')) if (props.plugin?.plugin_icon?.startsWith('http'))
return `${import.meta.env.VITE_API_BASE_URL}system/img/1?imgurl=${encodeURIComponent(props.plugin?.plugin_icon)}&cache=true` return `${import.meta.env.VITE_API_BASE_URL}system/img/1?imgurl=${encodeURIComponent(
props.plugin?.plugin_icon,
)}&cache=true`
return `./plugin_icon/${props.plugin?.plugin_icon}` return `./plugin_icon/${props.plugin?.plugin_icon}`
}) })
@@ -267,15 +269,15 @@ const dropdownItems = ref([
<!-- 安装插件进度框 --> <!-- 安装插件进度框 -->
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" /> <ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
<!-- 更新日志 --> <!-- 更新日志 -->
<DialogWrapper v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable> <VDialog v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable>
<VCard :title="t('plugin.updateHistoryTitle', { name: props.plugin?.plugin_name })"> <VCard :title="t('plugin.updateHistoryTitle', { name: props.plugin?.plugin_name })">
<VDialogCloseBtn @click="releaseDialog = false" /> <VDialogCloseBtn @click="releaseDialog = false" />
<VDivider /> <VDivider />
<VersionHistory :history="props.plugin?.history" /> <VersionHistory :history="props.plugin?.history" />
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 插件详情--> <!-- 插件详情-->
<DialogWrapper v-if="detailDialog" v-model="detailDialog" max-width="30rem"> <VDialog v-if="detailDialog" v-model="detailDialog" max-width="30rem">
<VCard> <VCard>
<VDialogCloseBtn @click="detailDialog = false" /> <VDialogCloseBtn @click="detailDialog = false" />
<VCardText> <VCardText>
@@ -335,6 +337,6 @@ const dropdownItems = ref([
</VCol> </VCol>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</div> </div>
</template> </template>
+6 -6
View File
@@ -547,7 +547,7 @@ watch(
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" /> <ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
<!-- 更新日志 --> <!-- 更新日志 -->
<DialogWrapper v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable :fullscreen="!display.mdAndUp.value"> <VDialog v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable :fullscreen="!display.mdAndUp.value">
<VCard :title="t('plugin.updateHistoryTitle', { name: props.plugin?.plugin_name })"> <VCard :title="t('plugin.updateHistoryTitle', { name: props.plugin?.plugin_name })">
<VDialogCloseBtn @click="releaseDialog = false" /> <VDialogCloseBtn @click="releaseDialog = false" />
<VDivider /> <VDivider />
@@ -562,10 +562,10 @@ watch(
</VBtn> </VBtn>
</VCardItem> </VCardItem>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 实时日志弹窗 --> <!-- 实时日志弹窗 -->
<DialogWrapper <VDialog
v-if="loggingDialog" v-if="loggingDialog"
v-model="loggingDialog" v-model="loggingDialog"
scrollable scrollable
@@ -591,10 +591,10 @@ watch(
<LoggingView :logfile="`plugins/${props.plugin?.id?.toLowerCase()}.log`" /> <LoggingView :logfile="`plugins/${props.plugin?.id?.toLowerCase()}.log`" />
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 插件分身对话框 --> <!-- 插件分身对话框 -->
<DialogWrapper <VDialog
v-if="pluginCloneDialog" v-if="pluginCloneDialog"
v-model="pluginCloneDialog" v-model="pluginCloneDialog"
width="600" width="600"
@@ -700,7 +700,7 @@ watch(
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</div> </div>
</template> </template>
+4 -4
View File
@@ -350,7 +350,7 @@ const dropdownItems = ref([
</VHover> </VHover>
<!-- 重命名对话框 --> <!-- 重命名对话框 -->
<DialogWrapper v-if="renameDialog" v-model="renameDialog" max-width="400"> <VDialog v-if="renameDialog" v-model="renameDialog" max-width="400">
<VCard> <VCard>
<VCardItem> <VCardItem>
<template #prepend> <template #prepend>
@@ -374,10 +374,10 @@ const dropdownItems = ref([
<VBtn color="primary" prepend-icon="mdi-check" class="px-5" @click="confirmRename">确认</VBtn> <VBtn color="primary" prepend-icon="mdi-check" class="px-5" @click="confirmRename">确认</VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 设置对话框 --> <!-- 设置对话框 -->
<DialogWrapper <VDialog
v-if="settingDialog" v-if="settingDialog"
v-model="settingDialog" v-model="settingDialog"
max-width="600" max-width="600"
@@ -480,7 +480,7 @@ const dropdownItems = ref([
<VBtn color="primary" prepend-icon="mdi-content-save" class="px-5" @click="saveSettings">保存</VBtn> <VBtn color="primary" prepend-icon="mdi-content-save" class="px-5" @click="saveSettings">保存</VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</div> </div>
</template> </template>
+2 -2
View File
@@ -220,7 +220,7 @@ function onClose() {
@close="smbConfigDialog = false" @close="smbConfigDialog = false"
@done="handleDone" @done="handleDone"
/> />
<DialogWrapper <VDialog
v-if="customConfigDialog" v-if="customConfigDialog"
v-model="customConfigDialog" v-model="customConfigDialog"
scrollable scrollable
@@ -263,6 +263,6 @@ function onClose() {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</div> </div>
</template> </template>
+3 -3
View File
@@ -278,7 +278,7 @@ onMounted(() => {
</VCard> </VCard>
<!-- 更多来源对话框 --> <!-- 更多来源对话框 -->
<DialogWrapper v-model="showMoreTorrents" max-width="25rem" location="center"> <VDialog v-model="showMoreTorrents" max-width="25rem" location="center">
<VCard> <VCard>
<VCardTitle class="py-3 d-flex align-center"> <VCardTitle class="py-3 d-flex align-center">
<span>其他来源</span> <span>其他来源</span>
@@ -361,7 +361,7 @@ onMounted(() => {
</VList> </VList>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<AddDownloadDialog <AddDownloadDialog
v-if="addDownloadDialog" v-if="addDownloadDialog"
@@ -418,7 +418,7 @@ onMounted(() => {
} }
.chip-web-source { .chip-web-source {
background-color: #8000FF; background-color: #8000ff;
color: white; color: white;
} }
+2 -2
View File
@@ -132,7 +132,7 @@ onMounted(() => {
}) })
</script> </script>
<template> <template>
<DialogWrapper max-width="35rem" scrollable> <VDialog max-width="35rem" scrollable>
<VCard> <VCard>
<VCardItem class="py-2"> <VCardItem class="py-2">
<template #prepend> <template #prepend>
@@ -209,5 +209,5 @@ onMounted(() => {
</VBtn> </VBtn>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -70,7 +70,7 @@ async function savaAlistConfig() {
</script> </script>
<template> <template>
<DialogWrapper width="50rem" scrollable :fullscreen="!display.mdAndUp.value"> <VDialog width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VCardItem> <VCardItem>
@@ -143,5 +143,5 @@ async function savaAlistConfig() {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -110,7 +110,7 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<DialogWrapper width="40rem" scrollable :fullscreen="!display.mdAndUp.value"> <VDialog width="40rem" scrollable :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VCardItem> <VCardItem>
@@ -148,5 +148,5 @@ onUnmounted(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
@@ -170,7 +170,7 @@ onMounted(() => {
}) })
</script> </script>
<template> <template>
<DialogWrapper max-width="40rem" scrollable> <VDialog max-width="40rem" scrollable>
<VCard> <VCard>
<VCardText> <VCardText>
<VCol> <VCol>
@@ -286,5 +286,5 @@ onMounted(() => {
</VCardText> </VCardText>
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -156,7 +156,7 @@ async function doDelete() {
} }
</script> </script>
<template> <template>
<DialogWrapper max-width="40rem" scrollable> <VDialog max-width="40rem" scrollable>
<VCard> <VCard>
<VCardText> <VCardText>
<VCol> <VCol>
@@ -266,7 +266,7 @@ async function doDelete() {
</VCardText> </VCardText>
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
<style lang="scss"> <style lang="scss">
+2 -2
View File
@@ -24,7 +24,7 @@ function handleImport() {
</script> </script>
<template> <template>
<DialogWrapper width="40rem" scrollable max-height="85vh"> <VDialog width="40rem" scrollable max-height="85vh">
<VCard> <VCard>
<VCardItem> <VCardItem>
<template #prepend> <template #prepend>
@@ -43,5 +43,5 @@ function handleImport() {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -15,12 +15,12 @@ defineProps({
const emit = defineEmits(['close']) const emit = defineEmits(['close'])
</script> </script>
<template> <template>
<DialogWrapper max-width="50rem"> <VDialog max-width="50rem">
<VCard> <VCard>
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VCardItem> <VCardItem>
<MediaInfoCard :context="context" /> <MediaInfoCard :context="context" />
</VCardItem> </VCardItem>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -148,7 +148,7 @@ onBeforeMount(async () => {
}) })
</script> </script>
<template> <template>
<DialogWrapper scrollable max-width="60rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="60rem" :fullscreen="!display.mdAndUp.value">
<!-- Vuetify 渲染模式 --> <!-- Vuetify 渲染模式 -->
<VCard v-if="renderMode === 'vuetify'" :title="`${props.plugin?.plugin_name} - ${t('dialog.pluginConfig.title')}`"> <VCard v-if="renderMode === 'vuetify'" :title="`${props.plugin?.plugin_name} - ${t('dialog.pluginConfig.title')}`">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
@@ -187,5 +187,5 @@ onBeforeMount(async () => {
<!-- 进度框 --> <!-- 进度框 -->
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" /> <ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -124,7 +124,7 @@ onMounted(() => {
}) })
</script> </script>
<template> <template>
<DialogWrapper scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value">
<!-- Vuetify 渲染模式 --> <!-- Vuetify 渲染模式 -->
<VCard v-if="renderMode === 'vuetify'" :title="`${props.plugin?.plugin_name}`"> <VCard v-if="renderMode === 'vuetify'" :title="`${props.plugin?.plugin_name}`">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
@@ -160,5 +160,5 @@ onMounted(() => {
/> />
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
@@ -63,7 +63,7 @@ onMounted(() => {
</script> </script>
<template> <template>
<DialogWrapper width="50rem" scrollable :fullscreen="!display.mdAndUp.value"> <VDialog width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem> <VCardItem>
<VCardTitle> <VCardTitle>
@@ -89,5 +89,5 @@ onMounted(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -10,12 +10,12 @@ const props = defineProps({
</script> </script>
<template> <template>
<!-- Progress Dialog --> <!-- Progress Dialog -->
<DialogWrapper :scrim="false" width="25rem"> <VDialog :scrim="false" width="25rem">
<VCard elevation="3" color="primary"> <VCard elevation="3" color="primary">
<VCardText class="text-center"> <VCardText class="text-center">
{{ props.text || t('dialog.progress.processing') }} {{ props.text || t('dialog.progress.processing') }}
<VProgressLinear color="white" class="mb-0 mt-1" :model-value="props.value" indeterminate /> <VProgressLinear color="white" class="mb-0 mt-1" :model-value="props.value" indeterminate />
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -57,7 +57,7 @@ async function handleReset() {
</script> </script>
<template> <template>
<DialogWrapper width="50rem" scrollable :fullscreen="!display.mdAndUp.value"> <VDialog width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VCardItem> <VCardItem>
@@ -99,5 +99,5 @@ async function handleReset() {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+5 -5
View File
@@ -205,7 +205,7 @@ const progressSSE = useProgressSSE(
`${import.meta.env.VITE_API_BASE_URL}system/progress/filetransfer`, `${import.meta.env.VITE_API_BASE_URL}system/progress/filetransfer`,
handleProgressMessage, handleProgressMessage,
'reorganize-progress', 'reorganize-progress',
progressActive progressActive,
) )
// 使用SSE监听加载进度 // 使用SSE监听加载进度
@@ -269,7 +269,7 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<DialogWrapper scrollable max-width="45rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="45rem" :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem class="py-2"> <VCardItem class="py-2">
<template #prepend> <VIcon icon="mdi-folder-move" class="me-2" /> </template> <template #prepend> <VIcon icon="mdi-folder-move" class="me-2" /> </template>
@@ -487,7 +487,7 @@ onUnmounted(() => {
<!-- 手动整理进度框 --> <!-- 手动整理进度框 -->
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" :value="progressValue" /> <ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" :value="progressValue" />
<!-- TMDB ID搜索框 --> <!-- TMDB ID搜索框 -->
<DialogWrapper v-model="mediaSelectorDialog" width="40rem" scrollable max-height="85vh"> <VDialog v-model="mediaSelectorDialog" width="40rem" scrollable max-height="85vh">
<MediaIdSelector <MediaIdSelector
v-if="mediaSource === 'themoviedb'" v-if="mediaSource === 'themoviedb'"
v-model="transferForm.tmdbid" v-model="transferForm.tmdbid"
@@ -500,6 +500,6 @@ onUnmounted(() => {
@close="mediaSelectorDialog = false" @close="mediaSelectorDialog = false"
:type="mediaSource" :type="mediaSource"
/> />
</DialogWrapper> </VDialog>
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -370,7 +370,7 @@ onMounted(() => {
}) })
</script> </script>
<template> <template>
<DialogWrapper v-model="dialog" max-width="42rem" scrollable :fullscreen="!display.mdAndUp.value"> <VDialog v-model="dialog" max-width="42rem" scrollable :fullscreen="!display.mdAndUp.value">
<VCard class="search-dialog"> <VCard class="search-dialog">
<!-- 搜索输入框 --> <!-- 搜索输入框 -->
<VCardItem class="pa-4 pa-sm-5 search-box-container"> <VCardItem class="pa-4 pa-sm-5 search-box-container">
@@ -785,7 +785,7 @@ onMounted(() => {
</div> </div>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 站点选择对话框 --> <!-- 站点选择对话框 -->
<SearchSiteDialog <SearchSiteDialog
+2 -2
View File
@@ -56,7 +56,7 @@ const filteredSites = computed(() => {
</script> </script>
<template> <template>
<!-- Site Selection Dialog --> <!-- Site Selection Dialog -->
<DialogWrapper max-width="40rem" fullscreen-mobile> <VDialog max-width="40rem" fullscreen-mobile>
<VCard class="site-dialog"> <VCard class="site-dialog">
<VCardItem> <VCardItem>
<template #prepend> <template #prepend>
@@ -169,7 +169,7 @@ const filteredSites = computed(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
<style scoped> <style scoped>
.site-checkbox-wrapper { .site-checkbox-wrapper {
+2 -2
View File
@@ -147,7 +147,7 @@ onMounted(async () => {
</script> </script>
<template> <template>
<DialogWrapper scrollable :close-on-back="false" eager max-width="45rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable :close-on-back="false" eager max-width="45rem" :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem :class="props.oper === 'add' ? 'py-3' : 'py-2'"> <VCardItem :class="props.oper === 'add' ? 'py-3' : 'py-2'">
<template #prepend> <template #prepend>
@@ -350,5 +350,5 @@ onMounted(async () => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
@@ -71,7 +71,7 @@ async function updateSiteCookie() {
} }
</script> </script>
<template> <template>
<DialogWrapper max-width="30rem" scrollable> <VDialog max-width="30rem" scrollable>
<!-- Dialog Content --> <!-- Dialog Content -->
<VCard :title="t('dialog.siteCookieUpdate.title')"> <VCard :title="t('dialog.siteCookieUpdate.title')">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
@@ -114,5 +114,5 @@ async function updateSiteCookie() {
</VCard> </VCard>
<!-- 进度框 --> <!-- 进度框 -->
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" /> <ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -222,7 +222,7 @@ watch(selectedFile, async newFile => {
</script> </script>
<template> <template>
<DialogWrapper scrollable max-width="50rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="50rem" :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem class="py-2"> <VCardItem class="py-2">
<template #prepend> <template #prepend>
@@ -383,7 +383,7 @@ watch(selectedFile, async newFile => {
</div> </div>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
<style scoped> <style scoped>
+2 -2
View File
@@ -130,7 +130,7 @@ onMounted(() => {
}) })
</script> </script>
<template> <template>
<DialogWrapper scrollable fullscreen :scrim="false" transition="dialog-bottom-transition"> <VDialog scrollable fullscreen :scrim="false" transition="dialog-bottom-transition">
<VCard> <VCard>
<!-- Toolbar --> <!-- Toolbar -->
<div> <div>
@@ -281,7 +281,7 @@ onMounted(() => {
@error="addDownloadError" @error="addDownloadError"
@close="addDownloadDialog = false" @close="addDownloadDialog = false"
/> />
</DialogWrapper> </VDialog>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -205,7 +205,7 @@ onMounted(() => {
</script> </script>
<template> <template>
<DialogWrapper max-width="50rem" :fullscreen="display.smAndDown.value" scrollable> <VDialog max-width="50rem" :fullscreen="display.smAndDown.value" scrollable>
<VCard> <VCard>
<!-- 标题栏 --> <!-- 标题栏 -->
<VCardItem> <VCardItem>
@@ -302,7 +302,7 @@ onMounted(() => {
</VCard> </VCard>
<!-- 详情弹窗 --> <!-- 详情弹窗 -->
<DialogWrapper v-model="detailDialog" :max-width="display.mdAndUp.value ? 600 : '95%'" scrollable> <VDialog v-model="detailDialog" :max-width="display.mdAndUp.value ? 600 : '95%'" scrollable>
<VCard v-if="selectedSite"> <VCard v-if="selectedSite">
<VCardItem class="py-3"> <VCardItem class="py-3">
<template #prepend> <template #prepend>
@@ -379,8 +379,8 @@ onMounted(() => {
</div> </div>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</DialogWrapper> </VDialog>
</template> </template>
<style scoped> <style scoped>
+2 -2
View File
@@ -287,7 +287,7 @@ onBeforeMount(() => {
</script> </script>
<template> <template>
<DialogWrapper scrollable eager max-width="80rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable eager max-width="80rem" :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem> <VCardItem>
<VCardTitle> <VCardTitle>
@@ -484,5 +484,5 @@ onBeforeMount(() => {
</VCard> </VCard>
<!-- 进度框 --> <!-- 进度框 -->
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="t('dialog.siteUserData.refreshing')" /> <ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="t('dialog.siteUserData.refreshing')" />
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -50,7 +50,7 @@ async function saveSmbConfig() {
</script> </script>
<template> <template>
<DialogWrapper width="50rem" scrollable :fullscreen="!display.mdAndUp.value"> <VDialog width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VCardItem> <VCardItem>
@@ -127,5 +127,5 @@ async function saveSmbConfig() {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
@@ -284,7 +284,7 @@ onMounted(() => {
</script> </script>
<template> <template>
<DialogWrapper scrollable max-width="45rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="45rem" :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem class="py-2"> <VCardItem class="py-2">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
@@ -543,5 +543,5 @@ onMounted(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
@@ -85,7 +85,7 @@ onBeforeMount(() => {
}) })
</script> </script>
<template> <template>
<DialogWrapper scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem class="my-2"> <VCardItem class="my-2">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
@@ -206,7 +206,7 @@ onBeforeMount(() => {
</div> </div>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -146,7 +146,7 @@ function getMediaTypeText(type: string | undefined) {
</script> </script>
<template> <template>
<DialogWrapper scrollable max-width="50rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="50rem" :fullscreen="!display.mdAndUp.value">
<VCard class="mx-auto" width="100%"> <VCard class="mx-auto" width="100%">
<VCardItem> <VCardItem>
<VCardTitle>{{ t('dialog.subscribeHistory.title', { type: getMediaTypeText(props.type) }) }}</VCardTitle> <VCardTitle>{{ t('dialog.subscribeHistory.title', { type: getMediaTypeText(props.type) }) }}</VCardTitle>
@@ -220,5 +220,5 @@ function getMediaTypeText(type: string | undefined) {
</VCard> </VCard>
<!-- 进度框 --> <!-- 进度框 -->
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" /> <ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
</DialogWrapper> </VDialog>
</template> </template>
@@ -55,7 +55,7 @@ const $toast = useToast()
</script> </script>
<template> <template>
<DialogWrapper scrollable max-width="30rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="30rem" :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem class="py-2"> <VCardItem class="py-2">
<template #prepend> <template #prepend>
@@ -112,5 +112,5 @@ const $toast = useToast()
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
@@ -118,7 +118,7 @@ onMounted(() => {
</script> </script>
<template> <template>
<DialogWrapper scrollable max-width="40rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="40rem" :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem> <VCardItem>
<template #prepend> <template #prepend>
@@ -331,7 +331,7 @@ onMounted(() => {
</div> </div>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
<style scoped> <style scoped>
@@ -154,7 +154,7 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<DialogWrapper scrollable max-width="50rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="50rem" :fullscreen="!display.mdAndUp.value">
<VCard class="mx-auto" width="100%"> <VCard class="mx-auto" width="100%">
<VCardItem> <VCardItem>
<VCardTitle>{{ t('dialog.transferQueue.title') }}</VCardTitle> <VCardTitle>{{ t('dialog.transferQueue.title') }}</VCardTitle>
@@ -203,5 +203,5 @@ onUnmounted(() => {
</VWindow> </VWindow>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -115,7 +115,7 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<DialogWrapper width="40rem" scrollable :fullscreen="!display.mdAndUp.value"> <VDialog width="40rem" scrollable :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VCardItem> <VCardItem>
@@ -147,5 +147,5 @@ onUnmounted(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -366,7 +366,7 @@ onMounted(() => {
</script> </script>
<template> <template>
<DialogWrapper scrollable max-width="40rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="40rem" :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem :class="props.oper === 'add' ? 'py-3' : 'py-2'"> <VCardItem :class="props.oper === 'add' ? 'py-3' : 'py-2'">
<template #prepend> <template #prepend>
@@ -619,5 +619,5 @@ onMounted(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+2 -3
View File
@@ -4,7 +4,6 @@ import api from '@/api'
import { useToast } from 'vue-toastification' import { useToast } from 'vue-toastification'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
// //
const { t } = useI18n() const { t } = useI18n()
@@ -134,7 +133,7 @@ onMounted(async () => {
</script> </script>
<template> <template>
<DialogWrapper width="40rem" scrollable> <VDialog width="40rem" scrollable>
<VCard> <VCard>
<VCardItem> <VCardItem>
<VCardTitle> <VCardTitle>
@@ -179,5 +178,5 @@ onMounted(async () => {
</VBtn> </VBtn>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
@@ -197,7 +197,7 @@ const isMacOS = computed(() => {
</script> </script>
<template> <template>
<DialogWrapper scrollable fullscreen :scrim="false" transition="dialog-bottom-transition"> <VDialog scrollable fullscreen :scrim="false" transition="dialog-bottom-transition">
<VCard class="workflow-dialog"> <VCard class="workflow-dialog">
<!-- Toolbar --> <!-- Toolbar -->
<VToolbar color="primary" density="comfortable"> <VToolbar color="primary" density="comfortable">
@@ -256,7 +256,7 @@ const isMacOS = computed(() => {
@close="importCodeDialog = false" @close="importCodeDialog = false"
@save="saveCodeString" @save="saveCodeString"
/> />
</DialogWrapper> </VDialog>
</template> </template>
<style lang="scss"> <style lang="scss">
@@ -182,7 +182,7 @@ onMounted(() => {
</script> </script>
<template> <template>
<DialogWrapper scrollable :close-on-back="false" eager max-width="30rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable :close-on-back="false" eager max-width="30rem" :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem> <VCardItem>
<template #prepend> <template #prepend>
@@ -269,5 +269,5 @@ onMounted(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
@@ -68,7 +68,7 @@ const $toast = useToast()
</script> </script>
<template> <template>
<DialogWrapper scrollable max-width="30rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="30rem" :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem class="py-2"> <VCardItem class="py-2">
<template #prepend> <template #prepend>
@@ -132,5 +132,5 @@ const $toast = useToast()
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -749,7 +749,7 @@ onMounted(() => {
</VCardText> </VCardText>
</VCard> </VCard>
<!-- 重命名弹窗 --> <!-- 重命名弹窗 -->
<DialogWrapper v-if="renamePopper" v-model="renamePopper" max-width="35rem"> <VDialog v-if="renamePopper" v-model="renamePopper" max-width="35rem">
<VCard> <VCard>
<VCardItem> <VCardItem>
<template #prepend> <template #prepend>
@@ -783,7 +783,7 @@ onMounted(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 文件整理弹窗 --> <!-- 文件整理弹窗 -->
<ReorganizeDialog <ReorganizeDialog
v-if="transferPopper" v-if="transferPopper"
+2 -2
View File
@@ -166,7 +166,7 @@ const sortIcon = computed(() => {
<VIcon icon="mdi-arrow-up-bold-outline" /> <VIcon icon="mdi-arrow-up-bold-outline" />
</IconBtn> </IconBtn>
<!-- 新建文件夹 --> <!-- 新建文件夹 -->
<DialogWrapper v-model="newFolderPopper" max-width="35rem"> <VDialog v-model="newFolderPopper" max-width="35rem">
<template #activator="{ props }"> <template #activator="{ props }">
<IconBtn> <IconBtn>
<VIcon v-bind="props" icon="mdi-folder-plus-outline" /> <VIcon v-bind="props" icon="mdi-folder-plus-outline" />
@@ -191,6 +191,6 @@ const sortIcon = computed(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</VToolbar> </VToolbar>
</template> </template>
-383
View File
@@ -1,383 +0,0 @@
import { ref, watch, onBeforeUnmount, readonly } from 'vue'
/**
* Composable
*
* 使
*
* // 基本用法
* const { isLocked, lockScroll, restoreScroll } = useScrollLock()
*
* // 带配置的用法
* const { isLocked, lockScroll, restoreScroll } = useScrollLock({
* preventTouchScroll: true,
* preserveScrollPosition: true,
* allowScrollSelectors: ['.my-modal', '.scrollable-content'],
* allowScrollContainerSelectors: ['.modal-content'],
* customScrollCheck: (element) => {
* // 自定义逻辑
* return element.classList.contains('allow-scroll')
* }
* })
*
* // 自动监听版本
* const { isLocked, lockScroll, restoreScroll } = useScrollLockWithWatch(
* showModal, // 响应式布尔值
* {
* allowScrollSelectors: ['.modal-content'],
* allowScrollContainerSelectors: ['.scrollable-area']
* }
* )
*/
// 滚动锁定配置
export interface ScrollLockOptions {
// 是否在组件卸载时自动恢复滚动
autoRestore?: boolean
// 是否保存和恢复滚动位置
preserveScrollPosition?: boolean
// 是否阻止触摸事件穿透
preventTouchScroll?: boolean
// 自定义锁定时的样式
lockStyles?: {
overflow?: string
position?: string
width?: string
}
// 允许滚动的选择器列表(CSS选择器)
// 例如:['.my-modal', '.scrollable-content']
allowScrollSelectors?: string[]
// 允许滚动的容器选择器列表(CSS选择器)
// 这些容器内的可滚动元素将被允许滚动
// 例如:['.modal-content', '.scroll-container']
allowScrollContainerSelectors?: string[]
// 自定义滚动检查函数
// 返回 true 表示允许滚动,false 表示阻止滚动
customScrollCheck?: (element: Element) => boolean
}
// 默认配置
const DEFAULT_OPTIONS: Required<
Omit<ScrollLockOptions, 'allowScrollSelectors' | 'allowScrollContainerSelectors' | 'customScrollCheck'>
> = {
autoRestore: true,
preserveScrollPosition: true,
preventTouchScroll: true,
lockStyles: {
overflow: 'hidden',
position: 'fixed',
width: '100%',
},
}
// 全局状态管理
const globalLockCount = ref(0)
const globalOriginalStyles = ref<{
body: { [key: string]: string }
documentElement: { [key: string]: string }
html: { [key: string]: string }
} | null>(null)
const globalSavedScrollPosition = ref(0)
const globalTouchEventListeners = new Set<(event: TouchEvent) => void>()
// 保存全局原始样式(只在第一次锁定时保存)
const saveGlobalOriginalStyles = () => {
if (globalOriginalStyles.value === null) {
globalOriginalStyles.value = {
body: {
overflow: document.body.style.overflow,
},
documentElement: {
overflow: document.documentElement.style.overflow,
},
html: {
overflow: document.documentElement.style.overflow,
},
}
}
}
// 保存全局滚动位置(只在第一次锁定时保存)
const saveGlobalScrollPosition = () => {
if (globalLockCount.value === 0) {
globalSavedScrollPosition.value =
window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
}
}
// 应用全局锁定样式
const applyGlobalLockStyles = (config: any) => {
if (globalLockCount.value === 1) {
// 第一次锁定时应用样式
document.body.style.overflow = config.lockStyles.overflow || 'hidden'
document.documentElement.style.overflow = config.lockStyles.overflow || 'hidden'
document.documentElement.classList.add('v-overlay-scroll-blocked')
}
}
// 恢复全局样式(只在最后一个锁定时恢复)
const restoreGlobalStyles = (config: any) => {
if (globalLockCount.value === 0 && globalOriginalStyles.value) {
// 最后一个锁定时恢复样式
document.body.style.overflow = globalOriginalStyles.value.body.overflow || ''
document.documentElement.style.overflow = globalOriginalStyles.value.documentElement.overflow || ''
// 移除 CSS 类名
document.documentElement.classList.remove('v-overlay-scroll-blocked')
// 重置全局状态
globalOriginalStyles.value = null
globalSavedScrollPosition.value = 0
}
}
// 添加全局触摸事件监听器
const addGlobalTouchEventListener = (listener: (event: TouchEvent) => void) => {
globalTouchEventListeners.add(listener)
if (globalTouchEventListeners.size === 1) {
// 第一次添加监听器时绑定到document
document.addEventListener('touchmove', listener, { passive: false })
}
}
// 移除全局触摸事件监听器
const removeGlobalTouchEventListener = (listener: (event: TouchEvent) => void) => {
globalTouchEventListeners.delete(listener)
if (globalTouchEventListeners.size === 0) {
// 最后一个监听器被移除时解绑
document.removeEventListener('touchmove', listener)
}
}
export function useScrollLock(options: ScrollLockOptions = {}) {
const config = {
...DEFAULT_OPTIONS,
allowScrollSelectors: options.allowScrollSelectors || [],
allowScrollContainerSelectors: options.allowScrollContainerSelectors || [],
customScrollCheck: options.customScrollCheck,
...options,
}
// 状态管理
const isLocked = ref(false)
const savedScrollPosition = ref(0)
// 保存当前滚动位置
const saveScrollPosition = () => {
if (config.preserveScrollPosition) {
savedScrollPosition.value =
window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
}
}
// 检查元素是否应该允许滚动
const shouldAllowScroll = (element: Element): boolean => {
// 1. 检查是否匹配允许滚动的选择器
for (const selector of config.allowScrollSelectors) {
if (element.matches(selector) || element.closest(selector)) {
return true
}
}
// 2. 检查是否在允许滚动的容器内
for (const selector of config.allowScrollContainerSelectors) {
const container = element.closest(selector)
if (container) {
// 检查容器是否可滚动
const style = getComputedStyle(container)
const isScrollable =
container.scrollHeight > container.clientHeight &&
style.overflow !== 'hidden' &&
(style.overflow === 'auto' ||
style.overflow === 'scroll' ||
style.overflowY === 'auto' ||
style.overflowY === 'scroll')
if (isScrollable) {
return true
}
}
}
// 3. 检查是否在弹窗、菜单或其他覆盖层内
const isInDialog = element.closest(
'.v-dialog, .v-menu, .v-bottom-sheet, .v-snackbar, [role="dialog"], .v-overlay__content',
)
// 4. 检查是否是可滚动的内容区域
const isScrollableContent = element.closest(
'.v-card-text, .v-list, .v-table__wrapper, .v-data-table__wrapper, .v-sheet, .v-card__content, .v-data-table, .v-table',
)
// 5. 检查是否在可滚动的容器内
const scrollableContainer = element.closest('[style*="overflow"], [class*="overflow"]')
const isInScrollableContainer =
scrollableContainer &&
(scrollableContainer.scrollHeight > scrollableContainer.clientHeight ||
getComputedStyle(scrollableContainer).overflow !== 'hidden')
// 6. 使用自定义检查函数
if (config.customScrollCheck && config.customScrollCheck(element)) {
return true
}
// 如果不在弹窗内且不是可滚动内容且不在可滚动容器内,则不允许滚动
return !!(isInDialog || isScrollableContent || isInScrollableContainer)
}
// 阻止触摸滚动事件
const preventTouchScroll = (event: TouchEvent) => {
if (isLocked.value && config.preventTouchScroll) {
// 检查触摸事件的目标元素
const target = event.target as Element
if (target) {
// 如果元素应该允许滚动,则不阻止事件
if (shouldAllowScroll(target)) {
return
}
}
// 否则阻止滚动
event.preventDefault()
event.stopPropagation()
}
}
// 锁定滚动
const lockScroll = () => {
if (isLocked.value) return
// 增加全局锁定计数
globalLockCount.value++
// 保存当前状态(只在第一次锁定时)
if (globalLockCount.value === 1) {
saveGlobalOriginalStyles()
saveGlobalScrollPosition()
}
// 应用锁定样式
applyGlobalLockStyles(config)
// 添加触摸事件监听器
if (config.preventTouchScroll) {
addGlobalTouchEventListener(preventTouchScroll)
}
isLocked.value = true
}
// 恢复滚动
const restoreScroll = () => {
if (!isLocked.value) return
// 减少全局锁定计数
globalLockCount.value--
// 移除触摸事件监听器
if (config.preventTouchScroll) {
removeGlobalTouchEventListener(preventTouchScroll)
}
// 恢复样式(只在最后一个锁定时)
restoreGlobalStyles(config)
isLocked.value = false
}
// 切换滚动锁定状态
const toggleScrollLock = (lock?: boolean) => {
const shouldLock = lock !== undefined ? lock : !isLocked.value
if (shouldLock) {
lockScroll()
} else {
restoreScroll()
}
}
// 监听响应式值的变化
const watchTarget = (target: any) => {
return watch(
target,
newValue => {
toggleScrollLock(!!newValue)
},
{ immediate: false },
)
}
// 生命周期清理
onBeforeUnmount(() => {
if (config.autoRestore && isLocked.value) {
restoreScroll()
}
})
return {
// 状态
isLocked: readonly(isLocked),
savedScrollPosition: readonly(savedScrollPosition),
// 方法
lockScroll,
restoreScroll,
toggleScrollLock,
watchTarget,
// 工具方法
saveScrollPosition,
}
}
// 便捷的自动监听版本
export function useScrollLockWithWatch(target: any, options: ScrollLockOptions = {}) {
const scrollLock = useScrollLock(options)
// 自动监听目标值的变化
const stopWatcher = scrollLock.watchTarget(target)
// 返回所有功能 + 停止监听的方法
return {
...scrollLock,
stopWatcher,
}
}
// 全局弹窗检测和管理
export function useGlobalDialogScrollLock() {
const activeDialogs = ref<Set<string>>(new Set())
const registerDialog = (dialogId: string) => {
activeDialogs.value.add(dialogId)
if (activeDialogs.value.size === 1) {
// 第一个弹窗时锁定滚动
lockGlobalScroll()
}
}
const unregisterDialog = (dialogId: string) => {
activeDialogs.value.delete(dialogId)
if (activeDialogs.value.size === 0) {
// 没有弹窗时恢复滚动
unlockGlobalScroll()
}
}
const lockGlobalScroll = () => {
document.body.style.overflow = 'hidden'
document.documentElement.classList.add('v-overlay-scroll-blocked')
}
const unlockGlobalScroll = () => {
document.body.style.overflow = ''
document.documentElement.classList.remove('v-overlay-scroll-blocked')
}
return {
activeDialogs: readonly(activeDialogs),
registerDialog,
unregisterDialog,
lockGlobalScroll,
unlockGlobalScroll,
}
}
-12
View File
@@ -18,7 +18,6 @@ import { useRoute } from 'vue-router'
import { filterMenusByPermission } from '@/utils/permission' import { filterMenusByPermission } from '@/utils/permission'
import { onUnreadMessage } from '@/utils/badge' import { onUnreadMessage } from '@/utils/badge'
import { usePullDownGesture } from '@/composables/usePullDownGesture' import { usePullDownGesture } from '@/composables/usePullDownGesture'
import { useScrollLockWithWatch } from '@/composables/useScrollLock'
import { usePWA } from '@/composables/usePWA' import { usePWA } from '@/composables/usePWA'
import OfflinePage from '@/layouts/components/OfflinePage.vue' import OfflinePage from '@/layouts/components/OfflinePage.vue'
import { useGlobalOfflineStatus } from '@/composables/useOfflineStatus' import { useGlobalOfflineStatus } from '@/composables/useOfflineStatus'
@@ -163,17 +162,6 @@ const handleServiceWorkerMessage = (event: MessageEvent) => {
} }
} }
// 使 composableshowPluginQuickAccess
useScrollLockWithWatch(showPluginQuickAccess, {
preventTouchScroll: true,
preserveScrollPosition: true,
autoRestore: true,
// 访
allowScrollSelectors: ['.plugin-quick-access'],
// 访
allowScrollContainerSelectors: ['.plugin-grid'],
})
// 使 // 使
const canUsePullGesture = () => { const canUsePullGesture = () => {
// dashboard // dashboard
+12 -12
View File
@@ -265,7 +265,7 @@ onMounted(() => {
</VCard> </VCard>
</VMenu> </VMenu>
<!-- 名称测试弹窗 --> <!-- 名称测试弹窗 -->
<DialogWrapper <VDialog
v-if="nameTestDialog" v-if="nameTestDialog"
v-model="nameTestDialog" v-model="nameTestDialog"
max-width="45rem" max-width="45rem"
@@ -285,9 +285,9 @@ onMounted(() => {
<NameTestView /> <NameTestView />
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 网络测试弹窗 --> <!-- 网络测试弹窗 -->
<DialogWrapper <VDialog
v-if="netTestDialog" v-if="netTestDialog"
v-model="netTestDialog" v-model="netTestDialog"
max-width="35rem" max-width="35rem"
@@ -307,9 +307,9 @@ onMounted(() => {
<NetTestView /> <NetTestView />
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 实时日志弹窗 --> <!-- 实时日志弹窗 -->
<DialogWrapper <VDialog
v-if="loggingDialog" v-if="loggingDialog"
v-model="loggingDialog" v-model="loggingDialog"
scrollable scrollable
@@ -335,9 +335,9 @@ onMounted(() => {
<LoggingView logfile="moviepilot.log" /> <LoggingView logfile="moviepilot.log" />
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 过滤规则弹窗 --> <!-- 过滤规则弹窗 -->
<DialogWrapper <VDialog
v-if="ruleTestDialog" v-if="ruleTestDialog"
v-model="ruleTestDialog" v-model="ruleTestDialog"
max-width="35rem" max-width="35rem"
@@ -357,9 +357,9 @@ onMounted(() => {
<RuleTestView /> <RuleTestView />
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 系统健康检查弹窗 --> <!-- 系统健康检查弹窗 -->
<DialogWrapper <VDialog
v-if="systemTestDialog" v-if="systemTestDialog"
v-model="systemTestDialog" v-model="systemTestDialog"
max-width="35rem" max-width="35rem"
@@ -379,9 +379,9 @@ onMounted(() => {
<ModuleTestView /> <ModuleTestView />
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 消息中心弹窗 --> <!-- 消息中心弹窗 -->
<DialogWrapper <VDialog
v-if="messageDialog" v-if="messageDialog"
v-model="messageDialog" v-model="messageDialog"
max-width="50rem" max-width="50rem"
@@ -424,5 +424,5 @@ onMounted(() => {
</div> </div>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+4 -4
View File
@@ -650,7 +650,7 @@ onUnmounted(() => {
<!-- 用户认证对话框 --> <!-- 用户认证对话框 -->
<UserAuthDialog v-if="siteAuthDialog" v-model="siteAuthDialog" @done="siteAuthDone" @close="siteAuthDialog = false" /> <UserAuthDialog v-if="siteAuthDialog" v-model="siteAuthDialog" @done="siteAuthDone" @close="siteAuthDialog = false" />
<!-- 自定义 CSS --> <!-- 自定义 CSS -->
<DialogWrapper v-if="cssDialog" v-model="cssDialog" max-width="50rem" scrollable :fullscreen="!display.mdAndUp.value"> <VDialog v-if="cssDialog" v-model="cssDialog" max-width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem> <VCardItem>
<VCardTitle> <VCardTitle>
@@ -671,10 +671,10 @@ onUnmounted(() => {
</VBtn> </VBtn>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 透明度调整对话框 --> <!-- 透明度调整对话框 -->
<DialogWrapper v-if="showTransparencyDialog" v-model="showTransparencyDialog" max-width="30rem"> <VDialog v-if="showTransparencyDialog" v-model="showTransparencyDialog" max-width="30rem">
<VCard> <VCard>
<VCardItem> <VCardItem>
<VCardTitle> <VCardTitle>
@@ -763,7 +763,7 @@ onUnmounted(() => {
</VBtn> </VBtn>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
+2 -2
View File
@@ -389,7 +389,7 @@ onDeactivated(() => {
</Teleport> </Teleport>
<!-- 弹窗根据配置生成选项 --> <!-- 弹窗根据配置生成选项 -->
<DialogWrapper v-if="dialog" v-model="dialog" max-width="35rem" :fullscreen="!display.mdAndUp.value" scrollable> <VDialog v-if="dialog" v-model="dialog" max-width="35rem" :fullscreen="!display.mdAndUp.value" scrollable>
<VCard> <VCard>
<VCardItem> <VCardItem>
<VCardTitle> <VCardTitle>
@@ -443,7 +443,7 @@ onDeactivated(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.settings-card-header { .settings-card-header {
+2 -2
View File
@@ -216,7 +216,7 @@ onActivated(async () => {
</VWindowItem> </VWindowItem>
</VWindow> </VWindow>
<!-- 弹窗根据配置生成选项 --> <!-- 弹窗根据配置生成选项 -->
<DialogWrapper <VDialog
v-if="orderConfigDialog" v-if="orderConfigDialog"
v-model="orderConfigDialog" v-model="orderConfigDialog"
max-width="35rem" max-width="35rem"
@@ -265,7 +265,7 @@ onActivated(async () => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 快速滚动到顶部按钮 --> <!-- 快速滚动到顶部按钮 -->
<Teleport to="body" v-if="route.path === '/discover'"> <Teleport to="body" v-if="route.path === '/discover'">
<VScrollToTopBtn /> <VScrollToTopBtn />
+2 -8
View File
@@ -269,13 +269,7 @@ onActivated(async () => {
</div> </div>
<!-- 设置面板 --> <!-- 设置面板 -->
<DialogWrapper <VDialog v-model="dialog" width="35rem" class="settings-dialog" scrollable :fullscreen="!display.mdAndUp.value">
v-model="dialog"
width="35rem"
class="settings-dialog"
scrollable
:fullscreen="!display.mdAndUp.value"
>
<VCard class="settings-card"> <VCard class="settings-card">
<VCardItem class="settings-card-header"> <VCardItem class="settings-card-header">
<VCardTitle> <VCardTitle>
@@ -327,7 +321,7 @@ onActivated(async () => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 快速滚动到顶部按钮 --> <!-- 快速滚动到顶部按钮 -->
<Teleport to="body" v-if="route.path === '/recommend'"> <Teleport to="body" v-if="route.path === '/recommend'">
+1 -1
View File
@@ -6,7 +6,7 @@ declare let self: ServiceWorkerGlobalScope & {
} }
// 缓存版本控制 // 缓存版本控制
const CACHE_VERSION = 'v1.0.7' const CACHE_VERSION = 'v1.0.8'
const CACHE_NAMES = { const CACHE_NAMES = {
appShell: `app-shell-${CACHE_VERSION}`, appShell: `app-shell-${CACHE_VERSION}`,
static: `static-resources-${CACHE_VERSION}`, static: `static-resources-${CACHE_VERSION}`,
+7 -10
View File
@@ -215,10 +215,7 @@ const defaultColor = '#2196F3'
// //
const isFilterFormEmpty = computed(() => { const isFilterFormEmpty = computed(() => {
return ( return (
!filterForm.name && !filterForm.name && filterForm.author.length === 0 && filterForm.label.length === 0 && filterForm.repo.length === 0
filterForm.author.length === 0 &&
filterForm.label.length === 0 &&
filterForm.repo.length === 0
) )
}) })
@@ -1552,7 +1549,7 @@ function onDragStartPlugin(evt: any) {
/> />
<!-- 插件搜索窗口 --> <!-- 插件搜索窗口 -->
<DialogWrapper <VDialog
v-if="SearchDialog" v-if="SearchDialog"
v-model="SearchDialog" v-model="SearchDialog"
scrollable scrollable
@@ -1611,20 +1608,20 @@ function onDragStartPlugin(evt: any) {
</VVirtualScroll> </VVirtualScroll>
</VList> </VList>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 安装插件进度框 --> <!-- 安装插件进度框 -->
<DialogWrapper v-if="progressDialog" v-model="progressDialog" :scrim="false" width="25rem"> <VDialog v-if="progressDialog" v-model="progressDialog" :scrim="false" width="25rem">
<VCard color="primary"> <VCard color="primary">
<VCardText class="text-center"> <VCardText class="text-center">
{{ progressText }} {{ progressText }}
<VProgressLinear indeterminate color="white" class="mb-0 mt-1" /> <VProgressLinear indeterminate color="white" class="mb-0 mt-1" />
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 新建文件夹对话框 --> <!-- 新建文件夹对话框 -->
<DialogWrapper v-if="newFolderDialog" v-model="newFolderDialog" max-width="400"> <VDialog v-if="newFolderDialog" v-model="newFolderDialog" max-width="400">
<VCard> <VCard>
<VDialogCloseBtn @click="newFolderDialog = false" /> <VDialogCloseBtn @click="newFolderDialog = false" />
<VCardItem> <VCardItem>
@@ -1646,5 +1643,5 @@ function onDragStartPlugin(evt: any) {
}}</VBtn> }}</VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+2 -2
View File
@@ -338,7 +338,7 @@ onMounted(() => {
</div> </div>
</div> </div>
</div> </div>
<DialogWrapper v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable> <VDialog v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable>
<VCard> <VCard>
<VCardItem> <VCardItem>
<VDialogCloseBtn @click="releaseDialog = false" /> <VDialogCloseBtn @click="releaseDialog = false" />
@@ -346,7 +346,7 @@ onMounted(() => {
</VCardItem> </VCardItem>
<VCardText v-html="releaseDialogBody" /> <VCardText v-html="releaseDialogBody" />
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
<style type="scss" scoped> <style type="scss" scoped>
+2 -3
View File
@@ -11,7 +11,6 @@ import { usePWA } from '@/composables/usePWA'
// //
const { t } = useI18n() const { t } = useI18n()
// PWA // PWA
const { appMode } = usePWA() const { appMode } = usePWA()
@@ -423,7 +422,7 @@ onMounted(() => {
</VCard> </VCard>
<!-- 重新识别对话框 --> <!-- 重新识别对话框 -->
<DialogWrapper v-model="reidentifyDialog" scrollable max-width="35rem"> <VDialog v-model="reidentifyDialog" scrollable max-width="35rem">
<VCard> <VCard>
<VCardItem class="py-2"> <VCardItem class="py-2">
<template #prepend> <template #prepend>
@@ -469,5 +468,5 @@ onMounted(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
@@ -444,7 +444,7 @@ onMounted(() => {
:indeterminate="true" :indeterminate="true"
/> />
<!-- 模板编辑器对话框 --> <!-- 模板编辑器对话框 -->
<DialogWrapper v-model="editorVisible" v-if="editorVisible" max-width="50rem" :fullscreen="!display.mdAndUp.value"> <VDialog v-model="editorVisible" v-if="editorVisible" max-width="50rem" :fullscreen="!display.mdAndUp.value">
<VCard> <VCard>
<VCardItem class="py-2"> <VCardItem class="py-2">
<template #prepend> <template #prepend>
@@ -472,7 +472,7 @@ onMounted(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
<style scoped> <style scoped>
/* Monaco编辑器容器样式 */ /* Monaco编辑器容器样式 */
+2 -2
View File
@@ -733,7 +733,7 @@ onDeactivated(() => {
</VRow> </VRow>
<!-- 高级系统设置 --> <!-- 高级系统设置 -->
<DialogWrapper <VDialog
v-if="advancedDialog" v-if="advancedDialog"
v-model="advancedDialog" v-model="advancedDialog"
scrollable scrollable
@@ -1329,5 +1329,5 @@ onDeactivated(() => {
</VForm> </VForm>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</template> </template>
+4 -4
View File
@@ -617,7 +617,7 @@ const handleSortIconClick = () => {
</VCard> </VCard>
<!-- 全部筛选弹窗 --> <!-- 全部筛选弹窗 -->
<DialogWrapper <VDialog
v-model="allFilterMenuOpen" v-model="allFilterMenuOpen"
max-width="50rem" max-width="50rem"
location="center" location="center"
@@ -690,10 +690,10 @@ const handleSortIconClick = () => {
</div> </div>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 筛选弹窗 --> <!-- 筛选弹窗 -->
<DialogWrapper v-model="filterMenuOpen" max-width="25rem" location="center" max-height="85vh" scrollable> <VDialog v-model="filterMenuOpen" max-width="25rem" location="center" max-height="85vh" scrollable>
<VCard> <VCard>
<VCardTitle class="py-3 d-flex align-center"> <VCardTitle class="py-3 d-flex align-center">
<VIcon :icon="getFilterIcon(currentFilter)" class="me-2"></VIcon> <VIcon :icon="getFilterIcon(currentFilter)" class="me-2"></VIcon>
@@ -735,7 +735,7 @@ const handleSortIconClick = () => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 资源列表 --> <!-- 资源列表 -->
<VInfiniteScroll mode="intersect" side="end" :items="displayDataList" class="overflow-visible" @load="loadMore"> <VInfiniteScroll mode="intersect" side="end" :items="displayDataList" class="overflow-visible" @load="loadMore">
+4 -4
View File
@@ -597,7 +597,7 @@ onMounted(() => {
</VCard> </VCard>
<!-- 全部筛选弹窗 --> <!-- 全部筛选弹窗 -->
<DialogWrapper <VDialog
v-model="allFilterMenuOpen" v-model="allFilterMenuOpen"
max-width="50rem" max-width="50rem"
location="center" location="center"
@@ -670,10 +670,10 @@ onMounted(() => {
</div> </div>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 筛选弹窗 --> <!-- 筛选弹窗 -->
<DialogWrapper v-model="filterMenuOpen" max-width="25rem" max-height="85vh" location="center" scrollable> <VDialog v-model="filterMenuOpen" max-width="25rem" max-height="85vh" location="center" scrollable>
<VCard> <VCard>
<VCardTitle class="py-3 d-flex align-center"> <VCardTitle class="py-3 d-flex align-center">
<VIcon :icon="getFilterIcon(currentFilter)" class="me-2"></VIcon> <VIcon :icon="getFilterIcon(currentFilter)" class="me-2"></VIcon>
@@ -715,7 +715,7 @@ onMounted(() => {
</VBtn> </VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</DialogWrapper> </VDialog>
<!-- 资源列表容器 --> <!-- 资源列表容器 -->
<VCard class="resource-list-container"> <VCard class="resource-list-container">
+2 -2
View File
@@ -454,7 +454,7 @@ watch(
</VRow> </VRow>
<!-- 双重验证弹窗 --> <!-- 双重验证弹窗 -->
<DialogWrapper v-if="otpDialog" v-model="otpDialog" max-width="45rem" scrollable> <VDialog v-if="otpDialog" v-model="otpDialog" max-width="45rem" scrollable>
<!-- 开启双重验证弹窗内容 --> <!-- 开启双重验证弹窗内容 -->
<VCard> <VCard>
<VDialogCloseBtn @click="otpDialog = false" /> <VDialogCloseBtn @click="otpDialog = false" />
@@ -492,6 +492,6 @@ watch(
</VForm> </VForm>
</VCardText> </VCardText>
</VCard> </VCard>
</DialogWrapper> </VDialog>
</div> </div>
</template> </template>