From 62d59a2f03e2832b699c446ee631425d5930544c Mon Sep 17 00:00:00 2001
From: gqt <3217233537@qq.com>
Date: Sun, 12 Jul 2026 20:38:33 +0800
Subject: [PATCH] feat: add comprehensive membership and stored value mall
---
miniprogram/package.json | 3 +-
.../scripts/verify-comprehensive-commerce.mjs | 34 +++
.../modules/comprehensive/api/membership.js | 31 +++
.../modules/comprehensive/api/storedValue.js | 27 ++
miniprogram/src/pages.json | 7 +
.../src/pages/comprehensive/mall/index.vue | 238 ++++++++++++++++++
6 files changed, 339 insertions(+), 1 deletion(-)
create mode 100644 miniprogram/scripts/verify-comprehensive-commerce.mjs
create mode 100644 miniprogram/src/modules/comprehensive/api/membership.js
create mode 100644 miniprogram/src/modules/comprehensive/api/storedValue.js
create mode 100644 miniprogram/src/pages/comprehensive/mall/index.vue
diff --git a/miniprogram/package.json b/miniprogram/package.json
index 5674bbb..cd8d5bc 100644
--- a/miniprogram/package.json
+++ b/miniprogram/package.json
@@ -13,7 +13,8 @@
"verify:home-switch": "node scripts/verify-home-venue-switch.mjs",
"verify:comprehensive-auth": "node scripts/verify-comprehensive-auth-state.mjs",
"verify:comprehensive-session": "node scripts/verify-comprehensive-session-contract.mjs",
- "verify:auth-agreements": "node scripts/verify-auth-agreements.mjs"
+ "verify:auth-agreements": "node scripts/verify-auth-agreements.mjs",
+ "verify:comprehensive-commerce": "node scripts/verify-comprehensive-commerce.mjs"
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-alpha-5000120260211001",
diff --git a/miniprogram/scripts/verify-comprehensive-commerce.mjs b/miniprogram/scripts/verify-comprehensive-commerce.mjs
new file mode 100644
index 0000000..08fd659
--- /dev/null
+++ b/miniprogram/scripts/verify-comprehensive-commerce.mjs
@@ -0,0 +1,34 @@
+import { readFileSync } from 'node:fs'
+import { fileURLToPath } from 'node:url'
+import { dirname, resolve } from 'node:path'
+
+const root = resolve(dirname(fileURLToPath(import.meta.url)), '..')
+const srcRoot = resolve(root, 'src')
+const failures = []
+
+const expectIncludes = (content, expected, label) => {
+ if (!content.includes(expected)) failures.push(`${label} is missing: ${expected}`)
+}
+
+const membershipApi = readFileSync(resolve(srcRoot, 'modules/comprehensive/api/membership.js'), 'utf8')
+const storedValueApi = readFileSync(resolve(srcRoot, 'modules/comprehensive/api/storedValue.js'), 'utf8')
+const pagesJson = readFileSync(resolve(srcRoot, 'pages.json'), 'utf8')
+const mallPage = readFileSync(resolve(srcRoot, 'pages/comprehensive/mall/index.vue'), 'utf8')
+
+expectIncludes(membershipApi, "url: '/api/membership/plans'", 'membership plans')
+expectIncludes(membershipApi, "url: '/api/membership/orders'", 'membership order')
+expectIncludes(membershipApi, 'data: { plan_id: planId }', 'membership payload')
+expectIncludes(storedValueApi, "url: '/api/stored-value/cards'", 'stored value cards')
+expectIncludes(storedValueApi, "url: '/api/stored-value/orders'", 'stored value order')
+expectIncludes(storedValueApi, 'data: { card_id: cardId }', 'stored value payload')
+expectIncludes(pagesJson, 'pages/comprehensive/mall/index', 'mall route')
+expectIncludes(mallPage, '储蓄卡', 'stored value UI copy')
+expectIncludes(mallPage, 'face_value', 'face value display')
+
+if (failures.length) {
+ console.error(`Comprehensive commerce verification failed with ${failures.length} issue(s):`)
+ for (const failure of failures) console.error(`- ${failure}`)
+ process.exit(1)
+}
+
+console.log('Comprehensive commerce verification passed.')
diff --git a/miniprogram/src/modules/comprehensive/api/membership.js b/miniprogram/src/modules/comprehensive/api/membership.js
new file mode 100644
index 0000000..02a2f7e
--- /dev/null
+++ b/miniprogram/src/modules/comprehensive/api/membership.js
@@ -0,0 +1,31 @@
+import { request } from './request'
+import { toArray, toNumber } from './mappers'
+import { toOrderBrief } from './order'
+
+const toPlan = (item = {}) => ({
+ id: item.id ?? null,
+ name: item.name || '',
+ price: item.price || '0.00',
+ total_count: toNumber(item.total_count),
+ is_active: item.is_active === true,
+ courses: toArray(item.courses).map((course) => ({
+ id: course.id ?? null,
+ title: course.title || ''
+ })),
+ created_at: item.created_at || ''
+})
+
+export const membershipApi = {
+ getPlans() {
+ return request({
+ url: '/api/membership/plans'
+ }).then((data) => toArray(data.items || data).map(toPlan))
+ },
+ createMembershipOrder(planId) {
+ return request({
+ url: '/api/membership/orders',
+ method: 'POST',
+ data: { plan_id: planId }
+ }).then(toOrderBrief)
+ }
+}
diff --git a/miniprogram/src/modules/comprehensive/api/storedValue.js b/miniprogram/src/modules/comprehensive/api/storedValue.js
new file mode 100644
index 0000000..87e8052
--- /dev/null
+++ b/miniprogram/src/modules/comprehensive/api/storedValue.js
@@ -0,0 +1,27 @@
+import { request } from './request'
+import { toArray } from './mappers'
+import { toOrderBrief } from './order'
+
+const toStoredValueCard = (item = {}) => ({
+ id: item.id ?? null,
+ name: item.name || '',
+ price: item.price || '0.00',
+ face_value: item.face_value || '0.00',
+ is_active: item.is_active === true,
+ created_at: item.created_at || ''
+})
+
+export const storedValueApi = {
+ getCards() {
+ return request({
+ url: '/api/stored-value/cards'
+ }).then((data) => toArray(data.items || data).map(toStoredValueCard))
+ },
+ createOrder(cardId) {
+ return request({
+ url: '/api/stored-value/orders',
+ method: 'POST',
+ data: { card_id: cardId }
+ }).then(toOrderBrief)
+ }
+}
diff --git a/miniprogram/src/pages.json b/miniprogram/src/pages.json
index 12c4bd6..de9fc3a 100644
--- a/miniprogram/src/pages.json
+++ b/miniprogram/src/pages.json
@@ -137,6 +137,13 @@
"navigationBarTitleText": "个人信息"
}
},
+ {
+ "path": "pages/comprehensive/mall/index",
+ "style": {
+ "navigationBarTitleText": "商城",
+ "enablePullDownRefresh": true
+ }
+ },
{
"path": "pages/ice/home/index",
"style": {
diff --git a/miniprogram/src/pages/comprehensive/mall/index.vue b/miniprogram/src/pages/comprehensive/mall/index.vue
new file mode 100644
index 0000000..37acb0f
--- /dev/null
+++ b/miniprogram/src/pages/comprehensive/mall/index.vue
@@ -0,0 +1,238 @@
+
+
+
+
+
+
+
+ {{ plan.name }}
+ ¥{{ plan.price }}
+
+ 总次数 {{ plan.total_count }}
+
+ {{ course.title }}
+
+
+
+ 暂无可购买的次卡套餐
+
+
+
+
+
+
+
+
+ {{ card.name }}
+ ¥{{ card.price }}
+
+
+ 支付
+ ¥{{ card.price }}
+ 到账
+ ¥{{ card.face_value }}
+
+
+
+ 暂无可购买的储蓄卡
+
+
+
+ 加载中...
+
+
+
+
+
+