feat: 实现友链页面功能并优化其他页面
添加友链页面表单和展示功能,包括申请友链和显示友链列表 优化首页搜索框自动聚焦和画廊页面图片样式 修复博客列表分页器显示条件
This commit is contained in:
+181
-8
@@ -1,19 +1,190 @@
|
||||
<template>
|
||||
<div class="plink-page">
|
||||
<h1>友链页</h1>
|
||||
<!-- 友链内容 -->
|
||||
<icon-loading class="zhuan text-primary w-12 h-12" />
|
||||
<div class="plink-page pt-4 flex justify-between" :style="boxStyle">
|
||||
<div class="left ml-4 ">
|
||||
<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" />
|
||||
申请友链
|
||||
</div>
|
||||
</template>
|
||||
<div>
|
||||
<n-form :model="plinkData" ref="formRef" :rules="rules" label-width="80" :inline="false"
|
||||
feedback-style="font-size: 12px">
|
||||
<n-form-item path="name">
|
||||
<template #label>
|
||||
<div class="flex items-center gap-1 text-sm text-gray-500">
|
||||
<user-icon></user-icon>
|
||||
昵称
|
||||
</div>
|
||||
</template>
|
||||
<n-input v-model:value="plinkData.name" placeholder="请输入你的昵称" />
|
||||
</n-form-item>
|
||||
<n-form-item path="title">
|
||||
<template #label>
|
||||
<div class="flex items-center gap-1 text-sm text-gray-500">
|
||||
<site-icon></site-icon>
|
||||
网站名称
|
||||
</div>
|
||||
</template>
|
||||
<n-input v-model:value="plinkData.title" placeholder="请输入你的网站名称" />
|
||||
</n-form-item>
|
||||
<n-form-item path="url">
|
||||
<template #label>
|
||||
<div class="flex items-center gap-1 text-sm text-gray-500">
|
||||
<url-icon></url-icon>
|
||||
站点地址
|
||||
</div>
|
||||
</template>
|
||||
<n-input v-model:value="plinkData.url" placeholder="请输入你的网站地址" />
|
||||
</n-form-item>
|
||||
<n-form-item path="avater">
|
||||
<template #label>
|
||||
<div class="flex items-center gap-1 text-sm text-gray-500">
|
||||
<ava-icon></ava-icon>
|
||||
头像链接
|
||||
</div>
|
||||
</template>
|
||||
<n-input v-model:value="plinkData.avater" placeholder="请输入你的头像链接" />
|
||||
</n-form-item>
|
||||
<n-form-item path="desc">
|
||||
<template #label>
|
||||
<div class="flex items-center gap-1 text-sm text-gray-500">
|
||||
<desc-icon></desc-icon>
|
||||
站点介绍
|
||||
</div>
|
||||
</template>
|
||||
<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>
|
||||
<div class="flex items-center gap-1 text-sm text-gray-500">
|
||||
<tag-icon></tag-icon>
|
||||
标签
|
||||
</div>
|
||||
</template>
|
||||
<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>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</div>
|
||||
</n-card>
|
||||
<div class="mt-4 text-right text-primary text-sm font-italic">申请完不显示是因为需要审核奥~~</div>
|
||||
</div>
|
||||
<n-scrollbar class="h-full">
|
||||
<div class="right h-full grid grid-cols-3 gap-5 flex-1 px-12">
|
||||
<div
|
||||
class="rounded-lg bg-white shadow flex flex-col items-center justify-center p-4 cursor-pointer transition-transform duration-300 box-border hover:-translate-y-1.5"
|
||||
v-for="p in pList" :key="p.pid" @click="gotoWebsite(p.url)">
|
||||
<div class="ava">
|
||||
<n-avatar round size="large" :src="p.avater"></n-avatar>
|
||||
</div>
|
||||
<div class="text-primary">
|
||||
{{ 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>
|
||||
</div>
|
||||
<div class="truncate w-full text-gray-400 text-sm text-center">
|
||||
{{ p.desc }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</n-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import avaIcon from '@/icon/plink/ava.svg';
|
||||
import descIcon from '@/icon/plink/desc.svg';
|
||||
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';
|
||||
|
||||
|
||||
definePage({
|
||||
name:'plink',
|
||||
name: 'plink',
|
||||
meta: {
|
||||
title: '友链',
|
||||
}
|
||||
})
|
||||
// 友链页逻辑
|
||||
const boxStyle: any = ref({})
|
||||
const nav: any = $store.nav.useNavStore()
|
||||
const plinkData = reactive<any>({
|
||||
name: '',
|
||||
title: '',
|
||||
avater: '',
|
||||
url: '',
|
||||
desc: '',
|
||||
tagname: '',
|
||||
});
|
||||
const rules: any = {
|
||||
name: [{ required: true, message: '昵称不能为空~~', trigger: ['blur'] }],
|
||||
title: [{ required: true, message: '网站名称不能为空~~', trigger: ['blur'] }],
|
||||
url: [{ required: true, message: '站点地址不能为空~~', trigger: ['blur'] }],
|
||||
avater: [{ required: true, message: '头像链接不能为空~~', trigger: ['blur'] }],
|
||||
desc: [{ required: true, message: '站点介绍不能为空~~', trigger: ['blur'] }],
|
||||
tagname: [{ required: true, message: '标签不能为空~~', trigger: ['blur'] }],
|
||||
}
|
||||
const pList = ref<any>([])
|
||||
const formRef = ref<any>(null)
|
||||
async function getPlinkList() {
|
||||
const res = await $http.plink.getPlinkList()
|
||||
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)
|
||||
});
|
||||
return tags
|
||||
}
|
||||
function gotoWebsite(url: string) {
|
||||
window.open(url, '_blank')
|
||||
}
|
||||
|
||||
function submitPut() {
|
||||
formRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
$msg.error('请完善表单~~')
|
||||
} else {
|
||||
const res = await $http.plink.addPlink(plinkData)
|
||||
if (res?.code !== 200) {
|
||||
$msg.error(res.msg)
|
||||
return
|
||||
}
|
||||
$msg.success(res.msg)
|
||||
plinkData.name = ''
|
||||
plinkData.title = ''
|
||||
plinkData.avater = ''
|
||||
plinkData.url = ''
|
||||
plinkData.desc = ''
|
||||
plinkData.tagname = ''
|
||||
getPlinkList()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
boxStyle.value = {
|
||||
height: window.innerHeight - nav.navH - 1 + 'px',
|
||||
}
|
||||
getPlinkList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -22,6 +193,7 @@ definePage({
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
@@ -34,7 +206,8 @@ definePage({
|
||||
animation: spin 1.5s linear infinite;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
:deep(.n-form-item-feedback__line) {
|
||||
text-align: right;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user