feat(homepage): align homepage settings with Zibll main-list keys

Move /settings/homepage onto a dedicated REST trait that stores Zibll
option IDs (home_posts_list_s, index_list_title, home_lists, exclude
posts/cats, list1 orderby). Reader exposes both canonical keys and
temporary aliases for existing front-end helpers; save path drops
superseded AKSRT-only keys. HomepageSettings.vue binds to the new
contract while remaining a Vue custom page.
This commit is contained in:
2026-07-11 15:14:22 +08:00
parent 18630370dc
commit 8fddc33156
7 changed files with 467 additions and 196 deletions
@@ -41,19 +41,19 @@
<template #header><strong>主列表</strong></template>
<n-form :model="form" label-placement="left" label-width="160" class="aksrt-form">
<n-form-item label="启用主列表">
<n-switch v-model:value="form.home_posts_list_enabled" />
<n-switch v-model:value="form.home_posts_list_s" />
<template #feedback><span class="aksrt-hint-text">首页主内容区保留 Zibll 式内容流,不建议关闭。</span></template>
</n-form-item>
<n-form-item label="区块标题">
<n-input v-model:value="form.home_list_title" placeholder="最新发布" />
<n-form-item label="显示标题">
<n-input v-model:value="form.index_list_title" placeholder="最新发布" />
</n-form-item>
<n-form-item label="默认排序">
<n-select v-model:value="form.homepage_default_sort" :options="allSortOptions" />
<n-form-item label="主栏目默认排序">
<n-select v-model:value="form.home_list1_orderby_option.orderby" :options="allSortOptions" />
</n-form-item>
<n-form-item label="启用排序栏">
<n-switch v-model:value="form.home_list_sort_enabled" />
<n-form-item label="显示排序方式按钮">
<n-switch v-model:value="form.home_list1_orderby_s" />
</n-form-item>
<n-form-item v-if="form.home_list_sort_enabled" label="排序栏样式">
<n-form-item v-if="form.home_list1_orderby_s" label="排序栏样式">
<n-radio-group v-model:value="form.home_list_sort_dropdown">
<n-space size="large">
<n-radio-button :value="false">内联链接</n-radio-button>
@@ -61,9 +61,9 @@
</n-space>
</n-radio-group>
</n-form-item>
<n-form-item v-if="form.home_list_sort_enabled" label="可用排序选项">
<n-form-item v-if="form.home_list1_orderby_s" label="排序方式选项">
<n-select
v-model:value="form.home_list_sort_options"
v-model:value="form.home_list1_orderby_option.options"
:options="allSortOptions"
multiple
placeholder="选择排序选项"
@@ -75,7 +75,7 @@
<n-card class="aksrt-section-card" style="margin-bottom:16px;">
<template #header><strong>排除规则</strong></template>
<n-form :model="form" label-placement="left" label-width="160" class="aksrt-form">
<n-form-item label="排除文章 ID">
<n-form-item label="排除文章">
<n-input
v-model:value="excludePostIdsText"
type="textarea"
@@ -84,7 +84,7 @@
/>
<template #feedback><span class="aksrt-hint-text">主列表和首页 Tab 查询均排除这些文章。</span></template>
</n-form-item>
<n-form-item label="排除分类 ID">
<n-form-item label="排除分类">
<n-input
v-model:value="excludeCategoryIdsText"
type="textarea"
@@ -99,8 +99,8 @@
<n-card class="aksrt-section-card" style="margin-bottom:16px;">
<template #header>
<div style="display:flex; align-items:center; justify-content:space-between;">
<strong>首页 Tab</strong>
<n-button size="small" @click="addTab">+ 添加 Tab</n-button>
<strong>更多栏目</strong>
<n-button size="small" @click="addTab">+ 添加栏目</n-button>
</div>
</template>
<n-form :model="form" label-placement="left" label-width="160" class="aksrt-form" style="margin-bottom:16px;">
@@ -112,11 +112,11 @@
</n-form-item>
</n-form>
<div v-if="form.homepage_tabs.length === 0" class="homepage-settings__empty-tabs">
<n-text depth="3">暂无 Tab 配置,点击“添加 Tab”创建首页分类切换。</n-text>
<div v-if="form.home_lists.length === 0" class="homepage-settings__empty-tabs">
<n-text depth="3">暂无更多栏目,点击“添加栏目”创建分类/专题 Tab。</n-text>
</div>
<div v-for="(tab, index) in form.homepage_tabs" :key="index" class="homepage-settings__tab-row">
<div v-for="(tab, index) in form.home_lists" :key="index" class="homepage-settings__tab-row">
<div class="homepage-settings__tab-fields">
<n-select
:value="tab.term_id"
@@ -242,50 +242,52 @@ const allSortOptions = [
const form = reactive({
homepage_content_model: 'mixed',
homepage_tabs: [],
home_posts_list_s: true,
home_list1_orderby_s: true,
home_list1_orderby_option: {
orderby: 'modified',
options: ['modified', 'date', 'views', 'likes', 'comments'],
},
index_list_title: '最新发布',
home_exclude_posts: [],
home_exclude_cats: [],
home_lists: [],
homepage_card_style: 'default',
homepage_multi_thumb_enabled: true,
homepage_multi_thumb_min_images: 3,
homepage_sidebar_mini_enabled: true,
homepage_default_sort: 'modified',
homepage_default_view: 'list',
homepage_sort_ajax_enabled: true,
homepage_sticky_tabs_enabled: true,
home_posts_list_enabled: true,
home_list_title: '最新发布',
home_list_sort_enabled: true,
home_list_sort_options: ['modified', 'date', 'views', 'likes', 'comments'],
home_list_sort_dropdown: false,
home_exclude_post_ids: [],
home_exclude_category_ids: [],
homepage_tab_posts_per_page: 6,
homepage_tab_limit: 4,
})
const excludePostIdsText = computed({
get: () => (form.home_exclude_post_ids || []).join(','),
get: () => (form.home_exclude_posts || []).join(','),
set: (val) => {
form.home_exclude_post_ids = val.split(',').map(s => parseInt(s.trim(), 10)).filter(n => n > 0)
form.home_exclude_posts = val.split(',').map(s => parseInt(s.trim(), 10)).filter(n => n > 0)
},
})
const excludeCategoryIdsText = computed({
get: () => (form.home_exclude_category_ids || []).join(','),
get: () => (form.home_exclude_cats || []).join(','),
set: (val) => {
form.home_exclude_category_ids = val.split(',').map(s => parseInt(s.trim(), 10)).filter(n => n > 0)
form.home_exclude_cats = val.split(',').map(s => parseInt(s.trim(), 10)).filter(n => n > 0)
},
})
function addTab() {
form.homepage_tabs.push({ term_id: 0, title: '', orderby: 'date', enabled: true })
form.home_lists.push({ term_id: 0, title: '', orderby: 'date', enabled: true })
}
function removeTab(index) {
form.homepage_tabs.splice(index, 1)
form.home_lists.splice(index, 1)
}
function updateTab(index, field, value) {
form.homepage_tabs[index][field] = value
form.home_lists[index][field] = value
}
async function loadCategories() {
@@ -308,27 +310,38 @@ async function loadSettings() {
const d = res?.data || {}
form.homepage_content_model = d.homepage_content_model || 'mixed'
form.homepage_tabs = Array.isArray(d.homepage_tabs) ? d.homepage_tabs : []
form.home_posts_list_s = d.home_posts_list_s !== false && d.home_posts_list_enabled !== false
form.home_list1_orderby_s = d.home_list1_orderby_s !== false && d.home_list_sort_enabled !== false
const orderOpt = d.home_list1_orderby_option && typeof d.home_list1_orderby_option === 'object' ? d.home_list1_orderby_option : {}
form.home_list1_orderby_option = {
orderby: orderOpt.orderby || d.homepage_default_sort || 'modified',
options: Array.isArray(orderOpt.options) && orderOpt.options.length
? orderOpt.options
: (Array.isArray(d.home_list_sort_options) && d.home_list_sort_options.length
? d.home_list_sort_options
: ['modified', 'date', 'views', 'likes', 'comments']),
}
form.index_list_title = d.index_list_title || d.home_list_title || '最新发布'
form.home_exclude_posts = Array.isArray(d.home_exclude_posts)
? d.home_exclude_posts
: (Array.isArray(d.home_exclude_post_ids) ? d.home_exclude_post_ids : [])
form.home_exclude_cats = Array.isArray(d.home_exclude_cats)
? d.home_exclude_cats
: (Array.isArray(d.home_exclude_category_ids) ? d.home_exclude_category_ids : [])
form.home_lists = Array.isArray(d.home_lists)
? d.home_lists
: (Array.isArray(d.homepage_tabs) ? d.homepage_tabs : [])
form.homepage_card_style = d.homepage_card_style || 'default'
form.homepage_multi_thumb_enabled = d.homepage_multi_thumb_enabled !== false
form.homepage_multi_thumb_min_images = d.homepage_multi_thumb_min_images || 3
form.homepage_sidebar_mini_enabled = d.homepage_sidebar_mini_enabled !== false
form.homepage_default_sort = d.homepage_default_sort || 'modified'
form.homepage_default_view = d.homepage_default_view || 'list'
form.homepage_sort_ajax_enabled = d.homepage_sort_ajax_enabled !== false
form.homepage_sticky_tabs_enabled = d.homepage_sticky_tabs_enabled !== false
form.home_posts_list_enabled = d.home_posts_list_enabled !== false
form.home_list_title = d.home_list_title || '最新发布'
form.home_list_sort_enabled = d.home_list_sort_enabled !== false
form.home_list_sort_options = Array.isArray(d.home_list_sort_options) && d.home_list_sort_options.length
? d.home_list_sort_options
: ['modified', 'date', 'views', 'likes', 'comments']
form.home_list_sort_dropdown = !!d.home_list_sort_dropdown
form.home_exclude_post_ids = Array.isArray(d.home_exclude_post_ids) ? d.home_exclude_post_ids : []
form.home_exclude_category_ids = Array.isArray(d.home_exclude_category_ids) ? d.home_exclude_category_ids : []
form.homepage_tab_posts_per_page = d.homepage_tab_posts_per_page || 6
form.homepage_tab_limit = d.homepage_tab_limit || 4
} catch (error) {
} catch (error) {
message.error(error.message || '加载设置失败')
} finally {
loading.value = false
@@ -941,7 +941,7 @@ export const pageDisplaySchemas = {
homepage_default_view: 'list',
homepage_sort_ajax_enabled: true,
homepage_sticky_tabs_enabled: true,
home_posts_list_enabled: true,
home_posts_list_s: true,
home_list_title: '最新发布',
home_list_sort_enabled: true,
home_list_sort_options: ['modified', 'date', 'views', 'likes', 'comments'],
@@ -975,12 +975,12 @@ export const pageDisplaySchemas = {
title: '主列表',
icon: 'fas fa-list',
fields: [
{ key: 'home_posts_list_enabled', label: '启用主列表', type: 'switch', default: true },
{ key: 'home_list_title', label: '区块标题', type: 'input', default: '最新发布', dependsOn: { key: 'home_posts_list_enabled', value: true } },
{ key: 'homepage_default_sort', label: '默认排序', type: 'select', default: 'modified', dependsOn: { key: 'home_posts_list_enabled', value: true }, options: sortOptions },
{ key: 'home_list_sort_enabled', label: '启用排序栏', type: 'switch', default: true, dependsOn: { key: 'home_posts_list_enabled', value: true } },
{ key: 'home_list_sort_dropdown', label: '排序栏下拉模式', type: 'switch', default: false, dependsOn: { key: 'home_list_sort_enabled', value: true } },
{ key: 'home_list_sort_options', label: '可用排序选项', type: 'checkbox', default: ['modified', 'date', 'views', 'likes', 'comments'], dependsOn: { key: 'home_list_sort_enabled', value: true }, options: sortOptions },
{ key: 'home_posts_list_s', label: '启用主列表', type: 'switch', default: true },
{ key: 'index_list_title', label: '区块标题', type: 'input', default: '最新发布', dependsOn: { key: 'home_posts_list_s', value: true } },
{ key: 'home_list1_orderby_option.orderby', label: '默认排序', type: 'select', default: 'modified', dependsOn: { key: 'home_posts_list_s', value: true }, options: sortOptions },
{ key: 'home_list1_orderby_s', label: '启用排序栏', type: 'switch', default: true, dependsOn: { key: 'home_posts_list_s', value: true } },
{ key: 'home_list_sort_dropdown', label: '排序栏下拉模式', type: 'switch', default: false, dependsOn: { key: 'home_list1_orderby_s', value: true } },
{ key: 'home_list1_orderby_option', label: '可用排序选项', type: 'checkbox', default: ['modified', 'date', 'views', 'likes', 'comments'], dependsOn: { key: 'home_list1_orderby_s', value: true }, options: sortOptions },
],
},
{
@@ -988,8 +988,8 @@ export const pageDisplaySchemas = {
title: '排除规则',
icon: 'fas fa-filter',
fields: [
{ key: 'home_exclude_post_ids', label: '排除文章 ID', type: 'array', default: [], help: '主列表和 Tab 查询均排除这些文章。' },
{ key: 'home_exclude_category_ids', label: '排除分类 ID', type: 'array', default: [], help: '主列表排除这些分类。' },
{ key: 'home_exclude_posts', label: '排除文章 ID', type: 'array', default: [], help: '主列表和 Tab 查询均排除这些文章。' },
{ key: 'home_exclude_cats', label: '排除分类 ID', type: 'array', default: [], help: '主列表排除这些分类。' },
],
},
{
@@ -997,7 +997,7 @@ export const pageDisplaySchemas = {
title: '首页 Tab',
icon: 'fas fa-tags',
fields: [
{ key: 'homepage_tabs', label: '首页 Tab', type: 'array', default: [], help: '分类 Tab 由 HomepageSettings.vue 中的可视化编辑器维护。' },
{ key: 'home_lists', label: '首页 Tab', type: 'array', default: [], help: '分类 Tab 由 HomepageSettings.vue 中的可视化编辑器维护。' },
{ key: 'homepage_tab_limit', label: 'Tab 数量上限', type: 'number', default: 4, min: 1, max: 12 },
{ key: 'homepage_tab_posts_per_page', label: '每 Tab 文章数', type: 'number', default: 6, min: 1, max: 20 },
{ key: 'homepage_sticky_tabs_enabled', label: 'Tab 吸顶', type: 'switch', default: true },