diff --git a/docs/superpowers/plans/2026-06-08-merged-venue-miniapp.md b/docs/superpowers/plans/2026-06-08-merged-venue-miniapp.md
new file mode 100644
index 0000000..33850ac
--- /dev/null
+++ b/docs/superpowers/plans/2026-06-08-merged-venue-miniapp.md
@@ -0,0 +1,1683 @@
+# Merged Venue Miniapp Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Build a new merged uni-app WeChat mini program under `场馆小程序/miniprogram` that lets users choose and switch between ice venue and comprehensive venue while keeping both Django backends, auth tokens, APIs, and business pages isolated.
+
+**Architecture:** The app uses one public venue selection shell and two isolated modules: `src/modules/ice` and `src/modules/comprehensive`. Route pages live under `src/pages/ice/*` and `src/pages/comprehensive/*`, while each module imports only its own API client and state. No backend code is changed.
+
+**Tech Stack:** uni-app, Vue 3, Vite 5, Pinia, uview-plus, dayjs, WeChat mini program target.
+
+---
+
+## File Structure Map
+
+- Create `miniprogram/package.json`: merged project dependency and script manifest copied from the existing miniapp projects.
+- Create `miniprogram/package-lock.json`: copied from the comprehensive project first, then refreshed by `npm install` if needed.
+- Create `miniprogram/vite.config.js`: Vite + uni plugin config with two API env variables and two H5 proxy prefixes.
+- Create `miniprogram/.env`: production-like default backend URLs for both venues.
+- Create `miniprogram/.env.example`: local development URL examples for both venues.
+- Create `miniprogram/src/main.js`: Vue app bootstrap with Pinia and uview-plus.
+- Create `miniprogram/src/App.vue`: merged global styles and app lifecycle logging.
+- Create `miniprogram/src/manifest.json`: WeChat app manifest using `wx516b3e0d9940c788`.
+- Create `miniprogram/src/uni.scss`: shared SCSS imports.
+- Create `miniprogram/src/styles/variables.scss`: shared design variables and mixins.
+- Create `miniprogram/src/pages.json`: merged page registry, no global `tabBar` in first version.
+- Create `miniprogram/src/stores/venue.js`: public Pinia store for current venue selection.
+- Create `miniprogram/src/utils/venue.js`: venue constants, storage helpers, target home paths, and navigation helpers.
+- Create `miniprogram/src/pages/venue-select/index.vue`: first-entry venue selector and switch page.
+- Create `miniprogram/src/modules/comprehensive/api/*`: comprehensive backend API modules.
+- Create `miniprogram/src/modules/comprehensive/stores/session.js`: comprehensive session store with dedicated store id.
+- Create `miniprogram/src/modules/comprehensive/utils/*`: comprehensive business utility modules.
+- Create `miniprogram/src/pages/comprehensive/*`: comprehensive venue route pages.
+- Create `miniprogram/src/modules/ice/api/*`: ice backend API modules.
+- Create `miniprogram/src/components/ice/StatePanel.vue`: ice module state panel component.
+- Create `miniprogram/src/pages/ice/*`: ice venue route pages.
+- Create `miniprogram/src/static/comprehensive/tab/*`: comprehensive tab image assets for future module navigation.
+- Create `miniprogram/src/static/ice/tab/*`: ice tab image assets for future module navigation.
+
+## Source Roots
+
+- Existing comprehensive miniapp: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/综合场馆小程序/miniprogram`
+- Existing ice miniapp: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/冰场馆小程序/miniprogram`
+- New merged miniapp: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram`
+
+## Implementation Tasks
+
+### Task 1: Scaffold the Merged Miniapp Shell
+
+**Files:**
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/package.json`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/package-lock.json`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/vite.config.js`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/.env`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/.env.example`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/main.js`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/App.vue`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/manifest.json`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/uni.scss`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/styles/variables.scss`
+
+- [ ] **Step 1: Copy baseline project metadata**
+
+Run:
+
+```bash
+cp '/Volumes/ExternalStorageA/project/2026.5/体育场馆/综合场馆小程序/miniprogram/package.json' '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/package.json'
+cp '/Volumes/ExternalStorageA/project/2026.5/体育场馆/综合场馆小程序/miniprogram/package-lock.json' '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/package-lock.json'
+```
+
+Expected: both files exist in `场馆小程序/miniprogram`.
+
+- [ ] **Step 2: Update merged package metadata**
+
+Edit `miniprogram/package.json` to:
+
+```json
+{
+ "name": "merged-venue-miniapp",
+ "version": "0.1.0",
+ "description": "冰场馆与综合场馆合并版微信小程序端",
+ "type": "module",
+ "scripts": {
+ "dev:mp-weixin": "uni -p mp-weixin",
+ "build:mp-weixin": "uni build -p mp-weixin",
+ "dev:h5": "uni",
+ "build:h5": "uni build"
+ },
+ "dependencies": {
+ "@dcloudio/uni-app": "3.0.0-alpha-5000120260211001",
+ "@dcloudio/uni-components": "3.0.0-alpha-5000120260211001",
+ "@dcloudio/uni-h5": "3.0.0-alpha-5000120260211001",
+ "@dcloudio/uni-mp-weixin": "3.0.0-alpha-5000120260211001",
+ "dayjs": "^1.11.21",
+ "pinia": "^2.3.1",
+ "uview-plus": "^3.8.37",
+ "vue": "^3.4.0"
+ },
+ "devDependencies": {
+ "@dcloudio/uni-automator": "3.0.0-alpha-5000120260211001",
+ "@dcloudio/uni-cli-shared": "3.0.0-alpha-5000120260211001",
+ "@dcloudio/uni-stacktracey": "3.0.0-alpha-5000120260211001",
+ "@dcloudio/vite-plugin-uni": "3.0.0-alpha-5000120260211001",
+ "sass": "^1.83.0",
+ "vite": "^5.2.0"
+ }
+}
+```
+
+Expected: package name and description identify the merged app; dependencies remain identical to the two existing miniapps.
+
+- [ ] **Step 3: Create environment files**
+
+Create `miniprogram/.env`:
+
+```dotenv
+VITE_ICE_API_BASE_URL=https://venue.test.chatgqt.top
+VITE_COMPREHENSIVE_API_BASE_URL=https://venue2.test.chatgqt.top
+```
+
+Create `miniprogram/.env.example`:
+
+```dotenv
+VITE_ICE_API_BASE_URL=http://127.0.0.1:8000
+VITE_COMPREHENSIVE_API_BASE_URL=http://127.0.0.1:8001
+```
+
+Expected: no old single `VITE_API_BASE_URL` remains in these files.
+
+- [ ] **Step 4: Create Vite config**
+
+Create `miniprogram/vite.config.js`:
+
+```js
+import { fileURLToPath, URL } from 'node:url'
+import { defineConfig, loadEnv } from 'vite'
+import uniPlugin from '@dcloudio/vite-plugin-uni'
+
+const uni = typeof uniPlugin === 'function' ? uniPlugin : uniPlugin.default
+
+export default defineConfig(({ mode }) => {
+ const env = loadEnv(mode, process.cwd(), '')
+ const iceApiBase = env.VITE_ICE_API_BASE_URL || 'http://127.0.0.1:8000'
+ const comprehensiveApiBase = env.VITE_COMPREHENSIVE_API_BASE_URL || 'http://127.0.0.1:8001'
+
+ return {
+ plugins: [uni()],
+ optimizeDeps: {
+ include: ['uview-plus'],
+ },
+ resolve: {
+ alias: {
+ '@': fileURLToPath(new URL('./src', import.meta.url)),
+ },
+ },
+ css: {
+ preprocessorOptions: {
+ scss: {
+ api: 'modern-compiler',
+ },
+ },
+ },
+ server: {
+ proxy: {
+ '/ice-api': {
+ target: iceApiBase,
+ changeOrigin: true,
+ secure: false,
+ rewrite: (path) => path.replace(/^\/ice-api/, ''),
+ },
+ '/comprehensive-api': {
+ target: comprehensiveApiBase,
+ changeOrigin: true,
+ secure: false,
+ rewrite: (path) => path.replace(/^\/comprehensive-api/, ''),
+ },
+ },
+ },
+ }
+})
+```
+
+Expected: H5 development can proxy both backends; WeChat builds still use env URLs directly.
+
+- [ ] **Step 5: Create app bootstrap**
+
+Create `miniprogram/src/main.js`:
+
+```js
+import { createSSRApp } from 'vue'
+import App from './App.vue'
+import * as Pinia from 'pinia'
+import uviewPlus from 'uview-plus'
+import 'uview-plus/index.scss'
+
+export function createApp() {
+ const app = createSSRApp(App)
+ app.use(Pinia.createPinia())
+ app.use(uviewPlus)
+ return {
+ app,
+ Pinia
+ }
+}
+```
+
+Expected: Pinia and uview-plus are globally registered.
+
+- [ ] **Step 6: Create manifest**
+
+Create `miniprogram/src/manifest.json`:
+
+```json
+{
+ "name": "场馆服务",
+ "appid": "",
+ "description": "冰场馆与综合场馆合并版会员服务小程序",
+ "versionName": "0.1.0",
+ "versionCode": "100",
+ "transformPx": false,
+ "mp-weixin": {
+ "appid": "wx516b3e0d9940c788",
+ "setting": {
+ "urlCheck": false,
+ "es6": true,
+ "postcss": true,
+ "minified": true
+ },
+ "usingComponents": true
+ },
+ "vueVersion": "3"
+}
+```
+
+Expected: WeChat appid is `wx516b3e0d9940c788`.
+
+- [ ] **Step 7: Create global SCSS files**
+
+Create `miniprogram/src/uni.scss`:
+
+```scss
+@use "@/styles/variables.scss" as *;
+@import "uview-plus/theme.scss";
+```
+
+Create `miniprogram/src/styles/variables.scss`:
+
+```scss
+$bg-color-main: #FFFFFF;
+$bg-color-soft: #F8FAFC;
+$bg-color-hover: #F1F5F9;
+$bg-color-panel: #EFF6FF;
+
+$text-color-main: #0F172A;
+$text-color-regular: #334155;
+$text-color-muted: #64748B;
+$text-color-light: #94A3B8;
+
+$color-primary: #0EA5E9;
+$color-primary-light: #E0F2FE;
+$color-success: #10B981;
+$color-success-light: #D1FAE5;
+$color-warning: #F59E0B;
+$color-warning-light: #FEF3C7;
+$color-danger: #EF4444;
+$color-danger-light: #FEE2E2;
+
+$border-color: #E2E8F0;
+$border-radius-sm: 6rpx;
+$border-radius-base: 12rpx;
+$border-radius-lg: 20rpx;
+
+$spacing-xs: 8rpx;
+$spacing-sm: 16rpx;
+$spacing-md: 24rpx;
+$spacing-lg: 32rpx;
+$spacing-xl: 48rpx;
+
+@mixin minimal-card {
+ background: $bg-color-main;
+ border: 1rpx solid $border-color;
+ border-radius: $border-radius-base;
+ padding: $spacing-md;
+ box-shadow: 0 2rpx 8rpx rgba(15, 23, 42, 0.03);
+}
+
+@mixin text-ellipsis {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+```
+
+Expected: SCSS variables used by both old projects are available.
+
+- [ ] **Step 8: Create global App component**
+
+Create `miniprogram/src/App.vue`:
+
+```vue
+
+
+
+```
+
+Expected: common global classes used by the comprehensive project remain available, and ice pages still get the shared variables.
+
+- [ ] **Step 9: Commit shell**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序'
+git add miniprogram/package.json miniprogram/package-lock.json miniprogram/vite.config.js miniprogram/.env miniprogram/.env.example miniprogram/src/main.js miniprogram/src/App.vue miniprogram/src/manifest.json miniprogram/src/uni.scss miniprogram/src/styles/variables.scss
+git commit -m "feat: scaffold merged miniapp shell"
+```
+
+Expected: commit succeeds with only shell files staged.
+
+### Task 2: Add Public Venue Selection State and Page
+
+**Files:**
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/utils/venue.js`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/stores/venue.js`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/pages/venue-select/index.vue`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/pages.json`
+
+- [ ] **Step 1: Create venue utility module**
+
+Create `miniprogram/src/utils/venue.js`:
+
+```js
+export const CURRENT_VENUE_KEY = 'CURRENT_VENUE'
+
+export const VENUE_KEYS = Object.freeze({
+ ICE: 'ice',
+ COMPREHENSIVE: 'comprehensive'
+})
+
+export const VENUE_OPTIONS = Object.freeze([
+ {
+ key: VENUE_KEYS.ICE,
+ name: '冰场馆',
+ description: '课程预约、会员卡与滑冰服务',
+ homePath: '/pages/ice/home/index'
+ },
+ {
+ key: VENUE_KEYS.COMPREHENSIVE,
+ name: '综合场馆',
+ description: '课程、包场、门票、订单与余额',
+ homePath: '/pages/comprehensive/home/index'
+ }
+])
+
+export const isVenueKey = (value) => {
+ return value === VENUE_KEYS.ICE || value === VENUE_KEYS.COMPREHENSIVE
+}
+
+export const getVenueOption = (venueKey) => {
+ return VENUE_OPTIONS.find((item) => item.key === venueKey) || null
+}
+
+export const getStoredVenue = () => {
+ const venue = uni.getStorageSync(CURRENT_VENUE_KEY)
+ return isVenueKey(venue) ? venue : ''
+}
+
+export const setStoredVenue = (venueKey) => {
+ if (!isVenueKey(venueKey)) {
+ uni.removeStorageSync(CURRENT_VENUE_KEY)
+ return ''
+ }
+
+ uni.setStorageSync(CURRENT_VENUE_KEY, venueKey)
+ return venueKey
+}
+
+export const navigateToVenueHome = (venueKey, options = {}) => {
+ const venue = getVenueOption(venueKey)
+ if (!venue) {
+ uni.reLaunch({ url: '/pages/venue-select/index' })
+ return
+ }
+
+ const navigate = options.redirect === true ? uni.redirectTo : uni.reLaunch
+ navigate({ url: venue.homePath })
+}
+```
+
+Expected: utility has a single source of truth for venue keys and home paths.
+
+- [ ] **Step 2: Create venue Pinia store**
+
+Create `miniprogram/src/stores/venue.js`:
+
+```js
+import { defineStore } from 'pinia'
+import { getStoredVenue, getVenueOption, navigateToVenueHome, setStoredVenue } from '@/utils/venue'
+
+export const useVenueStore = defineStore('currentVenue', {
+ state: () => ({
+ currentVenue: ''
+ }),
+ getters: {
+ currentVenueOption: (state) => getVenueOption(state.currentVenue),
+ hasSelectedVenue: (state) => Boolean(getVenueOption(state.currentVenue))
+ },
+ actions: {
+ init() {
+ this.currentVenue = getStoredVenue()
+ return this.currentVenue
+ },
+ selectVenue(venueKey) {
+ this.currentVenue = setStoredVenue(venueKey)
+ return this.currentVenue
+ },
+ enterVenue(venueKey) {
+ const selectedVenue = this.selectVenue(venueKey)
+ navigateToVenueHome(selectedVenue)
+ }
+ }
+})
+```
+
+Expected: selection persists and can navigate to module home.
+
+- [ ] **Step 3: Create venue selection page**
+
+Create `miniprogram/src/pages/venue-select/index.vue`:
+
+```vue
+
+
+
+
+
+
+
+ {{ venue.name }}
+ {{ venue.description }}
+
+
+ {{ venue.key === currentVenue ? '当前' : '进入' }}
+
+
+
+
+
+
+
+
+
+```
+
+Expected: first page gives two concrete choices and persists selection before navigation.
+
+- [ ] **Step 4: Create initial pages registry**
+
+Create `miniprogram/src/pages.json`:
+
+```json
+{
+ "easycom": {
+ "autoscan": true,
+ "custom": {
+ "^u--(.*)": "uview-plus/components/u-$1/u-$1.vue",
+ "^up-(.*)": "uview-plus/components/u-$1/u-$1.vue",
+ "^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue"
+ }
+ },
+ "pages": [
+ {
+ "path": "pages/venue-select/index",
+ "style": {
+ "navigationBarTitleText": "选择场馆",
+ "navigationBarBackgroundColor": "#FFFFFF",
+ "navigationBarTextStyle": "black"
+ }
+ }
+ ],
+ "globalStyle": {
+ "navigationBarTextStyle": "black",
+ "navigationBarBackgroundColor": "#FFFFFF",
+ "backgroundColor": "#F8FAFC",
+ "backgroundColorBottom": "#F8FAFC",
+ "backgroundColorTop": "#FFFFFF"
+ }
+}
+```
+
+Expected: app has a valid first page before business modules are migrated.
+
+- [ ] **Step 5: Verify selection shell builds**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram'
+npm install
+npm run build:mp-weixin
+```
+
+Expected: build succeeds or fails only because `/pages/ice/home/index` and `/pages/comprehensive/home/index` do not exist yet after tapping; compile-time should not require those target files until pages are registered. If compile fails for missing dependencies, fix dependency installation before continuing.
+
+- [ ] **Step 6: Commit selection shell**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序'
+git add miniprogram/src/utils/venue.js miniprogram/src/stores/venue.js miniprogram/src/pages/venue-select/index.vue miniprogram/src/pages.json miniprogram/package-lock.json
+git commit -m "feat: add venue selection shell"
+```
+
+Expected: commit succeeds with public shell files and any refreshed lockfile.
+
+### Task 3: Migrate Comprehensive Venue Module
+
+**Files:**
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/modules/comprehensive/api/*.js`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/modules/comprehensive/stores/session.js`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/modules/comprehensive/utils/*.js`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/pages/comprehensive/**`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/static/comprehensive/tab/*.png`
+- Modify: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/pages.json`
+
+- [ ] **Step 1: Copy comprehensive source files into namespaced locations**
+
+Run:
+
+```bash
+mkdir -p '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/modules/comprehensive'
+mkdir -p '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/pages/comprehensive'
+mkdir -p '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/static/comprehensive'
+cp -R '/Volumes/ExternalStorageA/project/2026.5/体育场馆/综合场馆小程序/miniprogram/src/api' '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/modules/comprehensive/api'
+cp -R '/Volumes/ExternalStorageA/project/2026.5/体育场馆/综合场馆小程序/miniprogram/src/stores' '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/modules/comprehensive/stores'
+cp -R '/Volumes/ExternalStorageA/project/2026.5/体育场馆/综合场馆小程序/miniprogram/src/utils' '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/modules/comprehensive/utils'
+cp -R '/Volumes/ExternalStorageA/project/2026.5/体育场馆/综合场馆小程序/miniprogram/src/pages/.' '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/pages/comprehensive/'
+cp -R '/Volumes/ExternalStorageA/project/2026.5/体育场馆/综合场馆小程序/miniprogram/src/static/tab' '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/static/comprehensive/tab'
+```
+
+Expected: comprehensive pages exist under `src/pages/comprehensive`, and API/store/utils exist under `src/modules/comprehensive`.
+
+- [ ] **Step 2: Update comprehensive request base URL**
+
+Edit `miniprogram/src/modules/comprehensive/api/request.js` so the top constants are:
+
+```js
+const KEY_TOKEN = 'COMPREHENSIVE_VENUE_TOKEN'
+
+const API_BASE_URL = import.meta.env.VITE_COMPREHENSIVE_API_BASE_URL || 'http://127.0.0.1:8001'
+```
+
+Expected: `VITE_API_BASE_URL` is not used in this module.
+
+- [ ] **Step 3: Rename comprehensive session store id and imports**
+
+Edit `miniprogram/src/modules/comprehensive/stores/session.js`:
+
+```js
+import { defineStore } from 'pinia'
+import { authApi, authStorage } from '@/modules/comprehensive/api/auth'
+import { memberApi } from '@/modules/comprehensive/api/member'
+
+export const useComprehensiveSessionStore = defineStore('comprehensiveVenueSession', {
+ state: () => ({
+ isReady: false,
+ isLoggedIn: false,
+ member: null
+ }),
+ actions: {
+ async init() {
+ this.isLoggedIn = authStorage.isLoggedIn()
+ if (this.isLoggedIn) {
+ try {
+ this.member = await memberApi.getMemberMe()
+ } catch (error) {
+ if ([40001, 40002, 401, 403].includes(error.code) || [401, 403].includes(error.statusCode)) {
+ authStorage.clear()
+ this.member = null
+ this.isLoggedIn = false
+ }
+ }
+ }
+ this.isReady = true
+ },
+ async login() {
+ const loginResult = await loginByWechat()
+ const data = await authApi.wechatLogin({ code: loginResult.code })
+ this.member = data.member
+ this.isLoggedIn = true
+ },
+ logout() {
+ authApi.logout()
+ this.member = null
+ this.isLoggedIn = false
+ },
+ async refreshMember() {
+ if (!authStorage.isLoggedIn()) return
+ this.member = await memberApi.getMemberMe()
+ this.isLoggedIn = true
+ }
+ }
+})
+
+const loginByWechat = () => new Promise((resolve, reject) => {
+ uni.login({
+ provider: 'weixin',
+ success: (res) => {
+ if (!res.code) {
+ reject(new Error('微信登录未返回 code'))
+ return
+ }
+ resolve(res)
+ },
+ fail: reject
+ })
+})
+```
+
+Expected: no `@/api` imports and no `defineStore('session')` remain in this file.
+
+- [ ] **Step 4: Rewrite comprehensive page imports**
+
+Run these replacements from `miniprogram`:
+
+```bash
+perl -pi -e "s#@/api/#@/modules/comprehensive/api/#g" src/pages/comprehensive/**/*.vue
+perl -pi -e "s#@/stores/session#@/modules/comprehensive/stores/session#g" src/pages/comprehensive/**/*.vue
+perl -pi -e "s#@/utils/#@/modules/comprehensive/utils/#g" src/pages/comprehensive/**/*.vue
+perl -pi -e "s#useSessionStore#useComprehensiveSessionStore#g" src/pages/comprehensive/**/*.vue
+```
+
+Expected: comprehensive pages import from `@/modules/comprehensive/*`.
+
+- [ ] **Step 5: Rewrite comprehensive route strings**
+
+Run these replacements from `miniprogram`:
+
+```bash
+perl -pi -e "s#/pages/home#/pages/comprehensive/home#g" src/pages/comprehensive/**/*.vue
+perl -pi -e "s#/pages/courses#/pages/comprehensive/courses#g" src/pages/comprehensive/**/*.vue
+perl -pi -e "s#/pages/bookings#/pages/comprehensive/bookings#g" src/pages/comprehensive/**/*.vue
+perl -pi -e "s#/pages/profile#/pages/comprehensive/profile#g" src/pages/comprehensive/**/*.vue
+perl -pi -e "s#/pages/activities#/pages/comprehensive/activities#g" src/pages/comprehensive/**/*.vue
+perl -pi -e "s#/pages/private#/pages/comprehensive/private#g" src/pages/comprehensive/**/*.vue
+perl -pi -e "s#/pages/tickets#/pages/comprehensive/tickets#g" src/pages/comprehensive/**/*.vue
+perl -pi -e "s#/pages/orders#/pages/comprehensive/orders#g" src/pages/comprehensive/**/*.vue
+perl -pi -e "s#/pages/pay#/pages/comprehensive/pay#g" src/pages/comprehensive/**/*.vue
+```
+
+Expected: comprehensive pages no longer navigate to unprefixed old routes.
+
+- [ ] **Step 6: Add comprehensive switch entry to profile menu**
+
+Edit `miniprogram/src/pages/comprehensive/profile/index.vue`.
+
+Add one item to `menuItems` after the personal info item:
+
+```js
+{ title: '切换场馆', url: '/pages/venue-select/index', theme: 'profile-theme', icon: 'profile' }
+```
+
+Expected: logged-in comprehensive users can navigate to the venue selection page. If the page shows no menu when logged out, the venue selector remains available by manually opening the first page; Task 7 will also validate direct switching.
+
+- [ ] **Step 7: Register comprehensive pages**
+
+Modify `miniprogram/src/pages.json` by appending these page entries after `pages/venue-select/index`:
+
+```json
+{
+ "path": "pages/comprehensive/home/index",
+ "style": {
+ "navigationBarTitleText": "首页",
+ "enablePullDownRefresh": true
+ }
+},
+{
+ "path": "pages/comprehensive/courses/index",
+ "style": {
+ "navigationBarTitleText": "课程",
+ "enablePullDownRefresh": true
+ }
+},
+{
+ "path": "pages/comprehensive/bookings/index",
+ "style": {
+ "navigationBarTitleText": "我的预约",
+ "enablePullDownRefresh": true
+ }
+},
+{
+ "path": "pages/comprehensive/profile/index",
+ "style": {
+ "navigationBarTitleText": "会员中心"
+ }
+},
+{
+ "path": "pages/comprehensive/activities/index",
+ "style": {
+ "navigationBarTitleText": "活动公告",
+ "enablePullDownRefresh": true
+ }
+},
+{
+ "path": "pages/comprehensive/activities/detail",
+ "style": {
+ "navigationBarTitleText": "活动详情"
+ }
+},
+{
+ "path": "pages/comprehensive/courses/detail",
+ "style": {
+ "navigationBarTitleText": "课程详情"
+ }
+},
+{
+ "path": "pages/comprehensive/courses/confirm",
+ "style": {
+ "navigationBarTitleText": "确认课程预约"
+ }
+},
+{
+ "path": "pages/comprehensive/private/index",
+ "style": {
+ "navigationBarTitleText": "包场预约"
+ }
+},
+{
+ "path": "pages/comprehensive/private/confirm",
+ "style": {
+ "navigationBarTitleText": "确认包场"
+ }
+},
+{
+ "path": "pages/comprehensive/tickets/index",
+ "style": {
+ "navigationBarTitleText": "篮球门票"
+ }
+},
+{
+ "path": "pages/comprehensive/pay/index",
+ "style": {
+ "navigationBarTitleText": "订单支付"
+ }
+},
+{
+ "path": "pages/comprehensive/orders/detail",
+ "style": {
+ "navigationBarTitleText": "订单详情"
+ }
+},
+{
+ "path": "pages/comprehensive/bookings/course-detail",
+ "style": {
+ "navigationBarTitleText": "课程预约详情"
+ }
+},
+{
+ "path": "pages/comprehensive/bookings/private-detail",
+ "style": {
+ "navigationBarTitleText": "包场预约详情"
+ }
+},
+{
+ "path": "pages/comprehensive/profile/balance",
+ "style": {
+ "navigationBarTitleText": "余额流水",
+ "enablePullDownRefresh": true
+ }
+},
+{
+ "path": "pages/comprehensive/profile/tickets",
+ "style": {
+ "navigationBarTitleText": "我的门票",
+ "enablePullDownRefresh": true
+ }
+},
+{
+ "path": "pages/comprehensive/profile/orders",
+ "style": {
+ "navigationBarTitleText": "我的订单",
+ "enablePullDownRefresh": true
+ }
+},
+{
+ "path": "pages/comprehensive/profile/detail",
+ "style": {
+ "navigationBarTitleText": "个人信息"
+ }
+}
+```
+
+Expected: all comprehensive pages from the old `pages.json` are registered with the `pages/comprehensive` prefix.
+
+- [ ] **Step 8: Verify comprehensive module references**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram'
+rg -n "@/api|@/stores/session|@/utils/" src/pages/comprehensive src/modules/comprehensive
+rg -n "'/pages/(home|courses|bookings|profile|activities|private|tickets|orders|pay)|\"/pages/(home|courses|bookings|profile|activities|private|tickets|orders|pay)" src/pages/comprehensive
+rg -n "VITE_API_BASE_URL" src/modules/comprehensive
+```
+
+Expected: all three commands return no matches.
+
+- [ ] **Step 9: Build after comprehensive migration**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram'
+npm run build:mp-weixin
+```
+
+Expected: build succeeds, or fails only because ice pages have not been registered yet. If the failure references comprehensive imports, fix those references before continuing.
+
+- [ ] **Step 10: Commit comprehensive module**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序'
+git add miniprogram/src/modules/comprehensive miniprogram/src/pages/comprehensive miniprogram/src/static/comprehensive miniprogram/src/pages.json
+git commit -m "feat: migrate comprehensive venue module"
+```
+
+Expected: commit succeeds with comprehensive module files.
+
+### Task 4: Migrate Ice Venue Module
+
+**Files:**
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/modules/ice/api/*.js`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/components/ice/StatePanel.vue`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/pages/ice/**`
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/static/ice/tab/*.png`
+- Modify: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/pages.json`
+
+- [ ] **Step 1: Copy ice source files into namespaced locations**
+
+Run:
+
+```bash
+mkdir -p '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/modules/ice'
+mkdir -p '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/pages/ice'
+mkdir -p '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/components/ice'
+mkdir -p '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/static/ice'
+cp -R '/Volumes/ExternalStorageA/project/2026.5/体育场馆/冰场馆小程序/miniprogram/src/api' '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/modules/ice/api'
+cp '/Volumes/ExternalStorageA/project/2026.5/体育场馆/冰场馆小程序/miniprogram/src/components/StatePanel.vue' '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/components/ice/StatePanel.vue'
+cp -R '/Volumes/ExternalStorageA/project/2026.5/体育场馆/冰场馆小程序/miniprogram/src/pages/.' '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/pages/ice/'
+cp -R '/Volumes/ExternalStorageA/project/2026.5/体育场馆/冰场馆小程序/miniprogram/src/static/tab' '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/static/ice/tab'
+```
+
+Expected: ice pages exist under `src/pages/ice`, API under `src/modules/ice/api`, and state panel under `src/components/ice`.
+
+- [ ] **Step 2: Update ice request base URL**
+
+Edit `miniprogram/src/modules/ice/api/request.js` so the base URL constant is:
+
+```js
+const API_BASE_URL = import.meta.env.VITE_ICE_API_BASE_URL || 'http://127.0.0.1:8000'
+```
+
+Expected: `VITE_API_BASE_URL` is not used in this module.
+
+- [ ] **Step 3: Rewrite ice page imports**
+
+Run these replacements from `miniprogram`:
+
+```bash
+perl -pi -e "s#@/api/#@/modules/ice/api/#g" src/pages/ice/**/*.vue
+perl -pi -e "s#@/components/StatePanel.vue#@/components/ice/StatePanel.vue#g" src/pages/ice/**/*.vue
+```
+
+Expected: ice pages import from `@/modules/ice/api/*` and `@/components/ice/StatePanel.vue`.
+
+- [ ] **Step 4: Rewrite ice route strings**
+
+Run these replacements from `miniprogram`:
+
+```bash
+perl -pi -e "s#/pages/home#/pages/ice/home#g" src/pages/ice/**/*.vue
+perl -pi -e "s#/pages/courses#/pages/ice/courses#g" src/pages/ice/**/*.vue
+perl -pi -e "s#/pages/bookings#/pages/ice/bookings#g" src/pages/ice/**/*.vue
+perl -pi -e "s#/pages/profile#/pages/ice/profile#g" src/pages/ice/**/*.vue
+perl -pi -e "s#/pages/activities#/pages/ice/activities#g" src/pages/ice/**/*.vue
+```
+
+Expected: ice pages no longer navigate to unprefixed old routes.
+
+- [ ] **Step 5: Add ice switch entry to profile page**
+
+Edit `miniprogram/src/pages/ice/profile/index.vue`.
+
+Add a menu item in the logged-in menu group before the logout item:
+
+```vue
+
+```
+
+If the page does not define `.profile-theme` or `.svg-profile-minimal`, use the existing `card-theme` icon container classes instead:
+
+```vue
+
+
+
+
+
+```
+
+Expected: logged-in ice users can navigate to the venue selection page.
+
+- [ ] **Step 6: Register ice pages**
+
+Modify `miniprogram/src/pages.json` by appending these page entries after the comprehensive entries:
+
+```json
+{
+ "path": "pages/ice/home/index",
+ "style": {
+ "navigationBarTitleText": "首页",
+ "enablePullDownRefresh": true
+ }
+},
+{
+ "path": "pages/ice/courses/index",
+ "style": {
+ "navigationBarTitleText": "近期课程",
+ "enablePullDownRefresh": true
+ }
+},
+{
+ "path": "pages/ice/bookings/index",
+ "style": {
+ "navigationBarTitleText": "我的预约",
+ "enablePullDownRefresh": true
+ }
+},
+{
+ "path": "pages/ice/profile/index",
+ "style": {
+ "navigationBarTitleText": "会员中心"
+ }
+},
+{
+ "path": "pages/ice/bookings/detail",
+ "style": {
+ "navigationBarTitleText": "预约详情"
+ }
+},
+{
+ "path": "pages/ice/courses/detail",
+ "style": {
+ "navigationBarTitleText": "课程详情"
+ }
+},
+{
+ "path": "pages/ice/profile/cards",
+ "style": {
+ "navigationBarTitleText": "我的会员卡",
+ "enablePullDownRefresh": true
+ }
+},
+{
+ "path": "pages/ice/profile/card-history",
+ "style": {
+ "navigationBarTitleText": "会员卡使用流水",
+ "enablePullDownRefresh": true
+ }
+},
+{
+ "path": "pages/ice/profile/detail",
+ "style": {
+ "navigationBarTitleText": "个人信息"
+ }
+},
+{
+ "path": "pages/ice/activities/detail",
+ "style": {
+ "navigationBarTitleText": "活动详情"
+ }
+}
+```
+
+Expected: all ice pages from the old `pages.json` are registered with the `pages/ice` prefix.
+
+- [ ] **Step 7: Verify ice module references**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram'
+rg -n "@/api|@/components/StatePanel.vue" src/pages/ice src/modules/ice
+rg -n "'/pages/(home|courses|bookings|profile|activities)|\"/pages/(home|courses|bookings|profile|activities)" src/pages/ice
+rg -n "VITE_API_BASE_URL" src/modules/ice
+```
+
+Expected: all three commands return no matches.
+
+- [ ] **Step 8: Build after ice migration**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram'
+npm run build:mp-weixin
+```
+
+Expected: build succeeds. If build fails, fix the reported import, route registration, or SCSS variable error before continuing.
+
+- [ ] **Step 9: Commit ice module**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序'
+git add miniprogram/src/modules/ice miniprogram/src/pages/ice miniprogram/src/components/ice miniprogram/src/static/ice miniprogram/src/pages.json
+git commit -m "feat: migrate ice venue module"
+```
+
+Expected: commit succeeds with ice module files.
+
+### Task 5: Finalize Cross-Module Navigation and Safety Checks
+
+**Files:**
+- Modify: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/pages/venue-select/index.vue`
+- Modify: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/src/utils/venue.js`
+- Modify: module pages only if checks reveal stale routes or stale imports.
+
+- [ ] **Step 1: Ensure venue selector can return to stored current venue**
+
+Update `miniprogram/src/pages/venue-select/index.vue` to keep the existing card UI and add a continue action when a venue is already selected:
+
+```vue
+
+
+
+
+
+ 当前场馆
+ {{ selectedVenue.name }}
+
+
+
+
+
+
+ {{ venue.name }}
+ {{ venue.description }}
+
+
+ {{ venue.key === currentVenue ? '切换进入' : '进入' }}
+
+
+
+
+
+```
+
+Add script code:
+
+```js
+const selectedVenue = computed(() => venueStore.currentVenueOption)
+
+const continueCurrentVenue = () => {
+ if (!venueStore.currentVenue) return
+ venueStore.enterVenue(venueStore.currentVenue)
+}
+```
+
+Add styles:
+
+```scss
+.current-card {
+ display: flex;
+ flex-direction: column;
+ gap: 12rpx;
+ margin-bottom: 32rpx;
+ padding: 28rpx;
+ border-radius: $border-radius-lg;
+ background: $bg-color-main;
+ border: 1rpx solid $border-color;
+}
+
+.current-label {
+ color: $text-color-muted;
+ font-size: 22rpx;
+ font-weight: 700;
+}
+
+.current-name {
+ color: $text-color-main;
+ font-size: 32rpx;
+ font-weight: 900;
+}
+
+.continue-btn {
+ margin-top: 12rpx;
+}
+```
+
+Expected: users who return to the selector can continue into the stored venue without changing it.
+
+- [ ] **Step 2: Run stale import checks**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram'
+rg -n "@/api|@/stores/session|@/utils/(date|money|status)|@/components/StatePanel.vue" src/pages src/modules
+```
+
+Expected: no matches. If matches appear, rewrite them to module-specific imports:
+
+```text
+@/modules/ice/api/
+@/modules/comprehensive/api/
+@/modules/comprehensive/utils/
+@/components/ice/StatePanel.vue
+```
+
+- [ ] **Step 3: Run stale route checks**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram'
+rg -n "'/pages/(home|courses|bookings|profile|activities|private|tickets|orders|pay)|\"/pages/(home|courses|bookings|profile|activities|private|tickets|orders|pay)|`/pages/(home|courses|bookings|profile|activities|private|tickets|orders|pay)" src/pages
+```
+
+Expected: no matches. If matches appear, prefix with `ice` or `comprehensive` based on the file path.
+
+- [ ] **Step 4: Run API base URL checks**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram'
+rg -n "VITE_API_BASE_URL|const API_BASE_URL" src/modules
+```
+
+Expected output includes only:
+
+```text
+src/modules/ice/api/request.js:const API_BASE_URL = import.meta.env.VITE_ICE_API_BASE_URL || 'http://127.0.0.1:8000'
+src/modules/comprehensive/api/request.js:const API_BASE_URL = import.meta.env.VITE_COMPREHENSIVE_API_BASE_URL || 'http://127.0.0.1:8001'
+```
+
+- [ ] **Step 5: Run token isolation checks**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram'
+rg -n "ICE_MEMBER_TOKEN|ICE_MEMBER_TOKEN_EXPIRES_AT|COMPREHENSIVE_VENUE_TOKEN" src/modules
+```
+
+Expected output includes:
+
+```text
+src/modules/ice/api/request.js:const KEY_TOKEN = 'ICE_MEMBER_TOKEN'
+src/modules/ice/api/request.js:const KEY_TOKEN_EXPIRES_AT = 'ICE_MEMBER_TOKEN_EXPIRES_AT'
+src/modules/comprehensive/api/request.js:const KEY_TOKEN = 'COMPREHENSIVE_VENUE_TOKEN'
+```
+
+- [ ] **Step 6: Build final merged app**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram'
+npm run build:mp-weixin
+```
+
+Expected: build succeeds and outputs `dist/build/mp-weixin`.
+
+- [ ] **Step 7: Commit safety pass**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序'
+git add miniprogram
+git commit -m "fix: finalize merged venue navigation"
+```
+
+Expected: commit succeeds if files changed. If no files changed after checks, skip this commit and record that no safety-pass commit was needed.
+
+### Task 6: Manual WeChat Mini Program Smoke Test
+
+**Files:**
+- No source files should be modified unless the smoke test finds a defect.
+
+- [ ] **Step 1: Open generated mini program in WeChat DevTools**
+
+Open this directory in WeChat DevTools:
+
+```text
+/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram/dist/build/mp-weixin
+```
+
+Expected: project opens with appid `wx516b3e0d9940c788`.
+
+- [ ] **Step 2: Smoke test venue selector**
+
+In the simulator:
+
+```text
+1. Open first page.
+2. Confirm "选择场馆" appears.
+3. Tap "冰场馆".
+4. Confirm URL is pages/ice/home/index.
+5. Navigate back to pages/venue-select/index.
+6. Tap "综合场馆".
+7. Confirm URL is pages/comprehensive/home/index.
+```
+
+Expected: both venue cards navigate to the correct module home page.
+
+- [ ] **Step 3: Smoke test ice module navigation**
+
+Open these paths in WeChat DevTools page path input:
+
+```text
+pages/ice/home/index
+pages/ice/courses/index
+pages/ice/bookings/index
+pages/ice/profile/index
+pages/ice/profile/cards
+```
+
+Expected: each page loads without a JavaScript import error. Network errors from unavailable backend are acceptable during local smoke testing if request URLs point to `https://venue.test.chatgqt.top`.
+
+- [ ] **Step 4: Smoke test comprehensive module navigation**
+
+Open these paths in WeChat DevTools page path input:
+
+```text
+pages/comprehensive/home/index
+pages/comprehensive/courses/index
+pages/comprehensive/bookings/index
+pages/comprehensive/profile/index
+pages/comprehensive/private/index
+pages/comprehensive/tickets/index
+pages/comprehensive/pay/index?order_id=1
+```
+
+Expected: each page loads without a JavaScript import error. The pay page may show an order loading error for `order_id=1`; it must not call the ice backend.
+
+- [ ] **Step 5: Inspect request domains**
+
+Use WeChat DevTools network panel:
+
+```text
+1. Open pages/ice/home/index.
+2. Confirm requests go to https://venue.test.chatgqt.top.
+3. Open pages/comprehensive/home/index.
+4. Confirm requests go to https://venue2.test.chatgqt.top.
+```
+
+Expected: requests never cross backend domains.
+
+- [ ] **Step 6: Commit smoke-test fixes**
+
+If source fixes were required, run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序'
+git add miniprogram
+git commit -m "fix: address merged miniapp smoke test issues"
+```
+
+Expected: commit succeeds only if smoke testing found and fixed defects.
+
+### Task 7: Final Verification and Delivery Notes
+
+**Files:**
+- Create: `/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/docs/merged-miniapp-verification.md`
+
+- [ ] **Step 1: Run final command verification**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序/miniprogram'
+npm run build:mp-weixin
+rg -n "@/api|@/stores/session|@/utils/(date|money|status)|@/components/StatePanel.vue" src/pages src/modules
+rg -n "'/pages/(home|courses|bookings|profile|activities|private|tickets|orders|pay)|\"/pages/(home|courses|bookings|profile|activities|private|tickets|orders|pay)|`/pages/(home|courses|bookings|profile|activities|private|tickets|orders|pay)" src/pages
+rg -n "VITE_API_BASE_URL" src/modules .env .env.example vite.config.js
+```
+
+Expected:
+
+```text
+npm run build:mp-weixin exits 0
+stale import rg exits 1 with no matches
+stale route rg exits 1 with no matches
+VITE_API_BASE_URL rg exits 1 with no matches
+```
+
+- [ ] **Step 2: Write verification note**
+
+Create `docs/merged-miniapp-verification.md`:
+
+```markdown
+# 合并版场馆小程序验证记录
+
+## 构建
+
+- 命令:`npm run build:mp-weixin`
+- 结果:通过
+- 产物:`miniprogram/dist/build/mp-weixin`
+
+## 路由隔离
+
+- 检查旧的无前缀页面路径:通过
+- 冰场馆页面前缀:`pages/ice`
+- 综合场馆页面前缀:`pages/comprehensive`
+
+## API 隔离
+
+- 冰场馆 baseURL:`VITE_ICE_API_BASE_URL`
+- 综合场馆 baseURL:`VITE_COMPREHENSIVE_API_BASE_URL`
+- 旧 `VITE_API_BASE_URL`:未使用
+
+## 登录态隔离
+
+- 冰场馆 token:`ICE_MEMBER_TOKEN`
+- 冰场馆 token 过期时间:`ICE_MEMBER_TOKEN_EXPIRES_AT`
+- 综合场馆 token:`COMPREHENSIVE_VENUE_TOKEN`
+
+## 上线前人工检查
+
+- 微信 request 合法域名包含 `venue.test.chatgqt.top`
+- 微信 request 合法域名包含 `venue2.test.chatgqt.top`
+- 综合场馆支付仍由综合场馆后端生成支付参数
+```
+
+If any command fails, replace `结果:通过` with the exact failing command and actual status, then fix the issue before final delivery.
+
+- [ ] **Step 3: Commit verification note**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序'
+git add docs/merged-miniapp-verification.md
+git commit -m "docs: record merged miniapp verification"
+```
+
+Expected: commit succeeds with the verification record.
+
+- [ ] **Step 4: Final git status check**
+
+Run:
+
+```bash
+cd '/Volumes/ExternalStorageA/project/2026.5/体育场馆/场馆小程序'
+git status --short
+```
+
+Expected: no uncommitted files except intentionally ignored build output if `.gitignore` is added later. If build output appears and should not be committed, add a project `.gitignore` that ignores:
+
+```gitignore
+miniprogram/node_modules/
+miniprogram/dist/
+.DS_Store
+```
+
+Commit `.gitignore` with:
+
+```bash
+git add .gitignore
+git commit -m "chore: ignore generated miniapp files"
+```
+
+Expected: working tree is clean or only contains intentionally untracked files reported to the user.
+
+## Plan Self-Review
+
+Spec coverage:
+
+- New project under `场馆小程序/miniprogram`: Task 1.
+- First-entry venue choice and in-app switching: Tasks 2, 5, and 6.
+- Isolated Django backends and API clients: Tasks 1, 3, 4, and 5.
+- Token isolation: Tasks 3, 4, 5, and 7.
+- Route prefixing: Tasks 3, 4, and 5.
+- No backend/admin/CI merge: all tasks operate only under `场馆小程序`.
+- Build and smoke verification: Tasks 5, 6, and 7.
+
+Placeholder scan: the plan intentionally avoids unspecified implementation slots. Each migration step includes exact copy commands, rewrite commands, file paths, expected checks, and commit commands.
+
+Type consistency:
+
+- Venue key values are `ice` and `comprehensive` across `VENUE_KEYS`, storage, routes, and page prefixes.
+- Store exports are `useVenueStore` and `useComprehensiveSessionStore`.
+- Environment variables are `VITE_ICE_API_BASE_URL` and `VITE_COMPREHENSIVE_API_BASE_URL`.
+- Token keys are `ICE_MEMBER_TOKEN`, `ICE_MEMBER_TOKEN_EXPIRES_AT`, and `COMPREHENSIVE_VENUE_TOKEN`.