Files
wordpress-theme-aksrt/assets/admin/src/pages/SiteSettings.vue
T
kate522 91b083b2b0 refactor(settings): collapse get_all to aksrt_settings and drop migration UI
Make aksrt_settings the sole theme settings store for get_all(), remove
aksrt_seo_settings/aksrt_basic_settings merge paths, point global.logo
schema at aksrt_settings, and delete the retired settings migration page,
route, REST endpoint, and related SPA surface.
2026-07-11 16:55:27 +08:00

211 lines
9.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="aksrt-page-container">
<PageHeader title="站点设置" desc="集中管理评论、分页、懒加载、头像源与备案信息。">
<template #actions>
<n-button type="primary" :loading="saving" @click="handleSave">保存全部</n-button>
</template>
</PageHeader>
<n-spin :show="loading" style="width:100%; min-height:200px;">
<!-- 1. 评论 -->
<n-card class="aksrt-section-card">
<div class="aksrt-section-header">
<span class="section-icon"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></span>
<h3>评论设置</h3>
</div>
<n-form :model="basic" label-placement="left" label-width="140" class="aksrt-form">
<n-form-item label="全局评论开关">
<n-switch v-model:value="basic.comment_enabled">
<template #checked>已开启</template>
<template #unchecked>已关闭</template>
</n-switch>
<template #feedback>
<span class="aksrt-hint-text">关闭后全站禁用评论功能。</span>
</template>
</n-form-item>
<n-form-item v-if="basic.comment_enabled" label="必须注册才能评论">
<n-switch v-model:value="basic.comment_requires_registration">
<template #checked>是</template>
<template #unchecked>否</template>
</n-switch>
</n-form-item>
</n-form>
</n-card>
<!-- 2. 分页 -->
<n-card class="aksrt-section-card">
<div class="aksrt-section-header">
<span class="section-icon"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg></span>
<h3>分页设置</h3>
</div>
<n-form :model="basic" label-placement="left" label-width="140" class="aksrt-form">
<n-form-item label="文章列表分页">
<n-radio-group v-model:value="basic.paging_ajax_s">
<n-space size="large">
<n-radio-button value="0">数字翻页</n-radio-button>
<n-radio-button value="1">加载更多</n-radio-button>
<n-radio-button value="1">无限滚动</n-radio-button>
</n-space>
</n-radio-group>
</n-form-item>
<n-form-item label="评论列表分页">
<n-radio-group v-model:value="basic.comment_pagination_mode">
<n-space size="large">
<n-radio-button value="0">数字翻页</n-radio-button>
<n-radio-button value="1">加载更多</n-radio-button>
<n-radio-button value="1">无限滚动</n-radio-button>
</n-space>
</n-radio-group>
</n-form-item>
</n-form>
</n-card>
<!-- 3. 懒加载 -->
<n-card class="aksrt-section-card">
<div class="aksrt-section-header">
<span class="section-icon"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg></span>
<h3>图片懒加载</h3>
</div>
<n-form :model="basic" label-placement="left" label-width="140" class="aksrt-form">
<n-form-item label="启用懒加载">
<n-switch v-model:value="basic.lazyload_enabled">
<template #checked>已开启</template>
<template #unchecked>已关闭</template>
</n-switch>
<template #feedback>
<span class="aksrt-hint-text">开启后图片在进入视口时才加载,可显著提升页面加载速度。</span>
</template>
</n-form-item>
<n-form-item v-if="basic.lazyload_enabled" label="自定义占位图 URL">
<n-input v-model:value="basic.lazyload_placeholder_url" placeholder="留空使用默认占位图" />
</n-form-item>
</n-form>
</n-card>
<!-- 4. 头像 -->
<n-card class="aksrt-section-card">
<div class="aksrt-section-header">
<span class="section-icon"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg></span>
<h3>Gravatar 头像源</h3>
</div>
<n-form :model="basic" label-placement="left" label-width="130" class="aksrt-form">
<n-form-item label="头像服务源">
<n-select v-model:value="basic.avatar_source" :options="avatarSourceOptions" placeholder="选择头像镜像源" />
<template #feedback>
<span class="aksrt-hint-text">国内站点建议优先选 Cravatar。</span>
</template>
</n-form-item>
</n-form>
</n-card>
<!-- 5. 备案 -->
<n-card class="aksrt-section-card">
<div class="aksrt-section-header">
<span class="section-icon"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg></span>
<h3>备案信息</h3>
</div>
<n-form :model="basic" label-placement="left" label-width="120" class="aksrt-form">
<n-form-item label="ICP 备案号">
<n-input v-model:value="basic.icp_number" placeholder="例如:ICP 备 xxxxxxxx 号" />
</n-form-item>
<n-form-item label="公安备案号">
<n-input v-model:value="basic.police_number" placeholder="例如:公网安备 xxxxxx 号" />
</n-form-item>
</n-form>
</n-card>
<div class="aksrt-form-actions">
<n-button type="primary" :loading="saving" @click="handleSave">保存全部</n-button>
</div>
</n-spin>
</div>
</template>
<script setup>
import { onMounted, reactive, ref } from 'vue'
import { useMessage } from 'naive-ui'
import api from '@/api'
import PageHeader from '@/components/PageHeader.vue'
const message = useMessage()
const loading = ref(true)
const saving = ref(false)
// 基础设置(canonical: aksrt_settings)
// 后端 /settings/basic 返回基础字段;auth 相关字段由 /settings/auth 独立维护。
const basic = reactive({
comment_enabled: true,
comment_requires_registration: false,
avatar_source: 'cn.cravatar.com',
icp_number: '',
police_number: '',
lazyload_enabled: true,
lazyload_placeholder_url: '',
paging_ajax_s: '1',
comment_pagination_mode: 'numbered',
})
const avatarSourceOptions = [
{ label: 'Cravatar (国内推荐)', value: 'cn.cravatar.com' },
{ label: 'Gravatar 国内镜像', value: 'cn.gravatar.com' },
{ label: 'Gravatar 官方', value: 'gravatar.com' },
]
async function loadAll() {
loading.value = true
try {
const basicRes = await api.getBasicSettings()
if (basicRes?.code === 'success' && basicRes.data) {
const d = basicRes.data
basic.comment_enabled = d.comment_enabled !== false
basic.comment_requires_registration = !!d.comment_requires_registration
basic.avatar_source = d.avatar_source || 'cn.cravatar.com'
basic.icp_number = d.icp_number || ''
basic.police_number = d.police_number || ''
basic.lazyload_enabled = d.lazyload_enabled !== false
basic.lazyload_placeholder_url = d.lazyload_placeholder_url || ''
basic.paging_ajax_s = d.paging_ajax_s ?? '1'
basic.comment_pagination_mode = d.comment_pagination_mode || 'numbered'
}
} catch (e) {
message.error(e.message || '加载失败')
} finally {
loading.value = false
}
}
async function handleSave() {
saving.value = true
try {
const basicPayload = {
comment_enabled: basic.comment_enabled,
comment_requires_registration: basic.comment_requires_registration,
avatar_source: basic.avatar_source,
icp_number: basic.icp_number,
police_number: basic.police_number,
lazyload_enabled: basic.lazyload_enabled,
lazyload_placeholder_url: basic.lazyload_placeholder_url,
paging_ajax_s: basic.paging_ajax_s,
comment_pagination_mode: basic.comment_pagination_mode,
}
const res = await api.saveBasicSettings(basicPayload)
if (res?.code === 'success') {
message.success('已保存')
} else {
throw new Error(res?.message || '保存失败')
}
} catch (e) {
message.error(e.message || '保存失败')
} finally {
saving.value = false
}
}
onMounted(loadAll)
</script>