From cd30f57f2cd6ae2de4b08ef3491d137340a859f6 Mon Sep 17 00:00:00 2001 From: wdh-home <243823965@qq.com> Date: Thu, 23 Apr 2026 21:25:24 +0800 Subject: [PATCH] feat: migrate static pages to native tabbar --- app.js | 4 +- app.json | 64 ++++ app.wxss | 18 +- packages/demo/pages/workbench/index.js | 7 +- packages/learning/pages/center/index.js | 74 ++++ packages/learning/pages/center/index.json | 5 + packages/learning/pages/center/index.wxml | 44 +++ packages/learning/pages/center/index.wxss | 150 ++++++++ packages/mingli/pages/bazi/index.js | 52 +++ packages/mingli/pages/bazi/index.json | 5 + packages/mingli/pages/bazi/index.wxml | 63 ++++ packages/mingli/pages/bazi/index.wxss | 194 ++++++++++ packages/mingli/pages/book-detail/index.js | 63 ++++ packages/mingli/pages/book-detail/index.json | 5 + packages/mingli/pages/book-detail/index.wxml | 28 ++ packages/mingli/pages/book-detail/index.wxss | 75 ++++ packages/mingli/pages/hall/index.js | 81 ++++ packages/mingli/pages/hall/index.json | 5 + packages/mingli/pages/hall/index.wxml | 76 ++++ packages/mingli/pages/hall/index.wxss | 166 +++++++++ packages/mingli/pages/interpret/index.js | 42 +++ packages/mingli/pages/interpret/index.json | 5 + packages/mingli/pages/interpret/index.wxml | 24 ++ packages/mingli/pages/interpret/index.wxss | 91 +++++ packages/mingli/pages/search-books/index.js | 61 +++ packages/mingli/pages/search-books/index.json | 5 + packages/mingli/pages/search-books/index.wxml | 21 ++ packages/mingli/pages/search-books/index.wxss | 43 +++ packages/mingli/pages/section/index.js | 57 +++ packages/mingli/pages/section/index.json | 5 + packages/mingli/pages/section/index.wxml | 19 + packages/mingli/pages/section/index.wxss | 56 +++ packages/tcm/pages/ai-history/index.js | 80 ++++ packages/tcm/pages/ai-history/index.json | 5 + packages/tcm/pages/ai-history/index.wxml | 27 ++ packages/tcm/pages/ai-history/index.wxss | 82 ++++ packages/tcm/pages/assets/index.js | 153 ++++++++ packages/tcm/pages/assets/index.json | 5 + packages/tcm/pages/assets/index.wxml | 36 ++ packages/tcm/pages/assets/index.wxss | 80 ++++ packages/tcm/pages/bianzheng/index.js | 50 +++ packages/tcm/pages/bianzheng/index.json | 5 + packages/tcm/pages/bianzheng/index.wxml | 30 ++ packages/tcm/pages/bianzheng/index.wxss | 120 ++++++ packages/tcm/pages/book-detail/index.js | 125 +++++++ packages/tcm/pages/book-detail/index.json | 5 + packages/tcm/pages/book-detail/index.wxml | 54 +++ packages/tcm/pages/book-detail/index.wxss | 147 ++++++++ packages/tcm/pages/placeholder/index.js | 99 +++++ packages/tcm/pages/placeholder/index.json | 5 + packages/tcm/pages/placeholder/index.wxml | 26 ++ packages/tcm/pages/placeholder/index.wxss | 83 +++++ packages/tcm/pages/search-books/index.js | 90 +++++ packages/tcm/pages/search-books/index.json | 5 + packages/tcm/pages/search-books/index.wxml | 50 +++ packages/tcm/pages/search-books/index.wxss | 96 +++++ packages/tcm/pages/section/index.js | 97 +++++ packages/tcm/pages/section/index.json | 5 + packages/tcm/pages/section/index.wxml | 49 +++ packages/tcm/pages/section/index.wxss | 102 +++++ pages/ai/index.js | 185 +++++++++ pages/ai/index.json | 5 + pages/ai/index.wxml | 107 ++++++ pages/ai/index.wxss | 306 +++++++++++++++ pages/ai/tab-ai-active.png | Bin 0 -> 1785 bytes pages/ai/tab-ai.png | Bin 0 -> 1805 bytes pages/home/index.js | 264 +++++++++---- pages/home/index.json | 8 +- pages/home/index.wxml | 154 +++++--- pages/home/index.wxss | 337 +++++++++++++++-- pages/home/tab-home-active.png | Bin 0 -> 1578 bytes pages/home/tab-home.png | Bin 0 -> 1601 bytes pages/library/index.js | 350 ++++++++++++++++++ pages/library/index.json | 5 + pages/library/index.wxml | 43 +++ pages/library/index.wxss | 205 ++++++++++ pages/library/tab-library-active.png | Bin 0 -> 1562 bytes pages/library/tab-library.png | Bin 0 -> 1590 bytes pages/login/index.js | 117 +++--- pages/login/index.json | 7 +- pages/login/index.wxml | 61 ++- pages/login/index.wxss | 107 +++++- pages/profile/index.js | 131 +++++++ pages/profile/index.json | 5 + pages/profile/index.wxml | 65 ++++ pages/profile/index.wxss | 204 ++++++++++ pages/profile/tab-profile-active.png | Bin 0 -> 1931 bytes pages/profile/tab-profile.png | Bin 0 -> 1941 bytes project.config.json | 5 +- services/api/user.js | 2 +- services/request/index.js | 2 +- tests/ai-page-render.test.js | 34 ++ tests/ai-page.test.js | 170 +++++++++ tests/home-page-render.test.js | 72 ++++ tests/home-page.test.js | 169 +++++++++ tests/library-page-render.test.js | 29 ++ tests/library-page.test.js | 145 ++++++++ tests/login-page-render.test.js | 22 ++ tests/login-page.test.js | 75 ++++ tests/mingli-bazi-page-render.test.js | 33 ++ tests/mingli-learning-pages.test.js | 29 ++ tests/miniprogram-compatibility.test.js | 83 +++++ tests/profile-page-render.test.js | 24 ++ tests/profile-page.test.js | 43 +++ tests/project-config.test.js | 82 ++++ tests/request.test.js | 2 +- tests/static-ux-domain-data.test.js | 46 +++ tests/static-ux-navigation.test.js | 26 ++ tests/static-ux-route-map.test.js | 12 + tests/tcm-reading-pages.test.js | 25 ++ tests/tcm-support-pages.test.js | 99 +++++ utils/static-ux/learning.js | 15 + utils/static-ux/mingli.js | 48 +++ utils/static-ux/route-map.js | 81 ++++ utils/static-ux/shared.js | 22 ++ utils/static-ux/tcm.js | 74 ++++ 116 files changed, 7143 insertions(+), 311 deletions(-) create mode 100644 packages/learning/pages/center/index.js create mode 100644 packages/learning/pages/center/index.json create mode 100644 packages/learning/pages/center/index.wxml create mode 100644 packages/learning/pages/center/index.wxss create mode 100644 packages/mingli/pages/bazi/index.js create mode 100644 packages/mingli/pages/bazi/index.json create mode 100644 packages/mingli/pages/bazi/index.wxml create mode 100644 packages/mingli/pages/bazi/index.wxss create mode 100644 packages/mingli/pages/book-detail/index.js create mode 100644 packages/mingli/pages/book-detail/index.json create mode 100644 packages/mingli/pages/book-detail/index.wxml create mode 100644 packages/mingli/pages/book-detail/index.wxss create mode 100644 packages/mingli/pages/hall/index.js create mode 100644 packages/mingli/pages/hall/index.json create mode 100644 packages/mingli/pages/hall/index.wxml create mode 100644 packages/mingli/pages/hall/index.wxss create mode 100644 packages/mingli/pages/interpret/index.js create mode 100644 packages/mingli/pages/interpret/index.json create mode 100644 packages/mingli/pages/interpret/index.wxml create mode 100644 packages/mingli/pages/interpret/index.wxss create mode 100644 packages/mingli/pages/search-books/index.js create mode 100644 packages/mingli/pages/search-books/index.json create mode 100644 packages/mingli/pages/search-books/index.wxml create mode 100644 packages/mingli/pages/search-books/index.wxss create mode 100644 packages/mingli/pages/section/index.js create mode 100644 packages/mingli/pages/section/index.json create mode 100644 packages/mingli/pages/section/index.wxml create mode 100644 packages/mingli/pages/section/index.wxss create mode 100644 packages/tcm/pages/ai-history/index.js create mode 100644 packages/tcm/pages/ai-history/index.json create mode 100644 packages/tcm/pages/ai-history/index.wxml create mode 100644 packages/tcm/pages/ai-history/index.wxss create mode 100644 packages/tcm/pages/assets/index.js create mode 100644 packages/tcm/pages/assets/index.json create mode 100644 packages/tcm/pages/assets/index.wxml create mode 100644 packages/tcm/pages/assets/index.wxss create mode 100644 packages/tcm/pages/bianzheng/index.js create mode 100644 packages/tcm/pages/bianzheng/index.json create mode 100644 packages/tcm/pages/bianzheng/index.wxml create mode 100644 packages/tcm/pages/bianzheng/index.wxss create mode 100644 packages/tcm/pages/book-detail/index.js create mode 100644 packages/tcm/pages/book-detail/index.json create mode 100644 packages/tcm/pages/book-detail/index.wxml create mode 100644 packages/tcm/pages/book-detail/index.wxss create mode 100644 packages/tcm/pages/placeholder/index.js create mode 100644 packages/tcm/pages/placeholder/index.json create mode 100644 packages/tcm/pages/placeholder/index.wxml create mode 100644 packages/tcm/pages/placeholder/index.wxss create mode 100644 packages/tcm/pages/search-books/index.js create mode 100644 packages/tcm/pages/search-books/index.json create mode 100644 packages/tcm/pages/search-books/index.wxml create mode 100644 packages/tcm/pages/search-books/index.wxss create mode 100644 packages/tcm/pages/section/index.js create mode 100644 packages/tcm/pages/section/index.json create mode 100644 packages/tcm/pages/section/index.wxml create mode 100644 packages/tcm/pages/section/index.wxss create mode 100644 pages/ai/index.js create mode 100644 pages/ai/index.json create mode 100644 pages/ai/index.wxml create mode 100644 pages/ai/index.wxss create mode 100644 pages/ai/tab-ai-active.png create mode 100644 pages/ai/tab-ai.png create mode 100644 pages/home/tab-home-active.png create mode 100644 pages/home/tab-home.png create mode 100644 pages/library/index.js create mode 100644 pages/library/index.json create mode 100644 pages/library/index.wxml create mode 100644 pages/library/index.wxss create mode 100644 pages/library/tab-library-active.png create mode 100644 pages/library/tab-library.png create mode 100644 pages/profile/index.js create mode 100644 pages/profile/index.json create mode 100644 pages/profile/index.wxml create mode 100644 pages/profile/index.wxss create mode 100644 pages/profile/tab-profile-active.png create mode 100644 pages/profile/tab-profile.png create mode 100644 tests/ai-page-render.test.js create mode 100644 tests/ai-page.test.js create mode 100644 tests/home-page-render.test.js create mode 100644 tests/home-page.test.js create mode 100644 tests/library-page-render.test.js create mode 100644 tests/library-page.test.js create mode 100644 tests/login-page-render.test.js create mode 100644 tests/login-page.test.js create mode 100644 tests/mingli-bazi-page-render.test.js create mode 100644 tests/mingli-learning-pages.test.js create mode 100644 tests/miniprogram-compatibility.test.js create mode 100644 tests/profile-page-render.test.js create mode 100644 tests/profile-page.test.js create mode 100644 tests/project-config.test.js create mode 100644 tests/static-ux-domain-data.test.js create mode 100644 tests/static-ux-navigation.test.js create mode 100644 tests/static-ux-route-map.test.js create mode 100644 tests/tcm-reading-pages.test.js create mode 100644 tests/tcm-support-pages.test.js create mode 100644 utils/static-ux/learning.js create mode 100644 utils/static-ux/mingli.js create mode 100644 utils/static-ux/route-map.js create mode 100644 utils/static-ux/shared.js create mode 100644 utils/static-ux/tcm.js diff --git a/app.js b/app.js index 555e979..e3523cd 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,6 @@ const { getRuntimeConfig } = require('./config/env') -const { setUnauthorizedHandler } = require('./services/request') -const { sessionStore } = require('./stores') +const { setUnauthorizedHandler } = require('./services/request/index') +const { sessionStore } = require('./stores/index') App({ globalData: { diff --git a/app.json b/app.json index 83cdbc6..2f5ef5d 100644 --- a/app.json +++ b/app.json @@ -1,6 +1,9 @@ { "pages": [ "pages/home/index", + "pages/library/index", + "pages/ai/index", + "pages/profile/index", "pages/login/index" ], "subPackages": [ @@ -9,6 +12,35 @@ "pages": [ "pages/workbench/index" ] + }, + { + "root": "packages/tcm", + "pages": [ + "pages/ai-history/index", + "pages/assets/index", + "pages/bianzheng/index", + "pages/book-detail/index", + "pages/search-books/index", + "pages/section/index", + "pages/placeholder/index" + ] + }, + { + "root": "packages/mingli", + "pages": [ + "pages/hall/index", + "pages/bazi/index", + "pages/book-detail/index", + "pages/search-books/index", + "pages/section/index", + "pages/interpret/index" + ] + }, + { + "root": "packages/learning", + "pages": [ + "pages/center/index" + ] } ], "preloadRule": { @@ -25,6 +57,38 @@ "navigationBarBackgroundColor": "#f5f7fa", "backgroundColor": "#f5f7fa" }, + "tabBar": { + "color": "#9f7c56", + "selectedColor": "#8f5c1f", + "backgroundColor": "#fff8ee", + "borderStyle": "white", + "list": [ + { + "pagePath": "pages/home/index", + "text": "首页", + "iconPath": "pages/home/tab-home.png", + "selectedIconPath": "pages/home/tab-home-active.png" + }, + { + "pagePath": "pages/library/index", + "text": "典籍", + "iconPath": "pages/library/tab-library.png", + "selectedIconPath": "pages/library/tab-library-active.png" + }, + { + "pagePath": "pages/ai/index", + "text": "AI", + "iconPath": "pages/ai/tab-ai.png", + "selectedIconPath": "pages/ai/tab-ai-active.png" + }, + { + "pagePath": "pages/profile/index", + "text": "我的", + "iconPath": "pages/profile/tab-profile.png", + "selectedIconPath": "pages/profile/tab-profile-active.png" + } + ] + }, "networkTimeout": { "request": 10000 }, diff --git a/app.wxss b/app.wxss index 03299cd..defb07c 100644 --- a/app.wxss +++ b/app.wxss @@ -1,4 +1,4 @@ -@import 'tdesign-miniprogram/common/style/index.wxss'; +@import './miniprogram_npm/tdesign-miniprogram/common/style/index.wxss'; page { min-height: 100%; @@ -45,3 +45,19 @@ text { justify-content: space-between; gap: 24rpx; } + +.xz-page--warm { + min-height: 100vh; + background: linear-gradient(180deg, #f8edd6 0%, #f9f0de 24%, #f6ead4 100%); +} + +.xz-page--mingli { + min-height: 100vh; + background: linear-gradient(180deg, #fbf6f3 0%, #f4ebe6 100%); +} + +.xz-card { + border-radius: 28rpx; + border: 1rpx solid rgba(84, 58, 29, 0.08); + box-shadow: 0 16rpx 36rpx rgba(84, 58, 29, 0.06); +} diff --git a/packages/demo/pages/workbench/index.js b/packages/demo/pages/workbench/index.js index 6f418cf..44aed68 100644 --- a/packages/demo/pages/workbench/index.js +++ b/packages/demo/pages/workbench/index.js @@ -1,4 +1,5 @@ -const { sessionStore } = require('../../../../stores') +const { sessionStore } = require('../../../../stores/index') +const { openStaticRoute } = require('../../../../utils/static-ux/route-map') const MODULES = [ { @@ -41,8 +42,6 @@ Page({ return } - wx.navigateTo({ - url: path - }) + openStaticRoute(path, wx) } }) diff --git a/packages/learning/pages/center/index.js b/packages/learning/pages/center/index.js new file mode 100644 index 0000000..6f66f37 --- /dev/null +++ b/packages/learning/pages/center/index.js @@ -0,0 +1,74 @@ +const { + createLearningCenterPageData: createBaseLearningCenterPageData +} = require('../../../../utils/static-ux/learning') +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +function createLearningCenterPageData() { + const baseData = createBaseLearningCenterPageData() + + return { + ...baseData, + heroTitle: '先继续上次学习,再回看静态记录', + heroDescription: '学习中心不再承接旧后台列表,而是把最值得继续的学习动作放到最上面。', + quickDeck: [ + { + key: 'qa-history', + title: 'AI历史', + description: '继续查看中医问答与辨证分析的静态记录页', + route: ROUTES.tcm.aiHistory, + domain: 'tcm' + }, + { + key: 'assets', + title: '学习资产', + description: '回到笔记、书架、收藏和历史四类资产入口', + route: `${ROUTES.tcm.assets}?kind=notes`, + domain: 'tcm' + }, + { + key: 'interpret', + title: '命理解读', + description: '进入易学侧的静态问题解读页', + route: `${ROUTES.mingli.interpret}?scene=result`, + domain: 'mingli' + }, + { + key: 'bazi', + title: '八字排盘', + description: '继续查看静态排盘结果与四柱结构', + route: `${ROUTES.mingli.bazi}?scene=result`, + domain: 'mingli' + } + ], + recentItems: [ + { + key: 'recent-reading', + title: '典籍阅读', + description: '回到《黄帝内经素问》的静态阅读页。', + route: `${ROUTES.tcm.section}?scene=reader-a` + }, + { + key: 'recent-yixue', + title: '易学阅读', + description: '继续浏览《滴天髓》的静态阅读页。', + route: `${ROUTES.mingli.section}?scene=reader-a` + } + ] + } +} + +function showNavigate(route) { + openStaticRoute(route, wx) +} + +Page({ + data: createLearningCenterPageData(), + + handleRouteTap(event) { + showNavigate(event.currentTarget.dataset.route) + } +}) + +module.exports = { + createLearningCenterPageData +} diff --git a/packages/learning/pages/center/index.json b/packages/learning/pages/center/index.json new file mode 100644 index 0000000..ce57338 --- /dev/null +++ b/packages/learning/pages/center/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "学习中心", + "navigationBarBackgroundColor": "#f7f0e6", + "navigationBarTextStyle": "black" +} diff --git a/packages/learning/pages/center/index.wxml b/packages/learning/pages/center/index.wxml new file mode 100644 index 0000000..f2457a1 --- /dev/null +++ b/packages/learning/pages/center/index.wxml @@ -0,0 +1,44 @@ + + + {{heroTitle}} + {{heroDescription}} + + + {{item.value}} + {{item.label}} + + + + + + + {{item.domain === 'tcm' ? '中医继续学习' : '易学继续学习'}} + {{item.title}} + {{item.description}} + + + + + 最近学习动作 + + + + {{item.title}} + {{item.description}} + + > + + + diff --git a/packages/learning/pages/center/index.wxss b/packages/learning/pages/center/index.wxss new file mode 100644 index 0000000..bd0ff83 --- /dev/null +++ b/packages/learning/pages/center/index.wxss @@ -0,0 +1,150 @@ +page { + min-height: 100%; + background: linear-gradient(180deg, #f7f2ea 0%, #efe7dc 100%); +} + +.learning-page { + box-sizing: border-box; + min-height: 100vh; + padding: 28rpx 20rpx 72rpx; +} + +.hero-card, +.section-card, +.quick-card { + border: 1rpx solid rgba(84, 58, 29, 0.08); + border-radius: 28rpx; + background: rgba(255, 251, 244, 0.92); + box-shadow: 0 10rpx 26rpx rgba(78, 50, 22, 0.06); +} + +.hero-card { + padding: 24rpx; +} + +.hero-card__title, +.section-card__title, +.quick-card__title, +.timeline-item__title { + display: block; + color: #2f261d; + font-family: 'STSong', 'Songti SC', serif; + font-size: 34rpx; + font-weight: 700; + line-height: 1.3; +} + +.hero-card__desc, +.quick-card__desc, +.timeline-item__desc { + display: block; + margin-top: 10rpx; + color: #7b6d60; + font-size: 24rpx; + line-height: 1.6; +} + +.stats-row { + display: flex; + flex-wrap: wrap; + margin: 14rpx -5rpx 0; +} + +.stat-pill { + box-sizing: border-box; + width: 25%; + padding: 5rpx; +} + +.stat-pill__value, +.stat-pill__label { + display: block; + text-align: center; +} + +.stat-pill__value { + padding: 12rpx 0 6rpx; + border-radius: 18rpx 18rpx 0 0; + background: rgba(255, 250, 242, 0.8); + color: #2f261d; + font-size: 28rpx; + font-weight: 700; +} + +.stat-pill__label { + padding: 0 0 12rpx; + border-radius: 0 0 18rpx 18rpx; + background: rgba(255, 250, 242, 0.8); + color: #7b6d60; + font-size: 22rpx; +} + +.quick-grid { + display: flex; + flex-wrap: wrap; + margin: 12rpx -6rpx 0; +} + +.quick-card { + box-sizing: border-box; + width: 50%; + margin-top: 12rpx; + padding: 24rpx 18rpx; + margin-left: 6rpx; + margin-right: 6rpx; +} + +.quick-card__tag { + display: inline-block; + padding: 8rpx 12rpx; + border-radius: 999rpx; + background: rgba(84, 58, 29, 0.08); + color: #6d4d2f; + font-size: 18rpx; + line-height: 1; +} + +.quick-card__title { + margin-top: 14rpx; +} + +.section-card { + margin-top: 18rpx; + padding: 24rpx; +} + +.timeline-item { + display: flex; + align-items: center; + margin-top: 16rpx; + padding-top: 16rpx; + border-top: 1rpx solid rgba(84, 58, 29, 0.08); +} + +.timeline-item:first-of-type { + margin-top: 10rpx; + padding-top: 0; + border-top: 0; +} + +.timeline-item__icon { + width: 72rpx; + height: 72rpx; + border-radius: 18rpx; + background: rgba(84, 58, 29, 0.08); + color: #6d4d2f; + font-size: 26rpx; + line-height: 72rpx; + text-align: center; +} + +.timeline-item__body { + flex: 1; + margin-left: 14rpx; +} + +.timeline-item__arrow { + color: #b4946a; + font-size: 28rpx; + line-height: 1; +} diff --git a/packages/mingli/pages/bazi/index.js b/packages/mingli/pages/bazi/index.js new file mode 100644 index 0000000..ab813ad --- /dev/null +++ b/packages/mingli/pages/bazi/index.js @@ -0,0 +1,52 @@ +const { resolveScene } = require('../../../../utils/static-ux/shared') +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +function createMingliBaziPageData(rawScene) { + const scene = resolveScene(rawScene, ['default', 'result'], 'default') + + return { + title: '八字排盘', + scene, + form: { + name: '张三', + gender: '男', + birthDate: '1990-01-01', + birthTime: '08:30' + }, + result: + scene === 'result' + ? { + headline: '学习型排盘结果', + subline: '以静态四柱结果承接旧页面的结果层级,不迁移旧排盘引擎。', + pillars: [ + { key: 'year', label: '年柱', value: '庚午' }, + { key: 'month', label: '月柱', value: '戊寅' }, + { key: 'day', label: '日柱', value: '甲辰' }, + { key: 'time', label: '时柱', value: '丁卯' } + ] + } + : null, + primaryActionText: scene === 'result' ? '重新排盘' : '开始排盘', + secondaryActionText: '命理解读' + } +} + +Page({ + data: createMingliBaziPageData('default'), + + onLoad(options) { + this.setData(createMingliBaziPageData(options.scene)) + }, + + handlePrimaryTap() { + this.setData(createMingliBaziPageData(this.data.scene === 'result' ? 'default' : 'result')) + }, + + handleSecondaryTap() { + openStaticRoute(`${ROUTES.mingli.interpret}?scene=result`, wx) + } +}) + +module.exports = { + createMingliBaziPageData +} diff --git a/packages/mingli/pages/bazi/index.json b/packages/mingli/pages/bazi/index.json new file mode 100644 index 0000000..4d7c784 --- /dev/null +++ b/packages/mingli/pages/bazi/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "八字排盘", + "navigationBarBackgroundColor": "#f8f0ee", + "navigationBarTextStyle": "black" +} diff --git a/packages/mingli/pages/bazi/index.wxml b/packages/mingli/pages/bazi/index.wxml new file mode 100644 index 0000000..ac54c2f --- /dev/null +++ b/packages/mingli/pages/bazi/index.wxml @@ -0,0 +1,63 @@ + + + 命理练习台 + {{title}} + + 排盘页当前只保留输入层级、四柱结果和跳转关系,并把阅读节奏整体放大。 + + + 静态录入 + 四柱结果 + 命理解读 + + + + + + 基础信息 + 保留排盘必需字段,用更大的信息卡呈现当前静态示例。 + + + + 姓名 + {{form.name}} + + + 性别 + {{form.gender}} + + + + + 出生日期 + {{form.birthDate}} + + + 出生时间 + {{form.birthTime}} + + + + {{primaryActionText}} + + {{secondaryActionText}} + + + + + + + {{result.headline}} + {{result.subline}} + + + + + {{item.label}} + {{item.value}} + + + + 结果区保留静态展示,可继续进入命理解读页查看后续层级。 + + diff --git a/packages/mingli/pages/bazi/index.wxss b/packages/mingli/pages/bazi/index.wxss new file mode 100644 index 0000000..c4bb0fe --- /dev/null +++ b/packages/mingli/pages/bazi/index.wxss @@ -0,0 +1,194 @@ +page { + min-height: 100%; + background: linear-gradient(180deg, #f9f7f5 0%, #f3ebe8 100%); +} + +.bazi-page { + box-sizing: border-box; + min-height: 100vh; + padding: 36rpx 24rpx 96rpx; +} + +.hero-card, +.form-card, +.result-card { + margin-top: 22rpx; + padding: 34rpx 28rpx; + border: 1rpx solid rgba(139, 59, 49, 0.08); + border-radius: 32rpx; + background: rgba(255, 252, 248, 0.94); + box-shadow: 0 14rpx 34rpx rgba(139, 59, 49, 0.08); +} + +.hero-card { + margin-top: 0; +} + +.hero-card__eyebrow { + display: block; + color: #9f594e; + font-size: 22rpx; + font-weight: 600; + letter-spacing: 6rpx; + line-height: 1.4; +} + +.hero-card__title { + display: block; + margin-top: 14rpx; + color: #2c2621; + font-family: 'STSong', 'Songti SC', serif; + font-size: 46rpx; + font-weight: 700; + line-height: 1.28; +} + +.hero-card__desc { + display: block; + margin-top: 18rpx; + color: #7a6f64; + font-size: 28rpx; + line-height: 1.8; +} + +.hero-card__meta { + margin: 20rpx -6rpx 0; + font-size: 0; +} + +.hero-card__meta-item { + display: inline-block; + margin: 10rpx 6rpx 0; + padding: 10rpx 18rpx; + border-radius: 999rpx; + background: rgba(139, 59, 49, 0.08); + color: #8b3b31; + font-size: 22rpx; + line-height: 1.4; +} + +.panel-header { + margin-bottom: 4rpx; +} + +.panel-header__title { + display: block; + color: #2c2621; + font-family: 'STSong', 'Songti SC', serif; + font-size: 34rpx; + font-weight: 700; + line-height: 1.35; +} + +.panel-header__desc, +.result-card__hint { + display: block; + margin-top: 12rpx; + color: #7a6f64; + font-size: 24rpx; + line-height: 1.7; +} + +.panel-header--result { + margin-bottom: 8rpx; +} + +.field-row { + display: flex; + margin: 0 -8rpx; +} + +.field-block { + box-sizing: border-box; + width: 50%; + padding: 0 8rpx; + margin-top: 20rpx; +} + +.field-block__label { + display: block; + color: #8b5a3c; + font-size: 24rpx; + line-height: 1.5; +} + +.field-block__value { + box-sizing: border-box; + width: 100%; + min-height: 94rpx; + margin-top: 12rpx; + padding: 24rpx 22rpx; + border: 1rpx solid rgba(139, 90, 60, 0.1); + border-radius: 24rpx; + background: linear-gradient(180deg, #fffdfa 0%, #f7f1ec 100%); + color: #5a4335; + font-size: 30rpx; + font-weight: 600; + line-height: 1.4; +} + +.action-group { + margin-top: 26rpx; +} + +.action-button { + margin-top: 18rpx; + padding: 28rpx 24rpx; + border-radius: 24rpx; + background: linear-gradient(135deg, #a64e44 0%, #7a342b 100%); + color: #fff; + font-size: 30rpx; + font-weight: 600; + line-height: 1.2; + text-align: center; +} + +.action-button--ghost { + background: rgba(139, 59, 49, 0.08); + color: #8b3b31; +} + +.result-card__grid { + display: flex; + flex-wrap: wrap; + margin: 18rpx -8rpx 0; +} + +.pillar-card { + box-sizing: border-box; + width: 50%; + padding: 0 8rpx; + margin-top: 16rpx; +} + +.pillar-card__inner { + min-height: 156rpx; + padding: 24rpx 18rpx; + border-radius: 24rpx; + background: linear-gradient(180deg, #fff7f3 0%, #fff 100%); + border: 1rpx solid rgba(139, 59, 49, 0.08); + box-shadow: inset 0 1rpx 0 rgba(255, 255, 255, 0.7); +} + +.pillar-card__label { + display: block; + color: #8b3b31; + font-size: 24rpx; + line-height: 1.4; + text-align: center; +} + +.pillar-card__value { + display: block; + margin-top: 16rpx; + color: #5d312a; + font-family: 'STSong', 'Songti SC', serif; + font-size: 40rpx; + font-weight: 700; + line-height: 1.3; + text-align: center; +} + +.result-card__hint { + margin-top: 24rpx; +} diff --git a/packages/mingli/pages/book-detail/index.js b/packages/mingli/pages/book-detail/index.js new file mode 100644 index 0000000..daa58c6 --- /dev/null +++ b/packages/mingli/pages/book-detail/index.js @@ -0,0 +1,63 @@ +const { resolveScene } = require('../../../../utils/static-ux/shared') +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +const BOOK_SURFACES = Object.freeze({ + 'classic-a': { + coverText: '滴', + title: '滴天髓', + subtitle: '命理经典研习入口', + route: `${ROUTES.mingli.section}?scene=reader-a`, + catalog: ['总论', '天干地支', '格局取法'], + recommends: [{ key: 'classic-b', title: '穷通宝鉴', route: `${ROUTES.mingli.bookDetail}?scene=classic-b` }] + }, + 'classic-b': { + coverText: '穷', + title: '穷通宝鉴', + subtitle: '格局与用神的静态阅读入口', + route: `${ROUTES.mingli.section}?scene=reader-b`, + catalog: ['四时旺衰', '五行喜忌', '命局评析'], + recommends: [{ key: 'classic-a', title: '滴天髓', route: `${ROUTES.mingli.bookDetail}?scene=classic-a` }] + } +}) + +function createMingliBookDetailPageData(rawScene) { + const scene = resolveScene(rawScene, ['classic-a', 'classic-b'], 'classic-a') + const surface = BOOK_SURFACES[scene] + + return { + title: '易学典籍详情', + scene, + coverText: surface.coverText, + book: { + title: surface.title, + subtitle: surface.subtitle + }, + catalog: [...surface.catalog], + primaryRoute: surface.route, + recommends: surface.recommends.map(item => ({ ...item })) + } +} + +function showNavigate(route) { + openStaticRoute(route, wx) +} + +Page({ + data: createMingliBookDetailPageData('classic-a'), + + onLoad(options) { + this.setData(createMingliBookDetailPageData(options.scene)) + }, + + handlePrimaryTap() { + showNavigate(this.data.primaryRoute) + }, + + handleRecommendTap(event) { + showNavigate(event.currentTarget.dataset.route) + } +}) + +module.exports = { + createMingliBookDetailPageData +} diff --git a/packages/mingli/pages/book-detail/index.json b/packages/mingli/pages/book-detail/index.json new file mode 100644 index 0000000..be9b2a2 --- /dev/null +++ b/packages/mingli/pages/book-detail/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "易学典籍详情", + "navigationBarBackgroundColor": "#f8f0ee", + "navigationBarTextStyle": "black" +} diff --git a/packages/mingli/pages/book-detail/index.wxml b/packages/mingli/pages/book-detail/index.wxml new file mode 100644 index 0000000..3243577 --- /dev/null +++ b/packages/mingli/pages/book-detail/index.wxml @@ -0,0 +1,28 @@ + + + {{coverText}} + + {{book.title}} + {{book.subtitle}} + 进入阅读 + + + + + 目录预览 + {{item}} + + + + 相关推荐 + + {{item.title}} + + + diff --git a/packages/mingli/pages/book-detail/index.wxss b/packages/mingli/pages/book-detail/index.wxss new file mode 100644 index 0000000..d5b4ea0 --- /dev/null +++ b/packages/mingli/pages/book-detail/index.wxss @@ -0,0 +1,75 @@ +page { + min-height: 100%; + background: linear-gradient(180deg, #f9f7f5 0%, #f3ebe8 100%); +} + +.mingli-book-page { + box-sizing: border-box; + min-height: 100vh; + padding: 28rpx 20rpx 72rpx; +} + +.hero-card, +.section-card { + margin-top: 18rpx; + padding: 24rpx; + border: 1rpx solid rgba(139, 59, 49, 0.08); + border-radius: 28rpx; + background: rgba(255, 252, 248, 0.94); + box-shadow: 0 10rpx 26rpx rgba(139, 59, 49, 0.06); +} + +.hero-card { + display: flex; + align-items: flex-start; + margin-top: 0; +} + +.hero-card__cover { + width: 110rpx; + height: 150rpx; + border-radius: 22rpx; + background: rgba(139, 59, 49, 0.12); + color: #8b3b31; + font-family: 'STSong', 'Songti SC', serif; + font-size: 38rpx; + font-weight: 700; + line-height: 150rpx; + text-align: center; +} + +.hero-card__body { + flex: 1; + margin-left: 18rpx; +} + +.hero-card__title, +.section-card__title { + display: block; + color: #2c2621; + font-family: 'STSong', 'Songti SC', serif; + font-size: 34rpx; + font-weight: 700; + line-height: 1.3; +} + +.hero-card__subtitle, +.section-card__item { + display: block; + margin-top: 10rpx; + color: #7a6f64; + font-size: 24rpx; + line-height: 1.6; +} + +.hero-card__button, +.section-card__recommend { + margin-top: 16rpx; + padding: 18rpx 22rpx; + border-radius: 20rpx; + background: rgba(139, 59, 49, 0.08); + color: #8b3b31; + font-size: 24rpx; + line-height: 1; + text-align: center; +} diff --git a/packages/mingli/pages/hall/index.js b/packages/mingli/pages/hall/index.js new file mode 100644 index 0000000..c5bfab0 --- /dev/null +++ b/packages/mingli/pages/hall/index.js @@ -0,0 +1,81 @@ +const { createMingliHallPageData: createBaseMingliHallPageData } = require('../../../../utils/static-ux/mingli') +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +function createMingliHallPageData() { + const baseData = createBaseMingliHallPageData() + + return { + ...baseData, + almanac: { + date: '乙巳年 · 宜研习 · 忌浮躁', + ganzhi: '壬寅日 · 辰时', + yi: '宜:开卷、推演 · 忌:断章', + icon: '盘' + }, + wisdomCard: { + text: '知进退存亡,而不失其正者,其唯圣人乎。', + from: '《周易》' + }, + hotTopics: [ + { + key: 'topic-drops', + label: '滴天髓', + route: `${ROUTES.mingli.searchBooks}?keyword=滴天髓` + }, + { + key: 'topic-bazi', + label: '八字', + route: ROUTES.mingli.bazi + }, + { + key: 'topic-interpret', + label: '命理解读', + route: ROUTES.mingli.interpret + } + ], + guideCards: [ + { + key: 'guide-1', + title: '从排盘到解读', + description: '先完成静态排盘,再进入命理解读页承接结果结构。', + route: ROUTES.mingli.bazi + }, + { + key: 'guide-2', + title: '从经典到术语', + description: '从易学典籍页进入静态阅读,再回到问题解释。', + route: `${ROUTES.mingli.bookDetail}?scene=classic-a` + } + ], + recommendedBooks: [ + { + key: 'book-a', + title: '滴天髓', + subtitle: '命理经典研习入口', + route: `${ROUTES.mingli.bookDetail}?scene=classic-a` + }, + { + key: 'book-b', + title: '穷通宝鉴', + subtitle: '格局与用神的静态学习入口', + route: `${ROUTES.mingli.bookDetail}?scene=classic-b` + } + ] + } +} + +function showNavigate(route) { + openStaticRoute(route, wx) +} + +Page({ + data: createMingliHallPageData(), + + handleRouteTap(event) { + showNavigate(event.currentTarget.dataset.route) + } +}) + +module.exports = { + createMingliHallPageData +} diff --git a/packages/mingli/pages/hall/index.json b/packages/mingli/pages/hall/index.json new file mode 100644 index 0000000..cdb8629 --- /dev/null +++ b/packages/mingli/pages/hall/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "易学阁", + "navigationBarBackgroundColor": "#f8f0ee", + "navigationBarTextStyle": "black" +} diff --git a/packages/mingli/pages/hall/index.wxml b/packages/mingli/pages/hall/index.wxml new file mode 100644 index 0000000..20fef1b --- /dev/null +++ b/packages/mingli/pages/hall/index.wxml @@ -0,0 +1,76 @@ + + + + {{almanac.date}} + {{almanac.ganzhi}} + {{almanac.yi}} + + {{almanac.icon}} + + + + + {{item.icon}} + {{item.title}} + {{item.subtitle}} + + + + + 每日一言 + {{wisdomCard.text}} + —— {{wisdomCard.from}} + + + + 搜索热词 + + + {{item.label}} + + + + + + 导读推荐 + + {{item.title}} + {{item.description}} + + + + + 经典研习 + + + + {{item.title}} + {{item.subtitle}} + + + + diff --git a/packages/mingli/pages/hall/index.wxss b/packages/mingli/pages/hall/index.wxss new file mode 100644 index 0000000..18bec5f --- /dev/null +++ b/packages/mingli/pages/hall/index.wxss @@ -0,0 +1,166 @@ +page { + min-height: 100%; + background: linear-gradient(180deg, #f9f7f5 0%, #f3ebe8 100%); +} + +.hall-page { + box-sizing: border-box; + min-height: 100vh; + padding: 28rpx 20rpx 72rpx; +} + +.almanac-card, +.section-card, +.hall-card { + border: 1rpx solid rgba(139, 59, 49, 0.08); + border-radius: 28rpx; + background: rgba(255, 252, 248, 0.94); + box-shadow: 0 10rpx 26rpx rgba(139, 59, 49, 0.06); +} + +.almanac-card { + display: flex; + align-items: center; + justify-content: space-between; + padding: 24rpx; +} + +.almanac-card__date, +.almanac-card__yi, +.section-card__from { + display: block; + color: #7a6f64; + font-size: 22rpx; + line-height: 1.6; +} + +.almanac-card__ganzhi { + display: block; + margin: 8rpx 0; + color: #8b3b31; + font-family: 'STSong', 'Songti SC', serif; + font-size: 34rpx; + font-weight: 700; + line-height: 1.3; +} + +.almanac-card__icon { + color: #8b3b31; + font-size: 46rpx; +} + +.hall-grid { + display: flex; + flex-wrap: wrap; + margin: 12rpx -6rpx 0; +} + +.hall-card { + box-sizing: border-box; + width: 50%; + margin-top: 12rpx; + padding: 24rpx 18rpx; + background: #fff; + border-radius: 24rpx; + margin-left: 6rpx; + margin-right: 6rpx; +} + +.hall-card__icon { + width: 82rpx; + height: 82rpx; + border-radius: 20rpx; + background: rgba(139, 59, 49, 0.08); + color: #8b3b31; + font-size: 34rpx; + line-height: 82rpx; + text-align: center; +} + +.hall-card__title, +.section-card__title, +.guide-card__title, +.book-row__title { + display: block; + color: #2c2621; + font-family: 'STSong', 'Songti SC', serif; + font-size: 32rpx; + font-weight: 700; + line-height: 1.3; +} + +.hall-card__title { + margin-top: 16rpx; +} + +.hall-card__subtitle, +.guide-card__desc, +.book-row__subtitle, +.section-card__text { + display: block; + margin-top: 8rpx; + color: #7a6f64; + font-size: 24rpx; + line-height: 1.6; +} + +.section-card { + margin-top: 18rpx; + padding: 24rpx; +} + +.section-card__text { + margin-top: 14rpx; + font-size: 30rpx; + line-height: 1.8; + color: #352f29; +} + +.chips-row { + margin: 14rpx -6rpx 0; +} + +.chips-row__item { + display: inline-block; + margin: 6rpx; + padding: 12rpx 18rpx; + border-radius: 999rpx; + background: rgba(139, 59, 49, 0.08); + color: #8b3b31; + font-size: 22rpx; + line-height: 1; +} + +.guide-card, +.book-row { + margin-top: 16rpx; + padding: 20rpx 0 0; + border-top: 1rpx solid rgba(139, 59, 49, 0.08); +} + +.guide-card:first-of-type, +.book-row:first-of-type { + padding-top: 16rpx; + border-top: 0; +} + +.book-row { + display: flex; + align-items: center; +} + +.book-row__cover { + width: 72rpx; + height: 96rpx; + border-radius: 18rpx; + background: rgba(139, 59, 49, 0.1); + color: #8b3b31; + font-size: 28rpx; + line-height: 96rpx; + text-align: center; +} + +.book-row__body { + flex: 1; + margin-left: 16rpx; +} diff --git a/packages/mingli/pages/interpret/index.js b/packages/mingli/pages/interpret/index.js new file mode 100644 index 0000000..2b685eb --- /dev/null +++ b/packages/mingli/pages/interpret/index.js @@ -0,0 +1,42 @@ +const { resolveScene } = require('../../../../utils/static-ux/shared') +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +function createMingliInterpretPageData(rawScene) { + const scene = resolveScene(rawScene, ['default', 'result'], 'default') + + return { + title: '命理解读', + scene, + contextText: '围绕命理问题或盘面结果,保留一个学习型解释区块。', + result: + scene === 'result' + ? { + title: '学习型命理解读', + summary: '当前静态结果围绕“甲木日主”的基本气象来展示结果版式和引用层级。', + references: ['《滴天髓》重视日主气势', '先看时令,再看格局与用神'] + } + : null, + primaryActionText: scene === 'result' ? '重新解读' : '提交解读', + secondaryActionText: '查看排盘' + } +} + +Page({ + data: createMingliInterpretPageData('default'), + + onLoad(options) { + this.setData(createMingliInterpretPageData(options.scene)) + }, + + handlePrimaryTap() { + this.setData(createMingliInterpretPageData(this.data.scene === 'result' ? 'default' : 'result')) + }, + + handleSecondaryTap() { + openStaticRoute(`${ROUTES.mingli.bazi}?scene=result`, wx) + } +}) + +module.exports = { + createMingliInterpretPageData +} diff --git a/packages/mingli/pages/interpret/index.json b/packages/mingli/pages/interpret/index.json new file mode 100644 index 0000000..daf5567 --- /dev/null +++ b/packages/mingli/pages/interpret/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "命理解读", + "navigationBarBackgroundColor": "#f8f0ee", + "navigationBarTextStyle": "black" +} diff --git a/packages/mingli/pages/interpret/index.wxml b/packages/mingli/pages/interpret/index.wxml new file mode 100644 index 0000000..5e7c75d --- /dev/null +++ b/packages/mingli/pages/interpret/index.wxml @@ -0,0 +1,24 @@ + + + {{title}} + {{contextText}} + + + + + + {{primaryActionText}} + + {{secondaryActionText}} + + + + + {{result.title}} + {{result.summary}} + + · + {{item}} + + + diff --git a/packages/mingli/pages/interpret/index.wxss b/packages/mingli/pages/interpret/index.wxss new file mode 100644 index 0000000..62d7795 --- /dev/null +++ b/packages/mingli/pages/interpret/index.wxss @@ -0,0 +1,91 @@ +page { + min-height: 100%; + background: linear-gradient(180deg, #f9f7f5 0%, #f3ebe8 100%); +} + +.interpret-page { + box-sizing: border-box; + min-height: 100vh; + padding: 28rpx 20rpx 72rpx; +} + +.hero-card, +.form-card, +.result-card { + margin-top: 18rpx; + padding: 24rpx; + border: 1rpx solid rgba(139, 59, 49, 0.08); + border-radius: 28rpx; + background: rgba(255, 252, 248, 0.94); + box-shadow: 0 10rpx 26rpx rgba(139, 59, 49, 0.06); +} + +.hero-card { + margin-top: 0; +} + +.hero-card__title, +.result-card__title { + display: block; + color: #2c2621; + font-family: 'STSong', 'Songti SC', serif; + font-size: 36rpx; + font-weight: 700; + line-height: 1.3; +} + +.hero-card__desc, +.result-card__desc, +.reference-item__text { + display: block; + margin-top: 10rpx; + color: #7a6f64; + font-size: 24rpx; + line-height: 1.7; +} + +.form-card__textarea, +.form-card__input { + box-sizing: border-box; + width: 100%; + padding: 18rpx 20rpx; + border: 1rpx solid rgba(139, 90, 60, 0.12); + border-radius: 18rpx; + background: #fff; + color: #5a4335; + font-size: 24rpx; + line-height: 1.6; +} + +.form-card__input { + margin-top: 12rpx; +} + +.action-button { + margin-top: 16rpx; + padding: 22rpx 24rpx; + border-radius: 22rpx; + background: linear-gradient(135deg, #a64e44 0%, #7a342b 100%); + color: #fff; + font-size: 26rpx; + line-height: 1; + text-align: center; +} + +.action-button--ghost { + background: rgba(139, 59, 49, 0.08); + color: #8b3b31; +} + +.reference-item { + display: flex; + align-items: flex-start; + margin-top: 10rpx; +} + +.reference-item__dot { + margin-right: 10rpx; + color: #8b3b31; + font-size: 26rpx; + line-height: 1.6; +} diff --git a/packages/mingli/pages/search-books/index.js b/packages/mingli/pages/search-books/index.js new file mode 100644 index 0000000..e9ed77e --- /dev/null +++ b/packages/mingli/pages/search-books/index.js @@ -0,0 +1,61 @@ +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +const SEARCH_CATALOG = Object.freeze([ + { + key: 'classic-a', + title: '滴天髓', + subtitle: '命理经典结果', + aliases: ['滴天', '天髓'], + route: `${ROUTES.mingli.bookDetail}?scene=classic-a` + }, + { + key: 'classic-b', + title: '穷通宝鉴', + subtitle: '格局与用神', + aliases: ['穷通', '宝鉴'], + route: `${ROUTES.mingli.bookDetail}?scene=classic-b` + } +]) + +function createMingliSearchBooksPageData(keyword) { + const normalizedKeyword = (keyword || '').trim() + const results = normalizedKeyword + ? SEARCH_CATALOG.filter(item => { + return ( + item.title.includes(normalizedKeyword) || + item.aliases.some(alias => alias.includes(normalizedKeyword)) + ) + }).map(item => ({ ...item })) + : [] + + return { + title: '搜索易学典籍', + keyword: normalizedKeyword, + history: ['滴天髓', '穷通宝鉴', '子平真诠'], + results + } +} + +function showNavigate(route) { + openStaticRoute(route, wx) +} + +Page({ + data: createMingliSearchBooksPageData(''), + + onLoad(options) { + this.setData(createMingliSearchBooksPageData(options.keyword || options.q)) + }, + + handleHistoryTap(event) { + this.setData(createMingliSearchBooksPageData(event.currentTarget.dataset.keyword)) + }, + + handleResultTap(event) { + showNavigate(event.currentTarget.dataset.route) + } +}) + +module.exports = { + createMingliSearchBooksPageData +} diff --git a/packages/mingli/pages/search-books/index.json b/packages/mingli/pages/search-books/index.json new file mode 100644 index 0000000..452401d --- /dev/null +++ b/packages/mingli/pages/search-books/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "搜索易学典籍", + "navigationBarBackgroundColor": "#f8f0ee", + "navigationBarTextStyle": "black" +} diff --git a/packages/mingli/pages/search-books/index.wxml b/packages/mingli/pages/search-books/index.wxml new file mode 100644 index 0000000..7a1cdff --- /dev/null +++ b/packages/mingli/pages/search-books/index.wxml @@ -0,0 +1,21 @@ + + + {{title}} + + {{item}} + + + + + 搜索结果 + + {{item.title}} · {{item.subtitle}} + + + diff --git a/packages/mingli/pages/search-books/index.wxss b/packages/mingli/pages/search-books/index.wxss new file mode 100644 index 0000000..73cfa8d --- /dev/null +++ b/packages/mingli/pages/search-books/index.wxss @@ -0,0 +1,43 @@ +page { + min-height: 100%; + background: linear-gradient(180deg, #f9f7f5 0%, #f3ebe8 100%); +} + +.mingli-search-page { + box-sizing: border-box; + min-height: 100vh; + padding: 28rpx 20rpx 72rpx; +} + +.section-card { + margin-top: 18rpx; + padding: 24rpx; + border: 1rpx solid rgba(139, 59, 49, 0.08); + border-radius: 28rpx; + background: rgba(255, 252, 248, 0.94); + box-shadow: 0 10rpx 26rpx rgba(139, 59, 49, 0.06); +} + +.section-card:first-child { + margin-top: 0; +} + +.section-card__title { + display: block; + color: #2c2621; + font-family: 'STSong', 'Songti SC', serif; + font-size: 34rpx; + font-weight: 700; + line-height: 1.3; +} + +.section-card__item { + display: block; + margin-top: 14rpx; + padding: 18rpx 20rpx; + border-radius: 20rpx; + background: rgba(139, 59, 49, 0.08); + color: #8b3b31; + font-size: 24rpx; + line-height: 1.6; +} diff --git a/packages/mingli/pages/section/index.js b/packages/mingli/pages/section/index.js new file mode 100644 index 0000000..c52a2db --- /dev/null +++ b/packages/mingli/pages/section/index.js @@ -0,0 +1,57 @@ +const { resolveScene } = require('../../../../utils/static-ux/shared') +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +const READER_SURFACES = Object.freeze({ + 'reader-a': { + title: '滴天髓 · 总论', + passages: ['欲识三元万法宗,先观帝载与神功。', '气机流转之间,先看格局成败。'] + }, + 'reader-b': { + title: '穷通宝鉴 · 四时旺衰', + passages: ['论命之法,首重月令。', '得时得地者旺,失时失地者衰。'] + } +}) + +function createMingliSectionPageData(rawScene) { + const scene = resolveScene(rawScene, ['reader-a', 'reader-b'], 'reader-a') + const surface = READER_SURFACES[scene] + + return { + title: '易学阅读', + scene, + chapterTitle: surface.title, + passages: [...surface.passages], + actions: [ + { + key: 'interpret', + title: '打开命理解读', + route: ROUTES.mingli.interpret + }, + { + key: 'hall', + title: '返回易学阁', + route: ROUTES.mingli.hall + } + ] + } +} + +function showNavigate(route) { + openStaticRoute(route, wx) +} + +Page({ + data: createMingliSectionPageData('reader-a'), + + onLoad(options) { + this.setData(createMingliSectionPageData(options.scene)) + }, + + handleActionTap(event) { + showNavigate(event.currentTarget.dataset.route) + } +}) + +module.exports = { + createMingliSectionPageData +} diff --git a/packages/mingli/pages/section/index.json b/packages/mingli/pages/section/index.json new file mode 100644 index 0000000..03b5552 --- /dev/null +++ b/packages/mingli/pages/section/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "易学阅读", + "navigationBarBackgroundColor": "#f8f0ee", + "navigationBarTextStyle": "black" +} diff --git a/packages/mingli/pages/section/index.wxml b/packages/mingli/pages/section/index.wxml new file mode 100644 index 0000000..46cb46b --- /dev/null +++ b/packages/mingli/pages/section/index.wxml @@ -0,0 +1,19 @@ + + + {{chapterTitle}} + + + + {{item}} + + + + {{item.title}} + + diff --git a/packages/mingli/pages/section/index.wxss b/packages/mingli/pages/section/index.wxss new file mode 100644 index 0000000..017cad7 --- /dev/null +++ b/packages/mingli/pages/section/index.wxss @@ -0,0 +1,56 @@ +page { + min-height: 100%; + background: linear-gradient(180deg, #f9f7f5 0%, #f3ebe8 100%); +} + +.mingli-section-page { + box-sizing: border-box; + min-height: 100vh; + padding: 28rpx 20rpx 72rpx; +} + +.hero-card, +.passage-card { + margin-top: 18rpx; + padding: 24rpx; + border: 1rpx solid rgba(139, 59, 49, 0.08); + border-radius: 28rpx; + background: rgba(255, 252, 248, 0.94); + box-shadow: 0 10rpx 26rpx rgba(139, 59, 49, 0.06); +} + +.hero-card { + margin-top: 0; +} + +.hero-card__title { + display: block; + color: #2c2621; + font-family: 'STSong', 'Songti SC', serif; + font-size: 34rpx; + font-weight: 700; + line-height: 1.3; +} + +.passage-card__item { + display: block; + margin-top: 16rpx; + color: #453730; + font-size: 28rpx; + line-height: 1.8; +} + +.passage-card__item:first-child { + margin-top: 0; +} + +.action-button { + margin-top: 16rpx; + padding: 22rpx 24rpx; + border-radius: 22rpx; + background: rgba(139, 59, 49, 0.08); + color: #8b3b31; + font-size: 26rpx; + line-height: 1; + text-align: center; +} diff --git a/packages/tcm/pages/ai-history/index.js b/packages/tcm/pages/ai-history/index.js new file mode 100644 index 0000000..b335f67 --- /dev/null +++ b/packages/tcm/pages/ai-history/index.js @@ -0,0 +1,80 @@ +const { resolveScene } = require('../../../../utils/static-ux/shared') +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +const HISTORY_GROUPS = Object.freeze([ + { + key: 'today', + label: '今天', + items: [ + { + key: 'qa-1', + tag: 'AI答疑', + title: '什么是阴阳?', + summary: '从基础概念切回到静态 AI 答疑面板。', + route: ROUTES.tabs.ai + }, + { + key: 'analysis-1', + tag: '辨证分析', + title: '脾虚湿困的学习型分析', + summary: '查看静态辨证结果展示页。', + route: `${ROUTES.tcm.bianzheng}?scene=result` + } + ] + }, + { + key: 'week', + label: '近七天', + items: [ + { + key: 'qa-2', + tag: 'AI答疑', + title: '肝主疏泄如何理解?', + summary: '保留历史列表样式,不保留旧问答记录模型。', + route: ROUTES.tabs.ai + } + ] + } +]) + +function cloneGroups(groups) { + return groups.map(group => ({ + ...group, + items: group.items.map(item => ({ ...item })) + })) +} + +function createTcmAiHistoryPageData(rawScene) { + const scene = resolveScene(rawScene, ['default', 'empty'], 'default') + + return { + title: 'AI对话历史', + scene, + emptyTitle: '还没有 AI 记录', + emptyDescription: '去 AI 页先完成一次答疑或辨证分析。', + actionText: '返回 AI', + groups: scene === 'empty' ? [] : cloneGroups(HISTORY_GROUPS) + } +} + +Page({ + data: createTcmAiHistoryPageData('default'), + + onLoad(options) { + this.setData(createTcmAiHistoryPageData(options.scene)) + }, + + handlePrimaryTap() { + openStaticRoute(ROUTES.tabs.ai, wx) + }, + + handleHistoryTap(event) { + const { route } = event.currentTarget.dataset + + openStaticRoute(route, wx) + } +}) + +module.exports = { + createTcmAiHistoryPageData +} diff --git a/packages/tcm/pages/ai-history/index.json b/packages/tcm/pages/ai-history/index.json new file mode 100644 index 0000000..121c905 --- /dev/null +++ b/packages/tcm/pages/ai-history/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "AI对话历史", + "navigationBarBackgroundColor": "#f8ecd8", + "navigationBarTextStyle": "black" +} diff --git a/packages/tcm/pages/ai-history/index.wxml b/packages/tcm/pages/ai-history/index.wxml new file mode 100644 index 0000000..0447eaf --- /dev/null +++ b/packages/tcm/pages/ai-history/index.wxml @@ -0,0 +1,27 @@ + + {{title}} + + + {{emptyTitle}} + {{emptyDescription}} + {{actionText}} + + + + + {{item.label}} + + {{historyItem.tag}} + {{historyItem.title}} + {{historyItem.summary}} + + + + diff --git a/packages/tcm/pages/ai-history/index.wxss b/packages/tcm/pages/ai-history/index.wxss new file mode 100644 index 0000000..0bbf312 --- /dev/null +++ b/packages/tcm/pages/ai-history/index.wxss @@ -0,0 +1,82 @@ +page { + min-height: 100%; + background: linear-gradient(180deg, #faf3e8 0%, #f1e9dd 100%); +} + +.ai-history-page { + box-sizing: border-box; + min-height: 100vh; + padding: 28rpx 20rpx 72rpx; +} + +.ai-history-page__title { + display: block; + color: #2f1f12; + font-family: 'STSong', 'Songti SC', serif; + font-size: 56rpx; + font-weight: 700; + line-height: 1.2; +} + +.empty-card, +.history-group { + margin-top: 18rpx; + padding: 26rpx; + border: 1rpx solid rgba(118, 83, 42, 0.08); + border-radius: 32rpx; + background: rgba(255, 250, 242, 0.92); + box-shadow: 0 18rpx 42rpx rgba(86, 58, 25, 0.08); +} + +.empty-card__title, +.history-group__label, +.history-item__title { + display: block; + color: #2c2419; + font-family: 'STSong', 'Songti SC', serif; + font-size: 34rpx; + font-weight: 700; + line-height: 1.35; +} + +.empty-card__description, +.history-item__description { + display: block; + margin-top: 10rpx; + color: #7c705e; + font-size: 26rpx; + line-height: 1.7; +} + +.empty-card__action { + display: inline-block; + margin-top: 20rpx; + padding: 18rpx 24rpx; + border-radius: 999rpx; + background: linear-gradient(135deg, #9e652f 0%, #75441a 100%); + color: #fff7eb; + font-size: 26rpx; + line-height: 1; +} + +.history-item { + margin-top: 14rpx; + padding: 22rpx; + border-radius: 24rpx; + background: rgba(255, 254, 250, 0.94); + border: 1rpx solid rgba(118, 83, 42, 0.06); +} + +.history-item__tag { + display: inline-block; + padding: 8rpx 14rpx; + border-radius: 999rpx; + background: rgba(111, 66, 22, 0.08); + color: #6f4216; + font-size: 22rpx; + line-height: 1; +} + +.history-item__title { + margin-top: 12rpx; +} diff --git a/packages/tcm/pages/assets/index.js b/packages/tcm/pages/assets/index.js new file mode 100644 index 0000000..b8f4af7 --- /dev/null +++ b/packages/tcm/pages/assets/index.js @@ -0,0 +1,153 @@ +const { createTcmAssetPageData } = require('../../../../utils/static-ux/tcm') +const { resolveKind } = require('../../../../utils/static-ux/shared') +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +const ASSET_KIND_LABELS = Object.freeze({ + notes: '笔记', + bookshelf: '书架', + favorites: '收藏', + history: '历史' +}) + +const ASSET_ITEMS = Object.freeze({ + notes: [ + { + key: 'note-1', + title: '阴阳学习摘记', + subtitle: '来自《黄帝内经素问》静态演示卡片', + description: '把阴阳作为纲领来理解脏腑、经络与病机的对应关系。', + route: `${ROUTES.tcm.bookDetail}?scene=classic-a` + }, + { + key: 'note-2', + title: '脾虚湿困辨证提要', + subtitle: '辨证分析里的高频主题', + description: '先看脾运失健,再看湿困中焦的症状组合。', + route: `${ROUTES.tcm.bianzheng}?scene=result` + } + ], + bookshelf: [ + { + key: 'book-1', + title: '黄帝内经素问', + subtitle: '已加入静态书架', + description: '继续阅读:上古天真论', + route: `${ROUTES.tcm.bookDetail}?scene=classic-a` + }, + { + key: 'book-2', + title: '伤寒论', + subtitle: '已加入静态书架', + description: '继续阅读:太阳病篇', + route: `${ROUTES.tcm.bookDetail}?scene=classic-b` + } + ], + favorites: [ + { + key: 'favorite-1', + title: '经络总览卡片', + subtitle: '已收藏条目', + description: '保留为静态收藏示例,后续再接新的收藏体系。', + route: `${ROUTES.tcm.placeholder}?kind=about` + }, + { + key: 'favorite-2', + title: '命理解读入口', + subtitle: '跨域收藏示例', + description: '当前用于展示从中医域跳到命理域的 UI 连接。', + route: ROUTES.mingli.interpret + } + ], + history: [ + { + key: 'history-1', + title: 'AI答疑: 什么是气虚?', + subtitle: '最近浏览', + description: '返回 AI 页查看静态问答入口。', + route: ROUTES.tabs.ai + }, + { + key: 'history-2', + title: '典籍阅读: 上古天真论', + subtitle: '最近阅读', + description: '回到典籍阅读页继续浏览。', + route: `${ROUTES.tcm.section}?scene=reader-a` + } + ] +}) + +const ASSET_EMPTY_COPY = Object.freeze({ + notes: { + title: '还没有学习笔记', + description: '后续接入新后端后,这里会汇总你的静态摘录与标注。' + }, + bookshelf: { + title: '书架还是空的', + description: '可以先从典籍页进入静态详情,再决定如何组织新的书架逻辑。' + }, + favorites: { + title: '还没有收藏内容', + description: '本轮只保留收藏区块的 UI 结构,不迁移旧收藏模型。' + }, + history: { + title: '还没有浏览记录', + description: '继续浏览典籍、AI 或易学页后,后续可在这里接入新的记录源。' + } +}) + +function cloneItems(items) { + return items.map(item => ({ ...item })) +} + +function createFilterItems(kinds) { + return kinds.map(kind => ({ + key: kind, + label: ASSET_KIND_LABELS[kind], + route: `${ROUTES.tcm.assets}?kind=${kind}` + })) +} + +function createTcmAssetsPageData(rawKind) { + const baseData = createTcmAssetPageData(rawKind) + const items = cloneItems(ASSET_ITEMS[baseData.activeKind] || []) + const emptyCopy = ASSET_EMPTY_COPY[baseData.activeKind] + + return { + title: baseData.title, + activeKind: baseData.activeKind, + filterItems: createFilterItems(baseData.kinds), + items, + emptyTitle: emptyCopy.title, + emptyDescription: emptyCopy.description + } +} + +function showNavigate(route) { + openStaticRoute(route, wx) +} + +Page({ + data: createTcmAssetsPageData('notes'), + + onLoad(options) { + this.setData( + createTcmAssetsPageData( + resolveKind(options.kind, ['notes', 'bookshelf', 'favorites', 'history'], 'notes') + ) + ) + }, + + handleFilterTap(event) { + const { kind } = event.currentTarget.dataset + + this.setData(createTcmAssetsPageData(kind)) + }, + + handleEntryTap(event) { + showNavigate(event.currentTarget.dataset.route) + } +}) + +module.exports = { + createTcmAssetsPageData +} diff --git a/packages/tcm/pages/assets/index.json b/packages/tcm/pages/assets/index.json new file mode 100644 index 0000000..aaf8a18 --- /dev/null +++ b/packages/tcm/pages/assets/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "学习资产", + "navigationBarBackgroundColor": "#f8ecd8", + "navigationBarTextStyle": "black" +} diff --git a/packages/tcm/pages/assets/index.wxml b/packages/tcm/pages/assets/index.wxml new file mode 100644 index 0000000..fbbca41 --- /dev/null +++ b/packages/tcm/pages/assets/index.wxml @@ -0,0 +1,36 @@ + + + {{title}} + + + + + {{item.label}} + + + + + + {{item.title}} + {{item.subtitle}} + {{item.description}} + + + + + {{emptyTitle}} + {{emptyDescription}} + + diff --git a/packages/tcm/pages/assets/index.wxss b/packages/tcm/pages/assets/index.wxss new file mode 100644 index 0000000..ef30a57 --- /dev/null +++ b/packages/tcm/pages/assets/index.wxss @@ -0,0 +1,80 @@ +page { + min-height: 100%; + background: linear-gradient(180deg, #faf3e8 0%, #f1e9dd 100%); +} + +.asset-page { + box-sizing: border-box; + min-height: 100vh; + padding: 28rpx 20rpx 72rpx; + background: + radial-gradient(circle at top right, rgba(177, 130, 74, 0.14) 0%, rgba(177, 130, 74, 0) 24%), + linear-gradient(135deg, rgba(255, 255, 255, 0.54) 0%, rgba(255, 249, 240, 0) 38%); +} + +.asset-page__header { + padding: 8rpx 0 22rpx; +} + +.asset-page__title { + display: block; + color: #2f1f12; + font-family: 'STSong', 'Songti SC', serif; + font-size: 56rpx; + font-weight: 700; + line-height: 1.2; +} + +.asset-page__filters { + margin: 0 -6rpx 14rpx; +} + +.asset-page__filter { + display: inline-block; + padding: 6rpx; +} + +.asset-page__filter-label { + display: block; + padding: 14rpx 20rpx; + border-radius: 999rpx; + background: rgba(111, 66, 22, 0.08); + color: #6f4216; + font-size: 24rpx; + line-height: 1; +} + +.asset-page__filter--active .asset-page__filter-label { + background: linear-gradient(135deg, #a56a31 0%, #7c4b1d 100%); + color: #fff7eb; +} + +.asset-card, +.asset-page__empty { + margin-top: 16rpx; + padding: 26rpx; + border: 1rpx solid rgba(118, 83, 42, 0.08); + border-radius: 32rpx; + background: rgba(255, 250, 242, 0.92); + box-shadow: 0 18rpx 42rpx rgba(86, 58, 25, 0.08); +} + +.asset-card__title, +.asset-page__empty-title { + display: block; + color: #2c2419; + font-family: 'STSong', 'Songti SC', serif; + font-size: 34rpx; + font-weight: 700; + line-height: 1.35; +} + +.asset-card__subtitle, +.asset-card__description, +.asset-page__empty-description { + display: block; + margin-top: 10rpx; + color: #7c705e; + font-size: 26rpx; + line-height: 1.7; +} diff --git a/packages/tcm/pages/bianzheng/index.js b/packages/tcm/pages/bianzheng/index.js new file mode 100644 index 0000000..3652fc4 --- /dev/null +++ b/packages/tcm/pages/bianzheng/index.js @@ -0,0 +1,50 @@ +const { resolveScene } = require('../../../../utils/static-ux/shared') +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +function createTcmBianzhengPageData(rawScene) { + const scene = resolveScene(rawScene, ['default', 'result'], 'default') + + return { + title: '辨证分析', + scene, + eyebrow: 'AI 辨证分析', + intro: '把症状整理成结构化输入,再输出学习型辨证结果。', + fields: [ + { key: 'mainSymptoms', label: '核心症状', placeholder: '主要症状,用逗号分隔' }, + { key: 'tongue', label: '舌象', placeholder: '舌象' }, + { key: 'pulse', label: '脉象', placeholder: '脉象' }, + { key: 'constitution', label: '体质', placeholder: '体质' }, + { key: 'duration', label: '病程', placeholder: '病程' } + ], + result: + scene === 'result' + ? { + title: '学习型辨证结果', + summary: '当前静态结果以“脾虚湿困”为例,用于承接老页面的信息层级和结果区块。', + references: ['《素问》重视脾胃运化', '症见困倦乏力、纳呆便溏可作为学习型线索'] + } + : null, + primaryActionText: scene === 'result' ? '重新整理症状' : '提交辨证分析', + secondaryActionText: '返回 AI' + } +} + +Page({ + data: createTcmBianzhengPageData('default'), + + onLoad(options) { + this.setData(createTcmBianzhengPageData(options.scene)) + }, + + handlePrimaryTap() { + this.setData(createTcmBianzhengPageData(this.data.scene === 'result' ? 'default' : 'result')) + }, + + handleSecondaryTap() { + openStaticRoute(ROUTES.tabs.ai, wx) + } +}) + +module.exports = { + createTcmBianzhengPageData +} diff --git a/packages/tcm/pages/bianzheng/index.json b/packages/tcm/pages/bianzheng/index.json new file mode 100644 index 0000000..b0f4ca1 --- /dev/null +++ b/packages/tcm/pages/bianzheng/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "辨证分析", + "navigationBarBackgroundColor": "#f8ecd8", + "navigationBarTextStyle": "black" +} diff --git a/packages/tcm/pages/bianzheng/index.wxml b/packages/tcm/pages/bianzheng/index.wxml new file mode 100644 index 0000000..ac1f56b --- /dev/null +++ b/packages/tcm/pages/bianzheng/index.wxml @@ -0,0 +1,30 @@ + + + {{eyebrow}} + {{title}} + {{intro}} + + + + + {{item.label}} + + + + + {{primaryActionText}} + + {{secondaryActionText}} + + + + + + {{result.title}} + {{result.summary}} + + · + {{item}} + + + diff --git a/packages/tcm/pages/bianzheng/index.wxss b/packages/tcm/pages/bianzheng/index.wxss new file mode 100644 index 0000000..74aebb5 --- /dev/null +++ b/packages/tcm/pages/bianzheng/index.wxss @@ -0,0 +1,120 @@ +page { + min-height: 100%; + background: linear-gradient(180deg, #faf3e8 0%, #f1e9dd 100%); +} + +.bianzheng-page { + box-sizing: border-box; + min-height: 100vh; + padding: 28rpx 20rpx 72rpx; +} + +.hero-card, +.form-card, +.result-card { + margin-top: 18rpx; + padding: 26rpx; + border: 1rpx solid rgba(118, 83, 42, 0.08); + border-radius: 32rpx; + background: rgba(255, 250, 242, 0.92); + box-shadow: 0 18rpx 42rpx rgba(86, 58, 25, 0.08); +} + +.hero-card { + margin-top: 0; +} + +.hero-card__eyebrow { + display: inline-block; + padding: 8rpx 14rpx; + border-radius: 999rpx; + background: rgba(111, 66, 22, 0.08); + color: #6f4216; + font-size: 22rpx; + line-height: 1; +} + +.hero-card__title, +.result-card__title { + display: block; + margin-top: 18rpx; + color: #2c2419; + font-family: 'STSong', 'Songti SC', serif; + font-size: 38rpx; + font-weight: 700; + line-height: 1.3; +} + +.hero-card__description, +.result-card__summary, +.result-card__reference-text { + display: block; + margin-top: 12rpx; + color: #7c705e; + font-size: 26rpx; + line-height: 1.75; +} + +.field-block { + margin-top: 16rpx; +} + +.field-block:first-child { + margin-top: 0; +} + +.field-block__label { + display: block; + color: #6f4b2d; + font-size: 24rpx; + line-height: 1.5; +} + +.field-block__input { + box-sizing: border-box; + width: 100%; + margin-top: 10rpx; + padding: 18rpx 20rpx; + border: 1rpx solid rgba(199, 171, 133, 0.5); + border-radius: 22rpx; + background: rgba(255, 254, 250, 0.92); + color: #8f6842; + font-size: 26rpx; + line-height: 1.5; +} + +.form-card__actions { + margin-top: 22rpx; +} + +.form-card__button { + padding: 20rpx 24rpx; + border-radius: 24rpx; + background: linear-gradient(135deg, #9e652f 0%, #75441a 100%); + color: #fff7eb; + font-size: 28rpx; + line-height: 1; + text-align: center; +} + +.form-card__button + .form-card__button { + margin-top: 12rpx; +} + +.form-card__button--ghost { + background: rgba(111, 66, 22, 0.08); + color: #6f4216; +} + +.result-card__reference { + display: flex; + align-items: flex-start; + margin-top: 10rpx; +} + +.result-card__reference-dot { + margin-right: 10rpx; + color: #9a622d; + font-size: 28rpx; + line-height: 1.6; +} diff --git a/packages/tcm/pages/book-detail/index.js b/packages/tcm/pages/book-detail/index.js new file mode 100644 index 0000000..8707c9e --- /dev/null +++ b/packages/tcm/pages/book-detail/index.js @@ -0,0 +1,125 @@ +const { resolveScene } = require('../../../../utils/static-ux/shared') +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +const BOOK_DETAIL_SURFACES = Object.freeze({ + 'classic-a': { + coverText: '黄', + title: '黄帝内经素问', + subtitle: '传世中医典籍 · 学习阅读入口', + tags: ['经典', '入门'], + description: '当前典籍详情页只保留封面、简介、目录和推荐区块,不迁移旧项目的详情接口。', + progressText: '已读到:上古天真论', + primaryRoute: `${ROUTES.tcm.section}?scene=reader-a`, + catalog: [ + { + key: 'chapter-1', + title: '上古天真论', + route: `${ROUTES.tcm.section}?scene=reader-a`, + children: ['节录一', '节录二'] + }, + { + key: 'chapter-2', + title: '四气调神大论', + route: `${ROUTES.tcm.section}?scene=reader-a`, + children: ['节录一', '节录二'] + } + ], + recommends: [ + { + key: 'recommend-b', + title: '伤寒论', + route: `${ROUTES.tcm.bookDetail}?scene=classic-b` + } + ] + }, + 'classic-b': { + coverText: '伤', + title: '伤寒论', + subtitle: '经方经典 · 学习阅读入口', + tags: ['经方', '进阶'], + description: '静态详情页保留目录结构和推荐卡片,为后续新数据层留出清晰接口边界。', + progressText: '已读到:太阳病篇', + primaryRoute: `${ROUTES.tcm.section}?scene=reader-b`, + catalog: [ + { + key: 'chapter-1', + title: '太阳病篇', + route: `${ROUTES.tcm.section}?scene=reader-b`, + children: ['条文一', '条文二'] + }, + { + key: 'chapter-2', + title: '阳明病篇', + route: `${ROUTES.tcm.section}?scene=reader-b`, + children: ['条文一', '条文二'] + } + ], + recommends: [ + { + key: 'recommend-a', + title: '黄帝内经素问', + route: `${ROUTES.tcm.bookDetail}?scene=classic-a` + } + ] + } +}) + +function cloneCatalog(items) { + return items.map(item => ({ + ...item, + children: [...item.children] + })) +} + +function cloneItems(items) { + return items.map(item => ({ ...item })) +} + +function createTcmBookDetailPageData(rawScene) { + const scene = resolveScene(rawScene, ['classic-a', 'classic-b'], 'classic-a') + const surface = BOOK_DETAIL_SURFACES[scene] + + return { + title: '典籍详情', + scene, + coverText: surface.coverText, + book: { + title: surface.title, + subtitle: surface.subtitle + }, + tags: [...surface.tags], + description: surface.description, + progressText: surface.progressText, + primaryRoute: surface.primaryRoute, + catalog: cloneCatalog(surface.catalog), + recommends: cloneItems(surface.recommends) + } +} + +function showNavigate(route) { + openStaticRoute(route, wx) +} + +Page({ + data: createTcmBookDetailPageData('classic-a'), + + onLoad(options) { + this.setData(createTcmBookDetailPageData(options.scene)) + }, + + handlePrimaryTap() { + showNavigate(this.data.primaryRoute) + }, + + handleCatalogTap(event) { + showNavigate(event.currentTarget.dataset.route) + }, + + handleRecommendTap(event) { + showNavigate(event.currentTarget.dataset.route) + } +}) + +module.exports = { + createTcmBookDetailPageData +} diff --git a/packages/tcm/pages/book-detail/index.json b/packages/tcm/pages/book-detail/index.json new file mode 100644 index 0000000..10efc9d --- /dev/null +++ b/packages/tcm/pages/book-detail/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "典籍详情", + "navigationBarBackgroundColor": "#f8ecd8", + "navigationBarTextStyle": "black" +} diff --git a/packages/tcm/pages/book-detail/index.wxml b/packages/tcm/pages/book-detail/index.wxml new file mode 100644 index 0000000..b523516 --- /dev/null +++ b/packages/tcm/pages/book-detail/index.wxml @@ -0,0 +1,54 @@ + + + {{coverText}} + + {{book.title}} + {{book.subtitle}} + + {{item}} + + 开始阅读 + + + + + 简介 + {{description}} + + + + 我的阅读进度 + {{progressText}} + + + + 章节目录 + + + {{item.title}} + {{item}} + + > + + + + + 相关推荐 + + + {{item.title}} + + + diff --git a/packages/tcm/pages/book-detail/index.wxss b/packages/tcm/pages/book-detail/index.wxss new file mode 100644 index 0000000..2339bfc --- /dev/null +++ b/packages/tcm/pages/book-detail/index.wxss @@ -0,0 +1,147 @@ +page { + min-height: 100%; + background: linear-gradient(180deg, #fbf4e9 0%, #f3eadf 100%); +} + +.book-detail-page { + box-sizing: border-box; + min-height: 100vh; + padding: 28rpx 20rpx 72rpx; +} + +.hero-card, +.section-card { + margin-top: 18rpx; + padding: 28rpx; + border: 1rpx solid rgba(118, 83, 42, 0.08); + border-radius: 32rpx; + background: rgba(255, 250, 242, 0.92); + box-shadow: 0 18rpx 42rpx rgba(86, 58, 25, 0.08); +} + +.hero-card { + display: flex; + align-items: flex-start; + margin-top: 0; +} + +.hero-card__cover { + width: 126rpx; + height: 168rpx; + border-radius: 24rpx; + background: linear-gradient(180deg, #d0b288 0%, #b98b5a 100%); + color: #fff9ef; + font-family: 'STSong', 'Songti SC', serif; + font-size: 42rpx; + font-weight: 700; + line-height: 168rpx; + text-align: center; +} + +.hero-card__body { + flex: 1; + margin-left: 22rpx; +} + +.hero-card__title, +.section-card__title, +.catalog-row__title { + display: block; + color: #2c2419; + font-family: 'STSong', 'Songti SC', serif; + font-size: 36rpx; + font-weight: 700; + line-height: 1.3; +} + +.hero-card__subtitle, +.section-card__description, +.catalog-row__child { + display: block; + margin-top: 10rpx; + color: #7d705d; + font-size: 26rpx; + line-height: 1.7; +} + +.hero-card__tags { + margin-top: 14rpx; +} + +.hero-card__tag { + display: inline-block; + margin-right: 8rpx; + padding: 8rpx 16rpx; + border-radius: 999rpx; + background: rgba(111, 66, 22, 0.08); + color: #6f4216; + font-size: 22rpx; + line-height: 1; +} + +.hero-card__button { + display: inline-block; + margin-top: 18rpx; + padding: 18rpx 24rpx; + border-radius: 24rpx; + background: linear-gradient(135deg, #9a622d 0%, #6f4216 100%); + color: #fff8ef; + font-size: 26rpx; + line-height: 1; +} + +.catalog-row { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 16rpx; + padding: 18rpx 0; + border-bottom: 1rpx solid rgba(118, 83, 42, 0.08); +} + +.catalog-row:last-child { + border-bottom: 0; +} + +.catalog-row__body { + min-width: 0; + flex: 1; +} + +.catalog-row__arrow { + color: #bfa882; + font-size: 28rpx; + line-height: 1; +} + +.recommend-card { + display: flex; + align-items: center; + margin-top: 16rpx; + padding: 18rpx 0; + border-bottom: 1rpx solid rgba(118, 83, 42, 0.08); +} + +.recommend-card:last-child { + border-bottom: 0; +} + +.recommend-card__cover { + width: 70rpx; + height: 90rpx; + border-radius: 18rpx; + background: linear-gradient(180deg, #d0b288 0%, #b98b5a 100%); + color: #fff9ef; + font-family: 'STSong', 'Songti SC', serif; + font-size: 28rpx; + font-weight: 700; + line-height: 90rpx; + text-align: center; +} + +.recommend-card__title { + margin-left: 16rpx; + color: #2c2419; + font-size: 28rpx; + line-height: 1.5; +} diff --git a/packages/tcm/pages/placeholder/index.js b/packages/tcm/pages/placeholder/index.js new file mode 100644 index 0000000..0ab2a5a --- /dev/null +++ b/packages/tcm/pages/placeholder/index.js @@ -0,0 +1,99 @@ +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +const PLACEHOLDER_SURFACES = Object.freeze({ + membership: { + title: '开通会员', + eyebrow: 'Membership', + description: '会员页当前只承接静态展示,后续接入新的权益体系时保持当前信息层级。', + tips: [ + '保留老页面的会员引导区块和 CTA 位置', + '不迁移旧项目的付费逻辑、订单状态和接口', + '后续只在这里接新的会员说明与权益列表' + ] + }, + feedback: { + title: '意见反馈', + eyebrow: 'Feedback', + description: '反馈入口先保留为静态说明页,用来承接“我的”页的跳转。', + tips: [ + '后续可接表单或工单系统', + '当前不提交任何内容', + '只保留页面层级和提示文案' + ] + }, + share: { + title: '分享 APP', + eyebrow: 'Share', + description: '分享页先保留 UI 占位,不接旧项目的传播逻辑。', + tips: [ + '后续可接小程序分享卡片', + '当前只展示说明与返回入口', + '不接邀请码、海报或裂变结构' + ] + }, + about: { + title: '关于我们', + eyebrow: 'About', + description: '关于页保持静态信息卡片结构,为后续新内容预留容器。', + tips: [ + '保留页面标题和说明卡片', + '后续可以接版本信息与项目介绍', + '当前不复用旧工程中的关于数据结构' + ] + }, + settings: { + title: '设置', + eyebrow: 'Settings', + description: '设置页先只保留静态说明,不接旧登录态和缓存策略。', + tips: [ + '后续可接新账号体系下的设置项', + '当前不读写 storage', + '不迁移旧项目的 session 或偏好逻辑' + ] + } +}) + +function createTcmPlaceholderPageData(kind) { + const activeKind = Object.prototype.hasOwnProperty.call(PLACEHOLDER_SURFACES, kind) ? kind : 'about' + const surface = PLACEHOLDER_SURFACES[activeKind] + + return { + kind: activeKind, + title: surface.title, + eyebrow: surface.eyebrow, + description: surface.description, + tips: [...surface.tips], + actions: [ + { + key: 'back-home', + title: '返回首页', + actionType: 'tab', + route: ROUTES.tabs.home + }, + { + key: 'go-profile', + title: '去我的页', + actionType: 'tab', + route: ROUTES.tabs.profile + } + ] + } +} + +Page({ + data: createTcmPlaceholderPageData('about'), + + onLoad(options) { + this.setData(createTcmPlaceholderPageData(options.kind)) + }, + + handleActionTap(event) { + const { route } = event.currentTarget.dataset + + openStaticRoute(route, wx) + } +}) + +module.exports = { + createTcmPlaceholderPageData +} diff --git a/packages/tcm/pages/placeholder/index.json b/packages/tcm/pages/placeholder/index.json new file mode 100644 index 0000000..86b98f8 --- /dev/null +++ b/packages/tcm/pages/placeholder/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "说明页", + "navigationBarBackgroundColor": "#f8ecd8", + "navigationBarTextStyle": "black" +} diff --git a/packages/tcm/pages/placeholder/index.wxml b/packages/tcm/pages/placeholder/index.wxml new file mode 100644 index 0000000..9e1b0a5 --- /dev/null +++ b/packages/tcm/pages/placeholder/index.wxml @@ -0,0 +1,26 @@ + + + {{eyebrow}} + {{title}} + {{description}} + + + + 当前状态 + + + {{item}} + + + + + {{item.title}} + + diff --git a/packages/tcm/pages/placeholder/index.wxss b/packages/tcm/pages/placeholder/index.wxss new file mode 100644 index 0000000..81bea9f --- /dev/null +++ b/packages/tcm/pages/placeholder/index.wxss @@ -0,0 +1,83 @@ +page { + min-height: 100%; + background: linear-gradient(180deg, #faf3e8 0%, #f1e9dd 100%); +} + +.placeholder-page { + box-sizing: border-box; + min-height: 100vh; + padding: 28rpx 20rpx 72rpx; +} + +.hero-card, +.tips-card { + margin-top: 18rpx; + padding: 28rpx; + border: 1rpx solid rgba(118, 83, 42, 0.08); + border-radius: 32rpx; + background: rgba(255, 250, 242, 0.92); + box-shadow: 0 18rpx 42rpx rgba(86, 58, 25, 0.08); +} + +.hero-card { + margin-top: 0; +} + +.hero-card__eyebrow { + display: inline-block; + padding: 8rpx 16rpx; + border-radius: 999rpx; + background: rgba(111, 66, 22, 0.08); + color: #6f4216; + font-size: 22rpx; + line-height: 1; +} + +.hero-card__title, +.tips-card__title { + display: block; + margin-top: 18rpx; + color: #2c2419; + font-family: 'STSong', 'Songti SC', serif; + font-size: 36rpx; + font-weight: 700; + line-height: 1.35; +} + +.hero-card__description, +.tips-card__text { + display: block; + margin-top: 12rpx; + color: #7c705e; + font-size: 26rpx; + line-height: 1.75; +} + +.tips-card__item { + display: flex; + align-items: flex-start; + margin-top: 12rpx; +} + +.tips-card__dot { + margin-right: 10rpx; + color: #9a622d; + font-size: 28rpx; + line-height: 1.6; +} + +.action-row__button { + margin-top: 16rpx; + padding: 22rpx 24rpx; + border-radius: 24rpx; + background: linear-gradient(135deg, #9e652f 0%, #75441a 100%); + color: #fff7eb; + font-size: 28rpx; + line-height: 1; + text-align: center; +} + +.action-row__button--ghost { + background: rgba(111, 66, 22, 0.08); + color: #6f4216; +} diff --git a/packages/tcm/pages/search-books/index.js b/packages/tcm/pages/search-books/index.js new file mode 100644 index 0000000..0ce498d --- /dev/null +++ b/packages/tcm/pages/search-books/index.js @@ -0,0 +1,90 @@ +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +const SEARCH_CATALOG = Object.freeze([ + { + key: 'classic-a', + title: '黄帝内经素问', + subtitle: '书名命中', + aliases: ['黄帝内经', '素问'], + route: `${ROUTES.tcm.bookDetail}?scene=classic-a` + }, + { + key: 'classic-b', + title: '伤寒论', + subtitle: '经典结果', + aliases: ['伤寒', '仲景'], + route: `${ROUTES.tcm.bookDetail}?scene=classic-b` + } +]) + +const SEARCH_HISTORY = Object.freeze(['黄帝内经', '伤寒论', '温病条辨']) + +function createResults(keyword) { + const normalizedKeyword = (keyword || '').trim() + + if (!normalizedKeyword) { + return [] + } + + return SEARCH_CATALOG.filter(item => { + return ( + item.title.includes(normalizedKeyword) || + item.aliases.some(alias => alias.includes(normalizedKeyword)) + ) + }).map(item => ({ ...item })) +} + +function createTcmSearchBooksPageData(keyword) { + const normalizedKeyword = (keyword || '').trim() + + return { + title: '搜索典籍', + keyword: normalizedKeyword, + draftKeyword: normalizedKeyword, + summary: '只保留静态搜索 UI 和结果列表,不接旧项目的检索接口与搜索历史存储。', + placeholder: '搜索书名或常见别名', + historyTitle: '最近搜索', + history: SEARCH_HISTORY.map(item => ({ + key: item, + label: item + })), + results: createResults(normalizedKeyword), + searched: Boolean(normalizedKeyword) + } +} + +function showNavigate(route) { + openStaticRoute(route, wx) +} + +Page({ + data: createTcmSearchBooksPageData(''), + + onLoad(options) { + this.setData(createTcmSearchBooksPageData(options.keyword || options.q)) + }, + + handleKeywordInput(event) { + this.setData({ + draftKeyword: event.detail.value + }) + }, + + handleSearchTap() { + this.setData(createTcmSearchBooksPageData(this.data.draftKeyword)) + }, + + handleHistoryTap(event) { + const keyword = event.currentTarget.dataset.keyword + + this.setData(createTcmSearchBooksPageData(keyword)) + }, + + handleResultTap(event) { + showNavigate(event.currentTarget.dataset.route) + } +}) + +module.exports = { + createTcmSearchBooksPageData +} diff --git a/packages/tcm/pages/search-books/index.json b/packages/tcm/pages/search-books/index.json new file mode 100644 index 0000000..7f6e415 --- /dev/null +++ b/packages/tcm/pages/search-books/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "搜索典籍", + "navigationBarBackgroundColor": "#f8ecd8", + "navigationBarTextStyle": "black" +} diff --git a/packages/tcm/pages/search-books/index.wxml b/packages/tcm/pages/search-books/index.wxml new file mode 100644 index 0000000..a2b8c44 --- /dev/null +++ b/packages/tcm/pages/search-books/index.wxml @@ -0,0 +1,50 @@ + + + {{title}} + {{summary}} + + + + 搜索 + + + + + {{historyTitle}} + + + {{item.label}} + + + + + + 搜索结果 + + {{item.title}} + {{item.subtitle}} + + + + + 没有找到相关典籍 + 换一个书名或常见别名再试试。 + + diff --git a/packages/tcm/pages/search-books/index.wxss b/packages/tcm/pages/search-books/index.wxss new file mode 100644 index 0000000..d091ab5 --- /dev/null +++ b/packages/tcm/pages/search-books/index.wxss @@ -0,0 +1,96 @@ +page { + min-height: 100%; + background: linear-gradient(180deg, #fbf4e9 0%, #f3eadf 100%); +} + +.search-books-page { + box-sizing: border-box; + min-height: 100vh; + padding: 28rpx 20rpx 72rpx; +} + +.hero-card, +.section-card { + margin-top: 18rpx; + padding: 28rpx; + border: 1rpx solid rgba(118, 83, 42, 0.08); + border-radius: 32rpx; + background: rgba(255, 250, 242, 0.92); + box-shadow: 0 18rpx 42rpx rgba(86, 58, 25, 0.08); +} + +.hero-card { + margin-top: 0; +} + +.hero-card__title, +.section-card__title, +.result-card__title { + display: block; + color: #2c2419; + font-family: 'STSong', 'Songti SC', serif; + font-size: 36rpx; + font-weight: 700; + line-height: 1.3; +} + +.hero-card__description, +.section-card__description, +.result-card__subtitle { + display: block; + margin-top: 10rpx; + color: #7d705d; + font-size: 26rpx; + line-height: 1.7; +} + +.search-row { + display: flex; + align-items: center; + margin-top: 18rpx; +} + +.search-row__input { + flex: 1; + height: 84rpx; + padding: 0 20rpx; + border-radius: 22rpx; + background: rgba(255, 254, 250, 0.92); + color: #3f2e1f; + font-size: 26rpx; +} + +.search-row__button { + margin-left: 12rpx; + padding: 20rpx 24rpx; + border-radius: 22rpx; + background: linear-gradient(135deg, #9a622d 0%, #6f4216 100%); + color: #fff8ef; + font-size: 26rpx; + line-height: 1; +} + +.history-list { + margin: 14rpx -6rpx 0; +} + +.history-chip { + display: inline-block; + margin: 6rpx; + padding: 12rpx 18rpx; + border-radius: 999rpx; + background: rgba(111, 66, 22, 0.08); + color: #6f4216; + font-size: 22rpx; + line-height: 1; +} + +.result-card { + margin-top: 16rpx; + padding: 22rpx 0; + border-bottom: 1rpx solid rgba(118, 83, 42, 0.08); +} + +.result-card:last-child { + border-bottom: 0; +} diff --git a/packages/tcm/pages/section/index.js b/packages/tcm/pages/section/index.js new file mode 100644 index 0000000..ed135e6 --- /dev/null +++ b/packages/tcm/pages/section/index.js @@ -0,0 +1,97 @@ +const { resolveScene } = require('../../../../utils/static-ux/shared') +const { ROUTES, openStaticRoute } = require('../../../../utils/static-ux/route-map') + +const READER_SURFACES = Object.freeze({ + 'reader-a': { + chapterTitle: '上古天真论', + passages: [ + '上古之人,其知道者,法于阴阳,和于术数。', + '食饮有节,起居有常,不妄作劳,故能形与神俱。' + ] + }, + 'reader-b': { + chapterTitle: '太阳病篇', + passages: [ + '伤寒者,太阳病也。', + '太阳之为病,脉浮,头项强痛而恶寒。' + ] + } +}) + +function createTcmSectionPageData(rawScene) { + const scene = resolveScene(rawScene, ['reader-a', 'reader-b'], 'reader-a') + const surface = READER_SURFACES[scene] + + return { + title: '典籍阅读', + scene, + chapterTitle: surface.chapterTitle, + passages: [...surface.passages], + toolbarVisible: false, + settings: { + fontScale: 1, + lineMode: 'normal', + bgMode: 'default' + }, + lineModes: [ + { key: 'compact', label: '紧凑' }, + { key: 'normal', label: '适中' }, + { key: 'relaxed', label: '宽松' } + ], + backgroundModes: [ + { key: 'default', label: '默认' }, + { key: 'paper', label: '纸张' }, + { key: 'care', label: '护眼' } + ], + catalogItems: [ + { + key: 'reader-a', + title: '上古天真论', + route: `${ROUTES.tcm.section}?scene=reader-a` + }, + { + key: 'reader-b', + title: '太阳病篇', + route: `${ROUTES.tcm.section}?scene=reader-b` + } + ] + } +} + +function showNavigate(route) { + openStaticRoute(route, wx) +} + +Page({ + data: createTcmSectionPageData('reader-a'), + + onLoad(options) { + this.setData(createTcmSectionPageData(options.scene)) + }, + + handleToolbarToggle() { + this.setData({ + toolbarVisible: !this.data.toolbarVisible + }) + }, + + handleLineModeTap(event) { + this.setData({ + 'settings.lineMode': event.currentTarget.dataset.mode + }) + }, + + handleBackgroundTap(event) { + this.setData({ + 'settings.bgMode': event.currentTarget.dataset.mode + }) + }, + + handleCatalogTap(event) { + showNavigate(event.currentTarget.dataset.route) + } +}) + +module.exports = { + createTcmSectionPageData +} diff --git a/packages/tcm/pages/section/index.json b/packages/tcm/pages/section/index.json new file mode 100644 index 0000000..2eddc0a --- /dev/null +++ b/packages/tcm/pages/section/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "典籍阅读", + "navigationBarBackgroundColor": "#f8ecd8", + "navigationBarTextStyle": "black" +} diff --git a/packages/tcm/pages/section/index.wxml b/packages/tcm/pages/section/index.wxml new file mode 100644 index 0000000..51c0fd9 --- /dev/null +++ b/packages/tcm/pages/section/index.wxml @@ -0,0 +1,49 @@ + + + {{chapterTitle}} + {{item}} + + + + {{title}} + + + 行间距 + + {{item.label}} + + + + + 背景 + + {{item.label}} + + + + + 目录 + + {{item.title}} + + + + diff --git a/packages/tcm/pages/section/index.wxss b/packages/tcm/pages/section/index.wxss new file mode 100644 index 0000000..b489957 --- /dev/null +++ b/packages/tcm/pages/section/index.wxss @@ -0,0 +1,102 @@ +page { + min-height: 100%; + background: #f8f1e6; +} + +.reading-page { + box-sizing: border-box; + min-height: 100vh; + padding: 0 0 40rpx; +} + +.reading-page--default { + background: #f8f1e6; +} + +.reading-page--paper { + background: #f4ead1; +} + +.reading-page--care { + background: #eef4e8; +} + +.reading-page__article { + padding: 72rpx 40rpx 48rpx; +} + +.reading-page__chapter { + display: block; + color: #2c2419; + font-family: 'STSong', 'Songti SC', serif; + font-size: 40rpx; + font-weight: 700; + line-height: 1.35; + text-align: center; +} + +.reading-page__passage { + display: block; + margin-top: 24rpx; + color: #3b3027; + font-size: 30rpx; + line-height: 1.9; + text-align: justify; +} + +.reading-toolbar { + margin: 0 20rpx; + padding: 24rpx; + border: 1rpx solid rgba(118, 83, 42, 0.08); + border-radius: 28rpx; + background: rgba(255, 251, 244, 0.96); + box-shadow: 0 18rpx 42rpx rgba(86, 58, 25, 0.08); +} + +.reading-toolbar__title, +.reading-toolbar__label { + display: block; + color: #2c2419; +} + +.reading-toolbar__title { + font-family: 'STSong', 'Songti SC', serif; + font-size: 32rpx; + font-weight: 700; + line-height: 1.35; +} + +.reading-toolbar__group { + margin-top: 20rpx; +} + +.reading-toolbar__label { + font-size: 24rpx; + line-height: 1.5; +} + +.reading-toolbar__pill { + display: inline-block; + margin: 10rpx 8rpx 0 0; + padding: 12rpx 18rpx; + border-radius: 999rpx; + background: rgba(111, 66, 22, 0.08); + color: #6f4216; + font-size: 22rpx; + line-height: 1; +} + +.reading-toolbar__pill--active { + background: linear-gradient(135deg, #9a622d 0%, #6f4216 100%); + color: #fff8ef; +} + +.catalog-item { + margin-top: 12rpx; + padding: 18rpx 20rpx; + border-radius: 20rpx; + background: rgba(255, 254, 250, 0.94); + color: #4f3e2e; + font-size: 24rpx; + line-height: 1.5; +} diff --git a/pages/ai/index.js b/pages/ai/index.js new file mode 100644 index 0000000..601428d --- /dev/null +++ b/pages/ai/index.js @@ -0,0 +1,185 @@ +const { ROUTES, openStaticRoute } = require('../../utils/static-ux/route-map') + +const AI_PAGE_BLUEPRINT = Object.freeze({ + title: 'AI助手', + historyText: '历史', + disclaimerText: '本功能仅供学习参考,不能替代专业医师诊断。', + tabs: [ + { + key: 'qa', + label: 'AI答疑' + }, + { + key: 'analysis', + label: '辨证分析' + }, + { + key: 'constitution', + label: '体质检测' + } + ], + panels: { + qa: { + key: 'qa', + badge: 'AI答疑', + heading: '您好,我是中医学习助手', + subheading: '围绕中医理论、术语和典籍原文快速提问', + highlights: ['解答中医理论问题', '解释典籍原文含义', '给出学习型出处引用'], + examples: ['什么是阴阳?', '气虚和阳虚有什么区别?', '如何理解肝主疏泄?'], + formType: 'qa', + actionTitle: '输入你的问题', + inputPlaceholder: '例如:什么是气虚?', + actionButtonText: '发送' + }, + analysis: { + key: 'analysis', + badge: '辨证分析', + heading: '先整理症状,再查看学习型辨证分析', + subheading: '把症状整理为结构化输入,再看学习型辨证思路', + highlights: ['输入主要症状', '补充舌象、脉象、体质', '查看学习型辨证结论'], + examples: ['乏力、睡眠差应如何整理输入?', '舌淡苔白常见于哪些证型?', '如何理解脾虚湿困?'], + formType: 'analysis', + actionTitle: '整理辨证输入', + primaryField: { + label: '主要症状', + placeholder: '主要症状,多个用逗号分隔' + }, + secondaryFields: [ + { + key: 'tongue', + placeholder: '舌象' + }, + { + key: 'pulse', + placeholder: '脉象' + }, + { + key: 'constitution', + placeholder: '体质' + }, + { + key: 'course', + placeholder: '病程' + } + ], + noteField: { + label: '补充说明', + placeholder: '例如:近两周明显乏力,睡眠浅。' + }, + actionButtonText: '开始分析' + }, + constitution: { + key: 'constitution', + badge: '体质检测', + heading: '体质检测即将开放', + subheading: '九种体质入口先按设计稿保留为 UI-first 模式', + highlights: ['后续会补齐问卷式体质评估', '保持学习参考语义', '不会输出医疗诊断结论'], + examples: ['我总怕冷属于哪种体质?', '气虚质有哪些特征?', '体质结果将如何回到典籍学习?'], + formType: 'constitution', + actionTitle: '体质检测即将开放', + actionDescription: + '当前回合先严格对齐 UI 结构,问卷式体质检测会在后续接入真实题目与结果逻辑。', + actionButtonText: '查看其它待开放能力' + } + } +}) + +function cloneTabs(tabs) { + return tabs.map(item => ({ ...item })) +} + +function cloneSecondaryFields(fields) { + return fields.map(item => ({ ...item })) +} + +function createPanelByKey(panelKey) { + const sourcePanel = AI_PAGE_BLUEPRINT.panels[panelKey] || AI_PAGE_BLUEPRINT.panels.qa + + return { + ...sourcePanel, + highlights: [...sourcePanel.highlights], + examples: [...sourcePanel.examples], + primaryField: sourcePanel.primaryField ? { ...sourcePanel.primaryField } : undefined, + secondaryFields: sourcePanel.secondaryFields + ? cloneSecondaryFields(sourcePanel.secondaryFields) + : undefined, + noteField: sourcePanel.noteField ? { ...sourcePanel.noteField } : undefined + } +} + +function createAiPageData() { + return { + title: AI_PAGE_BLUEPRINT.title, + historyText: AI_PAGE_BLUEPRINT.historyText, + disclaimerText: AI_PAGE_BLUEPRINT.disclaimerText, + secondaryEntries: [ + { + key: 'ai-history', + title: 'AI历史', + subtitle: '查看中医问答与辨证分析的静态历史页', + route: ROUTES.tcm.aiHistory + }, + { + key: 'mingli-interpret', + title: '命理解读', + subtitle: '进入命理方向的静态解读页', + route: ROUTES.mingli.interpret + } + ], + tabs: cloneTabs(AI_PAGE_BLUEPRINT.tabs), + activeTabKey: 'qa', + currentPanel: createPanelByKey('qa') + } +} + +function showPlaceholderToast(title) { + if (typeof wx?.showToast === 'function') { + wx.showToast({ + title: title || '功能建设中', + icon: 'none' + }) + } +} + +function showNavigate(route) { + if (openStaticRoute(route, wx)) { + return + } + + showPlaceholderToast() +} + +Page({ + data: createAiPageData(), + + handleTabTap(event) { + const { tabKey } = event.currentTarget.dataset + + if (!AI_PAGE_BLUEPRINT.panels[tabKey] || tabKey === this.data.activeTabKey) { + return + } + + this.setData({ + activeTabKey: tabKey, + currentPanel: createPanelByKey(tabKey) + }) + }, + + handleHistoryTap() { + showNavigate(ROUTES.tcm.aiHistory) + }, + + handleSecondaryEntryTap(event) { + showNavigate(event.currentTarget.dataset.route) + }, + + handleActionTap() { + showPlaceholderToast() + } +}) + +module.exports = { + AI_PAGE_BLUEPRINT, + createPanelByKey, + createAiPageData +} diff --git a/pages/ai/index.json b/pages/ai/index.json new file mode 100644 index 0000000..40cbce1 --- /dev/null +++ b/pages/ai/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "AI助手", + "navigationBarBackgroundColor": "#f8ecd8", + "navigationBarTextStyle": "black" +} diff --git a/pages/ai/index.wxml b/pages/ai/index.wxml new file mode 100644 index 0000000..4e19874 --- /dev/null +++ b/pages/ai/index.wxml @@ -0,0 +1,107 @@ + + + {{title}} + {{historyText}} + + + + + {{item.label}} + + + + + + {{item.title}} + {{item.subtitle}} + + + + + {{currentPanel.badge}} + {{currentPanel.heading}} + {{currentPanel.subheading}} + + + + · + {{item}} + + + + + + {{item}} + + + + + + {{disclaimerText}} + + + + + {{currentPanel.actionTitle}} + + + {{currentPanel.actionButtonText}} + + + + + {{currentPanel.actionTitle}} + {{currentPanel.primaryField.label}} + + + + + + + + + {{currentPanel.noteField.label}} + + + + {{currentPanel.actionButtonText}} + + + + + {{currentPanel.actionTitle}} + {{currentPanel.actionDescription}} + + {{currentPanel.actionButtonText}} + + + diff --git a/pages/ai/index.wxss b/pages/ai/index.wxss new file mode 100644 index 0000000..49db62f --- /dev/null +++ b/pages/ai/index.wxss @@ -0,0 +1,306 @@ +page { + min-height: 100%; + background: + linear-gradient(180deg, #f7ecd9 0%, #fbf3e6 24%, #f7eedf 100%); +} + +.ai-page { + box-sizing: border-box; + min-height: 100vh; + padding: 16rpx 20rpx 48rpx; + background: + radial-gradient(circle at top right, rgba(197, 150, 86, 0.12) 0, rgba(197, 150, 86, 0) 26%), + linear-gradient(135deg, rgba(255, 255, 255, 0.7) 0%, rgba(255, 248, 238, 0) 38%); +} + +.ai-page__nav { + display: flex; + align-items: center; + justify-content: space-between; + padding: 22rpx 0 26rpx; +} + +.ai-page__title { + font-family: 'STSong', 'Songti SC', serif; + font-size: 62rpx; + font-weight: 700; + line-height: 1.1; + color: #2b1a0e; +} + +.ai-page__history { + min-width: 94rpx; + padding: 16rpx 22rpx; + border-radius: 999rpx; + background: rgba(247, 236, 220, 0.92); + color: #9f7142; + font-size: 24rpx; + line-height: 1; + text-align: center; + box-shadow: 0 10rpx 20rpx rgba(186, 141, 83, 0.08); +} + +.ai-page__tabs { + display: flex; + margin: 0 -8rpx; +} + +.ai-page__tab { + box-sizing: border-box; + width: 33.3333%; + padding: 0 8rpx; +} + +.ai-page__tab-label { + display: block; + padding: 24rpx 0; + border: 1rpx solid rgba(213, 194, 165, 0.6); + border-radius: 999rpx; + background: rgba(255, 252, 246, 0.96); + color: #a37545; + font-family: 'STSong', 'Songti SC', serif; + font-size: 30rpx; + line-height: 1; + text-align: center; + box-shadow: 0 12rpx 28rpx rgba(188, 152, 103, 0.08); +} + +.ai-page__tab--active .ai-page__tab-label { + border-color: rgba(150, 94, 34, 0.92); + background: linear-gradient(135deg, #b07434 0%, #8f5920 100%); + color: #fff6ea; + box-shadow: 0 14rpx 24rpx rgba(144, 89, 31, 0.26); +} + +.ai-page__secondary-list { + margin-top: 18rpx; +} + +.ai-page__secondary-item { + padding: 22rpx 24rpx; + border: 1rpx solid rgba(212, 189, 152, 0.24); + border-radius: 28rpx; + background: rgba(255, 250, 243, 0.94); + box-shadow: 0 14rpx 28rpx rgba(186, 148, 96, 0.1); +} + +.ai-page__secondary-item + .ai-page__secondary-item { + margin-top: 14rpx; +} + +.ai-page__secondary-title { + display: block; + color: #6d431d; + font-family: 'STSong', 'Songti SC', serif; + font-size: 34rpx; + font-weight: 700; + line-height: 1.35; +} + +.ai-page__secondary-subtitle { + display: block; + margin-top: 8rpx; + color: #96704a; + font-size: 26rpx; + line-height: 1.7; +} + +.panel-card, +.action-card { + margin-top: 20rpx; + padding: 28rpx 20rpx 20rpx; + border: 1rpx solid rgba(209, 185, 148, 0.22); + border-radius: 34rpx; + background: rgba(255, 251, 245, 0.95); + box-shadow: 0 18rpx 36rpx rgba(178, 145, 96, 0.14); +} + +.panel-card__badge { + display: inline-block; + padding: 10rpx 18rpx; + border-radius: 999rpx; + background: rgba(247, 238, 227, 0.96); + color: #a36f3d; + font-size: 24rpx; + line-height: 1; +} + +.panel-card__heading { + display: block; + margin-top: 24rpx; + font-family: 'STSong', 'Songti SC', serif; + font-size: 56rpx; + font-weight: 700; + line-height: 1.22; + color: #2c1b10; +} + +.panel-card__subheading { + display: block; + margin-top: 18rpx; + color: #9a7248; + font-size: 28rpx; + line-height: 1.75; +} + +.panel-card__highlights { + margin-top: 16rpx; +} + +.panel-card__highlight { + display: flex; + align-items: flex-start; + margin-top: 8rpx; +} + +.panel-card__highlight-dot { + margin-right: 10rpx; + color: #a66c34; + font-size: 32rpx; + line-height: 1.5; +} + +.panel-card__highlight-text { + flex: 1; + color: #6f4b2d; + font-size: 30rpx; + line-height: 1.8; +} + +.panel-card__examples { + display: flex; + flex-wrap: wrap; + margin: 18rpx -6rpx 0; +} + +.example-chip { + box-sizing: border-box; + padding: 0 6rpx 12rpx; +} + +.example-chip__text { + display: block; + padding: 14rpx 22rpx; + border-radius: 999rpx; + background: rgba(246, 236, 225, 0.94); + color: #9d6d3e; + font-size: 26rpx; + line-height: 1.2; +} + +.panel-card__notice { + display: flex; + align-items: center; + margin-top: 10rpx; + padding: 22rpx 20rpx; + border-radius: 24rpx; + background: rgba(247, 239, 229, 0.92); +} + +.panel-card__notice-icon { + margin-right: 12rpx; + color: #d08c2f; + font-size: 24rpx; + line-height: 1; +} + +.panel-card__notice-text { + flex: 1; + color: #9b7247; + font-size: 26rpx; + line-height: 1.6; +} + +.action-card__title { + display: block; + font-family: 'STSong', 'Songti SC', serif; + font-size: 46rpx; + font-weight: 700; + line-height: 1.25; + color: #2d1c11; +} + +.action-card__label { + display: block; + margin-top: 20rpx; + color: #6d492c; + font-size: 28rpx; + line-height: 1.5; +} + +.action-card__input, +.action-card__textarea { + box-sizing: border-box; + width: 100%; + margin-top: 16rpx; + padding: 18rpx 22rpx; + border: 1rpx solid rgba(214, 193, 162, 0.72); + border-radius: 24rpx; + background: rgba(255, 252, 247, 0.96); + color: #8f6842; + font-size: 30rpx; + line-height: 1.5; +} + +.action-card__input--single { + min-height: 86rpx; +} + +.action-card__grid { + display: flex; + flex-wrap: wrap; + margin: 8rpx -8rpx 0; +} + +.action-card__grid-item { + box-sizing: border-box; + width: 50%; + padding: 8rpx; +} + +.action-card__input--half { + margin-top: 0; +} + +.action-card__textarea { + min-height: 104rpx; +} + +.action-card__description { + display: block; + margin-top: 20rpx; + color: #8e6640; + font-size: 30rpx; + line-height: 1.8; +} + +.action-card__button { + display: inline-flex; + align-items: center; + justify-content: center; + align-self: center; + min-width: 180rpx; + margin: 28rpx auto 4rpx; + padding: 20rpx 36rpx; + border-radius: 24rpx; + background: linear-gradient(135deg, #b07434 0%, #8f5920 100%); + color: #fff7eb; + font-family: 'STSong', 'Songti SC', serif; + font-size: 36rpx; + font-weight: 700; + line-height: 1; + text-align: center; + box-shadow: 0 14rpx 24rpx rgba(144, 89, 31, 0.22); +} + +.action-card__button--full { + display: flex; + width: 100%; + min-width: 0; + min-height: 84rpx; + margin-top: 24rpx; + border-radius: 22rpx; + background: rgba(244, 232, 213, 0.95); + color: #7d5327; + box-shadow: none; +} diff --git a/pages/ai/tab-ai-active.png b/pages/ai/tab-ai-active.png new file mode 100644 index 0000000000000000000000000000000000000000..0eef72e5178dd14b3cbd900ca45fe4502b9d74c1 GIT binary patch literal 1785 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D298NYK~#8N?OZ*K z95ob9Nl8h=^UzUJQlTJGAVC2QKjT^56%^4`*Ca}VIEey<+x0+`Ymg!&q);UiLPAOt zuDa?35=A5$q7Pmc|W^_kY^stt+tSj;FDw@yUtt+uzZ;6+2 z%uA0iw!}+|N_@gbP?G*Z0|imiFRB#Rcn0J1E){sj)D?ZT?raOCl63#lxjxT4CB@A? zvrb8RR#)PMcid{8(?VW`bZ?3_eZzO$R zSM=B!&mzA#eu4ZVQMSpWnSFF0m9h<|D*92C#mr-%UYwW3$Eqyqiw#OgFVuR;>yfJH zH&>CyO_dbi?U%({Xp9(CQheFz_UsX*cmw5~99T%d`_d`TynRXUq2jUGyrAN?Sy$1J zOO6as?#Y1TJ>Sl&D*BUM4wX$!USE}@LzJg6rr1OIM+Xb-HK3%!RIa-&dHF!Ov}~og zhI)(!UITqD%)2KlG#2Nw_?(xN_H3jjr<179#-Vp%&nChPJSs9aITFBiQpc`i2j-k^ zp#i5f13lbDd3h3y7Dv`Tfg~Mz1fLX}n9?z1jrt`Azd2k7c^4jg6IqwFqz5fSN?Oi8 z6|bY7Nx`X9`)$(cLW&Pj*ihn3u{kg4ef)f1^2^4coHH!cGZ~tKX*-ES! zo`UT z^-c{bA^$t-9|ihw$yQ<}{zid@u{c0Ov0?fDd~VJgkUK^g-MBGPmB$=Wo5&NczTRNgwi*|E^t#Pn?bh^rL(zIVjJx+2)d!D{eWW>B9y-HrE7Ni z3?3^DmD^#Cp*p%8t^E{KL0 z#DQrbdl!rucVp3o*p|TJ1cm5JUu-ypL(@R4=CJpn9R|ZAv?E9#;&{v+X`GYc^!&a< zEYK#Yayx0?fC`Q;ROvgD@cWwG@#RY5nRJpaGTkR_J!D`-+X6i-g}4!E1t83hVBbvkRIHlo-?eUrht zUJ>~ae-p%hZr(Ie&!jLd#>twRQd3{mz*(3wtm%T&*wn;(w@~1zkxwacGucQZlMj4& zh55AUQ`|wpr$W6OV_-c-gQpFCxO4HbDU(HO_>4u<*!c%~&nRw;aI4-;i%E=od$Fiz zpwED@tJg!|wjVR;bPA!54rS1Vn@Y{*+Kbl(S3XcsX6&AwKJ;D!GT}^;Hjx<6H|sry zG+E8YHXMC@x8q))xtTvr1D?VBzJqhmuOS_!Tq{j3e9wKZ;gr_ERp8Xn4S#H9=s`?l zHZzYeLb|SNo;U3)x?SKi3MV~8T0dQYhFL{^3G4iXfi9S&ICR=1w8C&coK8EhQW z4}ObNH2$-hXynmk6l+#i}00000NkvXXu0mjf1FTrx literal 0 HcmV?d00001 diff --git a/pages/ai/tab-ai.png b/pages/ai/tab-ai.png new file mode 100644 index 0000000000000000000000000000000000000000..4e99e9237ea49a693eec541182378c5078b6650d GIT binary patch literal 1805 zcmV+o2lDudP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D2BJwsK~#8N?OZWv z9Y+v#nKEU{l<5)zffNY@(u6dTrN1jxi5r7)8sj37ZdXX8NUEU5U@&M;B88ifR3=3X z1~(xPP&!p6E(|VI7}CgH!pz-QZr{#H|MvF&ot1s?3Vr>*H#57lJ2Sg`SFU7aWMpJy zWMpJyWMpJ?M7g8hD9!pu9(UH?#P4O)D6L*`+q!gCKXOK$mRA3B5$o^XFRi*(?tJz- zwt4AM?tJlDY4rvf!5RGm4HQFX^)F?iZqNwE=Upn$h;debx9Dh#r8Da1OXvDL@{HQ- zH0q50+gbg)N25-H@3oLR%2~B{DO{ag%o+V0l>~)P+_t)3nzie0`|5k;*6Ldq@u1M3 zJFD-NRzJb^{I>NA>Oks9lx^}Lq1mkj#m)?8)M2@$SI|IR={8qCEsgs2JcBx`etV_n zOPY_I)kmlZliakJ-P!+Izm3L7!2>(nYIA$`h(f)C@=gvUr0l-xC5^m8qdq{zQPFr?Z;{RT%BO#Aa7t-@n3A`8>Z z9zf@x(&wn>px{)>>rM5t++O=Q5H^-DQkwi>Ywg3}`yEN0jX^nOSg7YZ*p)= z5QA!(s09II$gUb1Eo8B}hQE!XG#ZDF9l0Fecp#0!l#9u}nSB)~wXOHX&xGGc(dfsX zPD8KM7#DI%g+leSriWAF{!~P;A&1H|GUNXeWvgHx5?iskSIRBc@I7 z(149qxXqF;&*t23hi|z z@9m&V53$LG^I^(WSzLi@SDsS}!g;R5wj#;XQ?vclX(08A_W&v>34+9sU2*~ANZ%u- zNCSzqE$i!;I9}uj`NBUzAz~?wur@c9vKe&yXyW2x)itz3FYtk)rr^|TC`2Ts@TF~Z zNd`}q26F!2Y}cqwv_mfhnTpjvp%5{YR$a-J=WKK7BxxY+5PCW$&RqDg&;Uj}F#4Oo zATdml212pcS$!An&YoI-&m0?YOR-^P#BQ#LiqF{=sGmm+wCNx|>YoI3+yVt&^ki$3No#|G5o6N8 zp!i_*3hJK>c`07OGYad8~v2P*31gLHCFZT-m7msCQEE zgR$pn+ffkiRUq$|V=*>$kS&1^kvDrTMfNflgEKk$`Jk>m2d044!`E*I0#2U(T*xf+ zE!1}~;Pr~soA}Ehp68}T6ZISv)e+<24mAx;jw)~z4jI<80S`7Yx702QJT>wzC7$12 z#z7_t)rChtpC;irlMsZT0%B6oTGlfLvYWJ$pwqy=1QLX=mI)E_w4x- zngcHaU)c@9pQbXi2PuuoBabgahOSGT{1x3c)K@iHZ{OF-oxQpM4RbMh!MOMp22?N^ zV$*4v;A_0NKO@n9dB(l!JhYKyErVf+{{CHPXg)&92R0IXh9 zu*7Q27)bqMp*eZ#;1>){eC17zdUW2!%a)6f-+fb^Bj5Pn8Lkbyn|StuHML9RcZiXp v>c2U~r2mguFv!Tr$jHdZ$jHdZSPuRLWo^cU;d$>S00000NkvXXu0mjfwq ({ ...item })) +} +function createHomePageData() { return { - statusLabel: state.isLoggedIn ? '已登录' : '未登录', - userName, - tokenLabel: maskToken(state.token), - permissionsLabel: state.permissions.length ? state.permissions.join(' / ') : '暂无权限' + brandName: HOME_PAGE_BLUEPRINT.brandName, + greeting: HOME_PAGE_BLUEPRINT.greeting, + subtitle: HOME_PAGE_BLUEPRINT.subtitle, + searchPlaceholder: HOME_PAGE_BLUEPRINT.searchPlaceholder, + searchBadge: HOME_PAGE_BLUEPRINT.searchBadge, + searchRoute: HOME_PAGE_BLUEPRINT.searchRoute, + portalTitle: HOME_PAGE_BLUEPRINT.portalTitle, + portalCards: createTcmHomeHubCards(), + encyclopediaTitle: HOME_PAGE_BLUEPRINT.encyclopediaTitle, + encyclopediaCards: cloneItems(HOME_PAGE_BLUEPRINT.encyclopediaCards), + toolsTitle: HOME_PAGE_BLUEPRINT.toolsTitle, + toolCards: cloneItems(HOME_PAGE_BLUEPRINT.toolCards), + wellnessTitle: HOME_PAGE_BLUEPRINT.wellnessTitle, + wellnessCards: cloneItems(HOME_PAGE_BLUEPRINT.wellnessCards), + classicsTitle: HOME_PAGE_BLUEPRINT.classicsTitle, + classicsActionText: HOME_PAGE_BLUEPRINT.classicsActionText, + classicsActionRoute: HOME_PAGE_BLUEPRINT.classicsActionRoute, + classicsBooks: cloneItems(HOME_PAGE_BLUEPRINT.classicsBooks) } } +function navigateToRoute(route) { + openStaticRoute(route, wx) +} + +function showPendingToast(title) { + if (typeof wx?.showToast !== 'function') { + return + } + + wx.showToast({ + title: title ? `${title}待开放` : '功能建设中', + icon: 'none' + }) +} + +function handleHomeEntry(route, title) { + if (openStaticRoute(route, wx)) { + return + } + + showPendingToast(title) +} + Page({ - data: { - quickEntries: QUICK_ENTRIES, - envName: '', - apiBaseUrl: '', - isLoggedIn: false, - sessionView: buildSessionView(sessionStore.getState()) - }, - onLoad() { - const runtimeConfig = getRuntimeConfig() + data: createHomePageData(), - this.unsubscribe = sessionStore.subscribe(nextState => { - this.syncSession(nextState) - }) + handleSearchTap() { + handleHomeEntry(this.data.searchRoute, '搜索') + }, - this.setData({ - envName: runtimeConfig.name.toUpperCase(), - apiBaseUrl: runtimeConfig.baseURL - }) - this.syncSession(sessionStore.getState()) - }, - onUnload() { - this.unsubscribe?.() - }, - syncSession(state) { - this.setData({ - isLoggedIn: state.isLoggedIn, - sessionView: buildSessionView(state) - }) - }, - handlePrimaryAction() { - if (this.data.isLoggedIn) { - wx.navigateTo({ - url: '/packages/demo/pages/workbench/index' - }) - return - } + handleEncyclopediaTap(event) { + const { route, title } = event.currentTarget.dataset - wx.navigateTo({ - url: '/pages/login/index' - }) + handleHomeEntry(route, title) }, - handleLogout() { - sessionStore.clearSession() - wx.showToast({ - title: '已清理登录态', - icon: 'success' - }) + + handlePortalTap(event) { + navigateToRoute(event.currentTarget.dataset.route) }, - handleEntryAction(event) { - const { path } = event.detail - if (!path) { - return - } + handleToolTap(event) { + const { route, title } = event.currentTarget.dataset - wx.navigateTo({ - url: path - }) + handleHomeEntry(route, title) + }, + + handleWellnessTap(event) { + const { route, title } = event.currentTarget.dataset + + handleHomeEntry(route, title) + }, + + handleClassicActionTap() { + handleHomeEntry(this.data.classicsActionRoute, this.data.classicsActionText) + }, + + handleClassicTap(event) { + const { route, title } = event.currentTarget.dataset + + handleHomeEntry(route, title) } }) + +module.exports = { + HOME_PAGE_BLUEPRINT, + createHomePageData +} diff --git a/pages/home/index.json b/pages/home/index.json index 93aea9c..76e1d51 100644 --- a/pages/home/index.json +++ b/pages/home/index.json @@ -1,7 +1,5 @@ { - "navigationBarTitleText": "首页", - "usingComponents": { - "app-button": "../../components/base/app-button/index", - "entry-card": "../../components/biz/entry-card/index" - } + "navigationBarTitleText": "玄知中医", + "navigationBarBackgroundColor": "#f8ecd8", + "navigationBarTextStyle": "black" } diff --git a/pages/home/index.wxml b/pages/home/index.wxml index bfb5836..3fd2535 100644 --- a/pages/home/index.wxml +++ b/pages/home/index.wxml @@ -1,65 +1,105 @@ - - - Stable Native Architecture - 玄志小程序基础骨架 - - 原生小程序 + JS + npm + TDesign + 分包 + service/store 分层,保留微信原生性能和长期维护边界。 - - - + + {{brandName}} + {{greeting}} + {{subtitle}} + + + + {{searchPlaceholder}} + {{searchBadge}} - - 当前会话 - - - 运行环境 - {{envName}} - - - API 地址 - {{apiBaseUrl}} - - - 登录状态 - {{sessionView.statusLabel}} - - - 当前用户 - {{sessionView.userName}} - - - Token - {{sessionView.tokenLabel}} - - - 权限 - {{sessionView.permissionsLabel}} + + {{encyclopediaTitle}} + + + + {{item.status}} + {{item.icon}} + {{item.title}} + - - + + {{portalTitle}} + + + + {{item.badge}} + {{item.title}} + {{item.subtitle}} + + + + + + + {{toolsTitle}} + + + + {{item.icon}} + {{item.title}} + + + + + + + {{wellnessTitle}} + + + + {{item.status}} + + {{item.icon}} + + {{item.title}} + + + + + + + + {{classicsTitle}} + {{classicsActionText}} → + + + + + + {{item.coverText}} + + {{item.title}} + + + diff --git a/pages/home/index.wxss b/pages/home/index.wxss index 558f081..47262c5 100644 --- a/pages/home/index.wxss +++ b/pages/home/index.wxss @@ -1,68 +1,323 @@ -.hero { - display: flex; - flex-direction: column; - gap: 24rpx; - padding: 36rpx 32rpx; - background: linear-gradient(160deg, #0f172a 0%, #1e293b 100%); - color: #f8fafc; +page { + min-height: 100%; + background: + linear-gradient(180deg, #f8edd6 0%, #f9f0de 24%, #f6ead4 100%); } -.hero__eyebrow { - font-size: 22rpx; - letter-spacing: 4rpx; - text-transform: uppercase; - color: #93c5fd; +.home-page { + position: relative; + min-height: 100vh; + box-sizing: border-box; + padding: 12rpx 18rpx 36rpx; + background: + linear-gradient(135deg, rgba(255, 255, 255, 0.65) 0%, rgba(255, 248, 236, 0) 36%), + linear-gradient(225deg, rgba(255, 245, 227, 0.7) 0%, rgba(255, 245, 227, 0) 44%); } -.hero__title { - font-size: 48rpx; +.home-page__brand { + display: inline-flex; + padding: 12rpx 20rpx; + border-radius: 999rpx; + background: rgba(241, 222, 190, 0.95); + color: #946739; + font-size: 26rpx; + line-height: 1; + box-shadow: 0 12rpx 24rpx rgba(173, 120, 56, 0.08); +} + +.home-page__greeting { + display: block; + margin-top: 12rpx; + font-family: 'STSong', 'Songti SC', serif; + font-size: 60rpx; font-weight: 700; + line-height: 1.1; + color: #2f1f12; +} + +.home-page__subtitle { + display: block; + margin-top: 10rpx; + font-family: 'STSong', 'Songti SC', serif; + font-size: 24rpx; + line-height: 1.65; + color: #8f6a42; +} + +.search-card { + display: flex; + align-items: center; + margin-top: 16rpx; + padding: 16rpx 18rpx 16rpx 20rpx; + border: 1rpx solid rgba(182, 151, 112, 0.24); + border-radius: 30rpx; + background: rgba(255, 251, 245, 0.96); + box-shadow: 0 16rpx 30rpx rgba(185, 152, 108, 0.14); +} + +.search-card__leading { + margin-right: 12rpx; + width: 40rpx; + height: 40rpx; + border-radius: 50%; + background: linear-gradient(135deg, #78c7dd 0%, #7b60bf 100%); + color: #ffffff; + font-size: 22rpx; + font-weight: 700; + line-height: 40rpx; + text-align: center; + box-shadow: 0 10rpx 18rpx rgba(123, 96, 191, 0.22); +} + +.search-card__placeholder { + flex: 1; + margin-right: 12rpx; + font-size: 26rpx; + color: #a18463; +} + +.search-card__badge { + flex-shrink: 0; + min-width: 80rpx; + padding: 10rpx 18rpx; + border-radius: 999rpx; + background: linear-gradient(135deg, #b67b35 0%, #8f5e21 100%); + color: #fff4de; + font-family: 'Georgia', 'Times New Roman', serif; + font-size: 24rpx; + font-weight: 700; + line-height: 1; + text-align: center; +} + +.section-card { + margin-top: 16rpx; + padding: 24rpx 18rpx 16rpx; + border: 1rpx solid rgba(189, 155, 105, 0.14); + border-radius: 30rpx; + background: rgba(255, 250, 243, 0.94); + box-shadow: 0 18rpx 36rpx rgba(178, 144, 99, 0.12); +} + +.section-card--last { + margin-bottom: 0; +} + +.section-card__header { + display: flex; + align-items: flex-end; + justify-content: space-between; + margin-bottom: 18rpx; + padding: 0 4rpx; +} + +.section-card__header .section-card__title { + margin-bottom: 0; + padding-left: 0; +} + +.section-card__title { + display: block; + margin-bottom: 18rpx; + padding-left: 4rpx; + font-family: 'STSong', 'Songti SC', serif; + font-size: 42rpx; + font-weight: 700; + line-height: 1.2; + color: #2f1f12; +} + +.section-card__action { + color: #be8b4a; + font-family: 'STSong', 'Songti SC', serif; + font-size: 24rpx; line-height: 1.2; } -.hero__summary { - font-size: 26rpx; - line-height: 1.8; - color: rgba(248, 250, 252, 0.8); +.portal-grid { + overflow: hidden; + margin: 0 -5rpx; } -.session-card { +.portal-grid__item { + box-sizing: border-box; + float: left; + width: 50%; + padding: 0 5rpx 10rpx; +} + +.portal-card { + min-height: 164rpx; + padding: 18rpx 18rpx 16rpx; + border: 1rpx solid rgba(191, 169, 140, 0.46); + border-radius: 24rpx; + background: linear-gradient(180deg, rgba(255, 255, 255, 0.78) 0%, rgba(250, 243, 232, 0.96) 100%); + box-shadow: 0 10rpx 20rpx rgba(182, 150, 107, 0.1); +} + +.portal-card__badge { + display: inline-block; + padding: 6rpx 14rpx; + border-radius: 999rpx; + background: rgba(246, 234, 214, 0.94); + color: #b67c31; + font-size: 18rpx; + line-height: 1; +} + +.portal-card__title { + display: block; + margin-top: 18rpx; + font-family: 'STSong', 'Songti SC', serif; + font-size: 28rpx; + font-weight: 700; + line-height: 1.2; + color: #38261a; +} + +.portal-card__subtitle { + display: block; + margin-top: 10rpx; + font-size: 22rpx; + line-height: 1.55; + color: #8f6a42; +} + +.feature-grid { display: flex; - flex-direction: column; - gap: 24rpx; - padding: 32rpx; + flex-wrap: wrap; + margin: 0 -4rpx; } -.session-card__rows { +.feature-grid__item { + box-sizing: border-box; + padding: 0 4rpx 10rpx; +} + +.feature-grid--four .feature-grid__item { + width: 25%; +} + +.feature-grid--three .feature-grid__item { + width: 33.3333%; +} + +.feature-card { + position: relative; display: flex; + box-sizing: border-box; + width: 100%; flex-direction: column; - gap: 20rpx; + align-items: center; + justify-content: center; + padding: 18rpx 8rpx; + border: 1rpx solid rgba(191, 169, 140, 0.46); + border-radius: 22rpx; + background: linear-gradient(180deg, rgba(255, 255, 255, 0.7) 0%, rgba(250, 243, 232, 0.92) 100%); } -.session-card__label { - flex-shrink: 0; +.feature-grid--four .feature-card { + min-height: 152rpx; +} + +.feature-grid--three .feature-card { + min-height: 182rpx; +} + +.feature-card__status { + position: absolute; + top: 8rpx; + right: 8rpx; + padding: 6rpx 12rpx; + border-radius: 999rpx; + background: rgba(246, 234, 214, 0.94); + color: #c39d6a; + font-size: 18rpx; + line-height: 1; +} + +.feature-card__icon { + width: 60rpx; + height: 60rpx; + border-radius: 20rpx; + background: linear-gradient(180deg, #f5ebdc 0%, #efe1cc 100%); + color: #b67c31; + font-size: 28rpx; + font-weight: 700; + line-height: 60rpx; + text-align: center; + box-shadow: inset 0 -8rpx 16rpx rgba(189, 150, 95, 0.08); +} + +.feature-card__emoji-box { + display: flex; + align-items: center; + justify-content: center; + width: 72rpx; + height: 72rpx; + border-radius: 20rpx; + background: linear-gradient(180deg, #f7efe3 0%, #efe0ca 100%); + box-shadow: inset 0 -8rpx 16rpx rgba(189, 150, 95, 0.06); +} + +.feature-card__emoji { + font-size: 36rpx; + line-height: 1; +} + +.feature-card__icon + .feature-card__title { + margin-top: 12rpx; +} + +.feature-card__title { + font-family: 'STSong', 'Songti SC', serif; + font-size: 22rpx; + font-weight: 700; + line-height: 1.35; + color: #38261a; + text-align: center; +} + +.feature-card__title--wellness { + margin-top: 16rpx; font-size: 24rpx; - color: #64748b; } -.session-card__value { - flex: 1; - text-align: right; - font-size: 24rpx; - color: #0f172a; +.feature-card--classic { + justify-content: flex-start; + padding-top: 18rpx; + padding-bottom: 14rpx; } -.session-card__value--mono { - font-family: 'Cascadia Code', 'Courier New', monospace; - word-break: break-all; +.feature-card__book { + position: relative; + width: 76rpx; + height: 112rpx; + border-radius: 8rpx; + background: + linear-gradient(90deg, rgba(138, 93, 48, 0.44) 0, rgba(138, 93, 48, 0.44) 10rpx, transparent 10rpx, transparent 100%), + linear-gradient(180deg, #cfaa75 0%, #c79d67 100%); + box-shadow: 0 10rpx 18rpx rgba(173, 128, 70, 0.12); } -.entry-list { - display: flex; - flex-direction: column; - gap: 24rpx; +.feature-card__book-char { + position: absolute; + top: 50%; + left: 10rpx; + right: 0; + transform: translateY(-50%); + color: #fff7eb; + font-family: 'STSong', 'Songti SC', serif; + font-size: 28rpx; + font-weight: 700; + line-height: 1; + text-align: center; } -.meta-row--top { - align-items: flex-start; +.feature-card__title--classic { + margin-top: 14rpx; + min-height: 56rpx; + padding: 0 4rpx; + font-size: 20rpx; + line-height: 1.45; } diff --git a/pages/home/tab-home-active.png b/pages/home/tab-home-active.png new file mode 100644 index 0000000000000000000000000000000000000000..ff9a151ad69f3810b75e5a121001fc20beaebce4 GIT binary patch literal 1578 zcmV+_2G#kAP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1;0r|K~#8N?OZ*K z95ob9Nl8idJam+lR44@n5)D+qdRBJ@MRe6w5e*^|1q#{qP$dmgL=~!}K|)FsuDa@! zf+A8HQjzAQ6cnqgK%d7sWI;U{QNxEu4QCoWMpJyWMpJy zWMuTj4}0pJN~`NF?x})*m*G&A>Ql3n`=*p9m6lCas(&t{`|X3ORQuJQdYjw4^7wX7 zy|pgY7ZAZ{dBp+^qL$yxLft?Q=I320pvP3DeBZUV4W-fY=*kU!^gN^0*L`}O(eigy zs*@JAI_2MOrIw8;rMePB9Yd_r^3rp%?hgfd@Zo`ME0Ph1Xt# zcyV}vc#&*d@~C^CJYuJs!kJQjF^ggu5U3Ydi{f*$D5{GEmE$*RzQlZFN_px#QV&z3 z)lYX8#fL0L3>vMz+dAwqA{Od>wl_Jz$nfx$GxWSWT0UXNW3zri#a%bAvXC1@25fgS zK)e@Pc}*$LG340Usfqd3XgOkgYBALEatqDec}U8*C@ppPj?5!huBu6FfUIHxUW&JZWRsxdU@-w^+cGdSHNu zY%e;&Y;j~2GDyo&!0@D4$CRFs75g_i@aA|P#40@ZBGQ$Wmd7n2wQN>js`uE>NrA0Y z`)$hETC304*ljeWtOC7Z#lH)&TBv>gzm=BX`F9r)FPnpM?6BC+$xtUu+u;lXX*TpC z&MhKn%HpQi&aQSeHapUCK%Ms8iKHMRh$)C{c*6chhs_CcFI*HA8+RGg5i!skr;Z(M zI==nD(;)0L@-h}l09*EF1C{4ii_wcYvms6FbeBZeM}EHW+VDAMG@<=lxCZe18#dL z-*)&p8_|a;iipug?Z#bLY$CS(mQLA-K1@4`{Z(vwt?**fW_(*rWv=LV-I;z7$6Ew9-BCFzzWh9^3@2K#z zIp{&fO*ZUJA-5L-uzv zc-Jci9^%hQuII+0$$m}>S7JP>sA*2xs~X%3rwnVh!7FU4_tUr8;M9myN?uHMQpgkn z4zGAW?dlW{*ziR5|W_RVqU4hI88w!r8*%`~=B_J2hOj0Hi1NLTp zKuEW%+1Y|)ukUWT*XM5LrzzlTxbHi7_xx(g@sx9=+Y3MRpX->?9C#V9HT1)urZe(5 zrkHil!$nAc=(^{neMNU0a7N*651EZm7qBpw5ig<3Ck$-DWQs$lUBWs{=QANTKb`?` zTs`=0Y|-#%*VB+eIti_|Og9qdj{#%CUMer;89N)DxGuNLY|I>p{$U|UOdYmnDD{;$ zHeBz#$CoWT(O&wN2ll1>--O$SI=y!Ofwfzp4d795@BVJLm|9(*HDQpEk&%&+k&%&+ ck+B>63-j5dID>5YegFUf07*qoM6N<$g1r^~dH?_b literal 0 HcmV?d00001 diff --git a/pages/home/tab-home.png b/pages/home/tab-home.png new file mode 100644 index 0000000000000000000000000000000000000000..90ee7713f216fe2a6188d7624035a44def55c59c GIT binary patch literal 1601 zcmV-H2EO@;P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1=dMKK~#8N?OZ)< z97PmPNl8gbNe2xQ1qBifqT#S_=3GIVNReowG}t?1*`k0dN)stkBxdc(U8o`oB1KAr zT$%2wh$d1B7nW$84)oscoo>FF^X<>f?&O$H`U>0Y+4tVen|br*&EC3|k&%&+k&%&+ zk&%&+(Gum6_@Gp?FDxF-KE&rTYLr?|%%LoemM@GF*QJ*KZesoHS*gYC^5~oQvCXYV zdG!5zrIveS1f%2?8mJ46mcN&UxJx4#-?vqu5o5IcrRiwvN~6SYTj%;b@|4(bHR_c7 z$7p$OQHe|ExizGYGFm*`3Rfo=GfKWeB|+g!b12SAwR^`Le*0;8u=CL-o)q#sqvexQ z%U9T*-L|}<4y2Am*^&nd&2HsUY-uIv_=y73QJv~Z|L8E5(X-a_(zNYOY>N7Za74|G5G{K`H<5Ny>p5zc{?7*D2 zTM3UqhidnZN8XFk;>fa)_Z)#}B1gefV--_^A;m+~FFLAV+MWk#6&`yLX-qYJ2AzLR zzehczg11suZ;H3&;qI4?uxogtJ)?oP zPZ-WrTR2zPbsXD>OeKE6b_UzgaCXEt;APvLND@Y*&_|28-Hv>L`UVH*1TmWI=ZV(0B$YDTOQ6qast z)ISJlu2_B1shZAEn5In5h;+7tE*;~L3+KZwtMY=aj)4Pi%Cmvca}=Tt6E)&fyWP+W3stVJ3QbvIk04E%q7gBhL*9pW=nWLy5uycC zG$JNwqhz^p+t)RNLrl?#cqSdCii}d{)=N5Mv=>axh*a-rwWs72>K_Dn&fF*9PR)oI zXj36R>K_DDZs7>uu(B1IoDnhkpydSh4+gBe=~{D>mJ#K|YKyW}G0RFQ0JRk88FZ&W z$CZ^hL%oB7Uksywj~zY2y$j^?a!kgC4zhjVB68c6dhK3DrBjn5-$Zrg1#k;ky?l1x z5ioh$b0M>k_fX$x!0Q!V5Anw&)^pRMiF!swRbt$)sA)`cRDq)~W>~WhSlGlo5XUHR zYUEQ&tlu7@kjaPY!lS*PCgFGs^(Y0NtDu+T#Yaw)wJ7);igjVT z;l>Cj>s`6W>k#+$LXk(H&w!z`*L~oY9~0>+S_+|$oS+MHM-N$E+!U1gKtWm99yL3C z>AM6}%XAT?Oe6&8W<3gA2`%PBE;y7h#yD^(3*XF7)PM`r-*<5C`7t?R5pS;KxsNWO z<9nCyPiPL@1irHCgg>jwOrM1`CXYP62rh|SSbO`vR&M#}0yNBK@`ADX z69$wpiE-#OB={OHp3nGbe>~$!RSzzX`8ItqeZ)U2`Lh1Iv)UqSPZ&Q23< ({ ...item })) +} + +function getCategoryById(categoryId) { + return LIBRARY_CATEGORIES.find(item => item.id === categoryId) || LIBRARY_CATEGORIES[0] +} + +function getBooksByCategory(categoryId) { + const activeCategory = getCategoryById(categoryId) + return cloneItems(LIBRARY_BOOKS[activeCategory.id] || []) +} + +function createLibraryPageData(categoryId) { + const activeCategory = getCategoryById(categoryId) + + return { + title: '典籍', + searchButtonText: '搜索', + domainBridge: { + title: '进入易学阁', + subtitle: '切换到命理与经典的静态学习入口', + route: ROUTES.mingli.hall + }, + categories: cloneItems(LIBRARY_CATEGORIES), + activeCategoryId: activeCategory.id, + currentCategoryName: activeCategory.name, + visibleBooks: getBooksByCategory(activeCategory.id) + } +} + +function showNavigate(route) { + if (openStaticRoute(route, wx)) { + return + } + + if (typeof wx?.showToast === 'function') { + wx.showToast({ + title: '页面暂不可达', + icon: 'none' + }) + } +} + +Page({ + data: createLibraryPageData(), + + handleCategoryTap(event) { + const categoryId = event.currentTarget.dataset.categoryId + + this.setData(createLibraryPageData(categoryId)) + }, + + handleSearchTap() { + if (!wx || typeof wx.showToast !== 'function') { + return + } + + wx.showToast({ + title: '搜索功能暂未开放', + icon: 'none' + }) + }, + + handleDomainBridgeTap() { + showNavigate(ROUTES.mingli.hall) + } +}) + +module.exports = { + LIBRARY_CATEGORIES, + LIBRARY_BOOKS, + createLibraryPageData, + getBooksByCategory +} diff --git a/pages/library/index.json b/pages/library/index.json new file mode 100644 index 0000000..33b7698 --- /dev/null +++ b/pages/library/index.json @@ -0,0 +1,5 @@ +{ + "navigationBarTitleText": "典籍", + "navigationBarBackgroundColor": "#f8ecd8", + "navigationBarTextStyle": "black" +} diff --git a/pages/library/index.wxml b/pages/library/index.wxml new file mode 100644 index 0000000..a9fffa9 --- /dev/null +++ b/pages/library/index.wxml @@ -0,0 +1,43 @@ + + + {{title}} + {{searchButtonText}} + + + + + + {{item.name}} + + + + + + {{domainBridge.title}} + {{domainBridge.subtitle}} + + + 当前分类: {{currentCategoryName}} + + + + + + {{item.coverText}} + + + + {{item.title}} + {{item.author}} / {{item.dynasty}} / {{item.period}} + + + + + + diff --git a/pages/library/index.wxss b/pages/library/index.wxss new file mode 100644 index 0000000..769aed7 --- /dev/null +++ b/pages/library/index.wxss @@ -0,0 +1,205 @@ +page { + min-height: 100%; + background: + linear-gradient(180deg, #f8edd6 0%, #f9f0de 24%, #f6ead4 100%); +} + +.library-page { + box-sizing: border-box; + min-height: 100vh; + padding: 36rpx 20rpx 80rpx; + background: + linear-gradient(135deg, rgba(255, 255, 255, 0.58) 0%, rgba(255, 248, 236, 0) 36%), + linear-gradient(225deg, rgba(255, 245, 227, 0.68) 0%, rgba(255, 245, 227, 0) 48%); +} + +.library-page__header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 18rpx 2rpx 30rpx; +} + +.library-page__title { + font-family: 'STSong', 'Songti SC', serif; + font-size: 60rpx; + font-weight: 700; + line-height: 1.2; + color: #2f1f12; +} + +.library-page__search { + min-width: 112rpx; + padding: 18rpx 26rpx; + border-radius: 999rpx; + background: rgba(240, 225, 201, 0.9); + box-shadow: 0 12rpx 24rpx rgba(173, 120, 56, 0.08); + color: #a56d2d; + font-family: 'STSong', 'Songti SC', serif; + font-size: 30rpx; + line-height: 1; + text-align: center; +} + +.library-page__content { + display: flex; + align-items: stretch; +} + +.library-page__sidebar { + box-sizing: border-box; + width: 168rpx; + flex-shrink: 0; + padding: 16rpx 14rpx; + border: 1rpx solid rgba(189, 155, 105, 0.12); + border-radius: 34rpx; + background: rgba(255, 250, 243, 0.86); + box-shadow: 0 16rpx 32rpx rgba(178, 144, 99, 0.08); +} + +.library-page__category { + padding: 22rpx 16rpx; + border-radius: 24rpx; +} + +.library-page__category + .library-page__category { + margin-top: 14rpx; +} + +.library-page__category--active { + background: linear-gradient(180deg, rgba(240, 228, 207, 0.98) 0%, rgba(236, 221, 197, 0.98) 100%); + box-shadow: inset 0 -8rpx 18rpx rgba(186, 149, 99, 0.08); +} + +.library-page__category-label { + display: block; + color: #8f6a42; + font-family: 'STSong', 'Songti SC', serif; + font-size: 32rpx; + line-height: 1.5; +} + +.library-page__category--active .library-page__category-label { + color: #7b501f; + font-weight: 700; +} + +.library-page__main { + flex: 1; + margin-left: 16rpx; +} + +.library-page__bridge { + padding: 26rpx 26rpx 24rpx; + border: 1rpx solid rgba(191, 154, 103, 0.2); + border-radius: 34rpx; + background: linear-gradient(135deg, rgba(255, 249, 239, 0.96) 0%, rgba(245, 233, 214, 0.98) 100%); + box-shadow: 0 16rpx 28rpx rgba(176, 136, 84, 0.1); +} + +.library-page__bridge-title { + display: block; + color: #6f451c; + font-family: 'STSong', 'Songti SC', serif; + font-size: 36rpx; + font-weight: 700; + line-height: 1.35; +} + +.library-page__bridge-subtitle { + display: block; + margin-top: 10rpx; + color: #97714a; + font-size: 26rpx; + line-height: 1.7; +} + +.library-page__current { + margin-top: 16rpx; + padding: 30rpx 26rpx; + border: 1rpx solid rgba(189, 155, 105, 0.12); + border-radius: 34rpx 34rpx 0 0; + background: rgba(255, 250, 243, 0.88); + color: #9c6d35; + font-family: 'STSong', 'Songti SC', serif; + font-size: 30rpx; + line-height: 1.4; +} + +.library-page__book-list { + padding: 0 0 8rpx; + border: 1rpx solid rgba(189, 155, 105, 0.08); + border-top: 0; + border-radius: 0 0 34rpx 34rpx; + background: rgba(255, 250, 243, 0.72); +} + +.book-card { + display: flex; + align-items: center; + margin: 18rpx; + padding: 22rpx 20rpx; + border: 1rpx solid rgba(192, 159, 117, 0.14); + border-radius: 28rpx; + background: rgba(255, 252, 247, 0.96); + box-shadow: 0 12rpx 24rpx rgba(181, 145, 97, 0.08); +} + +.book-card__cover { + position: relative; + width: 100rpx; + height: 136rpx; + flex-shrink: 0; + border-radius: 22rpx; + background: linear-gradient(180deg, #d5b07b 0%, #c99f67 100%); + box-shadow: 0 10rpx 18rpx rgba(173, 128, 70, 0.14); +} + +.book-card__cover-spine { + position: absolute; + top: 0; + left: 0; + width: 12rpx; + height: 100%; + border-top-left-radius: 22rpx; + border-bottom-left-radius: 22rpx; + background: rgba(138, 93, 48, 0.4); +} + +.book-card__cover-char { + position: absolute; + top: 50%; + left: 12rpx; + right: 0; + transform: translateY(-50%); + color: #fff7eb; + font-family: 'STSong', 'Songti SC', serif; + font-size: 42rpx; + font-weight: 700; + line-height: 1; + text-align: center; +} + +.book-card__body { + min-width: 0; + flex: 1; + margin-left: 18rpx; +} + +.book-card__title { + display: block; + color: #2f1f12; + font-family: 'STSong', 'Songti SC', serif; + font-size: 42rpx; + font-weight: 700; + line-height: 1.35; +} + +.book-card__meta { + display: block; + margin-top: 14rpx; + color: #8f6a42; + font-family: 'STSong', 'Songti SC', serif; + font-size: 28rpx; + line-height: 1.6; +} diff --git a/pages/library/tab-library-active.png b/pages/library/tab-library-active.png new file mode 100644 index 0000000000000000000000000000000000000000..28eeb64683a1025537873bb5ff9ff6beea9f3a2e GIT binary patch literal 1562 zcmV+#2IcvQP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1+Pg&K~#8N?OZ*K z95ob9Nl8idymXY5R44@n5)D+qcvg1>MRe6wQ5r-f3KX(CLq!^-h$>V`gM^eOy6UPE zMT$siNJW~HC{nDh0(~A|nECAGc4zFhv-p!fDHpBA?|tK+=jZ3ScCDbGprD|jprD|j zprBw&e1D+cX|=jO;DMU)?+Ps1T7BBg<$hDklUB>Bt<~RG(f;;9TdTwNK)ub++6>I;a_X!(l;8bvL?HI=%79?b3S70_eaTE5$~w~b|^<Z zwpM2YYIV-PTT3mgrj~XuhB}5=tL3HRii>LYc~i~W{}xnE->CT#^HEdF@2(@= zFm1H@>25Xqki`hWMyqev4ttD-8QUs#gZ)Sb z%z?fkjMbAJO2vhqeT^w)*c)Yq?IioNbC^}wvxs1VXGc;KkpRz=CU#97m}9%e0_M~M zJv?T6(Fu~pk*&`lEhiqsvtk!hIzqPWUv%Kj@jQrCIQ1g3DO)X%2SRFDExuImv7b?a zt<>;s%EeNv&)C?j*jDP$(<>JIyU@hT=AaxqEcP=Rx`gR4oIxPXhHk=CB7#jlyUA_u zY)50VBmIW8Iv=|eNhuI$p$E89FO3*oZOA zN<>~SJo)l#Lj}oJ8!(QhK(84!F&s{Ls~JIh9lVNN1)f;LK)+u8O_%;11oiAZPCQL4yHopj&X2^sB6 z`a~SXN*(gEx8za(c{tQ(|AWAD&OABb&P7Bg(4NbE_CE+r%?%m9MP;j(xroTg2UNJR z|G~g@H&bhFau5+UI)i6vSw$@?K>#{*AWYDml01}=d}hCc!p-JjHJ#mL!`>9)yxd8~ zh7PiQ;Gi_r?j;4C^p}>GQHSy+cnb*PjDii!oz7fnL{!J@Z!|d9D<&S|ry$pJW6@+k zqr#RL2PtYwL334udtuD5W*wZurfxrdhYik+IHlypWG978KH%_*_tUmc@rVu2g=RJ8 zz&b^NXCG+Xx%k+n$+j-|j7?kE`IJXbl3~nnv))~aNr-!Up=f%bPr%UG>nU){k3qS} zA@nh!3=iQhQ?tAB;!T0f2OA28sM#4y?0N zfHMkbd&um4x`2hbig*c|e8RvaOkx~5?GnaeI-l{e|M3inW9z~1V2g%-+n$CD(wT3y zW!jODJ_Za4bE&+RXY6cn;=0@}voR?U{KG<)m^w_&Q0^;lXxQF)k1tzpM04p|9+;Q% ze-myUy7b!X53Jn=O#qLAd;7Q9Vrq3gX~LkOprD|jprD|jpkO!n2ULJYIv*eP*8l(j M07*qoM6N<$f?>4xeEPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1KV|W8CC!q~nehNfq1}42DQ|)pbr~(ijYG zjH^qxl}Tf8afKnxxl4F&W|z@7+U(AZw30Xa;4AD~X5Rbs_w@8MH*ORZ6ciK`6ciK` z6ciNnggp@-ST*~?;mPbn{9QoFOh z`NE+RSDoLjAT^ZH;@(aSbsAzu$=B#4IDBP}#f4S-x6JXkpW36nkJj<5lHVCEA6hM6 z;`7{R%Qw`3)R1Uf_8_BqSa}><3a7-mJ(3d?s4vao-q%)%pZ`lxqs8-gYQCiT$Y^mG^Ujs{932l$ZlG%VD>WF} z(JX2QXm>W?c+a!)8ZG8L|eQ;AcwKRIkAKl2Kx#FJP{zfp#$~ zaU1zw4FqMwhmr}J&OoU@aRZ-$_dVs90H{d%z3+& zaS!ZJ?ceg)dzmbbw3WQmF^DE|G(0!fF(n8o?xBCtQ3uoRJV>i>>P2K@s_A2B{A>Du z^fM}WE9JDNcx#XMzw8*hj@8~i_KGtlf9m`$FsZRID5o73`WX$heZp|2-okZ_UCTrw zGL`rN-@UaR4QEGO0j~z{L{f@Kp^p}G#}_T1qQAkxIYA7nX`=QRxDgYJ=ae(TyFA7Js4N!O-Lg-34WAVj%+&c_hJ> zka7X&e-Ka#$!#(D3JvPb3`Ar?+!!s(Qy)<}B97nQWg=popm2PfqyIrbb4B|_=W04b zV|p_e5$S9PhjffXE}RcXt;!2#A|jEer?xGjw}I3u&I>4|to<}kzeFG z`x1>9#EeAjEG}ByL>)$f3yNAV;8sH;hA<-$dH>(GMTtYyVH7$$6)hj35rdeKh?KjbgA@lP_GZGQAIW+oEhtWW1J4Os)Mj~Q@HcFNow|%2CIK+%Z#53tA zRb-SpcV03kqrIR<#6hIz;In&>>K)t9qeFf4KM3%gIY_{riHI0zQz1V39|TlxfyQrI z*}9Ush=|DtEhp%IFks!y=$e}>M3j^Evp8E7v#f*yP{;UCL3cuShO!bD=yy=?i?J8b zv7^VhcY%Cfj>*{2LADQEMBZ+>P`j5D?9}AQ*HMS^0=NaNUp~9rF)(|&b0M>mchKKx z!0Q#G5AhQa>$z#sL_edVE-?;N)Rcf6RbVfS8P==<7B(@D#3>q_8~KzH>$kU2$mBzP z;nCeslX1L-@)(~3X*I^cI!S?N8}xF#_{eFpAqAh2*%WsE*%>`4hB2a(^{$7oMq-9~0>+S`ML)oZt}VhTdj*@ur~62O7%8hN#&YNZ%!(#-__CWg;O! zH|x>h+GsJ~=7K{BV~hirw(!mTOa)w^`MyKvo*$DF7V+jvp8MzmI=*-L{*30pb>J(z zo$#ma%=B?cF}dgQMab^ZC1!s`cNLne8Y^$#H_k0TU4X)@CodT5KVd)#lNg6i+XP?Z z#q${--H&HHtn0zWDc`2AruX^ZN# z4+|~GQwM)wDD#y!G@9P|054l^LjLwmT}OWKzY}g1_%w0(fi-bTC@3f>DA*4E1+<1_y^C^_`Tzg`07*qoM6N<$g6t6Sv;Y7A literal 0 HcmV?d00001 diff --git a/pages/login/index.js b/pages/login/index.js index 9bcfee2..3c975f0 100644 --- a/pages/login/index.js +++ b/pages/login/index.js @@ -1,75 +1,58 @@ -const { sessionStore } = require('../../stores') -const { formatDateTime } = require('../../utils/util') +const { ROUTES, openStaticRoute } = require('../../utils/static-ux/route-map') + +function createLoginPageData() { + return { + title: '欢迎来到玄志', + subtitle: '当前阶段先提供静态登录页,后续会接入新的认证方案与后端接口。', + highlight: 'Static Login', + introTitle: '先把页面走通', + introDescription: '本页只保留 UI 和静态交互,用于承接首页、我的页和后续学习入口的跳转。', + notes: [ + '不会写入 session、token 或本地用户信息', + '不会复用旧 frontend 的认证 API 和表单结构', + '保留一个“先看看静态页面”的直接入口' + ], + actions: [ + { + key: 'wechat', + title: '微信授权登录', + description: '静态按钮,占位等待新认证方案', + actionType: 'toast' + }, + { + key: 'browse', + title: '先看看静态页面', + description: '直接返回首页,继续浏览已迁移页面', + actionType: 'route', + route: ROUTES.tabs.home + } + ] + } +} + +function showComingSoon() { + if (typeof wx?.showToast === 'function') { + wx.showToast({ + title: '登录功能建设中', + icon: 'none' + }) + } +} Page({ - data: { - submitting: false, - form: { - nickname: '', - mobile: '' - }, - mockHint: `请求层已接好,可把接口替换为真实后端。当前时间:${formatDateTime(new Date())}` - }, - handleNicknameChange(event) { - this.setData({ - 'form.nickname': event.detail.value - }) - }, - handleMobileChange(event) { - this.setData({ - 'form.mobile': event.detail.value - }) - }, - handleMockLogin() { - const { nickname, mobile } = this.data.form + data: createLoginPageData(), - if (!nickname.trim()) { - wx.showToast({ - title: '请输入昵称', - icon: 'none' - }) + handleActionTap(event) { + const { actionType, route } = event.currentTarget.dataset + + if (actionType === 'route' && openStaticRoute(route, wx)) { return } - this.setData({ - submitting: true - }) - - sessionStore.setSession({ - token: `mock_${Date.now()}`, - userInfo: { - nickname: nickname.trim(), - mobile: mobile.trim() - }, - permissions: ['workbench:view', 'profile:update'] - }) - - wx.showToast({ - title: '模拟登录成功', - icon: 'success' - }) - - this.setData({ - submitting: false - }) - - setTimeout(() => { - wx.reLaunch({ - url: '/pages/home/index' - }) - }, 300) - }, - handleClearSession() { - sessionStore.clearSession() - this.setData({ - form: { - nickname: '', - mobile: '' - } - }) - wx.showToast({ - title: '已清理', - icon: 'success' - }) + showComingSoon() } }) + +module.exports = { + createLoginPageData +} diff --git a/pages/login/index.json b/pages/login/index.json index 9e105ac..d240ade 100644 --- a/pages/login/index.json +++ b/pages/login/index.json @@ -1,8 +1,5 @@ { "navigationBarTitleText": "登录", - "usingComponents": { - "app-button": "../../components/base/app-button/index", - "t-input": "tdesign-miniprogram/input/input", - "t-tag": "tdesign-miniprogram/tag/tag" - } + "navigationBarBackgroundColor": "#f8ecd8", + "navigationBarTextStyle": "black" } diff --git a/pages/login/index.wxml b/pages/login/index.wxml index 9899a03..a7e5912 100644 --- a/pages/login/index.wxml +++ b/pages/login/index.wxml @@ -1,39 +1,30 @@ - -