From af8dccdc45d5acc9954a6bc8b9e4129a43b1662b Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 18 Oct 2026 17:14:00 +0800 Subject: [PATCH] feat(vip): restructure membership settings into structured groups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the pipe-delimited VIP configuration with structured groups and accordions, matching the reference theme (Zibll) 1:1. Settings: - 会员等级 keeps only the nav buttons and the two level switches, plus the "must enable level 1 first" guard. Level identity fields (display name, intro, benefits HTML, icon) and 会员商品 move into the 一级会员/二级会员 tabs of 会员购买选项, so each level is configured in one place. - Level tab titles bind to the configured display name via a new titleKey/titleFallback hook in AksFormRenderer. - 会员商品 is a repeater with exactly the reference fields: 执行价/原价/ 促销标签/标签颜色/会员有效时间/时长单位. The tag colour uses the full b+jb palette and now reaches the product card instead of a hardcoded jb-yellow. - 会员续费 gains the 自定义商品 type backed by per-level renew-product groups; the discount becomes a 0.1-9.9 slider with float sanitizing. - 会员升级 becomes the reference three-block accordion (month-to-month day-rate, jump to permanent, permanent to permanent), each with its own price, strikethrough price, promo tag and tag colour. - 积分兑换明细 is a repeater (points/level/duration/unit) where the duration accepts the literal Permanent. Runtime: - PaymentRuntime normalizes the structured groups into purchasable rows (money normalization, palette validation, zero-price and out-of-range rows dropped) and no longer emits any *_raw strings. - The catalog builder carries tag_class through and routes renewals to the renew-product group under 自定义商品. - The points-exchange order note carries time/unit so month durations use calendar math instead of a 30-day approximation. Dead code removed: parse_level_products, parse_packages, parse_upgrade_product_line and their pipe-splitting, plus nine zero-call PaymentRuntime proxy methods in HomeCms. No dual-format or migration path was added; SchemaProvider already falls back to defaults when a stored group value is not an array, so existing pipe strings degrade safely. Verified: php -l on every changed PHP file, 655 Node contract tests passing (14 new ones in vip-settings-structured-contract.test.cjs exercising the real schema build and runtime normalization via a PHP harness), and the admin SPA builds. --- assets/admin/src/components/form/AksField.vue | 2 + .../src/components/form/AksFormRenderer.vue | 18 +- .../admin/src/schema/sections/payment/vip.js | 335 ++++++++++++-- assets/js/pay-vip.js | 3 +- inc/helpers/user-center-renderers/vip-tab.php | 18 +- src/Admin/Schema/SchemaPayment.php | 196 ++++++-- src/Admin/SchemaProvider.php | 6 + src/Content/VipServiceModal.php | 12 +- src/Content/VipServicePackages.php | 434 +++++------------- src/Content/VipServicePurchase.php | 52 ++- src/Settings/HomeCms.php | 36 -- src/Settings/PaymentRuntime.php | 214 ++++++++- .../vip-modal-copy-fields.test.cjs | 48 +- .../vip-settings-structured-contract.test.cjs | 369 +++++++++++++++ .../vip-settings-structured-harness.php | 207 +++++++++ 15 files changed, 1461 insertions(+), 489 deletions(-) create mode 100644 tests/widget-system/vip-settings-structured-contract.test.cjs create mode 100644 tests/widget-system/vip-settings-structured-harness.php diff --git a/assets/admin/src/components/form/AksField.vue b/assets/admin/src/components/form/AksField.vue index 49a33bee..23a4c071 100644 --- a/assets/admin/src/components/form/AksField.vue +++ b/assets/admin/src/components/form/AksField.vue @@ -1053,6 +1053,8 @@ const repeaterDraft = ref({}) function createRepeaterItem() { const newItem = { _id: `rpt_${Date.now()}_${++repeaterIdCounter}` } for (const field of (props.schema.fields || [])) { + // UI-only chrome rows (notice / alert) are presentation only. + if (field.ui_only) continue if (field.default !== undefined) { newItem[field.key] = field.default } else if (field.type === 'switch') { diff --git a/assets/admin/src/components/form/AksFormRenderer.vue b/assets/admin/src/components/form/AksFormRenderer.vue index 5157530f..61e0c382 100644 --- a/assets/admin/src/components/form/AksFormRenderer.vue +++ b/assets/admin/src/components/form/AksFormRenderer.vue @@ -64,9 +64,9 @@