fix(vip): restore the upgrade-price accordion and space out structured groups
升级价格 declared three reference-theme blocks through the accordion sections option, but the section builder handed the computed the whole field object instead of its sections array, so the guard always saw an empty length and the renderer silently fell back to a flat list. The three blocks ran into each other with no separation at all. - Move the section expansion into a pure buildFieldsetSections() helper so the mistake is now covered by a real contract test that runs the actual schema through it, instead of a regex over the component source. - Apply dependsOn to fields inside each block, so 天单价/促销标签 hide when 月费会员升级月费会员 is switched off, matching the flat path. - Give structured groups (会员商品/续费商品/积分兑换明细/升级价格) their own bottom margin and widen the gap between accordion blocks, so two adjacent groups no longer sit flush against each other. Verified: 657 Node contract tests passing, the admin SPA builds.
This commit is contained in:
1 parent
05f16d5fd7
commit
4b5098a753
3 files changed
+74
-14
No files matched your search
@@ -493,7 +493,7 @@
|
||||
</div>
|
||||
<div v-show="isFieldsetSectionOpen(sIndex)" class="aksrt-field__accordion-section-body">
|
||||
<AksField
|
||||
v-for="field in section.fields"
|
||||
v-for="field in sectionFields(section)"
|
||||
:key="field.key"
|
||||
:schema="field"
|
||||
:model-value="fieldsetValue(field)"
|
||||
@@ -741,6 +741,7 @@ import FaIconPicker from './FaIconPicker.vue'
|
||||
import AksMediaField from './AksMediaField.vue'
|
||||
import AksGalleryField from './AksGalleryField.vue'
|
||||
import AksCodeEditor from './AksCodeEditor.vue'
|
||||
import { buildFieldsetSections } from './fieldset-sections.js'
|
||||
import draggable from 'vuedraggable'
|
||||
import api from '@/api'
|
||||
|
||||
@@ -865,18 +866,7 @@ function fieldsetValue(field) {
|
||||
* key,默认全部收起,点击块标题展开。未声明 sections 时保持平铺渲染。
|
||||
* ------------------------------------------------------------------ */
|
||||
const fieldsetSections = computed(() => {
|
||||
const sections = Array.isArray(props.schema.sections) ? props.schema : []
|
||||
if (!sections.length) return []
|
||||
const byKey = {}
|
||||
for (const field of (props.schema.fields || [])) {
|
||||
byKey[field.key] = field
|
||||
}
|
||||
return sections.map((section) => ({
|
||||
title: String(section.title || ''),
|
||||
fields: (Array.isArray(section.keys) ? section.keys : [])
|
||||
.map((key) => byKey[key])
|
||||
.filter(Boolean),
|
||||
}))
|
||||
return buildFieldsetSections(props.schema)
|
||||
})
|
||||
|
||||
const openFieldsetSections = ref(new Set())
|
||||
@@ -885,6 +875,11 @@ function isFieldsetSectionOpen(index) {
|
||||
return openFieldsetSections.value.has(index)
|
||||
}
|
||||
|
||||
/** 分块内字段同样遵循 dependsOn,数据源是本 fieldset 的值对象。 */
|
||||
function sectionFields(section) {
|
||||
return (section.fields || []).filter((field) => matchDependency(field.dependsOn, props.modelValue))
|
||||
}
|
||||
|
||||
function toggleFieldsetSection(index) {
|
||||
const next = new Set(openFieldsetSections.value)
|
||||
if (next.has(index)) {
|
||||
@@ -1319,6 +1314,15 @@ function confirmRepeaterModal() {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* 结构化分组(会员商品/续费商品/积分兑换/升级价格)与相邻字段之间留出更明确的间隔,
|
||||
* 避免两个分组上下贴在一起,和参考主题的留白一致。 */
|
||||
.aksrt-field--group,
|
||||
.aksrt-field--repeater,
|
||||
.aksrt-field--accordion,
|
||||
.aksrt-field--fieldset {
|
||||
margin-bottom: 26px;
|
||||
}
|
||||
|
||||
.aksrt-field__input-wrap {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
@@ -1585,7 +1589,7 @@ function confirmRepeaterModal() {
|
||||
}
|
||||
|
||||
.aksrt-field__accordion-section + .aksrt-field__accordion-section {
|
||||
margin-top: 8px;
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.aksrt-field__accordion-section-head {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 把 accordion / fieldset 的 `schema.sections` 声明展开成「块标题 + 字段定义」。
|
||||
*
|
||||
* 参考主题把「升级价格」这类复合配置拆成若干可折叠块,每块用 keys 声明自己
|
||||
* 包含哪些字段。这里是纯函数,方便在 Node 契约测试里直接用真实 schema 校验,
|
||||
* 避免渲染层的一个小疏忽让整块手风琴静默退化成平铺。
|
||||
*/
|
||||
export function buildFieldsetSections(schema) {
|
||||
const declared = schema && Array.isArray(schema.sections) ? schema.sections : []
|
||||
if (!declared.length) return []
|
||||
|
||||
const byKey = {}
|
||||
const nested = Array.isArray(schema.fields) ? schema.fields : []
|
||||
for (const field of nested) {
|
||||
if (field && field.key) byKey[field.key] = field
|
||||
}
|
||||
|
||||
return declared.map((section) => ({
|
||||
title: String((section && section.title) || ''),
|
||||
fields: (Array.isArray(section && section.keys) ? section.keys : [])
|
||||
.map((key) => byKey[key])
|
||||
.filter(Boolean),
|
||||
}))
|
||||
}
|
||||
Reference in new issue
Block a user