feat(navigation): hard-switch to Zibll navigation and Font Awesome 5

This commit is contained in:
2026-08-18 20:46:21 +08:00
parent 3c3ddac8be
commit a0b84977a2
630 changed files with 101647 additions and 11293 deletions
+1 -1
View File
@@ -43,7 +43,7 @@ $top_cats = get_terms([
<div class="term-page-header__body term-page-header__body--error">
<div>
<p class="error-hero__icon" aria-hidden="true">
<i class="far fa-compass"></i>
<i class="fa fas fa-compass"></i>
</p>
<p class="error-hero__code" id="error-title">404</p>
<h1 class="error-hero__title"><?php echo esc_html($other_page_settings['page_404_message']); ?></h1>
+1 -1
View File
@@ -152,7 +152,7 @@ $has_filter = $current_orderby !== 'date' || $current_price !== 'all' || $price_
<?php if ($has_filter) : ?>
<a class="resource-archive__reset" href="<?php echo esc_url($archive_url); ?>">
<i class="fas fa-times-circle" aria-hidden="true"></i>
<i class="fa fas fa-times-circle" aria-hidden="true"></i>
<?php esc_html_e('清除筛选', 'aksrt'); ?>
</a>
<?php endif; ?>
+8 -10
View File
@@ -9,22 +9,20 @@ export const pageDisplayApiMethods = {
getCategoryRecommendSettings() { return this.request('/settings/category-recommend') },
saveCategoryRecommendSettings(data) { return this.request('/settings/category-recommend', { method: 'POST', body: JSON.stringify(data) }) },
getCategories() { return this.request('/categories') },
getCategories(taxonomy = 'category') {
const value = Array.isArray(taxonomy) ? taxonomy.join(',') : taxonomy
return this.request(`/categories?taxonomy=${encodeURIComponent(value || 'category')}`)
},
updateCategoryMeta(id, data) { return this.request(`/categories/${id}/meta`, { method: 'POST', body: JSON.stringify(data) }) },
searchUsers(search = '', number = 20) { return this.request(`/users/search?search=${encodeURIComponent(search)}&number=${number}`) },
getBanners(kind = 'hero') { return this.request(`/banners?kind=${encodeURIComponent(kind)}`) },
getBanners() { return this.request('/banners') },
createBanner(data) { return this.request('/banners', { method: 'POST', body: JSON.stringify(data) }) },
updateBanner(id, data) { return this.request(`/banners/${id}`, { method: 'PUT', body: JSON.stringify(data) }) },
deleteBanner(id) { return this.request(`/banners/${id}`, { method: 'DELETE' }) },
getHeroes() { return this.getBanners('hero') },
createHero(data) { return this.createBanner({ ...data, kind: 'hero' }) },
updateHero(id, data) { return this.updateBanner(id, { ...data, kind: 'hero' }) },
deleteHero(id) { return this.deleteBanner(id) },
getHomepageBanners() { return this.getBanners('banner') },
createHomepageBanner(data) { return this.createBanner({ ...data, kind: 'banner' }) },
updateHomepageBanner(id, data) { return this.updateBanner(id, { ...data, kind: 'banner' }) },
getHomepageBanners() { return this.getBanners() },
createHomepageBanner(data) { return this.createBanner(data) },
updateHomepageBanner(id, data) { return this.updateBanner(id, data) },
deleteHomepageBanner(id) { return this.deleteBanner(id) },
}
+2 -2
View File
@@ -25,7 +25,7 @@
:key="i"
class="aksrt-deferred-page__feature"
>
<FaIcon icon="fas fa-check-circle" :size="14" />
<FaIcon icon="fa fas fa-check-circle" :size="14" />
<span>{{ feat }}</span>
</div>
</div>
@@ -63,7 +63,7 @@ const route = useRoute()
/** Merge direct props with route meta deferredProps */
const resolvedTitle = computed(() => props.title || route.meta?.deferredProps?.title || '功能开发中')
const resolvedDesc = computed(() => props.description || route.meta?.deferredProps?.description || '此功能正在规划开发中,将在后续版本上线。')
const resolvedIcon = computed(() => props.icon || route.meta?.deferredProps?.icon || 'fas fa-rocket')
const resolvedIcon = computed(() => props.icon || route.meta?.deferredProps?.icon || 'fa fas fa-rocket')
const resolvedStatus = computed(() => props.status || route.meta?.deferredProps?.status || 'deferred')
const resolvedPhase = computed(() => props.phase || route.meta?.deferredProps?.phase || '')
const resolvedDependsOn = computed(() => {
+1 -1
View File
@@ -12,7 +12,7 @@
defineProps({
title: { type: String, default: '功能开发中' },
desc: { type: String, default: '此功能模块正在规划中,后续版本将逐步开放。' },
icon: { type: String, default: 'fas fa-hourglass-half' },
icon: { type: String, default: 'fa fas fa-hourglass-half' },
})
</script>
@@ -15,7 +15,7 @@
class="aksrt-array-table__add"
@click="addItem"
>
<FaIcon icon="fas fa-plus" :size="12" />
<FaIcon icon="fa fas fa-plus" :size="12" />
{{ addText || '添加行' }}
</n-button>
</div>
@@ -105,13 +105,13 @@ const tableColumns = computed(() => {
render(row, rowIndex) {
return h('div', { style: 'display:flex;gap:2px' }, [
rowIndex > 0 ? h(NButton, { size: 'tiny', quaternary: true, onClick: () => moveUp(rowIndex) }, {
default: () => h(FaIcon, { icon: 'fas fa-arrow-up', size: 12 }),
default: () => h(FaIcon, { icon: 'fa fas fa-arrow-up', size: 12 }),
}) : null,
rowIndex < (props.modelValue?.length || 0) - 1 ? h(NButton, { size: 'tiny', quaternary: true, onClick: () => moveDown(rowIndex) }, {
default: () => h(FaIcon, { icon: 'fas fa-arrow-down', size: 12 }),
default: () => h(FaIcon, { icon: 'fa fas fa-arrow-down', size: 12 }),
}) : null,
h(NButton, { size: 'tiny', quaternary: true, type: 'error', onClick: () => removeItem(rowIndex) }, {
default: () => h(FaIcon, { icon: 'fas fa-trash', size: 12 }),
default: () => h(FaIcon, { icon: 'fa fas fa-trash-alt', size: 12 }),
}),
])
},
+12 -12
View File
@@ -7,7 +7,7 @@
</label>
<n-tooltip v-if="schema.help" trigger="hover">
<template #trigger>
<FaIcon icon="fas fa-question-circle" :size="13" class="aksrt-field__help-icon" />
<FaIcon icon="fa fas fa-question-circle" :size="13" class="aksrt-field__help-icon" />
</template>
{{ schema.help }}
</n-tooltip>
@@ -353,7 +353,7 @@
>
<img v-if="opt.image" :src="opt.image" :alt="opt.label" class="aksrt-field__image-select-img" />
<div v-else class="aksrt-field__image-select-placeholder">
<FaIcon :icon="opt.icon || 'fas fa-image'" :size="20" />
<FaIcon :icon="opt.icon || 'fa fas fa-image'" :size="20" />
</div>
<span class="aksrt-field__image-select-label">{{ opt.label }}</span>
</div>
@@ -386,7 +386,7 @@
:disabled="schema.disabled"
@click="removeRepeaterItem(index)"
>
<FaIcon icon="fas fa-trash" :size="12" />
<FaIcon icon="fa fas fa-trash-alt" :size="12" />
</n-button>
</div>
<div class="aksrt-field__repeater-fields">
@@ -406,7 +406,7 @@
:disabled="schema.disabled"
@click="addRepeaterItem"
>
<FaIcon icon="fas fa-plus" :size="12" style="margin-right: 6px" />
<FaIcon icon="fa fas fa-plus" :size="12" style="margin-right: 6px" />
{{ schema.addText || '添加一项' }}
</n-button>
</div>
@@ -427,7 +427,7 @@
:disabled="schema.disabled"
@click="moveRepeaterItem(index, -1)"
>
<FaIcon icon="fas fa-arrow-up" :size="12" />
<FaIcon icon="fa fas fa-arrow-up" :size="12" />
</n-button>
<n-button
v-if="index < (modelValue || []).length - 1"
@@ -436,7 +436,7 @@
:disabled="schema.disabled"
@click="moveRepeaterItem(index, 1)"
>
<FaIcon icon="fas fa-arrow-down" :size="12" />
<FaIcon icon="fa fas fa-arrow-down" :size="12" />
</n-button>
<n-button
size="tiny"
@@ -445,7 +445,7 @@
:disabled="schema.disabled"
@click="openRepeaterModal(index)"
>
<FaIcon icon="fas fa-edit" :size="12" />
<FaIcon icon="fa fas fa-edit" :size="12" />
编辑
</n-button>
<n-button
@@ -455,7 +455,7 @@
:disabled="schema.disabled"
@click="removeRepeaterItem(index)"
>
<FaIcon icon="fas fa-trash" :size="12" />
<FaIcon icon="fa fas fa-trash-alt" :size="12" />
删除
</n-button>
</div>
@@ -467,7 +467,7 @@
v-html="getRepeaterPreviewCustomIcon(item)"
/>
<i v-else-if="getRepeaterPreviewIcon(item)" :class="getRepeaterPreviewIcon(item)" aria-hidden="true" />
<FaIcon v-else icon="fas fa-star" :size="16" />
<FaIcon v-else icon="fa fas fa-star" :size="16" />
</div>
<div class="aksrt-field__repeater-list-meta">
<div class="aksrt-field__repeater-list-title">
@@ -481,7 +481,7 @@
</div>
</div>
<div v-else class="aksrt-field__repeater-empty">
<FaIcon icon="fas fa-inbox" :size="18" />
<FaIcon icon="fa fas fa-inbox" :size="18" />
<span>{{ schema.emptyText || '暂无数据' }}</span>
</div>
<n-button
@@ -491,7 +491,7 @@
:disabled="schema.disabled"
@click="openRepeaterModal(-1)"
>
<FaIcon icon="fas fa-plus" :size="12" style="margin-right: 6px" />
<FaIcon icon="fa fas fa-plus" :size="12" style="margin-right: 6px" />
{{ schema.addText || '添加一项' }}
</n-button>
@@ -600,7 +600,7 @@ async function loadTaxonomyTerms() {
if (!props.schema.taxonomy) return
taxonomyLoading.value = true
try {
const res = await api.getCategories()
const res = await api.getCategories(props.schema.taxonomy || 'category')
const items = res?.data || res || []
taxonomyOptions.value = (Array.isArray(items) ? items : []).map(t => ({
label: t.name + (t.count ? ' (' + t.count + ')' : ''),
@@ -26,7 +26,7 @@
@click.stop="toggleCollapse"
>
<FaIcon
:icon="collapsed ? 'fas fa-chevron-right' : 'fas fa-chevron-down'"
:icon="collapsed ? 'fa fas fa-chevron-right' : 'fa fas fa-chevron-down'"
:size="12"
/>
<span>{{ collapsed ? '展开' : '收起' }}</span>
@@ -17,7 +17,7 @@
clearable
>
<template #prefix>
<FaIcon icon="fas fa-search" :size="12" />
<FaIcon icon="fa fas fa-search" :size="12" />
</template>
</n-input>
</div>
@@ -87,7 +87,7 @@
<!-- Empty state -->
<div v-else class="aksrt-form-renderer__empty">
<FaIcon icon="fas fa-cog" :size="32" />
<FaIcon icon="fa fas fa-cog" :size="32" />
<p>暂无配置项</p>
</div>
@@ -95,7 +95,7 @@
<div v-if="dirty" class="aksrt-form-renderer__save-bar">
<div class="aksrt-form-renderer__save-bar__inner">
<div class="aksrt-form-renderer__save-bar__info">
<FaIcon icon="fas fa-exclamation-circle" :size="14" />
<FaIcon icon="fa fas fa-exclamation-circle" :size="14" />
<span>您有未保存的更改</span>
</div>
<div class="aksrt-form-renderer__save-bar__actions">
@@ -106,7 +106,7 @@
:loading="saving"
@click="$emit('save')"
>
<FaIcon v-if="!saving" icon="fas fa-save" :size="12" />
<FaIcon v-if="!saving" icon="fa fas fa-save" :size="12" />
保存设置
</n-button>
</div>
@@ -8,21 +8,21 @@
class="aksrt-media-field__image"
/>
<div v-else class="aksrt-media-field__file">
<FaIcon icon="fas fa-file" :size="24" />
<FaIcon icon="fa fas fa-file" :size="24" />
<span class="aksrt-media-field__filename">{{ fileName }}</span>
</div>
<div class="aksrt-media-field__overlay">
<n-button size="tiny" quaternary @click="openMediaLibrary">
<FaIcon icon="fas fa-exchange-alt" /> 更换
<FaIcon icon="fa fas fa-exchange-alt" /> 更换
</n-button>
<n-button size="tiny" quaternary type="error" @click="clearMedia">
<FaIcon icon="fas fa-trash" /> 移除
<FaIcon icon="fa fas fa-trash-alt" /> 移除
</n-button>
</div>
</div>
<div v-else class="aksrt-media-field__empty" @click="openMediaLibrary">
<FaIcon icon="fas fa-cloud-upload-alt" :size="28" />
<FaIcon icon="fa fas fa-cloud-upload-alt" :size="28" />
<span>{{ placeholder }}</span>
</div>
@@ -15,7 +15,7 @@
quaternary
@click="moveUp(index)"
>
<FaIcon icon="fas fa-arrow-up" :size="12" />
<FaIcon icon="fa fas fa-arrow-up" :size="12" />
</n-button>
<n-button
v-if="index < modelValue.length - 1"
@@ -23,7 +23,7 @@
quaternary
@click="moveDown(index)"
>
<FaIcon icon="fas fa-arrow-down" :size="12" />
<FaIcon icon="fa fas fa-arrow-down" :size="12" />
</n-button>
<n-button
size="tiny"
@@ -31,7 +31,7 @@
type="error"
@click="removeItem(index)"
>
<FaIcon icon="fas fa-trash" :size="12" />
<FaIcon icon="fa fas fa-trash-alt" :size="12" />
</n-button>
</div>
</div>
@@ -49,7 +49,7 @@
</div>
<div v-else class="aksrt-repeater__empty">
<FaIcon icon="fas fa-inbox" :size="20" />
<FaIcon icon="fa fas fa-inbox" :size="20" />
<span>{{ emptyText || '暂无数据' }}</span>
</div>
@@ -60,7 +60,7 @@
class="aksrt-repeater__add"
@click="addItem"
>
<FaIcon icon="fas fa-plus" :size="12" />
<FaIcon icon="fa fas fa-plus" :size="12" />
{{ addText || '添加项目' }}
</n-button>
</div>
+8 -8
View File
@@ -11,16 +11,16 @@
* FaIcon — Font Awesome 5 icon wrapper component.
*
* Usage:
* <FaIcon icon="fas fa-cog" />
* <FaIcon icon="fa-cog" /> → defaults to "fas" prefix
* <FaIcon icon="fab fa-github" />
* <FaIcon :size="18" icon="far fa-heart" />
* <FaIcon spin icon="fas fa-spinner" />
* <FaIcon icon="fa fas fa-cog" />
* <FaIcon icon="fa-cog" /> → defaults to solid FA5
* <FaIcon icon="fa fab fa-github" />
* <FaIcon :size="18" icon="fa fas fa-heart" />
* <FaIcon spin icon="fa fas fa-spinner" />
*/
import { computed } from 'vue'
const props = defineProps({
/** FA5 class string, e.g. "fas fa-cog", "fab fa-github", or just "fa-cog" */
/** FA5 class string, e.g. "fa fas fa-cog", "fa fab fa-github", or just "fa-cog" */
icon: { type: String, required: true },
/** Pixel size — maps to font-size */
size: { type: [Number, String], default: null },
@@ -41,10 +41,10 @@ const props = defineProps({
const iconClass = computed(() => {
const parts = []
// Auto-prefix: if only "fa-xxx" is given, default to "fas"
// Auto-prefix: if only "fa-circle" is given, use the solid FA5 style.
const raw = props.icon.trim()
if (raw.startsWith('fa-')) {
parts.push('fas', raw)
parts.push('fa', 'fas', raw)
} else {
parts.push(...raw.split(/\s+/))
}
@@ -13,7 +13,7 @@
<FaIcon v-if="modelValue" :icon="modelValue" />
</template>
<template #suffix>
<FaIcon icon="fas fa-chevron-down" :size="12" />
<FaIcon icon="fa fas fa-chevron-down" :size="12" />
</template>
</n-input>
</template>
@@ -27,7 +27,7 @@
clearable
>
<template #prefix>
<FaIcon icon="fas fa-search" :size="12" />
<FaIcon icon="fa fas fa-search" :size="12" />
</template>
</n-input>
</div>
@@ -45,11 +45,11 @@
v-for="icon in filteredIcons"
:key="icon"
class="aksrt-icon-picker__item"
:class="{ 'is-active': modelValue === `${activePrefix} ${icon}` }"
:class="{ 'is-active': modelValue === `fa ${activePrefix} ${icon}` }"
:title="icon"
@click="selectIcon(icon)"
>
<i :class="[activePrefix, icon]"></i>
<i :class="['fa', activePrefix, icon]"></i>
</div>
<div v-if="filteredIcons.length === 0" class="aksrt-icon-picker__empty">
未找到匹配图标
@@ -80,42 +80,42 @@ const activePrefix = ref('fas')
const gridRef = ref(null)
// Common FA5 icons subset — a curated list covering most admin UI needs.
// Full FA5 has 1600+ icons; this subset has ~200 of the most useful ones.
// Curated FA5 subsets for the three bundled font families.
const SOLID_ICONS = [
'fa-home', 'fa-cog', 'fa-cogs', 'fa-wrench', 'fa-sliders-h', 'fa-tools',
'fa-search', 'fa-filter', 'fa-sort', 'fa-sync', 'fa-redo', 'fa-undo',
'fa-home', 'fa-cog', 'fa-cogs', 'fa-wrench', 'fa-sliders-h', 'fa-wrench',
'fa-search', 'fa-filter', 'fa-sort', 'fa-sync-alt', 'fa-redo-alt', 'fa-undo',
'fa-plus', 'fa-minus', 'fa-times', 'fa-check', 'fa-exclamation', 'fa-info',
'fa-question', 'fa-bell', 'fa-envelope', 'fa-comment', 'fa-comments',
'fa-user', 'fa-users', 'fa-user-plus', 'fa-user-shield', 'fa-user-circle',
'fa-lock', 'fa-unlock', 'fa-key', 'fa-shield-alt', 'fa-fingerprint',
'fa-globe', 'fa-globe-americas', 'fa-link', 'fa-external-link-alt', 'fa-anchor',
'fa-image', 'fa-images', 'fa-camera', 'fa-video', 'fa-music', 'fa-file',
'fa-folder', 'fa-folder-open', 'fa-download', 'upload', 'fa-cloud',
'fa-database', 'fa-server', 'fa-hdd', 'fa-memory', 'fa-microchip',
'fa-user', 'fa-users', 'fa-user-plus', 'fa-user', 'fa-user-circle',
'fa-lock', 'fa-unlock', 'fa-key', 'fa-shield-alt', 'fa-id-badge',
'fa-globe', 'fa-globe', 'fa-link', 'fa-external-link-alt', 'fa-anchor',
'fa-image', 'fa-image', 'fa-camera', 'fa-video', 'fa-music', 'fa-file',
'fa-folder', 'fa-folder-open', 'fa-download', 'fa-upload', 'fa-cloud',
'fa-database', 'fa-server', 'fa-hdd', 'fa-microchip', 'fa-microchip',
'fa-desktop', 'fa-laptop', 'fa-mobile-alt', 'fa-tablet-alt',
'fa-chart-bar', 'fa-chart-line', 'fa-chart-pie', 'fa-chart-area',
'fa-tachometer-alt', 'fa-tasks', 'fa-clipboard', 'fa-clipboard-list',
'fa-tachometer-alt', 'fa-tasks', 'fa-clipboard', 'fa-clipboard',
'fa-list', 'fa-list-alt', 'fa-list-ol', 'fa-list-ul', 'fa-th', 'fa-th-large',
'fa-tags', 'fa-tag', 'fa-bookmark', 'fa-star', 'fa-heart', 'fa-thumbs-up',
'fa-share', 'fa-share-alt', 'fa-external-link-alt', 'fa-clipboard-check',
'fa-eye', 'fa-eye-slash', 'fa-lightbulb', 'fa-magic', 'fa-palette',
'fa-share', 'fa-share-alt', 'fa-external-link-alt', 'fa-clipboard',
'fa-eye', 'fa-eye-slash', 'fa-lightbulb', 'fa-magic', 'fa-paint-brush',
'fa-paint-brush', 'fa-font', 'fa-text-height', 'fa-bold', 'fa-italic',
'fa-code', 'fa-terminal', 'fa-bug', 'fa-exclamation-triangle',
'fa-exclamation-circle', 'fa-check-circle', 'fa-info-circle',
'fa-spinner', 'fa-circle-notch', 'fa-hourglass-half', 'fa-clock',
'fa-calendar', 'fa-calendar-alt', 'fa-history', 'fa-hourglass',
'fa-map-marker-alt', 'fa-map', 'fa-directions', 'fa-compass',
'fa-calendar', 'fa-calendar', 'fa-history', 'fa-hourglass',
'fa-map-marker-alt', 'fa-map', 'fa-road', 'fa-compass',
'fa-shopping-cart', 'fa-shopping-bag', 'fa-credit-card', 'fa-money-bill',
'fa-coins', 'fa-dollar-sign', 'fa-wallet', 'fa-receipt',
'fa-newspaper', 'fa-rss', 'fa-podcast', 'fa-megaphone',
'fa-flag', 'fa-trophy', 'fa-award', 'fa-medal', 'fa-gift',
'fa-fire', 'fa-bolt', 'fa-sun', 'fa-moon', 'fa-cloud-sun',
'fa-database', 'fa-dollar-sign', 'fa-credit-card', 'fa-file-alt',
'fa-newspaper', 'fa-rss', 'fa-podcast', 'fa-bullhorn',
'fa-flag', 'fa-trophy', 'fa-trophy', 'fa-trophy', 'fa-gift',
'fa-fire', 'fa-bolt', 'fa-sun', 'fa-moon', 'fa-cloud',
'fa-male', 'fa-female', 'fa-child', 'fa-id-card',
'fa-paper-plane', 'fa-paperclip', 'fa-at', 'fa-hashtag',
'fa-ellipsis-h', 'fa-ellipsis-v', 'fa-bars', 'fa-columns',
'fa-window-maximize', 'fa-window-minimize', 'fa-window-close',
'fa-expand', 'fa-compress', 'fa-arrows-alt', 'fa-crosshairs',
'fa-sign-in-alt', 'fa-sign-out-alt', 'fa-door-open',
'fa-sign-in-alt', 'fa-sign-out-alt', 'fa-sign-in-alt',
'fa-plug', 'fa-power-off', 'fa-redo-alt', 'fa-sync-alt',
]
@@ -135,35 +135,31 @@ const REGULAR_ICONS = [
const BRAND_ICONS = [
'fa-github', 'fa-gitlab', 'fa-bitbucket', 'fa-google', 'fa-google-plus',
'fa-facebook', 'fa-facebook-f', 'fa-twitter', 'fa-x-twitter',
'fa-instagram', 'fa-linkedin', 'fa-linkedin-in', 'fa-youtube',
'fa-weixin', 'fa-qq', 'fa-weibo', 'fa-telegram', 'fa-telegram-plane',
'fa-discord', 'fa-slack', 'fa-whatsapp', 'fa-skype',
'fa-apple', 'fa-windows', 'fa-linux', 'fa-android', 'fa-chrome',
'fa-firefox', 'fa-edge', 'fa-safari', 'fa-opera',
'fa-html5', 'fa-css3-alt', 'fa-js', 'fa-js-square', 'fa-node',
'fa-react', 'fa-vuejs', 'fa-angular', 'fa-php', 'fa-python',
'fa-java', 'fa-rust', 'fa-golang', 'fa-swift',
'fa-docker', 'fa-aws', 'fa-digital-ocean', 'fa-cloudflare',
'fa-wordpress', 'fa-joomla', 'fa-drupal', 'fa-shopify',
'fa-paypal', 'fa-stripe', 'fa-alipay', 'fa-weixin',
'fa-tiktok', 'fa-snapchat', 'fa-pinterest', 'fa-reddit',
'fa-stack-overflow', 'fa-codepen', 'fa-npm', 'fa-yarn',
'fa-twitch', 'fa-spotify', 'fa-soundcloud', 'fa-music',
'fa-bilibili',
'fa-facebook', 'fa-facebook-f', 'fa-twitter', 'fa-instagram',
'fa-linkedin', 'fa-linkedin-in', 'fa-youtube', 'fa-weixin', 'fa-qq',
'fa-weibo', 'fa-telegram', 'fa-telegram-plane', 'fa-discord', 'fa-slack',
'fa-whatsapp', 'fa-skype', 'fa-apple', 'fa-windows', 'fa-linux',
'fa-android', 'fa-chrome', 'fa-firefox', 'fa-edge', 'fa-safari',
'fa-opera', 'fa-html5', 'fa-css3-alt', 'fa-js', 'fa-node', 'fa-react',
'fa-vuejs', 'fa-angular', 'fa-php', 'fa-python', 'fa-java', 'fa-rust',
'fa-docker', 'fa-aws', 'fa-digital-ocean', 'fa-cloudflare', 'fa-wordpress',
'fa-joomla', 'fa-drupal', 'fa-shopify', 'fa-paypal', 'fa-stripe',
'fa-alipay', 'fa-tiktok', 'fa-snapchat', 'fa-pinterest', 'fa-reddit',
'fa-stack-overflow', 'fa-codepen', 'fa-npm', 'fa-yarn', 'fa-twitch',
'fa-spotify', 'fa-soundcloud',
]
const iconSets = { fas: SOLID_ICONS, far: REGULAR_ICONS, fab: BRAND_ICONS }
const filteredIcons = computed(() => {
const set = iconSets[activePrefix.value] || SOLID_ICONS
const q = search.value.toLowerCase().replace(/\s+/g, '')
const set = iconSets[activePrefix.value] || SOLID_ICONS
if (!q) return set
return set.filter(i => i.includes(q))
})
function selectIcon(icon) {
emit('update:modelValue', `${activePrefix.value} ${icon}`)
emit('update:modelValue', `fa ${activePrefix.value} ${icon}`)
}
</script>
@@ -4,27 +4,27 @@
<n-space>
<n-dropdown :options="addModuleOptions" trigger="click" @select="handleAddModule">
<n-button type="primary" size="small">
<template #icon><FaIcon icon="fas fa-plus" :size="12" /></template>
<template #icon><FaIcon icon="fa fas fa-plus" :size="12" /></template>
添加模块
</n-button>
</n-dropdown>
<n-button size="small" @click="$emit('pick-preset')">
<template #icon><FaIcon icon="fas fa-magic" :size="12" /></template>
<template #icon><FaIcon icon="fa fas fa-magic" :size="12" /></template>
应用预设
</n-button>
<n-button size="small" @click="$emit('export')">
<template #icon><FaIcon icon="fas fa-download" :size="12" /></template>
<template #icon><FaIcon icon="fa fas fa-download" :size="12" /></template>
导出
</n-button>
<n-button size="small" @click="$emit('import')">
<template #icon><FaIcon icon="fas fa-upload" :size="12" /></template>
<template #icon><FaIcon icon="fa fas fa-upload" :size="12" /></template>
导入
</n-button>
</n-space>
</div>
<div v-if="modules.length === 0" class="aksrt-module-canvas__empty">
<FaIcon icon="fas fa-th-large" :size="32" color="#c0c4cc" />
<FaIcon icon="fa fas fa-th-large" :size="32" color="#c0c4cc" />
<p>暂无首页模块,点击"添加模块"或"应用预设"开始配置。</p>
</div>
@@ -48,7 +48,7 @@
@dragend="handleDragEnd"
>
<div class="aksrt-module-canvas__item-handle" title="拖拽排序">
<FaIcon icon="fas fa-grip-vertical" :size="12" color="#c0c4cc" />
<FaIcon icon="fa fas fa-bars" :size="12" color="#c0c4cc" />
</div>
<div class="aksrt-module-canvas__item-icon">
<FaIcon :icon="getModuleIcon(mod.type)" :size="14" />
@@ -70,7 +70,7 @@
title="复制"
@click.stop="$emit('copy', index)"
>
<FaIcon icon="fas fa-copy" :size="11" />
<FaIcon icon="fa fas fa-copy" :size="11" />
</n-button>
<n-button
size="tiny"
@@ -79,7 +79,7 @@
title="删除"
@click.stop="$emit('remove', index)"
>
<FaIcon icon="fas fa-trash" :size="11" />
<FaIcon icon="fa fas fa-trash-alt" :size="11" />
</n-button>
<n-button
size="tiny"
@@ -88,7 +88,7 @@
title="上移"
@click.stop="$emit('move', index, -1)"
>
<FaIcon icon="fas fa-chevron-up" :size="11" />
<FaIcon icon="fa fas fa-chevron-up" :size="11" />
</n-button>
<n-button
size="tiny"
@@ -97,7 +97,7 @@
title="下移"
@click.stop="$emit('move', index, 1)"
>
<FaIcon icon="fas fa-chevron-down" :size="11" />
<FaIcon icon="fa fas fa-chevron-down" :size="11" />
</n-button>
</div>
</div>
@@ -157,15 +157,15 @@ const addModuleOptions = computed(() =>
key: m.type,
icon: () => {
const iconMap = {
image: 'fas fa-image', rectangle: 'fas fa-square', folder: 'fas fa-folder',
switcher: 'fas fa-columns', trophy: 'fas fa-trophy', clock: 'fas fa-clock',
tag: 'fas fa-tag', link: 'fas fa-link', code: 'fas fa-code', fire: 'fas fa-fire',
grid: 'fas fa-th', 'font-colors': 'fas fa-font', 'th-large': 'fas fa-th-large',
swap: 'fas fa-arrows-alt-v', 'question-circle': 'fas fa-question-circle',
table: 'fas fa-table', star: 'fas fa-star', handshake: 'fas fa-handshake',
'shopping-bag': 'fas fa-shopping-bag',
image: 'fa fas fa-image', rectangle: 'fa fas fa-square', folder: 'fa fas fa-folder',
switcher: 'fa fas fa-columns', trophy: 'fa fas fa-trophy', clock: 'fa fas fa-clock',
tag: 'fa fas fa-tag', link: 'fa fas fa-link', code: 'fa fas fa-code', fire: 'fa fas fa-fire',
grid: 'fa fas fa-th', 'font-colors': 'fa fas fa-font', 'th-large': 'fa fas fa-th-large',
swap: 'fa fas fa-arrows-alt-v', 'question-circle': 'fa fas fa-question-circle',
table: 'fa fas fa-table', star: 'fa fas fa-star', handshake: 'fa fas fa-handshake',
'shopping-bag': 'fa fas fa-shopping-bag',
}
return h('i', { class: iconMap[m.icon] || 'fas fa-cube', style: 'font-size:12px;margin-right:6px;' })
return h('i', { class: iconMap[m.icon] || 'fa fas fa-cube', style: 'font-size:12px;margin-right:6px;' })
},
}))
)
@@ -173,15 +173,15 @@ const addModuleOptions = computed(() =>
function getModuleIcon(type) {
const meta = MODULE_LIBRARY.find(m => m.type === type)
const iconMap = {
image: 'fas fa-image', rectangle: 'fas fa-square', folder: 'fas fa-folder',
switcher: 'fas fa-columns', trophy: 'fas fa-trophy', clock: 'fas fa-clock',
tag: 'fas fa-tag', link: 'fas fa-link', code: 'fas fa-code', fire: 'fas fa-fire',
grid: 'fas fa-th', 'font-colors': 'fas fa-font', 'th-large': 'fas fa-th-large',
swap: 'fas fa-arrows-alt-v', 'question-circle': 'fas fa-question-circle',
table: 'fas fa-table', star: 'fas fa-star', handshake: 'fas fa-handshake',
'shopping-bag': 'fas fa-shopping-bag',
image: 'fa fas fa-image', rectangle: 'fa fas fa-square', folder: 'fa fas fa-folder',
switcher: 'fa fas fa-columns', trophy: 'fa fas fa-trophy', clock: 'fa fas fa-clock',
tag: 'fa fas fa-tag', link: 'fa fas fa-link', code: 'fa fas fa-code', fire: 'fa fas fa-fire',
grid: 'fa fas fa-th', 'font-colors': 'fa fas fa-font', 'th-large': 'fa fas fa-th-large',
swap: 'fa fas fa-arrows-alt-v', 'question-circle': 'fa fas fa-question-circle',
table: 'fa fas fa-table', star: 'fa fas fa-star', handshake: 'fa fas fa-handshake',
'shopping-bag': 'fa fas fa-shopping-bag',
}
return iconMap[meta?.icon] || 'fas fa-cube'
return iconMap[meta?.icon] || 'fa fas fa-cube'
}
function getModuleLabel(type) {
@@ -1,7 +1,7 @@
<template>
<div class="aksrt-module-inspector">
<div v-if="!module" class="aksrt-module-inspector__empty">
<FaIcon icon="fas fa-mouse-pointer" :size="24" color="#c0c4cc" />
<FaIcon icon="fa fas fa-mouse-pointer" :size="24" color="#c0c4cc" />
<p>选择左侧模块查看和编辑配置</p>
</div>
@@ -138,7 +138,7 @@
@update:value="(val) => updateConfig(field.key, val)"
/>
<n-button size="tiny" quaternary @click="openMediaPicker(field.key)">
<template #icon><FaIcon icon="fas fa-image" :size="12" /></template>
<template #icon><FaIcon icon="fa fas fa-image" :size="12" /></template>
从媒体库选择
</n-button>
</div>
@@ -161,11 +161,11 @@
/>
</div>
<n-button size="tiny" quaternary type="error" @click="removeRepeaterItem(field.key, idx)">
<FaIcon icon="fas fa-times" :size="10" />
<FaIcon icon="fa fas fa-times" :size="10" />
</n-button>
</div>
<n-button size="tiny" quaternary @click="addRepeaterItem(field.key, field.fields)">
<template #icon><FaIcon icon="fas fa-plus" :size="10" /></template>
<template #icon><FaIcon icon="fa fas fa-plus" :size="10" /></template>
添加一项
</n-button>
</div>
@@ -223,15 +223,15 @@ const localConfig = computed(() => {
function getModuleIcon(type) {
const m = MODULE_LIBRARY.find(x => x.type === type)
const iconMap = {
image: 'fas fa-image', rectangle: 'fas fa-square', folder: 'fas fa-folder',
switcher: 'fas fa-columns', trophy: 'fas fa-trophy', clock: 'fas fa-clock',
tag: 'fas fa-tag', link: 'fas fa-link', code: 'fas fa-code', fire: 'fas fa-fire',
grid: 'fas fa-th', 'font-colors': 'fas fa-font', 'th-large': 'fas fa-th-large',
swap: 'fas fa-arrows-alt-v', 'question-circle': 'fas fa-question-circle',
table: 'fas fa-table', star: 'fas fa-star', handshake: 'fas fa-handshake',
'shopping-bag': 'fas fa-shopping-bag',
image: 'fa fas fa-image', rectangle: 'fa fas fa-square', folder: 'fa fas fa-folder',
switcher: 'fa fas fa-columns', trophy: 'fa fas fa-trophy', clock: 'fa fas fa-clock',
tag: 'fa fas fa-tag', link: 'fa fas fa-link', code: 'fa fas fa-code', fire: 'fa fas fa-fire',
grid: 'fa fas fa-th', 'font-colors': 'fa fas fa-font', 'th-large': 'fa fas fa-th-large',
swap: 'fa fas fa-arrows-alt-v', 'question-circle': 'fa fas fa-question-circle',
table: 'fa fas fa-table', star: 'fa fas fa-star', handshake: 'fa fas fa-handshake',
'shopping-bag': 'fa fas fa-shopping-bag',
}
return iconMap[m?.icon] || 'fas fa-cube'
return iconMap[m?.icon] || 'fa fas fa-cube'
}
function getModuleLabel(type) {
+1 -1
View File
@@ -3,7 +3,7 @@ import { renderFaIcon, customPage } from './helpers'
export const docsSection = {
key: 'tools-compat',
label: '兼容&工具',
icon: renderFaIcon('fas fa-toolbox'),
icon: renderFaIcon('fa fas fa-wrench'),
route: '/tools',
hidden: true,
children: [
@@ -3,7 +3,7 @@ import { renderFaIcon, schemaPage, customPage } from './helpers'
export const extensionsSection = {
key: 'extensions',
label: '扩展&增强',
icon: renderFaIcon('fas fa-puzzle-piece'),
icon: renderFaIcon('fa fas fa-puzzle-piece'),
route: '/extensions',
children: [
schemaPage({
@@ -3,7 +3,7 @@ import { renderFaIcon, schemaPage, customPage } from './helpers'
export const globalSection = {
key: 'global',
label: '全局&功能',
icon: renderFaIcon('fas fa-globe'),
icon: renderFaIcon('fa fas fa-globe'),
route: '/global',
children: [
schemaPage({
@@ -3,7 +3,7 @@ import { renderFaIcon, schemaPage, customPage } from './helpers'
export const pageDisplaySection = {
key: 'page-display',
label: '页面&显示',
icon: renderFaIcon('fas fa-desktop'),
icon: renderFaIcon('fa fas fa-desktop'),
route: '/page-display',
children: [
schemaPage({
@@ -42,21 +42,10 @@ export const pageDisplaySection = {
label: '顶部多功能组件',
route: '/page-display/header-components',
title: '顶部多功能组件',
desc: '配置顶部组件显示范围、轮播参数、搜索覆盖层与图标卡片。幻灯片内容见「Hero 轮播」「Banner 轮播」。',
desc: '配置顶部组件显示范围、幻灯片内容、轮播参数、搜索覆盖层与图标卡片。',
canonicalDomain: 'page_display',
section: 'header-components',
}),
customPage({
key: 'page-display-hero',
name: 'PageDisplayHero',
label: 'Hero 轮播',
route: '/page-display/hero',
title: 'Hero 轮播管理',
desc: '管理首页顶部 Hero 幻灯片内容(图片/视频、文案、图层、跳转)。显示开关与搜索/卡片配置见「顶部多功能组件」。',
component: 'HeroManager',
canonicalDomain: 'page_display',
section: 'hero',
}),
customPage({
key: 'page-display-banner',
name: 'PageDisplayBanner',
@@ -3,7 +3,7 @@ import { renderFaIcon, schemaPage, customPage } from './helpers'
export const paymentSection = {
key: 'payment',
label: '支付&付费',
icon: renderFaIcon('fas fa-wallet'),
icon: renderFaIcon('fa fas fa-credit-card'),
route: '/payment',
children: [
schemaPage({
@@ -3,7 +3,7 @@ import { renderFaIcon, customPage, schemaPage } from './helpers'
export const permissionsSection = {
key: 'permissions',
label: '功能&权限',
icon: renderFaIcon('fas fa-shield-alt'),
icon: renderFaIcon('fa fas fa-shield-alt'),
route: '/permissions',
children: [
customPage({
@@ -3,7 +3,7 @@ import { renderFaIcon, schemaPage, customPage } from './helpers'
export const postListSection = {
key: 'post-list',
label: '文章&列表',
icon: renderFaIcon('fas fa-file-alt'),
icon: renderFaIcon('fa fas fa-file-alt'),
route: '/post-list',
children: [
schemaPage({
@@ -3,7 +3,7 @@ import { renderFaIcon, customPage } from './helpers'
export const themeInfoSection = {
key: 'tools-compat',
label: '兼容&工具',
icon: renderFaIcon('fas fa-toolbox'),
icon: renderFaIcon('fa fas fa-wrench'),
route: '/tools',
hidden: true,
children: [
+1 -1
View File
@@ -3,7 +3,7 @@ import { renderFaIcon, customPage, schemaPage } from './helpers'
export const toolsSection = {
key: 'tools-compat',
label: '工具',
icon: renderFaIcon('fas fa-toolbox'),
icon: renderFaIcon('fa fas fa-wrench'),
route: '/tools',
children: [
customPage({
+1 -1
View File
@@ -7,7 +7,7 @@ import { renderFaIcon, schemaPage, customPage } from './helpers'
export const usersSection = {
key: 'users',
label: '用户&互动',
icon: renderFaIcon('fas fa-users'),
icon: renderFaIcon('fa fas fa-users'),
route: '/users',
children: [
schemaPage({
@@ -11,7 +11,7 @@
<template #header>
<div class="aksrt-card-header-row">
<div class="aksrt-card-header-row__left">
<span class="header-icon"><i class="fas fa-cog"></i></span>
<span class="header-icon"><i class="fa fas fa-cog"></i></span>
<strong class="aksrt-card-header-row__title">基础设置</strong>
</div>
</div>
@@ -61,11 +61,11 @@
<template #header>
<div class="aksrt-card-header-row">
<div class="aksrt-card-header-row__left">
<span class="header-icon"><i class="fas fa-layer-group"></i></span>
<span class="header-icon"><i class="fa fas fa-clone"></i></span>
<strong class="aksrt-card-header-row__title">按钮列表 ({{ form.items.length }})</strong>
</div>
<n-button type="primary" size="small" @click="addItem">
<template #icon><i class="fas fa-plus"></i></template>
<template #icon><i class="fa fas fa-plus"></i></template>
添加按钮
</n-button>
</div>
@@ -87,7 +87,7 @@
<div class="float-btn-sort__item">
<div class="float-btn-sort__main">
<button type="button" class="float-btn-sort__handle" aria-label="拖拽排序">
<i class="fas fa-grip-vertical"></i>
<i class="fa fas fa-bars"></i>
</button>
<span class="float-btn-sort__icon">
<i v-if="element.icon" :class="element.icon"></i>
@@ -107,11 +107,11 @@
</div>
<div class="float-btn-sort__actions">
<n-button size="tiny" quaternary type="primary" @click="editItem(index)">
<template #icon><i class="fas fa-edit" style="font-size:12px;" /></template>
<template #icon><i class="fa fas fa-edit" style="font-size:12px;" /></template>
编辑
</n-button>
<n-button size="tiny" quaternary type="error" @click="deleteItem(index)">
<template #icon><i class="fas fa-trash-alt" style="font-size:12px;" /></template>
<template #icon><i class="fa fas fa-trash-alt" style="font-size:12px;" /></template>
删除
</n-button>
</div>
@@ -140,12 +140,12 @@
<n-select v-model:value="editingItem.type" :options="typeOptions" placeholder="选择按钮类型" @update:value="handleTypeChange" />
</n-form-item-gi>
<n-form-item-gi v-if="editingItem.type !== 'theme_mode'" label="主图标 (Font Awesome)">
<n-input v-model:value="editingItem.icon" placeholder="例如: fas fa-home" />
<n-input v-model:value="editingItem.icon" placeholder="例如: fa fas fa-home" />
</n-form-item-gi>
<n-form-item-gi v-else label="主题图标">
<div class="theme-icon-preview">
<span><i class="fas fa-sun"></i> 亮色固定显示太阳</span>
<span><i class="fas fa-moon"></i> 暗色固定显示月亮</span>
<span><i class="fa fas fa-sun"></i> 亮色固定显示太阳</span>
<span><i class="fa fas fa-moon"></i> 暗色固定显示月亮</span>
</div>
</n-form-item-gi>
</n-grid>
@@ -153,12 +153,12 @@
<div class="icon-preview-row">
<span>预览:</span>
<template v-if="editingItem.type === 'theme_mode'">
<span class="theme-icon-preview-inline"><i class="fas fa-sun"></i> / <i class="fas fa-moon"></i></span>
<span class="theme-icon-preview-inline"><i class="fa fas fa-sun"></i> / <i class="fa fas fa-moon"></i></span>
</template>
<i v-else-if="editingItem.icon" :class="editingItem.icon" style="font-size: 18px;"></i>
<span v-else class="muted-text">未设置图标</span>
<a href="https://fontawesome.com/search?m=free" target="_blank" rel="noopener">
<i class="fas fa-external-link-alt"></i>
<i class="fa fas fa-external-link-alt"></i>
Font Awesome
</a>
</div>
@@ -229,12 +229,12 @@
<div class="add-items-editor__head-actions">
<n-dropdown trigger="click" :options="addPresetOptions" @select="applyAddPreset">
<n-button size="small">
<template #icon><i class="fas fa-magic" /></template>
<template #icon><i class="fa fas fa-magic" /></template>
一键预设
</n-button>
</n-dropdown>
<n-button size="small" type="primary" @click="appendAddItem">
<template #icon><i class="fas fa-plus" /></template>
<template #icon><i class="fa fas fa-plus" /></template>
添加子项
</n-button>
</div>
@@ -251,13 +251,13 @@
<template #item="{ element, index: subIndex }">
<div class="add-items-editor__row">
<button type="button" class="add-items-editor__drag" aria-label="拖拽排序">
<i class="fas fa-grip-vertical"></i>
<i class="fa fas fa-bars"></i>
</button>
<n-input v-model:value="element.label" placeholder="名称,例如: 写文章" />
<n-input v-model:value="element.icon" placeholder="图标,例如: fas fa-pen" />
<n-input v-model:value="element.icon" placeholder="图标,例如: fa fas fa-pen" />
<n-input v-model:value="element.url" placeholder="链接,例如: /submit" />
<n-button quaternary type="error" @click="removeAddItem(subIndex)">
<template #icon><i class="fas fa-trash-alt" /></template>
<template #icon><i class="fa fas fa-trash-alt" /></template>
</n-button>
</div>
</template>
@@ -270,7 +270,7 @@
<div class="add-items-preview__panel add-items-preview__panel--light">
<div class="add-items-preview__mode">亮色</div>
<div class="add-items-preview__trigger">
<i :class="editingItem.icon || 'fas fa-plus'"></i>
<i :class="editingItem.icon || 'fa fas fa-plus'"></i>
</div>
<div class="add-items-preview__menu">
<div v-if="editingItem.add_items.length" class="add-items-preview__list">
@@ -280,7 +280,7 @@
href="javascript:void(0)"
class="add-items-preview__item"
>
<i :class="subItem.icon || 'fas fa-pen'"></i>
<i :class="subItem.icon || 'fa fas fa-pen'"></i>
<span>{{ subItem.label || '未命名子项' }}</span>
</a>
</div>
@@ -290,7 +290,7 @@
<div class="add-items-preview__panel add-items-preview__panel--dark">
<div class="add-items-preview__mode">暗色</div>
<div class="add-items-preview__trigger add-items-preview__trigger--dark">
<i :class="editingItem.icon || 'fas fa-plus'"></i>
<i :class="editingItem.icon || 'fa fas fa-plus'"></i>
</div>
<div class="add-items-preview__menu add-items-preview__menu--dark">
<div v-if="editingItem.add_items.length" class="add-items-preview__list">
@@ -300,7 +300,7 @@
href="javascript:void(0)"
class="add-items-preview__item add-items-preview__item--dark"
>
<i :class="subItem.icon || 'fas fa-pen'"></i>
<i :class="subItem.icon || 'fa fas fa-pen'"></i>
<span>{{ subItem.label || '未命名子项' }}</span>
</a>
</div>
@@ -410,7 +410,7 @@ function createDefaultItem() {
return {
id: '',
type: 'custom',
icon: 'fas fa-link',
icon: 'fa fas fa-link',
icon_dark: '',
icon_light: '',
text: '',
@@ -435,14 +435,14 @@ function createDefaultItem() {
function applyTypeDefaults(type) {
const map = {
custom: { icon: 'fas fa-link', icon_dark: '', icon_light: '', text: '链接', desc: '', link: '', hover: '', action_mode: 'link', qr_size: 120 },
back_top: { icon: 'fas fa-chevron-up', icon_dark: '', icon_light: '', text: '顶部', desc: '返回顶部', link: '', hover: '', action_mode: 'link', qr_size: 120 },
theme_mode: { icon: 'fas fa-sun', icon_dark: '', icon_light: '', text: '主题', desc: '切换主题', link: '', hover: '', action_mode: 'link', qr_size: 120 },
qrcode: { icon: 'fas fa-qrcode', icon_dark: '', icon_light: '', text: '二维码', desc: '扫码继续浏览', link: '', hover: '', action_mode: 'qrcode', qr_size: 120 },
service_qq: { icon: 'fab fa-qq', icon_dark: '', icon_light: '', text: 'QQ', desc: 'QQ 联系', link: '', hover: '', action_mode: 'link', qr_size: 120 },
service_wechat: { icon: 'fab fa-weixin', icon_dark: '', icon_light: '', text: '微信', desc: '扫码添加微信', link: '', hover: '', action_mode: 'link', qr_size: 120 },
pay_vip: { icon: 'fas fa-gem', icon_dark: '', icon_light: '', text: '会员', desc: '开通/升级会员弹窗', link: '', hover: '', action_mode: 'link', qr_size: 120 },
add: { icon: 'fas fa-plus', icon_dark: '', icon_light: '', text: '发布', desc: '发布内容', link: '', hover: '', action_mode: 'link', qr_size: 120 },
custom: { icon: 'fa fas fa-link', icon_dark: '', icon_light: '', text: '链接', desc: '', link: '', hover: '', action_mode: 'link', qr_size: 120 },
back_top: { icon: 'fa fas fa-chevron-up', icon_dark: '', icon_light: '', text: '顶部', desc: '返回顶部', link: '', hover: '', action_mode: 'link', qr_size: 120 },
theme_mode: { icon: 'fa fas fa-sun', icon_dark: '', icon_light: '', text: '主题', desc: '切换主题', link: '', hover: '', action_mode: 'link', qr_size: 120 },
qrcode: { icon: 'fa fas fa-qrcode', icon_dark: '', icon_light: '', text: '二维码', desc: '扫码继续浏览', link: '', hover: '', action_mode: 'qrcode', qr_size: 120 },
service_qq: { icon: 'fa fab fa-qq', icon_dark: '', icon_light: '', text: 'QQ', desc: 'QQ 联系', link: '', hover: '', action_mode: 'link', qr_size: 120 },
service_wechat: { icon: 'fa fab fa-weixin', icon_dark: '', icon_light: '', text: '微信', desc: '扫码添加微信', link: '', hover: '', action_mode: 'link', qr_size: 120 },
pay_vip: { icon: 'fa fas fa-gem', icon_dark: '', icon_light: '', text: '会员', desc: '开通/升级会员弹窗', link: '', hover: '', action_mode: 'link', qr_size: 120 },
add: { icon: 'fa fas fa-plus', icon_dark: '', icon_light: '', text: '发布', desc: '发布内容', link: '', hover: '', action_mode: 'link', qr_size: 120 },
}
return map[type] || map.custom
}
@@ -465,8 +465,8 @@ function handleTypeChange(type) {
if (type === 'pay_vip') {
editingItem.link = ''
editingItem.hover = ''
if (!editingItem.icon || editingItem.icon.includes('fa-diamond')) {
editingItem.icon = 'fas fa-gem'
if (!editingItem.icon || editingItem.icon.includes('fa-gem')) {
editingItem.icon = 'fa fas fa-gem'
}
}
}
@@ -484,7 +484,7 @@ function appendAddItem() {
editingItem.add_items.push({
id: `add_${Date.now()}_${editingItem.add_items.length}`,
label: '',
icon: 'fas fa-pen',
icon: 'fa fas fa-pen',
url: '',
})
}
@@ -503,9 +503,9 @@ function applyAddPreset(key) {
}
const presetFactories = {
post: () => ({ label: '写文章', icon: 'fas fa-pen-nib', url: `${siteUrl}/submit/` }),
submit: () => ({ label: '投稿页', icon: 'fas fa-paper-plane', url: `${siteUrl}/submit/` }),
profile: () => ({ label: '创作中心', icon: 'fas fa-user-edit', url: `${siteUrl}/user/` }),
post: () => ({ label: '写文章', icon: 'fa fas fa-pen', url: `${siteUrl}/submit/` }),
submit: () => ({ label: '投稿页', icon: 'fa fas fa-paper-plane', url: `${siteUrl}/submit/` }),
profile: () => ({ label: '创作中心', icon: 'fa fas fa-user', url: `${siteUrl}/user/` }),
}
const factory = presetFactories[key]
@@ -531,9 +531,9 @@ function isAddPresetExists(key) {
function getAddPresetValue(key) {
const presetFactories = {
post: () => ({ label: '写文章', icon: 'fas fa-pen-nib', url: `${siteUrl}/submit/` }),
submit: () => ({ label: '投稿页', icon: 'fas fa-paper-plane', url: `${siteUrl}/submit/` }),
profile: () => ({ label: '创作中心', icon: 'fas fa-user-edit', url: `${siteUrl}/user/` }),
post: () => ({ label: '写文章', icon: 'fa fas fa-pen', url: `${siteUrl}/submit/` }),
submit: () => ({ label: '投稿页', icon: 'fa fas fa-paper-plane', url: `${siteUrl}/submit/` }),
profile: () => ({ label: '创作中心', icon: 'fa fas fa-user', url: `${siteUrl}/user/` }),
}
return presetFactories[key] ? presetFactories[key]() : null
@@ -602,7 +602,7 @@ function saveItem() {
const item = {
id: editingItem.id || `float_${Date.now()}`,
type: editingItem.type,
icon: editingItem.type === 'theme_mode' ? 'fas fa-sun' : (editingItem.type === 'pay_vip' ? (editingItem.icon || 'fas fa-gem') : editingItem.icon),
icon: editingItem.type === 'theme_mode' ? 'fa fas fa-sun' : (editingItem.type === 'pay_vip' ? (editingItem.icon || 'fa fas fa-gem') : editingItem.icon),
icon_dark: '',
icon_light: '',
text: editingItem.text,
@@ -618,7 +618,7 @@ function saveItem() {
add_items: editingItem.type === 'add' ? editingItem.add_items.filter(subItem => subItem.label || subItem.url).map((subItem, idx) => ({
id: subItem.id || `add_${idx}`,
label: subItem.label || '',
icon: subItem.icon || 'fas fa-pen',
icon: subItem.icon || 'fa fas fa-pen',
url: subItem.url || '',
})) : [],
hover: editingItem.type === 'pay_vip' ? '' : (supportsHover.value ? (editingItem.hover || '') : ''),
@@ -672,7 +672,7 @@ async function loadSettings() {
form.items = (data.items || []).map((item, index) => ({
...createDefaultItem(),
...item,
icon: item.type === 'theme_mode' ? 'fas fa-sun' : (item.icon || ''),
icon: item.type === 'theme_mode' ? 'fa fas fa-sun' : (item.icon || ''),
color: item.color || null,
bg: item.bg || null,
icon_dark: '',
@@ -705,7 +705,7 @@ async function handleSave() {
filter_blur: form.filter_blur,
items: form.items.map((item, index) => ({
...item,
icon: item.type === 'theme_mode' ? 'fas fa-sun' : (item.icon || ''),
icon: item.type === 'theme_mode' ? 'fa fas fa-sun' : (item.icon || ''),
icon_dark: '',
icon_light: '',
color: item.color || '',
@@ -409,7 +409,7 @@
<n-input v-model:value="editingContactMore.desc" placeholder="如:微信公众号" />
</n-form-item>
<n-form-item label="图标类名">
<n-input v-model:value="editingContactMore.icon" placeholder="如:fab fa-weixin" />
<n-input v-model:value="editingContactMore.icon" placeholder="如:fa fab fa-weixin" />
</n-form-item>
<n-form-item label="链接地址">
<n-input v-model:value="editingContactMore.link" placeholder="https://..." />
@@ -12,7 +12,7 @@
<template #header>
<div class="aksrt-card-header-row">
<div class="aksrt-card-header-row__left">
<span class="header-icon"><i class="fas fa-cog"></i></span>
<span class="header-icon"><i class="fa fas fa-cog"></i></span>
<strong class="aksrt-card-header-row__title">基础设置</strong>
</div>
</div>
@@ -46,11 +46,11 @@
<template #header>
<div class="aksrt-card-header-row">
<div class="aksrt-card-header-row__left">
<span class="header-icon"><i class="fas fa-list-ul"></i></span>
<span class="header-icon"><i class="fa fas fa-list-ul"></i></span>
<strong class="aksrt-card-header-row__title">Tab按钮配置 ({{ form.items.length }})</strong>
</div>
<n-button type="primary" size="small" @click="addItem">
<template #icon><i class="fas fa-plus"></i></template>
<template #icon><i class="fa fas fa-plus"></i></template>
添加按钮
</n-button>
</div>
@@ -72,7 +72,7 @@
<div class="tabbar-sort__item">
<div class="tabbar-sort__main">
<button type="button" class="tabbar-sort__handle" aria-label="拖拽排序">
<i class="fas fa-grip-vertical"></i>
<i class="fa fas fa-bars"></i>
</button>
<span class="tabbar-sort__icon">
<i v-if="element.icon" :class="element.icon"></i>
@@ -90,11 +90,11 @@
</div>
<div class="tabbar-sort__actions">
<n-button size="tiny" quaternary type="primary" @click="editItem(index)">
<template #icon><i class="fas fa-edit" style="font-size:12px;" /></template>
<template #icon><i class="fa fas fa-edit" style="font-size:12px;" /></template>
编辑
</n-button>
<n-button size="tiny" quaternary type="error" @click="deleteItem(index)">
<template #icon><i class="fas fa-trash-alt" style="font-size:12px;" /></template>
<template #icon><i class="fa fas fa-trash-alt" style="font-size:12px;" /></template>
删除
</n-button>
</div>
@@ -129,14 +129,14 @@
</n-form-item>
<n-form-item label="图标 (Font Awesome)">
<n-input v-model:value="editingItem.icon" placeholder="例如: fas fa-home" />
<n-input v-model:value="editingItem.icon" placeholder="例如: fa fas fa-home" />
<template #feedback>
<div class="icon-preview-row">
<span>预览:</span>
<i v-if="editingItem.icon" :class="editingItem.icon" style="font-size: 20px;"></i>
<span v-else class="muted-text">无图标</span>
<a href="https://fontawesome.com/search?m=free" target="_blank" rel="noopener" style="margin-left: 12px;">
<i class="fas fa-external-link-alt"></i> Font Awesome 图标库
<i class="fa fas fa-external-link-alt"></i> Font Awesome 图标库
</a>
</div>
</template>
@@ -198,7 +198,7 @@
<div class="add-items-editor__head">
<strong>发布菜单项</strong>
<n-button size="small" type="primary" @click="appendAddItem">
<template #icon><i class="fas fa-plus" /></template>
<template #icon><i class="fa fas fa-plus" /></template>
添加子项
</n-button>
</div>
@@ -227,13 +227,13 @@
<template #item="{ element, index: subIndex }">
<div class="add-items-editor__row">
<button type="button" class="add-items-editor__drag" aria-label="拖拽排序">
<i class="fas fa-grip-vertical"></i>
<i class="fa fas fa-bars"></i>
</button>
<n-input v-model:value="element.label" placeholder="名称,例如:写文章" />
<n-input v-model:value="element.icon" placeholder="图标,例如:fas fa-pen" />
<n-input v-model:value="element.icon" placeholder="图标,例如:fa fas fa-pen" />
<n-input v-model:value="element.url" placeholder="链接,例如:/wp-admin/post-new.php" />
<n-button quaternary type="error" @click="removeAddItem(subIndex)">
<template #icon><i class="fas fa-trash-alt" /></template>
<template #icon><i class="fa fas fa-trash-alt" /></template>
</n-button>
</div>
</template>
@@ -327,15 +327,15 @@ const typeLabelMap = {
}
const typeDefaults = {
home: { icon: 'fas fa-home', text: '首页' },
category: { icon: 'fas fa-th-large', text: '分类' },
link: { icon: 'fas fa-link', text: '链接' },
add: { icon: 'fas fa-plus', text: '发布' },
user: { icon: 'fas fa-user', text: '用户中心' },
auth: { icon: 'fas fa-user', text: '我的' },
search: { icon: 'fas fa-search', text: '搜索' },
msg: { icon: 'fas fa-bell', text: '消息' },
pay_vip: { icon: 'fas fa-crown', text: '会员' },
home: { icon: 'fa fas fa-home', text: '首页' },
category: { icon: 'fa fas fa-th-large', text: '分类' },
link: { icon: 'fa fas fa-link', text: '链接' },
add: { icon: 'fa fas fa-plus', text: '发布' },
user: { icon: 'fa fas fa-user', text: '用户中心' },
auth: { icon: 'fa fas fa-user', text: '我的' },
search: { icon: 'fa fas fa-search', text: '搜索' },
msg: { icon: 'fa fas fa-bell', text: '消息' },
pay_vip: { icon: 'fa fas fa-gem', text: '会员' },
}
const enabledPreviewItems = computed(() => form.items.filter((item) => item.enabled))
@@ -361,10 +361,10 @@ function getItemSummary(item) {
}
const addPresets = [
{ label: '写文章', icon: 'fas fa-pen-fancy', url: '/submit' },
{ label: '投稿页', icon: 'fas fa-file-alt', url: '/submit' },
{ label: '发布资源', icon: 'fas fa-cloud-upload-alt', url: '/resource-new' },
{ label: '创作中心', icon: 'fas fa-palette', url: '/creator' },
{ label: '写文章', icon: 'fa fas fa-pen', url: '/submit' },
{ label: '投稿页', icon: 'fa fas fa-file-alt', url: '/submit' },
{ label: '发布资源', icon: 'fa fas fa-cloud-upload-alt', url: '/resource-new' },
{ label: '创作中心', icon: 'fa fas fa-paint-brush', url: '/creator' },
]
function appendAddPreset(preset) {
@@ -381,7 +381,7 @@ function appendAddItem() {
editingItem.add_items.push({
id: `add_${Date.now()}_${editingItem.add_items.length}`,
label: '',
icon: 'fas fa-pen',
icon: 'fa fas fa-pen',
url: '',
})
}
@@ -421,7 +421,7 @@ function addItem() {
Object.assign(editingItem, {
id: `tab_${Date.now()}`,
type: 'link',
icon: 'fas fa-link',
icon: 'fa fas fa-link',
text: '链接',
link: '',
badge: '',
@@ -489,7 +489,7 @@ function saveItem() {
? editingItem.add_items.filter((sub) => sub.label && sub.url).map((sub) => ({
id: sub.id || `add_${Date.now()}`,
label: sub.label,
icon: sub.icon || 'fas fa-pen',
icon: sub.icon || 'fa fas fa-pen',
url: sub.url,
}))
: [],
@@ -1,518 +0,0 @@
<template>
<div class="aksrt-page-container content-page">
<PageHeader title="Hero 轮播管理" desc="管理首页 Hero 幻灯片内容(图片/视频、文案、图层、跳转)。标题、副标题可留空。" />
<n-card class="aksrt-section-card" style="margin-bottom:16px;">
<template #header>
<div class="aksrt-card-header-row">
<strong>显示范围</strong>
<n-button size="small" secondary @click="goHeaderComponents">顶部多功能组件(页面类型/搜索/卡片)</n-button>
</div>
</template>
<p class="aksrt-inline-setting__hint" style="margin:0;">
幻灯片内容在此维护。页面类型启用、设备规则、搜索覆盖层与图标卡片请到「顶部多功能组件」配置;全不选页面类型即为关闭。
</p>
</n-card>
<n-spin :show="loading" style="width:100%; min-height:200px;">
<n-card class="aksrt-section-card">
<template #header>
<div class="aksrt-card-header-row">
<div class="aksrt-card-header-row__left">
<span class="header-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px" aria-hidden="true">
<rect width="18" height="18" x="3" y="3" rx="2" ry="2"/>
<circle cx="9" cy="9" r="2"/>
<path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/>
</svg>
</span>
<strong class="aksrt-card-header-row__title">Hero 列表 ({{ slides.length }})</strong>
</div>
<n-button type="primary" size="small" @click="openCreate">+ 添加 Hero</n-button>
</div>
</template>
<n-data-table
v-if="slides.length"
:columns="columns"
:data="slides"
:row-key="(row) => row.id"
:bordered="false"
size="small"
/>
<n-empty v-else description="暂无 Hero,添加后首页即可使用。" />
</n-card>
</n-spin>
<!-- 编辑/新增 弹窗 -->
<n-modal
v-model:show="modalShow"
:mask-closable="false"
preset="card"
:title="editing.id ? '编辑 Hero' : '添加 Hero'"
class="aksrt-modal-card"
>
<n-form :model="editing" label-placement="top" class="aksrt-form">
<n-form-item label="标题">
<n-input v-model:value="editing.title" placeholder="可选,主标题" />
</n-form-item>
<n-form-item label="副标题">
<n-input v-model:value="editing.subtitle" placeholder="可选,副标题" />
</n-form-item>
<n-form-item label="背景图 URL">
<n-input-group>
<n-input v-model:value="editing.image_url" placeholder="https://..." />
<n-button secondary @click="pickImage">媒体库</n-button>
</n-input-group>
</n-form-item>
<div v-if="editing.image_url" class="aksrt-modal-preview">
<n-image :src="editing.image_url" width="100%" height="160" object-fit="cover" :preview-src="editing.image_url" />
</div>
<n-form-item label="跳转链接">
<n-input v-model:value="editing.link_url" placeholder="点击后跳转地址,可留空" />
</n-form-item>
<n-form-item label="描述文字">
<n-input v-model:value="editing.description" type="textarea" :rows="2" placeholder="可选,显示在副标题下方" />
</n-form-item>
<n-form-item label="视频背景 URL">
<n-input v-model:value="editing.video_url" placeholder="可选,MP4 视频地址替代背景图" />
</n-form-item>
<div class="aksrt-modal-grid">
<n-form-item label="链接打开方式">
<n-radio-group v-model:value="editing.link_target">
<n-radio-button value="_self">当前窗口</n-radio-button>
<n-radio-button value="_blank">新窗口</n-radio-button>
</n-radio-group>
</n-form-item>
<n-form-item label="文字对齐">
<n-radio-group v-model:value="editing.text_align">
<n-radio-button value="left">左</n-radio-button>
<n-radio-button value="center">居中</n-radio-button>
<n-radio-button value="right">右</n-radio-button>
</n-radio-group>
</n-form-item>
<n-form-item label="设备可见性">
<n-radio-group v-model:value="editing.device_visibility">
<n-radio-button value="all">全部</n-radio-button>
<n-radio-button value="pc">仅电脑</n-radio-button>
<n-radio-button value="mobile">仅移动</n-radio-button>
</n-radio-group>
</n-form-item>
<n-form-item label="文字视差">
<n-switch v-model:value="editing.text_parallax" />
</n-form-item>
<n-form-item label="文字大小(PC)">
<n-input v-model:value="editing.text_size_pc" placeholder="如 48px,留空默认" />
</n-form-item>
<n-form-item label="文字大小(移动)">
<n-input v-model:value="editing.text_size_m" placeholder="如 28px,留空默认" />
</n-form-item>
</div>
<div class="aksrt-modal-grid">
<n-form-item label="显示文字">
<n-switch v-model:value="editing.show_text" />
</n-form-item>
<n-form-item label="排序">
<n-input-number v-model:value="editing.sort_order" :min="0" style="width:100%;" />
</n-form-item>
<n-form-item label="启用">
<n-switch v-model:value="editing.enabled" />
</n-form-item>
<n-form-item label="显示元信息">
<n-switch v-model:value="editing.show_meta" />
</n-form-item>
</div>
<!-- 图片图层 -->
<n-divider title-placement="left" style="margin:16px 0 12px;">
图片图层(视差叠加)
</n-divider>
<div v-for="(layer, idx) in editing.layers" :key="idx" class="aksrt-layer-item">
<div class="aksrt-layer-item__header">
<strong>图层 {{ idx + 1 }}</strong>
<n-button size="tiny" type="error" quaternary @click="removeLayer(idx)">删除</n-button>
</div>
<n-form-item label="图片">
<n-input-group>
<n-input v-model:value="layer.image" placeholder="图片 URL" />
<n-button secondary @click="pickLayerImage(idx)">媒体库</n-button>
</n-input-group>
</n-form-item>
<div class="aksrt-modal-grid">
<n-form-item label="原始尺寸">
<n-switch v-model:value="layer.free_size" />
</n-form-item>
<n-form-item label="对齐方式">
<n-select v-model:value="layer.align" :options="[
{ label: '居中', value: 'center' },
{ label: '左上', value: 'left top' },
{ label: '右上', value: 'right top' },
{ label: '左下', value: 'left bottom' },
{ label: '右下', value: 'right bottom' },
]" />
</n-form-item>
<n-form-item label="视差">
<n-switch v-model:value="layer.parallax" />
</n-form-item>
<n-form-item label="视差强度" v-if="layer.parallax">
<n-slider v-model:value="layer.parallax_scale" :min="0" :max="1" :step="0.05" />
</n-form-item>
<n-form-item label="视差透明度" v-if="layer.parallax">
<n-slider v-model:value="layer.parallax_opacity" :min="0" :max="1" :step="0.05" />
</n-form-item>
</div>
</div>
<n-button size="small" dashed block @click="addLayer" style="margin-top:8px;">+ 添加图层</n-button>
</n-form>
<template #footer>
<div class="aksrt-modal-footer">
<n-button @click="modalShow = false">取消</n-button>
<n-button type="primary" :loading="saving" @click="handleSave">保存</n-button>
</div>
</template>
</n-modal>
</div>
</template>
<script setup>
import { h, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { NButton, NImage, NTag, useDialog, useMessage } from 'naive-ui'
import api from '@/api'
import { openMediaPicker } from '@/utils/media'
import PageHeader from '@/components/PageHeader.vue'
const router = useRouter()
const message = useMessage()
const dialog = useDialog()
function goHeaderComponents() {
router.push('/page-display/header-components')
}
const loading = ref(true)
const saving = ref(false)
const slides = ref([])
const modalShow = ref(false)
const editing = ref(emptyForm())
function emptyForm() {
return {
id: 0,
title: '',
subtitle: '',
description: '',
image_url: '',
video_url: '',
link_url: '',
link_target: '_self',
text_align: 'left',
device_visibility: 'all',
enabled: true,
show_text: true,
show_meta: false,
sort_order: 0,
text_size_pc: '',
text_size_m: '',
text_parallax: false,
layers: [],
}
}
const columns = [
{
title: '预览',
key: 'image_url',
width: 90,
render(row) {
if (!row.image_url) {
return h('span', { style: 'color:#bbb;font-size:12px;' }, '无')
}
return h(NImage, {
src: row.image_url,
width: 64,
height: 36,
objectFit: 'cover',
previewSrc: row.image_url,
style: 'border-radius:4px;display:block;',
})
},
},
{
title: '标题',
key: 'title',
ellipsis: { tooltip: true },
render(row) {
return row.title || h('span', { style: 'color:#bbb;' }, '未命名')
},
},
{
title: '文字',
key: 'show_text',
width: 70,
className: 'aksrt-table-mobile-hide',
render(row) {
return h(NTag, { size: 'small', type: row.show_text ? 'info' : 'default' }, {
default: () => (row.show_text ? '显示' : '隐藏'),
})
},
},
{
title: '元信息',
key: 'show_meta',
width: 78,
className: 'aksrt-table-mobile-hide',
render(row) {
return h(NTag, { size: 'small', type: row.show_meta ? 'info' : 'default' }, {
default: () => (row.show_meta ? '显示' : '隐藏'),
})
},
},
{
title: '跳转',
key: 'link_url',
ellipsis: { tooltip: true },
className: 'aksrt-table-mobile-hide',
render(row) {
return row.link_url || h('span', { style: 'color:#bbb;font-size:12px;' }, '—')
},
},
{
title: '排序',
key: 'sort_order',
width: 64,
className: 'aksrt-table-mobile-hide',
},
{
title: '状态',
key: 'enabled',
width: 84,
render(row) {
return h(NTag, { size: 'small', type: row.enabled ? 'success' : 'default' }, {
default: () => (row.enabled ? '启用' : '禁用'),
})
},
},
{
title: '操作',
key: 'actions',
width: 130,
render(row) {
return h('div', { style: 'display:flex;gap:6px;' }, [
h(NButton, { size: 'tiny', onClick: () => openEdit(row) }, { default: () => '编辑' }),
h(NButton, { size: 'tiny', type: 'error', quaternary: true, onClick: () => handleDelete(row) }, { default: () => '删除' }),
])
},
},
]
async function loadSlides() {
try {
loading.value = true
const res = await api.getHeroes()
if (res.code === 'success') {
slides.value = res.data || []
}
} catch (e) {
message.error(e.message || '加载失败')
} finally {
loading.value = false
}
}
function openCreate() {
editing.value = emptyForm()
modalShow.value = true
}
function openEdit(row) {
editing.value = {
id: row.id,
title: row.title || '',
subtitle: row.subtitle || '',
description: row.description || '',
image_url: row.image_url || '',
video_url: row.video_url || '',
link_url: row.link_url || '',
link_target: row.link_target || '_self',
text_align: row.text_align || 'left',
device_visibility: row.device_visibility || 'all',
show_text: row.show_text !== false,
enabled: !!row.enabled,
show_meta: row.show_meta === true,
sort_order: Number(row.sort_order) || 0,
text_size_pc: row.text_size_pc || '',
text_size_m: row.text_size_m || '',
text_parallax: !!row.text_parallax,
layers: Array.isArray(row.layers) ? row.layers : [],
}
modalShow.value = true
}
async function pickImage() {
try {
const media = await openMediaPicker({
title: '选择 Hero 背景图',
buttonText: '使用这张 Hero 图',
})
if (media?.url) {
editing.value.image_url = media.url
}
} catch (e) {
message.error(e.message || '打开媒体库失败')
}
}
function addLayer() {
editing.value.layers.push({
image: '',
free_size: false,
align: 'center',
parallax: false,
parallax_scale: 0.3,
parallax_opacity: 0.6,
})
}
function removeLayer(idx) {
editing.value.layers.splice(idx, 1)
}
async function pickLayerImage(idx) {
try {
const media = await openMediaPicker({
title: '选择图层图片',
buttonText: '使用这张图',
})
if (media?.url) {
editing.value.layers[idx].image = media.url
}
} catch (e) {
message.error(e.message || '打开媒体库失败')
}
}
async function handleSave() {
if (!editing.value.image_url) {
message.warning('请填写 Hero 背景图')
return
}
saving.value = true
try {
if (editing.value.id) {
await api.updateHero(editing.value.id, editing.value)
message.success('已保存')
} else {
await api.createHero(editing.value)
message.success('已添加')
}
modalShow.value = false
await loadSlides()
} catch (e) {
message.error(e.message || '保存失败')
} finally {
saving.value = false
}
}
function handleDelete(row) {
dialog.warning({
title: '确认删除',
content: `确定删除 Hero「${row.title || '未命名'}」?`,
positiveText: '删除',
negativeText: '取消',
onPositiveClick: async () => {
try {
await api.deleteHero(row.id)
message.success('已删除')
await loadSlides()
} catch (e) {
message.error(e.message || '删除失败')
}
},
})
}
onMounted(() => {
loadSlides()
})
</script>
<style scoped>
.aksrt-inline-setting {
display: flex;
align-items: center;
gap: 12px;
flex-wrap: wrap;
}
.aksrt-inline-setting__hint {
color: #7a7f8a;
font-size: 13px;
}
.aksrt-inline-setting__actions {
display: flex;
justify-content: flex-end;
}
.aksrt-modal-preview {
margin: -8px 0 18px;
border-radius: 8px;
overflow: hidden;
border: 1px solid #eef1f6;
}
.aksrt-modal-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
}
.aksrt-layer-item {
border: 1px solid #eef1f6;
border-radius: 8px;
padding: 14px;
margin-bottom: 10px;
background: #fafbfc;
}
.aksrt-layer-item__header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.aksrt-modal-footer {
display: flex;
justify-content: flex-end;
gap: 10px;
}
@media (max-width: 768px) {
.aksrt-modal-grid {
grid-template-columns: 1fr;
}
}
</style>
@@ -164,13 +164,12 @@
<template #header><strong>固定骨架说明</strong></template>
<n-space vertical>
<n-alert type="warning" :show-icon="false">
Hero 与 Banner 已作为固定首页骨架的一部分维护,不再由旧版首页模块编排驱动。
顶部多功能组件与 Banner 已作为固定首页骨架的一部分维护,不再由旧版首页模块编排驱动。
</n-alert>
<n-alert type="info" :show-icon="false">
如需调整首页首屏运营区,请前往对应管理页配置幻灯片内容或顶部组件参数。
</n-alert>
<n-space>
<n-button secondary type="primary" @click="router.push('/page-display/hero')">管理 Hero 轮播</n-button>
<n-button secondary type="primary" @click="router.push('/page-display/banner')">管理 Banner 轮播</n-button>
<n-button secondary @click="router.push('/page-display/header-components')">
顶部多功能组件
+11 -11
View File
@@ -7,7 +7,7 @@
<n-grid :cols="2" :x-gap="12" :y-gap="12">
<n-grid-item>
<div class="aksrt-docs__action">
<FaIcon icon="fas fa-palette" :size="16" />
<FaIcon icon="fa fas fa-paint-brush" :size="16" />
<div>
<strong>全局设置</strong>
<p>Logo、背景、菜单装饰、自定义代码</p>
@@ -17,7 +17,7 @@
</n-grid-item>
<n-grid-item>
<div class="aksrt-docs__action">
<FaIcon icon="fas fa-home" :size="16" />
<FaIcon icon="fa fas fa-home" :size="16" />
<div>
<strong>首页配置</strong>
<p>首页模块、布局、排序和预设模板</p>
@@ -27,7 +27,7 @@
</n-grid-item>
<n-grid-item>
<div class="aksrt-docs__action">
<FaIcon icon="fas fa-users" :size="16" />
<FaIcon icon="fa fas fa-users" :size="16" />
<div>
<strong>用户管理</strong>
<p>登录注册、OAuth、签到、积分</p>
@@ -37,7 +37,7 @@
</n-grid-item>
<n-grid-item>
<div class="aksrt-docs__action">
<FaIcon icon="fas fa-tools" :size="16" />
<FaIcon icon="fa fas fa-wrench" :size="16" />
<div>
<strong>系统工具</strong>
<p>导入导出、健康检查、迁移状态</p>
@@ -66,7 +66,7 @@
<h4 class="aksrt-docs__card-title">{{ doc.title }}</h4>
<p class="aksrt-docs__card-desc">{{ doc.description }}</p>
</div>
<FaIcon icon="fas fa-external-link-alt" :size="12" class="aksrt-docs__card-arrow" />
<FaIcon icon="fa fas fa-external-link-alt" :size="12" class="aksrt-docs__card-arrow" />
</div>
</n-card>
</div>
@@ -95,12 +95,12 @@ const themeVersion = ref(window.aksrtAdminData?.themeVersion || '3.4.0-dev')
const dbSchemaVersion = ref('—')
const docs = ref([
{ key: 'admin-ia-map', title: '后台 IA 蓝图', description: '完整的后台信息架构映射,12 个顶级分区及子页面清单。', icon: 'fas fa-sitemap', color: '#1890ff', file: 'admin-ia-map.md' },
{ key: 'zibll-gap-matrix', title: '对标差异矩阵', description: 'AKSRT 当前 → Zibll 参考 → AKSRT 目标三层对照表。', icon: 'fas fa-columns', color: '#722ed1', file: 'zibll-gap-matrix.md' },
{ key: 'frontend-page-matrix', title: '前端页面矩阵', description: '前端模板、CSS、JS 资产映射与覆盖范围。', icon: 'fas fa-desktop', color: '#13c2c2', file: 'frontend-page-matrix.md' },
{ key: 'manual-acceptance-baseline', title: '验收基线', description: '每个 Phase 的人工验收标准和检查清单。', icon: 'fas fa-clipboard-check', color: '#52c41a', file: 'manual-acceptance-baseline.md' },
{ key: 'feature-domain-map', title: '功能域地图', description: '业务域划分、依赖关系和模块边界说明。', icon: 'fas fa-map', color: '#fa8c16', file: 'feature-domain-map.md' },
{ key: 'migration-map', title: '迁移地图', description: '设置 key 迁移、旧选项兼容和 Schema 版本对照。', icon: 'fas fa-exchange-alt', color: '#eb2f96', file: 'migration-map.md' },
{ key: 'admin-ia-map', title: '后台 IA 蓝图', description: '完整的后台信息架构映射,12 个顶级分区及子页面清单。', icon: 'fa fas fa-sitemap', color: '#1890ff', file: 'admin-ia-map.md' },
{ key: 'zibll-gap-matrix', title: '对标差异矩阵', description: 'AKSRT 当前 → Zibll 参考 → AKSRT 目标三层对照表。', icon: 'fa fas fa-columns', color: '#722ed1', file: 'zibll-gap-matrix.md' },
{ key: 'frontend-page-matrix', title: '前端页面矩阵', description: '前端模板、CSS、JS 资产映射与覆盖范围。', icon: 'fa fas fa-desktop', color: '#13c2c2', file: 'frontend-page-matrix.md' },
{ key: 'manual-acceptance-baseline', title: '验收基线', description: '每个 Phase 的人工验收标准和检查清单。', icon: 'fa fas fa-clipboard', color: '#52c41a', file: 'manual-acceptance-baseline.md' },
{ key: 'feature-domain-map', title: '功能域地图', description: '业务域划分、依赖关系和模块边界说明。', icon: 'fa fas fa-map', color: '#fa8c16', file: 'feature-domain-map.md' },
{ key: 'migration-map', title: '迁移地图', description: '设置 key 迁移、旧选项兼容和 Schema 版本对照。', icon: 'fa fas fa-exchange-alt', color: '#eb2f96', file: 'migration-map.md' },
])
onMounted(async () => {
@@ -9,7 +9,7 @@
<div class="aksrt-ai__status">
<div class="aksrt-ai__status-card">
<div class="aksrt-ai__status-icon" :class="status.available ? 'aksrt-ai__status-icon--ok' : 'aksrt-ai__status-icon--off'">
<i class="fas fa-robot"></i>
<i class="fa fab fa-android"></i>
</div>
<div class="aksrt-ai__status-info">
<div class="aksrt-ai__status-label">可用状态</div>
@@ -18,7 +18,7 @@
</div>
<div class="aksrt-ai__status-card">
<div class="aksrt-ai__status-icon" :class="status.wp_ai_available ? 'aksrt-ai__status-icon--ok' : 'aksrt-ai__status-icon--warn'">
<i class="fas fa-plug"></i>
<i class="fa fas fa-plug"></i>
</div>
<div class="aksrt-ai__status-info">
<div class="aksrt-ai__status-label">WP AI Client</div>
@@ -27,7 +27,7 @@
</div>
<div class="aksrt-ai__status-card">
<div class="aksrt-ai__status-icon" :class="status.theme_available ? 'aksrt-ai__status-icon--ok' : 'aksrt-ai__status-icon--warn'">
<i class="fas fa-key"></i>
<i class="fa fas fa-key"></i>
</div>
<div class="aksrt-ai__status-info">
<div class="aksrt-ai__status-label">主题 Provider</div>
@@ -36,7 +36,7 @@
</div>
<div class="aksrt-ai__status-card">
<div class="aksrt-ai__status-icon aksrt-ai__status-icon--info">
<i class="fas fa-route"></i>
<i class="fa fas fa-road"></i>
</div>
<div class="aksrt-ai__status-info">
<div class="aksrt-ai__status-label">当前后端</div>
@@ -115,7 +115,7 @@
</div>
<div class="aksrt-ai__form-card aksrt-ai__notice">
<h3><i class="fas fa-exclamation-triangle"></i> 重要说明</h3>
<h3><i class="fa fas fa-exclamation-triangle"></i> 重要说明</h3>
<ul>
<li>AI 输出仅作为<strong>建议</strong>,不会自动写库;需用户点「更新/提交」才保存</li>
<li>主题 API Key 已配置时优先使用;否则回退 WordPress AI Connectors</li>
@@ -29,7 +29,7 @@
<strong>{{ tool.title }}</strong>
<p>{{ tool.desc }}</p>
</div>
<FaIcon icon="fas fa-chevron-right" :size="12" color="#c0c4cc" />
<FaIcon icon="fa fas fa-chevron-right" :size="12" color="#c0c4cc" />
</div>
</n-grid-item>
</n-grid>
@@ -57,15 +57,15 @@
<n-card title="手动维护" size="small" class="aksrt-tools__section">
<n-space>
<n-button @click="handleFlushCache">
<template #icon><FaIcon icon="fas fa-broom" :size="12" /></template>
<template #icon><FaIcon icon="fa fas fa-magic" :size="12" /></template>
清除缓存
</n-button>
<n-button @click="handleOptimizeDb">
<template #icon><FaIcon icon="fas fa-database" :size="12" /></template>
<template #icon><FaIcon icon="fa fas fa-database" :size="12" /></template>
优化数据表
</n-button>
<n-button @click="handleRebuildIndex">
<template #icon><FaIcon icon="fas fa-sync-alt" :size="12" /></template>
<template #icon><FaIcon icon="fa fas fa-sync-alt" :size="12" /></template>
重建索引
</n-button>
</n-space>
@@ -85,24 +85,24 @@ const router = useRouter()
const message = useMessage()
const healthItems = ref([
{ key: 'php', icon: 'fas fa-code', color: '#1890ff', value: '—', label: 'PHP 版本', status: 'ok' },
{ key: 'wp', icon: 'fab fa-wordpress', color: '#722ed1', value: '—', label: 'WordPress', status: 'ok' },
{ key: 'db', icon: 'fas fa-database', color: '#52c41a', value: '—', label: '数据库', status: 'ok' },
{ key: 'uploads', icon: 'fas fa-folder-open', color: '#fa8c16', value: '—', label: '上传目录', status: 'ok' },
{ key: 'php', icon: 'fa fas fa-code', color: '#1890ff', value: '—', label: 'PHP 版本', status: 'ok' },
{ key: 'wp', icon: 'fa fab fa-wordpress', color: '#722ed1', value: '—', label: 'WordPress', status: 'ok' },
{ key: 'db', icon: 'fa fas fa-database', color: '#52c41a', value: '—', label: '数据库', status: 'ok' },
{ key: 'uploads', icon: 'fa fas fa-folder-open', color: '#fa8c16', value: '—', label: '上传目录', status: 'ok' },
])
const tools = ref([
{ key: 'import-export', icon: 'fas fa-exchange-alt', bg: '#1890ff', title: '导入导出', desc: '设置导入、导出和重置', route: '/tools/import-export' },
{ key: 'health', icon: 'fas fa-heartbeat', bg: '#52c41a', title: '健康检查', desc: '系统状态检测和诊断', route: '/tools/health' },
{ key: 'email-rollback', icon: 'fas fa-undo', bg: '#fa8c16', title: '邮箱回滚', desc: '邮箱变更 14 天内回滚', route: '/tools/email-rollback' },
{ key: 'import-export', icon: 'fa fas fa-exchange-alt', bg: '#1890ff', title: '导入导出', desc: '设置导入、导出和重置', route: '/tools/import-export' },
{ key: 'health', icon: 'fa fas fa-heartbeat', bg: '#52c41a', title: '健康检查', desc: '系统状态检测和诊断', route: '/tools/health' },
{ key: 'email-rollback', icon: 'fa fas fa-undo', bg: '#fa8c16', title: '邮箱回滚', desc: '邮箱变更 14 天内回滚', route: '/tools/email-rollback' },
])
const services = ref([
{ key: 'sms', icon: 'fas fa-sms', color: '#1890ff', name: '短信服务', description: '验证码和通知短信', available: false },
{ key: 'wechat', icon: 'fab fa-weixin', color: '#52c41a', name: '微信通知', description: '微信模板消息和订阅通知', available: false },
{ key: 'captcha', icon: 'fas fa-shield-alt', color: '#722ed1', name: '验证码服务', description: '人机验证(极验/腾讯/阿里云)', available: false },
{ key: 'push', icon: 'fas fa-paper-plane', color: '#fa8c16', name: '搜索引擎推送', description: '百度/Google 主动推送', available: false },
{ key: 'audit', icon: 'fas fa-shield-virus', color: '#f5222d', name: '内容审核', description: '第三方内容安全审核 API', available: false },
{ key: 'sms', icon: 'fa fas fa-comment', color: '#1890ff', name: '短信服务', description: '验证码和通知短信', available: false },
{ key: 'wechat', icon: 'fa fab fa-weixin', color: '#52c41a', name: '微信通知', description: '微信模板消息和订阅通知', available: false },
{ key: 'captcha', icon: 'fa fas fa-shield-alt', color: '#722ed1', name: '验证码服务', description: '人机验证(极验/腾讯/阿里云)', available: false },
{ key: 'push', icon: 'fa fas fa-paper-plane', color: '#fa8c16', name: '搜索引擎推送', description: '百度/Google 主动推送', available: false },
{ key: 'audit', icon: 'fa fas fa-shield-alt', color: '#f5222d', name: '内容审核', description: '第三方内容安全审核 API', available: false },
])
onMounted(async () => {
@@ -51,12 +51,12 @@ const overview = ref({})
const loading = ref(false)
function iconFor(id) {
if (id === 'balance') return 'fas fa-wallet'
if (id === 'alipay' || id === 'epay_alipay') return 'fab fa-alipay'
if (id === 'wechatpay' || id === 'epay_wxpay') return 'fab fa-weixin'
if (id === 'paypal') return 'fab fa-paypal'
if (id === 'stripe') return 'fab fa-stripe-s'
return 'fas fa-credit-card'
if (id === 'balance') return 'fa fas fa-credit-card'
if (id === 'alipay' || id === 'epay_alipay') return 'fa fas fa-credit-card'
if (id === 'wechatpay' || id === 'epay_wxpay') return 'fa fab fa-weixin'
if (id === 'paypal') return 'fa fab fa-paypal'
if (id === 'stripe') return 'fa fab fa-cc-stripe'
return 'fa fas fa-credit-card'
}
onMounted(async () => {
@@ -99,10 +99,10 @@ const form = reactive({
})
const summaryItems = computed(() => [
{ key: 'profile', icon: 'fas fa-id-card', label: '资料卡图片', enabled: true },
{ key: 'submit', icon: 'fas fa-edit', label: '投稿图片', enabled: true },
{ key: 'comment', icon: 'fas fa-comment-dots', label: '评论图片', enabled: true },
{ key: 'resource', icon: 'fas fa-file-archive', label: '资源附件', enabled: true },
{ key: 'profile', icon: 'fa fas fa-id-card', label: '资料卡图片', enabled: true },
{ key: 'submit', icon: 'fa fas fa-edit', label: '投稿图片', enabled: true },
{ key: 'comment', icon: 'fa fas fa-comment-dots', label: '评论图片', enabled: true },
{ key: 'resource', icon: 'fa fas fa-file-archive', label: '资源附件', enabled: true },
])
function go(path) {
@@ -70,7 +70,7 @@
size="small"
class="aksrt-theme-info__module-tag"
>
<FaIcon :icon="mod.enabled ? 'fas fa-check-circle' : 'fas fa-circle'" :size="10" />
<FaIcon :icon="mod.enabled ? 'fa fas fa-check-circle' : 'fa fas fa-circle'" :size="10" />
{{ mod.label }}
</n-tag>
</div>
@@ -94,23 +94,23 @@
<n-card class="aksrt-theme-info__card" title="快速入口" size="small">
<div class="aksrt-theme-info__links">
<router-link to="/docs" class="aksrt-theme-info__link">
<FaIcon icon="fas fa-book" :size="16" />
<FaIcon icon="fa fas fa-book" :size="16" />
<span>文档中心</span>
</router-link>
<router-link to="/tools/update" class="aksrt-theme-info__link">
<FaIcon icon="fas fa-cloud-arrow-down" :size="16" />
<FaIcon icon="fa fas fa-cloud-download-alt" :size="16" />
<span>更新中心</span>
</router-link>
<router-link to="/tools/backup" class="aksrt-theme-info__link">
<FaIcon icon="fas fa-box-archive" :size="16" />
<FaIcon icon="fa fas fa-archive" :size="16" />
<span>数据备份</span>
</router-link>
<router-link to="/tools/health" class="aksrt-theme-info__link">
<FaIcon icon="fas fa-heartbeat" :size="16" />
<FaIcon icon="fa fas fa-heartbeat" :size="16" />
<span>健康检查</span>
</router-link>
<router-link to="/tools/import-export" class="aksrt-theme-info__link">
<FaIcon icon="fas fa-exchange-alt" :size="16" />
<FaIcon icon="fa fas fa-exchange-alt" :size="16" />
<span>导入导出</span>
</router-link>
</div>
@@ -6,7 +6,7 @@
<div class="aksrt-wechat__status">
<div class="aksrt-wechat__status-card">
<div class="aksrt-wechat__status-icon" :class="status.configured ? 'aksrt-wechat__status-icon--ok' : 'aksrt-wechat__status-icon--warn'">
<i :class="status.configured ? 'fas fa-check' : 'fas fa-exclamation'"></i>
<i :class="status.configured ? 'fa fas fa-check' : 'fa fas fa-exclamation'"></i>
</div>
<div class="aksrt-wechat__status-info">
<div class="aksrt-wechat__status-label">配置状态</div>
@@ -15,7 +15,7 @@
</div>
<div class="aksrt-wechat__status-card">
<div class="aksrt-wechat__status-icon" :class="status.has_token ? 'aksrt-wechat__status-icon--ok' : 'aksrt-wechat__status-icon--warn'">
<i :class="status.has_token ? 'fas fa-key' : 'fas fa-key'"></i>
<i :class="status.has_token ? 'fa fas fa-key' : 'fa fas fa-key'"></i>
</div>
<div class="aksrt-wechat__status-info">
<div class="aksrt-wechat__status-label">Access Token</div>
@@ -24,7 +24,7 @@
</div>
<div class="aksrt-wechat__status-card">
<div class="aksrt-wechat__status-icon" :class="status.has_template ? 'aksrt-wechat__status-icon--ok' : 'aksrt-wechat__status-icon--warn'">
<i :class="status.has_template ? 'fas fa-file-alt' : 'fas fa-file-alt'"></i>
<i :class="status.has_template ? 'fa fas fa-file-alt' : 'fa fas fa-file-alt'"></i>
</div>
<div class="aksrt-wechat__status-info">
<div class="aksrt-wechat__status-label">模板 ID</div>
@@ -33,7 +33,7 @@
</div>
<div class="aksrt-wechat__status-card">
<div class="aksrt-wechat__status-icon aksrt-wechat__status-icon--info">
<i class="fas fa-users"></i>
<i class="fa fas fa-users"></i>
</div>
<div class="aksrt-wechat__status-info">
<div class="aksrt-wechat__status-label">绑定用户</div>
@@ -6,7 +6,6 @@ export const corePageLoaders = {
FooterTabbarSettings: () => import('@/pages/content/FooterTabbarSettings.vue'),
FooterSettings: () => import('@/pages/content/FooterSettings.vue'),
HomepageSettings: () => import('@/pages/content/HomepageSettings.vue'),
HeroManager: () => import('@/pages/content/HeroManager.vue'),
BannerManager: () => import('@/pages/content/BannerManager.vue'),
PostPageSettings: () => import('@/pages/post-list/PostPageSettings.vue'),
CommentSettings: () => import('@/pages/post-list/CommentSettings.vue'),
+1 -1
View File
@@ -45,7 +45,7 @@ function createRouteMeta(page) {
meta.deferredProps = {
title: page.title,
description: page.desc || '',
icon: page.iconClass || 'fas fa-compass-drafting',
icon: page.iconClass || 'fa fas fa-compass',
phase: page.phase || '',
status: page.status || 'deferred',
dependsOn: page.dependsOn || [],
+2 -2
View File
@@ -9,7 +9,7 @@
* {
* key: 'global.seo',
* title: 'SEO优化',
* icon: 'fas fa-search',
* icon: 'fa fas fa-search',
* description: '...',
* api: { get: () => api.getSeoSettings(), save: (data) => api.saveSeoSettings(data) },
* defaults: { ... },
@@ -17,7 +17,7 @@
* {
* key: 'basic',
* title: '基础SEO',
* icon: 'fas fa-globe',
* icon: 'fa fas fa-globe',
* fields: [
* { key: 'site_title', label: '站点标题', type: 'input', default: '' },
* ...
@@ -1,7 +1,7 @@
export const auditSchema = {
key: 'extensions.audit',
title: 'API内容审核',
icon: 'fas fa-shield-virus',
icon: 'fa fas fa-shield-alt',
description: '配置第三方内容审核 API 接入、审核范围和失败回退策略。',
defaults: {
content_audit_enabled: false,
@@ -17,7 +17,7 @@ export const auditSchema = {
{
key: 'provider',
title: '审核接口',
icon: 'fas fa-plug',
icon: 'fa fas fa-plug',
fields: [
{ key: 'content_audit_enabled', label: '启用内容审核', type: 'switch', default: false, help: '开启后将对接第三方内容审核 API' },
{
@@ -38,7 +38,7 @@ export const auditSchema = {
{
key: 'scope',
title: '审核范围',
icon: 'fas fa-check-double',
icon: 'fa fas fa-check',
fields: [
{ key: 'content_audit_text_enabled', label: '文本审核', type: 'switch', default: true, dependsOn: { key: 'content_audit_enabled', value: true } },
{ key: 'content_audit_image_enabled', label: '图片审核', type: 'switch', default: false, dependsOn: { key: 'content_audit_enabled', value: true } },
@@ -47,7 +47,7 @@ export const auditSchema = {
{
key: 'fallback',
title: '失败策略',
icon: 'fas fa-exclamation-triangle',
icon: 'fa fas fa-exclamation-triangle',
fields: [
{
key: 'content_audit_on_failure',
@@ -1,7 +1,7 @@
export const ipSchema = {
key: 'extensions.ip',
title: 'IP归属地',
icon: 'fas fa-map-marker-alt',
icon: 'fa fas fa-map-marker-alt',
description: '配置 IP 数据源、缓存策略和前台归属地展示。',
defaults: {
ip_geo_enabled: false,
@@ -19,7 +19,7 @@ export const ipSchema = {
{
key: 'basic',
title: '基础配置',
icon: 'fas fa-globe',
icon: 'fa fas fa-globe',
fields: [
{ key: 'ip_geo_enabled', label: '启用 IP 归属地', type: 'switch', default: false, help: '开启后将在评论、用户主页等位置显示 IP 归属地信息' },
{
@@ -42,7 +42,7 @@ export const ipSchema = {
{
key: 'providers',
title: '接口凭据',
icon: 'fas fa-key',
icon: 'fa fas fa-key',
fields: [
{ key: 'ip_addr_sdk_qq_appkey', label: '腾讯 AppKey', type: 'input', default: '', dependsOn: { key: 'ip_addr_sdk', values: ['qq', 'polling'] }, help: '「腾讯位置服务」或「轮流查询」时填写;未填则轮询会跳过腾讯。' },
{ key: 'ip_addr_sdk_qq_secretkey', label: '腾讯 SecretKey', type: 'input', default: '', dependsOn: { key: 'ip_addr_sdk', values: ['qq', 'polling'] }, help: '启用 SK 签名时必填;未启用可留空。' },
@@ -53,7 +53,7 @@ export const ipSchema = {
{
key: 'display',
title: '展示设置',
icon: 'fas fa-eye',
icon: 'fa fas fa-eye',
fields: [
{
key: 'ip_geo_display',
@@ -1,7 +1,7 @@
export const pushSchema = {
key: 'extensions.push',
title: '百度推送',
icon: 'fas fa-paper-plane',
icon: 'fa fas fa-paper-plane',
description: '配置搜索引擎主动推送、批量提交和状态追踪。',
defaults: {
baidu_push_enabled: false,
@@ -22,7 +22,7 @@ export const pushSchema = {
{
key: 'basic',
title: '推送配置',
icon: 'fas fa-rocket',
icon: 'fa fas fa-rocket',
fields: [
{ key: 'baidu_push_enabled', label: '启用百度推送', type: 'switch', default: false, help: '开启后将自动向百度搜索推送页面链接' },
{ key: 'baidu_push_token', label: '推送 Token', type: 'input', default: '', dependsOn: { key: 'baidu_push_enabled', value: true }, help: '在百度搜索资源平台获取的推送准入 Token' },
@@ -31,7 +31,7 @@ export const pushSchema = {
{
key: 'trigger',
title: '触发规则',
icon: 'fas fa-bolt',
icon: 'fa fas fa-bolt',
fields: [
{ key: 'baidu_push_auto', label: '自动推送 (页面加载时)', type: 'switch', default: true, dependsOn: { key: 'baidu_push_enabled', value: true }, help: '在前台页面中嵌入百度自动推送 JS 代码' },
{ key: 'baidu_push_on_publish', label: '发布时主动推送', type: 'switch', default: true, dependsOn: { key: 'baidu_push_enabled', value: true } },
@@ -41,7 +41,7 @@ export const pushSchema = {
{
key: 'xzh',
title: '熊掌号 / JSON-LD',
icon: 'fas fa-paw',
icon: 'fa fas fa-paw',
fields: [
{ key: 'xzh_on', label: '启用熊掌号', type: 'switch', default: false },
{ key: 'xzh_appid', label: '百度 AppID', type: 'input', default: '', dependsOn: { key: 'xzh_on', value: true } },
@@ -54,7 +54,7 @@ export const pushSchema = {
{
key: 'advanced',
title: '高级设置',
icon: 'fas fa-cog',
icon: 'fa fas fa-cog',
fields: [
{ key: 'baidu_push_batch_size', label: '批量推送条数', type: 'number', default: 50, min: 1, max: 500, dependsOn: { key: 'baidu_push_enabled', value: true } },
{ key: 'baidu_push_log_enabled', label: '记录推送日志', type: 'switch', default: true, dependsOn: { key: 'baidu_push_enabled', value: true } },
@@ -1,7 +1,7 @@
export const codeHighlightSchema = {
key: 'global.code-highlight',
title: '代码高亮',
icon: 'fas fa-code',
icon: 'fa fas fa-code',
description: '代码块语法高亮主题、行号、最大高度等配置。',
defaults: {
highlight_kg: true,
@@ -15,7 +15,7 @@ export const codeHighlightSchema = {
{
key: 'basic',
title: '代码高亮设置',
icon: 'fas fa-highlighter',
icon: 'fa fas fa-pen',
fields: [
{ key: 'highlight_kg', label: '代码高亮开关', type: 'switch', default: true },
{ key: 'highlight_hh', label: '显示行号', type: 'switch', default: false },
@@ -26,7 +26,7 @@ export const codeHighlightSchema = {
{
key: 'theme',
title: '主题设置',
icon: 'fas fa-palette',
icon: 'fa fas fa-paint-brush',
fields: [
{
key: 'highlight_zt',
@@ -6,7 +6,7 @@ const defaultThumbnail = themeRoot ? `${themeRoot}/assets/img/thumbnail.svg` : '
export const commonSchema = {
key: 'global.common',
title: '常用功能',
icon: 'fas fa-cog',
icon: 'fa fas fa-cog',
description: '管理站点常用开关、懒加载与备案信息等基础配置。',
defaults: {
lazy_posts_thumb: true,
@@ -27,7 +27,7 @@ export const commonSchema = {
{
key: 'performance',
title: '性能优化',
icon: 'fas fa-tachometer-alt',
icon: 'fa fas fa-tachometer-alt',
fields: [
{ key: 'lazy_posts_thumb', label: '文章缩略图懒加载', type: 'switch', default: true, help: '滚动到图像附近时再加载真实图片。' },
{
@@ -47,7 +47,7 @@ export const commonSchema = {
{
key: 'lazyload-scope',
title: '懒加载范围',
icon: 'fas fa-layer-group',
icon: 'fa fas fa-clone',
fields: [
{ key: 'lazy_avatar', label: '头像懒加载', type: 'switch', default: true },
{ key: 'lazy_posts_content', label: '文章内容图片懒加载', type: 'switch', default: false },
@@ -61,7 +61,7 @@ export const commonSchema = {
{
key: 'filing',
title: '备案信息',
icon: 'fas fa-shield-alt',
icon: 'fa fas fa-shield-alt',
fields: [
{ key: 'icp_filing', label: 'ICP 备案号', type: 'input', placeholder: '例如:京ICP备12345678号', help: '显示在页脚的备案信息' },
{ key: 'police_filing', label: '公安备案号', type: 'input', placeholder: '例如:公网安备11000000000000号', help: '显示在页脚的备案信息' },
@@ -1,7 +1,7 @@
export const customCodeSchema = {
key: 'global.custom-code',
title: '自定义代码',
icon: 'fas fa-code',
icon: 'fa fas fa-code',
description: '自定义 CSS、JS 代码注入。',
defaults: {
custom_css: '',
@@ -13,7 +13,7 @@ export const customCodeSchema = {
{
key: 'css',
title: '自定义 CSS',
icon: 'fab fa-css3-alt',
icon: 'fa fab fa-css3',
fields: [
{ key: 'custom_css', label: '自定义 CSS', type: 'code', language: 'css', placeholder: '/* 在此输入自定义 CSS */', rows: 10, help: '将在页面 <head> 中加载' },
],
@@ -21,7 +21,7 @@ export const customCodeSchema = {
{
key: 'code',
title: '头部 & 底部代码',
icon: 'fas fa-code',
icon: 'fa fas fa-code',
fields: [
{ key: 'head_code', label: '头部 HTML 代码', type: 'code', placeholder: '<!-- 支持 meta/link/style/script 等任意 HTML -->', rows: 6, help: '在 <head> 中输出,支持 meta/link/style/script 等任意 HTML' },
{ key: 'foot_code', label: '底部 HTML 代码', type: 'code', placeholder: '<!-- 在 </body> 前输出 -->', rows: 6, help: '在页面底部 </body> 前输出,支持任意 HTML' },
@@ -30,7 +30,7 @@ export const customCodeSchema = {
{
key: 'stats',
title: '统计代码',
icon: 'fas fa-chart-bar',
icon: 'fa fas fa-chart-bar',
fields: [
{ key: 'trackcode', label: '统计代码', type: 'code', placeholder: '<!-- 百度统计 / GA / CNZZ / 51la -->', rows: 6, help: '百度统计、Google Analytics、CNZZ、51la 等统计代码,自动在 head 中输出' },
],
@@ -1,7 +1,7 @@
export const emailSchema = {
key: 'global.email',
title: '邮件配置',
icon: 'fas fa-envelope',
icon: 'fa fas fa-envelope',
description: 'SMTP 发信配置、邮件事件开关与模板自定义。',
defaults: {
email_footer_text: '',
@@ -19,7 +19,7 @@ export const emailSchema = {
{
key: 'global',
title: '全局设置',
icon: 'fas fa-cog',
icon: 'fa fas fa-cog',
fields: [
{ key: 'email_footer_text', label: '邮件页脚文字', type: 'textarea', rows: 2, placeholder: '留空则使用站点名称', help: '附加在每封邮件底部的文字' },
{ key: 'email_site_branding', label: '显示站点品牌', type: 'switch', default: true, help: '在邮件开头显示「[站点名]」前缀' },
@@ -45,7 +45,7 @@ export const emailSchema = {
{
key: 'branding',
title: '邮件品牌',
icon: 'fas fa-signature',
icon: 'fa fas fa-pen',
fields: [
{ key: 'mail_showname', label: '发件人名称', type: 'input', default: '', help: '覆盖系统默认发件人名称' },
{ key: 'mail_title_prefix', label: '主题前缀', type: 'input', default: '', help: '自动添加在所有邮件主题前面,如【站点名】' },
@@ -56,7 +56,7 @@ export const emailSchema = {
{
key: 'reg_verify_link',
title: '注册验证链接',
icon: 'fas fa-link',
icon: 'fa fas fa-link',
fields: [
{ key: 'email_reg_verify_link_enabled', label: '启用', type: 'switch', default: true, help: '注册后发送验证链接邮件' },
{ key: 'email_reg_verify_link_subject', label: '主题(留空使用默认)', type: 'input', placeholder: '验证你的邮箱地址' },
@@ -67,7 +67,7 @@ export const emailSchema = {
{
key: 'reg_verify_code',
title: '注册验证码',
icon: 'fas fa-keyboard',
icon: 'fa fas fa-keyboard',
fields: [
{ key: 'email_reg_verify_code_enabled', label: '启用', type: 'switch', default: true, help: '注册后发送 6 位验证码邮件' },
{ key: 'email_reg_verify_code_subject', label: '主题(留空使用默认)', type: 'input', placeholder: '邮箱验证码' },
@@ -78,7 +78,7 @@ export const emailSchema = {
{
key: 'reg_success',
title: '注册成功通知',
icon: 'fas fa-check-circle',
icon: 'fa fas fa-check-circle',
fields: [
{ key: 'email_reg_success_enabled', label: '启用', type: 'switch', default: true, help: '邮箱验证成功后发送通知邮件' },
{ key: 'email_reg_success_subject', label: '主题(留空使用默认)', type: 'input', placeholder: '邮箱验证成功' },
@@ -89,7 +89,7 @@ export const emailSchema = {
{
key: 'password_reset',
title: '密码重置',
icon: 'fas fa-unlock-alt',
icon: 'fa fas fa-unlock-alt',
fields: [
{ key: 'email_password_reset_enabled', label: '启用', type: 'switch', default: true, help: '发送密码重置链接邮件' },
{ key: 'email_password_reset_subject', label: '主题(留空使用默认)', type: 'input', placeholder: '重置密码' },
@@ -100,7 +100,7 @@ export const emailSchema = {
{
key: 'change_code',
title: '邮箱变更验证码',
icon: 'fas fa-shield-alt',
icon: 'fa fas fa-shield-alt',
fields: [
{ key: 'email_change_code_enabled', label: '启用', type: 'switch', default: true, help: '变更邮箱时发送验证码邮件' },
{ key: 'email_change_code_subject', label: '主题(留空使用默认)', type: 'input', placeholder: '邮箱验证码' },
@@ -111,7 +111,7 @@ export const emailSchema = {
{
key: 'change_notice',
title: '邮箱变更通知',
icon: 'fas fa-bell',
icon: 'fa fas fa-bell',
fields: [
{ key: 'email_change_notice_enabled', label: '启用', type: 'switch', default: true, help: '邮箱变更成功后向旧邮箱发送通知' },
{ key: 'email_change_notice_subject', label: '主题(留空使用默认)', type: 'input', placeholder: '账号邮箱已变更' },
@@ -1,7 +1,7 @@
export const floatingSchema = {
key: 'global.floating',
title: '右侧悬浮按钮',
icon: 'fas fa-ellipsis-v',
icon: 'fa fas fa-ellipsis-v',
description: '页面右侧浮动按钮的显示与配置。',
defaults: {},
groups: [],
@@ -1,7 +1,7 @@
export const i18nSchema = {
key: 'global.i18n',
title: '多语言翻译',
icon: 'fas fa-language',
icon: 'fa fas fa-language',
description: '配置站点语言、语言切换器和翻译管理。',
defaults: {
i18n_enabled: false,
@@ -16,7 +16,7 @@ export const i18nSchema = {
{
key: 'basic',
title: '基础配置',
icon: 'fas fa-globe',
icon: 'fa fas fa-globe',
fields: [
{ key: 'i18n_enabled', label: '启用多语言', type: 'switch', default: false, help: '开启后站点将支持多语言切换' },
{
@@ -43,7 +43,7 @@ export const i18nSchema = {
{
key: 'languages',
title: '语言管理',
icon: 'fas fa-language',
icon: 'fa fas fa-language',
fields: [
{ key: 'i18n_available_langs', label: '可用语言列表', type: 'textarea', default: 'zh-CN|简体中文\nen|English\nzh-TW|繁體中文\nja|日本語\nko|한국어\nfr|Français\nde|Deutsch\nes|Español\nru|Русский', dependsOn: { key: 'i18n_enabled', value: true }, help: '每行一个语言:语言代码|显示名称(9 种内置语言)' },
{ key: 'i18n_nomenclature', label: '自定义术语', type: 'code', default: '', dependsOn: { key: 'i18n_enabled', value: true }, help: 'JSON 格式自定义翻译术语(key => 翻译),对齐 zibll nomenclature' },
@@ -52,7 +52,7 @@ export const i18nSchema = {
{
key: 'display',
title: '展示设置',
icon: 'fas fa-eye',
icon: 'fa fas fa-eye',
fields: [
{
key: 'i18n_switcher_position',
@@ -1,7 +1,7 @@
export const layoutSchema = {
key: 'global.layout',
title: '显示 & 布局',
icon: 'fas fa-desktop',
icon: 'fa fas fa-desktop',
description: '全局布局风格、颜色方案、字体设置。',
defaults: {
theme_mode: 'time-auto',
@@ -29,7 +29,7 @@ export const layoutSchema = {
{
key: 'loading-animation',
title: '加载动画',
icon: 'fas fa-spinner',
icon: 'fa fas fa-spinner',
fields: [
{ key: 'qj_loading', label: '全站加载动画', type: 'switch', default: false, help: '开启后页面加载时显示全屏加载动画覆盖层' },
{
@@ -57,7 +57,7 @@ export const layoutSchema = {
{
key: 'color',
title: '色彩方案',
icon: 'fas fa-palette',
icon: 'fa fas fa-paint-brush',
fields: [
{
key: 'theme_mode',
@@ -110,7 +110,7 @@ export const layoutSchema = {
{
key: 'layout',
title: '布局设置',
icon: 'fas fa-columns',
icon: 'fa fas fa-columns',
fields: [
{ key: 'container_max_width', label: '内容最大宽度 (px)', type: 'select', default: 1200, options: [
{ label: '1200px', value: 1200 },
@@ -133,7 +133,7 @@ export const layoutSchema = {
{
key: 'sidebar-scope',
title: '侧边栏显示范围',
icon: 'fas fa-th-list',
icon: 'fa fas fa-th-list',
fields: [
{ key: 'sidebar_home_enabled', label: '首页侧边栏', type: 'switch', default: true, dependsOn: { key: 'sidebar_enabled', value: true } },
{ key: 'sidebar_category_enabled', label: '分类页侧边栏', type: 'switch', default: true, dependsOn: { key: 'sidebar_enabled', value: true } },
@@ -146,7 +146,7 @@ export const layoutSchema = {
{
key: 'typography',
title: '字体设置',
icon: 'fas fa-font',
icon: 'fa fas fa-font',
fields: [
{ key: 'font_family', label: '正文字体', type: 'select', default: 'system', options: [
{ label: '系统默认', value: 'system' },
@@ -1,7 +1,7 @@
export const logoSchema = {
key: 'global.logo',
title: 'LOGO & 品牌',
icon: 'fas fa-image',
icon: 'fa fas fa-image',
description: '管理站点 Logo、站点图标和品牌标识。',
defaults: {
site_logo: '',
@@ -15,7 +15,7 @@ export const logoSchema = {
{
key: 'logo',
title: 'Logo 设置',
icon: 'fas fa-image',
icon: 'fa fas fa-image',
fields: [
{ key: 'site_logo', label: '站点 Logo', type: 'media', help: '建议尺寸 300x80,支持 PNG/SVG 透明背景' },
{ key: 'site_logo_dark', label: '暗色模式 Logo', type: 'media', help: '暗色模式下显示的 Logo,留空则使用默认 Logo' },
@@ -26,7 +26,7 @@ export const logoSchema = {
{
key: 'favicon',
title: '站点图标',
icon: 'fas fa-fingerprint',
icon: 'fa fas fa-id-badge',
fields: [
{ key: 'site_favicon', label: '浏览器图标 (Favicon)', type: 'media', help: '建议 32x32 或 16x16 的 ICO/PNG 文件' },
{ key: 'site_icon', label: '移动端图标', type: 'media', help: '建议 192x192 的 PNG,用于移动端添加到桌面' },
@@ -1,76 +1,50 @@
export const searchSchema = {
key: 'global.search',
title: '搜索功能',
icon: 'fas fa-search',
description: '搜索模式、内容类型切换、搜索建议、热门搜索配置。',
icon: 'fa fas fa-search',
description: 'Zibll 原始搜索字段、内容类型、历史、热门词与分类配置。',
defaults: {
search_mode: 'default',
search_type: 'default',
search_history_enabled: true,
hot_search_enabled: true,
hot_search_keywords: '',
search_type: true,
search_type_in: 'post',
search_history: true,
search_popular_key: true,
search_placeholder: '开启精彩搜索',
search_suggestions_enabled: false,
search_posts: true,
'404_search_s': true,
search_no_page: true,
search_exclude_cats: '',
search_exclude_cats: [],
search_cat: true,
search_cat_in: '',
search_more_cat_obj: true,
search_more_cat_obj: [],
search_custom_key_s: true,
search_custom_key: 'title,content',
search_facets: false,
search_facets_order: 'category\ntag',
search_type_post: true,
search_type_user: false,
search_type_category: true,
search_type_tag: true,
search_default_type: 'post',
search_ms_enabled: false,
search_ms_api_url: '',
search_ms_api_key: '',
search_ms_index_prefix: 'aksrt',
search_ms_synonyms: '',
search_custom_key: ['title', 'content', 'excerpt', 'post_tag', 'forum_topic', 'shop_cat', 'shop_discount'],
search_facets: {},
search_ms_s: false,
search_ms_opt: { api_url: 'http://127.0.0.1:7700', api_key: '', index_prefix: 'aksrt', synonyms: [{ key: 'wordpress', val: 'wp,wordp,wordpre' }] },
},
groups: [
{
key: 'basic',
title: '搜索基础',
icon: 'fas fa-search',
icon: 'fa fas fa-search',
fields: [
{
key: 'search_mode',
label: '搜索模式',
type: 'radio',
default: 'default',
options: [
{ label: '默认搜索', value: 'default' },
{ label: 'AJAX 实时搜索', value: 'ajax' },
{ label: '跳转搜索', value: 'redirect' },
],
},
{ key: 'search_placeholder', label: '搜索框提示文字', type: 'input', placeholder: '开启精彩搜索' },
],
},
{
key: 'content-types',
title: '搜索内容类型',
icon: 'fas fa-layer-group',
icon: 'fa fas fa-clone',
fields: [
{ key: 'search_type_post', label: '文章', type: 'switch', default: true },
{ key: 'search_type_user', label: '用户', type: 'switch', default: false },
{ key: 'search_type_category', label: '分类', type: 'switch', default: true },
{ key: 'search_type_tag', label: '标签', type: 'switch', default: true },
{ key: 'search_type', label: '显示切换搜索类型按钮', type: 'switch', default: true },
{
key: 'search_default_type',
label: '默认类型',
type: 'select',
key: 'search_type_in',
label: '默认搜索类型',
type: 'radio',
default: 'post',
options: [
{ label: '文章', value: 'post' },
{ label: '用户', value: 'user' },
{ label: '分类', value: 'category' },
{ label: '标签', value: 'tag' },
],
},
],
@@ -78,51 +52,70 @@ export const searchSchema = {
{
key: 'features',
title: '搜索功能',
icon: 'fas fa-magic',
icon: 'fa fas fa-magic',
fields: [
{ key: 'search_history_enabled', label: '搜索历史', type: 'switch', default: true, help: '记录用户最近的搜索关键词' },
{ key: 'hot_search_enabled', label: '热门搜索', type: 'switch', default: true, help: '在搜索框下方展示热门搜索词' },
{ key: 'hot_search_keywords', label: '热门搜索关键词', type: 'textarea', placeholder: '每行一个关键词', dependsOn: { key: 'hot_search_enabled', value: true }, rows: 3, help: '手动设置热门搜索关键词,留空则自动统计' },
{ key: 'search_suggestions_enabled', label: '搜索建议', type: 'switch', default: false, help: '输入时显示搜索建议(需要 AJAX 搜索模式)' },
{ key: 'search_history', label: '搜索历史', type: 'switch', default: true, help: '显示用户最近的搜索关键词' },
{ key: 'search_popular_key', label: '热门搜索', type: 'switch', default: true, help: '展示网站热门搜索关键词' },
{ key: '404_search_s', label: '404 页面搜索', type: 'switch', default: true, help: '在 404 页面显示搜索功能' },
{ key: 'search_posts', label: '搜索框热门文章', type: 'switch', default: true, help: '在搜索面板中显示热门文章列表' },
{ key: 'search_no_page', label: '排除页面', type: 'switch', default: true, help: '搜索结果中排除页面(仅显示文章)' },
{ key: 'search_exclude_cats', label: '排除分类', type: 'textarea', placeholder: '分类 ID,逗号分隔', rows: 2, default: '', help: '搜索结果中排除的分类 ID(逗号分隔)' },
{ key: 'search_exclude_cats', label: '排除分类', type: 'taxonomy_select', taxonomy: ['category', 'shop_cat'], multiple: true, default: [], help: '搜索结果中排除的文章或商品分类' },
{ key: 'search_custom_key_s', label: '自定义匹配范围', type: 'switch', default: true, help: '启用后可配置搜索匹配字段范围' },
{ key: 'search_custom_key', label: '匹配字段', type: 'textarea', placeholder: 'title,content,excerpt,category,tag,author', rows: 2, default: 'title,content', dependsOn: { key: 'search_custom_key_s', value: true }, help: '搜索匹配字段(逗号分隔:title/content/excerpt/category/tag/author)' },
{ key: 'search_facets', label: '搜索结果筛选', type: 'switch', default: false, help: '启用搜索结果 taxonomy 筛选面板' },
{ key: 'search_facets_order', label: '筛选排序', type: 'textarea', rows: 3, default: 'category\ntag', dependsOn: { key: 'search_facets', value: true }, help: '筛选 fieldset 显示顺序(每行一个 taxonomy slug)' },
{ key: 'search_custom_key', label: '匹配字段', type: 'checkbox', default: ['title', 'content', 'excerpt', 'post_tag', 'forum_topic', 'shop_cat', 'shop_discount'], dependsOn: { key: 'search_custom_key_s', value: true }, options: [
{ label: '标题', value: 'title' }, { label: '内容', value: 'content' }, { label: '简介', value: 'excerpt' },
{ label: '分类', value: 'category' }, { label: '标签', value: 'post_tag' }, { label: '专题', value: 'topics' },
{ label: '评论', value: 'coment' }, { label: '作者昵称', value: 'user' },
{ label: '[帖子]话题', value: 'forum_topic' }, { label: '[帖子]标签', value: 'forum_tag' },
{ label: '[商品]分类', value: 'shop_cat' }, { label: '[商品]特色标签', value: 'shop_tag' }, { label: '[商品]优惠活动', value: 'shop_discount' },
] },
{ key: 'search_facets', label: '搜索筛选', type: 'fieldset', sanitizeType: 'array', default: {}, dependsOn: { key: 'search_ms_s', value: false }, help: '搜索结果中显示的筛选列表;启用 Meilisearch 后由搜索引擎生成关联筛选。', fields: [
{ key: 'category', label: '[文章] 分类', type: 'taxonomy_select', taxonomy: 'category', multiple: true, default: [] },
{ key: 'topics', label: '[文章] 专题', type: 'taxonomy_select', taxonomy: 'topics', multiple: true, default: [] },
{ key: 'post_tag', label: '[文章] 标签', type: 'taxonomy_select', taxonomy: 'post_tag', multiple: true, default: [] },
{ key: 'plate_id', label: '[论坛帖子] 板块 ID', type: 'input', default: '' },
{ key: 'forum_topic', label: '[论坛帖子] 话题', type: 'taxonomy_select', taxonomy: 'forum_topic', multiple: true, default: [] },
{ key: 'forum_tag', label: '[论坛帖子] 标签', type: 'taxonomy_select', taxonomy: 'forum_tag', multiple: true, default: [] },
{ key: 'shop_cat', label: '[商品] 分类', type: 'taxonomy_select', taxonomy: 'shop_cat', multiple: true, default: [] },
{ key: 'shop_discount', label: '[商品] 优惠活动', type: 'taxonomy_select', taxonomy: 'shop_discount', multiple: true, default: [] },
{ key: 'shop_tag', label: '[商品] 特色标签', type: 'taxonomy_select', taxonomy: 'shop_tag', multiple: true, default: [] },
] },
],
},
{
key: 'category-search',
title: '分类搜索',
icon: 'fas fa-folder-open',
icon: 'fa fas fa-folder-open',
fields: [
{ key: 'search_cat', label: '启用分类搜索', type: 'switch', default: true, help: '在搜索框旁显示分类选择器' },
{ key: 'search_cat_in', label: '默认分类', type: 'input', default: '', help: '默认搜索的分类 ID(留空为全部分类)' },
{ key: 'search_more_cat_obj', label: '显示更多分类', type: 'switch', default: true, help: '展开显示全部分类列表' },
{ key: 'search_cat_in', label: '默认分类', type: 'taxonomy_select', taxonomy: 'category', multiple: false, default: '', help: '留空为全部分类' },
{ key: 'search_more_cat_obj', label: '允许选择的更多分类', type: 'taxonomy_select', taxonomy: 'category', multiple: true, default: [] },
],
},
{
key: 'popular',
title: '热门搜索',
icon: 'fas fa-fire',
icon: 'fa fas fa-fire',
fields: [
{ key: 'search_popular_title', label: '标题', type: 'input', default: '热门搜索', help: '热门搜索区域标题,留空使用默认' },
{ key: 'search_popular_key_num', label: '显示数量', type: 'number', default: 20, min: 1, max: 50, help: '热门搜索显示条数' },
{ key: 'search_popular_sticky', label: '置顶词(每行一个)', type: 'textarea', rows: 3, default: '', help: '置顶搜索词始终显示在最前面' },
{ key: 'search_popular_key_num', label: '显示数量', type: 'number', default: 20, min: 10, max: 50, step: 2, help: '热门搜索显示条数' },
{ key: 'search_popular_sticky', label: '置顶关键词', type: 'input', default: '', help: '使用逗号分隔;可追加 &type=user 指定搜索类型' },
],
},
{
key: 'meilisearch',
title: 'Meilisearch 集成',
icon: 'fas fa-bolt',
title: 'Meilisearch 智能搜索',
icon: 'fa fas fa-bolt',
fields: [
{ key: 'search_ms_enabled', label: '启用 Meilisearch', type: 'switch', default: false, help: '启用后搜索请求将发送至 Meilisearch 服务器' },
{ key: 'search_ms_api_url', label: 'API 地址', type: 'input', default: '', help: 'Meilisearch 服务器 URL(如 http://localhost:7700)' },
{ key: 'search_ms_api_key', label: 'API Key', type: 'input', default: '', help: 'Meilisearch Search API Key(只读密钥)' },
{ key: 'search_ms_index_prefix', label: '索引前缀', type: 'input', default: 'aksrt', help: '索引名称前缀(实际索引名为 {prefix}_posts)' },
{ key: 'search_ms_synonyms', label: '同义词(JSON)', type: 'textarea', rows: 3, default: '', help: 'Meilisearch 同义词配置,JSON 格式(如 {"手机": ["phone","mobile"]})' },
{ key: 'search_ms_s', label: '启用 Meilisearch', type: 'switch', default: false },
{ key: 'search_ms_opt', label: 'Meilisearch 参数', type: 'fieldset', sanitizeType: 'array', dependsOn: { key: 'search_ms_s', value: true }, default: { api_url: 'http://127.0.0.1:7700', api_key: '', index_prefix: 'aksrt', synonyms: [{ key: 'wordpress', val: 'wp,wordp,wordpre' }] }, fields: [
{ key: 'api_url', label: 'API 地址', type: 'input', default: 'http://127.0.0.1:7700' },
{ key: 'api_key', label: 'API 密钥', type: 'input', default: '' },
{ key: 'index_prefix', label: '索引前缀', type: 'input', default: 'aksrt' },
{ key: 'synonyms', label: '同义词', type: 'repeater', default: [{ key: 'wordpress', val: 'wp,wordp,wordpre' }], addText: '添加同义词', fields: [
{ key: 'key', label: '关键词', type: 'input', default: '' },
{ key: 'val', label: '同义词', type: 'textarea', default: '' },
] },
] },
],
},
],
@@ -1,7 +1,7 @@
export const seoSchema = {
key: 'global.seo',
title: 'SEO 优化',
icon: 'fas fa-search',
icon: 'fa fas fa-search',
description: '站点标题、描述、关键词与 AI SEO。AI 生成入口在文章「独立 SEO」框;连接配置在「扩展 → AI 连接配置」。优先使用 WordPress AI Connectors。',
defaults: {
seo_enabled: true,
@@ -34,7 +34,7 @@ export const seoSchema = {
{
key: 'basic',
title: 'SEO 基础',
icon: 'fas fa-globe',
icon: 'fa fas fa-globe',
fields: [
{
key: 'seo_enabled',
@@ -60,7 +60,7 @@ export const seoSchema = {
{
key: 'ai-seo',
title: 'AI SEO 提示词',
icon: 'fas fa-robot',
icon: 'fa fab fa-android',
description: '留空则使用内置 Zibll 风格默认提示词。填写后作为 system instruction 覆盖默认。',
fields: [
{
@@ -98,7 +98,7 @@ export const seoSchema = {
{
key: 'baidu',
title: '百度推送',
icon: 'fas fa-paper-plane',
icon: 'fa fas fa-paper-plane',
fields: [
{ key: 'seo_baidu_push', label: '启用百度自动推送', type: 'switch', default: false },
{ key: 'seo_baidu_normal', label: '普通收录推送', type: 'switch', default: false },
@@ -109,7 +109,7 @@ export const seoSchema = {
{
key: 'image',
title: '图片 SEO',
icon: 'fas fa-image',
icon: 'fa fas fa-image',
fields: [
{ key: 'seo_image_optimize', label: '优化搜索引擎图片展示', type: 'switch', default: true },
{ key: 'seo_image_default', label: '默认分享图 / SEO 图', type: 'media', default: '' },
@@ -120,7 +120,7 @@ export const seoSchema = {
{
key: 'redirect',
title: '外链重定向',
icon: 'fas fa-external-link-alt',
icon: 'fa fas fa-external-link-alt',
fields: [
{ key: 'seo_go_link', label: '启用外链重定向', type: 'switch', default: true },
{ key: 'seo_go_link_nonce', label: '启用外链鉴权', type: 'switch', default: true },
@@ -131,7 +131,7 @@ export const seoSchema = {
{
key: 'advanced',
title: '高级 SEO',
icon: 'fas fa-sliders-h',
icon: 'fa fas fa-sliders-h',
fields: [
{ key: 'seo_no_category', label: '分类 URL 去掉 category', type: 'switch', default: false },
{ key: 'seo_jsonld', label: '启用 JSON-LD', type: 'switch', default: true },
@@ -1,7 +1,7 @@
export const systemNoticeSchema = {
key: 'global.system-notice',
title: '弹窗通知',
icon: 'fas fa-bullhorn',
icon: 'fa fas fa-bullhorn',
description: '全站弹窗公告配置,支持按用户身份定向、多按钮组、弹窗尺寸与过期周期。',
defaults: {
system_notice_enabled: true,
@@ -32,7 +32,7 @@ export const systemNoticeSchema = {
{
key: 'basic',
title: '公告设置',
icon: 'fas fa-bullhorn',
icon: 'fa fas fa-bullhorn',
fields: [
{ key: 'system_notice_enabled', label: '启用系统公告', type: 'switch', default: true },
{
@@ -56,7 +56,7 @@ export const systemNoticeSchema = {
{
key: 'buttons',
title: '按钮组(留空则不显示)',
icon: 'fas fa-th-large',
icon: 'fa fas fa-th-large',
fields: [
{ key: 'system_notice_btn1_text', label: '按钮 1 文案', type: 'input', default: '', dependsOn: { key: 'system_notice_enabled', value: true } },
{ key: 'system_notice_btn1_link', label: '按钮 1 链接', type: 'input', default: '', dependsOn: { key: 'system_notice_enabled', value: true }, help: '可选,填写后按钮变为链接' },
@@ -107,7 +107,7 @@ export const systemNoticeSchema = {
{
key: 'style',
title: '样式设置',
icon: 'fas fa-paint-brush',
icon: 'fa fas fa-paint-brush',
fields: [
{
key: 'system_notice_size',
@@ -124,7 +124,7 @@ export const systemNoticeSchema = {
},
{ key: 'system_notice_radius', label: '按钮圆角', type: 'switch', default: false, dependsOn: { key: 'system_notice_enabled', value: true }, help: '开启后弹窗按钮使用圆角样式' },
{ key: 'system_notice_class', label: '公告样式类', type: 'input', default: '', dependsOn: { key: 'system_notice_enabled', value: true } },
{ key: 'system_notice_title_icon', label: '标题图标', type: 'input', default: '', dependsOn: { key: 'system_notice_enabled', value: true }, help: '如 fas fa-bullhorn' },
{ key: 'system_notice_title_icon', label: '标题图标', type: 'input', default: '', dependsOn: { key: 'system_notice_enabled', value: true }, help: '如 fa fas fa-bullhorn' },
{ key: 'system_notice_title_class', label: '标题背景配色', type: 'select', default: '', dependsOn: { key: 'system_notice_enabled', value: true }, options: [
{ label: '无', value: '' },
{ label: '炫彩黄', value: 'jb-yellow' },
@@ -140,7 +140,7 @@ export const systemNoticeSchema = {
{
key: 'expire',
title: '过期设置',
icon: 'fas fa-clock',
icon: 'fa fas fa-clock',
fields: [
{ key: 'system_notice_expires', label: '弹窗周期(小时)', type: 'number', default: 24, min: 0, max: 720, dependsOn: { key: 'system_notice_enabled', value: true }, help: '0 表示永不过期' },
],
@@ -1,7 +1,7 @@
export const tabbarSchema = {
key: 'global.tabbar',
title: '手机底部Tab',
icon: 'fas fa-mobile-alt',
icon: 'fa fas fa-mobile-alt',
description: '移动端底部导航栏配置。',
defaults: {},
groups: [],
@@ -30,28 +30,23 @@ export const pageDisplaySchemas = {
'header-nav': {
key: 'page_display.header-nav',
title: '顶部导航栏',
icon: 'fas fa-bars',
icon: 'fa fas fa-bars',
description: '配置导航栏布局、菜单结构、搜索入口和用户入口。',
defaults: {
header_fixed: true,
header_search_enabled: true,
header_user_menu: true,
header_mobile_drawer: true,
header_nav_style: 'default',
header_max_width: 1200,
header_scroll_down_hide: true,
nav_fixed: true,
nav_scroll_down_hide: true,
header_layout: '1',
header_nav_pay_vip: true,
header_nav_user_pay_vip: true,
header_newposts_types: ['post'],
header_user_newposts_btn: 'post',
header_user_newposts_text: '发布内容',
nav_pay_vip: true,
nav_user_pay_vip: true,
nav_newposts_btns: ['post'],
nav_user_newposts_btn: 'post',
nav_user_newposts_btn_text: '发布文章',
mobile_header_layout: 'center',
mobile_navbar_align: 'left',
header_newposts_enabled: true,
header_newposts_text: '<i class="fa fa-pencil"></i> 发布',
header_newposts_radius: true,
header_newposts_class: 'jb-blue',
nav_newposts: true,
nav_newposts_text: '<i class="fa fas fa-fw fa-pen"></i>发布',
nav_newposts_radius: true,
nav_newposts_class: 'jb-blue',
header_theme_custom: false,
header_theme_bg_custom: '',
header_theme_bg: '',
@@ -61,27 +56,16 @@ export const pageDisplaySchemas = {
{
key: 'layout',
title: '导航栏布局',
icon: 'fas fa-th-large',
icon: 'fa fas fa-th-large',
fields: [
{ key: 'header_fixed', label: '固定导航栏', type: 'switch', default: true, help: '页面滚动时导航栏保持在顶部' },
{ key: 'header_nav_style', label: '导航栏风格', type: 'radio', default: 'default', options: [
{ label: '默认', value: 'default' },
{ label: '透明', value: 'transparent' },
{ label: '毛玻璃', value: 'blur' },
]},
{ key: 'header_max_width', label: '导航栏最大宽度', type: 'select', default: 1200, options: [
{ label: '跟随内容', value: 0 },
{ label: '1080px', value: 1080 },
{ label: '1200px', value: 1200 },
{ label: '1320px', value: 1320 },
]},
{ key: 'header_scroll_down_hide', label: '下滑隐藏导航', type: 'switch', default: true, help: '下滚动隐藏,上滚动显示(需开启固定导航)' },
{ key: 'nav_fixed', label: '导航栏一直固定在顶部', type: 'switch', default: true },
{ key: 'nav_scroll_down_hide', label: '下滚动隐藏,上滚动显示', type: 'switch', default: true, dependsOn: { key: 'nav_fixed', value: true } },
],
},
{
key: 'layout-type',
title: '布局类型',
icon: 'fas fa-columns',
icon: 'fa fas fa-columns',
fields: [
{
key: 'header_layout',
@@ -121,34 +105,34 @@ export const pageDisplaySchemas = {
{
key: 'newposts',
title: '发布按钮',
icon: 'fas fa-pen',
icon: 'fa fas fa-pen',
fields: [
{ key: 'header_newposts_enabled', label: '启用发布按钮', type: 'switch', default: true, help: '顶部导航显示发布入口(对齐 zibll nav_newposts)' },
{ key: 'header_newposts_text', label: '按钮文案', type: 'input', default: '<i class="fa fa-pencil"></i> 发布', dependsOn: { key: 'header_newposts_enabled', value: true } },
{ key: 'header_newposts_radius', label: '按钮圆角(胶囊)', type: 'switch', default: true, dependsOn: { key: 'header_newposts_enabled', value: true }, help: '开启后两端大圆角,对齐 zibll nav_newposts_radius' },
{ key: 'header_newposts_class', label: '按钮颜色', type: 'select', default: 'jb-blue', options: [
{ key: 'nav_newposts', label: '启用发布按钮', type: 'switch', default: true },
{ key: 'nav_newposts_text', label: '按钮文案', type: 'input', default: '<i class="fa fas fa-fw fa-pen"></i>发布', dependsOn: { key: 'nav_newposts', value: true } },
{ key: 'nav_newposts_radius', label: '按钮圆角(胶囊)', type: 'switch', default: true, dependsOn: { key: 'nav_newposts', value: true } },
{ key: 'nav_newposts_class', label: '按钮颜色', type: 'select', default: 'jb-blue', options: [
{ label: '蓝色', value: 'jb-blue' },
{ label: '红色', value: 'jb-red' },
{ label: '绿色', value: 'jb-green' },
{ label: '黄色', value: 'jb-yellow' },
{ label: '紫色', value: 'jb-purple' },
{ label: '粉色', value: 'jb-pink' },
], dependsOn: { key: 'header_newposts_enabled', value: true } },
{ key: 'header_newposts_types', label: '发布类型', type: 'checkbox', default: ['post'], options: [
], dependsOn: { key: 'nav_newposts', value: true } },
{ key: 'nav_newposts_btns', label: '发布类型', type: 'checkbox', default: ['post'], options: [
{ label: '文章', value: 'post' },
], dependsOn: { key: 'header_newposts_enabled', value: true }, help: '未开启的模块不会显示' },
{ key: 'header_user_newposts_btn', label: '用户卡发布类型', type: 'select', default: 'post', options: [
], dependsOn: { key: 'nav_newposts', value: true } },
{ key: 'nav_user_newposts_btn', label: '用户卡发布类型', type: 'select', default: 'post', options: [
{ label: '文章', value: 'post' },
] },
{ key: 'header_user_newposts_text', label: '用户卡发布文案', type: 'input', default: '发布内容' },
{ key: 'header_nav_pay_vip', label: '导航栏开通会员按钮', type: 'switch', default: true, help: '顶部导航显示开通会员' },
{ key: 'header_nav_user_pay_vip', label: '用户框开通会员按钮', type: 'switch', default: true },
{ key: 'nav_user_newposts_btn_text', label: '用户卡发布文案', type: 'input', default: '发布文章' },
{ key: 'nav_pay_vip', label: '导航栏开通会员按钮', type: 'switch', default: true },
{ key: 'nav_user_pay_vip', label: '用户框开通会员按钮', type: 'switch', default: true },
],
},
{
key: 'color',
title: '导航配色',
icon: 'fas fa-palette',
icon: 'fa fas fa-paint-brush',
fields: [
{ key: 'header_theme_custom', label: '自定义导航配色', type: 'switch', default: false, help: '启用后覆盖导航栏默认配色' },
{ key: 'header_theme_bg_custom', label: '导航背景色', type: 'color', default: '', dependsOn: { key: 'header_theme_custom', value: true } },
@@ -156,16 +140,6 @@ export const pageDisplaySchemas = {
{ key: 'header_theme_color_custom', label: '导航文字色', type: 'color', default: '', dependsOn: { key: 'header_theme_custom', value: true } },
],
},
{
key: 'components',
title: '导航组件',
icon: 'fas fa-puzzle-piece',
fields: [
{ key: 'header_search_enabled', label: '搜索入口', type: 'switch', default: true },
{ key: 'header_user_menu', label: '用户菜单', type: 'switch', default: true },
{ key: 'header_mobile_drawer', label: '移动端抽屉导航', type: 'switch', default: true },
],
},
],
},
@@ -175,7 +149,7 @@ export const pageDisplaySchemas = {
category: {
key: 'page_display.category',
title: '分类页面',
icon: 'fas fa-folder-open',
icon: 'fa fas fa-folder-open',
description: '为分类归档页配置头图、简介、列表模式、筛选条和侧边栏。',
defaults: {
category_cover_enabled: true,
@@ -193,7 +167,7 @@ export const pageDisplaySchemas = {
{
key: 'header',
title: '分类头图',
icon: 'fas fa-image',
icon: 'fa fas fa-image',
fields: [
{ key: 'category_header_style', label: '头部风格', type: 'radio', default: 'cover', options: [
{ label: '封面图', value: 'cover' },
@@ -208,7 +182,7 @@ export const pageDisplaySchemas = {
{
key: 'list',
title: '列表设置',
icon: 'fas fa-list',
icon: 'fa fas fa-list',
fields: [
{ key: 'category_list_mode', label: '列表模式', type: 'radio', default: 'grid', options: [
{ label: '网格', value: 'grid' },
@@ -224,7 +198,7 @@ export const pageDisplaySchemas = {
{
key: 'orderby',
title: '排序设置',
icon: 'fas fa-sort',
icon: 'fa fas fa-sort',
fields: [
{ key: 'category_orderby', label: '默认排序', type: 'select', default: 'modified', options: [
{ label: '最近更新', value: 'modified' },
@@ -244,7 +218,7 @@ export const pageDisplaySchemas = {
tag: {
key: 'page_display.tag',
title: '标签页面',
icon: 'fas fa-tags',
icon: 'fa fas fa-tags',
description: '为标签归档页配置展示样式和布局。',
defaults: {
tag_header_style: 'simple',
@@ -259,7 +233,7 @@ export const pageDisplaySchemas = {
{
key: 'header',
title: '标签头图',
icon: 'fas fa-tag',
icon: 'fa fas fa-tag',
fields: [
{ key: 'tag_header_style', label: '头部风格', type: 'radio', default: 'simple', options: [
{ label: '简洁标题', value: 'simple' },
@@ -272,7 +246,7 @@ export const pageDisplaySchemas = {
{
key: 'list',
title: '列表设置',
icon: 'fas fa-list',
icon: 'fa fas fa-list',
fields: [
{ key: 'tag_list_mode', label: '列表模式', type: 'radio', default: 'grid', options: [
{ label: '网格', value: 'grid' },
@@ -286,7 +260,7 @@ export const pageDisplaySchemas = {
{
key: 'orderby',
title: '排序设置',
icon: 'fas fa-sort',
icon: 'fa fas fa-sort',
fields: [
{ key: 'tag_orderby', label: '默认排序', type: 'select', default: 'count', options: [
{ label: '文章数', value: 'count' },
@@ -304,7 +278,7 @@ export const pageDisplaySchemas = {
'user-home': {
key: 'page_display.user-home',
title: '用户主页',
icon: 'fas fa-user-circle',
icon: 'fa fas fa-user-circle',
description: '公开用户主页对齐 Zibll 作者页:通栏头图 + Tab 计数;交易/快捷入口仅在用户中心。',
defaults: {
user_home_tabs: 'posts,favorites,comments,follow',
@@ -330,7 +304,7 @@ export const pageDisplaySchemas = {
{
key: 'layout',
title: '主页布局',
icon: 'fas fa-th-large',
icon: 'fa 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' }] },
@@ -343,7 +317,7 @@ export const pageDisplaySchemas = {
{
key: 'tabs',
title: 'Tab 配置',
icon: 'fas fa-columns',
icon: 'fa fas fa-columns',
fields: [
{ key: 'user_home_tabs', label: '显示的 Tab', type: 'input', default: 'posts,favorites,comments,follow', help: '逗号分隔;默认 posts,favorites,comments,follow(粉丝)。可选 credits' },
{ key: 'user_home_tabs_order', label: 'Tab 显示顺序', type: 'input', default: 'posts,favorites,comments,follow', help: '逗号分隔,控制栏目顺序' },
@@ -355,7 +329,7 @@ export const pageDisplaySchemas = {
{
key: 'display',
title: '展示设置',
icon: 'fas fa-eye',
icon: 'fa fas fa-eye',
fields: [
{ key: 'user_home_avatar', label: '显示头像', type: 'switch', default: true },
{ key: 'user_home_name', label: '显示用户名', type: 'switch', default: true },
@@ -375,7 +349,7 @@ export const pageDisplaySchemas = {
other: {
key: 'page_display.other',
title: '其它页面',
icon: 'fas fa-file',
icon: 'fa fas fa-file',
description: '配置 404 页面、搜索结果页等特殊页面的展示。',
defaults: {
page_header_style: '1',
@@ -394,7 +368,7 @@ export const pageDisplaySchemas = {
{
key: 'page-header',
title: '统一页头',
icon: 'fas fa-heading',
icon: 'fa fas fa-heading',
fields: [
{ key: 'page_header_style', label: '页面标题样式', type: 'select', default: '1', options: [
{ label: '不显示', value: '' },
@@ -408,7 +382,7 @@ export const pageDisplaySchemas = {
{
key: 'page_404',
title: '404 页面',
icon: 'fas fa-exclamation-triangle',
icon: 'fa fas fa-exclamation-triangle',
fields: [
{ key: 'page_404_message', label: '404 提示文字', type: 'input', default: '页面未找到' },
{ key: 'page_404_search', label: '显示搜索框', type: 'switch', default: true },
@@ -419,7 +393,7 @@ export const pageDisplaySchemas = {
{
key: 'search_results',
title: '搜索结果页',
icon: 'fas fa-search',
icon: 'fa fas fa-search',
fields: [
{ key: 'page_search_sidebar', label: '搜索结果侧边栏', type: 'switch', default: true },
{ key: 'page_search_per_page', label: '每页结果数', type: 'number', default: 12, min: 4, max: 48 },
@@ -428,7 +402,7 @@ export const pageDisplaySchemas = {
{
key: 'author',
title: '作者页面',
icon: 'fas fa-user-edit',
icon: 'fa fas fa-user',
fields: [
{ key: 'page_author_cover', label: '显示封面', type: 'switch', default: true },
{ key: 'page_author_sidebar', label: '显示侧边栏', type: 'switch', default: true },
@@ -444,7 +418,7 @@ export const pageDisplaySchemas = {
background: {
key: 'page_display.background',
title: '全局背景',
icon: 'fas fa-image',
icon: 'fa fas fa-image',
description: '配置站点全局背景图、背景色、暗色模式背景和遮罩。',
defaults: {
bg_color: '',
@@ -464,7 +438,7 @@ export const pageDisplaySchemas = {
{
key: 'light',
title: '亮色背景',
icon: 'fas fa-sun',
icon: 'fa fas fa-sun',
fields: [
{ key: 'bg_color', label: '背景颜色', type: 'color', default: '', help: '留空则使用主题默认背景色' },
{ key: 'bg_image', label: '背景图片', type: 'media', help: '推荐使用高分辨率图片' },
@@ -495,7 +469,7 @@ export const pageDisplaySchemas = {
{
key: 'dark',
title: '暗色背景',
icon: 'fas fa-moon',
icon: 'fa fas fa-moon',
fields: [
{ key: 'bg_dark_color', label: '暗色背景颜色', type: 'color', default: '', help: '留空则使用主题默认暗色背景' },
{ key: 'bg_dark_image', label: '暗色背景图片', type: 'media', help: '暗色模式下显示的背景图' },
@@ -504,7 +478,7 @@ export const pageDisplaySchemas = {
{
key: 'overlay',
title: '遮罩设置',
icon: 'fas fa-layer-group',
icon: 'fa fas fa-clone',
fields: [
{ key: 'bg_overlay', label: '启用背景遮罩', type: 'switch', default: false, help: '在背景图上方叠加半透明遮罩,提升文字可读性' },
{ key: 'bg_overlay_color', label: '遮罩颜色', type: 'input', default: 'rgba(0, 0, 0, 0.3)', dependsOn: { key: 'bg_overlay', value: true }, help: '支持 rgba/hex 色值' },
@@ -513,7 +487,7 @@ export const pageDisplaySchemas = {
{
key: 'page',
title: '页面背景',
icon: 'fas fa-file',
icon: 'fa fas fa-file',
fields: [
{ key: 'page_bg_color', label: '内容区背景色', type: 'color', default: '', help: '主内容区域的背景色' },
{ key: 'page_bg_image', label: '内容区背景图', type: 'media' },
@@ -522,142 +496,41 @@ export const pageDisplaySchemas = {
],
},
/**
* Menu decoration settings
*/
'menu-decoration': {
key: 'page_display.menu-decoration',
title: '菜单装饰',
icon: 'fas fa-bars',
description: '配置导航菜单的图标、徽章、下拉样式和图文卡片子菜单。',
defaults: {
menu_icon_enabled: true,
menu_badge_enabled: true,
menu_submenu_style: 'dropdown',
menu_submenu_columns: 1,
menu_submenu_width: 220,
menu_mobile_style: 'drawer',
menu_item_padding: 12,
menu_hover_effect: 'underline',
},
groups: [
{
key: 'icon',
title: '菜单图标',
icon: 'fas fa-icons',
fields: [
{ key: 'menu_icon_enabled', label: '显示菜单图标', type: 'switch', default: true, help: '在菜单项文字前显示图标(需在菜单管理中设置 CSS 类)' },
{ key: 'menu_badge_enabled', label: '显示菜单徽章', type: 'switch', default: true, help: '在菜单项上显示 "新"、"热" 等徽章标记' },
],
},
{
key: 'submenu',
title: '下拉子菜单',
icon: 'fas fa-caret-square-down',
fields: [
{
key: 'menu_submenu_style',
label: '子菜单样式',
type: 'radio',
default: 'dropdown',
options: [
{ label: '普通下拉', value: 'dropdown' },
{ label: '多列下拉', value: 'mega' },
{ label: '图文卡片', value: 'cards' },
],
},
{ key: 'menu_submenu_columns', label: '多列列数', type: 'number', default: 1, min: 1, max: 5, dependsOn: { key: 'menu_submenu_style', value: 'mega' } },
{ key: 'menu_submenu_width', label: '子菜单宽度 (px)', type: 'number', default: 220, min: 160, max: 800, dependsOn: { key: 'menu_submenu_style', value: 'mega' } },
],
},
{
key: 'effect',
title: '交互效果',
icon: 'fas fa-magic',
fields: [
{
key: 'menu_hover_effect',
label: 'Hover 效果',
type: 'radio',
default: 'underline',
options: [
{ label: '下划线', value: 'underline' },
{ label: '背景色', value: 'background' },
{ label: '文字变色', value: 'color' },
{ label: '无效果', value: 'none' },
],
},
{ key: 'menu_item_padding', label: '菜单项内边距 (px)', type: 'number', default: 12, min: 4, max: 32 },
],
},
{
key: 'mobile',
title: '移动端菜单',
icon: 'fas fa-mobile-alt',
fields: [
{
key: 'menu_mobile_style',
label: '移动端菜单样式',
type: 'radio',
default: 'drawer',
options: [
{ label: '抽屉', value: 'drawer' },
{ label: '全屏', value: 'fullscreen' },
{ label: '下拉', value: 'dropdown' },
],
},
],
},
],
},
/**
* Header components
*/
'header-components': {
key: 'page_display.header-components',
title: '顶部多功能组件',
icon: 'fas fa-th',
description: '配置顶部组件的显示范围、设备规则、轮播参数、搜索覆盖层与图标卡片。幻灯片图片/文案内容请到「Hero 轮播」「Banner 轮播」管理。',
icon: 'fa fas fa-th',
description: 'Zibll 顶部幻灯、搜索覆盖层和图标卡片的原始字段契约。',
defaults: {
header_components_search_enabled: true,
header_components_cards_enabled: false,
header_components_nav_color: '#ffffff',
header_components_show_on: ['home'],
header_components_device_visibility: '',
header_components_filter_blur_devices: ['pc', 'mobile'],
header_components_card_show_devices: ['pc', 'mobile'],
header_components_card_shared_bg: false,
header_components_card_icon_shape: 'circle',
header_components_icon_cards: [],
header_components_search_pc: true,
header_components_search_mobile: true,
header_components_search_show_keywords: true,
header_components_search_popular_limit: 6,
header_components_search_in_cat: '',
header_components_search_in_type: 'post',
header_components_search_more_cats: [],
header_components_search_show_input_cat: false,
header_components_search_show_type: false,
header_components_search_before_html: '<div class="em16 font-bold mb10">更优雅的Wordpress主题</div>\n<div>这是导航栏幻灯片多功能组件,可在后台进行配置</div>',
header_components_search_after_html: '',
slider_config_direction: 'horizontal',
slider_config_speed: 300,
slider_config_button: true,
slider_config_scale_height: false,
slider_config_scale: false,
slider_config_max_height: '',
slider_config_min_height: '',
header_slider_show: [],
header_slider_show_type: '',
header_slider_nav_color: '#ffffff',
header_slider: [
{ background: themeAsset('assets/vendor/zibll/img/slider-bg.jpg'), link: { url: 'https://www.zibll.com/', target: '_blank' }, text: { desc: '', title: '' }, text_align: 'left-bottom', text_parallax: 30, text_size_m: 20, text_size_pc: 30 },
{ background: themeAsset('assets/vendor/zibll/img/user_t.jpg'), link: { url: 'https://www.zibll.com/', target: '_blank' }, text: { desc: '', title: '' }, text_align: 'left-bottom', text_parallax: 30, text_size_m: 20, text_size_pc: 30 },
],
header_slider_option: { direction: 'horizontal', loop: true, button: true, pagination: true, effect: 'slide', scale_height: false, auto_height: false, pc_height: 550, m_height: 280, spacebetween: 0, speed: 0, autoplay: true, interval: 6 },
header_slider_search_s: ['pc_s', 'm_s'],
header_slider_search_option: { show_keywords: true, popular_limit: 6, show_input_cat: false, in_cat: '', more_cats: [], show_type: false, in_type: 'post', before_html: '<div class="em16 font-bold mb10">更优雅的Wordpress主题</div>\n<div>这是导航栏幻灯片多功能组件,可在后台进行配置</div>', after_html: '' },
header_slider_card_s: ['pc_s', 'm_s'],
header_slider_card_option: { show_widget_bg: false, icon_radius4: false, cards: [
{ icon: 'zibsvg-vip_1', customize_icon: '', icon_class: 'c-yellow', link: {}, title: '图标卡片', desc: '这是一个图标卡片示例' },
{ icon: 'zibsvg-vip_2', customize_icon: '', icon_class: 'c-blue-2', link: {}, title: '原创作品', desc: '这是一个图标卡片示例' },
{ icon: 'zibsvg-hot', customize_icon: '', icon_class: 'jb-pink', link: {}, title: '灵感来源<badge class="ml6 jb-yellow">NEW</badge>', desc: '这是一个图标卡片示例' },
{ icon: 'fa fas fa-ioxhost', customize_icon: '', icon_class: 'jb-cyan', link: {}, title: '系统工具 <badge class="ml6 jb-blue">GO <span class="fa fas fa-angle-right em12"></span></badge>', desc: '这是一个图标卡片示例' },
] },
header_slider_filter_blur: ['pc_s', 'm_s'],
},
groups: [
{
key: 'visibility',
title: '显示规则',
icon: 'fas fa-eye',
icon: 'fa fas fa-eye',
fields: [
{ key: 'header_components_search_enabled', label: '启用搜索覆盖层', type: 'switch', default: true, help: '在顶部组件区域显示搜索条覆盖层' },
{ key: 'header_components_cards_enabled', label: '启用图标卡片', type: 'switch', default: false, help: '在顶部组件区域显示图标卡片入口' },
{ key: 'header_components_show_on', label: '按页面类型启用', type: 'checkbox', default: ['home'], options: [
{ key: 'header_slider_show', label: '启用顶部多功能组件的页面', type: 'checkbox', default: [], options: [
{ label: '首页', value: 'home' },
{ label: '分类页', value: 'category' },
{ label: '标签页', value: 'tag' },
@@ -665,150 +538,60 @@ export const pageDisplaySchemas = {
{ label: '文章页', value: 'single' },
{ label: '搜索页', value: 'search' },
{ label: '其它页面', value: 'page' },
], help: '选择启用顶部多功能组件的页面类型,一个都不选则为关闭此功能' },
{ key: 'header_components_device_visibility', label: '设备显示规则', type: 'radio', default: '', options: [
{ label: '专题页', value: 'topics' },
{ label: '论坛首页', value: 'forum_home' },
{ label: '论坛板块', value: 'forum_plate' },
{ label: '论坛帖子', value: 'forum_post' },
] },
{ key: 'header_slider_show_type', label: '设备显示规则', type: 'radio', default: '', options: [
{ label: '全部', value: '' },
{ label: '仅电脑', value: 'only_pc' },
{ label: '仅移动', value: 'only_sm' },
] },
], dependsOn: { key: 'header_slider_show', not: [] } },
{ key: 'header_slider_nav_color', label: '导航栏文字颜色', type: 'color', default: '#ffffff', dependsOn: { key: 'header_slider_show', not: [] } },
],
},
{
key: 'nav-color',
title: '导航栏配色',
icon: 'fas fa-palette',
key: 'slides',
title: '背景内容',
icon: 'fa fas fa-image',
fields: [
{ key: 'header_components_nav_color', label: '导航栏文字颜色', type: 'color', default: '#ffffff', help: '顶部组件叠加时固定导航的文字颜色' },
{ key: 'header_slider', label: '幻灯片项目', type: 'json', sanitizeType: 'array', default: [
{ background: themeAsset('assets/vendor/zibll/img/slider-bg.jpg'), link: { url: 'https://www.zibll.com/', target: '_blank' }, text: { desc: '', title: '' }, text_align: 'left-bottom', text_parallax: 30, text_size_m: 20, text_size_pc: 30 },
{ background: themeAsset('assets/vendor/zibll/img/user_t.jpg'), link: { url: 'https://www.zibll.com/', target: '_blank' }, text: { desc: '', title: '' }, text_align: 'left-bottom', text_parallax: 30, text_size_m: 20, text_size_pc: 30 },
], help: '原始数组字段:background、background_video、video、hide、link、image_layer、text。' },
],
},
{
key: 'slider-config',
title: '幻灯片配置',
icon: 'fas fa-sliders-h',
title: '背景显示设置',
icon: 'fa fas fa-sliders-h',
fields: [
{ key: 'slider_config_direction', label: '滑动方向', type: 'radio', default: 'horizontal', options: [
{ label: '水平', value: 'horizontal' },
{ label: '垂直', value: 'vertical' },
]},
{ key: 'slider_config_speed', label: '切换速度 (ms)', type: 'number', default: 300, min: 100, max: 3000 },
{ key: 'slider_config_button', label: '显示前进后退按钮', type: 'switch', default: true },
{ key: 'slider_config_scale_height', label: '缩放高度', type: 'switch', default: false },
{ key: 'slider_config_scale', label: '缩放效果', type: 'switch', default: false },
{ key: 'slider_config_max_height', label: '最大高度', type: 'input', default: '' },
{ key: 'slider_config_min_height', label: '最小高度', type: 'input', default: '' },
{ key: 'header_slider_option', label: '幻灯片参数', type: 'json', sanitizeType: 'array', default: { direction: 'horizontal', loop: true, button: true, pagination: true, effect: 'slide', scale_height: false, auto_height: false, pc_height: 550, m_height: 280, spacebetween: 0, speed: 0, autoplay: true, interval: 6 } },
],
},
{
key: 'search',
title: '搜索组件',
icon: 'fas fa-search',
icon: 'fa fas fa-search',
fields: [
{ key: 'header_components_search_pc', label: 'PC 端显示搜索', type: 'switch', default: true, dependsOn: { key: 'header_components_search_enabled', value: true } },
{ key: 'header_components_search_mobile', label: '移动端显示搜索', type: 'switch', default: true, dependsOn: { key: 'header_components_search_enabled', value: true } },
{ key: 'header_components_search_show_keywords', label: '热门搜索', type: 'switch', default: true, dependsOn: { key: 'header_components_search_enabled', value: true }, help: '显示网站热门搜索关键词(移动端不会显示)' },
{ key: 'header_components_search_popular_limit', label: '关键词最多显示', type: 'number', default: 6, min: 2, max: 50, dependsOn: { key: 'header_components_search_show_keywords', value: true } },
{ key: 'header_components_search_show_input_cat', label: '分类搜索', type: 'switch', default: false, dependsOn: { key: 'header_components_search_enabled', value: true }, help: '显示分类搜索选择' },
{ key: 'header_components_search_in_cat', label: '默认搜索的分类', type: 'input', default: '', dependsOn: { key: 'header_components_search_show_input_cat', value: true }, help: '分类 ID,可留空' },
{ key: 'header_components_search_show_type', label: '显示类型选择', type: 'switch', default: false, dependsOn: { key: 'header_components_search_enabled', value: true }, help: '显示切换搜索类型的按钮(文章、用户)' },
{ key: 'header_components_search_in_type', label: '默认搜索类型', type: 'radio', default: 'post', dependsOn: { key: 'header_components_search_show_type', value: true }, options: [
{ label: '文章', value: 'post' },
{ label: '用户', value: 'user' },
]},
{
key: 'header_components_search_before_html',
label: '搜索上方额外内容',
type: 'textarea',
default: '<div class="em16 font-bold mb10">更优雅的Wordpress主题</div>\n<div>这是导航栏幻灯片多功能组件,可在后台进行配置</div>',
rows: 4,
dependsOn: { key: 'header_components_search_enabled', value: true },
help: 'Hero 主标题/副标题写在这里(支持 HTML)。不要依赖幻灯片文案,以免与搜索重叠;请注意组件总高度。',
},
{
key: 'header_components_search_after_html',
label: '搜索下方额外内容',
type: 'textarea',
default: '',
rows: 3,
dependsOn: { key: 'header_components_search_enabled', value: true },
help: '支持 HTML;请注意组件总高度。',
},
{ key: 'header_slider_search_s', label: '显示设备', type: 'checkbox', default: ['pc_s', 'm_s'], options: [{ label: 'PC 端显示', value: 'pc_s' }, { label: '移动端显示', value: 'm_s' }] },
{ key: 'header_slider_search_option', label: '搜索组件参数', type: 'json', sanitizeType: 'array', default: { show_keywords: true, popular_limit: 6, show_input_cat: false, in_cat: '', more_cats: [], show_type: false, in_type: 'post', before_html: '<div class="em16 font-bold mb10">更优雅的Wordpress主题</div>\n<div>这是导航栏幻灯片多功能组件,可在后台进行配置</div>', after_html: '' } },
],
},
{
key: 'cards',
title: '图标卡片样式',
icon: 'fas fa-th-large',
title: '图标卡片组件',
icon: 'fa fas fa-th-large',
fields: [
{ key: 'header_components_filter_blur_devices', label: '组件高斯模糊特效', type: 'checkbox', default: ['pc', 'mobile'], options: [
{ label: 'PC端开启', value: 'pc' },
{ label: '移动端开启', value: 'mobile' },
], help: '搜索组件和卡片组件背景显示高斯模糊特效(较耗性能)' },
{ key: 'header_components_card_show_devices', label: '卡片显示设备', type: 'checkbox', default: ['pc', 'mobile'], dependsOn: { key: 'header_components_cards_enabled', value: true }, options: [
{ label: 'PC端显示', value: 'pc' },
{ label: '移动端显示', value: 'mobile' },
]},
{ key: 'header_components_card_shared_bg', label: '模块背景', type: 'switch', default: false, dependsOn: { key: 'header_components_cards_enabled', value: true }, help: '整个模块显示背景;关闭后每个卡片各自显示背景(zibll show_widget_bg)' },
{ key: 'header_components_card_icon_shape', label: '方形图标', type: 'radio', default: 'circle', dependsOn: { key: 'header_components_cards_enabled', value: true }, options: [
{ label: '圆形', value: 'circle' },
{ label: '方形', value: 'square' },
], help: '图标显示为正方形,而不是圆形(zibll icon_radius4)' },
],
},
{
key: 'icon-cards',
title: '图标卡片列表',
icon: 'fas fa-list',
fields: [
{
key: 'header_components_icon_cards',
label: '图标卡片',
type: 'repeater',
ui: 'list-modal',
listPreview: {
iconKey: 'icon',
customIconKey: 'custom_icon',
iconClassKey: 'icon_class',
titleKey: 'title',
descKey: 'desc',
urlKey: 'url',
},
editText: '编辑卡片',
emptyText: '暂无图标卡片',
sanitize_type: 'array',
default: [],
dependsOn: { key: 'header_components_cards_enabled', value: true },
addText: '添加卡片',
fields: [
{ key: 'title', label: '文案标题', type: 'textarea', default: '', rows: 1, help: '第一行文案,字体稍大;支持 HTML(如 badge)' },
{ key: 'desc', label: '文案简介', type: 'textarea', default: '', rows: 2, help: '第二行文案,字体稍小;支持 HTML' },
{ key: 'icon', label: '选择图标', type: 'input', default: 'fa fa-magic', placeholder: 'fa fa-magic / fas fa-star' },
{ key: 'custom_icon', label: '自定义图标', type: 'textarea', default: '', rows: 1, placeholder: '自定义图标 HTML 代码', help: '如使用非自带图标,可输入自定义图标代码' },
{ key: 'icon_class', label: '图标颜色', type: 'select', default: 'c-yellow', options: [
{ label: 'Yellow', value: 'c-yellow' },
{ label: 'Blue', value: 'c-blue' },
{ label: 'Blue-2', value: 'c-blue-2' },
{ label: 'Green', value: 'c-green' },
{ label: 'Red', value: 'c-red' },
{ label: 'Red-2', value: 'c-red-2' },
{ label: 'Cyan', value: 'c-cyan' },
{ label: 'Pink', value: 'c-pink' },
{ label: 'Purple', value: 'c-purple' },
{ label: 'Gray', value: 'c-gray' },
{ label: 'Gradient Pink', value: 'jb-pink' },
{ label: 'Gradient Yellow', value: 'jb-yellow' },
{ label: 'Gradient Blue', value: 'jb-blue' },
{ label: 'Gradient Cyan', value: 'jb-cyan' },
{ label: 'Gradient Green', value: 'jb-green' },
{ label: 'Gradient Purple', value: 'jb-purple' },
{ label: 'Gradient Orange', value: 'jb-orange' },
]},
{ key: 'url', label: '跳转链接', type: 'input', default: '', placeholder: 'https://example.com' },
{ key: 'target', label: '打开方式', type: 'radio', default: '_self', options: [
{ label: '当前标签页', value: '_self' },
{ label: '新标签页', value: '_blank' },
]},
],
},
{ key: 'header_slider_card_s', label: '显示设备', type: 'checkbox', default: ['pc_s', 'm_s'], options: [{ label: 'PC 端显示', value: 'pc_s' }, { label: '移动端显示', value: 'm_s' }] },
{ key: 'header_slider_card_option', label: '图标卡片参数', type: 'json', sanitizeType: 'array', default: { show_widget_bg: false, icon_radius4: false, cards: [
{ icon: 'zibsvg-vip_1', customize_icon: '', icon_class: 'c-yellow', link: {}, title: '图标卡片', desc: '这是一个图标卡片示例' },
{ icon: 'zibsvg-vip_2', customize_icon: '', icon_class: 'c-blue-2', link: {}, title: '原创作品', desc: '这是一个图标卡片示例' },
{ icon: 'zibsvg-hot', customize_icon: '', icon_class: 'jb-pink', link: {}, title: '灵感来源<badge class="ml6 jb-yellow">NEW</badge>', desc: '这是一个图标卡片示例' },
{ icon: 'fa fas fa-ioxhost', customize_icon: '', icon_class: 'jb-cyan', link: {}, title: '系统工具 <badge class="ml6 jb-blue">GO <span class="fa fas fa-angle-right em12"></span></badge>', desc: '这是一个图标卡片示例' },
] } },
{ key: 'header_slider_filter_blur', label: '组件高斯模糊特效', type: 'checkbox', default: ['pc_s', 'm_s'], options: [{ label: 'PC 端开启', value: 'pc_s' }, { label: '移动端开启', value: 'm_s' }] },
],
},
],
@@ -817,7 +600,7 @@ export const pageDisplaySchemas = {
footer: {
key: 'page_display.footer',
title: '底部页脚',
icon: 'fas fa-shoe-prints',
icon: 'fa fas fa-paw',
description: '页脚布局、友链、版权信息配置。实际编辑界面在 FooterSettings.vue(customPage),此处为 REST 聚合描述。',
defaults: {
footer_columns: 3,
@@ -849,7 +632,7 @@ export const pageDisplaySchemas = {
{
key: 'layout',
title: '页脚布局',
icon: 'fas fa-columns',
icon: 'fa fas fa-columns',
fields: [
{ key: 'footer_columns', label: '页脚列数', type: 'number', default: 3, min: 1, max: 4 },
{ key: 'footer_copyright', label: '显示版权信息', type: 'switch', default: true },
@@ -860,7 +643,7 @@ export const pageDisplaySchemas = {
{
key: 'color',
title: '页脚颜色',
icon: 'fas fa-palette',
icon: 'fa fas fa-paint-brush',
fields: [
{ key: 'footer_theme_custom', label: '自定义页脚颜色', type: 'switch', default: false },
{ key: 'footer_theme_bg_custom', label: '自定义背景色', type: 'color', default: '' },
@@ -871,7 +654,7 @@ export const pageDisplaySchemas = {
{
key: 'contact',
title: '联系方式',
icon: 'fas fa-address-book',
icon: 'fa fas fa-address-book',
fields: [
{ key: 'footer_contact_wechat_img', label: '微信二维码', type: 'media', default: '' },
{ key: 'footer_contact_qq', label: 'QQ', type: 'input', default: '' },
@@ -882,7 +665,7 @@ export const pageDisplaySchemas = {
{
key: 'brand',
title: '品牌列(第一列)',
icon: 'fas fa-building',
icon: 'fa fas fa-building',
fields: [
{ key: 'footer_t1_m_s', label: '显示设备', type: 'checkbox', default: ['pc', 'mobile'] },
{ key: 'footer_t1_img', label: '页脚 Logo(日间)', type: 'media', default: '' },
@@ -894,7 +677,7 @@ export const pageDisplaySchemas = {
{
key: 'contact_ext',
title: '联系方式扩展',
icon: 'fas fa-phone-alt',
icon: 'fa fas fa-phone',
fields: [
{ key: 'footer_contact_m_s', label: '显示设备', type: 'checkbox', default: ['pc', 'mobile'] },
{ key: 'footer_contact_more', label: '更多联系项', type: 'textarea', default: '' },
@@ -905,7 +688,7 @@ export const pageDisplaySchemas = {
{
key: 'mini_qr',
title: '二维码图片组(第三列)',
icon: 'fas fa-qrcode',
icon: 'fa fas fa-qrcode',
fields: [
{ key: 'footer_mini_img_m_s', label: '显示设备', type: 'checkbox', default: ['pc', 'mobile'] },
{ key: 'footer_mini_img', label: '二维码组', type: 'textarea', default: '' },
@@ -914,7 +697,7 @@ export const pageDisplaySchemas = {
{
key: 'custom',
title: '底部自定义',
icon: 'fas fa-code',
icon: 'fa fas fa-code',
fields: [
{ key: 'fcode_customize_code', label: '底部自定义代码', type: 'textarea', default: '' },
],
@@ -928,7 +711,7 @@ export const pageDisplaySchemas = {
homepage: {
key: 'page_display.homepage',
title: '首页配置',
icon: 'fas fa-home',
icon: 'fa fas fa-home',
description: '配置首页主列表、分类 Tab 与首页交互。文章列表视觉统一由文章列表设置控制。',
defaults: {
homepage_tabs: [],
@@ -950,7 +733,7 @@ export const pageDisplaySchemas = {
{
key: 'main-stream',
title: '主列表',
icon: 'fas fa-list',
icon: 'fa fas fa-list',
fields: [
{ key: 'home_posts_list_s', label: '启用主列表', type: 'switch', default: true },
{ key: 'index_list_title', label: '区块标题', type: 'input', default: '最新发布', dependsOn: { key: 'home_posts_list_s', value: true } },
@@ -963,7 +746,7 @@ export const pageDisplaySchemas = {
{
key: 'exclude',
title: '排除规则',
icon: 'fas fa-filter',
icon: 'fa fas fa-filter',
fields: [
{ key: 'home_exclude_posts', label: '排除文章 ID', type: 'array', default: [], help: '主列表和 Tab 查询均排除这些文章。' },
{ key: 'home_exclude_cats', label: '排除分类 ID', type: 'array', default: [], help: '主列表排除这些分类。' },
@@ -972,7 +755,7 @@ export const pageDisplaySchemas = {
{
key: 'tabs',
title: '首页 Tab',
icon: 'fas fa-tags',
icon: 'fa fas fa-tags',
fields: [
{ key: 'home_lists', label: '首页 Tab', type: 'array', default: [], help: '分类 Tab 由 HomepageSettings.vue 中的可视化编辑器维护。' },
{ key: 'homepage_tab_limit', label: 'Tab 数量上限', type: 'number', default: 4, min: 1, max: 12 },
@@ -983,7 +766,7 @@ export const pageDisplaySchemas = {
{
key: 'cards-sidebar',
title: '侧栏与交互',
icon: 'fas fa-columns',
icon: 'fa fas fa-columns',
fields: [
{ key: 'homepage_sidebar_mini_enabled', label: '迷你侧栏列表', type: 'switch', default: true },
{ key: 'homepage_sort_ajax_enabled', label: '排序栏 AJAX', type: 'switch', default: true },
@@ -1,7 +1,7 @@
export const affiliateSchema = {
key: 'payment.affiliate',
title: '推广返佣',
icon: 'fas fa-share-alt',
icon: 'fa fas fa-share-alt',
description: '配置推广归因、分级佣金比例和结算规则。',
defaults: {
affiliate_enabled: false,
@@ -16,7 +16,7 @@ export const affiliateSchema = {
{
key: 'policy',
title: '返佣策略',
icon: 'fas fa-project-diagram',
icon: 'fa fas fa-sitemap',
fields: [
{ key: 'affiliate_enabled', label: '启用推广返佣', type: 'switch', default: false },
{ key: 'affiliate_ratio_user', label: '普通会员佣金比例(%)', type: 'number', default: 5, min: 0, max: 100, dependsOn: { key: 'affiliate_enabled', value: true } },
@@ -29,7 +29,7 @@ export const affiliateSchema = {
{
key: 'text',
title: '文案设置',
icon: 'fas fa-pen-fancy',
icon: 'fa fas fa-pen',
fields: [
{ key: 'affiliate_promotion_text', label: '推广说明', type: 'textarea', default: '', dependsOn: { key: 'affiliate_enabled', value: true } },
],
@@ -1,7 +1,7 @@
export const cardPassSchema = {
key: 'payment.card-pass',
title: '充值卡',
icon: 'fas fa-ticket-alt',
icon: 'fa fas fa-ticket-alt',
description: '配置充值卡类型、卡号规则、批量生成和兑换逻辑。',
defaults: {
card_pass_enabled: false,
@@ -23,7 +23,7 @@ export const cardPassSchema = {
{
key: 'basic',
title: '充值卡设置',
icon: 'fas fa-id-card',
icon: 'fa fas fa-id-card',
fields: [
{ key: 'card_pass_enabled', label: '启用充值卡', type: 'switch', default: false },
{ key: 'card_pass_desc', label: '充值卡说明', type: 'textarea', default: '', dependsOn: { key: 'card_pass_enabled', value: true } },
@@ -36,7 +36,7 @@ export const cardPassSchema = {
{
key: 'redeem',
title: '兑换设置',
icon: 'fas fa-exchange-alt',
icon: 'fa fas fa-exchange-alt',
fields: [
{ key: 'card_pass_max_redeem', label: '单卡最大兑换次数', type: 'number', default: 1, min: 1, max: 100, dependsOn: { key: 'card_pass_enabled', value: true } },
{ key: 'card_pass_expiry', label: '有效期(天)', type: 'number', default: 0, min: 0, help: '0为永久有效', dependsOn: { key: 'card_pass_enabled', value: true } },
@@ -48,7 +48,7 @@ export const cardPassSchema = {
{
key: 'display',
title: '展示设置',
icon: 'fas fa-desktop',
icon: 'fa fas fa-desktop',
fields: [
{ key: 'card_pass_redeem_page', label: '兑换页面', type: 'input', default: '', dependsOn: { key: 'card_pass_enabled', value: true } },
{ key: 'card_pass_success_msg', label: '兑换成功提示', type: 'input', default: '兑换成功!', dependsOn: { key: 'card_pass_enabled', value: true } },
@@ -1,7 +1,7 @@
export const gatewaySchema = {
key: 'payment.gateway',
title: '收款接口',
icon: 'fas fa-credit-card',
icon: 'fa fas fa-credit-card',
description: '管理已支持的收款通道:余额、支付宝、微信、PayPal、Stripe、易支付与卡密兑换。开启渠道后展开填写凭据。',
defaults: {
payment_wechat_enabled: false,
@@ -43,7 +43,7 @@ export const gatewaySchema = {
{
key: 'notice',
title: '说明',
icon: 'fas fa-info-circle',
icon: 'fa fas fa-info-circle',
fields: [
{
key: 'payment_gateway_notice',
@@ -57,7 +57,7 @@ export const gatewaySchema = {
{
key: 'gateways',
title: '支付渠道开关',
icon: 'fas fa-toggle-on',
icon: 'fa fas fa-toggle-on',
description: '先开启渠道,下方对应配置卡片会展开;填写凭据后网关状态变为可用。余额与卡密无第三方凭据,仅开关即可。',
fields: [
{ key: 'payment_balance_enabled', label: '余额支付', type: 'switch', default: true, help: '需同时在「余额充值」启用余额功能。关闭后用户中心仍可有钱包,但结账不可用余额支付。' },
@@ -72,7 +72,7 @@ export const gatewaySchema = {
{
key: 'wechat',
title: '微信支付配置',
icon: 'fab fa-weixin',
icon: 'fa fab fa-weixin',
description: '开启「微信支付」后填写商户号与密钥。',
collapsible: true,
expandWhen: 'payment_wechat_enabled',
@@ -92,7 +92,7 @@ export const gatewaySchema = {
{
key: 'alipay',
title: '支付宝配置',
icon: 'fab fa-alipay',
icon: 'fa fas fa-credit-card',
description: '开启「支付宝」后填写应用与证书。',
collapsible: true,
expandWhen: 'payment_alipay_enabled',
@@ -113,7 +113,7 @@ export const gatewaySchema = {
{
key: 'paypal',
title: 'PayPal 配置',
icon: 'fab fa-paypal',
icon: 'fa fab fa-paypal',
description: '开启「PayPal」后填写 Client 凭据。',
collapsible: true,
expandWhen: 'payment_paypal_enabled',
@@ -128,7 +128,7 @@ export const gatewaySchema = {
{
key: 'stripe',
title: 'Stripe 配置',
icon: 'fab fa-stripe',
icon: 'fa fab fa-cc-stripe',
description: '开启「Stripe」后填写 API Key 与 Webhook。',
collapsible: true,
expandWhen: 'payment_stripe_enabled',
@@ -144,7 +144,7 @@ export const gatewaySchema = {
{
key: 'epay',
title: '易支付配置',
icon: 'fas fa-university',
icon: 'fa fas fa-university',
description: '开启「易支付」后填写接口地址与商户信息,并选择支付宝/微信子通道。',
collapsible: true,
expandWhen: 'payment_epay_enabled',
@@ -1,7 +1,7 @@
export const orderSchema = {
key: 'payment.order',
title: '订单设置',
icon: 'fas fa-file-invoice',
icon: 'fa fas fa-file-alt',
description: '配置订单前缀、有效期、展示字段和状态文案。',
defaults: {
payment_order_prefix: 'AKSRT',
@@ -37,7 +37,7 @@ export const orderSchema = {
{
key: 'basic',
title: '订单基础',
icon: 'fas fa-cog',
icon: 'fa fas fa-cog',
fields: [
{ key: 'payment_order_prefix', label: '订单前缀', type: 'input', default: 'AKSRT' },
{ key: 'payment_order_expiry', label: '订单有效期(分钟)', type: 'number', default: 30, min: 5, max: 1440 },
@@ -53,7 +53,7 @@ export const orderSchema = {
{
key: 'display',
title: '展示设置',
icon: 'fas fa-eye',
icon: 'fa fas fa-eye',
fields: [
{ key: 'pay_mark', label: '付费标记', type: 'input', default: '付费' },
{ key: 'pay_box_position', label: '付费框位置', type: 'radio', default: 'top', options: [{ label: '文章框顶部(封面后)', value: 'box_top' }, { label: '正文顶部', value: 'top' }, { label: '正文底部', value: 'bottom' }, { label: '文章框底部(相关前)', value: 'box_bottom' }] },
@@ -67,7 +67,7 @@ export const orderSchema = {
{
key: 'status',
title: '状态设置',
icon: 'fas fa-tags',
icon: 'fa fas fa-tags',
fields: [
{ key: 'payment_order_status_pending', label: '待支付状态文案', type: 'input', default: '待支付' },
{ key: 'payment_order_status_paid', label: '已支付状态文案', type: 'input', default: '已支付' },
@@ -81,7 +81,7 @@ export const orderSchema = {
{
key: 'service',
title: '服务设置',
icon: 'fas fa-headset',
icon: 'fa fas fa-headphones',
fields: [
{ key: 'pay_service', label: '客服设置', type: 'textarea', default: '' },
{ key: 'pay_service_icon', label: '客服图标', type: 'icon', default: '' },
@@ -1,7 +1,7 @@
export const rechargeSchema = {
key: 'payment.recharge',
title: '余额充值',
icon: 'fas fa-charging-station',
icon: 'fa fas fa-bolt',
description: '配置余额充值套餐、转账与积分兑换。',
defaults: {
pay_balance_s: true,
@@ -30,7 +30,7 @@ export const rechargeSchema = {
{
key: 'basic',
title: '充值开关',
icon: 'fas fa-wallet',
icon: 'fa fas fa-credit-card',
fields: [
{ key: 'pay_balance_s', label: '启用余额功能', type: 'switch', default: true, help: '开启后用户中心显示现金钱包,并默认允许余额支付(可在收款接口单独关闭)。充值需另配支付宝/微信等外部网关。' },
{ key: 'pay_balance_desc', label: '充值说明', type: 'textarea', default: '', dependsOn: { key: 'pay_balance_s', value: true } },
@@ -40,7 +40,7 @@ export const rechargeSchema = {
{
key: 'packages',
title: '充值套餐',
icon: 'fas fa-box-open',
icon: 'fa fas fa-folder-open',
fields: [
{ key: 'pay_balance_product', label: '套餐列表', type: 'textarea', default: '30|30|入门包\n98|108|推荐包', help: '每行一个套餐:支付金额|到账金额|标题', dependsOn: { key: 'pay_balance_s', value: true } },
],
@@ -48,7 +48,7 @@ export const rechargeSchema = {
{
key: 'product',
title: '充值产品',
icon: 'fas fa-box',
icon: 'fa fas fa-archive',
fields: [
{ key: 'pay_balance_product_name', label: '充值产品', type: 'input', default: '', dependsOn: { key: 'pay_balance_s', value: true } },
{ key: 'pay_balance_price', label: '充值价格', type: 'number', default: 0, min: 0, max: 99999, dependsOn: { key: 'pay_balance_s', value: true } },
@@ -61,7 +61,7 @@ export const rechargeSchema = {
{
key: 'transfer',
title: '余额转账',
icon: 'fas fa-exchange-alt',
icon: 'fa fas fa-exchange-alt',
fields: [
{ key: 'pay_balance_transfer_s', label: '启用余额转账', type: 'switch', default: false },
{ key: 'pay_balance_transfer_service_charge', label: '转账手续费(%)', type: 'number', default: 0, min: 0, max: 50, dependsOn: { key: 'pay_balance_transfer_s', value: true } },
@@ -71,7 +71,7 @@ export const rechargeSchema = {
{
key: 'pass-charge',
title: '充值卡免扣',
icon: 'fas fa-ticket-alt',
icon: 'fa fas fa-ticket-alt',
fields: [
{ key: 'pay_balance_pass_charge_s', label: '启用余额卡密兑换', type: 'switch', default: false },
{ key: 'pay_balance_pass_charge_desc', label: '卡密兑换说明', type: 'textarea', default: '', dependsOn: { key: 'pay_balance_pass_charge_s', value: true } },
@@ -81,7 +81,7 @@ export const rechargeSchema = {
{
key: 'exchange',
title: '余额兑换积分',
icon: 'fas fa-coins',
icon: 'fa fas fa-database',
fields: [
{ key: 'pay_balance_points_exchange_s', label: '启用余额兑换积分', type: 'switch', default: false, dependsOn: { key: 'pay_balance_s', value: true } },
{ key: 'pay_balance_points_exchange_rate', label: '兑换比例', type: 'number', default: 100, min: 1, max: 10000, help: '1 余额 = N 积分', dependsOn: { key: 'pay_balance_points_exchange_s', value: true } },
@@ -1,7 +1,7 @@
export const revenueSchema = {
key: 'payment.revenue',
title: '创作中心',
icon: 'fas fa-chart-line',
icon: 'fa fas fa-chart-line',
description: '分别配置现金收益和积分收益的会员分成比例,结算周期结束后自动入账。',
defaults: {
pay_income_s: false,
@@ -18,7 +18,7 @@ export const revenueSchema = {
{
key: 'basic',
title: '创作中心设置',
icon: 'fas fa-cog',
icon: 'fa fas fa-cog',
fields: [
{ key: 'pay_income_s', label: '启用创作分成', type: 'switch', default: false },
{ key: 'payment_revenue_cycle_days', label: '结算周期(天)', type: 'number', default: 30, min: 1, max: 365, dependsOn: { key: 'pay_income_s', value: true } },
@@ -28,7 +28,7 @@ export const revenueSchema = {
{
key: 'cash',
title: '现金收益分成',
icon: 'fas fa-wallet',
icon: 'fa fas fa-credit-card',
fields: [
{ key: 'payment_revenue_cash_ratio_user', label: '普通用户分成比例(%)', type: 'number', default: 60, min: 0, max: 100, dependsOn: { key: 'pay_income_s', value: true } },
{ key: 'payment_revenue_cash_ratio_vip_1', label: '一级会员分成比例(%)', type: 'number', default: 70, min: 0, max: 100, dependsOn: { key: 'pay_income_s', value: true } },
@@ -38,7 +38,7 @@ export const revenueSchema = {
{
key: 'points',
title: '积分收益分成',
icon: 'fas fa-coins',
icon: 'fa fas fa-database',
fields: [
{ key: 'payment_revenue_points_ratio_user', label: '普通用户分成比例(%)', type: 'number', default: 0, min: 0, max: 100, dependsOn: { key: 'pay_income_s', value: true } },
{ key: 'payment_revenue_points_ratio_vip_1', label: '一级会员分成比例(%)', type: 'number', default: 0, min: 0, max: 100, dependsOn: { key: 'pay_income_s', value: true } },
@@ -1,7 +1,7 @@
export const vipSchema = {
key: 'payment.vip',
title: 'VIP会员',
icon: 'fas fa-crown',
icon: 'fa fas fa-gem',
description: '对齐 Zibll 双级会员:分档套餐、权益、续费/升级与积分兑换。',
defaults: {
pay_user_vip_1_s: true,
@@ -42,7 +42,7 @@ export const vipSchema = {
{
key: 'basic',
title: '会员等级',
icon: 'fas fa-user-shield',
icon: 'fa fas fa-user',
fields: [
{ key: 'pay_user_vip_1_s', label: '启用一级会员', type: 'switch', default: true },
{ key: 'pay_user_vip_1_name', label: '一级会员名称', type: 'input', default: '一级会员', dependsOn: { key: 'pay_user_vip_1_s', value: true } },
@@ -61,7 +61,7 @@ export const vipSchema = {
{
key: 'packages',
title: '分档套餐',
icon: 'fas fa-gem',
icon: 'fa fas fa-gem',
fields: [
{ key: 'vip_1_product_s', label: '允许购买一级会员', type: 'switch', default: true, dependsOn: { key: 'pay_user_vip_1_s', value: true } },
{
@@ -86,7 +86,7 @@ export const vipSchema = {
{
key: 'points_exchange',
title: '积分兑换会员',
icon: 'fas fa-coins',
icon: 'fa fas fa-database',
fields: [
{ key: 'pay_vip_points_exchange_s', label: '启用积分兑换', type: 'switch', default: false },
{
@@ -103,7 +103,7 @@ export const vipSchema = {
{
key: 'benefit',
title: '下载权益',
icon: 'fas fa-gift',
icon: 'fa fas fa-gift',
fields: [
{ key: 'pay_download_limit', label: '普通用户下载限制', type: 'number', default: 0, min: 0, max: 9999, help: '0为不限制' },
{ key: 'pay_download_limit_vip_1', label: '一级会员下载限制', type: 'number', default: 0, min: 0, max: 9999, dependsOn: { key: 'pay_user_vip_1_s', value: true } },
@@ -116,7 +116,7 @@ export const vipSchema = {
{
key: 'renew',
title: '续费设置',
icon: 'fas fa-sync-alt',
icon: 'fa fas fa-sync-alt',
fields: [
{ key: 'vip_renew', label: '允许续费', type: 'switch', default: true },
{ key: 'vip_renew_desc', label: '续费说明', type: 'textarea', default: '', dependsOn: { key: 'vip_renew', value: true } },
@@ -128,7 +128,7 @@ export const vipSchema = {
{
key: 'upgrade',
title: '升级设置',
icon: 'fas fa-arrow-up',
icon: 'fa fas fa-arrow-up',
fields: [
{ key: 'vip_upgrade', label: '允许升级', type: 'switch', default: true },
{ key: 'vip_upgrade_desc', label: '升级说明', type: 'textarea', default: '', dependsOn: { key: 'vip_upgrade', value: true } },
@@ -1,7 +1,7 @@
export const withdrawalSchema = {
key: 'payment.withdrawal',
title: '提现策略',
icon: 'fas fa-hand-holding-usd',
icon: 'fa fas fa-money-bill',
description: '配置提现门槛、手续费比例与每日限制。',
defaults: {
affiliate_min_withdrawal: 50,
@@ -15,7 +15,7 @@ export const withdrawalSchema = {
{
key: 'basic',
title: '提现设置',
icon: 'fas fa-sliders-h',
icon: 'fa fas fa-sliders-h',
fields: [
{ key: 'affiliate_min_withdrawal', label: '最低提现金额', type: 'number', default: 50, min: 0, max: 99999 },
{ key: 'affiliate_withdrawal_fee', label: '提现手续费(%)', type: 'number', default: 5, min: 0, max: 100 },
@@ -10,7 +10,7 @@ export const permissionsSchemas = {
login: {
key: 'permissions.login',
title: '人机验证',
icon: 'fas fa-shield-alt',
icon: 'fa fas fa-shield-alt',
description: '配置云验证码服务商,并选择需要强制人机验证的前端场景。',
defaults: {
enabled: false,
@@ -29,7 +29,7 @@ export const permissionsSchemas = {
{
key: 'basic',
title: '基础设置',
icon: 'fas fa-cog',
icon: 'fa fas fa-cog',
fields: [
{ key: 'enabled', label: '启用人机验证', type: 'switch', help: '总开关:关闭后所有场景均不验证' },
{
@@ -82,7 +82,7 @@ export const permissionsSchemas = {
{
key: 'providers',
title: '服务商配置',
icon: 'fas fa-server',
icon: 'fa fas fa-server',
description: '按当前选择的服务商填写对应密钥。',
fields: [
{
@@ -109,7 +109,7 @@ export const permissionsSchemas = {
capabilities: {
key: 'permissions.capabilities',
title: '基本权限',
icon: 'fas fa-user-shield',
icon: 'fa fas fa-user',
description: '统一管理用户、投稿和评论的角色权限。',
defaults: {},
groups: [],
@@ -121,7 +121,7 @@ export const permissionsSchemas = {
moderation: {
key: 'permissions.moderation',
title: '评论审核',
icon: 'fas fa-gavel',
icon: 'fa fas fa-gavel',
description: '管理评论审核、反垃圾、限流与拦截配置。',
defaults: {
enabled: false,
@@ -147,7 +147,7 @@ export const permissionsSchemas = {
{
key: 'basic',
title: '审核总开关',
icon: 'fas fa-power-off',
icon: 'fa fas fa-power-off',
fields: [
{ key: 'enabled', label: '启用审核系统', type: 'switch', help: '关闭后评论将不经过主题审核链路。' },
],
@@ -155,7 +155,7 @@ export const permissionsSchemas = {
{
key: 'akismet',
title: 'Akismet',
icon: 'fas fa-filter',
icon: 'fa fas fa-filter',
fields: [
{ key: 'akismet_enabled', label: '启用 Akismet', type: 'switch', dependsOn: { key: 'enabled', value: true } },
{ key: 'akismet_site_url', label: 'Site URL', type: 'input', placeholder: 'https://your-site.com', dependsOn: { key: 'akismet_enabled', value: true } },
@@ -166,7 +166,7 @@ export const permissionsSchemas = {
{
key: 'ai',
title: 'AI 审核',
icon: 'fas fa-robot',
icon: 'fa fab fa-android',
fields: [
{ key: 'ai_enabled', label: '启用 AI 审核', type: 'switch', dependsOn: { key: 'enabled', value: true } },
{ key: 'ai_api_hint', label: '审核 API 配置', type: 'notice', alertType: 'info', alertContent: 'API 接入(百度/阿里云等)在「扩展 → API内容审核」中统一配置,此处仅控制审核范围和策略。', dependsOn: { key: 'ai_enabled', value: true } },
@@ -181,7 +181,7 @@ export const permissionsSchemas = {
{
key: 'keywords',
title: '关键词拦截',
icon: 'fas fa-ban',
icon: 'fa fas fa-ban',
fields: [
{ key: 'blocked_keywords', label: '屏蔽关键词列表', type: 'textarea', rows: 4, placeholder: '每行一个关键词,也支持 /regex/i 格式。命中后会进入待审核并记录原因。', dependsOn: { key: 'enabled', value: true } },
],
@@ -189,7 +189,7 @@ export const permissionsSchemas = {
{
key: 'rate-limit',
title: '频率限制',
icon: 'fas fa-stopwatch',
icon: 'fa fas fa-clock',
fields: [
{ key: 'rate_limit_enabled', label: '启用频率限制', type: 'switch', dependsOn: { key: 'enabled', value: true } },
{ key: 'rate_limit_min_interval', label: '最小间隔(秒)', type: 'number', min: 1, max: 300, dependsOn: { key: 'rate_limit_enabled', value: true } },
@@ -199,7 +199,7 @@ export const permissionsSchemas = {
{
key: 'geoip',
title: 'GeoIP 拦截',
icon: 'fas fa-globe-asia',
icon: 'fa fas fa-globe',
fields: [
{ key: 'geoip_enabled', label: '启用 GeoIP 拦截', type: 'switch', dependsOn: { key: 'enabled', value: true } },
{ key: 'geoip_hint', label: 'IP 数据源', type: 'notice', alertType: 'info', alertContent: '复用「扩展 → IP归属地」中配置的数据源和 API Key。', dependsOn: { key: 'geoip_enabled', value: true } },
@@ -215,7 +215,7 @@ export const permissionsSchemas = {
attachment: {
key: 'permissions.attachment',
title: '附件权限',
icon: 'fas fa-paperclip',
icon: 'fa fas fa-paperclip',
description: '控制文件上传和附件下载权限。',
defaults: {
avatar_max_size: 2,
@@ -227,7 +227,7 @@ export const permissionsSchemas = {
{
key: 'profile',
title: '用户资料卡背景图',
icon: 'fas fa-user-circle',
icon: 'fa fas fa-user-circle',
fields: [
{ key: 'avatar_max_size', label: '头像/用户资料卡背景图大小上限 (MB)', type: 'number', min: 1, max: 10 },
],
@@ -235,7 +235,7 @@ export const permissionsSchemas = {
{
key: 'content',
title: '内容上传',
icon: 'fas fa-images',
icon: 'fa fas fa-image',
fields: [
{ key: 'submit_image_max_size', label: '投稿图片大小上限 (MB)', type: 'number', min: 1, max: 20 },
{ key: 'comment_image_max_size', label: '评论图片大小上限 (MB)', type: 'number', min: 1, max: 10 },
@@ -244,7 +244,7 @@ export const permissionsSchemas = {
{
key: 'resource',
title: '资源附件',
icon: 'fas fa-file-archive',
icon: 'fa fas fa-file-archive',
fields: [
{ key: 'resource_max_size', label: '资源附件大小上限 (MB)', type: 'number', min: 1, max: 200 },
],
@@ -1,7 +1,7 @@
export const commentSchema = {
key: 'post_list.comment',
title: '评论设置',
icon: 'fas fa-comment-dots',
icon: 'fa fas fa-comment-dots',
description: '配置评论区的排序、分页、权限、工具栏与互动方式。',
defaults: {
comment_order: 'asc',
@@ -33,7 +33,7 @@ export const commentSchema = {
{
key: 'display',
title: '评论展示',
icon: 'fas fa-comment',
icon: 'fa fas fa-comment',
fields: [
{ key: 'comment_order', label: '评论排序', type: 'radio', default: 'asc', options: [
{ label: '正序 (旧→新)', value: 'asc' },
@@ -54,7 +54,7 @@ export const commentSchema = {
{
key: 'permissions',
title: '评论设置',
icon: 'fas fa-lock',
icon: 'fa fas fa-lock',
fields: [
{ key: 'comment_close_comments', label: '关闭评论', type: 'switch', default: false },
{ key: 'comment_edit_window', label: '作者自助编辑时限 (分钟)', type: 'number', default: 10, min: 0, max: 1440 },
@@ -63,7 +63,7 @@ export const commentSchema = {
{
key: 'toolbar',
title: '评论工具栏',
icon: 'fas fa-toolbox',
icon: 'fa fas fa-wrench',
fields: [
{ key: 'comment_smilie', label: 'Emoji 表情', type: 'switch', default: true },
{ key: 'comment_code', label: '代码插入', type: 'switch', default: true },
@@ -74,7 +74,7 @@ export const commentSchema = {
{
key: 'interaction',
title: '互动功能',
icon: 'fas fa-heart',
icon: 'fa fas fa-heart',
fields: [
{ key: 'comment_hot_threshold', label: '神评点赞阈值', type: 'number', default: 10, min: 1, max: 999, help: '点赞数达到该值后显示「神评」徽章', dependsOn: { key: 'comment_like_s', value: true } },
{ key: 'comment_like_s', label: '评论点赞', type: 'switch', default: true },
@@ -93,7 +93,7 @@ export const commentSchema = {
{
key: 'text',
title: '文案配置',
icon: 'fas fa-font',
icon: 'fa fas fa-font',
fields: [
{ key: 'comment_empty_text', label: '空评论提示', type: 'input', default: '暂无评论,来做第一个评论的人吧~' },
{ key: 'comment_title', label: '评论区标题', type: 'input', default: '评论' },
@@ -1,7 +1,7 @@
export const featureSchema = {
key: 'post_list.feature',
title: '文章功能',
icon: 'fas fa-magic',
icon: 'fa fas fa-magic',
description: '配置文章页的互动功能开关。',
defaults: {
feature_pdf_export: false,
@@ -13,7 +13,7 @@ export const featureSchema = {
{
key: 'tools',
title: '工具功能',
icon: 'fas fa-tools',
icon: 'fa fas fa-wrench',
fields: [
{ key: 'feature_print', label: '打印文章', type: 'switch', default: true },
{ key: 'feature_word_count', label: '字数统计', type: 'switch', default: true },
@@ -1,7 +1,7 @@
export const filterSchema = {
key: 'post_list.filter',
title: '高级筛选',
icon: 'fas fa-filter',
icon: 'fa fas fa-filter',
description: '为文章列表配置筛选栏、排序方式和分类筛选功能。',
defaults: {
filter_enabled: false,
@@ -21,7 +21,7 @@ export const filterSchema = {
{
key: 'basic',
title: '筛选基础',
icon: 'fas fa-filter',
icon: 'fa fas fa-filter',
fields: [
{ key: 'filter_enabled', label: '启用筛选栏', type: 'switch', default: false },
{ key: 'custom_filter_show', label: '筛选显示页面', type: 'checkbox', default: ['cat', 'tag'], options: [{ label: '分类页', value: 'cat' }, { label: '标签页', value: 'tag' }], help: '选择在哪些页面显示筛选栏', dependsOn: { key: 'filter_enabled', value: true } },
@@ -34,7 +34,7 @@ export const filterSchema = {
{
key: 'ajax',
title: 'AJAX 筛选维度',
icon: 'fas fa-layer-group',
icon: 'fa fas fa-clone',
fields: [
{ key: 'filter_cat_show_cat', label: '分类页:显示分类筛选', type: 'switch', default: true },
{ key: 'filter_cat_show_tag', label: '分类页:显示标签筛选', type: 'switch', default: false },
@@ -45,7 +45,7 @@ export const filterSchema = {
{
key: 'custom_filter',
title: '自定义筛选维度',
icon: 'fas fa-sliders-h',
icon: 'fa fas fa-sliders-h',
fields: [
{
key: 'custom_filter',
@@ -75,7 +75,7 @@ export const filterSchema = {
{
key: 'cat_custom_filter',
title: '按分类绑定筛选',
icon: 'fas fa-object-group',
icon: 'fa fas fa-object-group',
fields: [
{
key: 'cat_custom_filter',
@@ -2,7 +2,7 @@
export const listSchema = {
key: 'post_list.list',
title: '文章列表',
icon: 'fas fa-list',
icon: 'fa fas fa-list',
description: '文章列表模式、UI、标签和翻页行为。',
defaults: {
list_orderby: 'modified',
@@ -26,12 +26,12 @@ export const listSchema = {
paging_ajax_s: '1',
paging_ajax_ias_s: true,
ias_max: 3,
ajax_trigger: '<i class="fa fa-angle-right"></i>加载更多',
ajax_trigger: '<i class="fa fas fa-angle-right"></i>加载更多',
ajax_nomore: '没有更多内容了',
},
groups: [
{
key: 'order', title: '默认排序与置顶', icon: 'fas fa-sort', fields: [
key: 'order', title: '默认排序与置顶', icon: 'fa fas fa-sort', fields: [
{ key: 'list_orderby', label: '默认排序方式', type: 'radio', default: 'modified', options: [
{ label: '发布时间', value: 'date' }, { label: '更新时间', value: 'modified' }, { label: 'WP默认', value: 'default' },
] },
@@ -44,7 +44,7 @@ export const listSchema = {
],
},
{
key: 'display', title: '列表显示', icon: 'fas fa-eye', fields: [
key: 'display', title: '列表显示', icon: 'fa 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 },
@@ -58,7 +58,7 @@ export const listSchema = {
],
},
{
key: 'layout', title: '列表模式与 UI', icon: 'fas fa-th-large', fields: [
key: 'layout', title: '列表模式与 UI', icon: 'fa fas fa-th-large', fields: [
{ key: 'list_show_type', label: '列表样式', type: 'radio', default: 'separate', options: [
{ label: '分离', value: 'separate' }, { label: '无间距', value: 'no_margin' },
] },
@@ -91,13 +91,13 @@ export const listSchema = {
],
},
{
key: 'paging', title: '列表翻页', icon: 'fas fa-ellipsis-h', fields: [
key: 'paging', title: '列表翻页', icon: 'fa 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_trigger', label: '翻页按钮文字', type: 'textarea', default: '<i class="fa fas fa-angle-right"></i>加载更多' },
{ key: 'ajax_nomore', label: '列表全部加载完毕文案', type: 'textarea', default: '没有更多内容了' },
],
},
@@ -1,7 +1,7 @@
export const pageSchema = {
key: 'post_list.page',
title: '文章页面',
icon: 'fas fa-file-alt',
icon: 'fa fas fa-file-alt',
description: '配置单篇文章页面的布局、目录树、图片灯箱、版权区和互动功能。',
defaults: {
post_toc_enabled: true,
@@ -58,7 +58,7 @@ export const pageSchema = {
{
key: 'navigation',
title: '文章导航',
icon: 'fas fa-compass',
icon: 'fa fas fa-compass',
fields: [
{ key: 'post_toc_enabled', label: '目录树导航', type: 'switch', default: true, help: '自动生成文章目录树' },
{ key: 'post_toc_depth', label: '目录深度', type: 'number', default: 3, min: 1, max: 6, dependsOn: { key: 'post_toc_enabled', value: true } },
@@ -86,7 +86,7 @@ export const pageSchema = {
{
key: 'cover',
title: '封面展示',
icon: 'fas fa-image',
icon: 'fa fas fa-image',
fields: [
{ key: 'post_article_image_cover', label: '图片封面', type: 'switch', default: true, help: '文章有特色图时自动展示封面' },
{ key: 'post_article_image_cover_scale', label: '封面高度比例(%)', type: 'number', default: 35, min: 10, max: 100, dependsOn: { key: 'post_article_image_cover', value: true } },
@@ -98,7 +98,7 @@ export const pageSchema = {
{
key: 'media',
title: '媒体功能',
icon: 'fas fa-photo-video',
icon: 'fa fas fa-image',
fields: [
{ key: 'post_lightbox', label: '图片灯箱', type: 'switch', default: true, help: '点击图片放大查看' },
{ key: 'post_lightbox_thumbs', label: '灯箱缩略图', type: 'switch', default: true, dependsOn: { key: 'post_lightbox', value: true }, help: '灯箱底部显示缩略图导航' },
@@ -111,7 +111,7 @@ export const pageSchema = {
{
key: 'related',
title: '相关推荐',
icon: 'fas fa-random',
icon: 'fa fas fa-random',
fields: [
{ key: 'post_related_s', label: '显示相关推荐', type: 'switch', default: true },
{ key: 'post_related_type', label: '展示样式', type: 'radio', default: 'img', options: [
@@ -135,7 +135,7 @@ export const pageSchema = {
{
key: 'interactions',
title: '互动功能',
icon: 'fas fa-heart',
icon: 'fa fas fa-heart',
fields: [
{ key: 'post_like_enabled', label: '点赞', type: 'switch', default: true },
{ key: 'post_favorite_enabled', label: '收藏', type: 'switch', default: true },
@@ -156,7 +156,7 @@ export const pageSchema = {
{
key: 'content',
title: '内容插入',
icon: 'fas fa-pen-square',
icon: 'fa fas fa-pen-square',
fields: [
{ key: 'post_front_content', label: '文章头部内容', type: 'textarea', default: '', help: '显示在所有文章正文前方(支持 HTML)' },
{ key: 'post_after_content', label: '文章底部内容', type: 'textarea', default: '', help: '显示在所有文章正文后方(支持 HTML)' },
@@ -165,7 +165,7 @@ export const pageSchema = {
{
key: 'yiyan',
title: '一言',
icon: 'fas fa-quote-left',
icon: 'fa fas fa-quote-left',
fields: [
{ key: 'post_yiyan_header', label: '文章头部一言', type: 'switch', default: false, help: '在文章标题下方显示一言' },
{ key: 'post_yiyan_footer', label: '文章底部一言', type: 'switch', default: false, help: '在文章内容底部显示一言' },
@@ -175,7 +175,7 @@ export const pageSchema = {
{
key: 'meta',
title: '默认数值',
icon: 'fas fa-chart-bar',
icon: 'fa fas fa-chart-bar',
fields: [
{ key: 'post_default_views_min', label: '默认浏览最小值', type: 'number', default: 20, min: 0, max: 9999 },
{ key: 'post_default_views_max', label: '默认浏览最大值', type: 'number', default: 50, min: 1, max: 9999 },
@@ -1,7 +1,7 @@
export const paySchema = {
key: 'post_list.pay',
title: '付费内容',
icon: 'fas fa-yen-sign',
icon: 'fa fas fa-yen-sign',
description: '配置文章付费阅读、下载功能和购买用户显示。',
defaults: {
post_pay_enable: false,
@@ -20,7 +20,7 @@ export const paySchema = {
{
key: 'basic',
title: '付费设置',
icon: 'fas fa-coins',
icon: 'fa fas fa-database',
fields: [
{ key: 'post_pay_enable', label: '启用付费内容', type: 'switch', default: false },
{ key: 'post_pay_price_default', label: '默认价格', type: 'number', default: 0, min: 0, max: 9999, dependsOn: { key: 'post_pay_enable', value: true } },
@@ -33,7 +33,7 @@ export const paySchema = {
{
key: 'download',
title: '下载设置',
icon: 'fas fa-download',
icon: 'fa fas fa-download',
fields: [
{ key: 'post_download_enable', label: '启用下载功能', type: 'switch', default: false },
{ key: 'post_download_remote_s', label: '远程文件下载', type: 'switch', default: false, dependsOn: { key: 'post_download_enable', value: true } },
@@ -1,7 +1,7 @@
export const shareSchema = {
key: 'post_list.share',
title: '分享设置',
icon: 'fas fa-share-alt',
icon: 'fa fas fa-share-alt',
description: '配置微信分享凭据、海报分享和社交分享选项。',
defaults: {
share_wechat_s: false,
@@ -18,7 +18,7 @@ export const shareSchema = {
{
key: 'wechat',
title: '微信分享',
icon: 'fab fa-weixin',
icon: 'fa fab fa-weixin',
fields: [
{ key: 'share_wechat_s', label: '启用微信分享', type: 'switch', default: false, help: '启用后文章页将支持微信 JSAPI 分享' },
{ key: 'share_wechat_appid', label: 'AppID', type: 'input', default: '', dependsOn: { key: 'share_wechat_s', value: true }, help: '微信公众号 AppID' },
@@ -29,7 +29,7 @@ export const shareSchema = {
{
key: 'poster',
title: '海报分享',
icon: 'fas fa-image',
icon: 'fa fas fa-image',
fields: [
{ key: 'share_img_compatible_s', label: '兼容模式', type: 'switch', default: false, help: '启用后使用兼容模式生成分享海报' },
{ key: 'share_img_byimg', label: '海报默认图', type: 'media', default: '', help: '海报分享使用的默认背景图' },
@@ -1,7 +1,7 @@
export const submitSchema = {
key: 'post_list.submit',
title: '前台投稿',
icon: 'fas fa-paper-plane',
icon: 'fa fas fa-paper-plane',
description: '配置前台投稿表单字段、审核流程、附件权限和封面策略。',
defaults: {
front_submit_enabled: true,
@@ -37,7 +37,7 @@ export const submitSchema = {
{
key: 'basic',
title: '基础配置',
icon: 'fas fa-cog',
icon: 'fa fas fa-cog',
fields: [
{ key: 'front_submit_enabled', label: '开启前台投稿', type: 'switch', default: true, help: '允许用户在前台提交文章' },
{ key: 'front_submit_roles', label: '允许投稿的角色', type: 'input', default: 'author,editor,administrator', dependsOn: { key: 'front_submit_enabled', value: true }, help: '逗号分隔角色标识' },
@@ -51,7 +51,7 @@ export const submitSchema = {
{
key: 'fields',
title: '表单字段',
icon: 'fas fa-list-alt',
icon: 'fa fas fa-list-alt',
fields: [
{ key: 'front_submit_title', label: '标题', type: 'switch', default: true, dependsOn: { key: 'front_submit_enabled', value: true } },
{ key: 'front_submit_content', label: '正文', type: 'switch', default: true, dependsOn: { key: 'front_submit_enabled', value: true } },
@@ -69,7 +69,7 @@ export const submitSchema = {
{
key: 'review',
title: '审核策略',
icon: 'fas fa-tasks',
icon: 'fa fas fa-tasks',
fields: [
{
key: 'front_submit_review_mode',
@@ -90,7 +90,7 @@ export const submitSchema = {
{
key: 'editor',
title: '编辑器设置',
icon: 'fas fa-edit',
icon: 'fa fas fa-edit',
fields: [
{
key: 'front_submit_editor_mode',
@@ -111,7 +111,7 @@ export const submitSchema = {
{
key: 'paid',
title: '付费投稿权限',
icon: 'fas fa-coins',
icon: 'fa fas fa-database',
fields: [
{ key: 'post_article_pay_free_s', label: '允许设置免费', type: 'switch', default: true, dependsOn: { key: 'front_submit_enabled', value: true } },
{ key: 'post_article_pay_price_min', label: '最低价格', type: 'number', default: 0, min: 0, max: 9999, help: '投稿可设置的最低付费金额', dependsOn: { key: 'front_submit_enabled', value: true } },
@@ -7,7 +7,7 @@ const spareThumbnailDefault = [{ img: `${themeRoot}/assets/img/thumbnail.svg` }]
export const thumbSchema = {
key: 'post_list.thumb',
title: '列表缩略图',
icon: 'fas fa-images',
icon: 'fa fas fa-image',
description: '缩略图获取优先级:文章特色图像 > 外链特色图像 > 文章首图 > 分类封面图 > 备用缩略图 > 懒加载预载图。',
defaults: {
list_thumb_slides_s: true,
@@ -23,7 +23,7 @@ export const thumbSchema = {
{
key: 'source',
title: '图片来源',
icon: 'fas fa-image',
icon: 'fa fas fa-image',
fields: [
{ key: 'list_thumb_slides_s', label: '幻灯片缩略图', type: 'switch', default: true, help: '允许设置幻灯片为列表缩略图' },
{ key: 'list_thumb_video_s', label: '视频缩略图', type: 'switch', default: true, help: '鼠标移动到列表上自动播放' },
@@ -1,14 +1,14 @@
export const backupSchema = {
key: 'tools.backup',
title: '数据备份',
icon: 'fas fa-cloud-download-alt',
icon: 'fa fas fa-cloud-download-alt',
description: '站点数据备份与恢复。',
defaults: {},
groups: [
{
key: 'backup',
title: '备份设置',
icon: 'fas fa-save',
icon: 'fa fas fa-save',
fields: [
{ key: 'backup_auto', label: '自动备份', type: 'switch', help: '启用自动定时备份' },
{
@@ -1,14 +1,14 @@
export const emailRollbackSchema = {
key: 'tools.email-rollback',
title: '邮件回滚',
icon: 'fas fa-undo',
icon: 'fa fas fa-undo',
description: '批量回滚已发送的通知邮件。',
defaults: {},
groups: [
{
key: 'rollback',
title: '邮件回滚',
icon: 'fas fa-envelope-open',
icon: 'fa fas fa-envelope-open',
fields: [
{
key: 'rollback_type',
@@ -1,7 +1,7 @@
export const frontendModalRolloutSchema = {
key: 'tools.frontend-modal-rollout',
title: '前台弹窗灰度',
icon: 'fas fa-bolt',
icon: 'fa fas fa-bolt',
description: '按领域控制前台弹窗新流程的分阶段发布。',
defaults: {
frontend_modal_rollout_identity: true,
@@ -13,7 +13,7 @@ export const frontendModalRolloutSchema = {
{
key: 'rollout',
title: '弹窗新流程开关',
icon: 'fas fa-toggle-on',
icon: 'fa fas fa-toggle-on',
fields: [
{
key: 'frontend_modal_rollout_identity',
@@ -1,14 +1,14 @@
export const healthSchema = {
key: 'tools.health',
title: '健康检查',
icon: 'fas fa-heartbeat',
icon: 'fa fas fa-heartbeat',
description: '检查主题运行环境和依赖状态。',
defaults: {},
groups: [
{
key: 'check',
title: '环境检查',
icon: 'fas fa-stethoscope',
icon: 'fa fas fa-stethoscope',
fields: [
{ key: 'php_version', label: 'PHP 版本', type: 'display', help: '建议 7.4+' },
{ key: 'wp_version', label: 'WordPress 版本', type: 'display', help: '建议 5.8+' },
@@ -1,14 +1,14 @@
export const importExportSchema = {
key: 'tools.import-export',
title: '导入导出',
icon: 'fas fa-exchange-alt',
icon: 'fa fas fa-exchange-alt',
description: '主题配置的导入和导出。',
defaults: {},
groups: [
{
key: 'export',
title: '导出配置',
icon: 'fas fa-file-export',
icon: 'fa fas fa-share',
fields: [
{ key: 'export_settings', label: '导出主题设置', type: 'button', help: '导出当前所有主题配置为 JSON 文件' },
{ key: 'export_options', label: '导出 WordPress 选项', type: 'button', help: '导出 aksrt_settings 等选项' },
@@ -17,7 +17,7 @@ export const importExportSchema = {
{
key: 'import',
title: '导入配置',
icon: 'fas fa-file-import',
icon: 'fa fas fa-download',
fields: [
{ key: 'import_settings', label: '导入主题设置', type: 'file', accept: '.json', help: '导入主题配置文件(将覆盖当前设置)' },
],
@@ -1,7 +1,7 @@
export const authSchema = {
key: 'users.auth',
title: '注册登录',
icon: 'fas fa-sign-in-alt',
icon: 'fa fas fa-sign-in-alt',
description: '注册方式、登录限制、密码策略配置。',
defaults: {
close_sign: false,
@@ -59,7 +59,7 @@ export const authSchema = {
{
key: 'register',
title: '注册设置',
icon: 'fas fa-user-plus',
icon: 'fa fas fa-user-plus',
fields: [
{ key: 'close_sign', label: '一键禁用登录注册', type: 'switch', default: false, help: '开启后前台禁用全部注册/登录入口(含社交登录),不影响后台登录' },
{ key: 'user_close_signup', label: '关闭注册', type: 'switch', default: false },
@@ -78,7 +78,7 @@ export const authSchema = {
{
key: 'login',
title: '登录设置',
icon: 'fas fa-sign-in-alt',
icon: 'fa fas fa-sign-in-alt',
fields: [
{ key: 'user_close_login', label: '关闭登录', type: 'switch', default: false },
{ key: 'user_sign_type', label: '登录注册样式', type: 'radio', default: 'page', options: [{ label: '弹窗', value: 'modal' }, { label: '跳转页面', value: 'page' }] },
@@ -96,7 +96,7 @@ export const authSchema = {
{
key: 'signup_captcha',
title: '注册验证',
icon: 'fas fa-user-shield',
icon: 'fa fas fa-user',
fields: [
{ key: 'user_signup_captch', label: '注册需验证', type: 'switch', default: true, help: '注册时需完成邮箱或手机验证' },
{ key: 'captch_type', label: '验证方式', type: 'radio', default: 'email', options: [{ label: '邮箱', value: 'email' }, { label: '手机', value: 'phone' }, { label: '邮箱或手机', value: 'email_phone' }], dependsOn: { key: 'user_signup_captch', value: true } },
@@ -107,7 +107,7 @@ export const authSchema = {
{
key: 'bind',
title: '绑定设置',
icon: 'fas fa-link',
icon: 'fa fas fa-link',
fields: [
{ key: 'bind_phone', label: '绑定手机', type: 'switch', default: false },
{ key: 'bind_reminder', label: '绑定提醒', type: 'radio', default: 'close', options: [{ label: '提醒绑定邮箱', value: 'email' }, { label: '提醒绑定手机', value: 'phone' }, { label: '提醒绑定邮箱和手机', value: 'email_phone' }, { label: '关闭', value: 'close' }] },
@@ -120,7 +120,7 @@ export const authSchema = {
{
key: 'referral_inline',
title: '推广码注册',
icon: 'fas fa-ticket-alt',
icon: 'fa fas fa-ticket-alt',
fields: [
{ key: 'referral_registration_enabled', label: '开放推广码注册', type: 'switch', default: true },
{ key: 'referral_register_field', label: '注册页推广码字段', type: 'select', default: 'optional', options: [{ label: '隐藏', value: 'hidden' }, { label: '选填', value: 'optional' }, { label: '必填', value: 'required' }], dependsOn: { key: 'referral_registration_enabled', value: true } },
@@ -134,7 +134,7 @@ export const authSchema = {
{
key: 'sign_page_ui',
title: '页面 UI 配置',
icon: 'fas fa-palette',
icon: 'fa fas fa-paint-brush',
fields: [
{ key: 'sign_page_background', label: '页面背景图', type: 'gallery', default: [], help: '登录注册页背景图,多图随机' },
{ key: 'sign_theme_mode', label: '主题模式', type: 'radio', default: 'default', options: [{ label: '默认', value: 'default' }, { label: '亮色', value: 'light' }, { label: '暗色', value: 'dark' }] },
@@ -147,7 +147,7 @@ export const authSchema = {
{
key: 'modal_ui',
title: '弹窗 UI 配置',
icon: 'fas fa-window-restore',
icon: 'fa fas fa-window-restore',
fields: [
{ key: 'sign_modal_background', label: '弹窗背景图', type: 'gallery', default: [], help: '弹窗左侧背景图,多图随机' },
{ key: 'sign_modal_show_logo', label: '弹窗显示 LOGO', type: 'switch', default: true },
@@ -156,7 +156,7 @@ export const authSchema = {
{
key: 'sign_logo',
title: '登录框 LOGO',
icon: 'fas fa-image',
icon: 'fa fas fa-image',
fields: [
{ key: 'user_logo', label: '日间 LOGO', type: 'gallery', default: [], help: '登录框专用日间 LOGO,留空使用站点全局 LOGO' },
{ key: 'user_logo_dark', label: '夜间 LOGO', type: 'gallery', default: [], help: '登录框专用夜间 LOGO,留空使用站点全局夜间 LOGO' },
@@ -89,7 +89,7 @@ export const defaultMedalArgs = () => [
export const badgeSchema = {
key: 'users.badge',
title: '用户徽章',
icon: 'fas fa-award',
icon: 'fa fas fa-trophy',
description: '配置勋章分类、自动授予条件与前台展示。路由仍为 /users/badge;存储键为 user_medal_*。',
defaults: {
user_medal_s: false,
@@ -101,7 +101,7 @@ export const badgeSchema = {
{
key: 'display',
title: '徽章展示',
icon: 'fas fa-medal',
icon: 'fa fas fa-trophy',
fields: [
{ key: 'user_medal_s', label: '启用徽章/勋章系统', type: 'switch', default: false },
{
@@ -125,7 +125,7 @@ export const badgeSchema = {
{
key: 'catalog',
title: '徽章明细',
icon: 'fas fa-trophy',
icon: 'fa fas fa-trophy',
fields: [
{
key: 'user_medal_args',
@@ -1,7 +1,7 @@
export const creditsSchema = {
key: 'users.credits',
title: '用户积分',
icon: 'fas fa-coins',
icon: 'fa fas fa-database',
description: '积分规则、积分日志、用户积分管理。',
defaults: {
points_s: true,
@@ -37,7 +37,7 @@ export const creditsSchema = {
{
key: 'basic',
title: '积分基础',
icon: 'fas fa-coins',
icon: 'fa fas fa-database',
fields: [
{ key: 'points_s', label: '启用积分系统', type: 'switch', default: true },
{ key: 'points_name', label: '积分名称', type: 'input', default: '积分' },
@@ -63,7 +63,7 @@ export const creditsSchema = {
{
key: 'spend',
title: '积分消费',
icon: 'fas fa-arrow-down',
icon: 'fa fas fa-arrow-down',
fields: [
{ key: 'points_spend_comment', label: '评论消耗', type: 'number', default: 0, min: 0, max: 100 },
{ key: 'points_spend_download', label: '下载消耗', type: 'number', default: 0, min: 0, max: 100 },
@@ -73,7 +73,7 @@ export const creditsSchema = {
{
key: 'transfer',
title: '积分转账',
icon: 'fas fa-exchange-alt',
icon: 'fa fas fa-exchange-alt',
fields: [
{ key: 'points_transfer_s', label: '启用积分转账', type: 'switch', default: false },
{ key: 'points_service_charge', label: '转账手续费(%)', type: 'number', default: 0, min: 0, max: 50, dependsOn: { key: 'points_transfer_s', value: true } },
@@ -83,7 +83,7 @@ export const creditsSchema = {
{
key: 'deduction',
title: '积分抵扣(预留)',
icon: 'fas fa-percent',
icon: 'fa fas fa-percent',
fields: [
{ key: 'points_deduction_s', label: '启用积分抵扣', type: 'switch', default: false, help: '对齐 zibll:运行时暂未启用(zibpay_is_allow_points_deduction 恒为 false)。字段保留供后续接收银台现金单抵扣。' },
{ key: 'points_deduction_rate', label: '积分换算比例', type: 'number', default: 100, min: 1, max: 10000, dependsOn: { key: 'points_deduction_s', value: true }, help: 'zibll 语义:points_deduction_rate = 多少积分抵 1 元(示例 30 表示 30 积分=1 元)。当前未参与下单计算。' },
@@ -93,7 +93,7 @@ export const creditsSchema = {
{
key: 'card_pass',
title: '积分卡密兑换',
icon: 'fas fa-ticket-alt',
icon: 'fa fas fa-ticket-alt',
fields: [
{ key: 'points_pass_exchange_s', label: '启用积分卡密兑换', type: 'switch', default: false, help: '对齐 zibll points_pass_exchange_s。后台充值卡可生成积分卡,用户中心兑换入账。' },
{ key: 'points_pass_exchange_desc', label: '兑换说明', type: 'textarea', default: '', dependsOn: { key: 'points_pass_exchange_s', value: true } },
@@ -103,7 +103,7 @@ export const creditsSchema = {
{
key: 'display',
title: '展示设置',
icon: 'fas fa-eye',
icon: 'fa fas fa-eye',
fields: [
{ key: 'points_show_balance', label: '导航栏显示余额', type: 'switch', default: true },
{ key: 'points_show_log', label: '显示积分记录', type: 'switch', default: true },
@@ -1,7 +1,7 @@
export const featuresSchema = {
key: 'users.features',
title: '用户功能',
icon: 'fas fa-user-cog',
icon: 'fa fas fa-user',
description: '配置用户中心和个人主页的功能模块。',
defaults: {
user_center_tabs: 'profile,level,posts,comments,favorites,vip,credits,revenue,auth',
@@ -20,7 +20,7 @@ export const featuresSchema = {
{
key: 'center',
title: '用户中心',
icon: 'fas fa-user-shield',
icon: 'fa fas fa-user',
fields: [
{ key: 'user_center_tabs', label: '用户中心 Tab', type: 'input', default: 'profile,level,comments,favorites,vip,credits,revenue,auth', help: '逗号分隔。level=我的等级;creator=创作中心;revenue=推广收益中心;auth=官方认证;等级、VIP、订单、创作中心、收益中心和认证会按功能开关自动注入' },
{ key: 'user_desc_std', label: '默认签名', type: 'input', default: '这家伙很懒…', help: '用户未设置个人简介时显示的默认文案' },
@@ -34,7 +34,7 @@ export function defaultIntegralOpt() {
export const levelSchema = {
key: 'users.level',
title: '用户等级',
icon: 'fas fa-level-up-alt',
icon: 'fa fas fa-level-up-alt',
description: '等级与经验值:最高等级、升级阈值、经验获取矩阵(对齐 Zibll user_level / user_integral)。',
defaults: {
user_level_s: true,
@@ -1,7 +1,7 @@
export const notificationsSchema = {
key: 'users.notifications',
title: '消息通知',
icon: 'fas fa-bell',
icon: 'fa fas fa-bell',
description: '站内通知、私信、通知策略配置。',
defaults: {
message_s: true,
@@ -27,7 +27,7 @@ export const notificationsSchema = {
{
key: 'basic',
title: '基础设置',
icon: 'fas fa-cog',
icon: 'fa fas fa-cog',
fields: [
{ key: 'message_s', label: '站内通知总开关', type: 'switch', default: true },
{ key: 'msg_center_rewrite_slug', label: '消息中心 URL 别名', type: 'input', default: 'message' },
@@ -39,7 +39,7 @@ export const notificationsSchema = {
{
key: 'types',
title: '通知类型',
icon: 'fas fa-list-check',
icon: 'fa fas fa-tasks',
fields: [
{ key: 'message_close_msg_type', label: '关闭部分推送', type: 'checkbox', default: [], options: [{ label: '文章通知', value: 'posts' }, { label: '评论回复', value: 'comment' }, { label: '收藏通知', value: 'favorite' }, { label: '点赞通知', value: 'like' }, { label: '热门通知', value: 'hot' }, { label: '关注通知', value: 'followed' }, { label: '系统通知', value: 'system' }, { label: '支付通知', value: 'pay' }, { label: '提现回复', value: 'withdraw_reply' }, { label: '勋章通知', value: 'medal' }, { label: '认证回复', value: 'auth_apply_reply' }], help: '勾选的类型将不向用户推送通知' },
],
@@ -47,7 +47,7 @@ export const notificationsSchema = {
{
key: 'auto_clear',
title: '自动清理',
icon: 'fas fa-broom',
icon: 'fa fas fa-magic',
fields: [
{ key: 'message_auto_clear_s', label: '自动清理已读消息', type: 'switch', default: true },
{ key: 'message_auto_clear_time', label: '过期天数', type: 'number', default: 365, min: 1, max: 3650, help: '已读消息超过此天数将被自动清理', dependsOn: { key: 'message_auto_clear_s', value: true } },
@@ -57,7 +57,7 @@ export const notificationsSchema = {
{
key: 'private',
title: '私信设置',
icon: 'fas fa-envelope',
icon: 'fa fas fa-envelope',
fields: [
{ key: 'private_s', label: '启用私信功能', type: 'switch', default: true },
{ key: 'private_smilie_s', label: '支持表情', type: 'switch', default: true, dependsOn: { key: 'private_s', value: true } },
+12 -12
View File
@@ -1,7 +1,7 @@
export const oauthSchema = {
key: 'users.oauth',
title: '第三方登录',
icon: 'fas fa-share-alt',
icon: 'fa fas fa-share-alt',
description: 'GitHub、Gitee、QQ、Google 等第三方登录配置。',
defaults: {
oauth_s: false,
@@ -68,7 +68,7 @@ export const oauthSchema = {
{
key: 'basic',
title: '基础设置',
icon: 'fas fa-cog',
icon: 'fa fas fa-cog',
fields: [
{ key: 'oauth_s', label: '启用第三方登录', type: 'switch', default: false },
{ key: 'oauth_proxy_mode', label: '代理登录模式', type: 'radio', default: 'close', options: [{ label: '关闭', value: 'close' }, { label: '服务端', value: 'server' }, { label: '客户端', value: 'client' }] },
@@ -87,7 +87,7 @@ export const oauthSchema = {
{
key: 'providers',
title: '登录提供商',
icon: 'fas fa-th',
icon: 'fa fas fa-th',
fields: [
{ key: 'oauth_github_s', label: 'GitHub登录', type: 'switch', default: false },
{ key: 'oauth_gitee_s', label: 'Gitee登录', type: 'switch', default: false },
@@ -103,7 +103,7 @@ export const oauthSchema = {
{
key: 'github',
title: 'GitHub配置',
icon: 'fab fa-github',
icon: 'fa fab fa-github',
fields: [
{ key: 'github_appid', label: 'Client ID', type: 'input', default: '' },
{ key: 'github_appkey', label: 'Client Secret', type: 'input', default: '' },
@@ -112,7 +112,7 @@ export const oauthSchema = {
{
key: 'gitee',
title: 'Gitee配置',
icon: 'fas fa-code-branch',
icon: 'fa fas fa-code-branch',
fields: [
{ key: 'gitee_appid', label: 'Client ID', type: 'input', default: '' },
{ key: 'gitee_appkey', label: 'Client Secret', type: 'input', default: '' },
@@ -121,7 +121,7 @@ export const oauthSchema = {
{
key: 'qq',
title: 'QQ配置',
icon: 'fab fa-qq',
icon: 'fa fab fa-qq',
fields: [
{ key: 'qq_appid', label: 'App ID', type: 'input', default: '' },
{ key: 'qq_appkey', label: 'App Key', type: 'input', default: '' },
@@ -130,7 +130,7 @@ export const oauthSchema = {
{
key: 'weixin',
title: '微信开放平台配置',
icon: 'fab fa-weixin',
icon: 'fa fab fa-weixin',
fields: [
{ key: 'weixin_appid', label: 'AppID', type: 'input', default: '' },
{ key: 'weixin_appsecret', label: 'AppSecret', type: 'input', default: '' },
@@ -139,7 +139,7 @@ export const oauthSchema = {
{
key: 'weixingzh',
title: '微信公众号配置',
icon: 'fab fa-weixin',
icon: 'fa fab fa-weixin',
fields: [
{ key: 'weixingzh_gzh_type', label: '公众号类型', type: 'radio', default: 'service', options: [{ label: '服务号', value: 'service' }, { label: '订阅号', value: 'subscribe' }] },
{ key: 'weixingzh_token', label: 'Token', type: 'input', default: '' },
@@ -165,7 +165,7 @@ export const oauthSchema = {
{
key: 'weibo',
title: '微博配置',
icon: 'fab fa-weibo',
icon: 'fa fab fa-weibo',
fields: [
{ key: 'weibo_appid', label: 'App Key', type: 'input', default: '' },
{ key: 'weibo_appkey', label: 'App Secret', type: 'input', default: '' },
@@ -174,7 +174,7 @@ export const oauthSchema = {
{
key: 'baidu',
title: '百度配置',
icon: 'fas fa-paw',
icon: 'fa fas fa-paw',
fields: [
{ key: 'baidu_appid', label: 'API Key', type: 'input', default: '' },
{ key: 'baidu_appkey', label: 'Secret Key', type: 'input', default: '' },
@@ -183,7 +183,7 @@ export const oauthSchema = {
{
key: 'clogin',
title: '彩虹聚合登录',
icon: 'fas fa-cloud',
icon: 'fa fas fa-cloud',
fields: [
{ key: 'clogin_url', label: '接口地址', type: 'input', default: '', help: '如 https://xxx.com 不要带 connect.php', dependsOn: { key: 'clogin_s', value: true } },
{ key: 'clogin_id', label: 'AppID', type: 'input', default: '', dependsOn: { key: 'clogin_s', value: true } },
@@ -200,7 +200,7 @@ export const oauthSchema = {
{
key: 'alipay',
title: '支付宝配置',
icon: 'fab fa-alipay',
icon: 'fa fas fa-credit-card',
fields: [
{ key: 'alipay_appid', label: 'AppID', type: 'input', default: '' },
{ key: 'alipay_privatekey', label: '应用私钥', type: 'textarea', rows: 3, default: '' },
@@ -1,7 +1,7 @@
export const reportSchema = {
key: 'users.report',
title: '禁封/举报',
icon: 'fas fa-flag',
icon: 'fa fas fa-flag',
description: '配置举报入口、公开限制提示和后续治理分类,为封禁/举报流程预留稳定结构。',
defaults: {
user_report_enabled: false,
@@ -19,7 +19,7 @@ export const reportSchema = {
{
key: 'entry',
title: '前台入口',
icon: 'fas fa-door-open',
icon: 'fa fas fa-sign-in-alt',
fields: [
{ key: 'user_report_enabled', label: '启用举报/禁封结构', type: 'switch', default: false },
{ key: 'user_report_public_entry', label: '公开主页展示举报入口', type: 'switch', default: true, dependsOn: { key: 'user_report_enabled', value: true } },
@@ -30,7 +30,7 @@ export const reportSchema = {
{
key: 'taxonomy',
title: '举报分类',
icon: 'fas fa-list',
icon: 'fa fas fa-list',
fields: [
{ key: 'user_report_categories', label: '举报分类', type: 'textarea', default: 'spam|垃圾信息\nabuse|人身攻击\ncopyright|版权投诉', help: '每行一个分类:slug|显示名称', dependsOn: { key: 'user_report_enabled', value: true } },
],
@@ -38,7 +38,7 @@ export const reportSchema = {
{
key: 'ban',
title: '禁封设置',
icon: 'fas fa-ban',
icon: 'fa fas fa-ban',
fields: [
{ key: 'ban_preset_reason', label: '预设封禁原因', type: 'textarea', default: 'spam|垃圾信息\nabuse|人身攻击\nviolation|违规操作', help: '每行一条:slug|显示名称', dependsOn: { key: 'user_report_enabled', value: true } },
{ key: 'ban_appeal_desc', label: '申诉说明', type: 'textarea', default: '', dependsOn: { key: 'user_report_enabled', value: true } },
@@ -48,7 +48,7 @@ export const reportSchema = {
{
key: 'image',
title: '图片举报',
icon: 'fas fa-image',
icon: 'fa fas fa-image',
fields: [
{ key: 'user_report_img_s', label: '启用图片举报', type: 'switch', default: true, dependsOn: { key: 'user_report_enabled', value: true } },
{ key: 'user_report_desc', label: '举报说明', type: 'textarea', default: '', dependsOn: { key: 'user_report_img_s', value: true } },
@@ -1,7 +1,7 @@
export const signinSchema = {
key: 'users.signin',
title: '签到奖励',
icon: 'fas fa-calendar-check',
icon: 'fa fas fa-calendar-check',
description: '配置签到规则、连续签到奖励和签到页面。',
defaults: {
signin_enabled: true,
@@ -14,7 +14,7 @@ export const signinSchema = {
{
key: 'rules',
title: '签到规则',
icon: 'fas fa-calendar-alt',
icon: 'fa fas fa-calendar',
fields: [
{ key: 'signin_enabled', label: '启用签到', type: 'switch', default: true },
{ key: 'signin_reward', label: '每日签到奖励', type: 'number', default: 1, min: 0, max: 100, dependsOn: { key: 'signin_enabled', value: true } },
@@ -1,7 +1,7 @@
export const smsSchema = {
key: 'users.sms',
title: '短信接口',
icon: 'fas fa-sms',
icon: 'fa fas fa-comment',
description: '配置短信验证码和短信通知服务的供应商、模板和限流策略。',
defaults: {
sms_enabled: false,
@@ -42,7 +42,7 @@ export const smsSchema = {
{
key: 'provider',
title: '供应商配置',
icon: 'fas fa-plug',
icon: 'fa fas fa-plug',
fields: [
{ key: 'sms_enabled', label: '启用短信服务', type: 'switch', default: false, help: '开启后支持短信验证码和短信通知' },
{
@@ -66,7 +66,7 @@ export const smsSchema = {
{
key: 'aliyun',
title: '阿里云配置',
icon: 'fas fa-cloud',
icon: 'fa fas fa-cloud',
fields: [
{ key: 'sms_ali_api_type', label: '接口类型', type: 'radio', default: 'sms', options: [{ label: '短信服务', value: 'sms' }, { label: '号码认证', value: 'verify' }], dependsOn: { key: 'sms_provider', value: 'aliyun' } },
{ key: 'sms_region_id', label: 'RegionId', type: 'input', default: 'cn-hangzhou', dependsOn: { key: 'sms_provider', value: 'aliyun' } },
@@ -75,7 +75,7 @@ export const smsSchema = {
{
key: 'tencent',
title: '腾讯云配置',
icon: 'fas fa-cloud',
icon: 'fa fas fa-cloud',
fields: [
{ key: 'sms_tencent_app_id', label: 'SdkAppId', type: 'input', default: '', dependsOn: { key: 'sms_provider', value: 'tencent' }, help: '腾讯云短信应用 ID' },
{ key: 'sms_tencent_app_key', label: 'AppKey', type: 'input', inputType: 'password', default: '', dependsOn: { key: 'sms_provider', value: 'tencent' } },
@@ -87,7 +87,7 @@ export const smsSchema = {
{
key: 'huawei',
title: '华为云配置',
icon: 'fas fa-cloud',
icon: 'fa fas fa-cloud',
fields: [
{ key: 'sms_huawei_sender', label: '通道号 (sender)', type: 'input', default: '', dependsOn: { key: 'sms_provider', value: 'huawei' } },
{ key: 'sms_huawei_signature', label: '短信签名', type: 'input', default: '', dependsOn: { key: 'sms_provider', value: 'huawei' }, help: '华为云短信签名内容' },
@@ -97,7 +97,7 @@ export const smsSchema = {
{
key: 'custom',
title: '自定义接口配置',
icon: 'fas fa-plug',
icon: 'fa fas fa-plug',
fields: [
{ key: 'sms_custom_url', label: '请求 URL', type: 'input', default: '', dependsOn: { key: 'sms_provider', value: 'custom' }, help: '支持 {phone} {code} {time} 变量' },
{ key: 'sms_custom_method', label: '请求方法', type: 'select', default: 'POST', options: [{ label: 'POST', value: 'POST' }, { label: 'GET', value: 'GET' }, { label: 'PUT', value: 'PUT' }], dependsOn: { key: 'sms_provider', value: 'custom' } },
@@ -112,7 +112,7 @@ export const smsSchema = {
{
key: 'template',
title: '短信模板',
icon: 'fas fa-sms',
icon: 'fa fas fa-comment',
fields: [
{ key: 'sms_sign_name', label: '短信签名', type: 'input', default: '', dependsOn: { key: 'sms_enabled', value: true }, help: '在短信服务商申请的短信签名(所有供应商共用此字段)' },
{ key: 'sms_template_code', label: '验证码模板 ID', type: 'input', default: '', dependsOn: { key: 'sms_enabled', value: true }, help: '所有供应商共用此模板 ID' },
@@ -123,7 +123,7 @@ export const smsSchema = {
{
key: 'rate_limit',
title: '限流策略',
icon: 'fas fa-shield-alt',
icon: 'fa fas fa-shield-alt',
fields: [
{ key: 'sms_rate_limit', label: '发送间隔 (秒)', type: 'number', default: 60, min: 10, max: 300, dependsOn: { key: 'sms_enabled', value: true }, help: '同一手机号两次发送的最小间隔' },
{ key: 'sms_daily_limit', label: '每日发送上限', type: 'number', default: 10, min: 1, max: 100, dependsOn: { key: 'sms_enabled', value: true }, help: '同一手机号每天最多发送条数' },
@@ -132,7 +132,7 @@ export const smsSchema = {
{
key: 'triggers',
title: '通知场景',
icon: 'fas fa-bell',
icon: 'fa fas fa-bell',
fields: [
{ key: 'sms_notify_bind', label: '绑定手机时验证', type: 'switch', default: true, dependsOn: { key: 'sms_enabled', value: true } },
{ key: 'sms_notify_login', label: '短信登录', type: 'switch', default: false, dependsOn: { key: 'sms_enabled', value: true } },
@@ -1,7 +1,7 @@
export const verifySchema = {
key: 'users.verify',
title: '身份认证',
icon: 'fas fa-id-card',
icon: 'fa fas fa-id-card',
description: '配置公开认证徽标、申请类型与申请门槛;审核、驳回和取消认证请前往 WordPress 用户 → 身份认证。',
defaults: {
user_verify_enabled: true,
@@ -24,7 +24,7 @@ export const verifySchema = {
{
key: 'display',
title: '公开展示',
icon: 'fas fa-eye',
icon: 'fa fas fa-eye',
fields: [
{ key: 'user_verify_enabled', label: '启用身份认证', type: 'switch', default: true },
{
@@ -45,13 +45,13 @@ export const verifySchema = {
],
},
{
key: 'workflow', title: '认证方式', icon: 'fas fa-tasks',
key: 'workflow', title: '认证方式', icon: 'fa fas fa-tasks',
fields: [{ type: 'alert', content: '认证方式固定为个人认证和企业认证,申请人不可自行新增或修改类型。' }],
},
{
key: 'apply',
title: '申请设置',
icon: 'fas fa-file-signature',
icon: 'fa fas fa-edit',
fields: [
{
key: 'user_verify_allow_apply',
@@ -1,7 +1,7 @@
export const wechatSchema = {
key: 'users.wechat',
title: '微信通知',
icon: 'fab fa-weixin',
icon: 'fa fab fa-weixin',
description: '配置微信模板消息、订阅/解绑和站外通知策略。',
defaults: {
wechat_notify_enabled: false,
@@ -19,7 +19,7 @@ export const wechatSchema = {
{
key: 'account',
title: '公众号配置',
icon: 'fab fa-weixin',
icon: 'fa fab fa-weixin',
fields: [
{ key: 'wechat_notify_enabled', label: '启用微信通知', type: 'switch', default: false, help: '开启后用户可绑定微信接收通知' },
{ key: 'wechat_app_id', label: 'AppID', type: 'input', default: '', dependsOn: { key: 'wechat_notify_enabled', value: true } },
@@ -30,7 +30,7 @@ export const wechatSchema = {
{
key: 'verify',
title: '服务器验证',
icon: 'fas fa-check-circle',
icon: 'fa fas fa-check-circle',
fields: [
{ key: 'wechat_token', label: 'Token', type: 'input', default: '', dependsOn: { key: 'wechat_notify_enabled', value: true }, help: '微信公众平台服务器配置中的 Token' },
{ key: 'wechat_encoding_aes_key', label: 'EncodingAESKey', type: 'input', default: '', dependsOn: { key: 'wechat_notify_enabled', value: true } },
@@ -39,7 +39,7 @@ export const wechatSchema = {
{
key: 'triggers',
title: '通知触发器',
icon: 'fas fa-bell',
icon: 'fa fas fa-bell',
fields: [
{ key: 'wechat_notify_comment', label: '新评论通知', type: 'switch', default: true, dependsOn: { key: 'wechat_notify_enabled', value: true } },
{ key: 'wechat_notify_reply', label: '评论回复通知', type: 'switch', default: true, dependsOn: { key: 'wechat_notify_enabled', value: true } },
+4 -21
View File
@@ -18,7 +18,6 @@
*/
export const MODULE_TYPES = [
'hero',
'banner',
'category',
'tabs',
@@ -42,18 +41,6 @@ export const MODULE_TYPES = [
]
export const MODULE_LIBRARY = [
{
type: 'hero',
label: 'Hero 首屏',
icon: 'image',
desc: '固定首页骨架:大图轮播首屏。幻灯片内容在「页面&显示 → Hero 轮播」维护;搜索/卡片参数见「顶部多功能组件」。',
defaultConfig: { with_search: true, show_cards: false, card_columns: 4, icon_cards: [] },
fields: [
{ key: 'with_search', type: 'switch', label: '显示搜索覆盖框' },
{ key: 'show_cards', type: 'switch', label: '显示图标卡片覆盖' },
{ key: 'card_columns', type: 'number', label: '卡片列数', min: 2, max: 6 },
],
},
{
type: 'banner',
label: 'Banner 轮播',
@@ -451,9 +438,8 @@ export const PRESET_TEMPLATES = [
{
key: 'resource_standard',
label: '资源站标准',
desc: 'Hero(固定骨架)+ Tabs + 最新文章 + 下载排行',
desc: 'Tabs + 最新文章 + 下载排行;头部幻灯由导航系统独立渲染',
modules: [
{ type: 'hero', config: {} },
{ type: 'tabs', config: { count: 8, layout: 'card' } },
{ type: 'recent', config: { count: 8, layout: 'card' } },
{ type: 'ranking', config: { metric: 'downloads', count: 6 } },
@@ -473,9 +459,8 @@ export const PRESET_TEMPLATES = [
{
key: 'mixed',
label: '混合站',
desc: 'Hero(固定骨架)+ 最新文章 + 多个分类块',
desc: '最新文章 + 多个分类块;头部幻灯由导航系统独立渲染',
modules: [
{ type: 'hero', config: {} },
{ type: 'recent', config: { count: 6, layout: 'card' } },
{ type: 'category', config: { count: 6, columns: 3, layout: 'card' } },
{ type: 'category', config: { count: 6, columns: 3, layout: 'card' } },
@@ -484,9 +469,8 @@ export const PRESET_TEMPLATES = [
{
key: 'landing',
label: '落地页',
desc: 'Hero + 标题 + 高亮卡片 + FAQ + 按钮组',
desc: '标题 + 高亮卡片 + FAQ + 按钮组',
modules: [
{ type: 'hero', config: {} },
{ type: 'text_title', config: { title: '为什么选择我们', align: 'center', style: 'default' } },
{ type: 'highlight_cards', config: { columns: 3 } },
{ type: 'spacing', config: { height: 40 } },
@@ -497,9 +481,8 @@ export const PRESET_TEMPLATES = [
{
key: 'corporate',
label: '企业站',
desc: 'Hero + 数据网格 + 产品展示 + 合作伙伴',
desc: '数据网格 + 产品展示 + 合作伙伴',
modules: [
{ type: 'hero', config: {} },
{ type: 'data_grid', config: { title: '核心数据', columns: 4, style: 'number' } },
{ type: 'product_showcase', config: { title: '产品展示', columns: 3 } },
{ type: 'partner_marquee', config: { title: '合作伙伴', speed: 30 } },
-3
View File
@@ -180,9 +180,6 @@
.but .icon,
.but > .fa:not(.fa-angle-right),
.but > .fas:not(.fa-angle-right),
.but > .far:not(.fa-angle-right),
.but > .fab:not(.fa-angle-right),
.but > i[class*="fa-"]:not(.fa-angle-right) { margin-right: 0.25em; }
/* hover / active */
-6
View File
@@ -468,12 +468,6 @@
}
}
/* Header CTA chips: never host layout-affecting ripple children */
.navbar-top a.navbar-cta,
.navbar-top a.newadd-btns,
.navbar-top a.payvip-icon.navbar-cta,
.navbar-top .navbar-but .but,
.navbar-top .navbar-vip a.but,
.nowave {
overflow: hidden;
}
@@ -19,7 +19,7 @@
margin-top: 0;
}
/* Fixed homepage hero under-nav is owned by nav/zib-navbar-fixed.css (body.nav-fixed .slide-header). */
/* Fixed homepage hero under-nav is owned by Zibll main.css. */
/* ============================================================
* Layer 1: Swiper shell — zibll .new-swiper.slide-header
-710
View File
@@ -1,710 +0,0 @@
@import url("nav/zib-navbar-fixed.css");
@import url("nav/zib-navbar-core.css");
@import url("nav/zib-mobile-navbar.css");
@import url("nav/zib-senior-submenu.css");
@import url("nav/zib-utilities.css");
@import url("nav/zib-search-box.css");
@import url("nav/zib-nav-style.css");
@import url("nav/header-menu-buttons.css");
@import url("nav/header-userbox.css");
@import url("nav/dark-mode-submenu.css");
/* ==========================================================================
* Top navbar icon/text alignment — 1:1 zibll (demo.zibll.com / main.css)
* Kept INLINE in the aggregator so browsers cannot miss it via stale @import.
* ========================================================================== */
/* --- Shell row --- */
.navbar-top {
margin: 0;
border-radius: 0 !important;
font-size: 15px;
/*
* Bootstrap 5 .navbar defaults --bs-navbar-padding-y: .5rem (8+8px).
* zibll uses BS3 (no that padding) + only .header { padding: 8px 20px }.
* Extra BS5 pad is why AKSRT bar is taller than zibll on PC and mobile.
*/
--bs-navbar-padding-y: 0;
--bs-navbar-padding-x: 0;
--bs-navbar-brand-padding-y: 0;
padding: 0 !important;
min-height: 0 !important;
flex-wrap: nowrap;
}
.header .navbar.navbar-top,
.header > .navbar {
--bs-navbar-padding-y: 0;
--bs-navbar-padding-x: 0;
padding-top: 0 !important;
padding-bottom: 0 !important;
min-height: 0 !important;
}
/* zibll .header — vertical rhythm only from this padding + logo row */
.header {
padding: 8px 20px;
}
.navbar-top .navbar-form,
.navbar-top .navbar-right,
.navbar-top .navbar-form.flex.ac {
display: flex !important;
align-items: center !important;
margin-top: 0;
margin-bottom: 0;
}
.navbar-top .list-inline {
display: flex;
align-items: center;
margin: 0;
padding: 0;
list-style: none;
}
.navbar-top .list-inline > li {
display: flex;
align-items: center;
margin: 0;
vertical-align: middle;
}
.navbar-top .list-inline.splitters > li + li {
margin-left: 6px;
}
/* --- Logo --- */
.navbar-top .navbar-brand {
display: flex;
align-items: center;
padding: 7px 10px;
line-height: 1;
}
.navbar-logo {
display: inline-flex;
align-items: center;
line-height: 0;
}
.navbar-logo > img {
display: block;
height: 36px;
padding: 0 30px;
width: auto;
max-height: 36px;
}
/* --- Primary menu text/icons --- */
.navbar-top .nav > li > a {
padding-left: 10px;
padding-right: 10px;
border-radius: 4px;
display: inline-flex !important;
align-items: center !important;
overflow: hidden;
line-height: 1.44;
}
.navbar-top .nav > li > a > .menu-item-title {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
line-height: 1.44;
display: inline-block;
vertical-align: middle;
}
.navbar-top .nav > li > a > .menu-item-icon,
.navbar-top .nav > li > a > i.menu-item-icon,
.navbar-top .nav > li > a > .fa.menu-item-icon,
.navbar-top .nav > li > a > .fas.menu-item-icon {
margin-right: 0.25em !important;
margin-left: 0 !important;
line-height: 1 !important;
position: static !important;
transform: none !important;
top: auto !important;
flex-shrink: 0;
vertical-align: 0 !important;
}
.navbar-top .nav > li > a > .fa-angle-down {
margin-left: 0.2em;
margin-right: 0 !important;
line-height: 1;
flex-shrink: 0;
}
.navbar-nav li a,
.navbar-nav li {
max-height: 50px;
position: relative;
}
/*
* CTA (发布 / 会员) — zibll main.css .navbar-top .navbar-but .but
* font-size 0.8em; padding 0.3em 1em; margin 0.4em; line-height 1.44
* Live markup: .navbar-form.navbar-but > a.but.navbar-cta (no cluster wrapper).
* Lock the SAME metrics on :active so ripple/focus cannot stretch the chip.
*/
.navbar-top .navbar-but .but,
.navbar-top .navbar-but a.but,
.navbar-top a.navbar-cta.but,
.navbar-top a.newadd-btns.navbar-cta,
.navbar-top a.navbar-newposts.navbar-cta,
.navbar-top a.payvip-icon.navbar-cta,
.navbar-top .navbar-vip a.navbar-cta,
.navbar-top .navbar-form.navbar-but .newadd-btns__toggle.navbar-cta,
.navbar-top .navbar-but .newadd-btns__toggle.navbar-cta {
font-size: 0.8em !important;
padding: 0.3em 1em !important;
margin: 0 0.4em !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
line-height: 1.44 !important;
vertical-align: middle;
box-sizing: border-box !important;
gap: 0.25em;
height: auto !important;
min-height: 0 !important;
max-height: 50px !important; /* zibll .navbar-nav li max-height */
width: fit-content !important;
max-width: fit-content !important;
min-width: 0 !important;
flex: 0 0 auto !important;
white-space: nowrap !important;
transform: none !important;
}
.navbar-top .navbar-but .but > i,
.navbar-top a.navbar-cta.but > i,
.navbar-top .navbar-but .but > .fa,
.navbar-top .navbar-but .but > .fas,
.navbar-top a.navbar-cta.but > .fa,
.navbar-top a.navbar-cta.but > .fas,
.navbar-top a.newadd-btns.navbar-cta > i,
.navbar-top a.navbar-newposts.navbar-cta > i,
.navbar-top a.payvip-icon.navbar-cta > i,
.navbar-top .navbar-form.navbar-but .newadd-btns__toggle > i,
.navbar-top .navbar-but .newadd-btns__toggle > i {
margin: 0 0.25em 0 0 !important;
line-height: 1 !important;
position: static !important;
transform: none !important;
top: auto !important;
flex-shrink: 0;
vertical-align: 0 !important;
display: inline-block;
}
.navbar-top .navbar-but .but > i:last-child,
.navbar-top a.navbar-cta.but > i:only-child,
.navbar-top a.newadd-btns.navbar-cta > i:only-child {
margin-right: 0 !important;
}
.navbar-top .navbar-but .but > .navbar-cta-text,
.navbar-top a.navbar-cta.but > .navbar-cta-text,
.navbar-top a.newadd-btns.navbar-cta > .navbar-cta-text,
.navbar-top a.navbar-newposts.navbar-cta > .navbar-cta-text,
.navbar-top a.payvip-icon.navbar-cta > .navbar-cta-text {
line-height: 1.44 !important;
display: inline-block;
vertical-align: middle;
white-space: nowrap;
margin: 0 !important;
}
/* --- Icon-only .btn chips (user / search) --- */
.navbar-top .list-inline > li > a.btn,
.navbar-top a.btn.signin-loader,
.navbar-top a.btn.nav-search-btn,
.navbar-top a.btn.main-search-btn {
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
width: 36px !important;
height: 36px !important;
min-width: 36px !important;
min-height: 36px !important;
max-height: 36px !important;
padding: 0 !important;
gap: 0 !important;
line-height: 1 !important;
border-radius: 4px;
box-sizing: border-box;
vertical-align: middle;
font-size: 16px;
}
.navbar-top .list-inline > li > a.btn > i,
.navbar-top a.btn.signin-loader > i,
.navbar-top a.btn.nav-search-btn > i,
.navbar-top a.btn.main-search-btn > i {
margin: 0 !important;
line-height: 1 !important;
position: static !important;
transform: none !important;
top: auto !important;
left: auto !important;
right: auto !important;
width: 1em;
height: 1em;
display: inline-flex !important;
align-items: center;
justify-content: center;
vertical-align: 0 !important;
}
/* Avatar trigger */
.navbar-top a.navbar-avatar {
display: inline-flex !important;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
padding: 0 !important;
line-height: 0;
}
.navbar-top a.navbar-avatar img,
.navbar-top a.navbar-avatar .avatar {
width: 32px !important;
height: 32px !important;
border-radius: 50%;
display: block;
margin: 0 !important;
}
/* --- Theme toggle (zibll toggle-radius 29px) --- */
.navbar-top a.toggle-theme.toggle-radius,
.navbar-top .toggle-theme.toggle-radius,
.navbar-but-cluster .toggle-theme {
position: relative !important;
width: 29px !important;
height: 29px !important;
min-width: 29px !important;
min-height: 29px !important;
display: inline-block !important;
overflow: hidden !important;
vertical-align: middle;
border-radius: 100% !important;
box-sizing: border-box;
padding: 0 !important;
flex: 0 0 auto;
line-height: 1;
}
.navbar-top a.toggle-theme.toggle-radius > i,
.navbar-top .toggle-theme.toggle-radius > i,
.navbar-top a.toggle-theme.toggle-radius .fa,
.navbar-top a.toggle-theme.toggle-radius .fas {
position: absolute !important;
top: 50% !important;
left: 0 !important;
right: 0 !important;
margin: auto !important;
transform: translateY(-50%) !important;
line-height: 1 !important;
width: 1em !important;
height: 1em !important;
align-items: center !important;
justify-content: center !important;
text-align: center;
vertical-align: 0 !important;
}
/*
* Theme glyph visibility is driven by html.dark / body.theme-dark.
* Light: moon (switch to dark). Dark: sun (switch to light).
* Never force both icons to display:inline-flex — that stacked them.
*/
.navbar-top .toggle-theme .theme-icon-moon,
.navbar-but-cluster .toggle-theme .theme-icon-moon,
.navbar-top .toggle-theme .theme-icon-sun,
.navbar-but-cluster .toggle-theme .theme-icon-sun {
display: none !important;
}
.navbar-top .toggle-theme .theme-icon-moon,
.navbar-but-cluster .toggle-theme .theme-icon-moon {
display: inline-flex !important;
}
html.dark .navbar-top .toggle-theme .theme-icon-moon,
html.dark .navbar-but-cluster .toggle-theme .theme-icon-moon,
body.theme-dark .navbar-top .toggle-theme .theme-icon-moon,
body.theme-dark .navbar-but-cluster .toggle-theme .theme-icon-moon,
body.dark-theme .navbar-top .toggle-theme .theme-icon-moon,
body.dark-theme .navbar-but-cluster .toggle-theme .theme-icon-moon {
display: none !important;
}
html.dark .navbar-top .toggle-theme .theme-icon-sun,
html.dark .navbar-but-cluster .toggle-theme .theme-icon-sun,
body.theme-dark .navbar-top .toggle-theme .theme-icon-sun,
body.theme-dark .navbar-but-cluster .toggle-theme .theme-icon-sun,
body.dark-theme .navbar-top .toggle-theme .theme-icon-sun,
body.dark-theme .navbar-but-cluster .toggle-theme .theme-icon-sun {
display: inline-flex !important;
}
/* --- Dropdown circular badges (header-user-href) keep 36px --- */
.navbar-top .header-user-href .toggle-radius,
.navbar-top .badg.toggle-radius {
position: relative !important;
width: 36px !important;
height: 36px !important;
display: inline-block !important;
text-align: center;
vertical-align: middle;
overflow: hidden;
border-radius: 100%;
box-sizing: border-box;
}
.navbar-top .header-user-href .toggle-radius > i,
.navbar-top .header-user-href .toggle-radius .fa,
.navbar-top .header-user-href .toggle-radius .fas,
.navbar-top .badg.toggle-radius > i,
.navbar-top .badg.toggle-radius .fa,
.navbar-top .badg.toggle-radius .fas {
position: absolute !important;
top: 50% !important;
left: 0 !important;
right: 0 !important;
margin: auto !important;
transform: translateY(-50%) !important;
line-height: 1 !important;
width: 1em;
height: 1em;
display: inline-flex !important;
align-items: center;
justify-content: center;
vertical-align: 0 !important;
}
/* --- FA general --- */
.navbar-top .fa,
.navbar-top .fas,
.navbar-top .far,
.navbar-top .fab {
line-height: 1;
transition: 0.2s;
}
.navbar-top .css-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
display: inline-block;
position: relative;
}
/* Fold / bars but in mid widths */
.navbar-top .show-nav-but .but {
display: inline-flex !important;
align-items: center;
justify-content: center;
line-height: 1;
padding: 0.3em 0.6em !important;
}
.navbar-top .show-nav-but .but > i {
margin: 0 !important;
line-height: 1 !important;
}
/* Final FA baseline: never vertical-align in the top bar (flex/abs centering only). */
.navbar-top .fa,
.navbar-top .fas,
.navbar-top .far,
.navbar-top .fab,
.navbar-top i[class*="fa-"] {
line-height: 1 !important;
vertical-align: 0 !important;
}
/*
* Header row height — 1:1 zibll (demo.zibll.com / main.css)
* Natural stack: .header padding 8px 20px + brand pad 7px + logo 36px
* → content row ~50px, bar ~66px. Senior submenu top: 59px. Fixed reserve 88px.
* Do NOT force min-height:50 on the flex row (over-tall vs zibll).
* CTA vertical margin uses 0 .4em (not .4em all sides) so flex cross-size
* stays logo-driven like a tight zibll bar.
*/
.navbar-top .container-header {
display: flex !important;
align-items: center !important;
min-height: 0 !important;
height: auto !important;
padding-top: 0 !important;
padding-bottom: 0 !important;
}
.navbar-top .navbar-form,
.navbar-top .navbar-right,
.navbar-top .navbar-header {
display: flex !important;
align-items: center !important;
min-height: 0 !important;
height: auto !important;
margin-top: 0 !important;
margin-bottom: 0 !important;
padding-top: 0 !important;
padding-bottom: 0 !important;
}
/* Brand: zibll padding 7px 10px only — kill BS5 brand pad/height */
.navbar-top .navbar-brand {
display: flex !important;
align-items: center !important;
padding: 7px 10px !important;
margin: 0 !important;
height: auto !important;
min-height: 0 !important;
line-height: 1 !important;
font-size: inherit !important;
}
/* Hover/active: same box as rest (prevent press stretch; ripple is absolute) */
.navbar-top a.navbar-cta.but:hover,
.navbar-top a.navbar-cta.but:focus,
.navbar-top a.navbar-cta.but:focus-visible,
.navbar-top a.navbar-cta.but:active,
.navbar-top .navbar-but .but:hover,
.navbar-top .navbar-but .but:focus,
.navbar-top .navbar-but .but:focus-visible,
.navbar-top .navbar-but .but:active,
.navbar-top a.newadd-btns.navbar-cta:hover,
.navbar-top a.newadd-btns.navbar-cta:focus,
.navbar-top a.newadd-btns.navbar-cta:focus-visible,
.navbar-top a.newadd-btns.navbar-cta:active,
.navbar-top a.payvip-icon.navbar-cta:hover,
.navbar-top a.payvip-icon.navbar-cta:focus,
.navbar-top a.payvip-icon.navbar-cta:focus-visible,
.navbar-top a.payvip-icon.navbar-cta:active {
font-size: 0.8em !important;
padding: 0.3em 1em !important;
margin: 0.4em !important;
line-height: 1.44 !important;
height: auto !important;
min-height: 0 !important;
max-height: 50px !important;
width: fit-content !important;
max-width: fit-content !important;
box-sizing: border-box !important;
transform: none !important;
}
/* .but.radius in buttons.css also uses 0.3em 1em — keep zibll metrics + pill radius */
.navbar-top a.but.radius.navbar-cta,
.navbar-top a.navbar-cta.radius,
.navbar-top a.newadd-btns.radius,
.navbar-top a.payvip-icon.radius {
padding: 0.3em 1em !important;
border-radius: var(--navbar-cta-radius, 50px) !important;
}
/* ==========================================================================
* P1 — No click deformation on top-nav controls
* ========================================================================== */
.navbar-top .but,
.navbar-top a.but,
.navbar-top a.btn,
.navbar-top button.but,
.navbar-top .navbar-cta,
.navbar-top .toggle-theme,
.navbar-top .toggle-radius,
.navbar-top a.navbar-avatar,
.navbar-top .navbar-toggle {
transform: none !important;
}
.navbar-top .but:hover,
.navbar-top .but:focus,
.navbar-top .but:active,
.navbar-top a.but:hover,
.navbar-top a.but:focus,
.navbar-top a.but:active,
.navbar-top a.btn:hover,
.navbar-top a.btn:focus,
.navbar-top a.btn:active,
.navbar-top .navbar-cta:hover,
.navbar-top .navbar-cta:focus,
.navbar-top .navbar-cta:active,
.navbar-top .toggle-theme:hover,
.navbar-top .toggle-theme:focus,
.navbar-top .toggle-theme:active,
.navbar-top a.navbar-avatar:hover,
.navbar-top a.navbar-avatar:focus,
.navbar-top a.navbar-avatar:active,
.navbar-top .navbar-toggle:hover,
.navbar-top .navbar-toggle:focus,
.navbar-top .navbar-toggle:active {
transform: none !important;
}
/* Keep CTA geometry stable on press — same zibll metrics, no stretch */
.navbar-top .navbar-but .but:hover,
.navbar-top .navbar-but .but:focus,
.navbar-top .navbar-but .but:active,
.navbar-top a.navbar-cta.but:hover,
.navbar-top a.navbar-cta.but:focus,
.navbar-top a.navbar-cta.but:active {
margin: 0 0.4em !important;
padding: 0.3em 1em !important;
line-height: 1.44 !important;
height: auto !important;
min-height: 0 !important;
max-height: 50px !important;
font-size: 0.8em !important;
box-sizing: border-box !important;
transform: none !important;
}
/* ==========================================================================
* P2 — User dropdown under avatar (not floating too high)
* ========================================================================== */
.navbar-top .list-inline > li,
.navbar-top .list-inline > li.relative {
position: relative;
}
.navbar-top .list-inline > li > .sub-menu,
.navbar-top .navbar-right .list-inline > li > .sub-menu,
.navbar-top .navbar-form .list-inline > li > .sub-menu {
top: calc(100% + 6px) !important;
right: 0 !important;
left: auto !important;
margin-top: 0 !important;
/* Override shared hover enter offset that reads as "too high" */
transform: translateY(0) !important;
}
.navbar-top .list-inline > li:not(:hover) > .sub-menu {
/* keep hidden state without vertical jump when revealed */
transform: translateY(4px) !important;
}
.navbar-top .list-inline > li:hover > .sub-menu {
transform: translateY(0) !important;
}
/* ==========================================================================
* P3 — Hamburger only on mobile; mobile header no logo overlap
* ========================================================================== */
/* Desktop / tablet landscape: never show mobile drawer toggle */
.navbar-top .navbar-toggle,
.navbar-top button.navbar-toggle {
display: none !important;
}
@media (max-width: 767px) {
.navbar-top .navbar-header {
display: flex !important;
align-items: center;
justify-content: space-between;
width: 100%;
position: relative;
min-height: 50px;
gap: 4px;
}
.navbar-top .navbar-brand {
position: static !important;
width: auto !important;
max-width: calc(100% - 96px);
flex: 1 1 auto;
min-width: 0;
padding: 4px 8px !important;
justify-content: center;
text-align: center;
}
.navbar-top.center .navbar-brand {
position: static !important;
width: auto !important;
}
.navbar-top .navbar-logo {
max-width: 100%;
}
.navbar-top .navbar-logo > img {
padding: 0 !important;
max-width: 100%;
height: 32px;
max-height: 32px;
}
/* Menu / search toggles: fixed slots on the sides, never over logo */
.navbar-top .navbar-toggle,
.navbar-top button.navbar-toggle {
display: inline-flex !important;
align-items: center;
justify-content: center;
width: 40px !important;
min-width: 40px !important;
height: 40px !important;
flex: 0 0 40px;
float: none !important;
position: relative;
z-index: 2;
margin: 0;
padding: 0;
}
/* Center layout: brand first in DOM — reorder to [menu][logo][search] */
.navbar-top.center .navbar-header {
display: grid !important;
grid-template-columns: 40px minmax(0, 1fr) 40px;
align-items: center;
column-gap: 6px;
}
.navbar-top.center .navbar-brand {
grid-column: 2;
grid-row: 1;
justify-self: center;
max-width: 100%;
}
.navbar-top.center .navbar-brand + .navbar-toggle {
grid-column: 1;
grid-row: 1;
justify-self: start;
}
.navbar-top.center .navbar-brand + .navbar-toggle + .navbar-toggle {
grid-column: 3;
grid-row: 1;
justify-self: end;
}
}
/* Mid-width fold (bars) only ≤991; never on true desktop */
@media (min-width: 992px) {
.navbar-top .show-nav-but {
display: none !important;
}
}
/* Absolute-size CTA chips: ignore injected .aksrt-wave for layout */
.navbar-top a.navbar-cta,
.navbar-top a.newadd-btns.navbar-cta,
.navbar-top a.navbar-newposts.navbar-cta,
.navbar-top a.payvip-icon.navbar-cta,
.navbar-top .navbar-but .but,
.navbar-top .navbar-form.navbar-but a.but,
.navbar-top .navbar-form.navbar-vip a.but {
position: relative !important;
overflow: hidden !important;
flex: 0 0 auto !important;
}
.navbar-top a.navbar-cta > .aksrt-wave,
.navbar-top a.but > .aksrt-wave,
.navbar-top .but > .aksrt-wave {
position: absolute !important;
pointer-events: none !important;
margin: 0 !important;
flex: none !important;
}
/* ---- zibll mobile header height (main.css @media max-width 640/767) ---- */
@media (max-width: 767px) {
.header {
padding: 0 8px !important;
}
.navbar-top,
.header .navbar.navbar-top {
--bs-navbar-padding-y: 0;
padding-top: 0 !important;
padding-bottom: 0 !important;
}
.navbar-top .navbar-brand {
padding: 7px 6px !important;
}
.navbar-top .navbar-logo > img {
height: 32px !important;
max-height: 32px !important;
padding-left: 8px !important;
padding-right: 8px !important;
}
/* touch row: match logo, not min 50 */
.navbar-top .navbar-header {
min-height: 0 !important;
}
.navbar-top .navbar-toggle,
.navbar-top button.navbar-toggle {
width: 36px !important;
min-width: 36px !important;
height: 36px !important;
flex-basis: 36px;
}
.navbar-top.center .navbar-header {
grid-template-columns: 36px minmax(0, 1fr) 36px;
}
}
@@ -1,109 +0,0 @@
/* Dark mode submenu */
html.dark ul.nav-desktop .sub-menu,
body.dark-theme ul.nav-desktop .sub-menu {
background: var(--surface-page);
border-color: var(--color-line, #2d2d3f);
}
/* ============================================================
* Mega Menu (图文超级菜单)
* ============================================================ */
/* Mega Menu 容器:全宽定位 */
ul.nav-desktop .mega-menu-item {
position: static;
}
ul.nav-desktop .mega-menu-item > .mega-menu__panel {
position: fixed; /* 对齐 zibll .senior-submenu: position:fixed 全视口宽 */
top: var(--nav-height, 60px);
left: 0;
right: 0;
transform: none;
max-width: var(--container);
margin: 0 auto; /* 内容区居中 */
padding: 20px 16px; /* 对齐 zibll 垂直 20px + 水平内边距 */
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.05); /* 对齐 zibll shadow */
}
/* 列布局 */
.mega-menu__columns-2 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 8px;
}
.mega-menu__columns-3 {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
}
.mega-menu__columns-4 {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
}
.mega-menu__columns-5 {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 8px;
}
/* Mega Menu 子项(卡片样式) */
.mega-menu__panel > .menu-item {
border-radius: 8px;
transition: background 0.15s;
}
.mega-menu__panel > .menu-item:hover {
background: var(--surface-2, #F4F5F7);
}
.mega-menu__panel > .menu-item > a {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
font-size: 14px;
border-radius: 8px;
white-space: normal;
line-height: 1.4;
}
.mega-menu__panel > .menu-item > a i {
width: 20px;
text-align: center;
color: var(--color-primary, var(--color-primary));
flex-shrink: 0;
}
/* 描述文字 */
.mega-menu__item-desc {
display: block;
font-size: 12px;
color: var(--color-ink-4, #8A8F98);
margin-top: 2px;
line-height: 1.3;
}
/* Mega Menu 标题分组 */
.mega-menu__panel .mega-menu__group-title {
grid-column: 1 / -1;
padding: 8px 12px 4px;
font-size: 12px;
font-weight: 600;
color: var(--color-ink-3);
text-transform: uppercase;
letter-spacing: 0.05em;
}
/* Mega Menu 底部区域(可放图片/CTA) */
.mega-menu__panel .mega-menu__footer {
grid-column: 1 / -1;
padding: 12px 0 0;
margin-top: 8px;
border-top: 1px solid var(--color-line);
}
@@ -1,837 +0,0 @@
/**
* Header multi-function publish cluster + VIP CTA + hover VIP cards.
*
* CTA metrics 1:1 zibll main.css:
* .navbar-top .navbar-but .but { font-size:.8em; padding:.3em 1em; margin:.4em; }
*
* @package AKSRT
*/
/* Shared CTA (cluster OR bare navbar-but / navbar-vip forms) */
.navbar-but-cluster a.navbar-cta,
.navbar-but-cluster a.btn-primary,
.navbar-but-cluster a.but.btn-primary,
.navbar-but-cluster a.navbar-newposts.but,
.navbar-but-cluster button.navbar-cta,
.navbar-but-cluster button.newadd-btns__toggle,
.navbar-but-cluster a.but:not(.newadd-btns__item),
.navbar-top .navbar-form.navbar-but a.but,
.navbar-top .navbar-form.navbar-but a.navbar-cta,
.navbar-top .navbar-form.navbar-vip a.navbar-cta,
.navbar-top .navbar-form.navbar-vip a.payvip-icon,
.navbar-top a.newadd-btns.navbar-cta,
.navbar-top a.navbar-newposts.but.navbar-cta,
.navbar-top a.payvip-icon.navbar-cta,
.navbar-top .navbar-form.navbar-but .newadd-btns__toggle.navbar-cta,
.navbar-top .navbar-but .newadd-btns__toggle.navbar-cta {
display: inline-flex !important;
align-items: center;
justify-content: center;
gap: 0.25em;
padding: 0.3em 1em !important;
height: auto !important;
min-height: 0 !important;
max-height: 50px !important;
border-radius: var(--navbar-cta-radius, 50px);
color: #fff !important;
text-decoration: none;
border: 0;
font-size: 0.8em !important;
line-height: 1.44 !important;
white-space: nowrap;
box-sizing: border-box !important;
vertical-align: middle;
flex: 0 0 auto !important;
width: fit-content !important;
max-width: fit-content !important;
min-width: 0 !important;
margin: 0 0.4em !important;
appearance: none;
-webkit-appearance: none;
cursor: pointer;
font-family: inherit;
transform: none !important;
}
/* Paint for publish when not already gradient-colored by jb-* */
.navbar-but-cluster a.navbar-cta,
.navbar-but-cluster a.btn-primary,
.navbar-but-cluster a.but.btn-primary,
.navbar-but-cluster a.navbar-newposts.but,
.navbar-but-cluster button.navbar-cta,
.navbar-but-cluster button.newadd-btns__toggle {
background: var(--color-primary, #2f6df6);
}
/* Multi-type toggle lives outside .navbar-but-cluster on live zibll DOM.
* Paint classes (jb-*) set --this-bg on the toggle; force them to show. */
.navbar-top .navbar-form.navbar-but .newadd-btns__toggle.navbar-cta,
.navbar-top .navbar-but .newadd-btns__toggle.navbar-cta,
.navbar-top .navbar-form.navbar-but a.navbar-newposts.navbar-cta,
.navbar-top .navbar-form.navbar-but a.newadd-btns.navbar-cta {
display: inline-flex !important;
visibility: visible !important;
opacity: 1 !important;
color: #fff !important;
background: var(--this-bg, linear-gradient(135deg, #59c3fb 10%, #268df7 100%)) !important;
border-radius: var(--navbar-cta-radius, 50px);
cursor: pointer;
}
.navbar-top .navbar-form.navbar-but .newadd-btns__toggle.navbar-cta > i,
.navbar-top .navbar-but .newadd-btns__toggle.navbar-cta > i,
.navbar-top .navbar-form.navbar-but .newadd-btns__toggle.navbar-cta .navbar-cta-text,
.navbar-top .navbar-but .newadd-btns__toggle.navbar-cta .navbar-cta-text {
color: inherit !important;
margin: 0 !important;
line-height: 1.44 !important;
}
.navbar-but-cluster {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: nowrap;
min-width: 0;
overflow: visible;
position: relative;
z-index: 30;
}
.navbar-but-cluster .navbar-but,
.navbar-but-cluster .navbar-vip {
display: inline-flex;
align-items: center;
min-width: 0;
flex: 0 0 auto;
width: auto;
max-width: none;
}
.navbar-but-cluster a.navbar-cta > i,
.navbar-but-cluster a.but > i,
.navbar-but-cluster a.btn-primary > i,
.navbar-but-cluster button.navbar-cta > i,
.navbar-but-cluster button.newadd-btns__toggle > i,
.navbar-but-cluster a.navbar-cta .navbar-cta-text,
.navbar-but-cluster a.navbar-cta > span:not(.badge),
.navbar-but-cluster button.navbar-cta .navbar-cta-text,
.navbar-but-cluster button.newadd-btns__toggle .navbar-cta-text,
.navbar-but-cluster button.newadd-btns__toggle > span {
display: inline-flex;
align-items: center;
justify-content: center;
margin: 0 !important;
flex: 0 0 auto;
line-height: 1.2;
white-space: nowrap;
color: inherit !important;
}
.navbar-but-cluster a.navbar-cta > i,
.navbar-but-cluster a.but > i,
.navbar-but-cluster a.btn-primary > i,
.navbar-but-cluster button.navbar-cta > i,
.navbar-but-cluster button.newadd-btns__toggle > i {
width: 1em;
height: 1em;
font-size: 1em;
line-height: 1;
}
/* Parent shell: shrink-wrap chip only */
.navbar-but-cluster .navbar-but,
.navbar-but-cluster .navbar-vip {
position: relative;
overflow: visible !important;
display: block !important;
width: fit-content !important;
max-width: fit-content !important;
min-width: 0 !important;
flex: 0 0 auto !important;
height: auto;
}
.navbar-but-cluster .payvip-icon.but,
.navbar-but-cluster a.payvip-icon {
background: linear-gradient(90deg, #ff6b6b, #f04494);
color: #fff;
padding: 0 12px !important;
height: auto !important;
border-radius: var(--navbar-cta-radius, 20px);
text-decoration: none;
font-size: 13px;
}
.navbar-but-cluster .ml10 {
margin-left: 0;
}
/*
* Publish multi-type dropdown
*
* The pink chip must NEVER share layout with the 168px menu.
* - wrapper = content-sized box (width: fit-content, no stretch)
* - toggle = only painted control
* - menu = absolute under wrapper, does not affect chip width
*/
.navbar-but-cluster .navbar-but {
/* outer shell around publish */
display: block !important;
width: fit-content !important;
max-width: fit-content !important;
min-width: 0 !important;
height: auto !important;
flex: 0 0 auto !important;
position: relative;
overflow: visible !important;
}
.navbar-but-cluster .navbar-but .newadd-btns.hover-show,
.navbar-but-cluster .newadd-btns.hover-show,
span.newadd-btns.hover-show,
div.newadd-btns.hover-show {
position: relative !important;
display: block !important;
width: fit-content !important;
max-width: fit-content !important;
min-width: 0 !important;
height: auto !important;
max-height: 50px !important;
padding: 0 !important;
margin: 0 !important;
border: 0 !important;
background: transparent !important;
box-shadow: none !important;
overflow: visible !important;
z-index: 40;
line-height: 0 !important;
float: none !important;
flex: 0 0 auto !important;
}
/* Pink chip only — content width, never 100% of anything */
.navbar-but-cluster .newadd-btns > .newadd-btns__toggle,
.navbar-but-cluster button.newadd-btns__toggle,
.navbar-but-cluster a.newadd-btns__toggle,
.navbar-but-cluster .newadd-btns__toggle.navbar-cta,
.navbar-top .navbar-form.navbar-but .newadd-btns > .newadd-btns__toggle,
.navbar-top .navbar-but .newadd-btns > .newadd-btns__toggle,
.navbar-top .newadd-btns__toggle.navbar-cta {
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
gap: 6px !important;
height: auto !important;
min-height: 0 !important;
max-height: 50px !important;
padding: 0.3em 1em !important;
margin: 0 !important;
width: fit-content !important;
max-width: fit-content !important;
min-width: 0 !important;
box-sizing: border-box !important;
white-space: nowrap !important;
position: relative;
z-index: 2;
flex: 0 0 auto !important;
}
/* Hard-lock open/focus: still content-sized, never stretch */
.navbar-but-cluster .newadd-btns > .newadd-btns__toggle:hover,
.navbar-but-cluster .newadd-btns > .newadd-btns__toggle:focus,
.navbar-but-cluster .newadd-btns > .newadd-btns__toggle:focus-visible,
.navbar-but-cluster .newadd-btns > .newadd-btns__toggle:active,
.navbar-but-cluster .newadd-btns.hover-show:hover > .newadd-btns__toggle,
.navbar-but-cluster .newadd-btns.hover-show:focus-within > .newadd-btns__toggle {
width: fit-content !important;
max-width: fit-content !important;
min-width: 0 !important;
padding: 0.3em 1em !important;
height: auto !important;
transform: none !important;
flex: 0 0 auto !important;
}
/* Menu floats under chip; fixed width; cannot expand chip */
.navbar-but-cluster .newadd-btns > .drop-newadd,
.navbar-but-cluster .newadd-btns .hover-show-con.drop-newadd,
.newadd-btns > .drop-newadd,
.newadd-btns .hover-show-con.drop-newadd {
display: block !important;
position: absolute !important;
top: calc(100% + 0px) !important;
/* Align menu to the RIGHT edge of the chip, not stretch chip */
right: 0 !important;
left: auto !important;
bottom: auto !important;
float: none !important;
width: 168px !important;
min-width: 168px !important;
max-width: 168px !important;
margin: 0 !important;
padding: 10px 0 6px !important;
background: transparent !important;
border: 0 !important;
box-shadow: none !important;
color: #222;
opacity: 0;
visibility: hidden;
transform: translateY(4px);
transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
z-index: 1200 !important;
pointer-events: none;
box-sizing: border-box !important;
}
.navbar-but-cluster .newadd-btns .drop-newadd::before,
.newadd-btns .drop-newadd::before,
.newadd-btns .hover-show-con.drop-newadd::before {
content: "" !important;
display: block !important;
position: absolute;
inset: 8px 0 0 0;
background: #ffffff !important;
border: 1px solid rgba(0, 0, 0, 0.08);
border-radius: 8px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
z-index: -1;
pointer-events: none;
}
.navbar-but-cluster .newadd-btns.hover-show:hover > .drop-newadd,
.navbar-but-cluster .newadd-btns.hover-show:focus-within > .drop-newadd,
.navbar-but-cluster .newadd-btns.hover-show:hover .hover-show-con.drop-newadd,
.navbar-but-cluster .newadd-btns.hover-show:focus-within .hover-show-con.drop-newadd,
.newadd-btns.hover-show:hover > .drop-newadd,
.newadd-btns.hover-show:focus-within > .drop-newadd {
opacity: 1;
visibility: visible;
transform: translateY(0);
pointer-events: auto;
}
.navbar-but-cluster .newadd-btns .newadd-btns__item,
.newadd-btns .drop-newadd .newadd-btns__item,
.newadd-btns__item {
display: flex !important;
align-items: center;
gap: 8px;
padding: 8px 14px !important;
margin: 0;
width: 100% !important;
height: auto !important;
min-height: 0;
border: 0 !important;
border-radius: 0;
background: transparent !important;
color: #222222 !important;
text-decoration: none !important;
white-space: nowrap;
position: relative;
z-index: 1;
box-sizing: border-box;
font-size: 13px !important;
font-weight: 500;
line-height: 1.35;
opacity: 1 !important;
}
.navbar-but-cluster .newadd-btns .newadd-btns__item > i,
.newadd-btns__item > i {
width: 1em;
margin: 0 !important;
text-align: center;
flex: 0 0 auto;
color: inherit !important;
opacity: 0.9;
}
.navbar-but-cluster .newadd-btns .newadd-btns__item > span,
.newadd-btns__item > span {
color: inherit !important;
line-height: 1.35;
}
.navbar-but-cluster .newadd-btns .newadd-btns__item:hover,
.newadd-btns .drop-newadd .newadd-btns__item:hover,
.newadd-btns__item:hover {
background: rgba(0, 0, 0, 0.05) !important;
color: var(--color-primary, #f04494) !important;
}
html.dark .newadd-btns .drop-newadd::before,
html.dark .newadd-btns .hover-show-con.drop-newadd::before,
body.dark-theme .newadd-btns .drop-newadd::before,
body.dark-theme .newadd-btns .hover-show-con.drop-newadd::before,
body.theme-dark .newadd-btns .drop-newadd::before,
body.theme-dark .newadd-btns .hover-show-con.drop-newadd::before {
background: #323335 !important;
border-color: rgba(255, 255, 255, 0.08);
}
html.dark .newadd-btns__item,
body.dark-theme .newadd-btns__item,
body.theme-dark .newadd-btns__item {
color: #f1f5f9 !important;
}
html.dark .newadd-btns__item:hover,
body.dark-theme .newadd-btns__item:hover,
body.theme-dark .newadd-btns__item:hover {
color: var(--color-primary, #f04494) !important;
background: rgba(255, 255, 255, 0.06) !important;
}
/* Portaled publish menu (moved to body by header-newadd.js) */
.newadd-btns.is-js-portal:hover > .drop-newadd,
.newadd-btns.is-js-portal:focus-within > .drop-newadd,
.newadd-btns.is-js-portal > .drop-newadd {
/* never paint/show menu while still inside chip wrapper */
opacity: 0 !important;
visibility: hidden !important;
pointer-events: none !important;
display: none !important;
}
body > .drop-newadd.hover-show-con,
body > .drop-newadd {
display: none;
position: fixed;
z-index: 2000;
width: 168px;
min-width: 168px;
max-width: 168px;
margin: 0;
padding: 6px 0;
background: #ffffff !important;
color: #222222 !important;
border: 1px solid rgba(0, 0, 0, 0.08);
border-radius: 8px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
box-sizing: border-box;
}
body > .drop-newadd.is-open {
display: block !important;
opacity: 1 !important;
visibility: visible !important;
pointer-events: auto !important;
transform: none !important;
}
body > .drop-newadd::before {
content: none !important;
display: none !important;
}
body > .drop-newadd .newadd-btns__item {
display: flex !important;
align-items: center;
gap: 8px;
padding: 8px 14px !important;
color: #222222 !important;
text-decoration: none !important;
font-size: 13px !important;
font-weight: 500;
background: transparent !important;
width: 100% !important;
height: auto !important;
box-sizing: border-box;
}
body > .drop-newadd .newadd-btns__item:hover {
background: rgba(0, 0, 0, 0.05) !important;
color: var(--color-primary, #f04494) !important;
}
html.dark body > .drop-newadd,
body.dark-theme body > .drop-newadd,
body.theme-dark body > .drop-newadd {
background: #323335 !important;
color: #f1f5f9 !important;
border-color: rgba(255, 255, 255, 0.08);
}
html.dark body > .drop-newadd .newadd-btns__item,
body.dark-theme body > .drop-newadd .newadd-btns__item,
body.theme-dark body > .drop-newadd .newadd-btns__item {
color: #f1f5f9 !important;
}
/* Generic hover-show (zibll parity) */
.hover-show {
position: relative;
cursor: pointer;
z-index: 20;
}
.hover-show .hover-show-con {
position: absolute;
top: 100%;
right: 0;
opacity: 0;
visibility: hidden;
transform: translateY(6px);
transition: opacity 0.25s ease, transform 0.25s ease, visibility 0.25s;
pointer-events: none;
z-index: 60;
/* invisible bridge so moving mouse into panel doesn't close it */
padding-top: 10px;
}
.hover-show:hover .hover-show-con,
.hover-show:focus-within .hover-show-con {
opacity: 1;
visibility: visible;
transform: translateY(0);
pointer-events: auto;
}
/* Header VIP hover cards — zibll .sub-vip-card
* Markup: .navbar-vip > span.navbar-vip-hover.hover-show > a + .sub-vip-card
* vip-modal.css also styles this; keep both in sync and win display:none.
*/
.navbar-but-cluster .navbar-vip,
.navbar-vip {
position: relative;
z-index: 35;
overflow: visible;
}
.navbar-vip-hover,
.navbar-vip .hover-show {
position: relative;
display: inline-block;
z-index: 35;
overflow: visible;
}
/* Kill vip-modal display:none when using the correct hover wrapper */
.navbar-vip-hover .sub-vip-card,
.navbar-vip .hover-show .sub-vip-card,
.sub-vip-card.hover-show-con,
.hover-show-con.sub-vip-card {
display: none; /* default hidden; shown on hover below */
position: absolute;
top: 100%;
right: 0;
left: auto;
z-index: 1200;
font-size: 12px;
padding: 12px 8px 8px !important; /* top bridge into cards */
background: transparent !important;
border: none !important;
box-shadow: none !important;
white-space: nowrap;
min-width: 0;
width: max-content;
max-width: min(520px, 92vw);
box-sizing: border-box;
/* reset opacity system from generic .hover-show-con when display is used */
opacity: 1;
visibility: visible;
transform: none;
pointer-events: auto;
}
.navbar-vip-hover:hover .sub-vip-card,
.navbar-vip-hover:focus-within .sub-vip-card,
.navbar-vip .hover-show:hover .sub-vip-card,
.navbar-vip .hover-show:focus-within .sub-vip-card,
.hover-show:hover > .sub-vip-card,
.hover-show:focus-within > .sub-vip-card {
display: flex !important;
flex-wrap: wrap;
align-items: stretch;
}
.sub-vip-card .vip-card {
display: inline-block;
vertical-align: top;
width: 240px;
margin: 5px;
padding: 15px;
border-radius: var(--main-radius, 8px);
overflow: hidden;
position: relative;
box-shadow: 0 0 10px var(--main-shadow, rgba(0, 0, 0, 0.12));
box-sizing: border-box;
white-space: normal;
transition: 0.3s;
}
.sub-vip-card .vip-card.vip-theme1,
.sub-vip-card .vip-card.level-1 {
background: linear-gradient(25deg, #e6aa4f 10%, #f1d7ad 70%, #f5b97b 100%);
color: #866127;
}
.sub-vip-card .vip-card.vip-theme2,
.sub-vip-card .vip-card.level-2 {
background: linear-gradient(132deg, #9b7de4 0%, #4f48b8 30%, #624fba 80%, #574dba);
color: #e4e2fb;
}
.sub-vip-card .vip-baicon.abs-center,
.sub-vip-card .vip-baicon {
position: absolute;
font-size: 10em;
left: 55%;
top: 50%;
transform: translate(-50%, -50%);
opacity: 0.12;
pointer-events: none;
line-height: 1;
}
.sub-vip-card .vip-img {
display: none;
}
.sub-vip-card .vip-name {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 16px;
position: relative;
z-index: 1;
}
.sub-vip-card .vip-name__icon {
display: flex;
flex: 0 0 auto;
align-items: center;
}
.sub-vip-card .vip-name__icon .aksrt-vip-level-icon {
display: block;
height: 1.1em;
width: auto;
}
.sub-vip-card .vip-name__label {
min-width: 0;
}
.sub-vip-card .v-equity,
.sub-vip-card ul.mb10 {
position: relative;
z-index: 1;
margin: 8px 0 12px;
padding: 0;
list-style: none;
text-align: left;
font-size: 12px;
line-height: 1.5;
opacity: 0.95;
}
.sub-vip-card .v-equity > li,
.sub-vip-card ul.mb10 > li {
display: block;
margin: 0 0 6px;
padding: 0;
list-style: none;
}
/* No forced decorative bullets — equity HTML is admin-authored */
.sub-vip-card .v-equity > li::before,
.sub-vip-card .v-equity > li::after,
.sub-vip-card ul.mb10 > li::before,
.sub-vip-card ul.mb10 > li::after {
content: none !important;
display: none !important;
}
/* Non-list equity HTML in hover cards */
.sub-vip-card .v-equity > p {
margin: 0 0 6px;
}
.sub-vip-card .v-equity > p:last-child {
margin-bottom: 0;
}
.sub-vip-card .payvip-button {
font-size: 1em !important;
margin: 0 !important;
display: inline-flex;
align-items: center;
gap: 4px;
background: linear-gradient(135deg, #ff9633 10%, #f14315 100%);
color: #fff;
padding: 4px 15px !important;
border-radius: 999px;
text-decoration: none;
box-shadow: 0 0 10px rgba(26, 22, 15, 0.3);
position: relative;
z-index: 2;
border: 0;
}
.sub-vip-card .payvip-button:hover {
filter: brightness(1.05);
color: #fff;
}
/* Theme toggle — zibll toggle-radius (29px) + absolute FA center, not flex+translate(-50%) */
.navbar-but-cluster .theme-toggle-desktop,
.navbar-but-cluster .toggle-theme,
.navbar-top .toggle-theme.toggle-radius {
display: inline-block;
align-items: unset;
justify-content: unset;
width: 29px;
height: 29px;
padding: 0;
border-radius: 100%;
flex: 0 0 auto;
position: relative;
overflow: hidden;
vertical-align: middle;
box-sizing: border-box;
}
.navbar-but-cluster .theme-toggle-desktop > i,
.navbar-but-cluster .toggle-theme > i,
.navbar-top .toggle-theme.toggle-radius > i {
margin: 0 !important;
line-height: 1 !important;
position: absolute;
left: 0 !important;
right: 0 !important;
top: 50%;
transform: translateY(-50%);
width: 1em;
height: 1em;
text-align: center;
align-items: center;
justify-content: center;
}
.theme-toggle-desktop,
.theme-toggle-mobile,
.toggle-theme {
position: relative;
overflow: hidden;
}
.theme-toggle-desktop .theme-icon-moon,
.theme-toggle-desktop .theme-icon-sun,
.theme-toggle-mobile .theme-icon-moon,
.theme-toggle-mobile .theme-icon-sun,
.toggle-theme .theme-icon-moon,
.toggle-theme .theme-icon-sun {
margin: 0 !important;
line-height: 1 !important;
width: 1em;
height: 1em;
text-align: center;
}
/* Light: moon only. Dark: sun only. (class-driven, not inline style) */
.theme-toggle-desktop .theme-icon-sun,
.theme-toggle-mobile .theme-icon-sun,
.toggle-theme .theme-icon-sun {
display: none !important;
}
.theme-toggle-desktop .theme-icon-moon,
.theme-toggle-mobile .theme-icon-moon,
.toggle-theme .theme-icon-moon {
display: inline-flex !important;
}
html.dark .theme-toggle-desktop .theme-icon-moon,
html.dark .theme-toggle-mobile .theme-icon-moon,
html.dark .toggle-theme .theme-icon-moon,
body.theme-dark .theme-toggle-desktop .theme-icon-moon,
body.theme-dark .theme-toggle-mobile .theme-icon-moon,
body.theme-dark .toggle-theme .theme-icon-moon,
body.dark-theme .theme-toggle-desktop .theme-icon-moon,
body.dark-theme .theme-toggle-mobile .theme-icon-moon,
body.dark-theme .toggle-theme .theme-icon-moon {
display: none !important;
}
html.dark .theme-toggle-desktop .theme-icon-sun,
html.dark .theme-toggle-mobile .theme-icon-sun,
html.dark .toggle-theme .theme-icon-sun,
body.theme-dark .theme-toggle-desktop .theme-icon-sun,
body.theme-dark .theme-toggle-mobile .theme-icon-sun,
body.theme-dark .toggle-theme .theme-icon-sun,
body.dark-theme .theme-toggle-desktop .theme-icon-sun,
body.dark-theme .theme-toggle-mobile .theme-icon-sun,
body.dark-theme .toggle-theme .theme-icon-sun {
display: inline-flex !important;
}
/* float commerce */
.float-btn-shop-cart {
position: relative;
}
.float-btn-shop-cart badge,
.float-btn-shop-cart [cart-count] {
position: absolute;
top: -4px;
right: -4px;
min-width: 16px;
height: 16px;
padding: 0 4px;
border-radius: 10px;
background: #e74c3c;
color: #fff;
font-size: 11px;
line-height: 16px;
text-align: center;
}
.float-btn-shop-cart badge:empty,
.float-btn-shop-cart [cart-count=""] {
display: none;
}
.float-btn.pay-vip,
.float-right .float-btn.pay-vip {
color: var(--this-color, #f5a623);
}
.float-right .float-btn.pay-vip:hover {
color: var(--this-color, #f5a623);
opacity: 0.9;
}
.float-right .float-btn > i {
margin: 0 !important;
line-height: 1;
font-size: 1.1em;
}
@media (max-width: 520px) {
.navbar-but-cluster {
gap: 6px;
}
.navbar-but-cluster .navbar-cta,
.navbar-but-cluster a.but {
padding: 6px 10px;
font-size: 12px;
}
.sub-vip-card .vip-card {
width: min(220px, 42vw);
}
}
/* Ensure publish form is never zero-sized */
.navbar-top .navbar-form.navbar-but {
display: flex !important;
align-items: center !important;
visibility: visible !important;
min-width: 0;
flex: 0 0 auto;
}
.navbar-top .navbar-form.navbar-but .newadd-btns.hover-show {
display: block !important;
visibility: visible !important;
width: fit-content !important;
max-width: fit-content !important;
line-height: normal !important;
}
-351
View File
@@ -1,351 +0,0 @@
/**
* Header user-box density (check-in / wallet / payvip / signout modal).
* Light-theme contrast fixes.
*
* @package AKSRT
*/
.aksrt-header-wallet {
display: flex;
gap: 10px;
justify-content: space-between;
padding: 8px 10px;
border-radius: 8px;
background: var(--surface-2, rgba(0, 0, 0, 0.04));
color: var(--color-ink, #222);
text-decoration: none;
font-size: 12px;
}
.aksrt-header-wallet__item {
color: var(--color-ink-2, #444);
}
.aksrt-header-wallet__item b {
margin-left: 2px;
color: var(--color-ink, #1a1a1a);
font-weight: 700;
}
.aksrt-header-wallet__item i {
margin-right: 2px;
color: var(--color-ink-3, #666);
}
/* Check-in: beat generic `.user-dropdown button { height:44px; background:none }` */
.user-dropdown button.aksrt-header-checkin,
.aksrt-header-checkin {
width: 100% !important;
max-width: 100%;
height: auto !important;
min-height: 36px;
border: 0 !important;
border-radius: 6px !important;
padding: 8px 10px !important;
margin: 0;
cursor: pointer;
background: #fff6db !important;
color: #8a5a00 !important;
font-weight: 600;
font-size: 13px !important;
line-height: 1.3;
display: inline-flex !important;
flex-direction: row !important;
align-items: center !important;
justify-content: center !important;
gap: 6px !important;
text-align: center !important;
box-sizing: border-box;
white-space: nowrap;
}
.user-dropdown button.aksrt-header-checkin > i,
.aksrt-header-checkin > i {
margin: 0 !important;
color: #b78103 !important;
flex: 0 0 auto;
line-height: 1;
}
.user-dropdown button.aksrt-header-checkin > span,
.aksrt-header-checkin > span {
line-height: 1.3;
color: inherit;
}
.user-dropdown button.aksrt-header-checkin.is-done,
.aksrt-header-checkin.is-done,
.user-dropdown button.aksrt-header-checkin:disabled,
.aksrt-header-checkin:disabled {
opacity: 0.85;
cursor: default;
background: #f3f4f6 !important;
color: #555 !important;
}
.user-dropdown button.aksrt-header-checkin.is-done > i,
.aksrt-header-checkin.is-done > i,
.user-dropdown button.aksrt-header-checkin:disabled > i,
.aksrt-header-checkin:disabled > i {
color: #777 !important;
}
.user-dropdown button.aksrt-header-checkin:hover,
.aksrt-header-checkin:hover {
background: #fff0c2 !important;
color: #8a5a00 !important;
}
.user-dropdown button.aksrt-header-checkin.is-done:hover,
.aksrt-header-checkin.is-done:hover,
.user-dropdown button.aksrt-header-checkin:disabled:hover,
.aksrt-header-checkin:disabled:hover {
background: #f3f4f6 !important;
color: #555 !important;
}
.aksrt-header-checkin-details {
color: var(--color-ink-3, #666) !important;
text-decoration: none;
}
/* VIP open CTA: same geometry as .aksrt-header-checkin (full width, 6px radius).
* Override any leftover .navbar-cta / .but.radius pill rules from top-nav. */
.user-dropdown .aksrt-header-payvip .payvip-icon,
.user-dropdown .aksrt-header-payvip .but,
.user-dropdown .aksrt-header-payvip__cta,
.aksrt-header-payvip .payvip-icon,
.aksrt-header-payvip .but,
.aksrt-header-payvip__cta {
display: inline-flex !important;
flex-direction: row !important;
align-items: center !important;
justify-content: center !important;
gap: 6px !important;
width: 100% !important;
max-width: 100% !important;
min-width: 0 !important;
height: auto !important;
min-height: 36px;
max-height: none !important;
box-sizing: border-box;
text-align: center;
text-decoration: none;
padding: 8px 10px !important;
margin: 0 !important;
border: 0 !important;
border-radius: 6px !important;
font-size: 13px !important;
font-weight: 600;
line-height: 1.3;
white-space: nowrap;
background: linear-gradient(90deg, #ff6b6b, #f04494) !important;
color: #fff !important;
flex: none !important;
transform: none !important;
}
.user-dropdown .aksrt-header-payvip .payvip-icon > i,
.user-dropdown .aksrt-header-payvip .but > i,
.user-dropdown .aksrt-header-payvip__cta > i,
.aksrt-header-payvip .payvip-icon > i,
.aksrt-header-payvip .but > i,
.aksrt-header-payvip__cta > i {
margin: 0 !important;
flex: 0 0 auto;
line-height: 1;
color: inherit !important;
}
.user-dropdown .aksrt-header-payvip__cta > span,
.aksrt-header-payvip__cta > span {
line-height: 1.3;
color: inherit;
}
.user-dropdown .aksrt-header-payvip__cta:hover,
.aksrt-header-payvip__cta:hover {
opacity: 0.92;
color: #fff !important;
}
/* Active VIP: level on line 1, smaller expiry on line 2 (no orange pill). */
.aksrt-header-payvip .payvip-icon.aksrt-header-payvip__active,
.aksrt-header-payvip__active {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2px;
line-height: 1.25;
}
.aksrt-header-payvip__level {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
font-weight: 600;
}
.aksrt-header-payvip__level > i {
margin: 0 !important;
}
.aksrt-header-payvip__exp {
display: block;
font-size: 0.85em;
font-weight: 400;
line-height: 1.3;
opacity: 0.9;
background: none !important;
border: 0;
padding: 0;
margin: 0;
color: inherit;
box-shadow: none;
}
.aksrt-header-badges {
flex-wrap: wrap;
gap: 4px;
}
/* Inline name + level badge in the dropdown profile row — one line, no wrap. */
.sub-user-box .user-right > .flex1 {
min-width: 0;
}
.sub-user-box .user-right b {
display: inline-flex;
align-items: center;
gap: 4px;
flex-wrap: nowrap;
white-space: nowrap;
max-width: 100%;
overflow: hidden;
}
.sub-user-box .user-right b .display-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
max-width: 100%;
}
.sub-user-box .user-right .aksrt-user-level-icon,
.sub-user-box .user-right .aksrt-identity-medal,
.sub-user-box .user-right .aksrt-header-user-medal,
.sub-user-box .user-right .aksrt-vip-badge {
height: 1.1em;
vertical-align: -.15em;
flex: 0 0 auto;
}
/* User dropdown light-theme text contrast */
.user-dropdown.sub-user-box,
.user-dropdown {
color: var(--color-ink, #222);
background: var(--main-bg-color, #fff);
}
.user-dropdown__name,
.user-dropdown__meta,
.user-dropdown__email,
.user-dropdown .muted-2-color {
color: var(--color-ink-2, #555) !important;
}
.user-dropdown__email {
opacity: 1;
}
.user-dropdown__action,
.user-dropdown__action span {
color: var(--color-ink, #222);
}
#modal_signout.modal {
position: fixed;
inset: 0;
z-index: 1100;
display: none;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.45);
padding: 16px;
}
#modal_signout.modal.is-open,
#modal_signout.modal.show {
display: flex;
}
#modal_signout .modal-content {
background: var(--main-bg-color, #fff);
border-radius: 10px;
min-width: 280px;
max-width: 92vw;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.18);
color: var(--color-ink, #222);
}
#modal_signout .but.c-red {
background: #e74c3c;
color: #fff;
text-decoration: none;
padding: 8px 14px;
border-radius: 6px;
}
#modal_signout .but {
border: 0;
background: var(--surface-2, #f0f0f0);
color: var(--color-ink, #222);
padding: 8px 14px;
border-radius: 6px;
cursor: pointer;
}
.user-dropdown .social_loginbar {
padding: 0 10px 12px;
}
/* Dark theme overrides */
html.dark .user-dropdown button.aksrt-header-checkin,
html.dark .aksrt-header-checkin,
body.dark-theme .user-dropdown button.aksrt-header-checkin,
body.dark-theme .aksrt-header-checkin,
body.theme-dark .user-dropdown button.aksrt-header-checkin,
body.theme-dark .aksrt-header-checkin {
background: rgba(255, 193, 7, 0.18) !important;
color: #f0c14b !important;
}
html.dark .user-dropdown button.aksrt-header-checkin > i,
html.dark .aksrt-header-checkin > i,
body.dark-theme .user-dropdown button.aksrt-header-checkin > i,
body.dark-theme .aksrt-header-checkin > i,
body.theme-dark .user-dropdown button.aksrt-header-checkin > i,
body.theme-dark .aksrt-header-checkin > i {
color: #f0c14b !important;
}
html.dark .user-dropdown button.aksrt-header-checkin.is-done,
html.dark .aksrt-header-checkin.is-done,
body.dark-theme .user-dropdown button.aksrt-header-checkin.is-done,
body.dark-theme .aksrt-header-checkin.is-done {
background: rgba(255, 255, 255, 0.08) !important;
color: #bbb !important;
}
html.dark .aksrt-header-wallet,
body.dark-theme .aksrt-header-wallet,
body.theme-dark .aksrt-header-wallet {
background: rgba(255, 255, 255, 0.06);
color: inherit;
}
html.dark .aksrt-header-wallet__item,
html.dark .aksrt-header-wallet__item b,
body.dark-theme .aksrt-header-wallet__item,
body.dark-theme .aksrt-header-wallet__item b {
color: inherit;
}
@@ -1,234 +0,0 @@
/* Ported/adapted from zibll main.css — mobile navbar drawer
*
* Desktop: fully off-document (display:none). Bootstrap 5 has no
* visible-xs-block; without this the drawer content sits in flow and
* creates a large blank band under the top nav (see blog.rutua.cn).
*/
/* ---- Base: hide drawer + overlay on all viewports by default ---- */
.mobile-header {
display: none;
}
.mobile-navbar {
display: none;
}
.fixed-body {
position: fixed;
inset: 0;
z-index: 996;
background: rgba(0, 0, 0, 0.45);
opacity: 0;
visibility: hidden;
pointer-events: none;
transition: opacity 0.35s ease, visibility 0.35s ease;
}
.mobile-navbar + .fixed-body {
z-index: 996;
}
@media (max-width: 767px) {
.navbar-toggle .icon-bar {
background: var(--main-color);
}
.navbar-toggle .icon-bar + .icon-bar {
margin-top: 5px;
}
/* Center layout is grid-driven in nav.css (menu | logo | search).
Do NOT absolute-position brand — it overlaps the hamburger. */
.navbar-top.center .navbar-brand {
position: static;
width: auto;
text-align: center;
}
.navbar-top.center .navbar-brand + .navbar-toggle {
float: none;
}
.navbar-top.center .navbar-brand > img {
display: unset;
}
.navbar-top .navbar-logo > img {
padding: 0;
}
/* Shell participates only on small screens */
.mobile-header {
display: block;
}
.mobile-navbar,
.mobile-navbar.visible-xs-block {
display: block;
z-index: 997;
position: fixed;
top: 0;
bottom: 0;
background: var(--main-bg-color);
width: 281px;
max-width: 86vw;
padding: 10px 20px 70px;
transition: transform 0.5s;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.mobile-navbar .navbar-logo {
margin-left: -10px;
}
.mobile-navbar badge:not(.top) {
transform: unset;
margin-left: 5px;
}
.mobile-navbar.right {
right: -2px;
transform: translateX(110%);
}
.mobile-navbar.left {
left: -2px;
transform: translateX(-110%);
}
.mobile-navbar.left > .toggle-radius {
float: right;
}
.mobile-navbar.top {
height: auto;
max-height: 70%;
width: 100%;
max-width: 100%;
left: 0;
right: 0;
transform: translateY(-110%);
}
.mobile-navbar-show .mobile-navbar {
transition: transform 0.6s cubic-bezier(0.28, 0.9, 0.34, 0.99);
transform: translate(0);
}
.mobile-navbar-show .mobile-navbar + .fixed-body {
visibility: visible;
opacity: 1;
pointer-events: auto;
}
.mobile-navbar-show .navbar-toggle .i-menu > i {
opacity: 0;
}
.mobile-navbar-show .navbar-toggle .i-menu::after {
transform: rotate(45deg);
width: calc(1em + 1px);
transform-origin: bottom right;
}
.mobile-navbar-show .navbar-toggle .i-menu::before {
right: 0;
width: calc(1em + 1px);
transform: rotate(-45deg);
transform-origin: top right;
}
.mobile-navbar .navbar-header {
margin-top: -58px;
margin-bottom: 10px;
}
.mobile-navbar .navbar-brand {
padding: 7px 10px;
}
.mobile-navbar .toggle-radius {
margin: 0 2px;
}
.mobile-menus li a {
display: block;
padding: 6px 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.mobile-menus > li > a::before {
margin: 0;
margin-right: 12px;
}
.mobile-menus .sub-menu {
word-wrap: break-word;
white-space: normal;
margin: 0 -2px;
}
.mobile-menus .sub-menu li {
width: calc(50% - 4px);
text-align: center;
display: inline-block;
}
.mobile-navbar.top .mobile-menus .sub-menu li {
width: calc(33.3% - 4px);
}
.mobile-menus .sub-menu li > a {
background: var(--main-border-color);
padding: 5px;
margin: 2px;
border-radius: 4px;
font-size: 0.9em;
position: relative;
}
.mobile-menus .sub-menu li > a > badge:not(.top) {
position: absolute;
right: 0;
top: 0;
transform: scale(0.85);
}
.mobile-user-menus a {
width: calc(50% - 12px);
float: left;
margin: 6px;
}
.mobile-nav-widget {
display: block;
width: 100%;
overflow: hidden;
white-space: normal;
}
.mobile-navbar .box-body.notop {
padding-left: 0;
padding-right: 0;
}
.mobile-navbar .sub-user-box {
margin-bottom: 30px;
}
.mobile-navbar .posts-nav-box .zib-widget {
background: var(--muted-border-color);
box-shadow: none;
}
.s-desc,
.slide-text,
.wp-block-carousel figcaption {
padding: 0.7em;
}
}

Some files were not shown because too many files have changed in this diff Show More