更新 Tailwind CSS 配置,添加重要性设置;在 Vite 配置中添加 PostCSS 插件;优化多个组件的 VCard 结构,移除多余的 class 属性以提升代码整洁性。

This commit is contained in:
jxxghp
2025-05-08 15:31:57 +08:00
parent e3bff71a91
commit 53a8835b6d
24 changed files with 59 additions and 47 deletions
+1 -1
View File
@@ -107,7 +107,7 @@ function onClose() {
</VCardText> </VCardText>
</VCard> </VCard>
<VDialog v-if="ruleInfoDialog" v-model="ruleInfoDialog" scrollable max-width="40rem"> <VDialog v-if="ruleInfoDialog" v-model="ruleInfoDialog" scrollable max-width="40rem">
<VCard :title="t('customRule.title', { id: props.rule.id })" class="rounded-t"> <VCard :title="t('customRule.title', { id: props.rule.id })">
<VDialogCloseBtn v-model="ruleInfoDialog" /> <VDialogCloseBtn v-model="ruleInfoDialog" />
<VDivider /> <VDivider />
<VCardText> <VCardText>
+1 -1
View File
@@ -220,7 +220,7 @@ function onClose() {
</VCardText> </VCardText>
</VCard> </VCard>
<VDialog v-if="groupInfoDialog" v-model="groupInfoDialog" scrollable max-width="80rem"> <VDialog v-if="groupInfoDialog" v-model="groupInfoDialog" scrollable max-width="80rem">
<VCard :title="`${props.group.name} - ${t('filterRule.title')}`" class="rounded-t"> <VCard :title="`${props.group.name} - ${t('filterRule.title')}`">
<VDialogCloseBtn v-model="groupInfoDialog" /> <VDialogCloseBtn v-model="groupInfoDialog" />
<VDivider /> <VDivider />
<VCardItem class="pt-1"> <VCardItem class="pt-1">
+1 -1
View File
@@ -200,7 +200,7 @@ onMounted(() => {
</VCardText> </VCardText>
</VCard> </VCard>
<VDialog v-if="mediaServerInfoDialog" v-model="mediaServerInfoDialog" scrollable max-width="40rem"> <VDialog v-if="mediaServerInfoDialog" v-model="mediaServerInfoDialog" scrollable max-width="40rem">
<VCard :title="`${props.mediaserver.name} - ${t('common.config')}`" class="rounded-t"> <VCard :title="`${props.mediaserver.name} - ${t('common.config')}`">
<VDialogCloseBtn v-model="mediaServerInfoDialog" /> <VDialogCloseBtn v-model="mediaServerInfoDialog" />
<VDivider /> <VDivider />
<VCardText> <VCardText>
@@ -135,7 +135,7 @@ function onClose() {
</VCardText> </VCardText>
</VCard> </VCard>
<VDialog v-if="notificationInfoDialog" v-model="notificationInfoDialog" scrollable max-width="40rem"> <VDialog v-if="notificationInfoDialog" v-model="notificationInfoDialog" scrollable max-width="40rem">
<VCard :title="`${props.notification.name} - ${t('notification.config')}`" class="rounded-t"> <VCard :title="`${props.notification.name} - ${t('notification.config')}`">
<VDialogCloseBtn v-model="notificationInfoDialog" /> <VDialogCloseBtn v-model="notificationInfoDialog" />
<VDivider /> <VDivider />
<VCardText> <VCardText>
+38 -22
View File
@@ -293,9 +293,7 @@ onMounted(() => {
</div> </div>
<!-- 右侧操作按钮区 --> <!-- 右侧操作按钮区 -->
<VSheet <VSheet class="site-card-actions absolute inset-y-0 right-0 z-20 flex flex-col py-2 px-1 transform duration-300">
class="site-card-actions absolute inset-y-0 right-0 z-20 flex flex-col py-2 px-1 transform translate-x-full transition-transform duration-200"
>
<!-- 测试按钮 --> <!-- 测试按钮 -->
<VBtn <VBtn
icon icon
@@ -386,12 +384,6 @@ onMounted(() => {
</template> </template>
<style scoped> <style scoped>
.site-card:hover {
.site-card-actions {
transform: translateX(0);
}
}
.site-status-indicator { .site-status-indicator {
position: absolute; position: absolute;
z-index: 1; z-index: 1;
@@ -430,15 +422,15 @@ onMounted(() => {
/* 上传下载条样式 */ /* 上传下载条样式 */
.upload-bar { .upload-bar {
animation: pulse-width 2s infinite;
background: linear-gradient(90deg, #4d79ff, #07f); background: linear-gradient(90deg, #4d79ff, #07f);
box-shadow: 0 0 4px rgba(0, 119, 255, 50%); box-shadow: 0 0 4px rgba(0, 119, 255, 50%);
animation: pulse-width 2s infinite;
} }
.download-bar { .download-bar {
animation: pulse-width 2s infinite;
background: linear-gradient(90deg, #42d392, #00b77e); background: linear-gradient(90deg, #42d392, #00b77e);
box-shadow: 0 0 4px rgba(0, 183, 126, 50%); box-shadow: 0 0 4px rgba(0, 183, 126, 50%);
animation: pulse-width 2s infinite;
} }
/* 测试状态点样式 */ /* 测试状态点样式 */
@@ -446,22 +438,22 @@ onMounted(() => {
position: absolute; position: absolute;
z-index: 1; z-index: 1;
border-radius: 50%; border-radius: 50%;
block-size: 70%;
content: ''; content: '';
height: 70%; inline-size: 70%;
width: 70%; inset-block-start: 15%;
top: 15%; inset-inline-start: 15%;
left: 15%;
} }
.pulse-dot::after { .pulse-dot::after {
position: absolute; position: absolute;
z-index: 2; z-index: 2;
border-radius: 50%; border-radius: 50%;
block-size: 100%;
content: ''; content: '';
height: 100%; inline-size: 100%;
width: 100%; inset-block-start: 0;
top: 0; inset-inline-start: 0;
left: 0;
} }
.pulse-dot.error::before { .pulse-dot.error::before {
@@ -508,11 +500,11 @@ onMounted(() => {
.spinner-circle { .spinner-circle {
position: absolute; position: absolute;
border: 1px solid rgba(var(--v-theme-primary), 0.2); border: 1px solid rgba(var(--v-theme-primary), 0.2);
border-top-color: rgba(var(--v-theme-primary), 1);
border-radius: 50%; border-radius: 50%;
width: 100%;
height: 100%;
animation: spin 0.8s linear infinite; animation: spin 0.8s linear infinite;
block-size: 100%;
border-block-start-color: rgba(var(--v-theme-primary), 1);
inline-size: 100%;
} }
/* 动画关键帧 */ /* 动画关键帧 */
@@ -522,6 +514,7 @@ onMounted(() => {
opacity: 0.85; opacity: 0.85;
transform: scaleX(0.95); transform: scaleX(0.95);
} }
50% { 50% {
opacity: 1; opacity: 1;
transform: scaleX(1.05); transform: scaleX(1.05);
@@ -532,9 +525,11 @@ onMounted(() => {
0% { 0% {
box-shadow: 0 0 0 0 rgba(var(--v-theme-error), 0.6); box-shadow: 0 0 0 0 rgba(var(--v-theme-error), 0.6);
} }
70% { 70% {
box-shadow: 0 0 0 10px rgba(var(--v-theme-error), 0); box-shadow: 0 0 0 10px rgba(var(--v-theme-error), 0);
} }
100% { 100% {
box-shadow: 0 0 0 0 rgba(var(--v-theme-error), 0); box-shadow: 0 0 0 0 rgba(var(--v-theme-error), 0);
} }
@@ -544,9 +539,11 @@ onMounted(() => {
0% { 0% {
box-shadow: 0 0 0 0 rgba(var(--v-theme-warning), 0.6); box-shadow: 0 0 0 0 rgba(var(--v-theme-warning), 0.6);
} }
70% { 70% {
box-shadow: 0 0 0 10px rgba(var(--v-theme-warning), 0); box-shadow: 0 0 0 10px rgba(var(--v-theme-warning), 0);
} }
100% { 100% {
box-shadow: 0 0 0 0 rgba(var(--v-theme-warning), 0); box-shadow: 0 0 0 0 rgba(var(--v-theme-warning), 0);
} }
@@ -556,9 +553,11 @@ onMounted(() => {
0% { 0% {
box-shadow: 0 0 0 0 rgba(var(--v-theme-success), 0.6); box-shadow: 0 0 0 0 rgba(var(--v-theme-success), 0.6);
} }
70% { 70% {
box-shadow: 0 0 0 10px rgba(var(--v-theme-success), 0); box-shadow: 0 0 0 10px rgba(var(--v-theme-success), 0);
} }
100% { 100% {
box-shadow: 0 0 0 0 rgba(var(--v-theme-success), 0); box-shadow: 0 0 0 0 rgba(var(--v-theme-success), 0);
} }
@@ -568,9 +567,11 @@ onMounted(() => {
0% { 0% {
box-shadow: 0 0 0 0 rgba(var(--v-theme-secondary), 0.6); box-shadow: 0 0 0 0 rgba(var(--v-theme-secondary), 0.6);
} }
70% { 70% {
box-shadow: 0 0 0 10px rgba(var(--v-theme-secondary), 0); box-shadow: 0 0 0 10px rgba(var(--v-theme-secondary), 0);
} }
100% { 100% {
box-shadow: 0 0 0 0 rgba(var(--v-theme-secondary), 0); box-shadow: 0 0 0 0 rgba(var(--v-theme-secondary), 0);
} }
@@ -580,6 +581,7 @@ onMounted(() => {
0% { 0% {
transform: rotate(0deg); transform: rotate(0deg);
} }
100% { 100% {
transform: rotate(360deg); transform: rotate(360deg);
} }
@@ -589,8 +591,22 @@ onMounted(() => {
from { from {
opacity: 0; opacity: 0;
} }
to { to {
opacity: 1; opacity: 1;
} }
} }
.site-card-actions {
opacity: 0;
transform: translateX(100%);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
visibility: hidden;
}
.site-card:hover .site-card-actions {
opacity: 1;
transform: translateX(0);
visibility: visible;
}
</style> </style>
+1 -1
View File
@@ -34,7 +34,7 @@ async function savaAlistConfig() {
<template> <template>
<VDialog width="50rem" scrollable max-height="85vh"> <VDialog width="50rem" scrollable max-height="85vh">
<VCard :title="t('dialog.alistConfig.title')" class="rounded-t"> <VCard :title="t('dialog.alistConfig.title')">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VCardText> <VCardText>
<VRow> <VRow>
+1 -1
View File
@@ -89,7 +89,7 @@ onUnmounted(() => {
<template> <template>
<VDialog width="40rem" scrollable max-height="85vh"> <VDialog width="40rem" scrollable max-height="85vh">
<VCard :title="t('dialog.aliyunAuth.loginTitle')" class="rounded-t"> <VCard :title="t('dialog.aliyunAuth.loginTitle')">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VCardText class="pt-2 flex flex-col items-center"> <VCardText class="pt-2 flex flex-col items-center">
<div class="my-6 rounded text-center p-3 border"> <div class="my-6 rounded text-center p-3 border">
+1 -1
View File
@@ -25,7 +25,7 @@ function handleImport() {
<template> <template>
<VDialog width="40rem" scrollable max-height="85vh"> <VDialog width="40rem" scrollable max-height="85vh">
<VCard :title="props.title" class="rounded-t"> <VCard :title="props.title">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VCardText class="pt-2"> <VCardText class="pt-2">
<VTextarea v-model="codeString" /> <VTextarea v-model="codeString" />
+1 -5
View File
@@ -150,11 +150,7 @@ onBeforeMount(async () => {
<template> <template>
<VDialog scrollable max-width="60rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="60rem" :fullscreen="!display.mdAndUp.value">
<!-- Vuetify 渲染模式 --> <!-- Vuetify 渲染模式 -->
<VCard <VCard v-if="renderMode === 'vuetify'" :title="`${props.plugin?.plugin_name} - ${t('dialog.pluginConfig.title')}`">
v-if="renderMode === 'vuetify'"
:title="`${props.plugin?.plugin_name} - ${t('dialog.pluginConfig.title')}`"
class="rounded-t"
>
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VDivider /> <VDivider />
<LoadingBanner v-if="!isRefreshed" class="mt-5" /> <LoadingBanner v-if="!isRefreshed" class="mt-5" />
+1 -1
View File
@@ -120,7 +120,7 @@ onMounted(() => {
<template> <template>
<VDialog 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}`" class="rounded-t"> <VCard v-if="renderMode === 'vuetify'" :title="`${props.plugin?.plugin_name}`">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<LoadingBanner v-if="!isRefreshed" class="mt-5" /> <LoadingBanner v-if="!isRefreshed" class="mt-5" />
<VCardText v-else class="min-h-40"> <VCardText v-else class="min-h-40">
@@ -45,7 +45,7 @@ onMounted(() => {
<template> <template>
<VDialog width="50rem" scrollable max-height="85vh"> <VDialog width="50rem" scrollable max-height="85vh">
<VCard class="rounded-t"> <VCard>
<VCardItem> <VCardItem>
<VCardTitle> <VCardTitle>
<VIcon icon="mdi-store-cog" class="me-2" /> <VIcon icon="mdi-store-cog" class="me-2" />
+1 -1
View File
@@ -42,7 +42,7 @@ async function savaRcloneConfig() {
<template> <template>
<VDialog width="50rem" scrollable max-height="85vh"> <VDialog width="50rem" scrollable max-height="85vh">
<VCard :title="t('dialog.rcloneConfig.title')" class="rounded-t"> <VCard :title="t('dialog.rcloneConfig.title')">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VCardText> <VCardText>
<VRow> <VRow>
+1 -1
View File
@@ -250,7 +250,7 @@ onUnmounted(() => {
<template> <template>
<VDialog scrollable max-width="45rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="45rem" :fullscreen="!display.mdAndUp.value">
<VCard :title="dialogTitle" class="rounded-t"> <VCard :title="dialogTitle">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VDivider /> <VDivider />
<VCardText> <VCardText>
@@ -152,7 +152,6 @@ onMounted(async () => {
:title="`${props.oper === 'add' ? t('site.actions.add') : t('site.actions.edit')}${t('site.title')}${ :title="`${props.oper === 'add' ? t('site.actions.add') : t('site.actions.edit')}${t('site.title')}${
props.oper !== 'add' ? ` - ${siteForm.name}` : '' props.oper !== 'add' ? ` - ${siteForm.name}` : ''
}`" }`"
class="rounded-t"
> >
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VDivider /> <VDivider />
+1 -1
View File
@@ -283,7 +283,7 @@ onBeforeMount(async () => {
<template> <template>
<VDialog scrollable eager max-width="80rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable eager max-width="80rem" :fullscreen="!display.mdAndUp.value">
<VCard class="rounded-t"> <VCard>
<VCardItem> <VCardItem>
<VCardTitle <VCardTitle
>{{ t('dialog.siteUserData.title') }} - {{ props.site?.name }} >{{ t('dialog.siteUserData.title') }} - {{ props.site?.name }}
@@ -292,7 +292,6 @@ onMounted(() => {
: '', : '',
}) })
" "
class="rounded-t"
> >
<VCardText> <VCardText>
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
@@ -80,7 +80,7 @@ onBeforeMount(() => {
</script> </script>
<template> <template>
<VDialog scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value"> <VDialog scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value">
<VCard class="rounded-t"> <VCard>
<VCardItem class="my-2"> <VCardItem class="my-2">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
</VCardItem> </VCardItem>
@@ -60,7 +60,6 @@ const $toast = useToast()
:title="`${t('dialog.subscribeShare.shareSubscription')} - ${props.sub?.name} ${ :title="`${t('dialog.subscribeShare.shareSubscription')} - ${props.sub?.name} ${
props.sub?.season ? t('dialog.subscribeShare.season', { number: props.sub?.season }) : '' props.sub?.season ? t('dialog.subscribeShare.season', { number: props.sub?.season }) : ''
}`" }`"
class="rounded-t"
> >
<VCardText> <VCardText>
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
+1 -1
View File
@@ -96,7 +96,7 @@ onUnmounted(() => {
<template> <template>
<VDialog width="40rem" scrollable max-height="85vh"> <VDialog width="40rem" scrollable max-height="85vh">
<VCard :title="t('dialog.u115Auth.loginTitle')" class="rounded-t"> <VCard :title="t('dialog.u115Auth.loginTitle')">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VCardText class="pt-2 flex flex-col items-center"> <VCardText class="pt-2 flex flex-col items-center">
<div class="my-6 rounded text-center p-3 border"> <div class="my-6 rounded text-center p-3 border">
@@ -295,7 +295,6 @@ onMounted(() => {
:title="`${props.oper === 'add' ? t('dialog.userAddEdit.add') : t('dialog.userAddEdit.edit')}${ :title="`${props.oper === 'add' ? t('dialog.userAddEdit.add') : t('dialog.userAddEdit.edit')}${
props.oper !== 'add' ? ` - ${userName}` : '' props.oper !== 'add' ? ` - ${userName}` : ''
}`" }`"
class="rounded-t"
> >
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VDivider /> <VDivider />
+1 -1
View File
@@ -134,7 +134,7 @@ onMounted(async () => {
<template> <template>
<VDialog width="40rem" max-height="85vh"> <VDialog width="40rem" max-height="85vh">
<VCard :title="t('dialog.userAuth.title')" class="rounded-t"> <VCard :title="t('dialog.userAuth.title')">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VCardText> <VCardText>
<VRow> <VRow>
@@ -86,7 +86,7 @@ async function editWorkflow() {
<template> <template>
<VDialog 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 :title="title" class="rounded-t"> <VCard :title="title">
<VDialogCloseBtn @click="emit('close')" /> <VDialogCloseBtn @click="emit('close')" />
<VDivider /> <VDivider />
<VCardText> <VCardText>
+1
View File
@@ -1,6 +1,7 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
important: true,
theme: { theme: {
extend: {}, extend: {},
}, },
+3
View File
@@ -200,5 +200,8 @@ export default defineConfig({
quietDeps: true, quietDeps: true,
}, },
}, },
postcss: {
plugins: [require('tailwindcss'), require('autoprefixer')],
},
}, },
}) })