Feature(custom): migrate all pages to tailwind

This commit is contained in:
Kuingsmile
2026-01-25 16:04:32 +08:00
parent d0853cca1f
commit 88a5a8087a
15 changed files with 462 additions and 1942 deletions

View File

@@ -25,6 +25,7 @@
- 优化相册页面卡片样式,边界更清晰,提升选择框视觉效果。
- 优化多个页面在窄屏下的显示,避免内容溢出。
- 文件浏览侧边栏名称超出宽度时支持滚动显示完整名称。
- 优化了视频播放页面的显示效果。
- 相册页面支持显示已选数量、匹配的 URL 列表和记忆过滤器状态。
- 支持浏览完整插件列表、查看详情及一键安装。
- 新增新手引导页面,首次运行自动弹出。
@@ -38,6 +39,7 @@
- 修复了管理页面中排序下拉框显示异常的问题。
- 修复了管理页面图床列表未正确高亮当前选中项的问题。
- 修复了管理页面markdown预览内容没有正确渲染的问题。
- 修复了暗色模式下任务页面的显示异常。
- 修复了图床设置页面“设置为默认图床”按钮状态更新不及时的问题。
- 修复了预处理设置页面中,图床水印独立设置按钮状态不同步的问题。

View File

@@ -29,3 +29,4 @@
@utility no-drag-region {
-webkit-app-region: none;
}

View File

