Normalize fixed profile fields, profile actions, and the five-column capability matrix for comments, uploads, and downloads.
177 lines
7.4 KiB
Vue
177 lines
7.4 KiB
Vue
<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>
|
||
</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>
|
||
|
||
<!-- 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,
|
||
icp_number: '',
|
||
police_number: '',
|
||
lazyload_enabled: true,
|
||
lazyload_placeholder_url: '',
|
||
paging_ajax_s: '1',
|
||
comment_pagination_mode: 'numbered',
|
||
})
|
||
|
||
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.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,
|
||
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>
|