feat(navigation): hard-switch to Zibll navigation and Font Awesome 5
This commit is contained in:
1 parent
3c3ddac8be
commit
a0b84977a2
630 files changed
+101647
-11293
No files matched your search
@@ -11,7 +11,7 @@
|
||||
<template #header>
|
||||
<div class="aksrt-card-header-row">
|
||||
<div class="aksrt-card-header-row__left">
|
||||
<span class="header-icon"><i class="fas fa-cog"></i></span>
|
||||
<span class="header-icon"><i class="fa fas fa-cog"></i></span>
|
||||
<strong class="aksrt-card-header-row__title">基础设置</strong>
|
||||
</div>
|
||||
</div>
|
||||
@@ -61,11 +61,11 @@
|
||||
<template #header>
|
||||
<div class="aksrt-card-header-row">
|
||||
<div class="aksrt-card-header-row__left">
|
||||
<span class="header-icon"><i class="fas fa-layer-group"></i></span>
|
||||
<span class="header-icon"><i class="fa fas fa-clone"></i></span>
|
||||
<strong class="aksrt-card-header-row__title">按钮列表 ({{ form.items.length }})</strong>
|
||||
</div>
|
||||
<n-button type="primary" size="small" @click="addItem">
|
||||
<template #icon><i class="fas fa-plus"></i></template>
|
||||
<template #icon><i class="fa fas fa-plus"></i></template>
|
||||
添加按钮
|
||||
</n-button>
|
||||
</div>
|
||||
@@ -87,7 +87,7 @@
|
||||
<div class="float-btn-sort__item">
|
||||
<div class="float-btn-sort__main">
|
||||
<button type="button" class="float-btn-sort__handle" aria-label="拖拽排序">
|
||||
<i class="fas fa-grip-vertical"></i>
|
||||
<i class="fa fas fa-bars"></i>
|
||||
</button>
|
||||
<span class="float-btn-sort__icon">
|
||||
<i v-if="element.icon" :class="element.icon"></i>
|
||||
@@ -107,11 +107,11 @@
|
||||
</div>
|
||||
<div class="float-btn-sort__actions">
|
||||
<n-button size="tiny" quaternary type="primary" @click="editItem(index)">
|
||||
<template #icon><i class="fas fa-edit" style="font-size:12px;" /></template>
|
||||
<template #icon><i class="fa fas fa-edit" style="font-size:12px;" /></template>
|
||||
编辑
|
||||
</n-button>
|
||||
<n-button size="tiny" quaternary type="error" @click="deleteItem(index)">
|
||||
<template #icon><i class="fas fa-trash-alt" style="font-size:12px;" /></template>
|
||||
<template #icon><i class="fa fas fa-trash-alt" style="font-size:12px;" /></template>
|
||||
删除
|
||||
</n-button>
|
||||
</div>
|
||||
@@ -140,12 +140,12 @@
|
||||
<n-select v-model:value="editingItem.type" :options="typeOptions" placeholder="选择按钮类型" @update:value="handleTypeChange" />
|
||||
</n-form-item-gi>
|
||||
<n-form-item-gi v-if="editingItem.type !== 'theme_mode'" label="主图标 (Font Awesome)">
|
||||
<n-input v-model:value="editingItem.icon" placeholder="例如: fas fa-home" />
|
||||
<n-input v-model:value="editingItem.icon" placeholder="例如: fa fas fa-home" />
|
||||
</n-form-item-gi>
|
||||
<n-form-item-gi v-else label="主题图标">
|
||||
<div class="theme-icon-preview">
|
||||
<span><i class="fas fa-sun"></i> 亮色固定显示太阳</span>
|
||||
<span><i class="fas fa-moon"></i> 暗色固定显示月亮</span>
|
||||
<span><i class="fa fas fa-sun"></i> 亮色固定显示太阳</span>
|
||||
<span><i class="fa fas fa-moon"></i> 暗色固定显示月亮</span>
|
||||
</div>
|
||||
</n-form-item-gi>
|
||||
</n-grid>
|
||||
@@ -153,12 +153,12 @@
|
||||
<div class="icon-preview-row">
|
||||
<span>预览:</span>
|
||||
<template v-if="editingItem.type === 'theme_mode'">
|
||||
<span class="theme-icon-preview-inline"><i class="fas fa-sun"></i> / <i class="fas fa-moon"></i></span>
|
||||
<span class="theme-icon-preview-inline"><i class="fa fas fa-sun"></i> / <i class="fa fas fa-moon"></i></span>
|
||||
</template>
|
||||
<i v-else-if="editingItem.icon" :class="editingItem.icon" style="font-size: 18px;"></i>
|
||||
<span v-else class="muted-text">未设置图标</span>
|
||||
<a href="https://fontawesome.com/search?m=free" target="_blank" rel="noopener">
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
<i class="fa fas fa-external-link-alt"></i>
|
||||
Font Awesome
|
||||
</a>
|
||||
</div>
|
||||
@@ -229,12 +229,12 @@
|
||||
<div class="add-items-editor__head-actions">
|
||||
<n-dropdown trigger="click" :options="addPresetOptions" @select="applyAddPreset">
|
||||
<n-button size="small">
|
||||
<template #icon><i class="fas fa-magic" /></template>
|
||||
<template #icon><i class="fa fas fa-magic" /></template>
|
||||
一键预设
|
||||
</n-button>
|
||||
</n-dropdown>
|
||||
<n-button size="small" type="primary" @click="appendAddItem">
|
||||
<template #icon><i class="fas fa-plus" /></template>
|
||||
<template #icon><i class="fa fas fa-plus" /></template>
|
||||
添加子项
|
||||
</n-button>
|
||||
</div>
|
||||
@@ -251,13 +251,13 @@
|
||||
<template #item="{ element, index: subIndex }">
|
||||
<div class="add-items-editor__row">
|
||||
<button type="button" class="add-items-editor__drag" aria-label="拖拽排序">
|
||||
<i class="fas fa-grip-vertical"></i>
|
||||
<i class="fa fas fa-bars"></i>
|
||||
</button>
|
||||
<n-input v-model:value="element.label" placeholder="名称,例如: 写文章" />
|
||||
<n-input v-model:value="element.icon" placeholder="图标,例如: fas fa-pen" />
|
||||
<n-input v-model:value="element.icon" placeholder="图标,例如: fa fas fa-pen" />
|
||||
<n-input v-model:value="element.url" placeholder="链接,例如: /submit" />
|
||||
<n-button quaternary type="error" @click="removeAddItem(subIndex)">
|
||||
<template #icon><i class="fas fa-trash-alt" /></template>
|
||||
<template #icon><i class="fa fas fa-trash-alt" /></template>
|
||||
</n-button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -270,7 +270,7 @@
|
||||
<div class="add-items-preview__panel add-items-preview__panel--light">
|
||||
<div class="add-items-preview__mode">亮色</div>
|
||||
<div class="add-items-preview__trigger">
|
||||
<i :class="editingItem.icon || 'fas fa-plus'"></i>
|
||||
<i :class="editingItem.icon || 'fa fas fa-plus'"></i>
|
||||
</div>
|
||||
<div class="add-items-preview__menu">
|
||||
<div v-if="editingItem.add_items.length" class="add-items-preview__list">
|
||||
@@ -280,7 +280,7 @@
|
||||
href="javascript:void(0)"
|
||||
class="add-items-preview__item"
|
||||
>
|
||||
<i :class="subItem.icon || 'fas fa-pen'"></i>
|
||||
<i :class="subItem.icon || 'fa fas fa-pen'"></i>
|
||||
<span>{{ subItem.label || '未命名子项' }}</span>
|
||||
</a>
|
||||
</div>
|
||||
@@ -290,7 +290,7 @@
|
||||
<div class="add-items-preview__panel add-items-preview__panel--dark">
|
||||
<div class="add-items-preview__mode">暗色</div>
|
||||
<div class="add-items-preview__trigger add-items-preview__trigger--dark">
|
||||
<i :class="editingItem.icon || 'fas fa-plus'"></i>
|
||||
<i :class="editingItem.icon || 'fa fas fa-plus'"></i>
|
||||
</div>
|
||||
<div class="add-items-preview__menu add-items-preview__menu--dark">
|
||||
<div v-if="editingItem.add_items.length" class="add-items-preview__list">
|
||||
@@ -300,7 +300,7 @@
|
||||
href="javascript:void(0)"
|
||||
class="add-items-preview__item add-items-preview__item--dark"
|
||||
>
|
||||
<i :class="subItem.icon || 'fas fa-pen'"></i>
|
||||
<i :class="subItem.icon || 'fa fas fa-pen'"></i>
|
||||
<span>{{ subItem.label || '未命名子项' }}</span>
|
||||
</a>
|
||||
</div>
|
||||
@@ -410,7 +410,7 @@ function createDefaultItem() {
|
||||
return {
|
||||
id: '',
|
||||
type: 'custom',
|
||||
icon: 'fas fa-link',
|
||||
icon: 'fa fas fa-link',
|
||||
icon_dark: '',
|
||||
icon_light: '',
|
||||
text: '',
|
||||
@@ -435,14 +435,14 @@ function createDefaultItem() {
|
||||
|
||||
function applyTypeDefaults(type) {
|
||||
const map = {
|
||||
custom: { icon: 'fas fa-link', icon_dark: '', icon_light: '', text: '链接', desc: '', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
back_top: { icon: 'fas fa-chevron-up', icon_dark: '', icon_light: '', text: '顶部', desc: '返回顶部', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
theme_mode: { icon: 'fas fa-sun', icon_dark: '', icon_light: '', text: '主题', desc: '切换主题', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
qrcode: { icon: 'fas fa-qrcode', icon_dark: '', icon_light: '', text: '二维码', desc: '扫码继续浏览', link: '', hover: '', action_mode: 'qrcode', qr_size: 120 },
|
||||
service_qq: { icon: 'fab fa-qq', icon_dark: '', icon_light: '', text: 'QQ', desc: 'QQ 联系', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
service_wechat: { icon: 'fab fa-weixin', icon_dark: '', icon_light: '', text: '微信', desc: '扫码添加微信', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
pay_vip: { icon: 'fas fa-gem', icon_dark: '', icon_light: '', text: '会员', desc: '开通/升级会员弹窗', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
add: { icon: 'fas fa-plus', icon_dark: '', icon_light: '', text: '发布', desc: '发布内容', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
custom: { icon: 'fa fas fa-link', icon_dark: '', icon_light: '', text: '链接', desc: '', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
back_top: { icon: 'fa fas fa-chevron-up', icon_dark: '', icon_light: '', text: '顶部', desc: '返回顶部', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
theme_mode: { icon: 'fa fas fa-sun', icon_dark: '', icon_light: '', text: '主题', desc: '切换主题', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
qrcode: { icon: 'fa fas fa-qrcode', icon_dark: '', icon_light: '', text: '二维码', desc: '扫码继续浏览', link: '', hover: '', action_mode: 'qrcode', qr_size: 120 },
|
||||
service_qq: { icon: 'fa fab fa-qq', icon_dark: '', icon_light: '', text: 'QQ', desc: 'QQ 联系', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
service_wechat: { icon: 'fa fab fa-weixin', icon_dark: '', icon_light: '', text: '微信', desc: '扫码添加微信', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
pay_vip: { icon: 'fa fas fa-gem', icon_dark: '', icon_light: '', text: '会员', desc: '开通/升级会员弹窗', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
add: { icon: 'fa fas fa-plus', icon_dark: '', icon_light: '', text: '发布', desc: '发布内容', link: '', hover: '', action_mode: 'link', qr_size: 120 },
|
||||
}
|
||||
return map[type] || map.custom
|
||||
}
|
||||
@@ -465,8 +465,8 @@ function handleTypeChange(type) {
|
||||
if (type === 'pay_vip') {
|
||||
editingItem.link = ''
|
||||
editingItem.hover = ''
|
||||
if (!editingItem.icon || editingItem.icon.includes('fa-diamond')) {
|
||||
editingItem.icon = 'fas fa-gem'
|
||||
if (!editingItem.icon || editingItem.icon.includes('fa-gem')) {
|
||||
editingItem.icon = 'fa fas fa-gem'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -484,7 +484,7 @@ function appendAddItem() {
|
||||
editingItem.add_items.push({
|
||||
id: `add_${Date.now()}_${editingItem.add_items.length}`,
|
||||
label: '',
|
||||
icon: 'fas fa-pen',
|
||||
icon: 'fa fas fa-pen',
|
||||
url: '',
|
||||
})
|
||||
}
|
||||
@@ -503,9 +503,9 @@ function applyAddPreset(key) {
|
||||
}
|
||||
|
||||
const presetFactories = {
|
||||
post: () => ({ label: '写文章', icon: 'fas fa-pen-nib', url: `${siteUrl}/submit/` }),
|
||||
submit: () => ({ label: '投稿页', icon: 'fas fa-paper-plane', url: `${siteUrl}/submit/` }),
|
||||
profile: () => ({ label: '创作中心', icon: 'fas fa-user-edit', url: `${siteUrl}/user/` }),
|
||||
post: () => ({ label: '写文章', icon: 'fa fas fa-pen', url: `${siteUrl}/submit/` }),
|
||||
submit: () => ({ label: '投稿页', icon: 'fa fas fa-paper-plane', url: `${siteUrl}/submit/` }),
|
||||
profile: () => ({ label: '创作中心', icon: 'fa fas fa-user', url: `${siteUrl}/user/` }),
|
||||
}
|
||||
|
||||
const factory = presetFactories[key]
|
||||
@@ -531,9 +531,9 @@ function isAddPresetExists(key) {
|
||||
|
||||
function getAddPresetValue(key) {
|
||||
const presetFactories = {
|
||||
post: () => ({ label: '写文章', icon: 'fas fa-pen-nib', url: `${siteUrl}/submit/` }),
|
||||
submit: () => ({ label: '投稿页', icon: 'fas fa-paper-plane', url: `${siteUrl}/submit/` }),
|
||||
profile: () => ({ label: '创作中心', icon: 'fas fa-user-edit', url: `${siteUrl}/user/` }),
|
||||
post: () => ({ label: '写文章', icon: 'fa fas fa-pen', url: `${siteUrl}/submit/` }),
|
||||
submit: () => ({ label: '投稿页', icon: 'fa fas fa-paper-plane', url: `${siteUrl}/submit/` }),
|
||||
profile: () => ({ label: '创作中心', icon: 'fa fas fa-user', url: `${siteUrl}/user/` }),
|
||||
}
|
||||
|
||||
return presetFactories[key] ? presetFactories[key]() : null
|
||||
@@ -602,7 +602,7 @@ function saveItem() {
|
||||
const item = {
|
||||
id: editingItem.id || `float_${Date.now()}`,
|
||||
type: editingItem.type,
|
||||
icon: editingItem.type === 'theme_mode' ? 'fas fa-sun' : (editingItem.type === 'pay_vip' ? (editingItem.icon || 'fas fa-gem') : editingItem.icon),
|
||||
icon: editingItem.type === 'theme_mode' ? 'fa fas fa-sun' : (editingItem.type === 'pay_vip' ? (editingItem.icon || 'fa fas fa-gem') : editingItem.icon),
|
||||
icon_dark: '',
|
||||
icon_light: '',
|
||||
text: editingItem.text,
|
||||
@@ -618,7 +618,7 @@ function saveItem() {
|
||||
add_items: editingItem.type === 'add' ? editingItem.add_items.filter(subItem => subItem.label || subItem.url).map((subItem, idx) => ({
|
||||
id: subItem.id || `add_${idx}`,
|
||||
label: subItem.label || '',
|
||||
icon: subItem.icon || 'fas fa-pen',
|
||||
icon: subItem.icon || 'fa fas fa-pen',
|
||||
url: subItem.url || '',
|
||||
})) : [],
|
||||
hover: editingItem.type === 'pay_vip' ? '' : (supportsHover.value ? (editingItem.hover || '') : ''),
|
||||
@@ -672,7 +672,7 @@ async function loadSettings() {
|
||||
form.items = (data.items || []).map((item, index) => ({
|
||||
...createDefaultItem(),
|
||||
...item,
|
||||
icon: item.type === 'theme_mode' ? 'fas fa-sun' : (item.icon || ''),
|
||||
icon: item.type === 'theme_mode' ? 'fa fas fa-sun' : (item.icon || ''),
|
||||
color: item.color || null,
|
||||
bg: item.bg || null,
|
||||
icon_dark: '',
|
||||
@@ -705,7 +705,7 @@ async function handleSave() {
|
||||
filter_blur: form.filter_blur,
|
||||
items: form.items.map((item, index) => ({
|
||||
...item,
|
||||
icon: item.type === 'theme_mode' ? 'fas fa-sun' : (item.icon || ''),
|
||||
icon: item.type === 'theme_mode' ? 'fa fas fa-sun' : (item.icon || ''),
|
||||
icon_dark: '',
|
||||
icon_light: '',
|
||||
color: item.color || '',
|
||||
|
||||
@@ -409,7 +409,7 @@
|
||||
<n-input v-model:value="editingContactMore.desc" placeholder="如:微信公众号" />
|
||||
</n-form-item>
|
||||
<n-form-item label="图标类名">
|
||||
<n-input v-model:value="editingContactMore.icon" placeholder="如:fab fa-weixin" />
|
||||
<n-input v-model:value="editingContactMore.icon" placeholder="如:fa fab fa-weixin" />
|
||||
</n-form-item>
|
||||
<n-form-item label="链接地址">
|
||||
<n-input v-model:value="editingContactMore.link" placeholder="https://..." />
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<template #header>
|
||||
<div class="aksrt-card-header-row">
|
||||
<div class="aksrt-card-header-row__left">
|
||||
<span class="header-icon"><i class="fas fa-cog"></i></span>
|
||||
<span class="header-icon"><i class="fa fas fa-cog"></i></span>
|
||||
<strong class="aksrt-card-header-row__title">基础设置</strong>
|
||||
</div>
|
||||
</div>
|
||||
@@ -46,11 +46,11 @@
|
||||
<template #header>
|
||||
<div class="aksrt-card-header-row">
|
||||
<div class="aksrt-card-header-row__left">
|
||||
<span class="header-icon"><i class="fas fa-list-ul"></i></span>
|
||||
<span class="header-icon"><i class="fa fas fa-list-ul"></i></span>
|
||||
<strong class="aksrt-card-header-row__title">Tab按钮配置 ({{ form.items.length }})</strong>
|
||||
</div>
|
||||
<n-button type="primary" size="small" @click="addItem">
|
||||
<template #icon><i class="fas fa-plus"></i></template>
|
||||
<template #icon><i class="fa fas fa-plus"></i></template>
|
||||
添加按钮
|
||||
</n-button>
|
||||
</div>
|
||||
@@ -72,7 +72,7 @@
|
||||
<div class="tabbar-sort__item">
|
||||
<div class="tabbar-sort__main">
|
||||
<button type="button" class="tabbar-sort__handle" aria-label="拖拽排序">
|
||||
<i class="fas fa-grip-vertical"></i>
|
||||
<i class="fa fas fa-bars"></i>
|
||||
</button>
|
||||
<span class="tabbar-sort__icon">
|
||||
<i v-if="element.icon" :class="element.icon"></i>
|
||||
@@ -90,11 +90,11 @@
|
||||
</div>
|
||||
<div class="tabbar-sort__actions">
|
||||
<n-button size="tiny" quaternary type="primary" @click="editItem(index)">
|
||||
<template #icon><i class="fas fa-edit" style="font-size:12px;" /></template>
|
||||
<template #icon><i class="fa fas fa-edit" style="font-size:12px;" /></template>
|
||||
编辑
|
||||
</n-button>
|
||||
<n-button size="tiny" quaternary type="error" @click="deleteItem(index)">
|
||||
<template #icon><i class="fas fa-trash-alt" style="font-size:12px;" /></template>
|
||||
<template #icon><i class="fa fas fa-trash-alt" style="font-size:12px;" /></template>
|
||||
删除
|
||||
</n-button>
|
||||
</div>
|
||||
@@ -129,14 +129,14 @@
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="图标 (Font Awesome)">
|
||||
<n-input v-model:value="editingItem.icon" placeholder="例如: fas fa-home" />
|
||||
<n-input v-model:value="editingItem.icon" placeholder="例如: fa fas fa-home" />
|
||||
<template #feedback>
|
||||
<div class="icon-preview-row">
|
||||
<span>预览:</span>
|
||||
<i v-if="editingItem.icon" :class="editingItem.icon" style="font-size: 20px;"></i>
|
||||
<span v-else class="muted-text">无图标</span>
|
||||
<a href="https://fontawesome.com/search?m=free" target="_blank" rel="noopener" style="margin-left: 12px;">
|
||||
<i class="fas fa-external-link-alt"></i> Font Awesome 图标库
|
||||
<i class="fa fas fa-external-link-alt"></i> Font Awesome 图标库
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
@@ -198,7 +198,7 @@
|
||||
<div class="add-items-editor__head">
|
||||
<strong>发布菜单项</strong>
|
||||
<n-button size="small" type="primary" @click="appendAddItem">
|
||||
<template #icon><i class="fas fa-plus" /></template>
|
||||
<template #icon><i class="fa fas fa-plus" /></template>
|
||||
添加子项
|
||||
</n-button>
|
||||
</div>
|
||||
@@ -227,13 +227,13 @@
|
||||
<template #item="{ element, index: subIndex }">
|
||||
<div class="add-items-editor__row">
|
||||
<button type="button" class="add-items-editor__drag" aria-label="拖拽排序">
|
||||
<i class="fas fa-grip-vertical"></i>
|
||||
<i class="fa fas fa-bars"></i>
|
||||
</button>
|
||||
<n-input v-model:value="element.label" placeholder="名称,例如:写文章" />
|
||||
<n-input v-model:value="element.icon" placeholder="图标,例如:fas fa-pen" />
|
||||
<n-input v-model:value="element.icon" placeholder="图标,例如:fa fas fa-pen" />
|
||||
<n-input v-model:value="element.url" placeholder="链接,例如:/wp-admin/post-new.php" />
|
||||
<n-button quaternary type="error" @click="removeAddItem(subIndex)">
|
||||
<template #icon><i class="fas fa-trash-alt" /></template>
|
||||
<template #icon><i class="fa fas fa-trash-alt" /></template>
|
||||
</n-button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -327,15 +327,15 @@ const typeLabelMap = {
|
||||
}
|
||||
|
||||
const typeDefaults = {
|
||||
home: { icon: 'fas fa-home', text: '首页' },
|
||||
category: { icon: 'fas fa-th-large', text: '分类' },
|
||||
link: { icon: 'fas fa-link', text: '链接' },
|
||||
add: { icon: 'fas fa-plus', text: '发布' },
|
||||
user: { icon: 'fas fa-user', text: '用户中心' },
|
||||
auth: { icon: 'fas fa-user', text: '我的' },
|
||||
search: { icon: 'fas fa-search', text: '搜索' },
|
||||
msg: { icon: 'fas fa-bell', text: '消息' },
|
||||
pay_vip: { icon: 'fas fa-crown', text: '会员' },
|
||||
home: { icon: 'fa fas fa-home', text: '首页' },
|
||||
category: { icon: 'fa fas fa-th-large', text: '分类' },
|
||||
link: { icon: 'fa fas fa-link', text: '链接' },
|
||||
add: { icon: 'fa fas fa-plus', text: '发布' },
|
||||
user: { icon: 'fa fas fa-user', text: '用户中心' },
|
||||
auth: { icon: 'fa fas fa-user', text: '我的' },
|
||||
search: { icon: 'fa fas fa-search', text: '搜索' },
|
||||
msg: { icon: 'fa fas fa-bell', text: '消息' },
|
||||
pay_vip: { icon: 'fa fas fa-gem', text: '会员' },
|
||||
}
|
||||
|
||||
const enabledPreviewItems = computed(() => form.items.filter((item) => item.enabled))
|
||||
@@ -361,10 +361,10 @@ function getItemSummary(item) {
|
||||
}
|
||||
|
||||
const addPresets = [
|
||||
{ label: '写文章', icon: 'fas fa-pen-fancy', url: '/submit' },
|
||||
{ label: '投稿页', icon: 'fas fa-file-alt', url: '/submit' },
|
||||
{ label: '发布资源', icon: 'fas fa-cloud-upload-alt', url: '/resource-new' },
|
||||
{ label: '创作中心', icon: 'fas fa-palette', url: '/creator' },
|
||||
{ label: '写文章', icon: 'fa fas fa-pen', url: '/submit' },
|
||||
{ label: '投稿页', icon: 'fa fas fa-file-alt', url: '/submit' },
|
||||
{ label: '发布资源', icon: 'fa fas fa-cloud-upload-alt', url: '/resource-new' },
|
||||
{ label: '创作中心', icon: 'fa fas fa-paint-brush', url: '/creator' },
|
||||
]
|
||||
|
||||
function appendAddPreset(preset) {
|
||||
@@ -381,7 +381,7 @@ function appendAddItem() {
|
||||
editingItem.add_items.push({
|
||||
id: `add_${Date.now()}_${editingItem.add_items.length}`,
|
||||
label: '',
|
||||
icon: 'fas fa-pen',
|
||||
icon: 'fa fas fa-pen',
|
||||
url: '',
|
||||
})
|
||||
}
|
||||
@@ -421,7 +421,7 @@ function addItem() {
|
||||
Object.assign(editingItem, {
|
||||
id: `tab_${Date.now()}`,
|
||||
type: 'link',
|
||||
icon: 'fas fa-link',
|
||||
icon: 'fa fas fa-link',
|
||||
text: '链接',
|
||||
link: '',
|
||||
badge: '',
|
||||
@@ -489,7 +489,7 @@ function saveItem() {
|
||||
? editingItem.add_items.filter((sub) => sub.label && sub.url).map((sub) => ({
|
||||
id: sub.id || `add_${Date.now()}`,
|
||||
label: sub.label,
|
||||
icon: sub.icon || 'fas fa-pen',
|
||||
icon: sub.icon || 'fa fas fa-pen',
|
||||
url: sub.url,
|
||||
}))
|
||||
: [],
|
||||
|
||||
@@ -1,518 +0,0 @@
|
||||
<template>
|
||||
<div class="aksrt-page-container content-page">
|
||||
<PageHeader title="Hero 轮播管理" desc="管理首页 Hero 幻灯片内容(图片/视频、文案、图层、跳转)。标题、副标题可留空。" />
|
||||
|
||||
<n-card class="aksrt-section-card" style="margin-bottom:16px;">
|
||||
<template #header>
|
||||
<div class="aksrt-card-header-row">
|
||||
<strong>显示范围</strong>
|
||||
<n-button size="small" secondary @click="goHeaderComponents">顶部多功能组件(页面类型/搜索/卡片)</n-button>
|
||||
</div>
|
||||
</template>
|
||||
<p class="aksrt-inline-setting__hint" style="margin:0;">
|
||||
幻灯片内容在此维护。页面类型启用、设备规则、搜索覆盖层与图标卡片请到「顶部多功能组件」配置;全不选页面类型即为关闭。
|
||||
</p>
|
||||
</n-card>
|
||||
|
||||
<n-spin :show="loading" style="width:100%; min-height:200px;">
|
||||
<n-card class="aksrt-section-card">
|
||||
<template #header>
|
||||
<div class="aksrt-card-header-row">
|
||||
<div class="aksrt-card-header-row__left">
|
||||
<span class="header-icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px" aria-hidden="true">
|
||||
<rect width="18" height="18" x="3" y="3" rx="2" ry="2"/>
|
||||
<circle cx="9" cy="9" r="2"/>
|
||||
<path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>
|
||||
</svg>
|
||||
</span>
|
||||
<strong class="aksrt-card-header-row__title">Hero 列表 ({{ slides.length }})</strong>
|
||||
</div>
|
||||
<n-button type="primary" size="small" @click="openCreate">+ 添加 Hero</n-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<n-data-table
|
||||
v-if="slides.length"
|
||||
:columns="columns"
|
||||
:data="slides"
|
||||
:row-key="(row) => row.id"
|
||||
:bordered="false"
|
||||
size="small"
|
||||
/>
|
||||
<n-empty v-else description="暂无 Hero,添加后首页即可使用。" />
|
||||
</n-card>
|
||||
</n-spin>
|
||||
|
||||
<!-- 编辑/新增 弹窗 -->
|
||||
<n-modal
|
||||
v-model:show="modalShow"
|
||||
:mask-closable="false"
|
||||
preset="card"
|
||||
:title="editing.id ? '编辑 Hero' : '添加 Hero'"
|
||||
class="aksrt-modal-card"
|
||||
>
|
||||
<n-form :model="editing" label-placement="top" class="aksrt-form">
|
||||
<n-form-item label="标题">
|
||||
<n-input v-model:value="editing.title" placeholder="可选,主标题" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="副标题">
|
||||
<n-input v-model:value="editing.subtitle" placeholder="可选,副标题" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="背景图 URL">
|
||||
<n-input-group>
|
||||
<n-input v-model:value="editing.image_url" placeholder="https://..." />
|
||||
<n-button secondary @click="pickImage">媒体库</n-button>
|
||||
</n-input-group>
|
||||
</n-form-item>
|
||||
|
||||
<div v-if="editing.image_url" class="aksrt-modal-preview">
|
||||
<n-image :src="editing.image_url" width="100%" height="160" object-fit="cover" :preview-src="editing.image_url" />
|
||||
</div>
|
||||
|
||||
<n-form-item label="跳转链接">
|
||||
<n-input v-model:value="editing.link_url" placeholder="点击后跳转地址,可留空" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="描述文字">
|
||||
<n-input v-model:value="editing.description" type="textarea" :rows="2" placeholder="可选,显示在副标题下方" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="视频背景 URL">
|
||||
<n-input v-model:value="editing.video_url" placeholder="可选,MP4 视频地址替代背景图" />
|
||||
</n-form-item>
|
||||
|
||||
<div class="aksrt-modal-grid">
|
||||
<n-form-item label="链接打开方式">
|
||||
<n-radio-group v-model:value="editing.link_target">
|
||||
<n-radio-button value="_self">当前窗口</n-radio-button>
|
||||
<n-radio-button value="_blank">新窗口</n-radio-button>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="文字对齐">
|
||||
<n-radio-group v-model:value="editing.text_align">
|
||||
<n-radio-button value="left">左</n-radio-button>
|
||||
<n-radio-button value="center">居中</n-radio-button>
|
||||
<n-radio-button value="right">右</n-radio-button>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="设备可见性">
|
||||
<n-radio-group v-model:value="editing.device_visibility">
|
||||
<n-radio-button value="all">全部</n-radio-button>
|
||||
<n-radio-button value="pc">仅电脑</n-radio-button>
|
||||
<n-radio-button value="mobile">仅移动</n-radio-button>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="文字视差">
|
||||
<n-switch v-model:value="editing.text_parallax" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="文字大小(PC)">
|
||||
<n-input v-model:value="editing.text_size_pc" placeholder="如 48px,留空默认" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="文字大小(移动)">
|
||||
<n-input v-model:value="editing.text_size_m" placeholder="如 28px,留空默认" />
|
||||
</n-form-item>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-modal-grid">
|
||||
<n-form-item label="显示文字">
|
||||
<n-switch v-model:value="editing.show_text" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="排序">
|
||||
<n-input-number v-model:value="editing.sort_order" :min="0" style="width:100%;" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="启用">
|
||||
<n-switch v-model:value="editing.enabled" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="显示元信息">
|
||||
<n-switch v-model:value="editing.show_meta" />
|
||||
</n-form-item>
|
||||
</div>
|
||||
|
||||
<!-- 图片图层 -->
|
||||
<n-divider title-placement="left" style="margin:16px 0 12px;">
|
||||
图片图层(视差叠加)
|
||||
</n-divider>
|
||||
<div v-for="(layer, idx) in editing.layers" :key="idx" class="aksrt-layer-item">
|
||||
<div class="aksrt-layer-item__header">
|
||||
<strong>图层 {{ idx + 1 }}</strong>
|
||||
<n-button size="tiny" type="error" quaternary @click="removeLayer(idx)">删除</n-button>
|
||||
</div>
|
||||
<n-form-item label="图片">
|
||||
<n-input-group>
|
||||
<n-input v-model:value="layer.image" placeholder="图片 URL" />
|
||||
<n-button secondary @click="pickLayerImage(idx)">媒体库</n-button>
|
||||
</n-input-group>
|
||||
</n-form-item>
|
||||
<div class="aksrt-modal-grid">
|
||||
<n-form-item label="原始尺寸">
|
||||
<n-switch v-model:value="layer.free_size" />
|
||||
</n-form-item>
|
||||
<n-form-item label="对齐方式">
|
||||
<n-select v-model:value="layer.align" :options="[
|
||||
{ label: '居中', value: 'center' },
|
||||
{ label: '左上', value: 'left top' },
|
||||
{ label: '右上', value: 'right top' },
|
||||
{ label: '左下', value: 'left bottom' },
|
||||
{ label: '右下', value: 'right bottom' },
|
||||
]" />
|
||||
</n-form-item>
|
||||
<n-form-item label="视差">
|
||||
<n-switch v-model:value="layer.parallax" />
|
||||
</n-form-item>
|
||||
<n-form-item label="视差强度" v-if="layer.parallax">
|
||||
<n-slider v-model:value="layer.parallax_scale" :min="0" :max="1" :step="0.05" />
|
||||
</n-form-item>
|
||||
<n-form-item label="视差透明度" v-if="layer.parallax">
|
||||
<n-slider v-model:value="layer.parallax_opacity" :min="0" :max="1" :step="0.05" />
|
||||
</n-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<n-button size="small" dashed block @click="addLayer" style="margin-top:8px;">+ 添加图层</n-button>
|
||||
</n-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="aksrt-modal-footer">
|
||||
<n-button @click="modalShow = false">取消</n-button>
|
||||
<n-button type="primary" :loading="saving" @click="handleSave">保存</n-button>
|
||||
</div>
|
||||
</template>
|
||||
</n-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { h, onMounted, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { NButton, NImage, NTag, useDialog, useMessage } from 'naive-ui'
|
||||
import api from '@/api'
|
||||
import { openMediaPicker } from '@/utils/media'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const message = useMessage()
|
||||
const dialog = useDialog()
|
||||
|
||||
function goHeaderComponents() {
|
||||
router.push('/page-display/header-components')
|
||||
}
|
||||
const loading = ref(true)
|
||||
const saving = ref(false)
|
||||
const slides = ref([])
|
||||
|
||||
const modalShow = ref(false)
|
||||
const editing = ref(emptyForm())
|
||||
|
||||
function emptyForm() {
|
||||
return {
|
||||
id: 0,
|
||||
title: '',
|
||||
subtitle: '',
|
||||
description: '',
|
||||
image_url: '',
|
||||
video_url: '',
|
||||
link_url: '',
|
||||
link_target: '_self',
|
||||
text_align: 'left',
|
||||
device_visibility: 'all',
|
||||
enabled: true,
|
||||
show_text: true,
|
||||
show_meta: false,
|
||||
sort_order: 0,
|
||||
text_size_pc: '',
|
||||
text_size_m: '',
|
||||
text_parallax: false,
|
||||
layers: [],
|
||||
}
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '预览',
|
||||
key: 'image_url',
|
||||
width: 90,
|
||||
render(row) {
|
||||
if (!row.image_url) {
|
||||
return h('span', { style: 'color:#bbb;font-size:12px;' }, '无')
|
||||
}
|
||||
return h(NImage, {
|
||||
src: row.image_url,
|
||||
width: 64,
|
||||
height: 36,
|
||||
objectFit: 'cover',
|
||||
previewSrc: row.image_url,
|
||||
style: 'border-radius:4px;display:block;',
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '标题',
|
||||
key: 'title',
|
||||
ellipsis: { tooltip: true },
|
||||
render(row) {
|
||||
return row.title || h('span', { style: 'color:#bbb;' }, '未命名')
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '文字',
|
||||
key: 'show_text',
|
||||
width: 70,
|
||||
className: 'aksrt-table-mobile-hide',
|
||||
render(row) {
|
||||
return h(NTag, { size: 'small', type: row.show_text ? 'info' : 'default' }, {
|
||||
default: () => (row.show_text ? '显示' : '隐藏'),
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '元信息',
|
||||
key: 'show_meta',
|
||||
width: 78,
|
||||
className: 'aksrt-table-mobile-hide',
|
||||
render(row) {
|
||||
return h(NTag, { size: 'small', type: row.show_meta ? 'info' : 'default' }, {
|
||||
default: () => (row.show_meta ? '显示' : '隐藏'),
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '跳转',
|
||||
key: 'link_url',
|
||||
ellipsis: { tooltip: true },
|
||||
className: 'aksrt-table-mobile-hide',
|
||||
render(row) {
|
||||
return row.link_url || h('span', { style: 'color:#bbb;font-size:12px;' }, '—')
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
key: 'sort_order',
|
||||
width: 64,
|
||||
className: 'aksrt-table-mobile-hide',
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'enabled',
|
||||
width: 84,
|
||||
render(row) {
|
||||
return h(NTag, { size: 'small', type: row.enabled ? 'success' : 'default' }, {
|
||||
default: () => (row.enabled ? '启用' : '禁用'),
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
width: 130,
|
||||
render(row) {
|
||||
return h('div', { style: 'display:flex;gap:6px;' }, [
|
||||
h(NButton, { size: 'tiny', onClick: () => openEdit(row) }, { default: () => '编辑' }),
|
||||
h(NButton, { size: 'tiny', type: 'error', quaternary: true, onClick: () => handleDelete(row) }, { default: () => '删除' }),
|
||||
])
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
async function loadSlides() {
|
||||
try {
|
||||
loading.value = true
|
||||
const res = await api.getHeroes()
|
||||
if (res.code === 'success') {
|
||||
slides.value = res.data || []
|
||||
}
|
||||
} catch (e) {
|
||||
message.error(e.message || '加载失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function openCreate() {
|
||||
editing.value = emptyForm()
|
||||
modalShow.value = true
|
||||
}
|
||||
|
||||
function openEdit(row) {
|
||||
editing.value = {
|
||||
id: row.id,
|
||||
title: row.title || '',
|
||||
subtitle: row.subtitle || '',
|
||||
description: row.description || '',
|
||||
image_url: row.image_url || '',
|
||||
video_url: row.video_url || '',
|
||||
link_url: row.link_url || '',
|
||||
link_target: row.link_target || '_self',
|
||||
text_align: row.text_align || 'left',
|
||||
device_visibility: row.device_visibility || 'all',
|
||||
show_text: row.show_text !== false,
|
||||
enabled: !!row.enabled,
|
||||
show_meta: row.show_meta === true,
|
||||
sort_order: Number(row.sort_order) || 0,
|
||||
text_size_pc: row.text_size_pc || '',
|
||||
text_size_m: row.text_size_m || '',
|
||||
text_parallax: !!row.text_parallax,
|
||||
layers: Array.isArray(row.layers) ? row.layers : [],
|
||||
}
|
||||
modalShow.value = true
|
||||
}
|
||||
|
||||
async function pickImage() {
|
||||
try {
|
||||
const media = await openMediaPicker({
|
||||
title: '选择 Hero 背景图',
|
||||
buttonText: '使用这张 Hero 图',
|
||||
})
|
||||
if (media?.url) {
|
||||
editing.value.image_url = media.url
|
||||
}
|
||||
} catch (e) {
|
||||
message.error(e.message || '打开媒体库失败')
|
||||
}
|
||||
}
|
||||
|
||||
function addLayer() {
|
||||
editing.value.layers.push({
|
||||
image: '',
|
||||
free_size: false,
|
||||
align: 'center',
|
||||
parallax: false,
|
||||
parallax_scale: 0.3,
|
||||
parallax_opacity: 0.6,
|
||||
})
|
||||
}
|
||||
|
||||
function removeLayer(idx) {
|
||||
editing.value.layers.splice(idx, 1)
|
||||
}
|
||||
|
||||
async function pickLayerImage(idx) {
|
||||
try {
|
||||
const media = await openMediaPicker({
|
||||
title: '选择图层图片',
|
||||
buttonText: '使用这张图',
|
||||
})
|
||||
if (media?.url) {
|
||||
editing.value.layers[idx].image = media.url
|
||||
}
|
||||
} catch (e) {
|
||||
message.error(e.message || '打开媒体库失败')
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSave() {
|
||||
if (!editing.value.image_url) {
|
||||
message.warning('请填写 Hero 背景图')
|
||||
return
|
||||
}
|
||||
|
||||
saving.value = true
|
||||
try {
|
||||
if (editing.value.id) {
|
||||
await api.updateHero(editing.value.id, editing.value)
|
||||
message.success('已保存')
|
||||
} else {
|
||||
await api.createHero(editing.value)
|
||||
message.success('已添加')
|
||||
}
|
||||
modalShow.value = false
|
||||
await loadSlides()
|
||||
} catch (e) {
|
||||
message.error(e.message || '保存失败')
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleDelete(row) {
|
||||
dialog.warning({
|
||||
title: '确认删除',
|
||||
content: `确定删除 Hero「${row.title || '未命名'}」?`,
|
||||
positiveText: '删除',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
try {
|
||||
await api.deleteHero(row.id)
|
||||
message.success('已删除')
|
||||
await loadSlides()
|
||||
} catch (e) {
|
||||
message.error(e.message || '删除失败')
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadSlides()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.aksrt-inline-setting {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.aksrt-inline-setting__hint {
|
||||
color: #7a7f8a;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.aksrt-inline-setting__actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.aksrt-modal-preview {
|
||||
margin: -8px 0 18px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #eef1f6;
|
||||
}
|
||||
|
||||
.aksrt-modal-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.aksrt-layer-item {
|
||||
border: 1px solid #eef1f6;
|
||||
border-radius: 8px;
|
||||
padding: 14px;
|
||||
margin-bottom: 10px;
|
||||
background: #fafbfc;
|
||||
}
|
||||
|
||||
.aksrt-layer-item__header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.aksrt-modal-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.aksrt-modal-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -164,13 +164,12 @@
|
||||
<template #header><strong>固定骨架说明</strong></template>
|
||||
<n-space vertical>
|
||||
<n-alert type="warning" :show-icon="false">
|
||||
Hero 与 Banner 已作为固定首页骨架的一部分维护,不再由旧版首页模块编排驱动。
|
||||
顶部多功能组件与 Banner 已作为固定首页骨架的一部分维护,不再由旧版首页模块编排驱动。
|
||||
</n-alert>
|
||||
<n-alert type="info" :show-icon="false">
|
||||
如需调整首页首屏运营区,请前往对应管理页配置幻灯片内容或顶部组件参数。
|
||||
</n-alert>
|
||||
<n-space>
|
||||
<n-button secondary type="primary" @click="router.push('/page-display/hero')">管理 Hero 轮播</n-button>
|
||||
<n-button secondary type="primary" @click="router.push('/page-display/banner')">管理 Banner 轮播</n-button>
|
||||
<n-button secondary @click="router.push('/page-display/header-components')">
|
||||
顶部多功能组件
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<n-grid :cols="2" :x-gap="12" :y-gap="12">
|
||||
<n-grid-item>
|
||||
<div class="aksrt-docs__action">
|
||||
<FaIcon icon="fas fa-palette" :size="16" />
|
||||
<FaIcon icon="fa fas fa-paint-brush" :size="16" />
|
||||
<div>
|
||||
<strong>全局设置</strong>
|
||||
<p>Logo、背景、菜单装饰、自定义代码</p>
|
||||
@@ -17,7 +17,7 @@
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<div class="aksrt-docs__action">
|
||||
<FaIcon icon="fas fa-home" :size="16" />
|
||||
<FaIcon icon="fa fas fa-home" :size="16" />
|
||||
<div>
|
||||
<strong>首页配置</strong>
|
||||
<p>首页模块、布局、排序和预设模板</p>
|
||||
@@ -27,7 +27,7 @@
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<div class="aksrt-docs__action">
|
||||
<FaIcon icon="fas fa-users" :size="16" />
|
||||
<FaIcon icon="fa fas fa-users" :size="16" />
|
||||
<div>
|
||||
<strong>用户管理</strong>
|
||||
<p>登录注册、OAuth、签到、积分</p>
|
||||
@@ -37,7 +37,7 @@
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<div class="aksrt-docs__action">
|
||||
<FaIcon icon="fas fa-tools" :size="16" />
|
||||
<FaIcon icon="fa fas fa-wrench" :size="16" />
|
||||
<div>
|
||||
<strong>系统工具</strong>
|
||||
<p>导入导出、健康检查、迁移状态</p>
|
||||
@@ -66,7 +66,7 @@
|
||||
<h4 class="aksrt-docs__card-title">{{ doc.title }}</h4>
|
||||
<p class="aksrt-docs__card-desc">{{ doc.description }}</p>
|
||||
</div>
|
||||
<FaIcon icon="fas fa-external-link-alt" :size="12" class="aksrt-docs__card-arrow" />
|
||||
<FaIcon icon="fa fas fa-external-link-alt" :size="12" class="aksrt-docs__card-arrow" />
|
||||
</div>
|
||||
</n-card>
|
||||
</div>
|
||||
@@ -95,12 +95,12 @@ const themeVersion = ref(window.aksrtAdminData?.themeVersion || '3.4.0-dev')
|
||||
const dbSchemaVersion = ref('—')
|
||||
|
||||
const docs = ref([
|
||||
{ key: 'admin-ia-map', title: '后台 IA 蓝图', description: '完整的后台信息架构映射,12 个顶级分区及子页面清单。', icon: 'fas fa-sitemap', color: '#1890ff', file: 'admin-ia-map.md' },
|
||||
{ key: 'zibll-gap-matrix', title: '对标差异矩阵', description: 'AKSRT 当前 → Zibll 参考 → AKSRT 目标三层对照表。', icon: 'fas fa-columns', color: '#722ed1', file: 'zibll-gap-matrix.md' },
|
||||
{ key: 'frontend-page-matrix', title: '前端页面矩阵', description: '前端模板、CSS、JS 资产映射与覆盖范围。', icon: 'fas fa-desktop', color: '#13c2c2', file: 'frontend-page-matrix.md' },
|
||||
{ key: 'manual-acceptance-baseline', title: '验收基线', description: '每个 Phase 的人工验收标准和检查清单。', icon: 'fas fa-clipboard-check', color: '#52c41a', file: 'manual-acceptance-baseline.md' },
|
||||
{ key: 'feature-domain-map', title: '功能域地图', description: '业务域划分、依赖关系和模块边界说明。', icon: 'fas fa-map', color: '#fa8c16', file: 'feature-domain-map.md' },
|
||||
{ key: 'migration-map', title: '迁移地图', description: '设置 key 迁移、旧选项兼容和 Schema 版本对照。', icon: 'fas fa-exchange-alt', color: '#eb2f96', file: 'migration-map.md' },
|
||||
{ key: 'admin-ia-map', title: '后台 IA 蓝图', description: '完整的后台信息架构映射,12 个顶级分区及子页面清单。', icon: 'fa fas fa-sitemap', color: '#1890ff', file: 'admin-ia-map.md' },
|
||||
{ key: 'zibll-gap-matrix', title: '对标差异矩阵', description: 'AKSRT 当前 → Zibll 参考 → AKSRT 目标三层对照表。', icon: 'fa fas fa-columns', color: '#722ed1', file: 'zibll-gap-matrix.md' },
|
||||
{ key: 'frontend-page-matrix', title: '前端页面矩阵', description: '前端模板、CSS、JS 资产映射与覆盖范围。', icon: 'fa fas fa-desktop', color: '#13c2c2', file: 'frontend-page-matrix.md' },
|
||||
{ key: 'manual-acceptance-baseline', title: '验收基线', description: '每个 Phase 的人工验收标准和检查清单。', icon: 'fa fas fa-clipboard', color: '#52c41a', file: 'manual-acceptance-baseline.md' },
|
||||
{ key: 'feature-domain-map', title: '功能域地图', description: '业务域划分、依赖关系和模块边界说明。', icon: 'fa fas fa-map', color: '#fa8c16', file: 'feature-domain-map.md' },
|
||||
{ key: 'migration-map', title: '迁移地图', description: '设置 key 迁移、旧选项兼容和 Schema 版本对照。', icon: 'fa fas fa-exchange-alt', color: '#eb2f96', file: 'migration-map.md' },
|
||||
])
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="aksrt-ai__status">
|
||||
<div class="aksrt-ai__status-card">
|
||||
<div class="aksrt-ai__status-icon" :class="status.available ? 'aksrt-ai__status-icon--ok' : 'aksrt-ai__status-icon--off'">
|
||||
<i class="fas fa-robot"></i>
|
||||
<i class="fa fab fa-android"></i>
|
||||
</div>
|
||||
<div class="aksrt-ai__status-info">
|
||||
<div class="aksrt-ai__status-label">可用状态</div>
|
||||
@@ -18,7 +18,7 @@
|
||||
</div>
|
||||
<div class="aksrt-ai__status-card">
|
||||
<div class="aksrt-ai__status-icon" :class="status.wp_ai_available ? 'aksrt-ai__status-icon--ok' : 'aksrt-ai__status-icon--warn'">
|
||||
<i class="fas fa-plug"></i>
|
||||
<i class="fa fas fa-plug"></i>
|
||||
</div>
|
||||
<div class="aksrt-ai__status-info">
|
||||
<div class="aksrt-ai__status-label">WP AI Client</div>
|
||||
@@ -27,7 +27,7 @@
|
||||
</div>
|
||||
<div class="aksrt-ai__status-card">
|
||||
<div class="aksrt-ai__status-icon" :class="status.theme_available ? 'aksrt-ai__status-icon--ok' : 'aksrt-ai__status-icon--warn'">
|
||||
<i class="fas fa-key"></i>
|
||||
<i class="fa fas fa-key"></i>
|
||||
</div>
|
||||
<div class="aksrt-ai__status-info">
|
||||
<div class="aksrt-ai__status-label">主题 Provider</div>
|
||||
@@ -36,7 +36,7 @@
|
||||
</div>
|
||||
<div class="aksrt-ai__status-card">
|
||||
<div class="aksrt-ai__status-icon aksrt-ai__status-icon--info">
|
||||
<i class="fas fa-route"></i>
|
||||
<i class="fa fas fa-road"></i>
|
||||
</div>
|
||||
<div class="aksrt-ai__status-info">
|
||||
<div class="aksrt-ai__status-label">当前后端</div>
|
||||
@@ -115,7 +115,7 @@
|
||||
</div>
|
||||
|
||||
<div class="aksrt-ai__form-card aksrt-ai__notice">
|
||||
<h3><i class="fas fa-exclamation-triangle"></i> 重要说明</h3>
|
||||
<h3><i class="fa fas fa-exclamation-triangle"></i> 重要说明</h3>
|
||||
<ul>
|
||||
<li>AI 输出仅作为<strong>建议</strong>,不会自动写库;需用户点「更新/提交」才保存</li>
|
||||
<li>主题 API Key 已配置时优先使用;否则回退 WordPress AI Connectors</li>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<strong>{{ tool.title }}</strong>
|
||||
<p>{{ tool.desc }}</p>
|
||||
</div>
|
||||
<FaIcon icon="fas fa-chevron-right" :size="12" color="#c0c4cc" />
|
||||
<FaIcon icon="fa fas fa-chevron-right" :size="12" color="#c0c4cc" />
|
||||
</div>
|
||||
</n-grid-item>
|
||||
</n-grid>
|
||||
@@ -57,15 +57,15 @@
|
||||
<n-card title="手动维护" size="small" class="aksrt-tools__section">
|
||||
<n-space>
|
||||
<n-button @click="handleFlushCache">
|
||||
<template #icon><FaIcon icon="fas fa-broom" :size="12" /></template>
|
||||
<template #icon><FaIcon icon="fa fas fa-magic" :size="12" /></template>
|
||||
清除缓存
|
||||
</n-button>
|
||||
<n-button @click="handleOptimizeDb">
|
||||
<template #icon><FaIcon icon="fas fa-database" :size="12" /></template>
|
||||
<template #icon><FaIcon icon="fa fas fa-database" :size="12" /></template>
|
||||
优化数据表
|
||||
</n-button>
|
||||
<n-button @click="handleRebuildIndex">
|
||||
<template #icon><FaIcon icon="fas fa-sync-alt" :size="12" /></template>
|
||||
<template #icon><FaIcon icon="fa fas fa-sync-alt" :size="12" /></template>
|
||||
重建索引
|
||||
</n-button>
|
||||
</n-space>
|
||||
@@ -85,24 +85,24 @@ const router = useRouter()
|
||||
const message = useMessage()
|
||||
|
||||
const healthItems = ref([
|
||||
{ key: 'php', icon: 'fas fa-code', color: '#1890ff', value: '—', label: 'PHP 版本', status: 'ok' },
|
||||
{ key: 'wp', icon: 'fab fa-wordpress', color: '#722ed1', value: '—', label: 'WordPress', status: 'ok' },
|
||||
{ key: 'db', icon: 'fas fa-database', color: '#52c41a', value: '—', label: '数据库', status: 'ok' },
|
||||
{ key: 'uploads', icon: 'fas fa-folder-open', color: '#fa8c16', value: '—', label: '上传目录', status: 'ok' },
|
||||
{ key: 'php', icon: 'fa fas fa-code', color: '#1890ff', value: '—', label: 'PHP 版本', status: 'ok' },
|
||||
{ key: 'wp', icon: 'fa fab fa-wordpress', color: '#722ed1', value: '—', label: 'WordPress', status: 'ok' },
|
||||
{ key: 'db', icon: 'fa fas fa-database', color: '#52c41a', value: '—', label: '数据库', status: 'ok' },
|
||||
{ key: 'uploads', icon: 'fa fas fa-folder-open', color: '#fa8c16', value: '—', label: '上传目录', status: 'ok' },
|
||||
])
|
||||
|
||||
const tools = ref([
|
||||
{ key: 'import-export', icon: 'fas fa-exchange-alt', bg: '#1890ff', title: '导入导出', desc: '设置导入、导出和重置', route: '/tools/import-export' },
|
||||
{ key: 'health', icon: 'fas fa-heartbeat', bg: '#52c41a', title: '健康检查', desc: '系统状态检测和诊断', route: '/tools/health' },
|
||||
{ key: 'email-rollback', icon: 'fas fa-undo', bg: '#fa8c16', title: '邮箱回滚', desc: '邮箱变更 14 天内回滚', route: '/tools/email-rollback' },
|
||||
{ key: 'import-export', icon: 'fa fas fa-exchange-alt', bg: '#1890ff', title: '导入导出', desc: '设置导入、导出和重置', route: '/tools/import-export' },
|
||||
{ key: 'health', icon: 'fa fas fa-heartbeat', bg: '#52c41a', title: '健康检查', desc: '系统状态检测和诊断', route: '/tools/health' },
|
||||
{ key: 'email-rollback', icon: 'fa fas fa-undo', bg: '#fa8c16', title: '邮箱回滚', desc: '邮箱变更 14 天内回滚', route: '/tools/email-rollback' },
|
||||
])
|
||||
|
||||
const services = ref([
|
||||
{ key: 'sms', icon: 'fas fa-sms', color: '#1890ff', name: '短信服务', description: '验证码和通知短信', available: false },
|
||||
{ key: 'wechat', icon: 'fab fa-weixin', color: '#52c41a', name: '微信通知', description: '微信模板消息和订阅通知', available: false },
|
||||
{ key: 'captcha', icon: 'fas fa-shield-alt', color: '#722ed1', name: '验证码服务', description: '人机验证(极验/腾讯/阿里云)', available: false },
|
||||
{ key: 'push', icon: 'fas fa-paper-plane', color: '#fa8c16', name: '搜索引擎推送', description: '百度/Google 主动推送', available: false },
|
||||
{ key: 'audit', icon: 'fas fa-shield-virus', color: '#f5222d', name: '内容审核', description: '第三方内容安全审核 API', available: false },
|
||||
{ key: 'sms', icon: 'fa fas fa-comment', color: '#1890ff', name: '短信服务', description: '验证码和通知短信', available: false },
|
||||
{ key: 'wechat', icon: 'fa fab fa-weixin', color: '#52c41a', name: '微信通知', description: '微信模板消息和订阅通知', available: false },
|
||||
{ key: 'captcha', icon: 'fa fas fa-shield-alt', color: '#722ed1', name: '验证码服务', description: '人机验证(极验/腾讯/阿里云)', available: false },
|
||||
{ key: 'push', icon: 'fa fas fa-paper-plane', color: '#fa8c16', name: '搜索引擎推送', description: '百度/Google 主动推送', available: false },
|
||||
{ key: 'audit', icon: 'fa fas fa-shield-alt', color: '#f5222d', name: '内容审核', description: '第三方内容安全审核 API', available: false },
|
||||
])
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
@@ -51,12 +51,12 @@ const overview = ref({})
|
||||
const loading = ref(false)
|
||||
|
||||
function iconFor(id) {
|
||||
if (id === 'balance') return 'fas fa-wallet'
|
||||
if (id === 'alipay' || id === 'epay_alipay') return 'fab fa-alipay'
|
||||
if (id === 'wechatpay' || id === 'epay_wxpay') return 'fab fa-weixin'
|
||||
if (id === 'paypal') return 'fab fa-paypal'
|
||||
if (id === 'stripe') return 'fab fa-stripe-s'
|
||||
return 'fas fa-credit-card'
|
||||
if (id === 'balance') return 'fa fas fa-credit-card'
|
||||
if (id === 'alipay' || id === 'epay_alipay') return 'fa fas fa-credit-card'
|
||||
if (id === 'wechatpay' || id === 'epay_wxpay') return 'fa fab fa-weixin'
|
||||
if (id === 'paypal') return 'fa fab fa-paypal'
|
||||
if (id === 'stripe') return 'fa fab fa-cc-stripe'
|
||||
return 'fa fas fa-credit-card'
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
@@ -99,10 +99,10 @@ const form = reactive({
|
||||
})
|
||||
|
||||
const summaryItems = computed(() => [
|
||||
{ key: 'profile', icon: 'fas fa-id-card', label: '资料卡图片', enabled: true },
|
||||
{ key: 'submit', icon: 'fas fa-edit', label: '投稿图片', enabled: true },
|
||||
{ key: 'comment', icon: 'fas fa-comment-dots', label: '评论图片', enabled: true },
|
||||
{ key: 'resource', icon: 'fas fa-file-archive', label: '资源附件', enabled: true },
|
||||
{ key: 'profile', icon: 'fa fas fa-id-card', label: '资料卡图片', enabled: true },
|
||||
{ key: 'submit', icon: 'fa fas fa-edit', label: '投稿图片', enabled: true },
|
||||
{ key: 'comment', icon: 'fa fas fa-comment-dots', label: '评论图片', enabled: true },
|
||||
{ key: 'resource', icon: 'fa fas fa-file-archive', label: '资源附件', enabled: true },
|
||||
])
|
||||
|
||||
function go(path) {
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
size="small"
|
||||
class="aksrt-theme-info__module-tag"
|
||||
>
|
||||
<FaIcon :icon="mod.enabled ? 'fas fa-check-circle' : 'fas fa-circle'" :size="10" />
|
||||
<FaIcon :icon="mod.enabled ? 'fa fas fa-check-circle' : 'fa fas fa-circle'" :size="10" />
|
||||
{{ mod.label }}
|
||||
</n-tag>
|
||||
</div>
|
||||
@@ -94,23 +94,23 @@
|
||||
<n-card class="aksrt-theme-info__card" title="快速入口" size="small">
|
||||
<div class="aksrt-theme-info__links">
|
||||
<router-link to="/docs" class="aksrt-theme-info__link">
|
||||
<FaIcon icon="fas fa-book" :size="16" />
|
||||
<FaIcon icon="fa fas fa-book" :size="16" />
|
||||
<span>文档中心</span>
|
||||
</router-link>
|
||||
<router-link to="/tools/update" class="aksrt-theme-info__link">
|
||||
<FaIcon icon="fas fa-cloud-arrow-down" :size="16" />
|
||||
<FaIcon icon="fa fas fa-cloud-download-alt" :size="16" />
|
||||
<span>更新中心</span>
|
||||
</router-link>
|
||||
<router-link to="/tools/backup" class="aksrt-theme-info__link">
|
||||
<FaIcon icon="fas fa-box-archive" :size="16" />
|
||||
<FaIcon icon="fa fas fa-archive" :size="16" />
|
||||
<span>数据备份</span>
|
||||
</router-link>
|
||||
<router-link to="/tools/health" class="aksrt-theme-info__link">
|
||||
<FaIcon icon="fas fa-heartbeat" :size="16" />
|
||||
<FaIcon icon="fa fas fa-heartbeat" :size="16" />
|
||||
<span>健康检查</span>
|
||||
</router-link>
|
||||
<router-link to="/tools/import-export" class="aksrt-theme-info__link">
|
||||
<FaIcon icon="fas fa-exchange-alt" :size="16" />
|
||||
<FaIcon icon="fa fas fa-exchange-alt" :size="16" />
|
||||
<span>导入导出</span>
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="aksrt-wechat__status">
|
||||
<div class="aksrt-wechat__status-card">
|
||||
<div class="aksrt-wechat__status-icon" :class="status.configured ? 'aksrt-wechat__status-icon--ok' : 'aksrt-wechat__status-icon--warn'">
|
||||
<i :class="status.configured ? 'fas fa-check' : 'fas fa-exclamation'"></i>
|
||||
<i :class="status.configured ? 'fa fas fa-check' : 'fa fas fa-exclamation'"></i>
|
||||
</div>
|
||||
<div class="aksrt-wechat__status-info">
|
||||
<div class="aksrt-wechat__status-label">配置状态</div>
|
||||
@@ -15,7 +15,7 @@
|
||||
</div>
|
||||
<div class="aksrt-wechat__status-card">
|
||||
<div class="aksrt-wechat__status-icon" :class="status.has_token ? 'aksrt-wechat__status-icon--ok' : 'aksrt-wechat__status-icon--warn'">
|
||||
<i :class="status.has_token ? 'fas fa-key' : 'fas fa-key'"></i>
|
||||
<i :class="status.has_token ? 'fa fas fa-key' : 'fa fas fa-key'"></i>
|
||||
</div>
|
||||
<div class="aksrt-wechat__status-info">
|
||||
<div class="aksrt-wechat__status-label">Access Token</div>
|
||||
@@ -24,7 +24,7 @@
|
||||
</div>
|
||||
<div class="aksrt-wechat__status-card">
|
||||
<div class="aksrt-wechat__status-icon" :class="status.has_template ? 'aksrt-wechat__status-icon--ok' : 'aksrt-wechat__status-icon--warn'">
|
||||
<i :class="status.has_template ? 'fas fa-file-alt' : 'fas fa-file-alt'"></i>
|
||||
<i :class="status.has_template ? 'fa fas fa-file-alt' : 'fa fas fa-file-alt'"></i>
|
||||
</div>
|
||||
<div class="aksrt-wechat__status-info">
|
||||
<div class="aksrt-wechat__status-label">模板 ID</div>
|
||||
@@ -33,7 +33,7 @@
|
||||
</div>
|
||||
<div class="aksrt-wechat__status-card">
|
||||
<div class="aksrt-wechat__status-icon aksrt-wechat__status-icon--info">
|
||||
<i class="fas fa-users"></i>
|
||||
<i class="fa fas fa-users"></i>
|
||||
</div>
|
||||
<div class="aksrt-wechat__status-info">
|
||||
<div class="aksrt-wechat__status-label">绑定用户</div>
|
||||
|
||||
Reference in new issue
Block a user