feat: 添加NProgress加载进度条和优化UI样式

添加NProgress依赖并集成到路由中,实现页面切换时的加载进度条
优化友链页面、博客分类和文章列表的UI样式
调整登录按钮和图片懒加载的显示效果
新增标签随机颜色功能,提升视觉体验
This commit is contained in:
2026-01-15 17:17:40 +08:00
parent d00c18d38a
commit ac4f8dac82
17 changed files with 204 additions and 73 deletions
+48 -18
View File
@@ -4,7 +4,7 @@
<n-card class="card w-100 shadow">
<template #header>
<div class="flex items-center gap-4 text-primary text-xl font-bold">
<icon-loading class="zhuan text-primary w-6 h-6" />
<icon-loading class="zhuan text-primary w-6 h-6" />
申请友链
</div>
</template>
@@ -54,8 +54,8 @@
站点介绍
</div>
</template>
<n-input type="textarea" :autosize="{ minRows: 2, maxRows: 3 }" maxlength="50" v-model:value="plinkData.desc"
placeholder="请用一句话简短的描述你的站点" />
<n-input type="textarea" :autosize="{ minRows: 2, maxRows: 3 }" maxlength="50"
v-model:value="plinkData.desc" placeholder="请用一句话简短的描述你的站点" />
</n-form-item>
<n-form-item path="tagname">
<template #label>
@@ -64,8 +64,8 @@
标签
</div>
</template>
<n-input type="textarea" :autosize="{ minRows: 2, maxRows: 3 }" maxlength="50" v-model:value="plinkData.tagname"
placeholder="输入你的标签,用逗号隔开,注意每个标签最多3个字符,且只显示前3个标签哦~" />
<n-input type="textarea" :autosize="{ minRows: 2, maxRows: 3 }" maxlength="50"
v-model:value="plinkData.tagname" placeholder="输入你的标签,用逗号隔开,注意每个标签最多3个字符,且只显示前3个标签哦~" />
</n-form-item>
<n-form-item>
<n-button class="w-full" type="primary" @click="submitPut">申请友链</n-button>
@@ -83,13 +83,16 @@
<div class="ava">
<n-avatar round size="large" :src="p.avater"></n-avatar>
</div>
<div class="text-primary">
<em class="bg-[#fbf2e3] px-4 rounded-full text-sm text-primary mb-4">{{ p.name }}</em>
<div class="font-bold text-xl text-gray-700 mb-1">
{{ p.title }}
</div>
<em class="text-gray-400 text-sm">{{ p.name }}</em>
<div class="flex gap-1 truncate">
<div v-for="i in getTags(p.tagname)" :key="i.tid" class="flex items-center gap-1 text-deepp text-sm">
<icon-tag2 class="w-3 h-3 !text-deepp" />{{ i }}
<div class="flex gap-1 truncate mb-1 text-sm">
<div v-for="i in getTags(p.tagname)" :key="i.tid"
:style="{ backgroundColor: getDictValue(tagColorList, 'tag', i, 'color') }"
class="flex items-center gap-1 cursor-pointer text-sm text-white rounded-full px-3">
<icon-tag2 class="w-3 h-3 " />{{ i }}
</div>
</div>
<div class="truncate w-full text-gray-400 text-sm text-center">
@@ -108,7 +111,7 @@ import siteIcon from '@/icon/plink/site.svg';
import tagIcon from '@/icon/plink/tag.svg';
import urlIcon from '@/icon/plink/uri.svg';
import userIcon from '@/icon/plink/user.svg';
import { getDictValue } from '@/util';
definePage({
name: 'plink',
@@ -137,18 +140,32 @@ const rules: any = {
}
const pList = ref<any>([])
const formRef = ref<any>(null)
const tagColorList: any = ref([])
async function getPlinkList() {
const res = await $http.plink.getPlinkList()
const list: Array<string> = []
// 对res.data.tags进行去重
res.data.forEach((i: any) => {
const t = getTags(i.tagname)
t.forEach((ii: string) => {
if (!list.includes(ii)) list.push(ii)
})
});
tagColorList.value = list.map((i: string) => {
return {
tag: i,
color: getRandomFromPalette()
}
})
pList.value = res.data
// for (let i = 0; i < 20; i++) {
// pList.value.push(res.data[0])
// }
}
function getTags(str: any) {
str = str.replaceAll('', ',')
let tags = str.split(',').slice(0, 3)
tags.forEach((tag: any, idx: number) => {
tags[idx] = tag.trim().slice(0, 3)
tags[idx] = tag.trim().slice(0, 4)
});
return tags
}
@@ -178,7 +195,23 @@ function submitPut() {
})
}
// 生成一个随机的鲜艳颜色,和白色能对比
function getRandomFromPalette(): string {
const hue = Math.floor(Math.random() * 360);
return hslToHex(hue, 80, 50);
}
function hslToHex(h: number, s: number, l: number): any {
l /= 100;
const a = s * Math.min(l, 1 - l) / 100;
const f = (n: number) => {
const k = (n + h / 30) % 12;
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return Math.round(255 * color).toString(16).padStart(2, '0');
}
return `#${f(0)}${f(8)}${f(4)}`;
}
onMounted(() => {
boxStyle.value = {
height: window.innerHeight - nav.navH - 1 + 'px',
@@ -197,11 +230,8 @@ onMounted(() => {
100% {
transform: rotate(360deg);
}
}
.zhuan {
animation: spin 1.5s linear infinite;
}