mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-05-10 17:42:50 +08:00
重构对话框组件,将所有 DialogWrapper 替换为 VDialog,并更新缓存版本至 v1.1.0
This commit is contained in:
2
components.d.ts
vendored
2
components.d.ts
vendored
@@ -10,7 +10,6 @@ declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
ConfirmDialog: typeof import('./src/@core/components/ConfirmDialog.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']
|
||||
ExistIcon: typeof import('./src/@core/components/ExistIcon.vue')['default']
|
||||
LoadingBanner: typeof import('./src/@core/components/LoadingBanner.vue')['default']
|
||||
@@ -20,5 +19,6 @@ declare module 'vue' {
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
ScrollToTopBtn: typeof import('./src/@core/components/ScrollToTopBtn.vue')['default']
|
||||
StatIcon: typeof import('./src/@core/components/StatIcon.vue')['default']
|
||||
VDialog: typeof import('./src/@core/components/VDialog.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ function handleCancel() {
|
||||
</script>
|
||||
|
||||
<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>
|
||||
<VCardItem>
|
||||
<div class="d-flex align-center justify-start mt-3">
|
||||
@@ -82,5 +82,5 @@ function handleCancel() {
|
||||
</VCardActions>
|
||||
<VDialogCloseBtn @click="handleCancel" />
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -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>
|
||||
@@ -133,7 +133,7 @@ const instructions = computed(() => {
|
||||
</Teleport>
|
||||
|
||||
<!-- 手动安装说明对话框 -->
|
||||
<DialogWrapper v-model="showInstructions" max-width="500">
|
||||
<VDialog v-model="showInstructions" max-width="500">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle class="d-flex align-center">
|
||||
@@ -170,7 +170,7 @@ const instructions = computed(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -116,7 +116,7 @@ function onClose() {
|
||||
<VImg :src="filter_svg" cover class="mt-7" max-width="3rem" />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="ruleInfoDialog"
|
||||
v-model="ruleInfoDialog"
|
||||
scrollable
|
||||
@@ -222,6 +222,6 @@ function onClose() {
|
||||
}}</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -147,7 +147,7 @@ const { stop: stopRefresh } = useConditionalDataRefresh(
|
||||
loadDownloaderInfo,
|
||||
shouldRefresh, // 响应式条件:只有当allowRefresh为true且downloader启用时才运行
|
||||
3000, // 3秒间隔
|
||||
true // 立即执行一次
|
||||
true, // 立即执行一次
|
||||
)
|
||||
|
||||
onUnmounted(() => {
|
||||
@@ -196,7 +196,7 @@ onUnmounted(() => {
|
||||
</VCard>
|
||||
</VHover>
|
||||
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="downloaderInfoDialog"
|
||||
v-model="downloaderInfoDialog"
|
||||
scrollable
|
||||
@@ -383,6 +383,6 @@ onUnmounted(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -223,7 +223,7 @@ function onClose() {
|
||||
<VImg :src="filter_group_svg" cover class="mt-10" max-width="3rem" />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="groupInfoDialog"
|
||||
v-model="groupInfoDialog"
|
||||
scrollable
|
||||
@@ -308,7 +308,7 @@ function onClose() {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
<ImportCodeDialog
|
||||
v-if="importCodeDialog"
|
||||
v-model="importCodeDialog"
|
||||
|
||||
@@ -204,7 +204,7 @@ onMounted(() => {
|
||||
</VCardText>
|
||||
</VCard>
|
||||
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="mediaServerInfoDialog"
|
||||
v-model="mediaServerInfoDialog"
|
||||
scrollable
|
||||
@@ -506,6 +506,6 @@ onMounted(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -141,7 +141,7 @@ function onClose() {
|
||||
</VCardText>
|
||||
</VCard>
|
||||
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="notificationInfoDialog"
|
||||
v-model="notificationInfoDialog"
|
||||
scrollable
|
||||
@@ -476,6 +476,6 @@ function onClose() {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -106,7 +106,9 @@ const iconPath: Ref<string> = computed(() => {
|
||||
if (imageLoadError.value) return noImage
|
||||
// 如果是网络图片则使用代理后返回
|
||||
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}`
|
||||
})
|
||||
@@ -267,15 +269,15 @@ const dropdownItems = ref([
|
||||
<!-- 安装插件进度框 -->
|
||||
<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 })">
|
||||
<VDialogCloseBtn @click="releaseDialog = false" />
|
||||
<VDivider />
|
||||
<VersionHistory :history="props.plugin?.history" />
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
<!-- 插件详情-->
|
||||
<DialogWrapper v-if="detailDialog" v-model="detailDialog" max-width="30rem">
|
||||
<VDialog v-if="detailDialog" v-model="detailDialog" max-width="30rem">
|
||||
<VCard>
|
||||
<VDialogCloseBtn @click="detailDialog = false" />
|
||||
<VCardText>
|
||||
@@ -335,6 +337,6 @@ const dropdownItems = ref([
|
||||
</VCol>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -547,7 +547,7 @@ watch(
|
||||
<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 })">
|
||||
<VDialogCloseBtn @click="releaseDialog = false" />
|
||||
<VDivider />
|
||||
@@ -562,10 +562,10 @@ watch(
|
||||
</VBtn>
|
||||
</VCardItem>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
|
||||
<!-- 实时日志弹窗 -->
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="loggingDialog"
|
||||
v-model="loggingDialog"
|
||||
scrollable
|
||||
@@ -591,10 +591,10 @@ watch(
|
||||
<LoggingView :logfile="`plugins/${props.plugin?.id?.toLowerCase()}.log`" />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
|
||||
<!-- 插件分身对话框 -->
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="pluginCloneDialog"
|
||||
v-model="pluginCloneDialog"
|
||||
width="600"
|
||||
@@ -700,7 +700,7 @@ watch(
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -350,7 +350,7 @@ const dropdownItems = ref([
|
||||
</VHover>
|
||||
|
||||
<!-- 重命名对话框 -->
|
||||
<DialogWrapper v-if="renameDialog" v-model="renameDialog" max-width="400">
|
||||
<VDialog v-if="renameDialog" v-model="renameDialog" max-width="400">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<template #prepend>
|
||||
@@ -374,10 +374,10 @@ const dropdownItems = ref([
|
||||
<VBtn color="primary" prepend-icon="mdi-check" class="px-5" @click="confirmRename">确认</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
|
||||
<!-- 设置对话框 -->
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="settingDialog"
|
||||
v-model="settingDialog"
|
||||
max-width="600"
|
||||
@@ -480,7 +480,7 @@ const dropdownItems = ref([
|
||||
<VBtn color="primary" prepend-icon="mdi-content-save" class="px-5" @click="saveSettings">保存</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ function onClose() {
|
||||
@close="smbConfigDialog = false"
|
||||
@done="handleDone"
|
||||
/>
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="customConfigDialog"
|
||||
v-model="customConfigDialog"
|
||||
scrollable
|
||||
@@ -263,6 +263,6 @@ function onClose() {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -278,7 +278,7 @@ onMounted(() => {
|
||||
</VCard>
|
||||
|
||||
<!-- 更多来源对话框 -->
|
||||
<DialogWrapper v-model="showMoreTorrents" max-width="25rem" location="center">
|
||||
<VDialog v-model="showMoreTorrents" max-width="25rem" location="center">
|
||||
<VCard>
|
||||
<VCardTitle class="py-3 d-flex align-center">
|
||||
<span>其他来源</span>
|
||||
@@ -361,7 +361,7 @@ onMounted(() => {
|
||||
</VList>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
|
||||
<AddDownloadDialog
|
||||
v-if="addDownloadDialog"
|
||||
@@ -418,7 +418,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.chip-web-source {
|
||||
background-color: #8000FF;
|
||||
background-color: #8000ff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ onMounted(() => {
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<DialogWrapper max-width="35rem" scrollable>
|
||||
<VDialog max-width="35rem" scrollable>
|
||||
<VCard>
|
||||
<VCardItem class="py-2">
|
||||
<template #prepend>
|
||||
@@ -209,5 +209,5 @@ onMounted(() => {
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -70,7 +70,7 @@ async function savaAlistConfig() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VDialogCloseBtn @click="emit('close')" />
|
||||
<VCardItem>
|
||||
@@ -143,5 +143,5 @@ async function savaAlistConfig() {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -110,7 +110,7 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper width="40rem" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog width="40rem" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VDialogCloseBtn @click="emit('close')" />
|
||||
<VCardItem>
|
||||
@@ -148,5 +148,5 @@ onUnmounted(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -170,7 +170,7 @@ onMounted(() => {
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<DialogWrapper max-width="40rem" scrollable>
|
||||
<VDialog max-width="40rem" scrollable>
|
||||
<VCard>
|
||||
<VCardText>
|
||||
<VCol>
|
||||
@@ -286,5 +286,5 @@ onMounted(() => {
|
||||
</VCardText>
|
||||
<VDialogCloseBtn @click="emit('close')" />
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -156,7 +156,7 @@ async function doDelete() {
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<DialogWrapper max-width="40rem" scrollable>
|
||||
<VDialog max-width="40rem" scrollable>
|
||||
<VCard>
|
||||
<VCardText>
|
||||
<VCol>
|
||||
@@ -266,7 +266,7 @@ async function doDelete() {
|
||||
</VCardText>
|
||||
<VDialogCloseBtn @click="emit('close')" />
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -24,7 +24,7 @@ function handleImport() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper width="40rem" scrollable max-height="85vh">
|
||||
<VDialog width="40rem" scrollable max-height="85vh">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<template #prepend>
|
||||
@@ -43,5 +43,5 @@ function handleImport() {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -15,12 +15,12 @@ defineProps({
|
||||
const emit = defineEmits(['close'])
|
||||
</script>
|
||||
<template>
|
||||
<DialogWrapper max-width="50rem">
|
||||
<VDialog max-width="50rem">
|
||||
<VCard>
|
||||
<VDialogCloseBtn @click="emit('close')" />
|
||||
<VCardItem>
|
||||
<MediaInfoCard :context="context" />
|
||||
</VCardItem>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -148,7 +148,7 @@ onBeforeMount(async () => {
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<DialogWrapper scrollable max-width="60rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog scrollable max-width="60rem" :fullscreen="!display.mdAndUp.value">
|
||||
<!-- Vuetify 渲染模式 -->
|
||||
<VCard v-if="renderMode === 'vuetify'" :title="`${props.plugin?.plugin_name} - ${t('dialog.pluginConfig.title')}`">
|
||||
<VDialogCloseBtn @click="emit('close')" />
|
||||
@@ -187,5 +187,5 @@ onBeforeMount(async () => {
|
||||
|
||||
<!-- 进度框 -->
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -124,7 +124,7 @@ onMounted(() => {
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<DialogWrapper scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value">
|
||||
<!-- Vuetify 渲染模式 -->
|
||||
<VCard v-if="renderMode === 'vuetify'" :title="`${props.plugin?.plugin_name}`">
|
||||
<VDialogCloseBtn @click="emit('close')" />
|
||||
@@ -160,5 +160,5 @@ onMounted(() => {
|
||||
/>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -63,7 +63,7 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
@@ -89,5 +89,5 @@ onMounted(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -10,12 +10,12 @@ const props = defineProps({
|
||||
</script>
|
||||
<template>
|
||||
<!-- Progress Dialog -->
|
||||
<DialogWrapper :scrim="false" width="25rem">
|
||||
<VDialog :scrim="false" width="25rem">
|
||||
<VCard elevation="3" color="primary">
|
||||
<VCardText class="text-center">
|
||||
{{ props.text || t('dialog.progress.processing') }}
|
||||
<VProgressLinear color="white" class="mb-0 mt-1" :model-value="props.value" indeterminate />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -57,7 +57,7 @@ async function handleReset() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VDialogCloseBtn @click="emit('close')" />
|
||||
<VCardItem>
|
||||
@@ -99,5 +99,5 @@ async function handleReset() {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -205,7 +205,7 @@ const progressSSE = useProgressSSE(
|
||||
`${import.meta.env.VITE_API_BASE_URL}system/progress/filetransfer`,
|
||||
handleProgressMessage,
|
||||
'reorganize-progress',
|
||||
progressActive
|
||||
progressActive,
|
||||
)
|
||||
|
||||
// 使用SSE监听加载进度
|
||||
@@ -269,7 +269,7 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper scrollable max-width="45rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog scrollable max-width="45rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VCardItem class="py-2">
|
||||
<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" />
|
||||
<!-- TMDB ID搜索框 -->
|
||||
<DialogWrapper v-model="mediaSelectorDialog" width="40rem" scrollable max-height="85vh">
|
||||
<VDialog v-model="mediaSelectorDialog" width="40rem" scrollable max-height="85vh">
|
||||
<MediaIdSelector
|
||||
v-if="mediaSource === 'themoviedb'"
|
||||
v-model="transferForm.tmdbid"
|
||||
@@ -500,6 +500,6 @@ onUnmounted(() => {
|
||||
@close="mediaSelectorDialog = false"
|
||||
:type="mediaSource"
|
||||
/>
|
||||
</DialogWrapper>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -370,7 +370,7 @@ onMounted(() => {
|
||||
})
|
||||
</script>
|
||||
<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">
|
||||
<!-- 搜索输入框 -->
|
||||
<VCardItem class="pa-4 pa-sm-5 search-box-container">
|
||||
@@ -785,7 +785,7 @@ onMounted(() => {
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
|
||||
<!-- 站点选择对话框 -->
|
||||
<SearchSiteDialog
|
||||
|
||||
@@ -56,7 +56,7 @@ const filteredSites = computed(() => {
|
||||
</script>
|
||||
<template>
|
||||
<!-- Site Selection Dialog -->
|
||||
<DialogWrapper max-width="40rem" fullscreen-mobile>
|
||||
<VDialog max-width="40rem" fullscreen-mobile>
|
||||
<VCard class="site-dialog">
|
||||
<VCardItem>
|
||||
<template #prepend>
|
||||
@@ -169,7 +169,7 @@ const filteredSites = computed(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
<style scoped>
|
||||
.site-checkbox-wrapper {
|
||||
|
||||
@@ -147,7 +147,7 @@ onMounted(async () => {
|
||||
</script>
|
||||
|
||||
<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>
|
||||
<VCardItem :class="props.oper === 'add' ? 'py-3' : 'py-2'">
|
||||
<template #prepend>
|
||||
@@ -350,5 +350,5 @@ onMounted(async () => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -71,7 +71,7 @@ async function updateSiteCookie() {
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<DialogWrapper max-width="30rem" scrollable>
|
||||
<VDialog max-width="30rem" scrollable>
|
||||
<!-- Dialog Content -->
|
||||
<VCard :title="t('dialog.siteCookieUpdate.title')">
|
||||
<VDialogCloseBtn @click="emit('close')" />
|
||||
@@ -114,5 +114,5 @@ async function updateSiteCookie() {
|
||||
</VCard>
|
||||
<!-- 进度框 -->
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -222,7 +222,7 @@ watch(selectedFile, async newFile => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper scrollable max-width="50rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog scrollable max-width="50rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VCardItem class="py-2">
|
||||
<template #prepend>
|
||||
@@ -383,7 +383,7 @@ watch(selectedFile, async newFile => {
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -130,7 +130,7 @@ onMounted(() => {
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<DialogWrapper scrollable fullscreen :scrim="false" transition="dialog-bottom-transition">
|
||||
<VDialog scrollable fullscreen :scrim="false" transition="dialog-bottom-transition">
|
||||
<VCard>
|
||||
<!-- Toolbar -->
|
||||
<div>
|
||||
@@ -281,7 +281,7 @@ onMounted(() => {
|
||||
@error="addDownloadError"
|
||||
@close="addDownloadDialog = false"
|
||||
/>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -205,7 +205,7 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper max-width="50rem" :fullscreen="display.smAndDown.value" scrollable>
|
||||
<VDialog max-width="50rem" :fullscreen="display.smAndDown.value" scrollable>
|
||||
<VCard>
|
||||
<!-- 标题栏 -->
|
||||
<VCardItem>
|
||||
@@ -302,7 +302,7 @@ onMounted(() => {
|
||||
</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">
|
||||
<VCardItem class="py-3">
|
||||
<template #prepend>
|
||||
@@ -379,8 +379,8 @@ onMounted(() => {
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -287,7 +287,7 @@ onBeforeMount(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper scrollable eager max-width="80rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog scrollable eager max-width="80rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
@@ -484,5 +484,5 @@ onBeforeMount(() => {
|
||||
</VCard>
|
||||
<!-- 进度框 -->
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="t('dialog.siteUserData.refreshing')" />
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -50,7 +50,7 @@ async function saveSmbConfig() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog width="50rem" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VDialogCloseBtn @click="emit('close')" />
|
||||
<VCardItem>
|
||||
@@ -127,5 +127,5 @@ async function saveSmbConfig() {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -284,7 +284,7 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper scrollable max-width="45rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog scrollable max-width="45rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VCardItem class="py-2">
|
||||
<VDialogCloseBtn @click="emit('close')" />
|
||||
@@ -543,5 +543,5 @@ onMounted(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -85,7 +85,7 @@ onBeforeMount(() => {
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<DialogWrapper scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VCardItem class="my-2">
|
||||
<VDialogCloseBtn @click="emit('close')" />
|
||||
@@ -206,7 +206,7 @@ onBeforeMount(() => {
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -146,7 +146,7 @@ function getMediaTypeText(type: string | undefined) {
|
||||
</script>
|
||||
|
||||
<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%">
|
||||
<VCardItem>
|
||||
<VCardTitle>{{ t('dialog.subscribeHistory.title', { type: getMediaTypeText(props.type) }) }}</VCardTitle>
|
||||
@@ -220,5 +220,5 @@ function getMediaTypeText(type: string | undefined) {
|
||||
</VCard>
|
||||
<!-- 进度框 -->
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -55,7 +55,7 @@ const $toast = useToast()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper scrollable max-width="30rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog scrollable max-width="30rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VCardItem class="py-2">
|
||||
<template #prepend>
|
||||
@@ -112,5 +112,5 @@ const $toast = useToast()
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -118,7 +118,7 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper scrollable max-width="40rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog scrollable max-width="40rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<template #prepend>
|
||||
@@ -331,7 +331,7 @@ onMounted(() => {
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -154,7 +154,7 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<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%">
|
||||
<VCardItem>
|
||||
<VCardTitle>{{ t('dialog.transferQueue.title') }}</VCardTitle>
|
||||
@@ -203,5 +203,5 @@ onUnmounted(() => {
|
||||
</VWindow>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -115,7 +115,7 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper width="40rem" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog width="40rem" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VDialogCloseBtn @click="emit('close')" />
|
||||
<VCardItem>
|
||||
@@ -147,5 +147,5 @@ onUnmounted(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -366,7 +366,7 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper scrollable max-width="40rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog scrollable max-width="40rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VCardItem :class="props.oper === 'add' ? 'py-3' : 'py-2'">
|
||||
<template #prepend>
|
||||
@@ -619,5 +619,5 @@ onMounted(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -4,7 +4,6 @@ import api from '@/api'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
|
||||
// 多语言支持
|
||||
const { t } = useI18n()
|
||||
|
||||
@@ -134,7 +133,7 @@ onMounted(async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper width="40rem" scrollable>
|
||||
<VDialog width="40rem" scrollable>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
@@ -179,5 +178,5 @@ onMounted(async () => {
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -197,7 +197,7 @@ const isMacOS = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper scrollable fullscreen :scrim="false" transition="dialog-bottom-transition">
|
||||
<VDialog scrollable fullscreen :scrim="false" transition="dialog-bottom-transition">
|
||||
<VCard class="workflow-dialog">
|
||||
<!-- Toolbar -->
|
||||
<VToolbar color="primary" density="comfortable">
|
||||
@@ -256,7 +256,7 @@ const isMacOS = computed(() => {
|
||||
@close="importCodeDialog = false"
|
||||
@save="saveCodeString"
|
||||
/>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -182,7 +182,7 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<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>
|
||||
<VCardItem>
|
||||
<template #prepend>
|
||||
@@ -269,5 +269,5 @@ onMounted(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -68,7 +68,7 @@ const $toast = useToast()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogWrapper scrollable max-width="30rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VDialog scrollable max-width="30rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VCard>
|
||||
<VCardItem class="py-2">
|
||||
<template #prepend>
|
||||
@@ -132,5 +132,5 @@ const $toast = useToast()
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -749,7 +749,7 @@ onMounted(() => {
|
||||
</VCardText>
|
||||
</VCard>
|
||||
<!-- 重命名弹窗 -->
|
||||
<DialogWrapper v-if="renamePopper" v-model="renamePopper" max-width="35rem">
|
||||
<VDialog v-if="renamePopper" v-model="renamePopper" max-width="35rem">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<template #prepend>
|
||||
@@ -783,7 +783,7 @@ onMounted(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
<!-- 文件整理弹窗 -->
|
||||
<ReorganizeDialog
|
||||
v-if="transferPopper"
|
||||
|
||||
@@ -166,7 +166,7 @@ const sortIcon = computed(() => {
|
||||
<VIcon icon="mdi-arrow-up-bold-outline" />
|
||||
</IconBtn>
|
||||
<!-- 新建文件夹 -->
|
||||
<DialogWrapper v-model="newFolderPopper" max-width="35rem">
|
||||
<VDialog v-model="newFolderPopper" max-width="35rem">
|
||||
<template #activator="{ props }">
|
||||
<IconBtn>
|
||||
<VIcon v-bind="props" icon="mdi-folder-plus-outline" />
|
||||
@@ -191,6 +191,6 @@ const sortIcon = computed(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</VToolbar>
|
||||
</template>
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ import { useRoute } from 'vue-router'
|
||||
import { filterMenusByPermission } from '@/utils/permission'
|
||||
import { onUnreadMessage } from '@/utils/badge'
|
||||
import { usePullDownGesture } from '@/composables/usePullDownGesture'
|
||||
import { useScrollLockWithWatch } from '@/composables/useScrollLock'
|
||||
import { usePWA } from '@/composables/usePWA'
|
||||
import OfflinePage from '@/layouts/components/OfflinePage.vue'
|
||||
import { useGlobalOfflineStatus } from '@/composables/useOfflineStatus'
|
||||
@@ -163,17 +162,6 @@ const handleServiceWorkerMessage = (event: MessageEvent) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 使用滚动锁定 composable(自动监听showPluginQuickAccess的变化)
|
||||
useScrollLockWithWatch(showPluginQuickAccess, {
|
||||
preventTouchScroll: true,
|
||||
preserveScrollPosition: true,
|
||||
autoRestore: true,
|
||||
// 允许快速访问面板内的滚动
|
||||
allowScrollSelectors: ['.plugin-quick-access'],
|
||||
// 允许快速访问面板内的可滚动容器
|
||||
allowScrollContainerSelectors: ['.plugin-grid'],
|
||||
})
|
||||
|
||||
// 检查是否可以使用下拉手势
|
||||
const canUsePullGesture = () => {
|
||||
// 检查是否在dashboard页面
|
||||
|
||||
@@ -265,7 +265,7 @@ onMounted(() => {
|
||||
</VCard>
|
||||
</VMenu>
|
||||
<!-- 名称测试弹窗 -->
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="nameTestDialog"
|
||||
v-model="nameTestDialog"
|
||||
max-width="45rem"
|
||||
@@ -285,9 +285,9 @@ onMounted(() => {
|
||||
<NameTestView />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
<!-- 网络测试弹窗 -->
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="netTestDialog"
|
||||
v-model="netTestDialog"
|
||||
max-width="35rem"
|
||||
@@ -307,9 +307,9 @@ onMounted(() => {
|
||||
<NetTestView />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
<!-- 实时日志弹窗 -->
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="loggingDialog"
|
||||
v-model="loggingDialog"
|
||||
scrollable
|
||||
@@ -335,9 +335,9 @@ onMounted(() => {
|
||||
<LoggingView logfile="moviepilot.log" />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
<!-- 过滤规则弹窗 -->
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="ruleTestDialog"
|
||||
v-model="ruleTestDialog"
|
||||
max-width="35rem"
|
||||
@@ -357,9 +357,9 @@ onMounted(() => {
|
||||
<RuleTestView />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
<!-- 系统健康检查弹窗 -->
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="systemTestDialog"
|
||||
v-model="systemTestDialog"
|
||||
max-width="35rem"
|
||||
@@ -379,9 +379,9 @@ onMounted(() => {
|
||||
<ModuleTestView />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
<!-- 消息中心弹窗 -->
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="messageDialog"
|
||||
v-model="messageDialog"
|
||||
max-width="50rem"
|
||||
@@ -424,5 +424,5 @@ onMounted(() => {
|
||||
</div>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -650,7 +650,7 @@ onUnmounted(() => {
|
||||
<!-- 用户认证对话框 -->
|
||||
<UserAuthDialog v-if="siteAuthDialog" v-model="siteAuthDialog" @done="siteAuthDone" @close="siteAuthDialog = false" />
|
||||
<!-- 自定义 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>
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
@@ -671,10 +671,10 @@ onUnmounted(() => {
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
|
||||
<!-- 透明度调整对话框 -->
|
||||
<DialogWrapper v-if="showTransparencyDialog" v-model="showTransparencyDialog" max-width="30rem">
|
||||
<VDialog v-if="showTransparencyDialog" v-model="showTransparencyDialog" max-width="30rem">
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
@@ -763,7 +763,7 @@ onUnmounted(() => {
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -389,7 +389,7 @@ onDeactivated(() => {
|
||||
</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>
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
@@ -443,7 +443,7 @@ onDeactivated(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.settings-card-header {
|
||||
|
||||
@@ -216,7 +216,7 @@ onActivated(async () => {
|
||||
</VWindowItem>
|
||||
</VWindow>
|
||||
<!-- 弹窗,根据配置生成选项 -->
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="orderConfigDialog"
|
||||
v-model="orderConfigDialog"
|
||||
max-width="35rem"
|
||||
@@ -265,7 +265,7 @@ onActivated(async () => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
<!-- 快速滚动到顶部按钮 -->
|
||||
<Teleport to="body" v-if="route.path === '/discover'">
|
||||
<VScrollToTopBtn />
|
||||
|
||||
@@ -269,13 +269,7 @@ onActivated(async () => {
|
||||
</div>
|
||||
|
||||
<!-- 设置面板 -->
|
||||
<DialogWrapper
|
||||
v-model="dialog"
|
||||
width="35rem"
|
||||
class="settings-dialog"
|
||||
scrollable
|
||||
:fullscreen="!display.mdAndUp.value"
|
||||
>
|
||||
<VDialog v-model="dialog" width="35rem" class="settings-dialog" scrollable :fullscreen="!display.mdAndUp.value">
|
||||
<VCard class="settings-card">
|
||||
<VCardItem class="settings-card-header">
|
||||
<VCardTitle>
|
||||
@@ -327,7 +321,7 @@ onActivated(async () => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
|
||||
<!-- 快速滚动到顶部按钮 -->
|
||||
<Teleport to="body" v-if="route.path === '/recommend'">
|
||||
|
||||
@@ -6,7 +6,7 @@ declare let self: ServiceWorkerGlobalScope & {
|
||||
}
|
||||
|
||||
// 缓存版本控制
|
||||
const CACHE_VERSION = 'v1.0.7'
|
||||
const CACHE_VERSION = 'v1.0.8'
|
||||
const CACHE_NAMES = {
|
||||
appShell: `app-shell-${CACHE_VERSION}`,
|
||||
static: `static-resources-${CACHE_VERSION}`,
|
||||
|
||||
@@ -215,10 +215,7 @@ const defaultColor = '#2196F3'
|
||||
// 计算过滤表单是否全部为空
|
||||
const isFilterFormEmpty = computed(() => {
|
||||
return (
|
||||
!filterForm.name &&
|
||||
filterForm.author.length === 0 &&
|
||||
filterForm.label.length === 0 &&
|
||||
filterForm.repo.length === 0
|
||||
!filterForm.name && 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-model="SearchDialog"
|
||||
scrollable
|
||||
@@ -1611,20 +1608,20 @@ function onDragStartPlugin(evt: any) {
|
||||
</VVirtualScroll>
|
||||
</VList>
|
||||
</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">
|
||||
<VCardText class="text-center">
|
||||
{{ progressText }}
|
||||
<VProgressLinear indeterminate color="white" class="mb-0 mt-1" />
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
|
||||
<!-- 新建文件夹对话框 -->
|
||||
<DialogWrapper v-if="newFolderDialog" v-model="newFolderDialog" max-width="400">
|
||||
<VDialog v-if="newFolderDialog" v-model="newFolderDialog" max-width="400">
|
||||
<VCard>
|
||||
<VDialogCloseBtn @click="newFolderDialog = false" />
|
||||
<VCardItem>
|
||||
@@ -1646,5 +1643,5 @@ function onDragStartPlugin(evt: any) {
|
||||
}}</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -338,7 +338,7 @@ onMounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DialogWrapper v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable>
|
||||
<VDialog v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VDialogCloseBtn @click="releaseDialog = false" />
|
||||
@@ -346,7 +346,7 @@ onMounted(() => {
|
||||
</VCardItem>
|
||||
<VCardText v-html="releaseDialogBody" />
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style type="scss" scoped>
|
||||
|
||||
@@ -11,7 +11,6 @@ import { usePWA } from '@/composables/usePWA'
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
|
||||
// PWA模式检测
|
||||
const { appMode } = usePWA()
|
||||
|
||||
@@ -423,7 +422,7 @@ onMounted(() => {
|
||||
</VCard>
|
||||
|
||||
<!-- 重新识别对话框 -->
|
||||
<DialogWrapper v-model="reidentifyDialog" scrollable max-width="35rem">
|
||||
<VDialog v-model="reidentifyDialog" scrollable max-width="35rem">
|
||||
<VCard>
|
||||
<VCardItem class="py-2">
|
||||
<template #prepend>
|
||||
@@ -469,5 +468,5 @@ onMounted(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -444,7 +444,7 @@ onMounted(() => {
|
||||
: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>
|
||||
<VCardItem class="py-2">
|
||||
<template #prepend>
|
||||
@@ -472,7 +472,7 @@ onMounted(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
<style scoped>
|
||||
/* Monaco编辑器容器样式 */
|
||||
|
||||
@@ -733,7 +733,7 @@ onDeactivated(() => {
|
||||
</VRow>
|
||||
|
||||
<!-- 高级系统设置 -->
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-if="advancedDialog"
|
||||
v-model="advancedDialog"
|
||||
scrollable
|
||||
@@ -1329,5 +1329,5 @@ onDeactivated(() => {
|
||||
</VForm>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
@@ -617,7 +617,7 @@ const handleSortIconClick = () => {
|
||||
</VCard>
|
||||
|
||||
<!-- 全部筛选弹窗 -->
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-model="allFilterMenuOpen"
|
||||
max-width="50rem"
|
||||
location="center"
|
||||
@@ -690,10 +690,10 @@ const handleSortIconClick = () => {
|
||||
</div>
|
||||
</VCardText>
|
||||
</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>
|
||||
<VCardTitle class="py-3 d-flex align-center">
|
||||
<VIcon :icon="getFilterIcon(currentFilter)" class="me-2"></VIcon>
|
||||
@@ -735,7 +735,7 @@ const handleSortIconClick = () => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
|
||||
<!-- 资源列表 -->
|
||||
<VInfiniteScroll mode="intersect" side="end" :items="displayDataList" class="overflow-visible" @load="loadMore">
|
||||
|
||||
@@ -597,7 +597,7 @@ onMounted(() => {
|
||||
</VCard>
|
||||
|
||||
<!-- 全部筛选弹窗 -->
|
||||
<DialogWrapper
|
||||
<VDialog
|
||||
v-model="allFilterMenuOpen"
|
||||
max-width="50rem"
|
||||
location="center"
|
||||
@@ -670,10 +670,10 @@ onMounted(() => {
|
||||
</div>
|
||||
</VCardText>
|
||||
</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>
|
||||
<VCardTitle class="py-3 d-flex align-center">
|
||||
<VIcon :icon="getFilterIcon(currentFilter)" class="me-2"></VIcon>
|
||||
@@ -715,7 +715,7 @@ onMounted(() => {
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
|
||||
<!-- 资源列表容器 -->
|
||||
<VCard class="resource-list-container">
|
||||
|
||||
@@ -454,7 +454,7 @@ watch(
|
||||
</VRow>
|
||||
|
||||
<!-- 双重验证弹窗 -->
|
||||
<DialogWrapper v-if="otpDialog" v-model="otpDialog" max-width="45rem" scrollable>
|
||||
<VDialog v-if="otpDialog" v-model="otpDialog" max-width="45rem" scrollable>
|
||||
<!-- 开启双重验证弹窗内容 -->
|
||||
<VCard>
|
||||
<VDialogCloseBtn @click="otpDialog = false" />
|
||||
@@ -492,6 +492,6 @@ watch(
|
||||
</VForm>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</DialogWrapper>
|
||||
</VDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user