feat(frontend): replace article system with Zibll 9.0

This commit is contained in:
2026-08-18 16:06:47 +08:00
parent 2881c69e9c
commit 0f2ac6c34a
69 changed files with 2603 additions and 4163 deletions
+33 -1
View File
@@ -359,6 +359,17 @@
</div>
</div>
<!-- Fieldset (single nested object) -->
<div v-else-if="schema.type === 'fieldset'" class="aksrt-field__fieldset">
<AksField
v-for="field in (schema.fields || [])"
:key="field.key"
:schema="field"
:model-value="fieldsetValue(field)"
@update:model-value="updateFieldsetValue(field.key, $event)"
/>
</div>
<!-- Repeater (array of objects) — inline expand (default) -->
<div v-else-if="schema.type === 'repeater' && schema.ui !== 'list-modal'" class="aksrt-field__repeater">
<div
@@ -529,7 +540,7 @@
* AksField — renders a single form field based on its schema definition.
*
* Supported types: switch, input/text, textarea, number, select, radio,
* checkbox, color, icon, media, slider, code, alert, repeater (inline|list-modal), custom (slot).
* checkbox, color, icon, media, slider, code, alert, fieldset, repeater (inline|list-modal), custom (slot).
*/
import { computed, ref, onMounted, watch } from 'vue'
import FaIcon from './FaIcon.vue'
@@ -553,6 +564,20 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue'])
function fieldsetValue(field) {
const current = props.modelValue && typeof props.modelValue === 'object' && !Array.isArray(props.modelValue)
? props.modelValue
: {}
return Object.prototype.hasOwnProperty.call(current, field.key) ? current[field.key] : field.default
}
function updateFieldsetValue(key, value) {
const current = props.modelValue && typeof props.modelValue === 'object' && !Array.isArray(props.modelValue)
? props.modelValue
: {}
emit('update:modelValue', { ...current, [key]: value })
}
/** Normalize options: support both string[] and {label, value}[] */
const normalizedOptions = computed(() => {
const opts = props.schema.options || []
@@ -974,6 +999,13 @@ function confirmRepeaterModal() {
}
/* Repeater */
.aksrt-field__fieldset {
padding: 14px;
border: 1px solid #eef1f6;
border-radius: 8px;
background: #fafbfc;
}
.aksrt-field__repeater {
display: flex;
flex-direction: column;
@@ -140,7 +140,7 @@
<n-card class="aksrt-section-card" style="margin-bottom:16px;">
<template #header><strong>列表显示</strong></template>
<n-alert type="info" :show-icon="false">
首页文章列表/卡片模式、样式变体与缩略图比例已统一到「文章&amp;列表 → 文章列表」设置(对齐 Zibll 全局 list_type / list_card_home)。此处不再单独维护 homepage_card_style / 默认视图。
首页文章列表/卡片模式、样式变体与缩略图比例统一由「文章&amp;列表 → 文章列表」中的 Zibll 全局字段控制。
</n-alert>
</n-card>
@@ -224,11 +224,7 @@ const form = reactive({
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_view: 'list',
homepage_sort_ajax_enabled: true,
homepage_sticky_tabs_enabled: true,
home_list_sort_dropdown: false,
@@ -294,11 +290,7 @@ async function loadSettings() {
form.home_exclude_posts = Array.isArray(d.home_exclude_posts) ? d.home_exclude_posts : []
form.home_exclude_cats = Array.isArray(d.home_exclude_cats) ? d.home_exclude_cats : []
form.home_lists = Array.isArray(d.home_lists) ? d.home_lists : []
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_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_list_sort_dropdown = !!d.home_list_sort_dropdown
@@ -313,7 +313,7 @@ export const pageDisplaySchemas = {
user_home_tabs_mobile_hide: '',
user_home_sidebar: false,
user_home_cover: true,
user_home_route_identifier: 'nicename',
user_home_route_identifier: 'nicename',
user_home_follow: true,
user_home_posts_per_page: 10,
user_home_avatar: true,
@@ -333,7 +333,7 @@ export const pageDisplaySchemas = {
icon: 'fas fa-th-large',
fields: [
{ key: 'user_home_cover', label: '封面区域', type: 'switch', default: true, help: '用户主页顶部封面图' },
{ key: 'user_home_route_identifier', label: '主页 URL 标识', type: 'select', default: 'nicename', options: [{ label: '用户名 URL slug', value: 'nicename' }, { label: '数字用户 ID', value: 'uid' }] },
{ key: 'user_home_route_identifier', label: '主页 URL 标识', type: 'select', default: 'nicename', options: [{ label: '用户名 URL slug', value: 'nicename' }, { label: '数字用户 ID', value: 'uid' }] },
{ key: 'user_home_sidebar', label: '侧边栏(已弃用)', type: 'switch', default: false, help: '公开主页为通栏布局(对齐 Zibll author);运行时强制关闭。交易服务请去用户中心。' },
{ key: 'user_home_follow', label: '关注按钮', type: 'switch', default: true },
{ key: 'user_home_posts_per_page', label: '每页文章数', type: 'number', default: 10, min: 5, max: 50 },
@@ -929,15 +929,11 @@ export const pageDisplaySchemas = {
key: 'page_display.homepage',
title: '首页配置',
icon: 'fas fa-home',
description: '配置首页主列表、分类 Tab、卡片样式与首页交互。实际编辑界面在 HomepageSettings.vue(customPage),此处补齐 page_display 的 schema 契约。',
description: '配置首页主列表、分类 Tab 与首页交互。文章列表视觉统一由文章列表设置控制。',
defaults: {
homepage_tabs: [],
homepage_card_style: 'default',
homepage_multi_thumb_enabled: false,
homepage_multi_thumb_min_images: 3,
homepage_sidebar_mini_enabled: true,
homepage_default_sort: 'date',
homepage_default_view: 'list',
homepage_sort_ajax_enabled: true,
homepage_sticky_tabs_enabled: true,
home_posts_list_s: true,
@@ -986,34 +982,9 @@ export const pageDisplaySchemas = {
},
{
key: 'cards-sidebar',
title: '卡片与侧栏',
title: '侧栏与交互',
icon: 'fas fa-columns',
fields: [
{
key: 'homepage_card_style',
label: '卡片风格(已弃用)',
type: 'radio',
default: 'default',
options: [
{ label: '默认', value: 'default' },
{ label: '风格 2', value: 'style2' },
{ label: '风格 3', value: 'style3' },
],
help: '已弃用:请改用「文章列表」中的列表/卡片样式设置。',
},
{ key: 'homepage_multi_thumb_enabled', label: '多图卡片(已弃用)', type: 'switch', default: true, help: '请改用文章列表缩略图/多图设置。' },
{ key: 'homepage_multi_thumb_min_images', label: '最少图片数(已弃用)', type: 'number', default: 3, min: 2, max: 4 },
{
key: 'homepage_default_view',
label: '默认视图(已弃用)',
type: 'radio',
default: 'list',
options: [
{ label: '列表', value: 'list' },
{ label: '卡片', value: 'card' },
],
help: 'SSR 以文章列表全局设置为准;此字段仅作兼容保留。',
},
{ key: 'homepage_sidebar_mini_enabled', label: '迷你侧栏列表', type: 'switch', default: true },
{ key: 'homepage_sort_ajax_enabled', label: '排序栏 AJAX', type: 'switch', default: true },
],
@@ -1,237 +1,104 @@
/**
* Post list — list section (Zibll-aligned admin contract).
* Keys match PHP AKSRT_Admin_Schema_Post_List_List / Zibll option IDs.
*/
/** Zibll 9.0 article-list settings. */
export const listSchema = {
key: 'post_list.list',
title: '文章列表',
icon: 'fas fa-list',
description: '对齐 Zibll 文章列表:默认排序、置顶范围、翻页模式(数字/AJAX/自动加载)与列表显示部件。',
description: '文章列表模式、UI、标签和翻页行为。',
defaults: {
list_orderby: 'modified',
post_time_source: 'modified',
sticky_s: ['home', 'cat'],
target_blank: false,
item_heading_bold: false,
post_list_author: true,
post_list_time: true,
list_meta_show: 'like',
list_badge_show: ['pay', 'tag', 'cat'],
list_badge_show: ['pay', 'cat', 'tag'],
list_show_type: 'separate',
list_type: 'thumb',
list_card_home: false,
list_card_tag: false,
list_card_author: false,
list_card_cat: [],
list_list_option: { style: 'null', img_position: 'left', scale: 70 },
list_card_option: { style: 'null', scale: 70 },
mult_thumb_cat: [],
paging_ajax_s: '1',
paging_ajax_ias_s: true,
ias_max: 3,
ajax_trigger: '加载更多',
ajax_nomore: '没有更多了',
post_card_style: 'thumb',
post_excerpt_length: 120,
post_list_per_page: 12,
list_show_type: 'separate',
list_list_style: '',
list_list_img_position: 'left',
list_list_scale: 70,
list_card_style: '',
list_card_scale: 70,
list_card_home: false,
list_card_cat: [],
list_card_tag: false,
list_card_author: false,
ajax_trigger: '<i class="fa fa-angle-right"></i>加载更多',
ajax_nomore: '没有更多内容了',
},
groups: [
{
key: 'order',
title: '默认排序与置顶',
icon: 'fas fa-sort',
fields: [
{
key: 'list_orderby',
label: '默认排序方式',
type: 'radio',
default: 'modified',
options: [
{ label: '发布时间', value: 'date' },
{ label: '更新时间', value: 'modified' },
{ label: 'WP默认', value: 'default' },
],
help: '文章列表全局默认排序(Zibll list_orderby)',
},
{
key: 'sticky_s',
label: '显示置顶文章',
type: 'checkbox',
default: ['home', 'cat'],
options: [
{ label: '首页', value: 'home' },
{ label: '分类页', value: 'cat' },
{ label: '标签页', value: 'tag' },
],
},
key: 'order', title: '默认排序与置顶', icon: 'fas fa-sort', fields: [
{ key: 'list_orderby', label: '默认排序方式', type: 'radio', default: 'modified', options: [
{ label: '发布时间', value: 'date' }, { label: '更新时间', value: 'modified' }, { label: 'WP默认', value: 'default' },
] },
{ key: 'post_time_source', label: '时间显示数据源', type: 'radio', default: 'modified', options: [
{ label: '发布时间', value: 'date' }, { label: '更新时间', value: 'modified' },
] },
{ key: 'sticky_s', label: '显示置顶文章', type: 'checkbox', default: ['home', 'cat'], options: [
{ label: '首页', value: 'home' }, { label: '分类页', value: 'cat' }, { label: '标签页', value: 'tag' },
] },
],
},
{
key: 'display',
title: '列表显示',
icon: 'fas fa-eye',
fields: [
key: 'display', title: '列表显示', icon: 'fas fa-eye', fields: [
{ key: 'target_blank', label: '新窗口打开文章', type: 'switch', default: false },
{ key: 'item_heading_bold', label: '列表标题粗体显示', type: 'switch', default: false },
{ key: 'post_list_author', label: '显示文章作者', type: 'switch', default: true },
{
key: 'post_list_time',
label: '显示文章时间',
type: 'switch',
default: true,
help: '建议作者与时间至少开启一项',
},
{
key: 'list_meta_show',
label: '列表小部件(移动端优先)',
type: 'radio',
default: 'like',
options: [
{ label: '阅读量', value: 'view' },
{ label: '点赞数', value: 'like' },
{ label: '评论', value: 'comm' },
],
},
{
key: 'list_badge_show',
label: '列表徽章',
type: 'checkbox',
default: ['pay', 'tag', 'cat'],
options: [
{ label: '付费', value: 'pay' },
{ label: '分类', value: 'cat' },
{ label: '标签', value: 'tag' },
],
},
{ key: 'post_list_time', label: '显示文章时间', type: 'switch', default: true },
{ key: 'list_meta_show', label: '列表小部件(移动端优先)', type: 'radio', default: 'like', options: [
{ label: '阅读量', value: 'view' }, { label: '点赞数', value: 'like' }, { label: '评论', value: 'comm' },
] },
{ key: 'list_badge_show', label: '显示列表标签', type: 'checkbox', default: ['pay', 'cat', 'tag'], options: [
{ label: '付费信息', value: 'pay' }, { label: '分类', value: 'cat' }, { label: '标签', value: 'tag' },
] },
],
},
{
key: 'paging',
title: '列表翻页',
icon: 'fas fa-ellipsis-h',
fields: [
{
key: 'paging_ajax_s',
label: '列表翻页模式',
type: 'radio',
default: '1',
options: [
{ label: 'AJAX 追加列表翻页', value: '1' },
{ label: '数字翻页按钮', value: '0' },
],
help: '对齐 Zibll paging_ajax_s',
},
{
key: 'paging_ajax_ias_s',
label: 'AJAX 自动加载',
type: 'switch',
default: true,
dependsOn: { key: 'paging_ajax_s', value: '1' },
help: '滚动到列表尽头时自动加载下一页',
},
{
key: 'ias_max',
label: '自动加载页数',
type: 'number',
default: 3,
min: 0,
max: 10,
dependsOn: { key: 'paging_ajax_s', value: '1' },
help: '0 表示不限制',
},
{
key: 'ajax_trigger',
label: '加载更多文案',
type: 'input',
default: '加载更多',
dependsOn: { key: 'paging_ajax_s', value: '1' },
},
{
key: 'ajax_nomore',
label: '没有更多文案',
type: 'input',
default: '没有更多了',
dependsOn: { key: 'paging_ajax_s', value: '1' },
},
key: 'layout', title: '列表模式与 UI', icon: 'fas fa-th-large', fields: [
{ key: 'list_show_type', label: '列表样式', type: 'radio', default: 'separate', options: [
{ label: '分离', value: 'separate' }, { label: '无间距', value: 'no_margin' },
] },
{ key: 'list_type', label: '默认列表模式', type: 'radio', default: 'thumb', options: [
{ label: '列表文字模式', value: 'text' },
{ label: '列表图文模式', value: 'thumb' },
{ label: '列表自动图文模式', value: 'thumb_if_has' },
{ label: '卡片模式', value: 'card' },
], help: '文字、自动图文和多图模式仅在开启侧栏的页面有效。' },
{ key: 'list_card_home', label: '首页列表卡片模式', type: 'switch', default: false, dependsOn: { key: 'list_type', not: true, value: 'card' } },
{ key: 'list_card_tag', label: '标签页列表卡片模式', type: 'switch', default: false, dependsOn: { key: 'list_type', not: true, value: 'card' } },
{ key: 'list_card_author', label: '用户页列表卡片模式', type: 'switch', default: false, dependsOn: { key: 'list_type', not: true, value: 'card' } },
{ key: 'list_card_cat', label: '分类页自定义卡片模式', type: 'taxonomy_select', taxonomy: 'category', multiple: true, default: [], dependsOn: { key: 'list_type', not: true, value: 'card' } },
{ key: 'list_list_option', label: '列表模式 UI 配置', type: 'fieldset', default: { style: 'null', img_position: 'left', scale: 70 }, fields: [
{ key: 'style', label: '列表样式', type: 'radio', default: 'null', options: [
{ label: '默认', value: 'null' }, { label: '样式 2', value: 'style2' },
] },
{ key: 'img_position', label: '缩略图位置', type: 'radio', default: 'left', options: [
{ label: '靠左', value: 'left' }, { label: '靠右', value: 'right' },
] },
{ key: 'scale', label: '缩略图长宽比例(%)', type: 'number', default: 70, min: 50, max: 200, step: 5 },
] },
{ key: 'list_card_option', label: '卡片模式 UI 配置', type: 'fieldset', default: { style: 'null', scale: 70 }, fields: [
{ key: 'style', label: '卡片样式', type: 'radio', default: 'null', options: [
{ label: '默认', value: 'null' }, { label: '样式 3', value: 'style3' },
] },
{ key: 'scale', label: '缩略图长宽比例(%)', type: 'number', default: 70, min: 20, max: 200, step: 5 },
] },
{ key: 'mult_thumb_cat', label: '列表多图显示分类', type: 'taxonomy_select', taxonomy: 'category', multiple: true, default: [], help: '文章格式为图片或画廊时默认显示 4 张缩略图;卡片模式或无侧栏时无效。' },
],
},
{
key: 'card',
title: '卡片与布局',
icon: 'fas fa-th-large',
fields: [
{
key: 'post_card_style',
label: '默认列表模式',
type: 'select',
default: 'thumb',
options: [
{ label: '列表图文模式', value: 'thumb' },
{ label: '列表文字模式', value: 'text' },
{ label: '列表自动图文', value: 'thumb_if_has' },
{ label: '卡片模式', value: 'card' },
{ label: '紧凑列表', value: 'compact' },
{ label: '大图列表', value: 'large_thumb' },
{ label: '多图列表', value: 'multi_thumb' },
],
help: '对齐 Zibll list_type:thumb/text/thumb_if_has 为列表,card 为卡片网格。首页可用下方「首页卡片模式」单独强制卡片。',
},
{ key: 'post_excerpt_length', label: '摘要长度', type: 'number', default: 120, min: 20, max: 500 },
{ key: 'post_list_per_page', label: '每页文章数', type: 'number', default: 12, min: 4, max: 48 },
{
key: 'list_show_type',
label: '列表间距样式',
type: 'radio',
default: 'separate',
options: [
{ label: '分隔卡片', value: 'separate' },
{ label: '无间距', value: 'no_margin' },
],
},
{
key: 'list_list_style',
label: '列表样式变体',
type: 'radio',
default: '',
options: [
{ label: '默认', value: '' },
{ label: '样式2', value: 'style2' },
],
},
{
key: 'list_list_img_position',
label: '列表缩略图位置',
type: 'radio',
default: 'left',
options: [
{ label: '左侧', value: 'left' },
{ label: '右侧', value: 'right' },
],
},
{ key: 'list_list_scale', label: '列表缩略图比例 (%)', type: 'number', default: 70, min: 50, max: 200 },
{
key: 'list_card_style',
label: '卡片样式变体',
type: 'radio',
default: '',
options: [
{ label: '默认', value: '' },
{ label: '样式3', value: 'style3' },
],
},
{ key: 'list_card_scale', label: '卡片缩略图比例 (%)', type: 'number', default: 70, min: 20, max: 200 },
{ key: 'list_card_home', label: '首页卡片模式', type: 'switch', default: false, help: '当默认模式不为卡片时,单独将首页列表强制为卡片(Zibll list_card_home)', dependsOn: { key: 'post_card_style', operator: '!=', value: 'card' } },
{
key: 'list_card_cat',
label: '分类卡片模式',
type: 'taxonomy_select',
taxonomy: 'category',
multiple: true,
default: [],
},
{ key: 'list_card_tag', label: '标签页卡片模式', type: 'switch', default: false },
{ key: 'list_card_author', label: '用户页卡片模式', type: 'switch', default: false },
key: 'paging', title: '列表翻页', icon: 'fas fa-ellipsis-h', fields: [
{ key: 'paging_ajax_s', label: '列表翻页模式', type: 'radio', default: '1', options: [
{ label: 'AJAX 追加列表翻页', value: '1' }, { label: '数字翻页按钮', value: '0' },
] },
{ key: 'paging_ajax_ias_s', label: 'AJAX 自动加载', type: 'switch', default: true, dependsOn: { key: 'paging_ajax_s', value: '1' } },
{ key: 'ias_max', label: '自动加载页数', type: 'number', default: 3, min: 0, max: 10, dependsOn: { key: 'paging_ajax_s', value: '1' } },
{ key: 'ajax_trigger', label: '翻页按钮文字', type: 'textarea', default: '<i class="fa fa-angle-right"></i>加载更多' },
{ key: 'ajax_nomore', label: '列表全部加载完毕文案', type: 'textarea', default: '没有更多内容了' },
],
},
],
@@ -19,14 +19,11 @@ export const pageSchema = {
post_lightbox_full: true,
post_lightbox_down: false,
post_lightbox_play: false,
post_related_enabled: true,
post_related_count: 6,
// Display style (Zibll img/list/text). Legacy post_related_type may still hold source or style.
post_related_style: 'img',
post_related_source: 'category',
post_related_type: 'category',
post_related_s: true,
post_related_type: 'img',
related_title: '相关推荐',
post_related_n: 6,
post_related_orderby: 'views',
post_related_title: '相关推荐',
breadcrumbs_single_text: true,
post_copyright_enabled: true,
post_copyright_text: '',
@@ -116,26 +113,23 @@ export const pageSchema = {
title: '相关推荐',
icon: 'fas fa-random',
fields: [
{ key: 'post_related_enabled', label: '显示相关推荐', type: 'switch', default: true },
{ key: 'post_related_count', label: '推荐数量', type: 'number', default: 6, min: 1, max: 20, dependsOn: { key: 'post_related_enabled', value: true } },
{ key: 'post_related_style', label: '展示样式', type: 'radio', default: 'img', options: [
{ key: 'post_related_s', label: '显示相关推荐', type: 'switch', default: true },
{ key: 'post_related_type', label: '展示样式', type: 'radio', default: 'img', options: [
{ label: '图文卡片', value: 'img' },
{ label: '列表', value: 'list' },
{ label: '纯文字', value: 'text' },
], dependsOn: { key: 'post_related_enabled', value: true }, help: '对齐 Zibll 相关文章三种样式' },
{ key: 'post_related_source', label: '推荐来源', type: 'radio', default: 'category', options: [
{ label: '同分类/标签', value: 'category' },
{ label: '同标签', value: 'tag' },
{ label: '随机', value: 'random' },
], dependsOn: { key: 'post_related_enabled', value: true } },
], dependsOn: { key: 'post_related_s', value: true }, help: '对齐 Zibll 相关文章三种样式' },
{ key: 'related_title', label: '推荐标题', type: 'input', default: '相关推荐', dependsOn: { key: 'post_related_s', value: true } },
{ key: 'post_related_n', label: '推荐数量', type: 'number', default: 6, min: 4, max: 12, step: 2, dependsOn: { key: 'post_related_s', value: true } },
{ key: 'post_related_orderby', label: '推荐排序', type: 'select', default: 'views', options: [
{ label: '浏览量', value: 'views' },
{ label: '随机', value: 'rand' },
{ label: '相关度', value: 'relevance' },
{ label: '时间', value: 'date' },
{ label: '更新时间', value: 'modified' },
], dependsOn: { key: 'post_related_enabled', value: true } },
{ key: 'post_related_title', label: '推荐标题', type: 'input', default: '相关推荐', dependsOn: { key: 'post_related_enabled', value: true } },
{ label: '发布时间', value: 'date' },
{ label: '浏览量', value: 'views' },
{ label: '点赞量', value: 'like' },
{ label: '评论量', value: 'comment_count' },
{ label: '收藏数量', value: 'favorite' },
{ label: '随机', value: 'rand' },
], dependsOn: { key: 'post_related_s', value: true } },
],
},
{
@@ -1,22 +1,23 @@
/** Zibll 9.0 list-thumbnail settings. */
const themeRoot = typeof window !== 'undefined' && window.aksrtAdminData?.themeUri
? String(window.aksrtAdminData.themeUri).replace(/\/$/, '')
: ''
const spareThumbnailDefault = [{ img: `${themeRoot}/assets/img/thumbnail.svg` }]
export const thumbSchema = {
key: 'post_list.thumb',
title: '列表缩略图',
icon: 'fas fa-images',
description: '配置缩略图来源优先级、尺寸、占位图和多图模式。',
description: '缩略图获取优先级:文章特色图像 > 外链特色图像 > 文章首图 > 分类封面图 > 备用缩略图 > 懒加载预载图。',
defaults: {
thumb_priority: 'featured,attachment,resource,custom',
thumb_fallback: 'placeholder',
thumb_spare_images: [],
thumb_aspect_ratio: '16:9',
list_thumb_fit: 'cover',
thumb_multi_enabled: false,
thumb_multi_count: 3,
list_thumb_slides_s: true,
list_thumb_video_s: true,
list_thumb_video_mute_s: true,
thumb_postfirstimg_s: true,
thumb_catimg_s: true,
mult_thumb_cat: [],
list_thumb_fit: '',
thumb_postfirstimg_size: 'medium',
spare_thumbnail: spareThumbnailDefault,
},
groups: [
{
@@ -24,44 +25,24 @@ export const thumbSchema = {
title: '图片来源',
icon: 'fas fa-image',
fields: [
{ key: 'thumb_priority', label: '图片优先级', type: 'input', default: 'featured,attachment,resource,custom', help: '逗号分隔: featured(特色图), attachment(附件), resource(资源封面), custom(自定义), post_first_img(文章首图), category_cover(分类封面)' },
{ key: 'thumb_fallback', label: '无图时处理', type: 'radio', default: 'placeholder', options: [
{ label: '显示占位图', value: 'placeholder' },
{ label: '隐藏缩略图', value: 'hide' },
{ label: '随机封面', value: 'random' },
]},
{ key: 'thumb_spare_images', label: '备用缩略图', type: 'gallery', default: [], help: '当无图处理选择"随机封面"时从此图库随机选取', dependsOn: { key: 'thumb_fallback', value: 'random' } },
{ key: 'thumb_aspect_ratio', label: '图片比例', type: 'select', default: '16:9', options: [
{ label: '16:9 宽屏', value: '16:9' },
{ label: '4:3 标准', value: '4:3' },
{ label: '1:1 正方形', value: '1:1' },
{ label: '自适应', value: 'auto' },
]},
{ key: 'list_thumb_fit', label: '缩略图填充方式', type: 'radio', default: 'cover', options: [
{ label: '填充裁剪', value: 'cover' },
{ label: '完整显示', value: 'contain' },
]},
{ key: 'list_thumb_slides_s', label: '幻灯片缩略图', type: 'switch', default: true, help: '允许幻灯片作为列表缩略图' },
{ key: 'list_thumb_video_s', label: '视频缩略图', type: 'switch', default: true, help: '鼠标悬停时自动播放视频缩略图' },
{ key: 'list_thumb_video_mute_s', label: '视频缩略图静音', type: 'switch', default: true, dependsOn: { key: 'list_thumb_video_s', value: true }, help: '视频缩略图播放时静音' },
{ key: 'thumb_postfirstimg_s', label: '自动获取文章首图', type: 'switch', default: true, help: '自动从文章内容中提取第一张图片作为缩略图' },
{ key: 'thumb_postfirstimg_size', label: '首图尺寸', type: 'select', default: 'medium', options: [
{ label: '缩略图', value: 'thumbnail' },
{ label: '中等', value: 'medium' },
{ label: '大', value: 'large' },
{ label: '原始', value: 'full' },
], dependsOn: { key: 'thumb_postfirstimg_s', value: true }, help: '自动获取文章首图时使用的 WP 图片尺寸' },
{ key: 'thumb_catimg_s', label: '自动获取分类封面', type: 'switch', default: true, help: '无特色图时使用分类封面图作为缩略图' },
],
},
{
key: 'multi',
title: '多图模式',
icon: 'fas fa-images',
fields: [
{ key: 'thumb_multi_enabled', label: '多图卡片', type: 'switch', default: false, help: '当文章有多张图片时,在列表中展示多图预览' },
{ key: 'thumb_multi_count', label: '最多显示几张', type: 'number', default: 3, min: 2, max: 6, dependsOn: { key: 'thumb_multi_enabled', value: true } },
{ key: 'mult_thumb_cat', label: '按分类多图显示', type: 'taxonomy_select', taxonomy: 'category', multiple: true, default: [], help: '选择的分类下所有文章自动显示多张缩略图' },
{ key: 'list_thumb_slides_s', label: '幻灯片缩略图', type: 'switch', default: true, help: '允许设置幻灯片为列表缩略图' },
{ key: 'list_thumb_video_s', label: '视频缩略图', type: 'switch', default: true, help: '鼠标移动到列表上自动播放' },
{ key: 'list_thumb_video_mute_s', label: '视频缩略图静音播放', type: 'switch', default: true, dependsOn: { key: 'list_thumb_video_s', value: true }, help: '部分手机浏览器无法实现静音播放' },
{ key: 'thumb_postfirstimg_s', label: '自动获取文章首图', type: 'switch', default: true },
{ key: 'thumb_catimg_s', label: '自动获取分类封面', type: 'switch', default: true },
{ key: 'list_thumb_fit', label: '缩略图填充方式', type: 'radio', default: '', options: [
{ label: 'cover 铺满', value: '' },
{ label: 'contain 等比例缩放', value: 'contain' },
] },
{ key: 'thumb_postfirstimg_size', label: '缩略图大小', type: 'radio', default: 'medium', options: [
{ label: '小尺寸', value: 'thumbnail' },
{ label: '中尺寸', value: 'medium' },
{ label: '大尺寸', value: 'large' },
{ label: '原图', value: 'full' },
] },
{ key: 'spare_thumbnail', label: '备用缩略图', type: 'repeater', default: spareThumbnailDefault, addText: '添加备用缩略图', fields: [
{ key: 'img', label: '图片', type: 'media', default: '' },
], help: '添加多张图片时自动随机获取' },
],
},
],
+3 -9
View File
@@ -78,8 +78,6 @@ export const MODULE_LIBRARY = [
options: [
{ label: '卡片', value: 'card' },
{ label: '列表', value: 'list' },
{ label: '瀑布流', value: 'masonry' },
{ label: '资源网格', value: 'grid-cms' },
],
},
],
@@ -89,7 +87,7 @@ export const MODULE_LIBRARY = [
label: '分类 Tabs',
icon: 'switcher',
desc: '多分类 Tab 切换',
defaultConfig: { cat_ids: [], count: 8, layout: 'grid-cms', title: '' },
defaultConfig: { cat_ids: [], count: 8, layout: 'card', title: '' },
fields: [
{ key: 'title', type: 'text', label: '标题' },
{ key: 'cat_ids', type: 'cats', label: '分类列表' },
@@ -99,8 +97,6 @@ export const MODULE_LIBRARY = [
options: [
{ label: '卡片', value: 'card' },
{ label: '列表', value: 'list' },
{ label: '瀑布流', value: 'masonry' },
{ label: '资源网格', value: 'grid-cms' },
],
},
],
@@ -138,8 +134,6 @@ export const MODULE_LIBRARY = [
options: [
{ label: '卡片', value: 'card' },
{ label: '列表', value: 'list' },
{ label: '瀑布流', value: 'masonry' },
{ label: '资源网格', value: 'grid-cms' },
],
},
],
@@ -460,8 +454,8 @@ export const PRESET_TEMPLATES = [
desc: 'Hero(固定骨架)+ Tabs + 最新文章 + 下载排行',
modules: [
{ type: 'hero', config: {} },
{ type: 'tabs', config: { count: 8, layout: 'grid-cms' } },
{ type: 'recent', config: { count: 8, layout: 'grid-cms' } },
{ type: 'tabs', config: { count: 8, layout: 'card' } },
{ type: 'recent', config: { count: 8, layout: 'card' } },
{ type: 'ranking', config: { metric: 'downloads', count: 6 } },
],
},
+1 -3
View File
@@ -418,11 +418,9 @@ html.dark .post-card,
html.dark .widget,
html.dark .aksrt-theme-box,
html.dark .theme-box,
html.dark .posts-item,
body.dark-theme .post-card,
body.dark-theme .widget,
body.dark-theme .aksrt-theme-box,
body.dark-theme .theme-box,
body.dark-theme .posts-item {
body.dark-theme .theme-box {
border-color: transparent;
}
@@ -41,26 +41,6 @@
padding-top: 16px;
}
.aksrt-homepage__posts > .posts-item.list {
padding: 15px;
gap: 14px;
}
.aksrt-homepage__posts > .posts-item.list .item-thumbnail {
width: 160px;
min-width: 160px;
padding-bottom: calc(160px * 0.7);
}
.aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items > span {
width: calc(33.333% - 6px);
padding-bottom: calc(var(--posts-list-scale, 70%) / 3);
}
.aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items > span:nth-child(4) {
display: none;
}
}
/* ================================================================
@@ -73,41 +53,6 @@
padding-right: 10px;
}
.aksrt-homepage__posts > .posts-item.list {
padding: 12px;
gap: 12px;
margin-bottom: 10px;
}
.aksrt-homepage__posts > .posts-item.list .item-thumbnail {
width: 120px;
min-width: 120px;
padding-bottom: calc(120px * 0.7);
}
.aksrt-homepage__posts .item-heading {
font-size: 15px;
line-height: 1.4;
}
.aksrt-homepage__posts .item-excerpt {
display: none;
}
.aksrt-homepage__posts .meta-right {
display: none;
}
/* Zibll keeps article cards in two columns throughout the mobile range. */
.aksrt-homepage__posts[data-view="card"] {
margin: -5px;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item {
width: calc(50% - 10px);
margin: 5px;
}
/* Tab skeleton: smaller thumb */
.aksrt-homepage__tab-skeleton-thumb {
width: 120px;
@@ -158,44 +103,6 @@
font-size: 13px;
}
.aksrt-homepage__posts > .posts-item.list {
padding: 10px;
gap: 10px;
border-radius: var(--radius, 8px);
}
.aksrt-homepage__posts > .posts-item.list .item-thumbnail {
width: 96px;
min-width: 96px;
padding-bottom: calc(96px * 0.7);
border-radius: 6px;
}
.aksrt-homepage__posts .item-heading {
font-size: 15px;
-webkit-line-clamp: 2;
}
.aksrt-homepage__posts .item-tags .badge {
font-size: 11px;
padding: 2px 5px;
}
.aksrt-homepage__posts .item-meta {
flex-wrap: wrap;
gap: 8px;
font-size: 12px;
}
.aksrt-homepage__posts .meta-avatar {
width: 20px;
height: 20px;
}
.aksrt-homepage__posts .meta-item {
font-size: 12px;
}
/* Tab skeleton: adapt */
.aksrt-homepage__tab-skeleton-thumb {
width: 96px;
+31 -454
View File
@@ -1,6 +1,5 @@
.aksrt-homepage__view-btn.is-active {
color: var(--color-primary, var(--color-primary));
color: var(--color-primary);
}
.aksrt-homepage__view-btn svg {
@@ -9,10 +8,6 @@
fill: currentColor;
}
/* ================================================================
7. TITLE THEME (sidebar section headers)
================================================================ */
.title-theme {
position: relative;
padding-left: 1.2em;
@@ -23,14 +18,14 @@
.title-theme::before {
position: absolute;
content: "";
width: 4px;
background: var(--color-primary, var(--color-primary));
top: 10%;
left: 2px;
bottom: 10%;
left: 2px;
width: 4px;
content: "";
background: var(--color-primary);
border-radius: 5px;
box-shadow: 1px 1px 3px -1px var(--color-primary, var(--color-primary));
box-shadow: 1px 1px 3px -1px var(--color-primary);
}
.aksrt-homepage__page-indicator {
@@ -40,29 +35,18 @@
opacity: 0.7;
}
/* ================================================================
8. PANELS
================================================================ */
.aksrt-homepage__panel[hidden] {
display: none !important;
}
.aksrt-homepage__panels {
display: block;
}
.home-tab-content {
display: block;
}
.aksrt-homepage__panel[hidden],
.index-tab-main .tab-pane[hidden],
.home-tab-content .tab-pane[hidden] {
display: none !important;
}
.aksrt-homepage__panels,
.home-tab-content {
display: block;
}
.aksrt-homepage__panel {
/* Inactive panes start transparent; active pane must be fully visible. */
opacity: 0;
transition: opacity 0.3s ease;
}
@@ -72,18 +56,15 @@
.aksrt-homepage__panel.fade.in,
.aksrt-homepage__panel.tab-pane.active,
#index-tab-main.aksrt-homepage__panel,
#index-tab-main.posts-row,
.home-tab-content .tab-pane.is-active,
.home-tab-content .tab-pane.show,
.home-tab-content .tab-pane.active,
.aksrt-homepage__panel.is-active,
.aksrt-homepage__panel.show {
opacity: 1 !important;
display: block !important;
visibility: visible !important;
opacity: 1 !important;
}
/* Beat Bootstrap .fade:not(.show){opacity:0} if fade class remains */
.home-tab-content .tab-pane.fade.is-active,
.home-tab-content .tab-pane.fade.show,
.home-tab-content .tab-pane.fade.active,
@@ -95,430 +76,26 @@
display: none;
}
.aksrt-homepage__posts.post-grid--home {
gap: 0;
}
.aksrt-homepage__posts {
display: block;
margin: 0;
}
/* List cards: wrapped (.aksrt-homepage__posts) OR direct panel children (skip_wrapper). */
.aksrt-homepage__posts > .posts-item.list,
.posts-row.ajaxpager > .posts-item.list,
#index-tab-main > .posts-item.list {
width: 100%;
margin: 15px 0;
padding: 20px;
display: flex;
flex-direction: row;
gap: 16px;
min-width: 0;
background: var(--surface-1, #fff);
border: none;
border-radius: var(--main-radius, var(--radius, 8px));
box-shadow: var(--shadow-sm);
overflow: hidden;
transition: box-shadow 0.2s ease;
font-size: 1rem;
opacity: 1;
}
.aksrt-homepage__posts > .posts-item.list:last-child,
.posts-row.ajaxpager > .posts-item.list:last-child,
#index-tab-main > .posts-item.list:last-child {
margin-bottom: 0;
}
.aksrt-homepage__posts > .posts-item.list:hover,
.posts-row.ajaxpager > .posts-item.list:hover,
#index-tab-main > .posts-item.list:hover {
box-shadow: var(--shadow);
transform: none;
}
html.dark .aksrt-homepage__posts > .posts-item.list:hover,
html.dark .posts-row.ajaxpager > .posts-item.list:hover,
html.dark #index-tab-main > .posts-item.list:hover {
box-shadow: 0 4px 16px rgba(24, 24, 24, 0.22);
}
.aksrt-homepage__posts > .posts-item.list .item-thumbnail {
position: relative;
width: 190px;
min-width: 190px;
height: 0;
padding-top: 0;
padding-bottom: calc(190px * 0.7);
border-radius: var(--radius, 8px);
overflow: hidden;
flex-shrink: 0;
}
.aksrt-homepage__posts > .posts-item.list .item-thumbnail > a {
position: absolute;
inset: 0;
display: block;
}
.aksrt-homepage__posts > .posts-item.list .item-thumbnail img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s;
}
.aksrt-homepage__posts > .posts-item.list:hover .item-thumbnail img {
transform: scale(1.02);
}
.aksrt-homepage__posts > .posts-item.list .item-thumbnail .img-badge {
position: absolute;
top: 8px;
left: 8px;
padding: 2px 6px;
border-radius: 4px;
font-size: 11px;
font-weight: 500;
line-height: 1.4;
background: rgba(0, 0, 0, 0.6);
color: #fff;
z-index: 1;
}
.aksrt-homepage__posts > .posts-item.list .thumb-items {
display: none;
}
.aksrt-homepage__posts > .posts-item.list.mult-thumb {
display: block;
}
.aksrt-homepage__posts > .posts-item.list.mult-thumb .item-thumbnail {
display: none;
}
.aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items {
display: block;
margin: 0 -3px 6px;
}
.aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items > span {
position: relative;
display: inline-block;
width: calc(25% - 6px);
height: 0;
margin: 0 3px;
padding-bottom: calc(var(--posts-list-scale, 70%) / 4);
}
.aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items.contain > span {
overflow: hidden;
background: var(--color-line, rgba(50, 50, 50, 0.06));
border-radius: var(--radius, 8px);
}
.aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items > span > img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.aksrt-homepage__posts > .posts-item.list.mult-thumb .thumb-items > span > img {
object-fit: cover;
transition: transform 0.3s;
}
.aksrt-homepage__posts > .posts-item.list.mult-thumb:hover .thumb-items > span > img {
transform: scale(1.02);
}
.aksrt-homepage__posts > .posts-item.list.mult-thumb .item-body {
width: 100%;
padding: 2px 0 0;
}
.aksrt-homepage__posts > .posts-item.list .item-body,
.posts-row.ajaxpager > .posts-item.list .item-body,
#index-tab-main > .posts-item.list .item-body {
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 8px;
margin: 0;
padding: 2px 0;
min-width: 0;
flex: 1 1 auto;
}
.aksrt-homepage__posts .item-heading,
#index-tab-main .item-heading,
.posts-row.ajaxpager .item-heading {
margin: 0 0 2px;
font-size: 18px;
font-weight: 500;
line-height: 1.4;
min-height: 0;
max-height: 2.8em;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
color: var(--color-ink);
}
.aksrt-homepage__posts .item-heading a,
#index-tab-main .item-heading a,
.posts-row.ajaxpager .item-heading a {
color: inherit;
text-decoration: none;
}
.aksrt-homepage__posts .item-heading a:hover,
#index-tab-main .item-heading a:hover,
.posts-row.ajaxpager .item-heading a:hover {
color: var(--color-primary, var(--color-primary));
}
.aksrt-homepage__posts .item-excerpt,
#index-tab-main .item-excerpt,
.posts-row.ajaxpager .item-excerpt {
margin: 0;
color: var(--main-color, #4e5358);
font-size: 14px;
line-height: 1.6;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.aksrt-homepage__posts .item-tags,
#index-tab-main .item-tags,
.posts-row.ajaxpager .item-tags {
display: flex;
align-items: center;
min-height: 0;
margin-bottom: 0;
gap: 5px;
flex-wrap: wrap;
overflow: visible;
}
.aksrt-homepage__posts .item-tags .badge {
min-height: auto;
margin-right: 0;
padding: 2px 5px;
border-radius: 4px;
font-size: 11px;
line-height: 1.4;
font-weight: 400;
}
.aksrt-homepage__posts .item-meta,
#index-tab-main .item-meta,
.posts-row.ajaxpager .item-meta {
display: flex;
align-items: center;
justify-content: space-between;
margin: 0;
padding-top: 0;
border-top: 0;
font-size: 13px;
color: var(--color-ink-3, #777);
}
.aksrt-homepage__posts .meta-author,
.aksrt-homepage__posts .meta-right {
display: flex;
align-items: center;
gap: 8px;
}
.aksrt-homepage__posts .meta-avatar {
width: 24px;
height: 24px;
border-radius: 50%;
}
.aksrt-homepage__posts .meta-name {
color: var(--color-ink);
font-weight: 500;
}
.aksrt-homepage__posts .meta-dot {
width: 4px;
height: 4px;
border-radius: 999px;
background: var(--color-ink-4, #b1b1b1);
}
.aksrt-homepage__posts .meta-item {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 13px;
white-space: nowrap;
color: var(--color-ink-3, #777);
}
.aksrt-homepage__posts .meta-item i {
font-size: 12px;
}
/* ================================================================
10. POST CARDS — CARD MODE (3-column grid)
================================================================ */
.aksrt-homepage__posts[data-view="card"] {
display: block;
margin: -8px;
font-size: 0;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item {
width: calc(33.333% - 16px);
margin: 8px;
padding: 10px;
display: inline-block;
vertical-align: top;
font-size: 1rem;
background: var(--surface-1, #fff);
border: none;
border-radius: var(--main-radius, var(--radius, 8px));
box-shadow: var(--shadow-sm);
overflow: hidden;
transition: box-shadow 0.3s ease;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item:hover {
box-shadow: var(--shadow);
}
.aksrt-homepage__posts[data-view="card"] > .posts-item.style2 {
background: transparent;
box-shadow: none;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item.style2:hover {
background: var(--surface-1, #fff);
box-shadow: 0 0 10px var(--shadow, rgba(116, 116, 116, 0.08));
}
.aksrt-homepage__posts[data-view="card"] > .posts-item.style3 {
padding: 0;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item .item-thumbnail {
position: relative;
display: block;
width: 100%;
height: 0;
padding-top: 0;
padding-bottom: var(--posts-card-scale, 70%);
min-width: unset;
border-radius: var(--radius, 8px);
overflow: hidden;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item .item-thumbnail > a {
position: absolute;
inset: 0;
display: block;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item .item-thumbnail img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item:hover .item-thumbnail img {
transform: scale(1.02);
}
.aksrt-homepage__posts[data-view="card"] > .posts-item.mult-thumb .thumb-items {
display: none;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item.mult-thumb .item-thumbnail {
display: block;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item.style3 .item-thumbnail,
.aksrt-homepage__posts[data-view="card"] > .posts-item.style3 .item-thumbnail img {
border-radius: var(--radius, 8px) var(--radius, 8px) 0 0;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item .item-body {
width: 100%;
margin: 10px 0 0;
padding: 0;
gap: 6px;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item.style3 .item-body {
margin: 0;
padding: 10px;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item .item-heading {
font-size: 14px;
font-weight: 500;
line-height: 1.4;
min-height: 2.8em;
-webkit-line-clamp: 2;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item .item-excerpt {
display: none;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item .item-meta {
font-size: 12px;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item .meta-right {
display: none;
}
/* ================================================================
VISIBILITY LOCK — homepage post stream must always paint
================================================================ */
posts.posts-item,
article.posts-item,
#index-tab-main > .posts-item,
.home-tab-content .posts-item {
opacity: 1 !important;
visibility: visible !important;
color: var(--color-ink, #333);
font-size: 1rem !important;
}
#index-tab-main > .posts-item.list,
.home-tab-content .posts-item.list {
.flex {
display: flex !important;
width: 100%;
box-sizing: border-box;
}
/* Minimal flex utilities used by post cards (zibll-style helpers) */
.flex { display: flex !important; }
.flex.xx,
.xx { flex-direction: column; }
.xx {
flex-direction: column;
}
.flex1,
.flex-1 { flex: 1 1 auto; min-width: 0; }
.jsb { justify-content: space-between; }
.ac { align-items: center; }
.jb { justify-content: space-between; }
.flex-1 {
flex: 1 1 auto;
min-width: 0;
}
.jsb,
.jb {
justify-content: space-between;
}
.ac {
align-items: center;
}
@@ -1,55 +1,3 @@
transition: transform 0.3s;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item.mult-thumb .thumb-items {
display: none;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item.mult-thumb .item-thumbnail {
display: block;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item.style3 .item-thumbnail,
.aksrt-homepage__posts[data-view="card"] > .posts-item.style3 .item-thumbnail img {
border-radius: var(--radius, 8px) var(--radius, 8px) 0 0;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item:hover .item-thumbnail img {
transform: scale(1.02);
}
.aksrt-homepage__posts[data-view="card"] > .posts-item .item-body {
width: 100%;
margin: 10px 0 0;
padding: 0;
gap: 6px;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item.style3 .item-body {
margin: 0;
padding: 10px;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item .item-heading {
font-size: 14px;
font-weight: 500;
line-height: 1.4;
min-height: 2.8em;
-webkit-line-clamp: 2;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item .item-excerpt {
display: none;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item .item-meta {
font-size: 12px;
}
.aksrt-homepage__posts[data-view="card"] > .posts-item .meta-right {
display: none;
}
/* ================================================================
11. PAGINATION
================================================================ */
@@ -231,7 +231,4 @@
padding: 0.7em;
}
.posts-item .item-thumbnail {
width: 138px;
}
}
-60
View File
@@ -1,60 +0,0 @@
/**
* Post Card · CMS (grid-cms layout)
*/
.post-grid--grid-cms {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
}
.post-grid--grid-cms .posts-item.card.posts-item--cms {
height: 100%;
border-radius: 16px;
}
.post-grid--grid-cms .posts-item--cms .item-body {
gap: 10px;
}
.post-grid--grid-cms .posts-item--cms .item-excerpt {
-webkit-line-clamp: 2;
}
.post-grid--grid-cms .posts-item--cms .item-cms-strip {
display: flex;
flex-wrap: wrap;
gap: 8px;
list-style: none;
margin: 0;
padding: 0;
}
.post-grid--grid-cms .posts-item--cms .item-cms-strip li {
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0 10px;
border-radius: 999px;
background: var(--surface-2);
color: var(--color-ink-4);
font-size: 12px;
font-weight: 500;
}
.post-grid--grid-cms .posts-item--cms .item-cms-strip li::before {
display: none;
}
@media (max-width: 640px) {
.post-grid--grid-cms {
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 14px;
}
}
@media (max-width: 380px) {
.post-grid--grid-cms {
grid-template-columns: 1fr;
}
}
File diff suppressed because it is too large Load Diff
+96
View File
@@ -4,6 +4,102 @@
(function () {
"use strict";
function renderGradientBackground(container) {
if (!container || container.dataset.aksrtGradientState || typeof window.Grade !== "function") return;
var source = container.querySelector("img");
if (!source || (!source.classList.contains("lazyloaded") && !(source.complete && source.naturalWidth > 0))) return;
container.dataset.aksrtGradientState = "loading";
window.Grade(container, null, function (result) {
var gradientData = result && result[0];
var colors = gradientData && gradientData.gradientData;
if (!gradientData || !colors || !colors[0] || !colors[1]) {
delete container.dataset.aksrtGradientState;
return;
}
var opacity = container.getAttribute("data-opacity");
var colorName = opacity ? "rgba" : "rgb";
var alpha = opacity ? "," + opacity : "";
var color1 = colorName + "(" + colors[0].rgba.slice(0, 3).join(",") + alpha + ") 10%";
var color2 = colorName + "(" + colors[1].rgba.slice(0, 3).join(",") + alpha + ") 80%";
gradientData.element.classList.add("gradient-bg-loaded");
gradientData.element.style.backgroundImage = "linear-gradient(135deg, " + color1 + ", " + color2 + ")";
container.dataset.aksrtGradientState = "loaded";
});
}
function initGradientBackgrounds(root) {
var scope = root || document;
if (scope.nodeType === 1 && scope.matches(".gradient-bg")) {
renderGradientBackground(scope);
}
scope.querySelectorAll(".gradient-bg").forEach(renderGradientBackground);
}
document.addEventListener("lazyloaded", function (event) {
if (!(event.target instanceof Element) || !event.target.matches(".gradient-bg img")) return;
renderGradientBackground(event.target.closest(".gradient-bg"));
}, true);
function initPostThumbMedia(root) {
var scope = root || document;
scope.querySelectorAll("[data-post-thumb-slider]").forEach(function (el) {
if (el.dataset.aksrtThumbSliderBound === "1" || typeof Swiper === "undefined") return;
el.dataset.aksrtThumbSliderBound = "1";
new Swiper(el, {
slidesPerView: 1,
loop: el.querySelectorAll(".swiper-slide").length > 1,
pagination: {
el: el.querySelector(".swiper-pagination"),
clickable: true,
},
});
});
scope.querySelectorAll("[data-post-thumb-video]").forEach(function (box) {
if (box.dataset.aksrtThumbVideoBound === "1") return;
box.dataset.aksrtThumbVideoBound = "1";
var video = box.querySelector("video");
if (!video) return;
function loadVideo() {
if (!video.getAttribute("src") && video.dataset.src) {
video.setAttribute("src", video.dataset.src);
video.load();
}
}
function playVideo() {
loadVideo();
var result = video.play();
var postItem = box.closest(".posts-item");
if (postItem) postItem.classList.add("thumb-dplayer-playing");
if (result && typeof result.catch === "function") result.catch(function () {});
}
function pauseVideo() {
video.pause();
var postItem = box.closest(".posts-item");
if (postItem) postItem.classList.remove("thumb-dplayer-playing");
}
var item = box.closest(".item-thumbnail") || box;
item.addEventListener("mouseenter", playVideo);
item.addEventListener("mouseleave", pauseVideo);
item.addEventListener("focusin", playVideo);
item.addEventListener("focusout", pauseVideo);
});
}
window.AksrtFrontend.register("aksrt-post-thumb-media", function (root) {
initPostThumbMedia(root);
initGradientBackgrounds(root);
});
function initRelatedSwiper() {
var el = document.querySelector(".related-swiper[data-swiper-config]");
if (!el || typeof Swiper === "undefined") return;
+28 -17
View File
@@ -9,7 +9,7 @@
}
function initAjaxPagination(root) {
var containers = (root || document).querySelectorAll(".aksrt-pagination-ajax, .ajax-pagination");
var containers = (root || document).querySelectorAll("[data-aksrt-pagination], .aksrt-comment-pagination");
if (!containers.length) return;
var triggerText = (window.aksrtData && aksrtData.ajaxTrigger) || "加载更多";
@@ -29,8 +29,9 @@
var commentOrder = container.dataset.commentOrder || "newest";
var loading = false;
var failed = false;
var loadMoreBtn = container.querySelector(".aksrt-load-more-btn, .ajax-next");
var indicator = container.querySelector(".aksrt-loading-indicator");
var clickTarget = container.querySelector(".next-page.ajax-next, .ias-btn") || container;
var loadMoreBtn = container.querySelector("[data-aksrt-load-more]") || clickTarget;
var indicator = container.querySelector(".post_ajax_loader");
var successfulAutoLoads = 0;
var iasMax = isComment
? ((window.aksrtData && typeof aksrtData.commentIasMax !== "undefined") ? parseInt(aksrtData.commentIasMax, 10) : 0)
@@ -68,13 +69,19 @@
function stopInfinite(markNomore) {
container.classList.remove("ias-pending");
if (markNomore && loadMoreBtn) {
loadMoreBtn.textContent = nomoreText;
loadMoreBtn.innerHTML = nomoreText;
loadMoreBtn.classList.remove("is-loading");
loadMoreBtn.classList.add("ajax-nomore");
var nextWrap = loadMoreBtn.closest(".next-page");
if (nextWrap) nextWrap.classList.add("no-more");
loadMoreBtn.style.pointerEvents = "none";
} else if (loadMoreBtn && !loadMoreBtn.classList.contains("ajax-nomore")) {
loadMoreBtn.classList.remove("is-loading");
loadMoreBtn.textContent = failed ? errorText : triggerText;
if (failed) {
loadMoreBtn.textContent = errorText;
} else {
loadMoreBtn.innerHTML = triggerText;
}
loadMoreBtn.style.pointerEvents = "";
}
}
@@ -164,7 +171,7 @@
target.appendChild(newItems[0]);
}
}
if (isComment && window.AksrtFrontend) {
if (window.AksrtFrontend) {
AksrtFrontend.rehydrate(target, "ajax");
}
nextPage++;
@@ -191,13 +198,16 @@
if (indicator) indicator.style.display = "none";
if (loadMoreBtn && !loadMoreBtn.classList.contains("ajax-nomore") && !failed) {
loadMoreBtn.classList.remove("is-loading");
loadMoreBtn.textContent = triggerText;
loadMoreBtn.innerHTML = triggerText;
if (mode === "infinite") {
var lazyTrigger = clickTarget.closest(".next-page") || clickTarget;
if (iasMax > 0 && successfulAutoLoads >= iasMax) {
stopInfinite(true);
container.classList.remove("ias-pending");
lazyTrigger.classList.remove("lazyload", "lazyloaded", "lazyloading");
lazyTrigger.removeAttribute("lazyload-action");
} else {
loadMoreBtn.classList.remove("lazyloaded", "lazyloading");
loadMoreBtn.classList.add("lazyload");
lazyTrigger.classList.remove("lazyloaded", "lazyloading");
lazyTrigger.classList.add("lazyload");
if (window.lazySizes && lazySizes.loader) {
lazySizes.loader.checkElems();
}
@@ -208,7 +218,7 @@
}
if (loadMoreBtn) {
loadMoreBtn.addEventListener("click", function(e) {
clickTarget.addEventListener("click", function(e) {
e.preventDefault();
if (loadMoreBtn.dataset.jumpComments === "1") {
var jumpInput = container.querySelector(".jump-input");
@@ -228,14 +238,14 @@
var archiveMax = parseInt(archiveJumpInput.dataset.maxPages || String(maxPages), 10) || maxPages;
archiveTargetPage = Math.max(1, Math.min(archiveMax, archiveTargetPage));
var archiveUrl = new URL(window.location.href);
archiveUrl.searchParams.set("paged", String(archiveTargetPage));
archiveUrl.searchParams.set(loadMoreBtn.dataset.pageVar || "paged", String(archiveTargetPage));
window.location.href = archiveUrl.toString();
return;
}
var fromAuto = loadMoreBtn.dataset.lazyAuto === "1";
delete loadMoreBtn.dataset.lazyAuto;
var fromAuto = clickTarget.dataset.lazyAuto === "1";
delete clickTarget.dataset.lazyAuto;
if (fromAuto && iasMax > 0 && successfulAutoLoads >= iasMax) {
stopInfinite(true);
container.classList.remove("ias-pending");
return;
}
// Manual click can recover from a previous auto-load failure.
@@ -246,8 +256,9 @@
if (mode === "infinite") {
if ((isComment && window.aksrtData && aksrtData.commentIasAuto === false) || !hasAjaxConfig()) {
loadMoreBtn.classList.remove("lazyload");
loadMoreBtn.removeAttribute("lazyload-action");
var autoTrigger = clickTarget.closest(".next-page") || clickTarget;
autoTrigger.classList.remove("lazyload");
autoTrigger.removeAttribute("lazyload-action");
return;
}
container.classList.add("ias-pending");
+1
View File
@@ -0,0 +1 @@
(function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.Grade=e()}})(function(){return function e(t,n,r){function i(o,s){if(!n[o]){if(!t[o]){var u="function"==typeof require&&require;if(!s&&u)return u(o,!0);if(a)return a(o,!0);var c=new Error("Cannot find module '"+o+"'");throw c.code="MODULE_NOT_FOUND",c}var g=n[o]={exports:{}};t[o][0].call(g.exports,function(e){var n=t[o][1][e];return i(n||e)},g,g.exports,e,t,n,r)}return n[o].exports}for(var a="function"==typeof require&&require,o=0;o<r.length;o++)i(r[o]);return i}({1:[function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=["webkit"],o=function(){function e(t,n,i){r(this,e),this.callback=i||null,this.container=t;var a=this.container.querySelector(n||"img");if(this.gradientData=[],a&&this.container){this.canvas=document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.imageData=[];var o=this;o.image=new Image,o.image.crossOrigin="Anonymous",o.image.src=a.getAttribute("data-src")||a.getAttribute("src"),o.image.onload=function(){o.readImage()}}}return i(e,[{key:"readImage",value:function(){this.imageDimensions={width:100,height:100},this.render()}},{key:"getImageData",value:function(){var e=this.ctx.getImageData(0,0,this.imageDimensions.width,this.imageDimensions.height).data;this.imageData=Array.from(e)}},{key:"getChunkedImageData",value:function(){var e=4,t=this.imageData.reduce(function(t,n,r){var i=Math.floor(r/e);return t[i]||(t[i]=[]),t[i].push(n),t},[]),n=t.filter(function(e){var t=e[0],n=e[1],r=e[2],i=Math.max(Math.abs(t-n),Math.abs(t-r),Math.abs(n-r));return i>20});return(!n||n.length<2)&&(n=t.filter(function(e){return e.slice(0,2).every(function(e){return e<245})&&e.slice(0,2).every(function(e){return e>10})})),n}},{key:"getRGBAGradientValues",value:function(e){return e.map(function(e,t){return"rgb("+e.rgba.slice(0,3).join(",")+") "+(0==t?"0%":"75%")}).join(",")}},{key:"getCSSGradientProperty",value:function(e){var t=this.getRGBAGradientValues(e);return a.map(function(e){return"background-image: -"+e+"-linear-gradient(\n 135deg,\n "+t+"\n )"}).concat(["background-image: linear-gradient(\n 135deg,\n "+t+"\n )"]).join(";")}},{key:"getMiddleRGB",value:function(e,t){var n=0,r=(n+1)/2,i=1-r,a=[parseInt(e[0]*r+t[0]*i),parseInt(e[1]*r+t[1]*i),parseInt(e[2]*r+t[2]*i)];return a}},{key:"getSortedValues",value:function(e){var t=Object.keys(e).map(function(t){var n=t,r=t.split("|"),i=(299*r[0]+587*r[1]+114*r[2])/1e3;return{rgba:n.split("|"),occurs:e[t],brightness:i}}).sort(function(e,t){return e.occurs-t.occurs}).reverse().slice(0,10);return t.sort(function(e,t){return e.brightness-t.brightness}).reverse()}},{key:"getTextProperty",value:function(e){var t=this.getMiddleRGB(e[0].rgba.slice(0,3),e[1].rgba.slice(0,3)),n=Math.round((299*parseInt(t[0])+587*parseInt(t[1])+114*parseInt(t[2]))/1e3);return n>125?"color: #000":"color: #fff"}},{key:"getTopValues",value:function(e){var t=this.getSortedValues(e);return[t[0],t[t.length-1]]}},{key:"getUniqValues",value:function(e){return e.reduce(function(e,t){var n=t.join("|");return e[n]?(e[n]=++e[n],e):(e[n]=1,e)},{})}},{key:"renderGradient",value:function(){var e=window.localStorage,t="grade-"+this.image.getAttribute("src"),n=null;if(e&&e.getItem(t)&&(n=JSON.parse(e.getItem(t))),!n||!n[0]){var r=this.getChunkedImageData();n=this.getTopValues(this.getUniqValues(r)),e&&e.setItem(t,JSON.stringify(n))}if(this.callback)return this.gradientData=n,void this.callback([{element:this.container,gradientData:n}]);var i=this.getCSSGradientProperty(n),a=this.getTextProperty(n),o=(this.container.getAttribute("style")||"")+"; "+i+"; "+a;this.container.setAttribute("style",o)}},{key:"render",value:function(){this.canvas.width=this.imageDimensions.width,this.canvas.height=this.imageDimensions.height,this.ctx.drawImage(this.image,0,0,this.imageDimensions.width,this.imageDimensions.height),this.getImageData(),this.renderGradient()}}]),e}();t.exports=function(e,t,n){var r=function(e,t,n){var r=new o(e,t,n),i=r.gradientData;return i.length?{element:e,gradientData:i}:null},i=(NodeList.prototype.isPrototypeOf(e)?Array.from(e).map(function(e){return r(e,t,n)}):[r(e,t,n)]).filter(Boolean);if(i.length)return n(i)}},{}]},{},[1])(1)});
+5 -110
View File
@@ -1,7 +1,7 @@
/**
* Homepage Fixed - Interactive Layer (v2.0 Zibll-aligned)
*
* Unified AJAX protocol for homepage tabs, sort, pagination, and view toggle.
* Unified AJAX protocol for homepage tabs, sort, and pagination.
* Uses Zibll-style ajaxpager DOM conventions and custom event flow:
* post_ajax.before → fetch → post_ajax.ed → aksrt:posts:rendered
*
@@ -11,34 +11,18 @@
(function () {
'use strict';
var STORAGE_KEY = 'aksrt_homepage_view_mode';
var SORT_QUERY_KEY = 'home_sort';
var DEFAULT_SORT = 'modified';
var DEFAULT_VIEW = 'list';
var REST_PATH = '/wp-json/aksrt/v1/homepage/tab-posts';
/* ============================================================
* Utilities
* ============================================================ */
function safeLocalStorage() {
try { return window.localStorage; } catch (e) { return null; }
}
function getViewMode() {
var store = safeLocalStorage();
if (store) {
var saved = store.getItem(STORAGE_KEY);
if (saved === 'card' || saved === 'list') return saved;
}
return getDefaultView();
}
function setViewMode(mode) {
var store = safeLocalStorage();
if (store) { try { store.setItem(STORAGE_KEY, mode); } catch (e) { /* */ } }
}
function getRenderedPostCount(scope) {
if (!scope) return 0;
return scope.querySelectorAll('.posts-item, .posts-mini').length;
@@ -63,8 +47,8 @@
}
function getDefaultView() {
var configured = window.aksrtData && aksrtData.homepageDefaultView;
return configured === 'card' || configured === 'list' ? configured : DEFAULT_VIEW;
var panel = document.querySelector('[data-home-tab-panel][data-view]');
return panel && panel.getAttribute('data-view') === 'card' ? 'card' : 'list';
}
function isSortAjaxEnabled(sortbar) {
@@ -119,8 +103,8 @@
}
function getStreamViewMode(stream) {
var activeBtn = stream.querySelector('.aksrt-homepage__view-btn.is-active');
return (activeBtn && activeBtn.getAttribute('data-view-mode')) || getViewMode();
var panel = getActivePanel(stream);
return panel && panel.getAttribute('data-view') === 'card' ? 'card' : 'list';
}
function getActivePanel(stream) {
@@ -153,7 +137,6 @@
'&page=' + encodeURIComponent(options.page || 1) +
'&per_page=' + encodeURIComponent(options.perPage || 10) +
'&sort=' + encodeURIComponent(options.sort || getDefaultSort()) +
'&view_mode=' + encodeURIComponent(options.viewMode || getDefaultView()) +
'&page_url=' + encodeURIComponent(options.pageUrl || window.location.href) +
'&panel=' + encodeURIComponent(options.panel || 'latest') +
'&source=' + encodeURIComponent(options.source || 'home') +
@@ -731,93 +714,6 @@
});
}
/* ============================================================
* View Mode Toggle
* ============================================================ */
function applyViewMode(buttons, postsContainers, mode) {
buttons.forEach(function (btn) {
var btnMode = btn.getAttribute('data-view-mode');
var isActive = btnMode === mode;
btn.classList.toggle('is-active', isActive);
btn.setAttribute('aria-pressed', isActive ? 'true' : 'false');
});
Array.prototype.forEach.call(postsContainers, function (container) {
container.setAttribute('data-view', mode);
container.querySelectorAll('.posts-item').forEach(function (item) {
item.classList.toggle('card', mode === 'card');
item.classList.toggle('list', mode === 'list');
});
});
}
function initViewToggle() {
var toggles = document.querySelectorAll('[data-aksrt-view-toggle]');
toggles.forEach(function (toggle) {
var buttons = toggle.querySelectorAll('.aksrt-homepage__view-btn');
var stream = toggle.closest('.aksrt-homepage__stream');
if (!stream) return;
function getPostsContainers() {
return stream.querySelectorAll('[data-home-tab-panel]');
}
function getActiveMode() {
var activeBtn = toggle.querySelector('.aksrt-homepage__view-btn.is-active');
return (activeBtn && activeBtn.getAttribute('data-view-mode')) || getViewMode();
}
var initialMode = getViewMode();
var activePanel = getActivePanel(stream);
var renderedMode = activePanel ? activePanel.getAttribute('data-view') : '';
applyViewMode(buttons, getPostsContainers(), initialMode);
// The persisted preference may differ from the server-rendered mode.
// Class toggling alone leaves list-only markup and its `.flex` utility in
// place, which forces a supposed card to occupy a full row. Fetch the
// matching renderer immediately so DOM and visual mode stay atomic.
if (activePanel && renderedMode !== initialMode) {
requestHomepagePanel(activePanel, {
termId: getPanelTermId(activePanel),
page: 1,
perPage: getHomepagePerPage(activePanel),
sort: getCurrentSort(stream),
viewMode: initialMode,
panel: activePanel.getAttribute('data-home-tab-panel') || 'latest',
source: 'home',
tabOrderby: getPanelTabOrderby(activePanel)
});
}
buttons.forEach(function (btn) {
btn.addEventListener('click', function () {
var mode = btn.getAttribute('data-view-mode') || getDefaultView();
var activePanel = getActivePanel(stream);
if (!activePanel || mode === getActiveMode()) return;
setViewMode(mode);
applyViewMode(buttons, getPostsContainers(), mode);
requestHomepagePanel(activePanel, {
termId: getPanelTermId(activePanel),
page: 1,
perPage: getHomepagePerPage(activePanel),
sort: getCurrentSort(stream),
viewMode: mode,
panel: activePanel.getAttribute('data-home-tab-panel') || 'latest',
source: 'home',
tabOrderby: getPanelTabOrderby(activePanel)
});
});
});
// Re-apply view mode after AJAX content renders
stream.addEventListener('aksrt:posts:rendered', function () {
applyViewMode(buttons, getPostsContainers(), getActiveMode());
});
});
}
/* ============================================================
* Init
* ============================================================ */
@@ -827,7 +723,6 @@
initSortbarDropdown();
initSortbar();
initStickyTabs();
initViewToggle();
}
if (document.readyState === 'loading') {