Zibll 主线收口:统一 single 并清退 compat 资源路径
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,9 +2,8 @@
|
||||
/**
|
||||
* Resource Archive Template
|
||||
*
|
||||
* 资源归档页(/resources)。
|
||||
* v3.4 起:作为「资源虚拟归档」(post + _aksrt_is_resource) 的渲染模板,
|
||||
* 兼容历史 aksrt_resource CPT 归档。
|
||||
* 统一资源归档页(/resources)。
|
||||
* 渲染资源虚拟归档 (post + _aksrt_is_resource) 与历史 aksrt_resource CPT 内容。
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="aksrt-page-container content-page">
|
||||
<PageHeader
|
||||
title="首页配置"
|
||||
desc="配置首页内容模型、模块编排、分类 Tab、卡片样式和交互方式。"
|
||||
desc="按 Zibll 首页主线配置内容模型、Tab、主列表、卡片样式与基础交互。"
|
||||
>
|
||||
<template #actions>
|
||||
<n-button type="primary" :loading="saving" @click="handleSave">保存设置</n-button>
|
||||
@@ -10,65 +10,39 @@
|
||||
</PageHeader>
|
||||
|
||||
<n-tabs v-model:value="activeTab" type="line" animated>
|
||||
<!-- Module Workstation Tab -->
|
||||
<n-tab-pane name="modules" tab="模块编排">
|
||||
<div class="aksrt-homepage__workstation">
|
||||
<div class="aksrt-homepage__canvas-panel">
|
||||
<ModuleCanvas
|
||||
:modules="homeModules"
|
||||
:selected-index="selectedModuleIndex"
|
||||
@select="selectedModuleIndex = $event"
|
||||
@add="handleAddModule"
|
||||
@remove="handleRemoveModule"
|
||||
@copy="handleCopyModule"
|
||||
@toggle="handleToggleModule"
|
||||
@move="handleMoveModule"
|
||||
@pick-preset="showPresetPicker = true"
|
||||
@export="handleExportModules"
|
||||
@import="showImportDialog = true"
|
||||
/>
|
||||
</div>
|
||||
<div class="aksrt-homepage__inspector-panel">
|
||||
<ModuleInspector
|
||||
:module="selectedModule"
|
||||
:module-index="selectedModuleIndex"
|
||||
@update="handleModuleUpdate"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</n-tab-pane>
|
||||
|
||||
<!-- Main Stream & Tabs Tab -->
|
||||
<n-tab-pane name="stream" tab="主列表 & Tab">
|
||||
<n-spin :show="loading" style="width:100%; min-height:200px;">
|
||||
<!-- Content Model -->
|
||||
<n-card class="aksrt-section-card" style="margin-bottom:16px;">
|
||||
<template #header><strong>内容模型</strong></template>
|
||||
<template #header><strong>首页模型</strong></template>
|
||||
<n-form :model="form" label-placement="left" label-width="160" class="aksrt-form">
|
||||
<n-form-item label="首页内容模型">
|
||||
<n-radio-group v-model:value="form.homepage_content_model">
|
||||
<n-space vertical>
|
||||
<n-radio value="mixed">
|
||||
<n-text>混合模式</n-text>
|
||||
<n-text depth="3" style="margin-left:8px;">文章 + 资源(默认)</n-text>
|
||||
<n-text>混合内容流</n-text>
|
||||
<n-text depth="3" style="margin-left:8px;">文章 + 资源,贴近 Zibll 首页主流呈现。</n-text>
|
||||
</n-radio>
|
||||
<n-radio value="post">
|
||||
<n-text>纯文章</n-text>
|
||||
<n-text depth="3" style="margin-left:8px;">仅标准文章</n-text>
|
||||
<n-text>纯文章流</n-text>
|
||||
<n-text depth="3" style="margin-left:8px;">仅标准文章,适合纯资讯站点。</n-text>
|
||||
</n-radio>
|
||||
</n-space>
|
||||
</n-radio-group>
|
||||
</n-form-item>
|
||||
<n-form-item label="首页说明">
|
||||
<n-alert type="info" :show-icon="false">
|
||||
当前首页已切换为固定骨架模式,不再使用旧版自由模块画布、导入导出预设或历史模块桥接。
|
||||
</n-alert>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-card>
|
||||
|
||||
<!-- Main Stream -->
|
||||
<n-card class="aksrt-section-card" style="margin-bottom:16px;">
|
||||
<template #header><strong>主列表(最新发布)</strong></template>
|
||||
<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" />
|
||||
<template #feedback><span class="aksrt-hint-text">关闭后首页将不显示文章列表(仅显示模块)。</span></template>
|
||||
<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="最新发布" />
|
||||
@@ -98,7 +72,6 @@
|
||||
</n-form>
|
||||
</n-card>
|
||||
|
||||
<!-- Exclusions -->
|
||||
<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">
|
||||
@@ -109,7 +82,7 @@
|
||||
placeholder="逗号分隔的文章 ID,如 12,34,56"
|
||||
:rows="2"
|
||||
/>
|
||||
<template #feedback><span class="aksrt-hint-text">主列表和 Tab 查询均排除这些文章。</span></template>
|
||||
<template #feedback><span class="aksrt-hint-text">主列表和首页 Tab 查询均排除这些文章。</span></template>
|
||||
</n-form-item>
|
||||
<n-form-item label="排除分类 ID">
|
||||
<n-input
|
||||
@@ -118,12 +91,11 @@
|
||||
placeholder="逗号分隔的分类 ID,如 5,8"
|
||||
:rows="2"
|
||||
/>
|
||||
<template #feedback><span class="aksrt-hint-text">主列表排除这些分类。Tab 不能绑定已排除的分类。</span></template>
|
||||
<template #feedback><span class="aksrt-hint-text">主列表排除这些分类,首页 Tab 不能绑定已排除分类。</span></template>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-card>
|
||||
|
||||
<!-- Tabs -->
|
||||
<n-card class="aksrt-section-card" style="margin-bottom:16px;">
|
||||
<template #header>
|
||||
<div style="display:flex; align-items:center; justify-content:space-between;">
|
||||
@@ -141,7 +113,7 @@
|
||||
</n-form>
|
||||
|
||||
<div v-if="form.homepage_tabs.length === 0" class="homepage-settings__empty-tabs">
|
||||
<n-text depth="3">暂无 Tab 配置,点击"添加 Tab"添加。</n-text>
|
||||
<n-text depth="3">暂无 Tab 配置,点击“添加 Tab”创建首页分类切换。</n-text>
|
||||
</div>
|
||||
|
||||
<div v-for="(tab, index) in form.homepage_tabs" :key="index" class="homepage-settings__tab-row">
|
||||
@@ -177,8 +149,7 @@
|
||||
</n-spin>
|
||||
</n-tab-pane>
|
||||
|
||||
<!-- Cards & Sidebar Tab -->
|
||||
<n-tab-pane name="cards" tab="卡片 & 侧栏">
|
||||
<n-tab-pane name="cards" tab="卡片 & 交互">
|
||||
<n-spin :show="loading" style="width:100%; min-height:200px;">
|
||||
<n-card class="aksrt-section-card" style="margin-bottom:16px;">
|
||||
<template #header><strong>卡片样式</strong></template>
|
||||
@@ -210,74 +181,36 @@
|
||||
</n-card>
|
||||
|
||||
<n-card class="aksrt-section-card" style="margin-bottom:16px;">
|
||||
<template #header><strong>侧边栏</strong></template>
|
||||
<template #header><strong>交互设置</strong></template>
|
||||
<n-form :model="form" label-placement="left" label-width="160" class="aksrt-form">
|
||||
<n-form-item label="排序栏 AJAX">
|
||||
<n-switch v-model:value="form.homepage_sort_ajax_enabled" />
|
||||
<template #feedback><span class="aksrt-hint-text">关闭后排序链接使用整页跳转。</span></template>
|
||||
</n-form-item>
|
||||
<n-form-item label="Tab 吸顶">
|
||||
<n-switch v-model:value="form.homepage_sticky_tabs_enabled" />
|
||||
</n-form-item>
|
||||
<n-form-item label="迷你侧栏列表">
|
||||
<n-switch v-model:value="form.homepage_sidebar_mini_enabled" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-card>
|
||||
|
||||
<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="排序栏 AJAX">
|
||||
<n-switch v-model:value="form.homepage_sort_ajax_enabled" />
|
||||
<template #feedback><span class="aksrt-hint-text">关闭后排序链接将使用整页跳转。</span></template>
|
||||
</n-form-item>
|
||||
<n-form-item label="Tab 吸顶">
|
||||
<n-switch v-model:value="form.homepage_sticky_tabs_enabled" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-card>
|
||||
|
||||
<!-- Module Status -->
|
||||
<n-card class="aksrt-section-card">
|
||||
<template #header><strong>模块状态</strong></template>
|
||||
<n-form label-placement="left" label-width="160" class="aksrt-form">
|
||||
<n-form-item label="Hero 首屏">
|
||||
<n-tag type="info" size="small">在 Hero 页面管理</n-tag>
|
||||
<n-text depth="3" style="margin-left:8px;">首页 Hero 开关已从首页设置中移出。</n-text>
|
||||
</n-form-item>
|
||||
<n-form-item label="Banner 轮播">
|
||||
<n-tag type="info" size="small">在 Banner 页面管理</n-tag>
|
||||
<n-text depth="3" style="margin-left:8px;">首页 Banner 开关已从首页设置中移出。</n-text>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<template #header><strong>固定骨架说明</strong></template>
|
||||
<n-space vertical>
|
||||
<n-alert type="warning" :show-icon="false">
|
||||
Hero 与 Banner 已作为固定首页骨架的一部分维护,不再由旧版首页模块编排驱动。
|
||||
</n-alert>
|
||||
<n-alert type="info" :show-icon="false">
|
||||
如需调整首页首屏运营区,请前往对应 Hero / Banner 管理页,而不是返回旧模块工作台。
|
||||
</n-alert>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-spin>
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
|
||||
<!-- Preset Picker Dialog -->
|
||||
<ModulePresetPicker
|
||||
:show="showPresetPicker"
|
||||
@close="showPresetPicker = false"
|
||||
@apply="handleApplyPreset"
|
||||
/>
|
||||
|
||||
<!-- Import Dialog -->
|
||||
<n-modal
|
||||
v-model:show="showImportDialog"
|
||||
title="导入模块配置"
|
||||
preset="dialog"
|
||||
style="width: 480px;"
|
||||
:show-icon="false"
|
||||
>
|
||||
<n-input
|
||||
v-model:value="importJson"
|
||||
type="textarea"
|
||||
:rows="8"
|
||||
placeholder="粘贴导出的 JSON 配置..."
|
||||
/>
|
||||
<template #action>
|
||||
<n-space>
|
||||
<n-button @click="showImportDialog = false">取消</n-button>
|
||||
<n-button type="primary" :disabled="!importJson.trim()" @click="handleImportModules">导入</n-button>
|
||||
</n-space>
|
||||
</template>
|
||||
</n-modal>
|
||||
|
||||
<div class="aksrt-form-actions">
|
||||
<n-button type="primary" :loading="saving" @click="handleSave">保存设置</n-button>
|
||||
</div>
|
||||
@@ -285,34 +218,16 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { computed, onMounted, reactive, ref } from 'vue'
|
||||
import { useMessage } from 'naive-ui'
|
||||
import api from '@/api'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
import ModuleCanvas from '@/components/homepage/ModuleCanvas.vue'
|
||||
import ModuleInspector from '@/components/homepage/ModuleInspector.vue'
|
||||
import ModulePresetPicker from '@/components/homepage/ModulePresetPicker.vue'
|
||||
import { makeDefaultModule } from '@/utils/home-module-schema'
|
||||
|
||||
const message = useMessage()
|
||||
const loading = ref(true)
|
||||
const saving = ref(false)
|
||||
const activeTab = ref('modules')
|
||||
const activeTab = ref('stream')
|
||||
const categoryOptions = ref([])
|
||||
const showPresetPicker = ref(false)
|
||||
const showImportDialog = ref(false)
|
||||
const importJson = ref('')
|
||||
|
||||
// Module workstation state
|
||||
const homeModules = ref([])
|
||||
const selectedModuleIndex = ref(-1)
|
||||
|
||||
const selectedModule = computed(() => {
|
||||
if (selectedModuleIndex.value >= 0 && selectedModuleIndex.value < homeModules.value.length) {
|
||||
return homeModules.value[selectedModuleIndex.value]
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
const allSortOptions = [
|
||||
{ label: '最近更新', value: 'modified' },
|
||||
@@ -361,116 +276,6 @@ const excludeCategoryIdsText = computed({
|
||||
},
|
||||
})
|
||||
|
||||
// Module operations
|
||||
function handleAddModule(type) {
|
||||
const newMod = makeDefaultModule(type)
|
||||
if (newMod) {
|
||||
newMod.id = 'mod_' + Date.now() + '_' + Math.random().toString(36).slice(2, 6)
|
||||
newMod.enabled = true
|
||||
newMod.title = ''
|
||||
homeModules.value.push(newMod)
|
||||
selectedModuleIndex.value = homeModules.value.length - 1
|
||||
}
|
||||
}
|
||||
|
||||
function handleRemoveModule(index) {
|
||||
homeModules.value.splice(index, 1)
|
||||
if (selectedModuleIndex.value >= homeModules.value.length) {
|
||||
selectedModuleIndex.value = homeModules.value.length - 1
|
||||
}
|
||||
}
|
||||
|
||||
function handleCopyModule(index) {
|
||||
const src = homeModules.value[index]
|
||||
if (!src) return
|
||||
const copy = JSON.parse(JSON.stringify(src))
|
||||
copy.id = 'mod_' + Date.now() + '_' + Math.random().toString(36).slice(2, 6)
|
||||
homeModules.value.splice(index + 1, 0, copy)
|
||||
selectedModuleIndex.value = index + 1
|
||||
}
|
||||
|
||||
function handleToggleModule(index, val) {
|
||||
if (homeModules.value[index]) {
|
||||
homeModules.value[index].enabled = val
|
||||
}
|
||||
}
|
||||
|
||||
function handleMoveModule(index, direction) {
|
||||
const newIndex = index + direction
|
||||
if (newIndex < 0 || newIndex >= homeModules.value.length) return
|
||||
const temp = homeModules.value[index]
|
||||
homeModules.value[index] = homeModules.value[newIndex]
|
||||
homeModules.value[newIndex] = temp
|
||||
// Trigger reactivity
|
||||
homeModules.value = [...homeModules.value]
|
||||
selectedModuleIndex.value = newIndex
|
||||
}
|
||||
|
||||
function handleModuleUpdate(index, key, value) {
|
||||
if (homeModules.value[index]) {
|
||||
if (key === 'config') {
|
||||
homeModules.value[index].config = value
|
||||
} else {
|
||||
homeModules.value[index][key] = value
|
||||
}
|
||||
// Trigger reactivity
|
||||
homeModules.value = [...homeModules.value]
|
||||
}
|
||||
}
|
||||
|
||||
function handleApplyPreset(preset) {
|
||||
homeModules.value = preset.modules.map((m, i) => ({
|
||||
id: 'mod_' + Date.now() + '_' + i,
|
||||
type: m.type,
|
||||
config: JSON.parse(JSON.stringify(m.config || {})),
|
||||
enabled: true,
|
||||
title: '',
|
||||
}))
|
||||
selectedModuleIndex.value = -1
|
||||
showPresetPicker.value = false
|
||||
message.success(`已应用预设「${preset.label}」,共 ${preset.modules.length} 个模块`)
|
||||
}
|
||||
|
||||
function handleExportModules() {
|
||||
const json = JSON.stringify(homeModules.value, null, 2)
|
||||
navigator.clipboard.writeText(json).then(() => {
|
||||
message.success('模块配置已复制到剪贴板')
|
||||
}).catch(() => {
|
||||
// Fallback: show in a dialog
|
||||
const blob = new Blob([json], { type: 'application/json' })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
a.download = 'homepage-modules.json'
|
||||
a.click()
|
||||
URL.revokeObjectURL(url)
|
||||
message.success('模块配置已导出')
|
||||
})
|
||||
}
|
||||
|
||||
function handleImportModules() {
|
||||
try {
|
||||
const parsed = JSON.parse(importJson.value)
|
||||
if (!Array.isArray(parsed)) {
|
||||
throw new Error('JSON 必须是数组格式')
|
||||
}
|
||||
homeModules.value = parsed.map((m, i) => ({
|
||||
id: m.id || 'mod_' + Date.now() + '_' + i,
|
||||
type: m.type,
|
||||
config: m.config || {},
|
||||
enabled: m.enabled !== false,
|
||||
title: m.title || '',
|
||||
}))
|
||||
selectedModuleIndex.value = -1
|
||||
showImportDialog.value = false
|
||||
importJson.value = ''
|
||||
message.success(`已导入 ${homeModules.value.length} 个模块`)
|
||||
} catch (err) {
|
||||
message.error('导入失败: ' + (err.message || 'JSON 格式错误'))
|
||||
}
|
||||
}
|
||||
|
||||
// Tab operations
|
||||
function addTab() {
|
||||
form.homepage_tabs.push({ term_id: 0, title: '', orderby: 'date', enabled: true })
|
||||
}
|
||||
@@ -483,7 +288,6 @@ function updateTab(index, field, value) {
|
||||
form.homepage_tabs[index][field] = value
|
||||
}
|
||||
|
||||
// Data loading
|
||||
async function loadCategories() {
|
||||
try {
|
||||
const res = await api.getHomepageCategories()
|
||||
@@ -492,7 +296,9 @@ async function loadCategories() {
|
||||
label: `${c.name} (${c.count})`,
|
||||
value: c.term_id,
|
||||
}))
|
||||
} catch { /* non-critical */ }
|
||||
} catch {
|
||||
// non-critical
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSettings() {
|
||||
@@ -522,15 +328,6 @@ async function loadSettings() {
|
||||
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
|
||||
|
||||
// Load modules
|
||||
homeModules.value = Array.isArray(d.homepage_modules) ? d.homepage_modules.map((m, i) => ({
|
||||
id: m.id || 'mod_' + i,
|
||||
type: m.type,
|
||||
config: m.config || {},
|
||||
enabled: m.enabled !== false,
|
||||
title: m.title || '',
|
||||
})) : []
|
||||
} catch (error) {
|
||||
message.error(error.message || '加载设置失败')
|
||||
} finally {
|
||||
@@ -543,13 +340,6 @@ async function handleSave() {
|
||||
try {
|
||||
const payload = {
|
||||
...form,
|
||||
homepage_modules: homeModules.value.map(m => ({
|
||||
id: m.id,
|
||||
type: m.type,
|
||||
config: m.config,
|
||||
enabled: m.enabled !== false,
|
||||
title: m.title || '',
|
||||
})),
|
||||
}
|
||||
|
||||
const res = await api.saveHomepageSettings(payload)
|
||||
@@ -572,26 +362,6 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.aksrt-homepage__workstation {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.aksrt-homepage__canvas-panel {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.aksrt-homepage__inspector-panel {
|
||||
width: 360px;
|
||||
flex-shrink: 0;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.homepage-settings__empty-tabs {
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
|
||||
@@ -57,7 +57,7 @@ export const orderSchema = {
|
||||
icon: 'fas fa-eye',
|
||||
fields: [
|
||||
{ key: 'payment_mark', label: '付费标记', type: 'input', default: '付费' },
|
||||
{ key: 'payment_box_position', label: '付费框位置', type: 'radio', default: 'top', options: [{ label: '文章模块上', value: 'box_top' }, { label: '内容顶', value: 'top' }, { label: '内容底', value: 'bottom' }, { label: '模块下', value: 'box_bottom' }] },
|
||||
{ key: 'payment_box_position', label: '付费框位置', type: 'radio', default: 'top', options: [{ label: '内容顶部(正文前)', value: 'top' }, { label: '内容底部(正文后)', value: 'bottom' }] },
|
||||
{ key: 'payment_free_logged_show', label: '登录用户显示免费', type: 'switch', default: false },
|
||||
{ key: 'payment_show_ip', label: '显示用户IP', type: 'switch', default: false },
|
||||
{ key: 'payment_show_device', label: '显示设备信息', type: 'switch', default: false },
|
||||
|
||||
@@ -51,7 +51,7 @@ export const paidSchema = {
|
||||
{ key: 'payment_currency_symbol', label: '货币符号', type: 'input', default: '¥', help: '商品价格前缀,如 ¥、$、¥' },
|
||||
{ key: 'payment_paid_show_user', label: '显示购买用户', type: 'switch', default: true },
|
||||
{ key: 'payment_paid_show_paycount', label: '显示购买次数', type: 'switch', default: true },
|
||||
{ key: 'payment_paid_box_position', label: '付费框位置', type: 'radio', default: 'top', options: [{ label: '文章模块上', value: 'box_top' }, { label: '内容顶', value: 'top' }, { label: '内容底', value: 'bottom' }, { label: '模块下', value: 'box_bottom' }] },
|
||||
{ key: 'payment_paid_box_position', label: '付费框位置', type: 'radio', default: 'top', options: [{ label: '内容顶部(正文前)', value: 'top' }, { label: '内容底部(正文后)', value: 'bottom' }] },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -196,39 +196,33 @@
|
||||
|
||||
.aksrt-homepage__stream-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
margin-bottom: 14px;
|
||||
gap: 12px;
|
||||
margin-bottom: 10px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.aksrt-homepage__stream-intro {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.aksrt-homepage__stream-kicker {
|
||||
margin-bottom: 6px;
|
||||
color: var(--color-primary, var(--color-primary));
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.aksrt-homepage__stream-title {
|
||||
margin: 0;
|
||||
color: var(--color-ink);
|
||||
font-size: 24px;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.aksrt-homepage__stream-subtitle {
|
||||
margin: 8px 0 0;
|
||||
margin: 0;
|
||||
color: var(--color-ink-3, #777);
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.aksrt-homepage__stream,
|
||||
@@ -248,7 +242,7 @@
|
||||
|
||||
.aksrt-homepage__tabs,
|
||||
.aksrt-homepage__titlebox {
|
||||
margin-bottom: 10px;
|
||||
margin-bottom: 6px;
|
||||
padding-bottom: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
@@ -380,18 +374,12 @@ html.dark .aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-aff
|
||||
.aksrt-homepage__sortbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
margin-bottom: 16px;
|
||||
padding: 2px 0 14px;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 0 0 8px;
|
||||
border-bottom: 1px solid var(--color-line, rgba(50, 50, 50, 0.06));
|
||||
color: var(--color-ink-3, #777);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.aksrt-homepage__sortbar-label {
|
||||
flex: 0 0 auto;
|
||||
color: var(--color-ink);
|
||||
font-weight: 700;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.aksrt-homepage__sortbar-links {
|
||||
|
||||
+14
-29
@@ -2,45 +2,30 @@
|
||||
/**
|
||||
* Homepage entry template.
|
||||
*
|
||||
* Front page requests are always delegated to the fixed homepage skeleton so
|
||||
* the site reads as a primary Zibll-style operation hub instead of a page body.
|
||||
* The rebuild treats the fixed homepage skeleton as the only supported front-page
|
||||
* experience. Static page-body fallback is intentionally removed so the site
|
||||
* always lands on the Zibll-style operation hub.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
if (function_exists('aksrt_render_fixed_homepage') && aksrt_render_fixed_homepage()) {
|
||||
return;
|
||||
}
|
||||
|
||||
get_header();
|
||||
?>
|
||||
|
||||
if (function_exists('aksrt_homepage_render_layout')) {
|
||||
aksrt_homepage_render_layout();
|
||||
} else {
|
||||
?>
|
||||
<main id="main-content" class="site-main content-shell" tabindex="-1">
|
||||
<?php $has_sidebar = is_active_sidebar('sidebar-blog'); ?>
|
||||
<div class="content-layout<?php echo $has_sidebar ? '' : ' content-layout--no-sidebar'; ?>">
|
||||
<div class="content-layout content-layout--no-sidebar">
|
||||
<div class="content-layout__primary">
|
||||
<?php
|
||||
while ( have_posts() ) :
|
||||
the_post();
|
||||
?>
|
||||
<article <?php post_class(); ?>>
|
||||
<header class="entry-header">
|
||||
<h1 class="entry-title"><?php the_title(); ?></h1>
|
||||
</header>
|
||||
<div class="entry-content">
|
||||
<?php the_content(); ?>
|
||||
<section class="widget widget-card box-body">
|
||||
<h1 class="entry-title"><?php esc_html_e('首页骨架未加载', 'aksrt'); ?></h1>
|
||||
<p><?php esc_html_e('固定首页骨架当前不可用,请检查主题加载链路。', 'aksrt'); ?></p>
|
||||
</section>
|
||||
</div>
|
||||
</article>
|
||||
<?php
|
||||
endwhile;
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php if ($has_sidebar) : ?>
|
||||
<?php get_sidebar(); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
get_footer();
|
||||
|
||||
@@ -307,16 +307,6 @@ if (class_exists('AKSRT_User_Credits_Admin')) {
|
||||
AKSRT_User_Credits_Admin::get_instance()->init();
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Homepage data model migration: legacy module tabs -> structured homepage_tabs
|
||||
// Idempotent; runs once on first admin visit.
|
||||
// ============================================================
|
||||
if (is_admin() && class_exists('AKSRT_Settings')) {
|
||||
add_action('admin_init', function () {
|
||||
AKSRT_Settings::maybe_migrate_homepage_tabs();
|
||||
}, 5);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 主题删除时的数据库清理(仅在用户启用清理选项时生效)
|
||||
// uninstall.php 会检查 aksrt_cleanup_on_uninstall 选项
|
||||
|
||||
+7
-5
@@ -138,10 +138,8 @@ if (!empty($aksrt_bg_styles)) {
|
||||
$aksrt_mobile_menu_location = has_nav_menu('mobile') ? 'mobile' : 'primary';
|
||||
$aksrt_show_user_entry = !empty($aksrt_header_settings['user_menu']);
|
||||
$aksrt_current_user = wp_get_current_user();
|
||||
$aksrt_user_unread = class_exists('AKSRT_Message') && is_user_logged_in() ? (int) AKSRT_Message::get_instance()->get_unread_count(get_current_user_id()) : 0;
|
||||
$aksrt_user_credit = function_exists('aksrt_user_credits') && is_user_logged_in() ? (int) aksrt_user_credits(get_current_user_id()) : 0;
|
||||
$aksrt_currency_name = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name() : __('积分', 'aksrt');
|
||||
$aksrt_messages_url = function_exists('aksrt_get_messages_url') ? aksrt_get_messages_url() : home_url('/messages/');
|
||||
$aksrt_orders_url = home_url('/orders/');
|
||||
$aksrt_publish_url = admin_url('post-new.php');
|
||||
$aksrt_theme_toggle_positions = class_exists('AKSRT_Settings')
|
||||
@@ -219,7 +217,7 @@ if (!empty($aksrt_bg_styles)) {
|
||||
?>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="nav-actions">
|
||||
<div class="nav-actions nav-actions--primary">
|
||||
<?php if (!empty($aksrt_header_settings['search_enabled'])) : ?>
|
||||
<form role="search" method="get" class="nav-searchbox" action="<?php echo esc_url(home_url('/')); ?>" data-aksrt-search-form="desktop" data-default-search-type="<?php echo esc_attr($aksrt_search_type); ?>" data-default-category="<?php echo esc_attr((string) $aksrt_search_category_id); ?>">
|
||||
<input type="hidden" name="aksrt_search_type" value="<?php echo esc_attr($aksrt_search_type); ?>">
|
||||
@@ -232,6 +230,7 @@ if (!empty($aksrt_bg_styles)) {
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="nav-actions__cta">
|
||||
<?php if ($aksrt_can_publish) : ?>
|
||||
<a class="btn-primary" href="<?php echo esc_url(admin_url('post-new.php')); ?>">
|
||||
<i class="fas fa-pen-nib" aria-hidden="true"></i>
|
||||
@@ -244,6 +243,7 @@ if (!empty($aksrt_bg_styles)) {
|
||||
<i class="fas fa-adjust" aria-hidden="true"></i>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($aksrt_show_user_entry) : ?>
|
||||
<?php if (is_user_logged_in()) : ?>
|
||||
@@ -266,9 +266,10 @@ if (!empty($aksrt_bg_styles)) {
|
||||
</div>
|
||||
<div class="user-dropdown__sep"></div>
|
||||
<a class="user-dropdown__item header-user-href" href="<?php echo esc_url(aksrt_get_user_center_url()); ?>"><span><?php esc_html_e('用户中心', 'aksrt'); ?></span></a>
|
||||
<a class="user-dropdown__item header-user-href" href="<?php echo esc_url($aksrt_messages_url); ?>"><span><?php esc_html_e('消息通知', 'aksrt'); ?></span><?php if ($aksrt_user_unread > 0) : ?><span class="user-dropdown__badge"><?php echo esc_html((string) $aksrt_user_unread); ?></span><?php endif; ?></a>
|
||||
<a class="user-dropdown__item header-user-href" href="<?php echo esc_url($aksrt_orders_url); ?>"><span><?php esc_html_e('我的订单', 'aksrt'); ?></span></a>
|
||||
<?php if ($aksrt_can_publish) : ?>
|
||||
<a class="user-dropdown__item header-user-href" href="<?php echo esc_url($aksrt_publish_url); ?>"><span><?php esc_html_e('发布内容', 'aksrt'); ?></span></a>
|
||||
<?php endif; ?>
|
||||
<a class="user-dropdown__item user-dropdown__logout header-user-href" href="<?php echo esc_url(wp_logout_url(home_url('/'))); ?>"><span><?php esc_html_e('退出登录', 'aksrt'); ?></span></a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -367,7 +368,7 @@ if (!empty($aksrt_bg_styles)) {
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="nav-actions__cta nav-actions__cta--drawer">
|
||||
<?php if ($aksrt_can_publish) : ?>
|
||||
<div class="nav-drawer__publish">
|
||||
<a class="btn-primary" href="<?php echo esc_url(admin_url('post-new.php')); ?>">
|
||||
@@ -400,6 +401,7 @@ if (!empty($aksrt_bg_styles)) {
|
||||
<?php dynamic_sidebar('mobile_nav_fluid'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="fixed-body"></div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@@ -32,20 +32,6 @@ class AKSRT_Admin_Extension_Controller extends AKSRT_Admin_Controller_Base {
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Docs page stats
|
||||
register_rest_route(self::API_NAMESPACE, '/docs/stats', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_docs_stats'],
|
||||
'permission_callback' => [$this, 'check_permission'],
|
||||
]);
|
||||
|
||||
// Docs search (public, for frontend AJAX)
|
||||
register_rest_route(self::API_NAMESPACE, '/docs/search', [
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'search_docs'],
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
|
||||
// Extensions service status summary (aggregated)
|
||||
register_rest_route(self::API_NAMESPACE, '/settings/extensions', [
|
||||
'methods' => 'GET',
|
||||
@@ -126,36 +112,11 @@ class AKSRT_Admin_Extension_Controller extends AKSRT_Admin_Controller_Base {
|
||||
}
|
||||
|
||||
public function get_docs_stats(): WP_REST_Response {
|
||||
$nav_count = 0;
|
||||
$special_count = 0;
|
||||
|
||||
$nav_query = new WP_Query([
|
||||
'post_type' => 'page',
|
||||
'post_status' => 'publish',
|
||||
'meta_key' => '_wp_page_template',
|
||||
'meta_value' => 'templates/pages/page-documentnav.php',
|
||||
'posts_per_page' => 1,
|
||||
'fields' => 'ids',
|
||||
'no_found_rows' => false,
|
||||
]);
|
||||
$nav_count = (int) $nav_query->found_posts;
|
||||
|
||||
$special_query = new WP_Query([
|
||||
'post_type' => 'page',
|
||||
'post_status' => 'publish',
|
||||
'meta_key' => '_wp_page_template',
|
||||
'meta_value' => 'templates/pages/page-special.php',
|
||||
'posts_per_page' => 1,
|
||||
'fields' => 'ids',
|
||||
'no_found_rows' => false,
|
||||
]);
|
||||
$special_count = (int) $special_query->found_posts;
|
||||
|
||||
return $this->success([
|
||||
'data' => [
|
||||
'total' => $nav_count + $special_count,
|
||||
'nav_count' => $nav_count,
|
||||
'special_count' => $special_count,
|
||||
'total' => 0,
|
||||
'nav_count' => 0,
|
||||
'special_count' => 0,
|
||||
],
|
||||
]);
|
||||
}
|
||||
@@ -164,24 +125,10 @@ class AKSRT_Admin_Extension_Controller extends AKSRT_Admin_Controller_Base {
|
||||
* GET /docs/search — search document pages by keyword.
|
||||
*/
|
||||
public function search_docs(WP_REST_Request $request): WP_REST_Response {
|
||||
$keyword = trim(sanitize_text_field((string) $request->get_param('keyword')));
|
||||
$root_id = (int) $request->get_param('root_id');
|
||||
$limit = max(1, min(50, (int) ($request->get_param('limit') ?: 20)));
|
||||
|
||||
if ($keyword === '') {
|
||||
return $this->success(['data' => ['results' => [], 'total' => 0]]);
|
||||
}
|
||||
|
||||
if (!class_exists('AKSRT_Docs_Presenter')) {
|
||||
return $this->success(['data' => ['results' => [], 'total' => 0]]);
|
||||
}
|
||||
|
||||
$results = AKSRT_Docs_Presenter::get_instance()->search_pages($keyword, $root_id, $limit);
|
||||
|
||||
return $this->success([
|
||||
'data' => [
|
||||
'results' => $results,
|
||||
'total' => count($results),
|
||||
'results' => [],
|
||||
'total' => 0,
|
||||
],
|
||||
]);
|
||||
}
|
||||
@@ -439,13 +386,12 @@ class AKSRT_Admin_Extension_Controller extends AKSRT_Admin_Controller_Base {
|
||||
$services['push'] = ['enabled' => false, 'provider' => '', 'configured' => false, 'available' => false, 'verified' => false, 'transport' => '', 'missing_fields' => []];
|
||||
}
|
||||
|
||||
// Docs Mode
|
||||
$docs_en = !empty($settings['docs_mode_enabled']);
|
||||
// Docs Mode (compat path is retired from rebuilt mainline)
|
||||
$services['docs_mode'] = [
|
||||
'enabled' => $docs_en,
|
||||
'enabled' => false,
|
||||
'provider' => 'builtin',
|
||||
'configured' => $docs_en,
|
||||
'available' => $docs_en,
|
||||
'configured' => false,
|
||||
'available' => false,
|
||||
'verified' => true,
|
||||
'transport' => 'builtin',
|
||||
'missing_fields' => [],
|
||||
|
||||
@@ -9,7 +9,6 @@ trait AKSRT_Admin_Global_Controller_Part_2 {
|
||||
|
||||
if ($request->get_method() === 'GET') {
|
||||
$data = AKSRT_Settings::get_homepage_fixed_settings();
|
||||
$data['homepage_modules'] = AKSRT_Settings::get_homepage_modules();
|
||||
return rest_ensure_response([
|
||||
'code' => 'success',
|
||||
'data' => $data,
|
||||
@@ -104,30 +103,6 @@ trait AKSRT_Admin_Global_Controller_Part_2 {
|
||||
$settings['homepage_tabs'] = $tabs;
|
||||
}
|
||||
|
||||
if (isset($params['homepage_modules']) && is_array($params['homepage_modules'])) {
|
||||
$modules = [];
|
||||
$allowed_types = [
|
||||
'hero', 'banner', 'category', 'tabs', 'ranking', 'recent',
|
||||
'tag_cloud', 'friend_links', 'html', 'hotspot',
|
||||
'category_recommend_cards', 'text_title', 'button_group',
|
||||
'spacing', 'faq', 'data_grid', 'highlight_cards',
|
||||
'partner_marquee', 'product_showcase',
|
||||
];
|
||||
foreach ($params['homepage_modules'] as $module) {
|
||||
if (!is_array($module) || !in_array($module['type'] ?? '', $allowed_types, true)) {
|
||||
continue;
|
||||
}
|
||||
$modules[] = [
|
||||
'id' => sanitize_text_field($module['id'] ?? uniqid('mod_')),
|
||||
'type' => sanitize_text_field($module['type']),
|
||||
'config' => is_array($module['config'] ?? null) ? $module['config'] : [],
|
||||
'enabled' => !empty($module['enabled']),
|
||||
'title' => sanitize_text_field($module['title'] ?? ''),
|
||||
];
|
||||
}
|
||||
$settings['homepage_modules'] = $modules;
|
||||
}
|
||||
|
||||
$current = get_option($option_key, []);
|
||||
if (!is_array($current)) {
|
||||
$current = [];
|
||||
@@ -141,7 +116,6 @@ trait AKSRT_Admin_Global_Controller_Part_2 {
|
||||
AKSRT_Settings::flush_settings_cache();
|
||||
update_option('aksrt_homepage_schema_version', gmdate('Y-m-d'));
|
||||
delete_transient('aksrt_homepage_cached_images');
|
||||
delete_transient('aksrt_homepage_modules_cache');
|
||||
do_action('aksrt_homepage_settings_changed');
|
||||
|
||||
return rest_ensure_response([
|
||||
|
||||
@@ -35,10 +35,8 @@ class AKSRT_Admin_Schema_Payment {
|
||||
['key' => 'payment_paid_show_user', 'label' => '显示购买用户', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'payment_paid_show_paycount', 'label' => '显示购买次数', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'payment_paid_box_position', 'label' => '付费框位置', 'type' => 'radio', 'default' => 'top', 'options' => [
|
||||
['label' => '文章模块上', 'value' => 'box_top'],
|
||||
['label' => '内容顶', 'value' => 'top'],
|
||||
['label' => '内容底', 'value' => 'bottom'],
|
||||
['label' => '模块下', 'value' => 'box_bottom'],
|
||||
['label' => '内容顶部(正文前)', 'value' => 'top'],
|
||||
['label' => '内容底部(正文后)', 'value' => 'bottom'],
|
||||
]],
|
||||
]],
|
||||
['key' => 'download', 'title' => '下载能力', 'fields' => [
|
||||
@@ -294,10 +292,8 @@ class AKSRT_Admin_Schema_Payment {
|
||||
['key' => 'display', 'title' => '展示设置', 'fields' => [
|
||||
['key' => 'payment_mark', 'label' => '付费标记', 'type' => 'input', 'default' => '付费'],
|
||||
['key' => 'payment_box_position', 'label' => '付费框位置', 'type' => 'radio', 'default' => 'top', 'options' => [
|
||||
['label' => '文章模块上', 'value' => 'box_top'],
|
||||
['label' => '内容顶', 'value' => 'top'],
|
||||
['label' => '内容底', 'value' => 'bottom'],
|
||||
['label' => '模块下', 'value' => 'box_bottom'],
|
||||
['label' => '内容顶部(正文前)', 'value' => 'top'],
|
||||
['label' => '内容底部(正文后)', 'value' => 'bottom'],
|
||||
]],
|
||||
['key' => 'payment_free_logged_show', 'label' => '登录用户显示免费', 'type' => 'switch', 'default' => false],
|
||||
['key' => 'payment_show_ip', 'label' => '显示用户IP', 'type' => 'switch', 'default' => false],
|
||||
|
||||
@@ -214,19 +214,6 @@ class AKSRT_Docs_Presenter {
|
||||
* @return bool
|
||||
*/
|
||||
public function is_docs_page(int $page_id): bool {
|
||||
if (!class_exists('AKSRT_Settings')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$settings = AKSRT_Settings::get_docs_mode_settings();
|
||||
if (empty($settings['enabled'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$template = get_page_template_slug($page_id);
|
||||
return in_array($template, [
|
||||
'templates/pages/page-documentnav.php',
|
||||
'templates/pages/page-special.php',
|
||||
], true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +33,9 @@ class AKSRT_Templates {
|
||||
}
|
||||
|
||||
/**
|
||||
* 主线页面模板:内容 / 用户 / 付费 / 论坛 / 商城主线可选模板。
|
||||
* Selectable page templates shown in wp-admin for the rebuilt mainline.
|
||||
*/
|
||||
private function mainline_page_template_map(): array {
|
||||
private function page_template_map(): array {
|
||||
return [
|
||||
'templates/pages/page-sign.php' => __('AKSRT - 登录/注册', 'aksrt'),
|
||||
'templates/pages/page-profile.php' => __('AKSRT - 个人中心', 'aksrt'),
|
||||
@@ -55,34 +55,6 @@ class AKSRT_Templates {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容保留页面模板:非 Zibll 主线能力(文档模式、下载中心、专题、消息、投稿)。
|
||||
*
|
||||
* 这些模板文件与已分配它们的历史页面继续正常渲染(见 load_page_template()),
|
||||
* 只是默认不再出现在 wp-admin 页面模板下拉中,避免污染主线内容心智。
|
||||
* 站点可通过 aksrt_show_compat_page_templates() 重新暴露下拉选项。
|
||||
*/
|
||||
private function compat_page_template_map(): array {
|
||||
return [
|
||||
'templates/pages/page-special.php' => __('AKSRT - 专题聚合(兼容)', 'aksrt'),
|
||||
'templates/pages/page-documentnav.php' => __('AKSRT - 文档导航(兼容)', 'aksrt'),
|
||||
'templates/pages/page-messages.php' => __('AKSRT - 消息中心(兼容)', 'aksrt'),
|
||||
'templates/pages/page-download.php' => __('AKSRT - 下载中心(兼容)', 'aksrt'),
|
||||
'templates/pages/page-submit.php' => __('AKSRT - 前台投稿(兼容)', 'aksrt'),
|
||||
];
|
||||
}
|
||||
|
||||
private function page_template_map(): array {
|
||||
$map = $this->mainline_page_template_map();
|
||||
|
||||
// 兼容页面模板默认隐藏出下拉;仅在站点显式开启时暴露。
|
||||
if (function_exists('aksrt_show_compat_page_templates') && aksrt_show_compat_page_templates()) {
|
||||
$map = array_merge($map, $this->compat_page_template_map());
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register selectable page templates in wp-admin.
|
||||
*/
|
||||
|
||||
@@ -61,12 +61,6 @@ $_aksrt_special_templates = [
|
||||
'title' => '友情链接',
|
||||
'fallback' => '/friends/',
|
||||
],
|
||||
'messages' => [
|
||||
'file' => 'templates/pages/page-messages.php',
|
||||
'slug' => 'messages',
|
||||
'title' => '消息',
|
||||
'fallback' => '/messages/',
|
||||
],
|
||||
'profile' => [
|
||||
'file' => 'templates/pages/page-profile.php',
|
||||
'slug' => 'profile',
|
||||
@@ -113,12 +107,6 @@ $_aksrt_special_templates = [
|
||||
'title' => '友情链接',
|
||||
'fallback' => '/friends/',
|
||||
],
|
||||
'messages' => [
|
||||
'file' => 'templates/pages/page-messages.php',
|
||||
'slug' => 'messages',
|
||||
'title' => '消息',
|
||||
'fallback' => '/messages/',
|
||||
],
|
||||
'profile' => [
|
||||
'file' => 'templates/pages/page-profile.php',
|
||||
'slug' => 'profile',
|
||||
@@ -249,7 +237,6 @@ function aksrt_resolve_page_template_file(string $template_file = '', string $po
|
||||
$slug_map = [
|
||||
'categories' => 'templates/pages/page-categories.php',
|
||||
'friends' => 'templates/pages/page-friends.php',
|
||||
'messages' => 'templates/pages/page-messages.php',
|
||||
'profile' => 'templates/pages/page-profile.php',
|
||||
];
|
||||
|
||||
|
||||
@@ -296,42 +296,6 @@ trait AKSRT_Scripts_Part_1b {
|
||||
);
|
||||
}
|
||||
|
||||
// 专题聚合页:路由专属 CSS
|
||||
if (is_page_template('templates/pages/page-special.php')) {
|
||||
wp_enqueue_style(
|
||||
'aksrt-route-special',
|
||||
$base_uri . '/assets/css/routes/special.css',
|
||||
['aksrt-tokens'],
|
||||
file_exists(get_template_directory() . '/assets/css/routes/special.css')
|
||||
? (string) filemtime(get_template_directory() . '/assets/css/routes/special.css')
|
||||
: $version
|
||||
);
|
||||
}
|
||||
|
||||
// 消息中心页
|
||||
if (is_page_template('templates/pages/page-messages.php')) {
|
||||
wp_enqueue_style(
|
||||
'aksrt-messages',
|
||||
$base_uri . '/assets/css/frontend/messages.css',
|
||||
['aksrt-tokens'],
|
||||
$version
|
||||
);
|
||||
wp_enqueue_script(
|
||||
'aksrt-messages',
|
||||
$base_uri . '/assets/js/messages.js',
|
||||
['aksrt-script'],
|
||||
$version,
|
||||
true
|
||||
);
|
||||
wp_enqueue_script(
|
||||
'aksrt-conversation',
|
||||
$base_uri . '/assets/js/conversation.js',
|
||||
['aksrt-script'],
|
||||
$version,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
// 订单中心页
|
||||
if (is_page_template('templates/pages/page-orders.php')) {
|
||||
wp_enqueue_style(
|
||||
@@ -494,8 +458,8 @@ trait AKSRT_Scripts_Part_1b {
|
||||
}
|
||||
}
|
||||
|
||||
// 前台投稿页面 — page-edit.js
|
||||
if (is_page_template('templates/pages/page-submit.php') || is_page_template('templates/pages/page-product-edit.php')) {
|
||||
// 商品编辑页共用 page-edit.js
|
||||
if (is_page_template('templates/pages/page-product-edit.php')) {
|
||||
$page_edit_js = get_template_directory() . '/assets/js/page-edit.js';
|
||||
if (file_exists($page_edit_js)) {
|
||||
wp_enqueue_script(
|
||||
@@ -1137,45 +1101,6 @@ trait AKSRT_Scripts_Part_1b {
|
||||
}
|
||||
|
||||
// Page navigation (TOC highlight, smooth scroll, doc search)
|
||||
if (is_page_template('templates/pages/page-documentnav.php') || is_singular()) {
|
||||
$page_navs_path = get_template_directory() . '/assets/js/page-navs.js';
|
||||
wp_enqueue_script(
|
||||
'aksrt-page-navs',
|
||||
$base_uri . '/assets/js/page-navs.js',
|
||||
['aksrt-script'],
|
||||
file_exists($page_navs_path) ? (string) filemtime($page_navs_path) : $version,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
// Docs navigation (collapsible tree, keyboard nav, sidebar search)
|
||||
if (is_page_template('templates/pages/page-documentnav.php')) {
|
||||
$docs_nav_path = get_template_directory() . '/assets/js/docs-navigation.js';
|
||||
if (file_exists($docs_nav_path)) {
|
||||
wp_enqueue_script(
|
||||
'aksrt-docs-navigation',
|
||||
$base_uri . '/assets/js/docs-navigation.js',
|
||||
['aksrt-script'],
|
||||
(string) filemtime($docs_nav_path),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Download center page interactions
|
||||
if (is_page_template('templates/pages/page-download.php')) {
|
||||
$dl_status_path = get_template_directory() . '/assets/js/download-status.js';
|
||||
if (file_exists($dl_status_path)) {
|
||||
wp_enqueue_script(
|
||||
'aksrt-download-status',
|
||||
$base_uri . '/assets/js/download-status.js',
|
||||
['aksrt-script'],
|
||||
(string) filemtime($dl_status_path),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 评论回复脚本
|
||||
if (is_singular() && comments_open() && get_option('thread_comments')) {
|
||||
wp_enqueue_script('comment-reply');
|
||||
@@ -1241,10 +1166,8 @@ trait AKSRT_Scripts_Part_1b {
|
||||
'register' => function_exists('aksrt_get_register_url') ? aksrt_get_register_url() : wp_registration_url(),
|
||||
'resetPassword' => function_exists('aksrt_get_reset_password_url') ? aksrt_get_reset_password_url() : wp_lostpassword_url(),
|
||||
'profile' => function_exists('aksrt_get_user_center_url') ? aksrt_get_user_center_url() : home_url('/profile/'),
|
||||
'messages' => $runtime_routes['messages'],
|
||||
'cart' => $runtime_routes['cart'],
|
||||
'orders' => $runtime_routes['orders'],
|
||||
'download' => $runtime_routes['download'],
|
||||
'resources' => $runtime_routes['resources'],
|
||||
],
|
||||
'shell' => [
|
||||
|
||||
@@ -244,16 +244,14 @@ trait AKSRT_Scripts_Part_2 {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve public route URLs from the current canonical page-template ownership.
|
||||
* Resolve public route URLs from the rebuilt mainline ownership.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
private function resolve_frontend_routes(): array {
|
||||
return [
|
||||
'messages' => $this->resolve_template_page_url('templates/pages/page-messages.php', '/messages/'),
|
||||
'cart' => $this->resolve_template_page_url('templates/pages/page-cart.php', '/cart/'),
|
||||
'orders' => $this->resolve_template_page_url('templates/pages/page-orders.php', '/orders/'),
|
||||
'download' => $this->resolve_template_page_url('templates/pages/page-download.php', '/download/'),
|
||||
'resources' => home_url('/resources/'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -135,12 +135,6 @@ class AKSRT_Settings_Home_Cms {
|
||||
return array_key_exists($key, $f) ? $f[$key] : $default;
|
||||
}
|
||||
|
||||
public static function get_homepage_modules(): array {
|
||||
$s = AKSRT_Settings::get_all();
|
||||
$mods = $s['homepage_modules'] ?? [];
|
||||
return is_array($mods) ? array_values($mods) : [];
|
||||
}
|
||||
|
||||
public static function homepage_allowed_sorts(): array {
|
||||
return ['modified', 'date', 'views', 'likes', 'comments', 'favorites', 'downloads', 'rand'];
|
||||
}
|
||||
@@ -209,68 +203,6 @@ class AKSRT_Settings_Home_Cms {
|
||||
return $settings['homepage_tabs'];
|
||||
}
|
||||
|
||||
public static function maybe_migrate_homepage_tabs(): bool {
|
||||
$all = AKSRT_Settings::get_all();
|
||||
|
||||
if (!empty($all['homepage_tabs_migrated'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$existing_tabs = isset($all['homepage_tabs']) && is_array($all['homepage_tabs']) ? $all['homepage_tabs'] : [];
|
||||
|
||||
if (!empty($existing_tabs)) {
|
||||
$all['homepage_tabs_migrated'] = true;
|
||||
update_option('aksrt_settings', $all);
|
||||
AKSRT_Settings::flush_settings_cache();
|
||||
return false;
|
||||
}
|
||||
|
||||
$legacy_tabs = [];
|
||||
$modules = isset($all['homepage_modules']) && is_array($all['homepage_modules']) ? $all['homepage_modules'] : [];
|
||||
|
||||
foreach ($modules as $module) {
|
||||
if (!is_array($module) || ($module['type'] ?? '') !== 'tabs') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$config = isset($module['config']) && is_array($module['config']) ? $module['config'] : [];
|
||||
$cat_ids = isset($config['cat_ids']) && is_array($config['cat_ids']) ? array_values(array_filter(array_map('intval', $config['cat_ids']))) : [];
|
||||
|
||||
foreach ($cat_ids as $cat_id) {
|
||||
if ($cat_id <= 0) {
|
||||
continue;
|
||||
}
|
||||
$term = get_term($cat_id, 'category');
|
||||
if (!$term || is_wp_error($term)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$legacy_tabs[] = [
|
||||
'term_id' => $cat_id,
|
||||
'title' => $term->name,
|
||||
'orderby' => 'date',
|
||||
'enabled' => true,
|
||||
];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!empty($legacy_tabs)) {
|
||||
$all['homepage_tabs'] = $legacy_tabs;
|
||||
}
|
||||
|
||||
if (!isset($all['homepage_content_model'])) {
|
||||
$all['homepage_content_model'] = 'mixed';
|
||||
}
|
||||
|
||||
$all['homepage_tabs_migrated'] = true;
|
||||
update_option('aksrt_settings', $all);
|
||||
AKSRT_Settings::flush_settings_cache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function homepage_card_style(): string {
|
||||
$settings = self::get_homepage_fixed_settings();
|
||||
return $settings['homepage_card_style'];
|
||||
@@ -363,7 +295,7 @@ class AKSRT_Settings_Home_Cms {
|
||||
$manual_note = trim((string) ($settings['payment_manual_delivery_note'] ?? ''));
|
||||
|
||||
$box_position = sanitize_key((string) ($settings['payment_paid_box_position'] ?? 'top'));
|
||||
if (!in_array($box_position, ['box_top', 'top', 'bottom', 'box_bottom'], true)) {
|
||||
if (!in_array($box_position, ['top', 'bottom'], true)) {
|
||||
$box_position = 'top';
|
||||
}
|
||||
|
||||
@@ -597,7 +529,7 @@ class AKSRT_Settings_Home_Cms {
|
||||
$max_minutes = max(5, min(1440, (int) ($s['payment_order_max_minutes'] ?? 30)));
|
||||
|
||||
$box_position = sanitize_key((string) ($s['payment_box_position'] ?? 'top'));
|
||||
if (!in_array($box_position, ['box_top', 'top', 'bottom', 'box_bottom'], true)) {
|
||||
if (!in_array($box_position, ['top', 'bottom'], true)) {
|
||||
$box_position = 'top';
|
||||
}
|
||||
|
||||
|
||||
@@ -3,14 +3,6 @@ defined('ABSPATH') || exit;
|
||||
|
||||
trait AKSRT_Settings_Homepage_Reader {
|
||||
|
||||
/**
|
||||
* 首页模块编排。
|
||||
* @return array
|
||||
*/
|
||||
public static function get_homepage_modules(): array {
|
||||
return AKSRT_Settings_Home_Cms::get_homepage_modules();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowed sort/orderby values for the homepage.
|
||||
*
|
||||
@@ -56,17 +48,6 @@ trait AKSRT_Settings_Homepage_Reader {
|
||||
return AKSRT_Settings_Home_Cms::homepage_tabs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate legacy homepage module tabs to the new structured format.
|
||||
*
|
||||
* Called once on first admin visit; idempotent.
|
||||
*
|
||||
* @return bool Whether migration was performed.
|
||||
*/
|
||||
public static function maybe_migrate_homepage_tabs(): bool {
|
||||
return AKSRT_Settings_Home_Cms::maybe_migrate_homepage_tabs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Homepage card view variant.
|
||||
*
|
||||
|
||||
@@ -469,20 +469,6 @@ add_filter('template_include', function ($template) {
|
||||
return $candidate ?: $template;
|
||||
});
|
||||
|
||||
// 标记为资源的 post:单页改用 single-aksrt_resource.php 模板
|
||||
add_filter('single_template', function ($template) {
|
||||
if (!is_singular('post')) return $template;
|
||||
$post = get_queried_object();
|
||||
if (!($post instanceof WP_Post)) return $template;
|
||||
if (!function_exists('aksrt_is_resource_post')) return $template;
|
||||
if (!aksrt_is_resource_post($post)) return $template;
|
||||
if (function_exists('aksrt_is_downloadable_content') && !aksrt_is_downloadable_content($post)) {
|
||||
return $template;
|
||||
}
|
||||
$candidate = locate_template(['single-aksrt_resource.php']);
|
||||
return $candidate ?: $template;
|
||||
});
|
||||
|
||||
// 资源归档页:标题
|
||||
add_filter('document_title_parts', function ($parts) {
|
||||
if (get_query_var('aksrt_is_resource_archive')) {
|
||||
|
||||
@@ -1,98 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* AKSRT 兼容层策略中枢 (Compatibility-layer policy hub)
|
||||
* Deprecated compatibility toggles retained only as hard-off stubs.
|
||||
*
|
||||
* AKSRT → Zibll 1:1 复刻项目的收口约定:部分非主线能力(文档模式、下载中心、
|
||||
* 前台投稿、专题聚合、站内私信)不再删除,也不再作为默认主入口,而是收敛为
|
||||
* “兼容保留”能力。本文件集中定义这些兼容入口的可见性开关,供后台与前台统一读取,
|
||||
* 避免各模板各自硬编码 `home_url()` 或 `function_exists()` 回退逻辑。
|
||||
*
|
||||
* 分类口径(见 docs/plan/stream-a-product-scope.md):
|
||||
* - 兼容保留:路由/数据/模板/设置键保留,但不作默认主入口。
|
||||
* - 前台隐藏:默认不在主导航、首页、页面模板下拉中暴露;可经 filter 次级开启。
|
||||
* - 停用候选:默认关闭前台入口;仅在明确兼容需求下由站点手动开启。
|
||||
*
|
||||
* 硬约束:这里只控制“入口是否暴露”,不销毁任何路由、模板、ajax handler 或历史数据。
|
||||
* The rebuild now treats Zibll-style mainline pages as the only product target.
|
||||
* Historical message center / PM entry points / compat template pickers stay on
|
||||
* disk for legacy routing safety, but no longer participate in product-facing
|
||||
* navigation or configuration decisions.
|
||||
*
|
||||
* @package AKSRT
|
||||
* @since 3.4.0
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
if (!function_exists('aksrt_get_messages_url')) {
|
||||
/**
|
||||
* 解析站内消息/通知中心页面地址。
|
||||
*
|
||||
* 消息通知骨架属于“兼容保留”能力:仍向已登录用户在用户下拉中提供次级入口,
|
||||
* 但不作为一级导航。优先解析已分配 page-messages 模板的实际页面,回退到 /messages/。
|
||||
*
|
||||
* @return string
|
||||
* Legacy message center URL stub.
|
||||
*/
|
||||
function aksrt_get_messages_url(): string {
|
||||
$url = '';
|
||||
|
||||
if (function_exists('aksrt_find_template_page')) {
|
||||
$page = aksrt_find_template_page('templates/pages/page-messages.php');
|
||||
if ($page instanceof WP_Post) {
|
||||
$url = (string) get_permalink($page);
|
||||
}
|
||||
}
|
||||
|
||||
if ($url === '') {
|
||||
$url = home_url('/messages/');
|
||||
}
|
||||
|
||||
/**
|
||||
* 允许站点/子主题覆盖兼容消息中心地址。
|
||||
*
|
||||
* @param string $url 消息中心地址。
|
||||
*/
|
||||
return (string) apply_filters('aksrt_messages_url', $url);
|
||||
return home_url('/messages/');
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_pm_frontend_enabled')) {
|
||||
/**
|
||||
* 是否在前台暴露站内私信/会话入口。
|
||||
*
|
||||
* 私信/会话系统在收口后属于“停用候选”:ajax handler、数据、模板均保留(后台兼容),
|
||||
* 但默认不再在前台(如作者操作条“私信”按钮)暴露,以免继续把产品心智推向社交平台。
|
||||
* 站点如确有兼容需求,可通过该 filter 或常量 AKSRT_ENABLE_PM_FRONTEND 重新开启。
|
||||
*
|
||||
* @return bool
|
||||
* Private-message entry is disabled in the rebuilt mainline.
|
||||
*/
|
||||
function aksrt_pm_frontend_enabled(): bool {
|
||||
$enabled = defined('AKSRT_ENABLE_PM_FRONTEND') && AKSRT_ENABLE_PM_FRONTEND;
|
||||
|
||||
/**
|
||||
* 允许站点重新开启前台私信入口(默认关闭)。
|
||||
*
|
||||
* @param bool $enabled 是否开启前台私信入口。
|
||||
*/
|
||||
return (bool) apply_filters('aksrt_pm_frontend_enabled', $enabled);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_show_compat_page_templates')) {
|
||||
/**
|
||||
* 是否在 wp-admin 页面模板下拉中暴露“兼容保留”页面模板。
|
||||
*
|
||||
* 文档导航、下载中心、消息中心、前台投稿、专题聚合等模板默认不再出现在页面模板
|
||||
* 下拉里,避免污染主线内容心智;但模板文件与已分配这些模板的历史页面仍照常渲染
|
||||
* (见 AKSRT_Templates::load_page_template())。站点如需继续手动创建这些兼容页面,
|
||||
* 可通过该 filter 或常量 AKSRT_SHOW_COMPAT_TEMPLATES 重新暴露下拉选项。
|
||||
*
|
||||
* @return bool
|
||||
* Compat-only page templates are hidden from the rebuilt product surface.
|
||||
*/
|
||||
function aksrt_show_compat_page_templates(): bool {
|
||||
$show = defined('AKSRT_SHOW_COMPAT_TEMPLATES') && AKSRT_SHOW_COMPAT_TEMPLATES;
|
||||
|
||||
/**
|
||||
* 允许站点在页面模板下拉中重新暴露兼容页面模板(默认关闭)。
|
||||
*
|
||||
* @param bool $show 是否暴露兼容页面模板下拉。
|
||||
*/
|
||||
return (bool) apply_filters('aksrt_show_compat_page_templates', $show);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,57 +60,6 @@ if (!function_exists('aksrt_homepage_get_post_types')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_homepage_get_legacy_tabs_config')) {
|
||||
/**
|
||||
* Use the first legacy "tabs" home module as a migration bridge so that
|
||||
* previously configured category ids keep powering the new fixed homepage.
|
||||
*
|
||||
* @return array{term_ids:int[],posts_per_page:int}
|
||||
*/
|
||||
function aksrt_homepage_get_legacy_tabs_config(): array {
|
||||
static $config = null;
|
||||
|
||||
if (is_array($config)) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
$config = [
|
||||
'term_ids' => [],
|
||||
'posts_per_page' => 6,
|
||||
];
|
||||
|
||||
if (!class_exists('AKSRT_Settings')) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
foreach (AKSRT_Settings::get_homepage_modules() as $module) {
|
||||
if (!is_array($module) || ($module['type'] ?? '') !== 'tabs') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$module_config = isset($module['config']) && is_array($module['config'])
|
||||
? $module['config']
|
||||
: [];
|
||||
|
||||
$term_ids = isset($module_config['cat_ids']) && is_array($module_config['cat_ids'])
|
||||
? array_values(array_filter(array_map('intval', $module_config['cat_ids'])))
|
||||
: [];
|
||||
|
||||
if ($term_ids) {
|
||||
$config['term_ids'] = $term_ids;
|
||||
}
|
||||
|
||||
if (!empty($module_config['count'])) {
|
||||
$config['posts_per_page'] = max(4, min(12, (int) $module_config['count']));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_homepage_get_tab_terms')) {
|
||||
/**
|
||||
* Homepage category tabs with full config.
|
||||
@@ -188,10 +137,7 @@ if (!function_exists('aksrt_homepage_get_tab_posts_per_page')) {
|
||||
}
|
||||
}
|
||||
|
||||
$legacy = aksrt_homepage_get_legacy_tabs_config();
|
||||
$count = (int) apply_filters('aksrt_homepage_tab_posts_per_page', $legacy['posts_per_page']);
|
||||
|
||||
return max(4, min(12, $count));
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,7 +339,6 @@ if (!function_exists('aksrt_homepage_render_sortbar')) {
|
||||
: $sort_items;
|
||||
?>
|
||||
<div class="aksrt-homepage__sortbar" data-sort-ajax="<?php echo $sort_ajax_enabled ? 'true' : 'false'; ?>" aria-label="<?php esc_attr_e('Homepage Sort', 'aksrt'); ?>">
|
||||
<span class="aksrt-homepage__sortbar-label"><?php esc_html_e('排序', 'aksrt'); ?></span>
|
||||
<?php if ($is_dropdown) : ?>
|
||||
<div class="aksrt-homepage__sortbar-dropdown">
|
||||
<button type="button" class="aksrt-homepage__sortbar-current" data-sort-dropdown-trigger>
|
||||
@@ -845,117 +790,6 @@ if (!function_exists('aksrt_homepage_render_system_module')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_homepage_get_featured_modules')) {
|
||||
/**
|
||||
* Resolve non-core homepage modules that should render alongside the fixed
|
||||
* hero/banner/main-stream skeleton.
|
||||
*
|
||||
* @return array<int,array{type:string,config:array}>
|
||||
*/
|
||||
function aksrt_homepage_get_featured_modules(): array {
|
||||
if (!class_exists('AKSRT_Settings')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$allowed_types = [
|
||||
'category',
|
||||
'recent',
|
||||
'ranking',
|
||||
'hotspot',
|
||||
'category_recommend_cards',
|
||||
'tag_cloud',
|
||||
'friend_links',
|
||||
'html',
|
||||
'highlight_cards',
|
||||
];
|
||||
$modules = [];
|
||||
|
||||
foreach (AKSRT_Settings::get_homepage_modules() as $module) {
|
||||
if (!is_array($module)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$type = sanitize_key((string) ($module['type'] ?? ''));
|
||||
if (!in_array($type, $allowed_types, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$modules[] = [
|
||||
'type' => $type,
|
||||
'config' => isset($module['config']) && is_array($module['config']) ? $module['config'] : [],
|
||||
];
|
||||
}
|
||||
|
||||
return $modules;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_homepage_render_featured_modules')) {
|
||||
/**
|
||||
* Render featured homepage modules in configured order.
|
||||
*/
|
||||
function aksrt_homepage_render_featured_modules(array $modules, string $wrapper_class = 'home-modules'): void {
|
||||
if (empty($modules)) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo '<div class="' . esc_attr(trim($wrapper_class)) . '">';
|
||||
foreach ($modules as $idx => $module) {
|
||||
$type = sanitize_key((string) ($module['type'] ?? ''));
|
||||
if ($type === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
set_query_var('aksrt_module_config', isset($module['config']) && is_array($module['config']) ? $module['config'] : []);
|
||||
set_query_var('aksrt_module_index', $idx);
|
||||
get_template_part('templates/parts/home-modules/module', $type);
|
||||
}
|
||||
set_query_var('aksrt_module_config', null);
|
||||
set_query_var('aksrt_module_index', null);
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_homepage_split_featured_modules')) {
|
||||
/**
|
||||
* Split legacy featured modules into homepage skeleton slots.
|
||||
*
|
||||
* @param array<int,array{type:string,config:array}> $modules
|
||||
* @return array{top:array<int,array{type:string,config:array}>,mid:array<int,array{type:string,config:array}>,bottom:array<int,array{type:string,config:array}>}
|
||||
*/
|
||||
function aksrt_homepage_split_featured_modules(array $modules): array {
|
||||
$buckets = [
|
||||
'top' => [],
|
||||
'mid' => [],
|
||||
'bottom' => [],
|
||||
];
|
||||
|
||||
$top_types = ['highlight_cards', 'hotspot', 'html'];
|
||||
$bottom_types = ['ranking', 'tag_cloud', 'friend_links'];
|
||||
|
||||
foreach ($modules as $module) {
|
||||
$type = sanitize_key((string) ($module['type'] ?? ''));
|
||||
if ($type === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($type, $top_types, true)) {
|
||||
$buckets['top'][] = $module;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($type, $bottom_types, true)) {
|
||||
$buckets['bottom'][] = $module;
|
||||
continue;
|
||||
}
|
||||
|
||||
$buckets['mid'][] = $module;
|
||||
}
|
||||
|
||||
return $buckets;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_homepage_render_layout')) {
|
||||
/**
|
||||
* Render the fixed homepage layout directly.
|
||||
@@ -964,8 +798,6 @@ if (!function_exists('aksrt_homepage_render_layout')) {
|
||||
$current_page = aksrt_homepage_get_current_page();
|
||||
$show_tabs = $current_page === 1;
|
||||
$tab_configs = $show_tabs ? aksrt_homepage_get_tab_configs() : [];
|
||||
$featured_modules = $show_tabs ? aksrt_homepage_get_featured_modules() : [];
|
||||
$featured_slots = $show_tabs ? aksrt_homepage_split_featured_modules($featured_modules) : ['top' => [], 'mid' => [], 'bottom' => []];
|
||||
$latest_contract = aksrt_homepage_get_latest_panel_contract();
|
||||
$has_sidebar = aksrt_homepage_has_sidebar();
|
||||
$hero_on = $show_tabs && aksrt_homepage_module_hero_enabled();
|
||||
@@ -1003,27 +835,20 @@ if (!function_exists('aksrt_homepage_render_layout')) {
|
||||
aksrt_homepage_render_system_module('banner', 'aksrt-homepage__content-zone aksrt-homepage__content-zone--banner aksrt-homepage__system-modules home-modules');
|
||||
}
|
||||
|
||||
if (!empty($featured_slots['top'])) {
|
||||
aksrt_homepage_render_featured_modules(
|
||||
$featured_slots['top'],
|
||||
'aksrt-homepage__content-zone aksrt-homepage__content-zone--operated aksrt-homepage__content-zone--top-modules home-modules'
|
||||
);
|
||||
}
|
||||
?>
|
||||
|
||||
<?php if ($main_list_enabled) : ?>
|
||||
<section class="widget widget-card aksrt-homepage__stream home-tab-content index-tab-main" aria-label="<?php esc_attr_e('Homepage Content', 'aksrt'); ?>">
|
||||
<div class="aksrt-homepage__stream-header box-body notop nobottom">
|
||||
<section class="aksrt-homepage__stream" aria-label="<?php esc_attr_e('Homepage Content', 'aksrt'); ?>">
|
||||
<div class="aksrt-homepage__stream-header">
|
||||
<div class="aksrt-homepage__stream-intro">
|
||||
<div class="aksrt-homepage__stream-kicker"><?php esc_html_e('首页主内容流', 'aksrt'); ?></div>
|
||||
<h2 class="aksrt-homepage__stream-title"><?php echo esc_html($list_title); ?></h2>
|
||||
<p class="aksrt-homepage__stream-subtitle"><?php esc_html_e('以内容流为主轴,承接运营入口、分类切换与持续更新。', 'aksrt'); ?></p>
|
||||
<p class="aksrt-homepage__stream-subtitle"><?php esc_html_e('以首页主内容流承接分类切换、排序与持续更新。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php if (function_exists('aksrt_render_admin_quick_link')) { aksrt_render_admin_quick_link('page-display/homepage', __('首页设置', 'aksrt'), 'aksrt-admin-quicklink aksrt-homepage__admin-link'); } ?>
|
||||
</div>
|
||||
|
||||
<?php if ($show_tabs && !empty($tab_configs)) : ?>
|
||||
<div class="aksrt-homepage__tabs box-body notop nobottom index-tab home-tab-nav-box" data-sticky-tabs="<?php echo aksrt_homepage_sticky_tabs_enabled() ? 'true' : 'false'; ?>">
|
||||
<div class="aksrt-homepage__tabs home-tab-nav-box" data-sticky-tabs="<?php echo aksrt_homepage_sticky_tabs_enabled() ? 'true' : 'false'; ?>">
|
||||
<ul class="aksrt-homepage__tab-list scroll-x no-scrollbar" role="tablist" data-aksrt-home-tabs>
|
||||
<li class="aksrt-homepage__tab-item is-active" role="presentation">
|
||||
<button
|
||||
@@ -1053,7 +878,7 @@ if (!function_exists('aksrt_homepage_render_layout')) {
|
||||
</ul>
|
||||
</div>
|
||||
<?php elseif ($current_page > 1) : ?>
|
||||
<div class="aksrt-homepage__titlebox box-body notop nobottom">
|
||||
<div class="aksrt-homepage__titlebox">
|
||||
<div class="title-theme">
|
||||
<?php echo esc_html($list_title); ?>
|
||||
<small class="aksrt-homepage__page-indicator">
|
||||
@@ -1101,24 +926,12 @@ if (!function_exists('aksrt_homepage_render_layout')) {
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
if (!empty($featured_slots['mid'])) {
|
||||
aksrt_homepage_render_featured_modules(
|
||||
$featured_slots['mid'],
|
||||
'aksrt-homepage__content-zone aksrt-homepage__content-zone--mid home-modules'
|
||||
);
|
||||
}
|
||||
|
||||
aksrt_homepage_render_widget_zone(
|
||||
['home_bottom_content'],
|
||||
'aksrt-homepage__content-zone aksrt-homepage__content-zone--bottom'
|
||||
);
|
||||
|
||||
if (!empty($featured_slots['bottom'])) {
|
||||
aksrt_homepage_render_featured_modules(
|
||||
$featured_slots['bottom'],
|
||||
'aksrt-homepage__content-zone aksrt-homepage__content-zone--supplement home-modules'
|
||||
);
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,355 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Single resource template.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
get_header();
|
||||
|
||||
while (have_posts()) :
|
||||
the_post();
|
||||
|
||||
$post_id = get_the_ID();
|
||||
$resource_meta = function_exists('aksrt_get_resource_meta') ? aksrt_get_resource_meta($post_id) : aksrt_default_resource_meta();
|
||||
$single_settings = function_exists('aksrt_resolve_single_post_display_settings')
|
||||
? aksrt_resolve_single_post_display_settings($post_id)
|
||||
: [];
|
||||
$show_toc = !empty($single_settings['toc_enabled']);
|
||||
$show_cover = !empty($single_settings['show_cover']);
|
||||
$cover_url = (string) ($single_settings['cover_url'] ?? '');
|
||||
$views = isset($resource_meta['view_count']) ? (int) $resource_meta['view_count'] : 0;
|
||||
$downloads = isset($resource_meta['download_count']) ? (int) $resource_meta['download_count'] : 0;
|
||||
$like_count = function_exists('aksrt_get_post_likes') ? (int) aksrt_get_post_likes($post_id) : 0;
|
||||
$favorite_count = function_exists('aksrt_get_post_favorites') ? (int) aksrt_get_post_favorites($post_id) : 0;
|
||||
$is_liked = function_exists('aksrt_is_post_liked') ? aksrt_is_post_liked($post_id) : false;
|
||||
$is_favorited = function_exists('aksrt_is_post_favorited') ? aksrt_is_post_favorited($post_id) : false;
|
||||
$word_count = function_exists('aksrt_post_word_count') && !empty($single_settings['word_count_enabled'])
|
||||
? aksrt_post_word_count($post_id)
|
||||
: 0;
|
||||
$reading_minutes = function_exists('aksrt_reading_minutes') && !empty($single_settings['reading_time_enabled'])
|
||||
? aksrt_reading_minutes($post_id)
|
||||
: 0;
|
||||
$author_meta_items = [];
|
||||
if (empty($single_settings['hide_time'])) {
|
||||
$author_meta_items[] = [
|
||||
'icon' => 'far fa-clock',
|
||||
'text' => sprintf(__('发布于 %s', 'aksrt'), get_the_date()),
|
||||
];
|
||||
}
|
||||
$author_meta_items[] = [
|
||||
'icon' => 'far fa-eye',
|
||||
'text' => sprintf(__('浏览 %s', 'aksrt'), function_exists('aksrt_format_number') ? aksrt_format_number($views) : number_format_i18n($views)),
|
||||
];
|
||||
$author_meta_items[] = [
|
||||
'icon' => 'fas fa-download',
|
||||
'text' => sprintf(__('下载 %s', 'aksrt'), number_format_i18n($downloads)),
|
||||
];
|
||||
if ($word_count > 0) {
|
||||
$author_meta_items[] = [
|
||||
'icon' => 'far fa-file-word',
|
||||
'text' => sprintf(__('约 %s 字', 'aksrt'), number_format_i18n($word_count)),
|
||||
];
|
||||
}
|
||||
if ($reading_minutes > 0) {
|
||||
$author_meta_items[] = [
|
||||
'icon' => 'far fa-hourglass-half',
|
||||
'text' => sprintf(_n('约 %d 分钟', '约 %d 分钟', $reading_minutes, 'aksrt'), $reading_minutes),
|
||||
];
|
||||
}
|
||||
|
||||
$show_action_card = !empty($single_settings['like_enabled'])
|
||||
|| !empty($single_settings['favorite_enabled'])
|
||||
|| !empty($single_settings['share_enabled'])
|
||||
|| !empty($single_settings['print_enabled'])
|
||||
|| !empty($single_settings['pdf_export_enabled']);
|
||||
$copyright_text = trim((string) ($single_settings['copyright_text'] ?? ''));
|
||||
if ($copyright_text === '') {
|
||||
$copyright_text = sprintf(
|
||||
/* translators: %s: author display name */
|
||||
__('本文由 %s 原创发布,转载请注明出处。', 'aksrt'),
|
||||
get_the_author()
|
||||
);
|
||||
}
|
||||
|
||||
set_query_var('aksrt_resource_meta', $resource_meta);
|
||||
$is_legacy_resource_shell = true;
|
||||
?>
|
||||
|
||||
<?php if (!empty($single_settings['reading_progress'])) : ?>
|
||||
<div id="reading-progress-global" class="reading-progress-bar" role="progressbar" aria-label="<?php esc_attr_e('阅读进度', 'aksrt'); ?>" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<main id="main-content" class="site-main container" tabindex="-1">
|
||||
<div class="content-wrap">
|
||||
<div class="content-layout">
|
||||
<div class="content-layout__primary">
|
||||
<?php if (!empty($single_settings['breadcrumbs']) && function_exists('aksrt_breadcrumbs')) : ?>
|
||||
<div class="post-breadcrumbs"><?php aksrt_breadcrumbs($single_settings['breadcrumbs_home'] ?? ''); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<article <?php post_class('article main-bg theme-box box-body radius8 main-shadow article-resource'); ?>>
|
||||
<a href="#resource-mobile-download" class="resource-mobile-fab" aria-label="<?php esc_attr_e('前往下载区', 'aksrt'); ?>">
|
||||
<i class="fas fa-download" aria-hidden="true"></i>
|
||||
</a>
|
||||
|
||||
<?php if ($show_cover && $cover_url !== '') : ?>
|
||||
<div class="single-head-cover single-cover graphic imgbox-container">
|
||||
<img src="<?php echo esc_url($cover_url); ?>" alt="<?php echo esc_attr(get_the_title()); ?>" class="fit-cover" loading="eager">
|
||||
<div class="single-cover__overlay"></div>
|
||||
<div class="single-cover__content">
|
||||
<h1 class="article-title title-h-left"><?php the_title(); ?></h1>
|
||||
<div class="single-metabox cover-meta abs-right">
|
||||
<?php foreach ($author_meta_items as $meta_item) : ?>
|
||||
<item class="meta-view"><?php if (!empty($meta_item['icon'])) : ?><i class="<?php echo esc_attr($meta_item['icon']); ?>" aria-hidden="true"></i> <?php endif; ?><?php echo esc_html((string) $meta_item['text']); ?></item>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!$show_cover) : ?>
|
||||
<div class="article-header theme-box clearfix relative">
|
||||
<h1 class="article-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($single_settings['authordesc'])) : ?>
|
||||
<?php
|
||||
set_query_var('aksrt_author_bar_class', 'article-author-bar');
|
||||
set_query_var('aksrt_author_bar_meta_items', $author_meta_items);
|
||||
set_query_var('aksrt_author_bar_bio', false);
|
||||
set_query_var('aksrt_author_bar_actions', false);
|
||||
get_template_part('templates/parts/single-author-bar');
|
||||
set_query_var('aksrt_author_bar_class', '');
|
||||
set_query_var('aksrt_author_bar_meta_items', []);
|
||||
set_query_var('aksrt_author_bar_bio', false);
|
||||
set_query_var('aksrt_author_bar_actions', false);
|
||||
?>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="theme-box wp-posts-content"
|
||||
data-nav="posts"
|
||||
data-aksrt-toc="<?php echo $show_toc ? '1' : '0'; ?>"
|
||||
data-aksrt-toc-depth="<?php echo esc_attr((string) ((int) ($single_settings['toc_depth'] ?? 3))); ?>"
|
||||
data-aksrt-lightbox="<?php echo !empty($single_settings['lightbox']) ? '1' : '0'; ?>">
|
||||
<?php
|
||||
the_content();
|
||||
wp_link_pages([
|
||||
'before' => '<p class="text-center post-nav-links radius8 padding-6">',
|
||||
'after' => '</p>',
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="article-footer">
|
||||
<?php if (!empty($single_settings['copyright_enabled'])) : ?>
|
||||
<div class="em09 muted-3-color">
|
||||
<div><span>©</span> <?php esc_html_e('版权声明', 'aksrt'); ?></div>
|
||||
<div class="posts-copyright"><?php echo esc_html($copyright_text); ?></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="text-center theme-box muted-3-color box-body separator em09">THE END</div>
|
||||
<div class="theme-box article-tags">
|
||||
<?php foreach (get_the_category() ?: [] as $cat) : ?>
|
||||
<a href="<?php echo esc_url(get_category_link($cat->term_id)); ?>" class="but"><i class="far fa-folder-open" aria-hidden="true"></i> <?php echo esc_html($cat->name); ?></a>
|
||||
<?php endforeach; ?>
|
||||
<br>
|
||||
<?php foreach (get_the_tags() ?: [] as $tag) : ?>
|
||||
<a href="<?php echo esc_url(get_tag_link($tag->term_id)); ?>" class="but"># <?php echo esc_html($tag->name); ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($show_action_card) : ?>
|
||||
<div class="theme-box box-body radius8 main-shadow">
|
||||
<div class="text-center muted-3-color box-body em09"><?php echo esc_html($single_settings['button_toptext'] ?? __('喜欢就支持一下吧', 'aksrt')); ?></div>
|
||||
<div class="text-center post-actions">
|
||||
<?php if (!empty($single_settings['like_enabled'])) : ?>
|
||||
<button type="button" class="action action-like<?php echo $is_liked ? ' is-active' : ''; ?>" id="action-like" data-post-id="<?php echo esc_attr((string) $post_id); ?>" data-initial-active="<?php echo $is_liked ? '1' : '0'; ?>">
|
||||
<i class="<?php echo $is_liked ? 'fas' : 'far'; ?> fa-heart" aria-hidden="true"></i>
|
||||
<span class="action-btn__count" data-stat-count="likes" data-base-count="<?php echo esc_attr((string) $like_count); ?>"><?php echo esc_html((string) $like_count); ?></span>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($single_settings['share_enabled'])) : ?>
|
||||
<button type="button" class="action action-share" id="action-share-trigger" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fas fa-share-alt" aria-hidden="true"></i>
|
||||
<span><?php esc_html_e('分享', 'aksrt'); ?></span>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($single_settings['favorite_enabled'])) : ?>
|
||||
<button type="button" class="action action-favorite<?php echo $is_favorited ? ' is-active' : ''; ?>" id="action-favorite" data-post-id="<?php echo esc_attr((string) $post_id); ?>" data-initial-active="<?php echo $is_favorited ? '1' : '0'; ?>">
|
||||
<i class="<?php echo $is_favorited ? 'fas' : 'far'; ?> fa-star" aria-hidden="true"></i>
|
||||
<span class="action-btn__count" data-stat-count="favorites" data-base-count="<?php echo esc_attr((string) $favorite_count); ?>"><?php echo esc_html((string) $favorite_count); ?></span>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($single_settings['share_enabled'])) : ?>
|
||||
<div class="share-dropdown" id="share-dropdown" aria-hidden="true">
|
||||
<div class="share-dropdown__grid">
|
||||
<button type="button" class="share-item" data-platform="qq"><i class="fab fa-qq"></i><span>QQ</span></button>
|
||||
<button type="button" class="share-item" data-platform="weibo"><i class="fab fa-weibo"></i><span>微博</span></button>
|
||||
<button type="button" class="share-item" data-platform="twitter"><i class="fab fa-x-twitter"></i><span>X</span></button>
|
||||
<button type="button" class="share-item" data-platform="wechat"><i class="fab fa-weixin"></i><span>微信</span></button>
|
||||
<button type="button" class="share-item" data-platform="copy"><i class="fas fa-link"></i><span><?php esc_html_e('复制链接', 'aksrt'); ?></span></button>
|
||||
</div>
|
||||
<div id="share-qrcode-box" aria-hidden="true">
|
||||
<img id="share-qrcode-image" src="" alt="QR Code">
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="resource-mobile-download-bar" id="resource-mobile-download">
|
||||
<?php get_template_part('templates/parts/resource-download-box'); ?>
|
||||
</div>
|
||||
|
||||
<?php if (comments_open() || get_comments_number()) : ?>
|
||||
<div class="theme-box box-body radius8 main-shadow comments-card">
|
||||
<?php comments_template(); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
$related_resource_query = null;
|
||||
$resource_cat_ids = wp_get_post_categories($post_id, ['fields' => 'ids']);
|
||||
if (!empty($single_settings['related_enabled']) && !empty($resource_cat_ids)) {
|
||||
$post_types = function_exists('aksrt_resource_post_types') ? aksrt_resource_post_types() : ['post'];
|
||||
$args = [
|
||||
'post_type' => $post_types,
|
||||
'posts_per_page' => (int) ($single_settings['related_count'] ?? 6),
|
||||
'post__not_in' => [$post_id],
|
||||
'category__in' => array_map('intval', $resource_cat_ids),
|
||||
'meta_key' => '_aksrt_res_download_count',
|
||||
'orderby' => 'meta_value_num',
|
||||
'order' => 'DESC',
|
||||
'no_found_rows' => true,
|
||||
];
|
||||
if (!post_type_exists('aksrt_resource')) {
|
||||
$args['meta_query'] = [[
|
||||
'key' => '_aksrt_is_resource',
|
||||
'value' => '1',
|
||||
'compare' => '=',
|
||||
]];
|
||||
}
|
||||
$related_resource_query = new WP_Query($args);
|
||||
}
|
||||
if ($related_resource_query instanceof WP_Query && $related_resource_query->have_posts()) :
|
||||
?>
|
||||
<section class="resource-related" aria-label="<?php esc_attr_e('相关资源', 'aksrt'); ?>">
|
||||
<header class="resource-related__header">
|
||||
<h2 class="resource-related__title"><?php esc_html_e('相关资源', 'aksrt'); ?></h2>
|
||||
</header>
|
||||
<?php
|
||||
aksrt_render_post_list($related_resource_query, [
|
||||
'context' => 'archive',
|
||||
'mode' => 'card',
|
||||
'card_style' => 'standard',
|
||||
'show_excerpt' => false,
|
||||
'wrapper_class' => 'resource-related__grid',
|
||||
]);
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div class="sidebar aksrt-resource__aside" role="complementary" aria-label="<?php esc_attr_e('侧栏', 'aksrt'); ?>">
|
||||
<div class="resource-legacy-note resource-legacy-note--aside">
|
||||
<strong><?php esc_html_e('旧资源兼容入口', 'aksrt'); ?></strong>
|
||||
<span><?php esc_html_e('当前单页仅保留历史资源内容兼容,下载能力已并入统一内容付费链路。', 'aksrt'); ?></span>
|
||||
</div>
|
||||
<?php get_template_part('templates/parts/resource-download-box'); ?>
|
||||
|
||||
<?php if ($show_toc) : ?>
|
||||
<div class="posts-nav-box toc-widget" data-title="<?php esc_attr_e('资源目录', 'aksrt'); ?>">
|
||||
<ol class="toc-list"></ol>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
$attributes = [];
|
||||
if (!empty($resource_meta['version'])) {
|
||||
$attributes[__('版本', 'aksrt')] = $resource_meta['version'];
|
||||
}
|
||||
if (!empty($resource_meta['size'])) {
|
||||
$attributes[__('大小', 'aksrt')] = $resource_meta['size'];
|
||||
}
|
||||
if (!empty($resource_meta['compat'])) {
|
||||
$attributes[__('兼容性', 'aksrt')] = $resource_meta['compat'];
|
||||
}
|
||||
if (!empty($resource_meta['demo_url'])) {
|
||||
$attributes[__('演示地址', 'aksrt')] = sprintf(
|
||||
'<a href="%s" target="_blank" rel="noopener noreferrer"><i class="fas fa-external-link-alt" aria-hidden="true"></i> %s</a>',
|
||||
esc_url($resource_meta['demo_url']),
|
||||
__('打开演示', 'aksrt')
|
||||
);
|
||||
}
|
||||
if (!empty($resource_meta['license'])) {
|
||||
$attributes[__('授权', 'aksrt')] = $resource_meta['license'];
|
||||
}
|
||||
if (!empty($attributes)) :
|
||||
?>
|
||||
<div class="widget widget-card resource-meta-card">
|
||||
<h3><?php esc_html_e('资源信息', 'aksrt'); ?></h3>
|
||||
<dl class="resource-meta-card__list">
|
||||
<?php foreach ($attributes as $key => $value) : ?>
|
||||
<div class="resource-meta-card__row">
|
||||
<dt><?php echo esc_html($key); ?></dt>
|
||||
<dd><?php echo wp_kses_post((string) $value); ?></dd>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</dl>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="widget widget-card resource-guarantee-card">
|
||||
<div class="resource-guarantee-card__list">
|
||||
<span><i class="fas fa-shield-alt" aria-hidden="true"></i> <?php esc_html_e('安全检测', 'aksrt'); ?></span>
|
||||
<span><i class="fas fa-sync-alt" aria-hidden="true"></i> <?php esc_html_e('持续更新', 'aksrt'); ?></span>
|
||||
<span><i class="fas fa-headset" aria-hidden="true"></i> <?php esc_html_e('售后支持', 'aksrt'); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (is_active_sidebar('sidebar-article')) : ?>
|
||||
<?php dynamic_sidebar('sidebar-article'); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php if ($show_toc) : ?>
|
||||
<button type="button" class="toc-float-btn" aria-label="<?php esc_attr_e('打开目录', 'aksrt'); ?>">
|
||||
<i class="fas fa-list-ul" aria-hidden="true"></i>
|
||||
</button>
|
||||
<div class="toc-drawer-overlay"></div>
|
||||
<aside class="toc-drawer posts-nav-box" aria-label="<?php esc_attr_e('资源目录', 'aksrt'); ?>">
|
||||
<div class="toc-drawer__head">
|
||||
<h3><?php esc_html_e('资源目录', 'aksrt'); ?></h3>
|
||||
<button type="button" class="toc-drawer__close" aria-label="<?php esc_attr_e('关闭目录', 'aksrt'); ?>">
|
||||
<i class="fas fa-times" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<ol class="toc-list"></ol>
|
||||
</aside>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($single_settings['lightbox'])) : ?>
|
||||
<div class="lightbox-overlay" id="lightbox-overlay" role="dialog" aria-modal="true" aria-label="<?php esc_attr_e('图片预览', 'aksrt'); ?>">
|
||||
<button type="button" class="lightbox-close" aria-label="<?php esc_attr_e('关闭', 'aksrt'); ?>"><i class="fas fa-times"></i></button>
|
||||
<img src="" alt="" class="lightbox-img">
|
||||
<div class="lightbox-caption" aria-live="polite"></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="toast-container" id="toast-container"></div>
|
||||
<?php endwhile; ?>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
+21
-7
@@ -91,15 +91,20 @@ while (have_posts()) :
|
||||
$post_toc_drawer = '';
|
||||
$post_share_dropdown = '';
|
||||
$post_reward_modal = '';
|
||||
$post_sidebar_prepend = '';
|
||||
$post_episode_count = max(0, (int) get_post_meta($post_id, '_aksrt_featured_video_episode', true));
|
||||
$post_slide_images = array_values(array_filter((array) ($single_settings['slide_images'] ?? [])));
|
||||
$author_card_html = '';
|
||||
$is_resource_compat_post = function_exists('aksrt_is_resource_post') && aksrt_is_resource_post($post_id);
|
||||
$has_download_capability = function_exists('aksrt_is_downloadable_content') && aksrt_is_downloadable_content($post_id);
|
||||
$paid_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_paid_content_settings() : [];
|
||||
$paid_display_settings = is_array($paid_settings['display'] ?? null) ? $paid_settings['display'] : [];
|
||||
$paid_box_position = (string) ($paid_display_settings['box_position'] ?? 'top');
|
||||
if (!in_array($paid_box_position, ['box_top', 'top', 'bottom', 'box_bottom'], true)) {
|
||||
if ($paid_box_position === 'box_top') {
|
||||
$paid_box_position = 'top';
|
||||
} elseif ($paid_box_position === 'box_bottom') {
|
||||
$paid_box_position = 'bottom';
|
||||
}
|
||||
if (!in_array($paid_box_position, ['top', 'bottom'], true)) {
|
||||
$paid_box_position = 'top';
|
||||
}
|
||||
if (class_exists('AKSRT_Docs_Presenter')) {
|
||||
@@ -298,8 +303,8 @@ while (have_posts()) :
|
||||
|
||||
<?php do_action('aksrt_single_content_before', $post); ?>
|
||||
|
||||
<?php if ($has_download_capability && in_array($paid_box_position, ['box_top', 'top'], true)) : ?>
|
||||
<div class="aksrt-single-download-box aksrt-single-download-box--before<?php echo $is_resource_compat_post ? ' is-legacy-resource' : ''; ?>">
|
||||
<?php if ($has_download_capability && $paid_box_position === 'top') : ?>
|
||||
<div class="aksrt-single-download-box aksrt-single-download-box--before">
|
||||
<?php get_template_part('templates/parts/resource-download-box'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
@@ -331,8 +336,8 @@ while (have_posts()) :
|
||||
<div class="post_after_content theme-box box-body"><?php echo wp_kses_post($post_after_content); ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($has_download_capability && in_array($paid_box_position, ['bottom', 'box_bottom'], true)) : ?>
|
||||
<div class="aksrt-single-download-box aksrt-single-download-box--after<?php echo $is_resource_compat_post ? ' is-legacy-resource' : ''; ?>">
|
||||
<?php if ($has_download_capability && $paid_box_position === 'bottom') : ?>
|
||||
<div class="aksrt-single-download-box aksrt-single-download-box--after">
|
||||
<?php get_template_part('templates/parts/resource-download-box'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
@@ -471,7 +476,16 @@ while (have_posts()) :
|
||||
|
||||
<?php if ($show_sidebar) : ?>
|
||||
<?php
|
||||
set_query_var('aksrt_sidebar_prepend_html', $show_toc ? $post_toc_widget : '');
|
||||
$post_sidebar_prepend = '';
|
||||
if ($has_download_capability) {
|
||||
ob_start();
|
||||
get_template_part('templates/parts/resource-meta-box');
|
||||
$post_sidebar_prepend .= (string) ob_get_clean();
|
||||
}
|
||||
if ($show_toc && $post_toc_widget !== '') {
|
||||
$post_sidebar_prepend .= $post_toc_widget;
|
||||
}
|
||||
set_query_var('aksrt_sidebar_prepend_html', $post_sidebar_prepend);
|
||||
get_sidebar();
|
||||
set_query_var('aksrt_sidebar_prepend_html', '');
|
||||
?>
|
||||
|
||||
@@ -117,7 +117,7 @@ $dl_requires_login = !empty($paid_settings['download_login']);
|
||||
<?php if ($resource_query->have_posts()) : ?>
|
||||
<div class="aksrt-download-center__grid">
|
||||
<?php while ($resource_query->have_posts()) : $resource_query->the_post(); ?>
|
||||
<article class="aksrt-download-card<?php echo function_exists('aksrt_is_resource_post') && aksrt_is_resource_post(get_the_ID()) ? ' is-legacy-resource' : ''; ?>">
|
||||
<article class="aksrt-download-card<?php echo function_exists('aksrt_is_resource_post') && aksrt_is_resource_post(get_the_ID()) ? ' is-resource' : ''; ?>">
|
||||
<?php if (has_post_thumbnail()) : ?>
|
||||
<div class="aksrt-download-card__thumb">
|
||||
<a href="<?php the_permalink(); ?>">
|
||||
@@ -127,7 +127,7 @@ $dl_requires_login = !empty($paid_settings['download_login']);
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-download-card__body">
|
||||
<p class="aksrt-download-card__eyebrow">
|
||||
<?php echo esc_html(function_exists('aksrt_is_resource_post') && aksrt_is_resource_post(get_the_ID()) ? __('旧资源兼容内容', 'aksrt') : __('内容付费入口', 'aksrt')); ?>
|
||||
<?php echo esc_html(function_exists('aksrt_is_resource_post') && aksrt_is_resource_post(get_the_ID()) ? __('资源内容入口', 'aksrt') : __('内容付费入口', 'aksrt')); ?>
|
||||
</p>
|
||||
<h3 class="aksrt-download-card__title">
|
||||
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
|
||||
@@ -215,7 +215,7 @@ $dl_requires_login = !empty($paid_settings['download_login']);
|
||||
<div class="aksrt-dl-sidebar-card__tips">
|
||||
<p><i class="fas fa-book-open" aria-hidden="true"></i> <?php esc_html_e('优先从普通文章内容页进入主付费链路', 'aksrt'); ?></p>
|
||||
<p><i class="fas fa-clock" aria-hidden="true"></i> <?php esc_html_e('下载链接 10 分钟内有效', 'aksrt'); ?></p>
|
||||
<p><i class="fas fa-sync-alt" aria-hidden="true"></i> <?php esc_html_e('历史资源页与下载中心仅作为兼容入口保留', 'aksrt'); ?></p>
|
||||
<p><i class="fas fa-sync-alt" aria-hidden="true"></i> <?php esc_html_e('下载中心作为统一内容付费的补充入口', 'aksrt'); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<?php
|
||||
/**
|
||||
* Paid Content Download Box
|
||||
* Unified paid-content download box.
|
||||
*
|
||||
* 统一内容付费 / 下载区:普通文章为主线,resource 样式仅保留兼容外壳。
|
||||
* Downloadable content now follows the unified single.php mainline; resource-
|
||||
* specific visuals are treated as content variants rather than a separate page
|
||||
* system.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
@@ -23,6 +25,7 @@ if ($pay_type !== 'download' || empty($downloads)) {
|
||||
}
|
||||
|
||||
$is_resource_context = function_exists('aksrt_is_resource_post') && aksrt_is_resource_post($post_id);
|
||||
$context_variant = $is_resource_context ? 'resource' : 'content';
|
||||
$subject_label = trim((string) ($meta['subject_label'] ?? ''));
|
||||
if ($subject_label === '') {
|
||||
$subject_label = $is_resource_context ? __('资源', 'aksrt') : __('内容', 'aksrt');
|
||||
@@ -77,7 +80,7 @@ $pay_type_badge = function_exists('aksrt_get_pay_type_badge') ? aksrt_get_pay_ty
|
||||
$currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name() : __('积分', 'aksrt');
|
||||
?>
|
||||
|
||||
<section class="widget resource-download-box resource-download-box--v2<?php echo $gate_blocked ? ' is-blocked' : ''; ?><?php echo $is_resource_context ? ' resource-download-box--legacy-resource' : ' resource-download-box--content'; ?>"
|
||||
<section class="widget resource-download-box resource-download-box--v2<?php echo $gate_blocked ? ' is-blocked' : ''; ?> resource-download-box--<?php echo esc_attr($context_variant); ?>"
|
||||
data-post-id="<?php echo esc_attr((string) $post_id); ?>"
|
||||
data-price="<?php echo esc_attr((string) ($meta['price'] ?? 0)); ?>"
|
||||
data-credit="<?php echo $credit_active ? '1' : '0'; ?>"
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* Resource Meta Box
|
||||
*
|
||||
* 单篇资源页用:版本/大小/授权/兼容/演示 等元信息表。
|
||||
* 统一资源/付费内容侧栏信息表。
|
||||
*
|
||||
* 由 single-aksrt_resource.php 调用:
|
||||
* 由统一 single.php / 资源内容上下文调用:
|
||||
* set_query_var('aksrt_resource_meta', $meta);
|
||||
* get_template_part('templates/parts/resource-meta-box');
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user