@@ -175,7 +175,6 @@ function validateForm(): boolean {
}
function clearFieldError(fieldName: string) {
console.log('Clearing error for field:', fieldName)
if (validationErrors[fieldName]) {
delete validationErrors[fieldName]
}

View File

@@ -6,16 +6,14 @@
<span v-if="required" class="ml-1 text-danger">*</span>
</label>
<slot name="title-extra"></slot>
<div v-if="tips" class="relative">
<div v-if="tips" class="group relative inline-block">
<div
class="flex h-[20px] w-[20px] cursor-pointer items-center justify-center rounded-full p-[2px] text-secondary hover:bg-bg-secondary hover:text-accent"
@click="toggleTooltip()"
>
<Info :size="16" />
</div>
<div
v-show="visibleTooltips"
class="absolute top-full left-0 z-1000 max-w-[300px] min-w-[200px] rounded-md border border-border bg-bg-secondary p-3 text-xs leading-[1.4] text-main shadow-lg max-md:max-w-[250px] max-md:min-w-[150px]"
class="invisible absolute top-[125%] left-1/2 z-1000 w-max max-w-[200px] translate-x-[-50%] rounded-md border border-border bg-bg-tertiary p-2 text-center text-xs text-main opacity-0 shadow-md transition-opacity duration-300 group-hover:visible group-hover:opacity-100"
v-html="transformMarkdownToHTML(tips)"
/>
</div>
@@ -62,7 +60,6 @@ const [modelValue, modifiers] = defineModel<any>({
})
const type = ref('text')
const visibleTooltips = ref(false)
const {
isPassword = false,
@@ -80,10 +77,6 @@ const {
tips?: string
}>()
function toggleTooltip() {
visibleTooltips.value = !visibleTooltips.value
}
function transformMarkdownToHTML(markdown: string) {
try {
return marked.parse(markdown)

View File

@@ -29,16 +29,14 @@
</div>
</label>
<slot name="title-extra"></slot>
<div v-if="tips" class="relative">
<div v-if="tips" class="group relative inline-block">
<div
class="flex h-[20px] w-[20px] cursor-pointer items-center justify-center rounded-full p-[2px] text-secondary hover:bg-bg-secondary hover:text-accent"
@click="toggleTooltip()"
>
<Info :size="16" />
</div>
<div
v-show="visibleTooltips"
class="absolute top-full left-0 z-1000 max-w-[300px] min-w-[200px] rounded-md border border-border bg-bg-secondary p-3 text-xs leading-[1.4] text-main shadow-lg max-md:max-w-[250px] max-md:min-w-[150px]"
class="invisible absolute top-[125%] left-1/2 z-1000 w-max max-w-[200px] translate-x-[-50%] rounded-md border border-border bg-bg-tertiary p-2 text-center text-xs text-main opacity-0 shadow-md transition-opacity duration-300 group-hover:visible group-hover:opacity-100"
v-html="transformMarkdownToHTML(tips)"
/>
</div>
@@ -48,12 +46,10 @@
<script lang="ts" setup>
import { Info } from 'lucide-vue-next'
import { marked } from 'marked'
import { onMounted, ref } from 'vue'
import { onMounted } from 'vue'
const emit = defineEmits(['change'])
const visibleTooltips = ref(false)
const modelValue = defineModel<boolean>()
const {
title = '',
@@ -75,10 +71,6 @@ const {
tighter?: boolean
}>()
function toggleTooltip() {
visibleTooltips.value = !visibleTooltips.value
}
function transformMarkdownToHTML(markdown: string) {
try {
return marked.parse(markdown)

View File

@@ -8,7 +8,7 @@
}
html {
@apply m-0 h-full p-0 w-full bg-transparent;
@apply m-0 h-full w-full bg-transparent p-0;
}
#app {
@@ -180,14 +180,14 @@
}
@keyframes slide-right {
from {
transform: translateX(100%);
opacity: 0;
}
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
to {
transform: translateX(0);
opacity: 1;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -40,16 +40,16 @@
>
<div class="flex h-full w-full">
<div
class="flex min-h-0 max-w-[400px] min-w-[40px] flex-col border-r-2 border-r-border transition-all duration-100 ease-out"
class="flex min-h-0 w-[40px] max-w-[400px] min-w-[40px] flex-col border-r-2 border-r-border transition-all duration-100 ease-out"
:style="{ width: sidebarWidth + 'px' }"
>
<div class="shrink-0 border-b-2 border-b-border-secondary p-2">
<div v-if="menuTitleMap[currentPicBedName]" class="shrink-0 border-b-2 border-b-border-secondary p-2">
<h3 class="m-0 text-center text-sm font-semibold text-secondary">
{{ menuTitleMap[currentPicBedName] }}
</h3>
</div>
<div class="min-h-0 flex-1 overflow-y-auto p-2">
<div class="min-h-0 flex-1 overflow-y-auto">
<div v-if="isLoadingBucketList" class="flex flex-col items-center justify-center gap-2 p-8">
<div
class="h-[25px] w-[25px] animate-spin rounded-full border-3 border-t-2 border-border border-t-accent"
@@ -287,7 +287,7 @@ const configMap = ref<any>(null)
const currentAlias = ref(route.query.alias as string)
const currentPicBedName = ref(route.query.picBedName as string)
const sidebarWidth = ref(160)
const sidebarWidth = ref(120)
const isResizing = ref(false)
let allPicBedConfigure = JSON.parse(route.query.allPicBedConfigure as string)

File diff suppressed because it is too large Load Diff

View File

@@ -242,12 +242,12 @@
</div>
</div>
<div class="flex shrink-0 flex-col justify-between">
<div class="flex min-w-0 shrink-0 flex-col justify-between">
<div
class="mb-1.5 overflow-hidden text-sm font-medium text-ellipsis whitespace-nowrap text-main"
class="mb-1.5 w-full truncate text-center text-sm font-medium text-main"
:title="(item.fileName || '').toString().length > 30 ? item.fileName || '' : ''"
>
<div class="text-center">{{ formatFileName(item.fileName || '') }}</div>
{{ formatFileName(item.fileName || '') }}
</div>
<div class="mr-2 flex items-center justify-between">

View File

@@ -5,7 +5,7 @@
:class="[osGlobal === 'linux' ? 'rounded-none bg-size-[100vh_100vw]' : 'rounded-full bg-size-[90vh_90vw]']"
>
<div
id="upload-area"
ref="uploadArea"
class="h-full w-full transition-all duration-200 ease-in-out"
:class="{
'bg-[rgba(0,0,0,0.3)]': dragover,
@@ -35,11 +35,12 @@
<script lang="ts" setup>
import type { IConfig } from 'piclist'
import { onBeforeMount, onBeforeUnmount, ref, watch } from 'vue'
import { onBeforeMount, onBeforeUnmount, ref, useTemplateRef, watch } from 'vue'
import { osGlobal } from '@/hooks/useGlobal'
import { isUrl } from '@/utils/common'
import { getConfig } from '@/utils/dataSender'
import { useDragEventListeners } from '@/utils/drag'
import { IRPCActionType } from '@/utils/enum'
const logoPath = ref('')
@@ -51,6 +52,9 @@ const wX = ref(-1)
const wY = ref(-1)
const screenX = ref(-1)
const screenY = ref(-1)
const uploadArea = useTemplateRef<HTMLDivElement>('uploadArea')
useDragEventListeners(uploadArea)
let removeListeners: () => void = () => {}

View File

@@ -135,7 +135,7 @@
small
no-border
:title="t('pages.settings.system.isHideDock')"
@change="handleHideDockChange(formOfSetting.isHideDock)"
@change="handleHideDockChange"
/>
</SettingCard>
@@ -163,7 +163,7 @@
small
no-border
:title="t('pages.settings.system.miniWindowOnTop')"
@click="handleMiniWindowOntop(formOfSetting.miniWindowOntop)"
@change="handleMiniWindowOntop"
/>
</SettingCard>
@@ -197,7 +197,7 @@
no-border
:title="t('pages.settings.system.autoLaunch')"
:description="t('pages.settings.system.autoLaunchDesc')"
@change="handleAutoStartChange(formOfSetting.autoStart)"
@change="handleAutoStartChange"
/>
</SettingCard>
<CustomNavCard

View File

@@ -111,6 +111,7 @@
>
<div
id="upload-area"
ref="uploadArea"
class="group/upload relative flex h-full w-full cursor-pointer items-center justify-center rounded-xl border-2 border-dashed border-border bg-bg-secondary px-1 py-12 duration-medium ease-standard focus-visible:focus-ring focus-visible:outline-offset-4 max-md:px-4 max-md:py-8 max-xs:px-2 max-xs:py-6 [:hover,.drag-active]:border-accent [:hover,.drag-active]:bg-[linear-gradient(135deg,var(--color-surface-elevated)_0%,color-mix(in_srgb,var(--color-accent),transparent_95%)_100%)] [:hover,.drag-active]:shadow-lg [:hover,.drag-active&]:-translate-y-[2px]"
:class="{ 'drag-active': dragover }"
@drop.prevent="onDrop"
@@ -736,7 +737,8 @@ interface IUploadTaskQueueStatus {
}
}
useDragEventListeners()
const uploadArea = useTemplateRef('uploadArea')
useDragEventListeners(uploadArea)
const $router = useRouter()
const { t } = useI18n()
const message = useMessage()

View File

@@ -1,23 +1,26 @@
import { onBeforeUnmount, onMounted } from 'vue'
import { onBeforeUnmount, onMounted, type Ref } from 'vue'
function disableDrag(e: DragEvent) {
const dropzone = document.getElementById('upload-area')
if (dropzone === null || !dropzone.contains(e.target as Node)) {
e.preventDefault()
e.dataTransfer!.effectAllowed = 'none'
e.dataTransfer!.dropEffect = 'none'
export function useDragEventListeners(dropZoneRef: Ref<HTMLElement | null>) {
function disableDrag(e: DragEvent) {
const dropzone = dropZoneRef.value
if (!dropzone || !dropzone.contains(e.target as Node)) {
e.preventDefault()
if (e.dataTransfer) {
e.dataTransfer.effectAllowed = 'none'
e.dataTransfer.dropEffect = 'none'
}
}
}
}
export function useDragEventListeners() {
onMounted(() => {
window.addEventListener('dragenter', disableDrag, false)
window.addEventListener('dragover', disableDrag)
window.addEventListener('drop', disableDrag)
window.addEventListener('dragover', disableDrag, false)
window.addEventListener('drop', disableDrag, false)
})
onBeforeUnmount(() => {
window.removeEventListener('dragenter', disableDrag, false)
window.removeEventListener('dragover', disableDrag)
window.removeEventListener('drop', disableDrag)
window.removeEventListener('dragover', disableDrag, false)
window.removeEventListener('drop', disableDrag, false)
})
}

View File

@@ -42,7 +42,6 @@
| .amv | AMV视频文件 | .mpg | MPEG视频文件 |
| .avi | AVI视频文件 | .mts | AVCHD视频文件 |
| .flac | FLAC音频文件 | .ogg | Ogg Vorbis音频文件 |
| .flv | Flash视频文件 | .ogv | Ogg Theora视频文件 |
| .m2ts | M2TS视频文件 | .vob | DVD视频文件 |
| .m4a | MPEG-4音频文件 | .wav | WAV音频文件 |
| .m4v | MPEG-4视频文件 | .webm | WebM视频文件 |