Compare commits
69
Commits
app-8-12
...
bd5d5c5f08
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd5d5c5f08 | ||
|
|
083fd857e8 | ||
|
|
9be2e18ea6 | ||
|
|
691c749f34 | ||
|
|
40319eea41 | ||
|
|
c1f7287331 | ||
|
|
9d91ff90ae | ||
|
|
1b8e166b33 | ||
|
|
0cea43b027 | ||
|
|
d0e2422155 | ||
|
|
9206d5ea62 | ||
|
|
bd0a3d3b96 | ||
|
|
a5f4c4472d | ||
|
|
9ef6eb8d67 | ||
|
|
d5164b7369 | ||
|
|
cf3fbdc5ef | ||
|
|
928f72ec3d | ||
|
|
b4c11881b4 | ||
|
|
58ffde808f | ||
|
|
486acc465d | ||
|
|
398f9f3726 | ||
|
|
5bd5eae62d | ||
|
|
456dd667df | ||
|
|
ed48f8be31 | ||
|
|
5e22d423d4 | ||
|
|
7f1ed49cc8 | ||
|
|
43ad07208f | ||
|
|
4b8b4eb649 | ||
|
|
75e214dc08 | ||
|
|
74ff568ba4 | ||
|
|
2fa8492c56 | ||
|
|
b5b14516a1 | ||
|
|
381fe65367 | ||
|
|
af603a4e9a | ||
|
|
f24afa116f | ||
|
|
b8ccbaf567 | ||
|
|
af1db59c07 | ||
|
|
47094cc617 | ||
|
|
01c38d8c5b | ||
|
|
1f3e580cf8 | ||
|
|
562fe0ea0e | ||
|
|
d9bb94cd3f | ||
|
|
9646ccd3f6 | ||
|
|
43e5411b6a | ||
|
|
c06d293424 | ||
|
|
6c444a4a04 | ||
|
|
cc6173e5b0 | ||
|
|
5794f60c5d | ||
|
|
35f91ee37a | ||
|
|
bc1228a310 | ||
|
|
8b9df1154c | ||
|
|
5f53aa0bbd | ||
|
|
ed040025e4 | ||
|
|
49309b7c57 | ||
|
|
18b92f1767 | ||
|
|
79601ea176 | ||
|
|
c1eee2d28a | ||
|
|
2fc8048844 | ||
|
|
18c15d1262 | ||
|
|
21790e35f4 | ||
|
|
cbe71905c0 | ||
|
|
72a5300b08 | ||
|
|
07188e82f8 | ||
|
|
c3713a8785 | ||
|
|
dddf2348d3 | ||
|
|
18ed3c48fa | ||
|
|
26839c2957 | ||
|
|
b2eb18c75f | ||
|
|
a1092c02c3 |
+35
-33
@@ -1,33 +1,35 @@
|
||||
# Build and Release Folders
|
||||
bin-debug/
|
||||
bin-release/
|
||||
[Oo]bj/
|
||||
[Bb]in/
|
||||
|
||||
# Other files and folders
|
||||
.settings/
|
||||
|
||||
# Executables
|
||||
*.swf
|
||||
*.air
|
||||
*.ipa
|
||||
*.apk
|
||||
|
||||
# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
|
||||
# should NOT be excluded as they contain compiler settings and other important
|
||||
# information for Eclipse / Flash Builder.
|
||||
|
||||
/.idea
|
||||
/.codex-tasks
|
||||
/.trellis
|
||||
/.claude
|
||||
/.agent
|
||||
/.shared
|
||||
/.cursor
|
||||
/.codex
|
||||
/.agents
|
||||
/server/.spool
|
||||
/server/.claude
|
||||
/.spool
|
||||
TUICallKit-Vue3/.env
|
||||
/.codegraph
|
||||
# Build and Release Folders
|
||||
bin-debug/
|
||||
bin-release/
|
||||
[Oo]bj/
|
||||
[Bb]in/
|
||||
|
||||
# Other files and folders
|
||||
.settings/
|
||||
|
||||
# Executables
|
||||
*.swf
|
||||
*.air
|
||||
*.ipa
|
||||
*.apk
|
||||
|
||||
# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
|
||||
# should NOT be excluded as they contain compiler settings and other important
|
||||
# information for Eclipse / Flash Builder.
|
||||
# 测试临时目录
|
||||
app/.test-tmp-stream/
|
||||
/.idea
|
||||
/.codex-tasks
|
||||
/.trellis
|
||||
/.claude
|
||||
/.agent
|
||||
/.shared
|
||||
/.cursor
|
||||
/.codex
|
||||
/.agents
|
||||
/server/.spool
|
||||
/server/.claude
|
||||
/.spool
|
||||
TUICallKit-Vue3/.env
|
||||
/.codegraph
|
||||
app/artifacts/
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
# 2026-08-20 — 医生工作站 AI 问诊对话框布局优化
|
||||
|
||||
## 改动
|
||||
- 文件: `app/src/doctor_workstation/ui/dialogs/ai_consult.py`
|
||||
- 模块: `AiConsultDialog` 右侧「智能分析」卡片 + 问诊对话卡片密度优化
|
||||
- 新增 helpers: `_InsightItem`, `_split_insight_segments`, `_split_numbered_list`, `_split_plain_paragraph`, `_split_label_or_sentence`, `_escape_html`
|
||||
- `_set_insights` 改成将稠密段落拆成 lead / list / plain 三类, 每类单独 QLabel 显示
|
||||
- CSS 新增 `AiConsultInsightMarker` / `AiConsultInsightText` / `AiConsultInsightPlaceholder`
|
||||
- 卡片 padding `10,8,10,8` → `14,12,14,14`; 卡间距 `8` → `10`
|
||||
- 聊天气泡垂直 margin `4` → `6`, chat_layout spacing `10` → `12`
|
||||
|
||||
## 拆分策略
|
||||
- 文本以 `1./2、/3)/4)` 起头 → 视为完整编号列表
|
||||
- 文本中嵌入 `…:1.…2.…` → 拆出序言 + 编号列表
|
||||
- 短中文标签 `XX:YY` 开头 → 视为 lead, 标签部分加粗
|
||||
- 其余按 `。/;/;/` 分句 → 单独成行
|
||||
|
||||
## 测试
|
||||
- 现有 `tests/test_ai_consult_ui.py` 通过 `widget.objectName() == "AiConsultRecordTitle"` 校验标题仍在, 未受影响
|
||||
- 暂未运行 UI 测试 (开发环境未装 PySide6); 解析逻辑单独脚本验证通过
|
||||
|
||||
## 注意
|
||||
- PySide6 QSS 对 `QLabel` 的 `line-height` 支持有限; 主要靠 item 间距 `8px` 与 `padding:1px 0` 提供节奏
|
||||
- 如果后续接入 `AiConsultInsightText` 还嫌密集, 可再调 `body_host.setSpacing`
|
||||
|
||||
---
|
||||
|
||||
# 接诊台 AI 智能分析详情对话框 (`ReceptionAiAnalysisDialog`) 优化
|
||||
用户截图(`clipboard-2026-08-20T08-42-40`...)反馈: 「问诊详情 → AI 智能分析」卡片里的诊断建议 / 风险评估 / 治疗建议三段文字太稠密, 不利于阅读。
|
||||
|
||||
## 关键差异
|
||||
这次的目标文件和上次不同 — 用户截图里出现 "诊断建议 / 风险评估 / 治疗建议" 标题, 而 `ai_consult.py` 用的是 "血糖控制评估 / 并发症风险评估 / 用药合理性评估"。实际是 `app/src/doctor_workstation/ui/pages/reception.py` 中的 `_ReceptionAiAnalysisDialog` 类。
|
||||
|
||||
## 改动
|
||||
- 文件: `app/src/doctor_workstation/ui/pages/reception.py`
|
||||
- 新增 helpers (与 ai_consult.py 类似但导出名加 `_ai_` 前缀):
|
||||
- `_ai_split_into_segments` / `_ai_split_numbered_list` / `_ai_split_plain_paragraph`
|
||||
- `_ai_segments_to_html` / `_ai_narrative_structured_html`
|
||||
- `_ai_split_label_or_sentence` / `_ai_escape_html`
|
||||
- 正则: `_AI_INSIGHT_LIST_RE`, `_AI_INSIGHT_LIST_LOOKAHEAD_RE`, `_AI_INSIGHT_LABEL_RE`
|
||||
- `add_text_section` 闭包内多挂一个 RichText `_structured_labels[name]` 标签 (`.setObjectName(name + "Structured")`, `property="dialogAiStructured"`)
|
||||
- 原 PlainText `value_label` 仍存在 (`hide()` + `setMaximumHeight(0)`) 用于兼容既有 findChild 测试
|
||||
- `_render_model` 同步刷新两个结构化标签; 空 HTML 时回退显示原 label 文本
|
||||
- 风险评估 FlowLayout spacing `7×7` → `9×9`
|
||||
- `body_layout.setSpacing` `12` → `14`
|
||||
- 卡片 contentsMargins `14,13,16,15` → `16,14,18,16`
|
||||
- QSS: `dialogAiBody` 加 `line-height: 1.85`, 新增 `dialogAiStructured` 选择器 (line-height 175%); 风险 pill `min-height` `28` → `30`, padding `4 10` → `5 12`, font 12 → 12.5, border-radius `7` → `8`
|
||||
|
||||
## 兼容约束
|
||||
- `tests/test_reception_parity_ui.py` 严格校验:
|
||||
- `findChild(QLabel, "ReceptionAiAnalysisDialogDiagnosisText")` 必须能找到
|
||||
- `.text()` 必须等于 `_ai_narrative_text` 归一化结果
|
||||
- `.textFormat() == Qt.TextFormat.PlainText`
|
||||
- 因此 PlainText 标签必须原样保留, 仅做 `.hide()` + `setMaximumHeight(0)` (避免 QSS `>` 子选择器不被 Qt 支持)
|
||||
|
||||
## 验证
|
||||
- `py_compile` 通过, 无 `SyntaxWarning`
|
||||
- 单独脚本跑过 4 组样本文本 (稠密段落 / 嵌入式编号列表 / 短句 / 纯编号列表), 拆分结果符合预期
|
||||
- 未在本机跑 UI 测试 (缺 PySide6)
|
||||
|
||||
---
|
||||
|
||||
# 患者列表 AI 分析: 发送完整患者资料给 AI
|
||||
|
||||
用户需求: 患者列表 AI 分析时, 每日血糖报告、舌苔、AI 报告、视频录制回放的文字对话都要发给 AI。
|
||||
|
||||
## 改动
|
||||
- `app/src/doctor_workstation/ui/dialogs/ai_consult.py`
|
||||
- `_load_workspace` 新增 `list_call_records` section (视频问诊记录, 含 `transcript_text`)
|
||||
- 模块级纯函数 (无 Qt 依赖, 便于测试):
|
||||
- `AI_CONTEXT_MAX_CHARS=320`, `AI_PROMPT_LIMIT=500`, `AI_CONTEXT_SEPARATOR="\n\n— 医生提问 —\n"`
|
||||
- `_truncate_for_context` / `_patient_context_blood_sugar` / `_patient_context_tongue` / `_patient_context_reports` / `_patient_context_prescriptions` / `_patient_context_videos` / `build_patient_ai_context` / `_compose_ai_prompt`
|
||||
- `build_patient_ai_context` 返回 `(text, labels)`, 按 每日血糖→舌苔/脉象→视频问诊文字→历史AI报告→处方记录 顺序装入 320 字预算的信封
|
||||
- `_patient_context_videos` 按 `diagnosis_id` 过滤归属 (`_exact_positive_id`), 只取最近一条有文字的
|
||||
- `_compose_ai_prompt` 本地强制 500 字上限: 上下文 + "— 医生提问 —" + 问题, 超长时截断问题加 `…` (服务端 `tcm.diagnosis/aiAssistant` prompt 上限 500)
|
||||
- `_ChatBubble.attach_extra()` 支持气泡下方挂载控件
|
||||
- `_render_patient_context`: 聊天区系统气泡 "AI 已加载本诊单上下文(N 项…)", `_attach_context_detail` 挂 "查看本次发送给 AI 的资料全文" 展开按钮 (QSS: `AiConsultContextToggle`/`AiConsultContextReveal`)
|
||||
- `_ask` 用 `_compose_ai_prompt(text, self._patient_ai_context)` 组装后传给 `_AiStreamWorker`; 医生气泡仍显示原始问题
|
||||
- `open_for` / `_clear_chat` 重置 `_patient_ai_context*` 三个状态, 防止跨患者残留
|
||||
|
||||
## 测试
|
||||
- `app/tests/test_ai_consult_ui.py` 新增 5 个测试 (总 15 个全通过):
|
||||
纯函数: 全 section 信封+视频按诊单过滤 / 仅基本病历返回空 / 长问题截断≤500
|
||||
UI: 上下文气泡+展开按钮+视频记录计数 / `_ask` 注入上下文 (FakeWorker 捕获 prompt, monkeypatch `QThreadPool`)
|
||||
- `app/scripts/check_ai_context.py`: AST 提取纯函数的冒烟脚本 (无需 Qt)
|
||||
- `tests/test_ai_consult_workspace_ui.py` 18 个测试无回归
|
||||
|
||||
## 环境要点 (重要)
|
||||
- **PySide6 + pytest 在 `app/.venv` 里可用**: 用 `D:/web/zyt/app/.venv/Scripts/python.exe -m pytest` 跑 UI 测试 (QT_QPA_PLATFORM=offscreen)。之前"本机缺 PySide6"的结论只对系统 Python 成立。
|
||||
- 测试 FakeWorker 需实现 `signals.event/error/finished.connect()` 和 `cancel()` (closeEvent 会调 cancel)
|
||||
@@ -1,6 +1,6 @@
|
||||
import App from './App'
|
||||
|
||||
var baseUrl = 'https://admin.zhenyangtang.com.cn/'
|
||||
var baseUrl = 'https://xt.zhenyangtang.com.cn/'
|
||||
|
||||
function joinApiUrl(base, path) {
|
||||
const b = String(base || '').replace(/\/+$/, '')
|
||||
|
||||
+68
-68
@@ -1,68 +1,68 @@
|
||||
{
|
||||
"name" : "tongji-uniapp",
|
||||
"appid" : "__UNI__TONGJI01",
|
||||
"description" : "血糖管理 / 日常护理",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"transformPx" : false,
|
||||
"app-plus" : {
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
"modules" : {},
|
||||
"distribute" : {
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>"
|
||||
]
|
||||
},
|
||||
"ios" : {},
|
||||
"sdkConfigs" : {}
|
||||
}
|
||||
},
|
||||
"quickapp" : {},
|
||||
"mp-weixin" : {
|
||||
"appid" : "wx79b9a0bfbfe7cbcd",
|
||||
"lazyCodeLoading" : "requiredComponents",
|
||||
"setting" : {
|
||||
"urlCheck" : false,
|
||||
"minified" : true
|
||||
},
|
||||
"optimization" : {
|
||||
"subPackages" : true
|
||||
},
|
||||
"usingComponents" : true,
|
||||
"requiredBackgroundModes" : [ "audio" ],
|
||||
"plugins" : {
|
||||
"WechatSI" : {
|
||||
"version" : "0.3.5",
|
||||
"provider" : "wx069ba97219f66d99"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3"
|
||||
}
|
||||
{
|
||||
"name" : "tongji-uniapp",
|
||||
"appid" : "__UNI__TONGJI01",
|
||||
"description" : "血糖管理 / 日常护理",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"transformPx" : false,
|
||||
"app-plus" : {
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
"modules" : {},
|
||||
"distribute" : {
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>"
|
||||
]
|
||||
},
|
||||
"ios" : {},
|
||||
"sdkConfigs" : {}
|
||||
}
|
||||
},
|
||||
"quickapp" : {},
|
||||
"mp-weixin" : {
|
||||
"appid" : "wx0c2a9d5ebad26a3f",
|
||||
"lazyCodeLoading" : "requiredComponents",
|
||||
"setting" : {
|
||||
"urlCheck" : false,
|
||||
"minified" : true
|
||||
},
|
||||
"optimization" : {
|
||||
"subPackages" : true
|
||||
},
|
||||
"usingComponents" : true,
|
||||
"requiredBackgroundModes" : [ "audio" ],
|
||||
"plugins" : {
|
||||
"WechatSI" : {
|
||||
"version" : "0.3.5",
|
||||
"provider" : "wx069ba97219f66d99"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3"
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"tab-bar-dock.js","sources":["components/app-tab-bar/tab-bar-dock.vue","../../../soft/HBuilderX/plugins/uniapp-cli-vite/uniComponent:/RDovd2ViL3p5dC9Ub25namlVbmlBcHAvY29tcG9uZW50cy9hcHAtdGFiLWJhci90YWItYmFyLWRvY2sudnVl"],"sourcesContent":["<template>\r\n <view class=\"tab-dock\">\r\n <view class=\"tab-dock__inner\">\r\n <view class=\"tab-dock__item tab-dock__item--center\" @click=\"goWeekly\">\r\n <view class=\"tab-dock__fab\" :class=\"{ 'tab-dock__fab--active': active === 0 }\">\r\n <text class=\"tab-dock__fab-text\">糖</text>\r\n </view>\r\n <text class=\"tab-dock__label tab-dock__label--center\" :style=\"{ color: active === 0 ? activeColor : color }\">血糖</text>\r\n </view>\r\n\r\n <view class=\"tab-dock__item\" @click=\"goUser\">\r\n <image\r\n class=\"tab-dock__icon\"\r\n :src=\"active === 1 ? '/static/user/user_no.png' : '/static/user/user.png'\"\r\n mode=\"aspectFit\"\r\n />\r\n <text class=\"tab-dock__label\" :style=\"{ color: active === 1 ? activeColor : color }\">我的</text>\r\n </view>\r\n </view>\r\n <view class=\"tab-dock__safe\" />\r\n </view>\r\n</template>\r\n\r\n<script setup>\r\nconst props = defineProps({\r\n /** 0 血糖 1 我的 */\r\n active: {\r\n type: Number,\r\n default: 0\r\n }\r\n})\r\n\r\nconst color = '#8a8a8a'\r\nconst activeColor = '#204e2b'\r\n\r\nfunction goUser() {\r\n if (props.active === 1) return\r\n uni.redirectTo({ url: '/pages/user/user' })\r\n}\r\n\r\nfunction goWeekly() {\r\n if (props.active === 0) return\r\n uni.redirectTo({ url: '/tongji/pages/weekly' })\r\n}\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.tab-dock {\r\n position: fixed;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n z-index: 999;\r\n background: #ffffff;\r\n border-top: 1rpx solid rgba(0, 0, 0, 0.06);\r\n box-shadow: 0 -6rpx 20rpx rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.tab-dock__inner {\r\n display: flex;\r\n align-items: flex-end;\r\n height: 100rpx;\r\n}\r\n\r\n.tab-dock__item {\r\n flex: 1;\r\n height: 100rpx;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.tab-dock__item--center {\r\n justify-content: flex-end;\r\n padding-bottom: 6rpx;\r\n}\r\n\r\n.tab-dock__icon {\r\n width: 46rpx;\r\n height: 46rpx;\r\n}\r\n\r\n.tab-dock__label {\r\n margin-top: 6rpx;\r\n font-size: 22rpx;\r\n line-height: 1.2;\r\n}\r\n\r\n.tab-dock__label--center {\r\n margin-top: 8rpx;\r\n}\r\n\r\n.tab-dock__fab {\r\n width: 96rpx;\r\n height: 96rpx;\r\n margin-top: -48rpx;\r\n border-radius: 50%;\r\n background: linear-gradient(180deg, #2d7340 0%, #204e2b 100%);\r\n border: 6rpx solid #ffffff;\r\n box-shadow: 0 10rpx 24rpx rgba(32, 78, 43, 0.35);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.tab-dock__fab--active {\r\n transform: scale(1.04);\r\n box-shadow: 0 12rpx 28rpx rgba(32, 78, 43, 0.42);\r\n}\r\n\r\n.tab-dock__fab-text {\r\n color: #ffffff;\r\n font-size: 38rpx;\r\n font-weight: 700;\r\n line-height: 1;\r\n}\r\n\r\n.tab-dock__safe {\r\n height: env(safe-area-inset-bottom);\r\n background: #ffffff;\r\n}\r\n</style>\r\n","import Component from 'D:/web/zyt/TongjiUniApp/components/app-tab-bar/tab-bar-dock.vue'\nwx.createComponent(Component)"],"names":["uni"],"mappings":";;AAgCA,MAAM,QAAQ;AACd,MAAM,cAAc;;;;;;;;;;;AATpB,UAAM,QAAQ;AAWd,aAAS,SAAS;AACd,UAAI,MAAM,WAAW;AAAG;AACxBA,oBAAAA,MAAI,WAAW,EAAE,KAAK,mBAAkB,CAAE;AAAA,IAC9C;AAEA,aAAS,WAAW;AAChB,UAAI,MAAM,WAAW;AAAG;AACxBA,oBAAAA,MAAI,WAAW,EAAE,KAAK,uBAAsB,CAAE;AAAA,IAClD;;;;;;;;;;;;;;AC1CA,GAAG,gBAAgB,SAAS;"}
|
||||
{"version":3,"file":"tab-bar-dock.js","sources":["components/app-tab-bar/tab-bar-dock.vue","../../../soft/HBuilderX/plugins/uniapp-cli-vite/uniComponent:/RDovd2ViL3p5dC9Ub25namlVbmlBcHAvY29tcG9uZW50cy9hcHAtdGFiLWJhci90YWItYmFyLWRvY2sudnVl"],"sourcesContent":["<template>\r\n <view class=\"tab-dock\">\r\n <view class=\"tab-dock__inner\">\r\n <view class=\"tab-dock__item tab-dock__item--center\" @click=\"goWeekly\">\r\n <view class=\"tab-dock__fab\" :class=\"{ 'tab-dock__fab--active': active === 0 }\">\r\n <text class=\"tab-dock__fab-text\">糖</text>\r\n </view>\r\n <text class=\"tab-dock__label tab-dock__label--center\" :style=\"{ color: active === 0 ? activeColor : color }\">血糖</text>\r\n </view>\r\n\r\n <view class=\"tab-dock__item\" @click=\"goUser\">\r\n <image\r\n class=\"tab-dock__icon\"\r\n :src=\"active === 1 ? '/static/user/user_no.png' : '/static/user/user.png'\"\r\n mode=\"aspectFit\"\r\n />\r\n <text class=\"tab-dock__label\" :style=\"{ color: active === 1 ? activeColor : color }\">我的</text>\r\n </view>\r\n </view>\r\n <view class=\"tab-dock__safe\" />\r\n </view>\r\n</template>\r\n\r\n<script setup>\r\nconst props = defineProps({\r\n /** 0 血糖 1 我的 */\r\n active: {\r\n type: Number,\r\n default: 0\r\n }\r\n})\r\n\r\nconst color = '#8a8a8a'\r\nconst activeColor = '#204e2b'\r\n\r\nfunction goUser() {\r\n if (props.active === 1) return\r\n uni.redirectTo({ url: '/pages/user/user' })\r\n}\r\n\r\nfunction goWeekly() {\r\n if (props.active === 0) return\r\n uni.redirectTo({ url: '/tongji/pages/weekly' })\r\n}\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.tab-dock {\r\n position: fixed;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n z-index: 999;\r\n background: #ffffff;\r\n border-top: 1rpx solid rgba(0, 0, 0, 0.06);\r\n box-shadow: 0 -6rpx 20rpx rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n.tab-dock__inner {\r\n display: flex;\r\n align-items: flex-end;\r\n height: 100rpx;\r\n}\r\n\r\n.tab-dock__item {\r\n flex: 1;\r\n height: 100rpx;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.tab-dock__item--center {\r\n justify-content: flex-end;\r\n padding-bottom: 6rpx;\r\n}\r\n\r\n.tab-dock__icon {\r\n width: 46rpx;\r\n height: 46rpx;\r\n}\r\n\r\n.tab-dock__label {\r\n margin-top: 6rpx;\r\n font-size: 22rpx;\r\n line-height: 1.2;\r\n}\r\n\r\n.tab-dock__label--center {\r\n margin-top: 8rpx;\r\n}\r\n\r\n.tab-dock__fab {\r\n width: 96rpx;\r\n height: 96rpx;\r\n margin-top: -48rpx;\r\n border-radius: 50%;\r\n background: linear-gradient(180deg, #2d7340 0%, #204e2b 100%);\r\n border: 6rpx solid #ffffff;\r\n box-shadow: 0 10rpx 24rpx rgba(32, 78, 43, 0.35);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.tab-dock__fab--active {\r\n transform: scale(1.04);\r\n box-shadow: 0 12rpx 28rpx rgba(32, 78, 43, 0.42);\r\n}\r\n\r\n.tab-dock__fab-text {\r\n color: #ffffff;\r\n font-size: 38rpx;\r\n font-weight: 700;\r\n line-height: 1;\r\n}\r\n\r\n.tab-dock__safe {\r\n height: env(safe-area-inset-bottom);\r\n background: #ffffff;\r\n}\r\n</style>\r\n","import Component from 'D:/web/zyt/TongjiUniApp/components/app-tab-bar/tab-bar-dock.vue'\nwx.createComponent(Component)"],"names":["color","activeColor","props","__props","goUser","uni","goWeekly","Component"],"mappings":"uDAgCMA,EAAQ,UACRC,EAAc,mFATpB,MAAMC,EAAQC,EAWd,SAASC,GAAS,CACVF,EAAM,SAAW,GACrBG,EAAAA,MAAI,WAAW,CAAE,IAAK,kBAAkB,CAAE,CAC9C,CAEA,SAASC,GAAW,CACZJ,EAAM,SAAW,GACrBG,EAAAA,MAAI,WAAW,CAAE,IAAK,sBAAsB,CAAE,CAClD,iOC1CA,GAAG,gBAAgBE,CAAS"}
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"VoiceSpeakMascot.js","sources":["../../../soft/HBuilderX/plugins/uniapp-cli-vite/uniComponent:/RDovd2ViL3p5dC9Ub25namlVbmlBcHAvdG9uZ2ppL2NvbXBvbmVudHMvVm9pY2VTcGVha01hc2NvdC52dWU"],"sourcesContent":["import Component from 'D:/web/zyt/TongjiUniApp/tongji/components/VoiceSpeakMascot.vue'\nwx.createComponent(Component)"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AACA,GAAG,gBAAgB,SAAS;"}
|
||||
{"version":3,"file":"VoiceSpeakMascot.js","sources":["../../../soft/HBuilderX/plugins/uniapp-cli-vite/uniComponent:/RDovd2ViL3p5dC9Ub25namlVbmlBcHAvdG9uZ2ppL2NvbXBvbmVudHMvVm9pY2VTcGVha01hc2NvdC52dWU"],"sourcesContent":["import Component from 'D:/web/zyt/TongjiUniApp/tongji/components/VoiceSpeakMascot.vue'\nwx.createComponent(Component)"],"names":["Component"],"mappings":"8XACA,GAAG,gBAAgBA,CAAS"}
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"useGameAuth.js","sources":["tongji/endless-game/composables/useGameAuth.js"],"sourcesContent":["/**\r\n * 识糖小课堂独立登录适配层。复用主小程序账号,但不依赖 tongji 其他页面代码。\r\n */\r\nexport function useGameAuth(proxy) {\r\n let loginPromise = null\r\n\r\n function hasToken() {\r\n return !!String(uni.getStorageSync('token') || '').trim()\r\n }\r\n\r\n function clearToken() {\r\n uni.removeStorageSync('token')\r\n }\r\n\r\n function wxLoginCode() {\r\n return new Promise((resolve, reject) => {\r\n uni.login({\r\n provider: 'weixin',\r\n success: (res) => res?.code ? resolve(res.code) : reject(new Error('微信登录未返回 code')),\r\n fail: reject\r\n })\r\n })\r\n }\r\n\r\n async function loginWithCode(code) {\r\n const res = await proxy.apiUrl({\r\n url: '/api/login/mnpLogin',\r\n method: 'POST',\r\n data: { code }\r\n }, false)\r\n if (res?.code !== 1 || !res.data?.token) {\r\n clearToken()\r\n throw new Error(res?.msg || '登录失败')\r\n }\r\n uni.setStorageSync('token', res.data.token)\r\n uni.setStorageSync('userData', res.data)\r\n return true\r\n }\r\n\r\n async function verifyOrLogin() {\r\n if (hasToken()) {\r\n try {\r\n const res = await proxy.apiUrl({ url: '/api/user/info', method: 'POST' }, false)\r\n if (res?.code === 1 && res.data) {\r\n uni.setStorageSync('userData', res.data)\r\n return true\r\n }\r\n // 只有明确的登录失效才重新换取 token;其他业务错误先保留原登录。\r\n if (res?.code !== -1) return true\r\n } catch (_) {\r\n // 断网不清除仍可能有效的 token,成绩由离线队列稍后补传。\r\n return true\r\n }\r\n clearToken()\r\n }\r\n const code = await wxLoginCode()\r\n return loginWithCode(code)\r\n }\r\n\r\n async function ensureLoggedIn() {\r\n if (loginPromise) return loginPromise\r\n loginPromise = verifyOrLogin()\r\n .then(ok => !!ok)\r\n .catch(() => false)\r\n // 只合并同时发生的登录;成功结果不能永久缓存,否则 token 过期后无法恢复。\r\n .finally(() => { loginPromise = null })\r\n return loginPromise\r\n }\r\n\r\n return { ensureLoggedIn }\r\n}\r\n"],"names":["uni"],"mappings":";;AAGO,SAAS,YAAY,OAAO;AAC/B,MAAI,eAAe;AAEnB,WAAS,WAAW;AAChB,WAAO,CAAC,CAAC,OAAOA,oBAAI,eAAe,OAAO,KAAK,EAAE,EAAE,KAAM;AAAA,EAC5D;AAED,WAAS,aAAa;AAClBA,kBAAG,MAAC,kBAAkB,OAAO;AAAA,EAChC;AAED,WAAS,cAAc;AACnB,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpCA,oBAAAA,MAAI,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS,CAAC,SAAQ,2BAAK,QAAO,QAAQ,IAAI,IAAI,IAAI,OAAO,IAAI,MAAM,cAAc,CAAC;AAAA,QAClF,MAAM;AAAA,MACtB,CAAa;AAAA,IACb,CAAS;AAAA,EACJ;AAED,iBAAe,cAAc,MAAM;;AAC/B,UAAM,MAAM,MAAM,MAAM,OAAO;AAAA,MAC3B,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,MAAM,EAAE,KAAM;AAAA,IACjB,GAAE,KAAK;AACR,SAAI,2BAAK,UAAS,KAAK,GAAC,SAAI,SAAJ,mBAAU,QAAO;AACrC,iBAAY;AACZ,YAAM,IAAI,OAAM,2BAAK,QAAO,MAAM;AAAA,IACrC;AACDA,kBAAAA,MAAI,eAAe,SAAS,IAAI,KAAK,KAAK;AAC1CA,kBAAAA,MAAI,eAAe,YAAY,IAAI,IAAI;AACvC,WAAO;AAAA,EACV;AAED,iBAAe,gBAAgB;AAC3B,QAAI,SAAQ,GAAI;AACZ,UAAI;AACA,cAAM,MAAM,MAAM,MAAM,OAAO,EAAE,KAAK,kBAAkB,QAAQ,OAAQ,GAAE,KAAK;AAC/E,aAAI,2BAAK,UAAS,KAAK,IAAI,MAAM;AAC7BA,wBAAAA,MAAI,eAAe,YAAY,IAAI,IAAI;AACvC,iBAAO;AAAA,QACV;AAED,aAAI,2BAAK,UAAS;AAAI,iBAAO;AAAA,MAChC,SAAQ,GAAG;AAER,eAAO;AAAA,MACV;AACD,iBAAY;AAAA,IACf;AACD,UAAM,OAAO,MAAM,YAAa;AAChC,WAAO,cAAc,IAAI;AAAA,EAC5B;AAED,iBAAe,iBAAiB;AAC5B,QAAI;AAAc,aAAO;AACzB,mBAAe,cAAe,EACzB,KAAK,QAAM,CAAC,CAAC,EAAE,EACf,MAAM,MAAM,KAAK,EAEjB,QAAQ,MAAM;AAAE,qBAAe;AAAA,KAAM;AAC1C,WAAO;AAAA,EACV;AAED,SAAO,EAAE,eAAgB;AAC7B;;"}
|
||||
{"version":3,"file":"useGameAuth.js","sources":["tongji/endless-game/composables/useGameAuth.js"],"sourcesContent":["/**\r\n * 识糖小课堂独立登录适配层。复用主小程序账号,但不依赖 tongji 其他页面代码。\r\n */\r\nexport function useGameAuth(proxy) {\r\n let loginPromise = null\r\n\r\n function hasToken() {\r\n return !!String(uni.getStorageSync('token') || '').trim()\r\n }\r\n\r\n function clearToken() {\r\n uni.removeStorageSync('token')\r\n }\r\n\r\n function wxLoginCode() {\r\n return new Promise((resolve, reject) => {\r\n uni.login({\r\n provider: 'weixin',\r\n success: (res) => res?.code ? resolve(res.code) : reject(new Error('微信登录未返回 code')),\r\n fail: reject\r\n })\r\n })\r\n }\r\n\r\n async function loginWithCode(code) {\r\n const res = await proxy.apiUrl({\r\n url: '/api/login/mnpLogin',\r\n method: 'POST',\r\n data: { code }\r\n }, false)\r\n if (res?.code !== 1 || !res.data?.token) {\r\n clearToken()\r\n throw new Error(res?.msg || '登录失败')\r\n }\r\n uni.setStorageSync('token', res.data.token)\r\n uni.setStorageSync('userData', res.data)\r\n return true\r\n }\r\n\r\n async function verifyOrLogin() {\r\n if (hasToken()) {\r\n try {\r\n const res = await proxy.apiUrl({ url: '/api/user/info', method: 'POST' }, false)\r\n if (res?.code === 1 && res.data) {\r\n uni.setStorageSync('userData', res.data)\r\n return true\r\n }\r\n // 只有明确的登录失效才重新换取 token;其他业务错误先保留原登录。\r\n if (res?.code !== -1) return true\r\n } catch (_) {\r\n // 断网不清除仍可能有效的 token,成绩由离线队列稍后补传。\r\n return true\r\n }\r\n clearToken()\r\n }\r\n const code = await wxLoginCode()\r\n return loginWithCode(code)\r\n }\r\n\r\n async function ensureLoggedIn() {\r\n if (loginPromise) return loginPromise\r\n loginPromise = verifyOrLogin()\r\n .then(ok => !!ok)\r\n .catch(() => false)\r\n // 只合并同时发生的登录;成功结果不能永久缓存,否则 token 过期后无法恢复。\r\n .finally(() => { loginPromise = null })\r\n return loginPromise\r\n }\r\n\r\n return { ensureLoggedIn }\r\n}\r\n"],"names":["useGameAuth","proxy","loginPromise","hasToken","uni","clearToken","wxLoginCode","resolve","reject","res","loginWithCode","code","_a","verifyOrLogin","ensureLoggedIn","ok"],"mappings":"0DAGO,SAASA,EAAYC,EAAO,CAC/B,IAAIC,EAAe,KAEnB,SAASC,GAAW,CAChB,MAAO,CAAC,CAAC,OAAOC,QAAI,eAAe,OAAO,GAAK,EAAE,EAAE,KAAM,CAC5D,CAED,SAASC,GAAa,CAClBD,EAAG,MAAC,kBAAkB,OAAO,CAChC,CAED,SAASE,GAAc,CACnB,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CACpCJ,EAAAA,MAAI,MAAM,CACN,SAAU,SACV,QAAUK,GAAQA,GAAA,MAAAA,EAAK,KAAOF,EAAQE,EAAI,IAAI,EAAID,EAAO,IAAI,MAAM,cAAc,CAAC,EAClF,KAAMA,CACtB,CAAa,CACb,CAAS,CACJ,CAED,eAAeE,EAAcC,EAAM,OAC/B,MAAMF,EAAM,MAAMR,EAAM,OAAO,CAC3B,IAAK,sBACL,OAAQ,OACR,KAAM,CAAE,KAAAU,CAAM,CACjB,EAAE,EAAK,EACR,IAAIF,GAAA,YAAAA,EAAK,QAAS,GAAK,GAACG,EAAAH,EAAI,OAAJ,MAAAG,EAAU,OAC9B,MAAAP,EAAY,EACN,IAAI,OAAMI,GAAA,YAAAA,EAAK,MAAO,MAAM,EAEtCL,OAAAA,EAAAA,MAAI,eAAe,QAASK,EAAI,KAAK,KAAK,EAC1CL,EAAAA,MAAI,eAAe,WAAYK,EAAI,IAAI,EAChC,EACV,CAED,eAAeI,GAAgB,CAC3B,GAAIV,EAAQ,EAAI,CACZ,GAAI,CACA,MAAMM,EAAM,MAAMR,EAAM,OAAO,CAAE,IAAK,iBAAkB,OAAQ,MAAQ,EAAE,EAAK,EAC/E,IAAIQ,GAAA,YAAAA,EAAK,QAAS,GAAKA,EAAI,KACvBL,OAAAA,EAAAA,MAAI,eAAe,WAAYK,EAAI,IAAI,EAChC,GAGX,IAAIA,GAAA,YAAAA,EAAK,QAAS,GAAI,MAAO,EAChC,MAAW,CAER,MAAO,EACV,CACDJ,EAAY,CACf,CACD,MAAMM,EAAO,MAAML,EAAa,EAChC,OAAOI,EAAcC,CAAI,CAC5B,CAED,eAAeG,GAAiB,CAC5B,OAAIZ,IACJA,EAAeW,EAAe,EACzB,KAAKE,GAAM,CAAC,CAACA,CAAE,EACf,MAAM,IAAM,EAAK,EAEjB,QAAQ,IAAM,CAAEb,EAAe,KAAM,EACnCA,EACV,CAED,MAAO,CAAE,eAAAY,CAAgB,CAC7B"}
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"svgDataUrl.js","sources":["tongji/utils/svgDataUrl.js"],"sourcesContent":["/**\r\n * 将 SVG 字符串转为小程序可用的 data URL(base64 在真机上更稳定)\r\n */\r\n\r\nfunction utf8ToBytes(str) {\r\n const encoded = encodeURIComponent(str)\r\n const bytes = []\r\n for (let i = 0; i < encoded.length; i++) {\r\n if (encoded.charCodeAt(i) === 37) {\r\n bytes.push(parseInt(encoded.substring(i + 1, i + 3), 16))\r\n i += 2\r\n } else {\r\n bytes.push(encoded.charCodeAt(i))\r\n }\r\n }\r\n return new Uint8Array(bytes)\r\n}\r\n\r\nfunction bytesToBase64(bytes) {\r\n if (typeof uni !== 'undefined' && typeof uni.arrayBufferToBase64 === 'function') {\r\n return uni.arrayBufferToBase64(bytes.buffer)\r\n }\r\n if (typeof btoa !== 'undefined') {\r\n let binary = ''\r\n for (let i = 0; i < bytes.length; i++) {\r\n binary += String.fromCharCode(bytes[i])\r\n }\r\n return btoa(binary)\r\n }\r\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\r\n let result = ''\r\n for (let i = 0; i < bytes.length; i += 3) {\r\n const a = bytes[i]\r\n const b = i + 1 < bytes.length ? bytes[i + 1] : 0\r\n const c = i + 2 < bytes.length ? bytes[i + 2] : 0\r\n result += chars[a >> 2]\r\n result += chars[((a & 3) << 4) | (b >> 4)]\r\n result += i + 1 < bytes.length ? chars[((b & 15) << 2) | (c >> 6)] : '='\r\n result += i + 2 < bytes.length ? chars[c & 63] : '='\r\n }\r\n return result\r\n}\r\n\r\nexport function svgToDataUrl(svg) {\r\n const normalized = String(svg || '').trim()\r\n if (!normalized) return ''\r\n const base64 = bytesToBase64(utf8ToBytes(normalized))\r\n return `data:image/svg+xml;base64,${base64}`\r\n}\r\n"],"names":["uni"],"mappings":";;AAIA,SAAS,YAAY,KAAK;AACtB,QAAM,UAAU,mBAAmB,GAAG;AACtC,QAAM,QAAQ,CAAE;AAChB,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACrC,QAAI,QAAQ,WAAW,CAAC,MAAM,IAAI;AAC9B,YAAM,KAAK,SAAS,QAAQ,UAAU,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AACxD,WAAK;AAAA,IACjB,OAAe;AACH,YAAM,KAAK,QAAQ,WAAW,CAAC,CAAC;AAAA,IACnC;AAAA,EACJ;AACD,SAAO,IAAI,WAAW,KAAK;AAC/B;AAEA,SAAS,cAAc,OAAO;AAC1B,MAAI,OAAOA,cAAG,UAAK,eAAe,OAAOA,cAAAA,MAAI,wBAAwB,YAAY;AAC7E,WAAOA,oBAAI,oBAAoB,MAAM,MAAM;AAAA,EAC9C;AACD,MAAI,OAAO,SAAS,aAAa;AAC7B,QAAI,SAAS;AACb,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACnC,gBAAU,OAAO,aAAa,MAAM,CAAC,CAAC;AAAA,IACzC;AACD,WAAO,KAAK,MAAM;AAAA,EACrB;AACD,QAAM,QAAQ;AACd,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;AACtC,UAAM,IAAI,MAAM,CAAC;AACjB,UAAM,IAAI,IAAI,IAAI,MAAM,SAAS,MAAM,IAAI,CAAC,IAAI;AAChD,UAAM,IAAI,IAAI,IAAI,MAAM,SAAS,MAAM,IAAI,CAAC,IAAI;AAChD,cAAU,MAAM,KAAK,CAAC;AACtB,cAAU,OAAQ,IAAI,MAAM,IAAM,KAAK,CAAE;AACzC,cAAU,IAAI,IAAI,MAAM,SAAS,OAAQ,IAAI,OAAO,IAAM,KAAK,CAAE,IAAI;AACrE,cAAU,IAAI,IAAI,MAAM,SAAS,MAAM,IAAI,EAAE,IAAI;AAAA,EACpD;AACD,SAAO;AACX;AAEO,SAAS,aAAa,KAAK;AAC9B,QAAM,aAAa,OAAO,OAAO,EAAE,EAAE,KAAM;AAC3C,MAAI,CAAC;AAAY,WAAO;AACxB,QAAM,SAAS,cAAc,YAAY,UAAU,CAAC;AACpD,SAAO,6BAA6B,MAAM;AAC9C;;"}
|
||||
{"version":3,"file":"svgDataUrl.js","sources":["tongji/utils/svgDataUrl.js"],"sourcesContent":["/**\r\n * 将 SVG 字符串转为小程序可用的 data URL(base64 在真机上更稳定)\r\n */\r\n\r\nfunction utf8ToBytes(str) {\r\n const encoded = encodeURIComponent(str)\r\n const bytes = []\r\n for (let i = 0; i < encoded.length; i++) {\r\n if (encoded.charCodeAt(i) === 37) {\r\n bytes.push(parseInt(encoded.substring(i + 1, i + 3), 16))\r\n i += 2\r\n } else {\r\n bytes.push(encoded.charCodeAt(i))\r\n }\r\n }\r\n return new Uint8Array(bytes)\r\n}\r\n\r\nfunction bytesToBase64(bytes) {\r\n if (typeof uni !== 'undefined' && typeof uni.arrayBufferToBase64 === 'function') {\r\n return uni.arrayBufferToBase64(bytes.buffer)\r\n }\r\n if (typeof btoa !== 'undefined') {\r\n let binary = ''\r\n for (let i = 0; i < bytes.length; i++) {\r\n binary += String.fromCharCode(bytes[i])\r\n }\r\n return btoa(binary)\r\n }\r\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\r\n let result = ''\r\n for (let i = 0; i < bytes.length; i += 3) {\r\n const a = bytes[i]\r\n const b = i + 1 < bytes.length ? bytes[i + 1] : 0\r\n const c = i + 2 < bytes.length ? bytes[i + 2] : 0\r\n result += chars[a >> 2]\r\n result += chars[((a & 3) << 4) | (b >> 4)]\r\n result += i + 1 < bytes.length ? chars[((b & 15) << 2) | (c >> 6)] : '='\r\n result += i + 2 < bytes.length ? chars[c & 63] : '='\r\n }\r\n return result\r\n}\r\n\r\nexport function svgToDataUrl(svg) {\r\n const normalized = String(svg || '').trim()\r\n if (!normalized) return ''\r\n const base64 = bytesToBase64(utf8ToBytes(normalized))\r\n return `data:image/svg+xml;base64,${base64}`\r\n}\r\n"],"names":["utf8ToBytes","str","encoded","bytes","i","bytesToBase64","uni","binary","chars","result","a","b","c","svgToDataUrl","svg","normalized"],"mappings":"uDAIA,SAASA,EAAYC,EAAK,CACtB,MAAMC,EAAU,mBAAmBD,CAAG,EAChCE,EAAQ,CAAE,EAChB,QAASC,EAAI,EAAGA,EAAIF,EAAQ,OAAQE,IAC5BF,EAAQ,WAAWE,CAAC,IAAM,IAC1BD,EAAM,KAAK,SAASD,EAAQ,UAAUE,EAAI,EAAGA,EAAI,CAAC,EAAG,EAAE,CAAC,EACxDA,GAAK,GAELD,EAAM,KAAKD,EAAQ,WAAWE,CAAC,CAAC,EAGxC,OAAO,IAAI,WAAWD,CAAK,CAC/B,CAEA,SAASE,EAAcF,EAAO,CAC1B,GAAI,OAAOG,EAAG,MAAK,KAAe,OAAOA,EAAAA,MAAI,qBAAwB,WACjE,OAAOA,QAAI,oBAAoBH,EAAM,MAAM,EAE/C,GAAI,OAAO,KAAS,IAAa,CAC7B,IAAII,EAAS,GACb,QAASH,EAAI,EAAGA,EAAID,EAAM,OAAQC,IAC9BG,GAAU,OAAO,aAAaJ,EAAMC,CAAC,CAAC,EAE1C,OAAO,KAAKG,CAAM,CACrB,CACD,MAAMC,EAAQ,mEACd,IAAIC,EAAS,GACb,QAASL,EAAI,EAAGA,EAAID,EAAM,OAAQC,GAAK,EAAG,CACtC,MAAMM,EAAIP,EAAMC,CAAC,EACXO,EAAIP,EAAI,EAAID,EAAM,OAASA,EAAMC,EAAI,CAAC,EAAI,EAC1CQ,EAAIR,EAAI,EAAID,EAAM,OAASA,EAAMC,EAAI,CAAC,EAAI,EAChDK,GAAUD,EAAME,GAAK,CAAC,EACtBD,GAAUD,GAAQE,EAAI,IAAM,EAAMC,GAAK,CAAE,EACzCF,GAAUL,EAAI,EAAID,EAAM,OAASK,GAAQG,EAAI,KAAO,EAAMC,GAAK,CAAE,EAAI,IACrEH,GAAUL,EAAI,EAAID,EAAM,OAASK,EAAMI,EAAI,EAAE,EAAI,GACpD,CACD,OAAOH,CACX,CAEO,SAASI,EAAaC,EAAK,CAC9B,MAAMC,EAAa,OAAOD,GAAO,EAAE,EAAE,KAAM,EAC3C,OAAKC,EAEE,6BADQV,EAAcL,EAAYe,CAAU,CAAC,CACV,GAFlB,EAG5B"}
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"treeSpecies.js","sources":["tongji/utils/treeSpecies.js"],"sourcesContent":["import { TREE_LEVELS, TREE_MAX_LEVEL, TREE_XP_PER_LEVEL } from './treeLevels.js'\r\n\r\n/** 可选树种:每级 emoji 与 treeLevels.js Lv.0~9 一一对应 */\r\nexport const TREE_SPECIES_LIST = [\r\n {\r\n id: 'classic',\r\n name: '稳糖灵树',\r\n tagline: '经典路线,从种子到圆满',\r\n stages: TREE_LEVELS.map((l) => l.emoji)\r\n },\r\n {\r\n id: 'bonsai',\r\n name: '雅韵盆景',\r\n tagline: '小巧精致,书桌旁的温柔陪伴',\r\n stages: ['🫘', '🌱', '🪴', '🎋', '🪴', '🌳', '🎍', '🌸', '🏵️', '🏆']\r\n },\r\n {\r\n id: 'pine',\r\n name: '苍劲青松',\r\n tagline: '挺拔向上,越记越稳',\r\n stages: ['🫘', '🌱', '🌿', '🌲', '🌲', '🌲', '⛰️', '🌲', '🏔️', '🏆']\r\n },\r\n {\r\n id: 'sakura',\r\n name: '樱花小树',\r\n tagline: '坚持打卡,枝头渐开',\r\n stages: ['🫘', '🌱', '🌿', '🌳', '🌸', '🌸', '🌸', '🌸', '🌺', '🏆']\r\n },\r\n {\r\n id: 'ginkgo',\r\n name: '金秋银杏',\r\n tagline: '叶色渐变,见证每一天',\r\n stages: ['🫘', '🌱', '🍃', '🌳', '🍂', '🍂', '🌳', '🍁', '🌟', '🏆']\r\n }\r\n]\r\n\r\nexport const TREE_SPECIES_STORAGE_KEY = 'tongji_tree_species_v1'\r\n\r\n/** 四项任务全勤时每日最多可领积分(与后端 taskDefs 一致) */\r\nexport const DAILY_MAX_TASK_POINTS = 40\r\n\r\nexport function getTreeSpecies(id) {\r\n return TREE_SPECIES_LIST.find((s) => s.id === id) || TREE_SPECIES_LIST[0]\r\n}\r\n\r\nexport function speciesEmojiAtLevel(speciesId, level) {\r\n const sp = getTreeSpecies(speciesId)\r\n const lv = Math.min(TREE_MAX_LEVEL, Math.max(0, Number(level) || 0))\r\n return sp.stages[lv] || sp.stages[0] || '🌱'\r\n}\r\n\r\n/** 当前树种成长路线图(供选择面板展示) */\r\nexport function speciesGrowthRoadmap(speciesId) {\r\n const sp = getTreeSpecies(speciesId)\r\n return TREE_LEVELS.map((meta, i) => {\r\n const xpTotal = i * TREE_XP_PER_LEVEL\r\n const daysHint = i === 0\r\n ? 0\r\n : Math.max(1, Math.ceil(xpTotal / DAILY_MAX_TASK_POINTS))\r\n return {\r\n level: i,\r\n name: meta.name,\r\n emoji: sp.stages[i] || meta.emoji,\r\n desc: meta.desc,\r\n xpTotal,\r\n daysHint\r\n }\r\n })\r\n}\r\n\r\n/** 全勤打卡大约多少天满级 */\r\nexport function estimateDaysToMaxLevel() {\r\n const totalXp = TREE_MAX_LEVEL * TREE_XP_PER_LEVEL\r\n return Math.max(1, Math.ceil(totalXp / DAILY_MAX_TASK_POINTS))\r\n}\r\n"],"names":["TREE_LEVELS","TREE_MAX_LEVEL","TREE_XP_PER_LEVEL"],"mappings":";;AAGY,MAAC,oBAAoB;AAAA,EAC7B;AAAA,IACI,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,QAAQA,wBAAW,YAAC,IAAI,CAAC,MAAM,EAAE,KAAK;AAAA,EACzC;AAAA,EACD;AAAA,IACI,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,QAAQ,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,OAAO,IAAI;AAAA,EACvE;AAAA,EACD;AAAA,IACI,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,QAAQ,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,OAAO,IAAI;AAAA,EACvE;AAAA,EACD;AAAA,IACI,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,QAAQ,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI;AAAA,EACtE;AAAA,EACD;AAAA,IACI,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,QAAQ,CAAC,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI;AAAA,EACtE;AACL;AAKO,MAAM,wBAAwB;AAE9B,SAAS,eAAe,IAAI;AAC/B,SAAO,kBAAkB,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,kBAAkB,CAAC;AAC5E;AAEO,SAAS,oBAAoB,WAAW,OAAO;AAClD,QAAM,KAAK,eAAe,SAAS;AACnC,QAAM,KAAK,KAAK,IAAIC,wBAAc,gBAAE,KAAK,IAAI,GAAG,OAAO,KAAK,KAAK,CAAC,CAAC;AACnE,SAAO,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK;AAC5C;AAGO,SAAS,qBAAqB,WAAW;AAC5C,QAAM,KAAK,eAAe,SAAS;AACnC,SAAOD,oCAAY,IAAI,CAAC,MAAM,MAAM;AAChC,UAAM,UAAU,IAAIE,wBAAiB;AACrC,UAAM,WAAW,MAAM,IACjB,IACA,KAAK,IAAI,GAAG,KAAK,KAAK,UAAU,qBAAqB,CAAC;AAC5D,WAAO;AAAA,MACH,OAAO;AAAA,MACP,MAAM,KAAK;AAAA,MACX,OAAO,GAAG,OAAO,CAAC,KAAK,KAAK;AAAA,MAC5B,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,IACH;AAAA,EACT,CAAK;AACL;AAGO,SAAS,yBAAyB;AACrC,QAAM,UAAUD,wBAAAA,iBAAiBC,wBAAiB;AAClD,SAAO,KAAK,IAAI,GAAG,KAAK,KAAK,UAAU,qBAAqB,CAAC;AACjE;;;;;;"}
|
||||
{"version":3,"file":"treeSpecies.js","sources":["tongji/utils/treeSpecies.js"],"sourcesContent":["import { TREE_LEVELS, TREE_MAX_LEVEL, TREE_XP_PER_LEVEL } from './treeLevels.js'\r\n\r\n/** 可选树种:每级 emoji 与 treeLevels.js Lv.0~9 一一对应 */\r\nexport const TREE_SPECIES_LIST = [\r\n {\r\n id: 'classic',\r\n name: '稳糖灵树',\r\n tagline: '经典路线,从种子到圆满',\r\n stages: TREE_LEVELS.map((l) => l.emoji)\r\n },\r\n {\r\n id: 'bonsai',\r\n name: '雅韵盆景',\r\n tagline: '小巧精致,书桌旁的温柔陪伴',\r\n stages: ['🫘', '🌱', '🪴', '🎋', '🪴', '🌳', '🎍', '🌸', '🏵️', '🏆']\r\n },\r\n {\r\n id: 'pine',\r\n name: '苍劲青松',\r\n tagline: '挺拔向上,越记越稳',\r\n stages: ['🫘', '🌱', '🌿', '🌲', '🌲', '🌲', '⛰️', '🌲', '🏔️', '🏆']\r\n },\r\n {\r\n id: 'sakura',\r\n name: '樱花小树',\r\n tagline: '坚持打卡,枝头渐开',\r\n stages: ['🫘', '🌱', '🌿', '🌳', '🌸', '🌸', '🌸', '🌸', '🌺', '🏆']\r\n },\r\n {\r\n id: 'ginkgo',\r\n name: '金秋银杏',\r\n tagline: '叶色渐变,见证每一天',\r\n stages: ['🫘', '🌱', '🍃', '🌳', '🍂', '🍂', '🌳', '🍁', '🌟', '🏆']\r\n }\r\n]\r\n\r\nexport const TREE_SPECIES_STORAGE_KEY = 'tongji_tree_species_v1'\r\n\r\n/** 四项任务全勤时每日最多可领积分(与后端 taskDefs 一致) */\r\nexport const DAILY_MAX_TASK_POINTS = 40\r\n\r\nexport function getTreeSpecies(id) {\r\n return TREE_SPECIES_LIST.find((s) => s.id === id) || TREE_SPECIES_LIST[0]\r\n}\r\n\r\nexport function speciesEmojiAtLevel(speciesId, level) {\r\n const sp = getTreeSpecies(speciesId)\r\n const lv = Math.min(TREE_MAX_LEVEL, Math.max(0, Number(level) || 0))\r\n return sp.stages[lv] || sp.stages[0] || '🌱'\r\n}\r\n\r\n/** 当前树种成长路线图(供选择面板展示) */\r\nexport function speciesGrowthRoadmap(speciesId) {\r\n const sp = getTreeSpecies(speciesId)\r\n return TREE_LEVELS.map((meta, i) => {\r\n const xpTotal = i * TREE_XP_PER_LEVEL\r\n const daysHint = i === 0\r\n ? 0\r\n : Math.max(1, Math.ceil(xpTotal / DAILY_MAX_TASK_POINTS))\r\n return {\r\n level: i,\r\n name: meta.name,\r\n emoji: sp.stages[i] || meta.emoji,\r\n desc: meta.desc,\r\n xpTotal,\r\n daysHint\r\n }\r\n })\r\n}\r\n\r\n/** 全勤打卡大约多少天满级 */\r\nexport function estimateDaysToMaxLevel() {\r\n const totalXp = TREE_MAX_LEVEL * TREE_XP_PER_LEVEL\r\n return Math.max(1, Math.ceil(totalXp / DAILY_MAX_TASK_POINTS))\r\n}\r\n"],"names":["TREE_SPECIES_LIST","TREE_LEVELS","l","DAILY_MAX_TASK_POINTS","getTreeSpecies","id","s","speciesEmojiAtLevel","speciesId","level","sp","lv","TREE_MAX_LEVEL","speciesGrowthRoadmap","meta","i","xpTotal","TREE_XP_PER_LEVEL","daysHint","estimateDaysToMaxLevel","totalXp"],"mappings":"gDAGaA,EAAoB,CAC7B,CACI,GAAI,UACJ,KAAM,OACN,QAAS,cACT,OAAQC,EAAW,YAAC,IAAKC,GAAMA,EAAE,KAAK,CACzC,EACD,CACI,GAAI,SACJ,KAAM,OACN,QAAS,gBACT,OAAQ,CAAC,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,MAAO,IAAI,CACvE,EACD,CACI,GAAI,OACJ,KAAM,OACN,QAAS,YACT,OAAQ,CAAC,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,MAAO,IAAI,CACvE,EACD,CACI,GAAI,SACJ,KAAM,OACN,QAAS,YACT,OAAQ,CAAC,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAI,CACtE,EACD,CACI,GAAI,SACJ,KAAM,OACN,QAAS,aACT,OAAQ,CAAC,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,IAAI,CACtE,CACL,EAKaC,EAAwB,GAE9B,SAASC,EAAeC,EAAI,CAC/B,OAAOL,EAAkB,KAAMM,GAAMA,EAAE,KAAOD,CAAE,GAAKL,EAAkB,CAAC,CAC5E,CAEO,SAASO,EAAoBC,EAAWC,EAAO,CAClD,MAAMC,EAAKN,EAAeI,CAAS,EAC7BG,EAAK,KAAK,IAAIC,EAAc,eAAE,KAAK,IAAI,EAAG,OAAOH,CAAK,GAAK,CAAC,CAAC,EACnE,OAAOC,EAAG,OAAOC,CAAE,GAAKD,EAAG,OAAO,CAAC,GAAK,IAC5C,CAGO,SAASG,EAAqBL,EAAW,CAC5C,MAAME,EAAKN,EAAeI,CAAS,EACnC,OAAOP,cAAY,IAAI,CAACa,EAAMC,IAAM,CAChC,MAAMC,EAAUD,EAAIE,EAAiB,kBAC/BC,EAAWH,IAAM,EACjB,EACA,KAAK,IAAI,EAAG,KAAK,KAAKC,EAAUb,CAAqB,CAAC,EAC5D,MAAO,CACH,MAAOY,EACP,KAAMD,EAAK,KACX,MAAOJ,EAAG,OAAOK,CAAC,GAAKD,EAAK,MAC5B,KAAMA,EAAK,KACX,QAAAE,EACA,SAAAE,CACH,CACT,CAAK,CACL,CAGO,SAASC,GAAyB,CACrC,MAAMC,EAAUR,EAAAA,eAAiBK,EAAiB,kBAClD,OAAO,KAAK,IAAI,EAAG,KAAK,KAAKG,EAAUjB,CAAqB,CAAC,CACjE"}
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"uni-icons.js","sources":["uni_modules/uni-icons/components/uni-icons/uni-icons.vue","../../../soft/HBuilderX/plugins/uniapp-cli-vite/uniComponent:/RDovd2ViL3p5dC9Ub25namlVbmlBcHAvdW5pX21vZHVsZXMvdW5pLWljb25zL2NvbXBvbmVudHMvdW5pLWljb25zL3VuaS1pY29ucy52dWU"],"sourcesContent":["<template>\r\n\t<!-- #ifdef APP-NVUE -->\r\n\t<text :style=\"styleObj\" class=\"uni-icons\" @click=\"_onClick\">{{unicode}}</text>\r\n\t<!-- #endif -->\r\n\t<!-- #ifndef APP-NVUE -->\r\n\t<text :style=\"styleObj\" class=\"uni-icons\" :class=\"['uniui-'+type,customPrefix,customPrefix?type:'']\" @click=\"_onClick\">\r\n\t\t<slot></slot>\r\n\t</text>\r\n\t<!-- #endif -->\r\n</template>\r\n\r\n<script>\r\n\timport { fontData } from './uniicons_file_vue.js';\r\n\r\n\tconst getVal = (val) => {\r\n\t\tconst reg = /^[0-9]*$/g\r\n\t\treturn (typeof val === 'number' || reg.test(val)) ? val + 'px' : val;\r\n\t}\r\n\r\n\t// #ifdef APP-NVUE\r\n\tvar domModule = weex.requireModule('dom');\r\n\timport iconUrl from './uniicons.ttf'\r\n\tdomModule.addRule('fontFace', {\r\n\t\t'fontFamily': \"uniicons\",\r\n\t\t'src': \"url('\" + iconUrl + \"')\"\r\n\t});\r\n\t// #endif\r\n\r\n\t/**\r\n\t * Icons 图标\r\n\t * @description 用于展示 icons 图标\r\n\t * @tutorial https://ext.dcloud.net.cn/plugin?id=28\r\n\t * @property {Number} size 图标大小\r\n\t * @property {String} type 图标图案,参考示例\r\n\t * @property {String} color 图标颜色\r\n\t * @property {String} customPrefix 自定义图标\r\n\t * @event {Function} click 点击 Icon 触发事件\r\n\t */\r\n\texport default {\r\n\t\tname: 'UniIcons',\r\n\t\temits: ['click'],\r\n\t\tprops: {\r\n\t\t\ttype: {\r\n\t\t\t\ttype: String,\r\n\t\t\t\tdefault: ''\r\n\t\t\t},\r\n\t\t\tcolor: {\r\n\t\t\t\ttype: String,\r\n\t\t\t\tdefault: '#333333'\r\n\t\t\t},\r\n\t\t\tsize: {\r\n\t\t\t\ttype: [Number, String],\r\n\t\t\t\tdefault: 16\r\n\t\t\t},\r\n\t\t\tcustomPrefix: {\r\n\t\t\t\ttype: String,\r\n\t\t\t\tdefault: ''\r\n\t\t\t},\r\n\t\t\tfontFamily: {\r\n\t\t\t\ttype: String,\r\n\t\t\t\tdefault: ''\r\n\t\t\t}\r\n\t\t},\r\n\t\tdata() {\r\n\t\t\treturn {\r\n\t\t\t\ticons: fontData\r\n\t\t\t}\r\n\t\t},\r\n\t\tcomputed: {\r\n\t\t\tunicode() {\r\n\t\t\t\tlet code = this.icons.find(v => v.font_class === this.type)\r\n\t\t\t\tif (code) {\r\n\t\t\t\t\treturn code.unicode\r\n\t\t\t\t}\r\n\t\t\t\treturn ''\r\n\t\t\t},\r\n\t\t\ticonSize() {\r\n\t\t\t\treturn getVal(this.size)\r\n\t\t\t},\r\n\t\t\tstyleObj() {\r\n\t\t\t\tif (this.fontFamily !== '') {\r\n\t\t\t\t\treturn `color: ${this.color}; font-size: ${this.iconSize}; font-family: ${this.fontFamily};`\r\n\t\t\t\t}\r\n\t\t\t\treturn `color: ${this.color}; font-size: ${this.iconSize};`\r\n\t\t\t}\r\n\t\t},\r\n\t\tmethods: {\r\n\t\t\t_onClick() {\r\n\t\t\t\tthis.$emit('click')\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n</script>\r\n\r\n<style lang=\"scss\">\r\n\t/* #ifndef APP-NVUE */\r\n\t@import './uniicons.css';\r\n\r\n\t@font-face {\r\n\t\tfont-family: uniicons;\r\n\t\tsrc: url('./uniicons.ttf');\r\n\t}\r\n\r\n\t/* #endif */\r\n\t.uni-icons {\r\n\t\tfont-family: uniicons;\r\n\t\ttext-decoration: none;\r\n\t\ttext-align: center;\r\n\t}\r\n</style>\n","import Component from 'D:/web/zyt/TongjiUniApp/uni_modules/uni-icons/components/uni-icons/uni-icons.vue'\nwx.createComponent(Component)"],"names":["fontData"],"mappings":";;;AAcC,MAAM,SAAS,CAAC,QAAQ;AACvB,QAAM,MAAM;AACZ,SAAQ,OAAO,QAAQ,YAAY,IAAI,KAAK,GAAG,IAAK,MAAM,OAAO;AAClE;AAqBA,MAAK,YAAU;AAAA,EACd,MAAM;AAAA,EACN,OAAO,CAAC,OAAO;AAAA,EACf,OAAO;AAAA,IACN,MAAM;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,IACT;AAAA,IACD,OAAO;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,IACT;AAAA,IACD,MAAM;AAAA,MACL,MAAM,CAAC,QAAQ,MAAM;AAAA,MACrB,SAAS;AAAA,IACT;AAAA,IACD,cAAc;AAAA,MACb,MAAM;AAAA,MACN,SAAS;AAAA,IACT;AAAA,IACD,YAAY;AAAA,MACX,MAAM;AAAA,MACN,SAAS;AAAA,IACV;AAAA,EACA;AAAA,EACD,OAAO;AACN,WAAO;AAAA,MACN,OAAOA,2DAAO;AAAA,IACf;AAAA,EACA;AAAA,EACD,UAAU;AAAA,IACT,UAAU;AACT,UAAI,OAAO,KAAK,MAAM,KAAK,OAAK,EAAE,eAAe,KAAK,IAAI;AAC1D,UAAI,MAAM;AACT,eAAO,KAAK;AAAA,MACb;AACA,aAAO;AAAA,IACP;AAAA,IACD,WAAW;AACV,aAAO,OAAO,KAAK,IAAI;AAAA,IACvB;AAAA,IACD,WAAW;AACV,UAAI,KAAK,eAAe,IAAI;AAC3B,eAAO,UAAU,KAAK,KAAK,gBAAgB,KAAK,QAAQ,kBAAkB,KAAK,UAAU;AAAA,MAC1F;AACA,aAAO,UAAU,KAAK,KAAK,gBAAgB,KAAK,QAAQ;AAAA,IACzD;AAAA,EACA;AAAA,EACD,SAAS;AAAA,IACR,WAAW;AACV,WAAK,MAAM,OAAO;AAAA,IACnB;AAAA,EACD;AACD;;;;;;;;;;;AC1FD,GAAG,gBAAgB,SAAS;"}
|
||||
{"version":3,"file":"uni-icons.js","sources":["uni_modules/uni-icons/components/uni-icons/uni-icons.vue","../../../soft/HBuilderX/plugins/uniapp-cli-vite/uniComponent:/RDovd2ViL3p5dC9Ub25namlVbmlBcHAvdW5pX21vZHVsZXMvdW5pLWljb25zL2NvbXBvbmVudHMvdW5pLWljb25zL3VuaS1pY29ucy52dWU"],"sourcesContent":["<template>\r\n\t<!-- #ifdef APP-NVUE -->\r\n\t<text :style=\"styleObj\" class=\"uni-icons\" @click=\"_onClick\">{{unicode}}</text>\r\n\t<!-- #endif -->\r\n\t<!-- #ifndef APP-NVUE -->\r\n\t<text :style=\"styleObj\" class=\"uni-icons\" :class=\"['uniui-'+type,customPrefix,customPrefix?type:'']\" @click=\"_onClick\">\r\n\t\t<slot></slot>\r\n\t</text>\r\n\t<!-- #endif -->\r\n</template>\r\n\r\n<script>\r\n\timport { fontData } from './uniicons_file_vue.js';\r\n\r\n\tconst getVal = (val) => {\r\n\t\tconst reg = /^[0-9]*$/g\r\n\t\treturn (typeof val === 'number' || reg.test(val)) ? val + 'px' : val;\r\n\t}\r\n\r\n\t// #ifdef APP-NVUE\r\n\tvar domModule = weex.requireModule('dom');\r\n\timport iconUrl from './uniicons.ttf'\r\n\tdomModule.addRule('fontFace', {\r\n\t\t'fontFamily': \"uniicons\",\r\n\t\t'src': \"url('\" + iconUrl + \"')\"\r\n\t});\r\n\t// #endif\r\n\r\n\t/**\r\n\t * Icons 图标\r\n\t * @description 用于展示 icons 图标\r\n\t * @tutorial https://ext.dcloud.net.cn/plugin?id=28\r\n\t * @property {Number} size 图标大小\r\n\t * @property {String} type 图标图案,参考示例\r\n\t * @property {String} color 图标颜色\r\n\t * @property {String} customPrefix 自定义图标\r\n\t * @event {Function} click 点击 Icon 触发事件\r\n\t */\r\n\texport default {\r\n\t\tname: 'UniIcons',\r\n\t\temits: ['click'],\r\n\t\tprops: {\r\n\t\t\ttype: {\r\n\t\t\t\ttype: String,\r\n\t\t\t\tdefault: ''\r\n\t\t\t},\r\n\t\t\tcolor: {\r\n\t\t\t\ttype: String,\r\n\t\t\t\tdefault: '#333333'\r\n\t\t\t},\r\n\t\t\tsize: {\r\n\t\t\t\ttype: [Number, String],\r\n\t\t\t\tdefault: 16\r\n\t\t\t},\r\n\t\t\tcustomPrefix: {\r\n\t\t\t\ttype: String,\r\n\t\t\t\tdefault: ''\r\n\t\t\t},\r\n\t\t\tfontFamily: {\r\n\t\t\t\ttype: String,\r\n\t\t\t\tdefault: ''\r\n\t\t\t}\r\n\t\t},\r\n\t\tdata() {\r\n\t\t\treturn {\r\n\t\t\t\ticons: fontData\r\n\t\t\t}\r\n\t\t},\r\n\t\tcomputed: {\r\n\t\t\tunicode() {\r\n\t\t\t\tlet code = this.icons.find(v => v.font_class === this.type)\r\n\t\t\t\tif (code) {\r\n\t\t\t\t\treturn code.unicode\r\n\t\t\t\t}\r\n\t\t\t\treturn ''\r\n\t\t\t},\r\n\t\t\ticonSize() {\r\n\t\t\t\treturn getVal(this.size)\r\n\t\t\t},\r\n\t\t\tstyleObj() {\r\n\t\t\t\tif (this.fontFamily !== '') {\r\n\t\t\t\t\treturn `color: ${this.color}; font-size: ${this.iconSize}; font-family: ${this.fontFamily};`\r\n\t\t\t\t}\r\n\t\t\t\treturn `color: ${this.color}; font-size: ${this.iconSize};`\r\n\t\t\t}\r\n\t\t},\r\n\t\tmethods: {\r\n\t\t\t_onClick() {\r\n\t\t\t\tthis.$emit('click')\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n</script>\r\n\r\n<style lang=\"scss\">\r\n\t/* #ifndef APP-NVUE */\r\n\t@import './uniicons.css';\r\n\r\n\t@font-face {\r\n\t\tfont-family: uniicons;\r\n\t\tsrc: url('./uniicons.ttf');\r\n\t}\r\n\r\n\t/* #endif */\r\n\t.uni-icons {\r\n\t\tfont-family: uniicons;\r\n\t\ttext-decoration: none;\r\n\t\ttext-align: center;\r\n\t}\r\n</style>\n","import Component from 'D:/web/zyt/TongjiUniApp/uni_modules/uni-icons/components/uni-icons/uni-icons.vue'\nwx.createComponent(Component)"],"names":["getVal","val","_sfc_main","fontData","code","v","Component"],"mappings":"iGAcOA,EAAUC,GAEP,OAAOA,GAAQ,UADX,YAC2B,KAAKA,CAAG,EAAKA,EAAM,KAAOA,EAsB7DC,EAAU,CACd,KAAM,WACN,MAAO,CAAC,OAAO,EACf,MAAO,CACN,KAAM,CACL,KAAM,OACN,QAAS,EACT,EACD,MAAO,CACN,KAAM,OACN,QAAS,SACT,EACD,KAAM,CACL,KAAM,CAAC,OAAQ,MAAM,EACrB,QAAS,EACT,EACD,aAAc,CACb,KAAM,OACN,QAAS,EACT,EACD,WAAY,CACX,KAAM,OACN,QAAS,EACV,CACA,EACD,MAAO,CACN,MAAO,CACN,MAAOC,EAAO,QACf,CACA,EACD,SAAU,CACT,SAAU,CACT,IAAIC,EAAO,KAAK,MAAM,KAAKC,GAAKA,EAAE,aAAe,KAAK,IAAI,EAC1D,OAAID,EACIA,EAAK,QAEN,EACP,EACD,UAAW,CACV,OAAOJ,EAAO,KAAK,IAAI,CACvB,EACD,UAAW,CACV,OAAI,KAAK,aAAe,GAChB,UAAU,KAAK,KAAK,gBAAgB,KAAK,QAAQ,kBAAkB,KAAK,UAAU,IAEnF,UAAU,KAAK,KAAK,gBAAgB,KAAK,QAAQ,GACzD,CACA,EACD,QAAS,CACR,UAAW,CACV,KAAK,MAAM,OAAO,CACnB,CACD,CACD,0NC1FD,GAAG,gBAAgBM,CAAS"}
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-164
@@ -1,165 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
const common_vendor = require("./common/vendor.js");
|
||||
if (!Math) {
|
||||
"./tongji/pages/weekly.js";
|
||||
"./pages/user/user.js";
|
||||
"./pages/user/userinfo.js";
|
||||
"./pages/Card/Card.js";
|
||||
"./pages/Card/edit_card.js";
|
||||
"./pages/Card/contact.js";
|
||||
"./tongji/pages/index.js";
|
||||
"./tongji/pages/more.js";
|
||||
"./tongji/endless-game/index.js";
|
||||
"./training/pages/grip-ring.js";
|
||||
"./training/pages/pilates-ring.js";
|
||||
"./training/pages/foot-pedal.js";
|
||||
"./training/pages/dumbbell.js";
|
||||
"./training/pages/metronome.js";
|
||||
}
|
||||
const _sfc_main = {
|
||||
__name: "App",
|
||||
setup(__props) {
|
||||
const { proxy } = common_vendor.getCurrentInstance();
|
||||
common_vendor.onLaunch(() => {
|
||||
try {
|
||||
common_vendor.index.setInnerAudioOption({
|
||||
obeyMuteSwitch: false,
|
||||
mixWithOther: true
|
||||
});
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("warn", "at App.vue:16", "setInnerAudioOption failed:", e);
|
||||
}
|
||||
common_vendor.index.login({
|
||||
provider: "weixin",
|
||||
success: function(loginRes) {
|
||||
if (common_vendor.index.getStorageSync("token")) {
|
||||
userinfo(loginRes.code);
|
||||
} else {
|
||||
wxcode(loginRes.code);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
const wxcode = async (code) => {
|
||||
try {
|
||||
const res = await proxy.apiUrl(
|
||||
{
|
||||
url: "/api/login/mnpLogin",
|
||||
method: "POST",
|
||||
data: {
|
||||
code
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
if (res && res.data && res.data.token) {
|
||||
common_vendor.index.setStorageSync("token", res.data.token);
|
||||
common_vendor.index.setStorageSync("userData", res.data);
|
||||
}
|
||||
} catch (err) {
|
||||
}
|
||||
};
|
||||
const userinfo = async (code) => {
|
||||
try {
|
||||
const res = await proxy.apiUrl(
|
||||
{
|
||||
url: "/api/user/info",
|
||||
method: "POST"
|
||||
},
|
||||
false
|
||||
);
|
||||
if (res.code == -1) {
|
||||
wxcode(code);
|
||||
return;
|
||||
}
|
||||
if (res && res.data) {
|
||||
common_vendor.index.setStorageSync("userData", res.data);
|
||||
}
|
||||
} catch (err) {
|
||||
}
|
||||
};
|
||||
return () => {
|
||||
};
|
||||
}
|
||||
};
|
||||
var baseUrl = "https://admin.zhenyangtang.com.cn/";
|
||||
function joinApiUrl(base, path) {
|
||||
const b = String(base || "").replace(/\/+$/, "");
|
||||
const p = String(path || "").replace(/^\/+/, "");
|
||||
return p ? `${b}/${p}` : b;
|
||||
}
|
||||
function apiUrl(promise, Loading = true) {
|
||||
const token = common_vendor.index.getStorageSync("token");
|
||||
const header = {
|
||||
token,
|
||||
"content-type": "application/x-www-form-urlencoded",
|
||||
...promise.header || {}
|
||||
};
|
||||
const data = promise.data || {};
|
||||
const url = joinApiUrl(baseUrl, promise.url || "");
|
||||
return new Promise((resolve, reject) => {
|
||||
if (Loading) {
|
||||
common_vendor.index.showLoading({ title: "加载中...", mask: true });
|
||||
}
|
||||
common_vendor.index.request({
|
||||
url,
|
||||
data,
|
||||
timeout: promise.timeout != null ? promise.timeout : 15e3,
|
||||
method: promise.method || "POST",
|
||||
header,
|
||||
sslVerify: false,
|
||||
success: (res) => {
|
||||
const data2 = res.data;
|
||||
if (data2.code === -1) {
|
||||
common_vendor.index.removeStorageSync("token");
|
||||
}
|
||||
resolve(data2);
|
||||
},
|
||||
fail: (e) => {
|
||||
reject(e);
|
||||
},
|
||||
complete: (e) => {
|
||||
if (Loading) {
|
||||
common_vendor.index.hideLoading();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
function parsePageParams(options) {
|
||||
const params = {};
|
||||
if (!options)
|
||||
return params;
|
||||
if (options.scene) {
|
||||
try {
|
||||
const decodedScene = decodeURIComponent(options.scene);
|
||||
decodedScene.split("&").forEach((item) => {
|
||||
const [key, value] = item.split("=");
|
||||
if (key && value) {
|
||||
params[key] = value;
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
common_vendor.index.__f__("error", "at main.js:126", "解析scene参数失败:", error);
|
||||
}
|
||||
}
|
||||
Object.keys(options).forEach((key) => {
|
||||
if (key !== "scene" && options[key]) {
|
||||
params[key] = options[key];
|
||||
}
|
||||
});
|
||||
return params;
|
||||
}
|
||||
function createApp() {
|
||||
const app = common_vendor.createSSRApp(_sfc_main);
|
||||
app.config.globalProperties.$url = baseUrl;
|
||||
app.config.globalProperties.apiUrl = apiUrl;
|
||||
app.config.globalProperties.$parsePageParams = parsePageParams;
|
||||
return {
|
||||
app
|
||||
};
|
||||
}
|
||||
createApp().app.mount("#app");
|
||||
exports.createApp = createApp;
|
||||
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./common/vendor.js"),l={__name:"App",setup(e){const{proxy:o}=n.getCurrentInstance();n.onLaunch(()=>{try{n.index.setInnerAudioOption({obeyMuteSwitch:!1,mixWithOther:!0})}catch(r){n.index.__f__("warn","at App.vue:16","setInnerAudioOption failed:",r)}n.index.login({provider:"weixin",success:function(r){n.index.getStorageSync("token")?s(r.code):a(r.code)}})});const a=async r=>{try{const t=await o.apiUrl({url:"/api/login/mnpLogin",method:"POST",data:{code:r}},!1);t&&t.data&&t.data.token&&(n.index.setStorageSync("token",t.data.token),n.index.setStorageSync("userData",t.data))}catch{}},s=async r=>{try{const t=await o.apiUrl({url:"/api/user/info",method:"POST"},!1);if(t.code==-1){a(r);return}t&&t.data&&n.index.setStorageSync("userData",t.data)}catch{}};return()=>{}}};var d="https://xt.zhenyangtang.com.cn/";function f(e,o){const a=String(e||"").replace(/\/+$/,""),s=String(o||"").replace(/^\/+/,"");return s?`${a}/${s}`:a}function m(e,o=!0){const s={token:n.index.getStorageSync("token"),"content-type":"application/x-www-form-urlencoded",...e.header||{}},r=e.data||{},t=f(d,e.url||"");return new Promise((g,u)=>{o&&n.index.showLoading({title:"加载中...",mask:!0}),n.index.request({url:t,data:r,timeout:e.timeout!=null?e.timeout:15e3,method:e.method||"POST",header:s,sslVerify:!1,success:i=>{const c=i.data;c.code===-1&&n.index.removeStorageSync("token"),g(c)},fail:i=>{u(i)},complete:i=>{o&&n.index.hideLoading()}})})}function S(e){const o={};if(!e)return o;if(e.scene)try{decodeURIComponent(e.scene).split("&").forEach(s=>{const[r,t]=s.split("=");r&&t&&(o[r]=t)})}catch(a){n.index.__f__("error","at main.js:126","解析scene参数失败:",a)}return Object.keys(e).forEach(a=>{a!=="scene"&&e[a]&&(o[a]=e[a])}),o}function p(){const e=n.createSSRApp(l);return e.config.globalProperties.$url=d,e.config.globalProperties.apiUrl=m,e.config.globalProperties.$parsePageParams=S,{app:e}}p().app.mount("#app");exports.createApp=p;
|
||||
//# sourceMappingURL=../.sourcemap/mp-weixin/app.js.map
|
||||
|
||||
+1
-6
@@ -1,7 +1,2 @@
|
||||
/* 全局基础 */
|
||||
page {
|
||||
background-color: #f4fbf4;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
|
||||
sans-serif;
|
||||
}
|
||||
page{background-color:#f4fbf4;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}
|
||||
page{--status-bar-height:25px;--top-window-height:0px;--window-top:0px;--window-bottom:0px;--window-left:0px;--window-right:0px;--window-magin:0px}[data-c-h="true"]{display: none !important;}
|
||||
+10
-8354
File diff suppressed because one or more lines are too long
+1
-39
@@ -1,40 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const color = "#8a8a8a";
|
||||
const activeColor = "#204e2b";
|
||||
const _sfc_main = {
|
||||
__name: "tab-bar-dock",
|
||||
props: {
|
||||
/** 0 血糖 1 我的 */
|
||||
active: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
setup(__props) {
|
||||
const props = __props;
|
||||
function goUser() {
|
||||
if (props.active === 1)
|
||||
return;
|
||||
common_vendor.index.redirectTo({ url: "/pages/user/user" });
|
||||
}
|
||||
function goWeekly() {
|
||||
if (props.active === 0)
|
||||
return;
|
||||
common_vendor.index.redirectTo({ url: "/tongji/pages/weekly" });
|
||||
}
|
||||
return (_ctx, _cache) => {
|
||||
return {
|
||||
a: __props.active === 0 ? 1 : "",
|
||||
b: __props.active === 0 ? activeColor : color,
|
||||
c: common_vendor.o(goWeekly, "40"),
|
||||
d: __props.active === 1 ? "/static/user/user_no.png" : "/static/user/user.png",
|
||||
e: __props.active === 1 ? activeColor : color,
|
||||
f: common_vendor.o(goUser, "79")
|
||||
};
|
||||
};
|
||||
}
|
||||
};
|
||||
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-c3efacf5"]]);
|
||||
wx.createComponent(Component);
|
||||
"use strict";const t=require("../../common/vendor.js"),r="#8a8a8a",n="#204e2b",i={__name:"tab-bar-dock",props:{active:{type:Number,default:0}},setup(e){const c=e;function o(){c.active!==1&&t.index.redirectTo({url:"/pages/user/user"})}function a(){c.active!==0&&t.index.redirectTo({url:"/tongji/pages/weekly"})}return(u,d)=>({a:e.active===0?1:"",b:e.active===0?n:r,c:t.o(a,"40"),d:e.active===1?"/static/user/user_no.png":"/static/user/user.png",e:e.active===1?n:r,f:t.o(o,"79")})}},s=t._export_sfc(i,[["__scopeId","data-v-c3efacf5"]]);wx.createComponent(s);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/components/app-tab-bar/tab-bar-dock.js.map
|
||||
|
||||
+1
-90
@@ -1,90 +1 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
/* 颜色变量 */
|
||||
/* 行为相关颜色 */
|
||||
/* 文字基本颜色 */
|
||||
/* 背景颜色 */
|
||||
/* 边框颜色 */
|
||||
/* 尺寸变量 */
|
||||
/* 文字尺寸 */
|
||||
/* 图片尺寸 */
|
||||
/* Border Radius */
|
||||
/* 水平间距 */
|
||||
/* 垂直间距 */
|
||||
/* 透明度 */
|
||||
/* 文章场景相关 */
|
||||
.tab-dock.data-v-c3efacf5 {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 999;
|
||||
background: #ffffff;
|
||||
border-top: 1rpx solid rgba(0, 0, 0, 0.06);
|
||||
box-shadow: 0 -6rpx 20rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.tab-dock__inner.data-v-c3efacf5 {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
height: 100rpx;
|
||||
}
|
||||
.tab-dock__item.data-v-c3efacf5 {
|
||||
flex: 1;
|
||||
height: 100rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.tab-dock__item--center.data-v-c3efacf5 {
|
||||
justify-content: flex-end;
|
||||
padding-bottom: 6rpx;
|
||||
}
|
||||
.tab-dock__icon.data-v-c3efacf5 {
|
||||
width: 46rpx;
|
||||
height: 46rpx;
|
||||
}
|
||||
.tab-dock__label.data-v-c3efacf5 {
|
||||
margin-top: 6rpx;
|
||||
font-size: 22rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.tab-dock__label--center.data-v-c3efacf5 {
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
.tab-dock__fab.data-v-c3efacf5 {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
margin-top: -48rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(180deg, #2d7340 0%, #204e2b 100%);
|
||||
border: 6rpx solid #ffffff;
|
||||
box-shadow: 0 10rpx 24rpx rgba(32, 78, 43, 0.35);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.tab-dock__fab--active.data-v-c3efacf5 {
|
||||
transform: scale(1.04);
|
||||
box-shadow: 0 12rpx 28rpx rgba(32, 78, 43, 0.42);
|
||||
}
|
||||
.tab-dock__fab-text.data-v-c3efacf5 {
|
||||
color: #ffffff;
|
||||
font-size: 38rpx;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
.tab-dock__safe.data-v-c3efacf5 {
|
||||
height: env(safe-area-inset-bottom);
|
||||
background: #ffffff;
|
||||
}
|
||||
.tab-dock.data-v-c3efacf5{position:fixed;left:0;right:0;bottom:0;z-index:999;background:#fff;border-top:1rpx solid rgba(0,0,0,.06);box-shadow:0 -6rpx 20rpx rgba(0,0,0,.04)}.tab-dock__inner.data-v-c3efacf5{display:flex;align-items:flex-end;height:100rpx}.tab-dock__item.data-v-c3efacf5{flex:1;height:100rpx;display:flex;flex-direction:column;align-items:center;justify-content:center}.tab-dock__item--center.data-v-c3efacf5{justify-content:flex-end;padding-bottom:6rpx}.tab-dock__icon.data-v-c3efacf5{width:46rpx;height:46rpx}.tab-dock__label.data-v-c3efacf5{margin-top:6rpx;font-size:22rpx;line-height:1.2}.tab-dock__label--center.data-v-c3efacf5{margin-top:8rpx}.tab-dock__fab.data-v-c3efacf5{width:96rpx;height:96rpx;margin-top:-48rpx;border-radius:50%;background:linear-gradient(180deg,#2d7340,#204e2b);border:6rpx solid #ffffff;box-shadow:0 10rpx 24rpx rgba(32,78,43,.35);display:flex;align-items:center;justify-content:center}.tab-dock__fab--active.data-v-c3efacf5{transform:scale(1.04);box-shadow:0 12rpx 28rpx rgba(32,78,43,.42)}.tab-dock__fab-text.data-v-c3efacf5{color:#fff;font-size:38rpx;font-weight:700;line-height:1}.tab-dock__safe.data-v-c3efacf5{height:env(safe-area-inset-bottom);background:#fff}
|
||||
+1
-88
@@ -1,89 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
|
||||
__name: "index",
|
||||
props: {
|
||||
bottom: { default: 200 },
|
||||
inline: { type: Boolean, default: false },
|
||||
tone: { default: "default" }
|
||||
},
|
||||
setup(__props) {
|
||||
const trainingItems = [
|
||||
{ url: "/training/pages/dumbbell", title: "哑铃", sub: "力量塑形", icon: "dumbbell", iconClass: "menu-icon--dumbbell" },
|
||||
{ url: "/training/pages/foot-pedal", title: "脚蹬器", sub: "下肢有氧", icon: "pedal", iconClass: "menu-icon--pedal" },
|
||||
{ url: "/training/pages/pilates-ring", title: "瑜伽环", sub: "核心塑形", icon: "pilates", iconClass: "menu-icon--pilates" },
|
||||
{ url: "/training/pages/grip-ring", title: "握力环", sub: "握力训练", icon: "grip", iconClass: "menu-icon--grip" },
|
||||
{ url: "/training/pages/metronome", title: "耗糖节拍器", sub: "健走配速", icon: "metro", iconClass: "menu-icon--metro", featured: true }
|
||||
];
|
||||
const props = __props;
|
||||
const inlineItems = common_vendor.computed(() => {
|
||||
if (props.tone !== "weekly")
|
||||
return trainingItems;
|
||||
const metro = trainingItems.find((i) => i.icon === "metro");
|
||||
const rest = trainingItems.filter((i) => i.icon !== "metro");
|
||||
return metro ? [metro, ...rest] : trainingItems;
|
||||
});
|
||||
const visible = common_vendor.ref(true);
|
||||
const expanded = common_vendor.ref(false);
|
||||
const toggle = () => {
|
||||
expanded.value = !expanded.value;
|
||||
};
|
||||
const goto = (url) => {
|
||||
expanded.value = false;
|
||||
common_vendor.index.navigateTo({ url });
|
||||
};
|
||||
return (_ctx, _cache) => {
|
||||
return common_vendor.e({
|
||||
a: visible.value && props.inline
|
||||
}, visible.value && props.inline ? common_vendor.e({
|
||||
b: props.tone === "weekly"
|
||||
}, props.tone === "weekly" ? {} : {}, {
|
||||
c: common_vendor.f(inlineItems.value, (item, k0, i0) => {
|
||||
return common_vendor.e({
|
||||
a: item.featured
|
||||
}, item.featured ? {} : {}, {
|
||||
b: item.icon === "dumbbell"
|
||||
}, item.icon === "dumbbell" ? {} : item.icon === "pedal" ? {} : item.icon === "pilates" ? {} : item.icon === "grip" ? {} : item.icon === "metro" ? {} : {}, {
|
||||
c: item.icon === "pedal",
|
||||
d: item.icon === "pilates",
|
||||
e: item.icon === "grip",
|
||||
f: item.icon === "metro",
|
||||
g: common_vendor.n(item.iconClass),
|
||||
h: common_vendor.t(item.title),
|
||||
i: common_vendor.t(item.sub),
|
||||
j: item.url,
|
||||
k: common_vendor.o(($event) => goto(item.url), item.url)
|
||||
});
|
||||
}),
|
||||
d: props.tone === "weekly"
|
||||
}, props.tone === "weekly" ? {} : {}, {
|
||||
e: props.tone === "weekly" ? 1 : ""
|
||||
}) : visible.value ? common_vendor.e({
|
||||
g: expanded.value
|
||||
}, expanded.value ? {
|
||||
h: common_vendor.o(($event) => goto("/training/pages/dumbbell"), "fd"),
|
||||
i: common_vendor.o(($event) => goto("/training/pages/foot-pedal"), "a5"),
|
||||
j: common_vendor.o(($event) => goto("/training/pages/pilates-ring"), "3f"),
|
||||
k: common_vendor.o(($event) => goto("/training/pages/grip-ring"), "23"),
|
||||
l: common_vendor.o(($event) => goto("/training/pages/metronome"), "ca"),
|
||||
m: common_vendor.o(() => {
|
||||
}, "26")
|
||||
} : {}, {
|
||||
n: !expanded.value
|
||||
}, !expanded.value ? {} : {}, {
|
||||
o: !expanded.value
|
||||
}, !expanded.value ? {} : {}, {
|
||||
p: expanded.value
|
||||
}, expanded.value ? {} : {}, {
|
||||
q: expanded.value ? 1 : "",
|
||||
r: common_vendor.o(toggle, "98"),
|
||||
s: props.bottom + "rpx"
|
||||
}) : {}, {
|
||||
f: visible.value
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-17534d15"]]);
|
||||
wx.createComponent(Component);
|
||||
"use strict";const n=require("../../common/vendor.js"),g=n.defineComponent({__name:"index",props:{bottom:{default:200},inline:{type:Boolean,default:!1},tone:{default:"default"}},setup(u){const i=[{url:"/training/pages/dumbbell",title:"哑铃",sub:"力量塑形",icon:"dumbbell",iconClass:"menu-icon--dumbbell"},{url:"/training/pages/foot-pedal",title:"脚蹬器",sub:"下肢有氧",icon:"pedal",iconClass:"menu-icon--pedal"},{url:"/training/pages/pilates-ring",title:"瑜伽环",sub:"核心塑形",icon:"pilates",iconClass:"menu-icon--pilates"},{url:"/training/pages/grip-ring",title:"握力环",sub:"握力训练",icon:"grip",iconClass:"menu-icon--grip"},{url:"/training/pages/metronome",title:"耗糖节拍器",sub:"健走配速",icon:"metro",iconClass:"menu-icon--metro",featured:!0}],t=u,c=n.computed(()=>{if(t.tone!=="weekly")return i;const a=i.find(e=>e.icon==="metro"),s=i.filter(e=>e.icon!=="metro");return a?[a,...s]:i}),r=n.ref(!0),o=n.ref(!1),p=()=>{o.value=!o.value},l=a=>{o.value=!1,n.index.navigateTo({url:a})};return(a,s)=>n.e({a:r.value&&t.inline},r.value&&t.inline?n.e({b:t.tone==="weekly"},t.tone==="weekly"?{}:{},{c:n.f(c.value,(e,v,f)=>n.e({a:e.featured},e.featured?{}:{},{b:e.icon==="dumbbell"},e.icon==="dumbbell"?{}:e.icon==="pedal"?{}:e.icon==="pilates"?{}:e.icon==="grip"?{}:e.icon==="metro"?{}:{},{c:e.icon==="pedal",d:e.icon==="pilates",e:e.icon==="grip",f:e.icon==="metro",g:n.n(e.iconClass),h:n.t(e.title),i:n.t(e.sub),j:e.url,k:n.o(b=>l(e.url),e.url)})),d:t.tone==="weekly"},t.tone==="weekly"?{}:{},{e:t.tone==="weekly"?1:""}):r.value?n.e({g:o.value},o.value?{h:n.o(e=>l("/training/pages/dumbbell"),"fd"),i:n.o(e=>l("/training/pages/foot-pedal"),"a5"),j:n.o(e=>l("/training/pages/pilates-ring"),"3f"),k:n.o(e=>l("/training/pages/grip-ring"),"23"),l:n.o(e=>l("/training/pages/metronome"),"ca"),m:n.o(()=>{},"26")}:{},{n:!o.value},o.value?{}:{},{o:!o.value},o.value?{}:{},{p:o.value},o.value?{}:{},{q:o.value?1:"",r:n.o(p,"98"),s:t.bottom+"rpx"}):{},{f:r.value})}}),d=n._export_sfc(g,[["__scopeId","data-v-17534d15"]]);wx.createComponent(d);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/components/dev-training-entry/index.js.map
|
||||
|
||||
+1
-489
File diff suppressed because one or more lines are too long
+1
-149
@@ -1,150 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
if (!Array) {
|
||||
const _easycom_uni_icons2 = common_vendor.resolveComponent("uni-icons");
|
||||
_easycom_uni_icons2();
|
||||
}
|
||||
const _easycom_uni_icons = () => "../../uni_modules/uni-icons/components/uni-icons/uni-icons.js";
|
||||
if (!Math) {
|
||||
_easycom_uni_icons();
|
||||
}
|
||||
const _sfc_main = {
|
||||
__name: "Card",
|
||||
setup(__props) {
|
||||
const { proxy } = common_vendor.getCurrentInstance();
|
||||
const cardList = common_vendor.ref([]);
|
||||
const loading = common_vendor.ref(false);
|
||||
common_vendor.onMounted(() => {
|
||||
loadCardList();
|
||||
});
|
||||
common_vendor.onShow(() => {
|
||||
loadCardList();
|
||||
});
|
||||
const loadCardList = async () => {
|
||||
var _a;
|
||||
loading.value = true;
|
||||
try {
|
||||
const token = common_vendor.index.getStorageSync("token");
|
||||
if (!token) {
|
||||
common_vendor.index.showToast({ title: "请先登录", icon: "none" });
|
||||
return;
|
||||
}
|
||||
const userData = common_vendor.index.getStorageSync("userData");
|
||||
const patientId = (_a = userData == null ? void 0 : userData.diagnosis) == null ? void 0 : _a.patient_id;
|
||||
if (!patientId) {
|
||||
return;
|
||||
}
|
||||
const res = await proxy.apiUrl({
|
||||
url: "/api/tcm/getCardList",
|
||||
method: "GET",
|
||||
data: {
|
||||
patient_id: patientId
|
||||
}
|
||||
});
|
||||
if (res.code === 1) {
|
||||
cardList.value = res.data || [];
|
||||
} else {
|
||||
common_vendor.index.showToast({ title: res.msg || "获取失败", icon: "none" });
|
||||
}
|
||||
} catch (err) {
|
||||
common_vendor.index.__f__("error", "at pages/Card/Card.vue:139", "加载就诊卡列表失败:", err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
const viewCardDetail = (card) => {
|
||||
common_vendor.index.navigateTo({
|
||||
url: `/pages/Card/edit_card?id=${card.id}`
|
||||
});
|
||||
};
|
||||
const viewDailyRecord = (card) => {
|
||||
const url = `/tongji/pages/index?diagnosis_id=${card.id}&patient_id=${card.patient_id || ""}&patient_name=${encodeURIComponent(card.patient_name || "")}&age=${card.age || ""}&gender=${card.gender || ""}`;
|
||||
common_vendor.index.navigateTo({ url });
|
||||
};
|
||||
const createCard = () => {
|
||||
const token = common_vendor.index.getStorageSync("token");
|
||||
if (!token) {
|
||||
common_vendor.index.showToast({ title: "请先登录", icon: "none" });
|
||||
return;
|
||||
}
|
||||
common_vendor.index.navigateTo({
|
||||
url: "/pages/Card/edit_card?add=1"
|
||||
});
|
||||
};
|
||||
const getStatusText = (status) => {
|
||||
return status === 1 ? "启用" : "禁用";
|
||||
};
|
||||
const getStatusClass = (status) => {
|
||||
return status === 1 ? "status-confirmed" : "status-pending";
|
||||
};
|
||||
const diagnosisTypeMap = {
|
||||
"first_visit": "初诊",
|
||||
"follow_up": "复诊",
|
||||
"consultation": "会诊"
|
||||
};
|
||||
const syndromeTypeMap = {
|
||||
"qi_deficiency": "气虚",
|
||||
"blood_deficiency": "血虚",
|
||||
"yin_deficiency": "阴虚",
|
||||
"yang_deficiency": "阳虚",
|
||||
"qi_stagnation": "气滞",
|
||||
"blood_stasis": "血瘀",
|
||||
"phlegm_dampness": "痰湿",
|
||||
"damp_heat": "湿热",
|
||||
"cold_dampness": "寒湿",
|
||||
"wind_cold": "风寒",
|
||||
"wind_heat": "风热"
|
||||
};
|
||||
const getDiagnosisTypeName = (type) => {
|
||||
return diagnosisTypeMap[type] || type || "-";
|
||||
};
|
||||
const getSyndromeTypeName = (type) => {
|
||||
return syndromeTypeMap[type] || type || "-";
|
||||
};
|
||||
const formatDate = (timestamp) => {
|
||||
if (!timestamp)
|
||||
return "-";
|
||||
const date = new Date(timestamp * 1e3);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
return `${year}-${month}-${day}`;
|
||||
};
|
||||
return (_ctx, _cache) => {
|
||||
return common_vendor.e({
|
||||
a: common_vendor.f(cardList.value, (card, k0, i0) => {
|
||||
return {
|
||||
a: common_vendor.t(card.id),
|
||||
b: common_vendor.t(card.status_desc || getStatusText(card.status)),
|
||||
c: common_vendor.n(getStatusClass(card.status)),
|
||||
d: common_vendor.t(card.patient_name || "-"),
|
||||
e: common_vendor.t(card.gender_desc || "-"),
|
||||
f: common_vendor.t(card.age),
|
||||
g: common_vendor.t(getDiagnosisTypeName(card.diagnosis_type)),
|
||||
h: common_vendor.t(getSyndromeTypeName(card.syndrome_type)),
|
||||
i: common_vendor.t(card.diagnosis_date_text || formatDate(card.diagnosis_date)),
|
||||
j: common_vendor.t(card.create_time || "-"),
|
||||
k: common_vendor.o(($event) => viewDailyRecord(card), card.id),
|
||||
l: common_vendor.o(($event) => viewCardDetail(card), card.id),
|
||||
m: card.id,
|
||||
n: common_vendor.o(($event) => viewCardDetail(card), card.id)
|
||||
};
|
||||
}),
|
||||
b: !loading.value && cardList.value.length === 0
|
||||
}, !loading.value && cardList.value.length === 0 ? {
|
||||
c: common_vendor.p({
|
||||
type: "wallet",
|
||||
size: "80",
|
||||
color: "#1890ff"
|
||||
}),
|
||||
d: common_vendor.o(createCard, "df")
|
||||
} : {}, {
|
||||
e: loading.value
|
||||
}, loading.value ? {} : {});
|
||||
};
|
||||
}
|
||||
};
|
||||
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-f80331d8"]]);
|
||||
_sfc_main.__runtimeHooks = 2;
|
||||
wx.createPage(MiniProgramPage);
|
||||
"use strict";const e=require("../../common/vendor.js");Array||e.resolveComponent("uni-icons")();const C=()=>"../../uni_modules/uni-icons/components/uni-icons/uni-icons.js";Math||C();const u={__name:"Card",setup(g){const{proxy:l}=e.getCurrentInstance(),d=e.ref([]),o=e.ref(!1);e.onMounted(()=>{r()}),e.onShow(()=>{r()});const r=async()=>{var t;o.value=!0;try{if(!e.index.getStorageSync("token")){e.index.showToast({title:"请先登录",icon:"none"});return}const n=e.index.getStorageSync("userData"),a=(t=n==null?void 0:n.diagnosis)==null?void 0:t.patient_id;if(!a)return;const s=await l.apiUrl({url:"/api/tcm/getCardList",method:"GET",data:{patient_id:a}});s.code===1?d.value=s.data||[]:e.index.showToast({title:s.msg||"获取失败",icon:"none"})}catch(i){e.index.__f__("error","at pages/Card/Card.vue:139","加载就诊卡列表失败:",i)}finally{o.value=!1}},c=t=>{e.index.navigateTo({url:`/pages/Card/edit_card?id=${t.id}`})},p=t=>{const i=`/tongji/pages/index?diagnosis_id=${t.id}&patient_id=${t.patient_id||""}&patient_name=${encodeURIComponent(t.patient_name||"")}&age=${t.age||""}&gender=${t.gender||""}`;e.index.navigateTo({url:i})},m=()=>{if(!e.index.getStorageSync("token")){e.index.showToast({title:"请先登录",icon:"none"});return}e.index.navigateTo({url:"/pages/Card/edit_card?add=1"})},f=t=>t===1?"启用":"禁用",y=t=>t===1?"status-confirmed":"status-pending",v={first_visit:"初诊",follow_up:"复诊",consultation:"会诊"},x={qi_deficiency:"气虚",blood_deficiency:"血虚",yin_deficiency:"阴虚",yang_deficiency:"阳虚",qi_stagnation:"气滞",blood_stasis:"血瘀",phlegm_dampness:"痰湿",damp_heat:"湿热",cold_dampness:"寒湿",wind_cold:"风寒",wind_heat:"风热"},h=t=>v[t]||t||"-",S=t=>x[t]||t||"-",w=t=>{if(!t)return"-";const i=new Date(t*1e3),n=i.getFullYear(),a=String(i.getMonth()+1).padStart(2,"0"),s=String(i.getDate()).padStart(2,"0");return`${n}-${a}-${s}`};return(t,i)=>e.e({a:e.f(d.value,(n,a,s)=>({a:e.t(n.id),b:e.t(n.status_desc||f(n.status)),c:e.n(y(n.status)),d:e.t(n.patient_name||"-"),e:e.t(n.gender_desc||"-"),f:e.t(n.age),g:e.t(h(n.diagnosis_type)),h:e.t(S(n.syndrome_type)),i:e.t(n.diagnosis_date_text||w(n.diagnosis_date)),j:e.t(n.create_time||"-"),k:e.o(_=>p(n),n.id),l:e.o(_=>c(n),n.id),m:n.id,n:e.o(_=>c(n),n.id)})),b:!o.value&&d.value.length===0},!o.value&&d.value.length===0?{c:e.p({type:"wallet",size:"80",color:"#1890ff"}),d:e.o(m,"df")}:{},{e:o.value},o.value?{}:{})}},T=e._export_sfc(u,[["__scopeId","data-v-f80331d8"]]);u.__runtimeHooks=2;wx.createPage(T);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/Card/Card.js.map
|
||||
|
||||
+1
-189
@@ -1,189 +1 @@
|
||||
/* 适老化设计:50-80岁 - 大字号、高对比、大触控区 */
|
||||
.card-container.data-v-f80331d8 {
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(180deg, #e8f0fa 0%, #ffffff 100%);
|
||||
padding-bottom: 56rpx;
|
||||
}
|
||||
.header.data-v-f80331d8 {
|
||||
background: #ffffff;
|
||||
padding: 48rpx 40rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.header .header-title.data-v-f80331d8 {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #1890ff;
|
||||
}
|
||||
.card-list.data-v-f80331d8 {
|
||||
padding: 40rpx;
|
||||
}
|
||||
.card-item.data-v-f80331d8 {
|
||||
background: #ffffff;
|
||||
border-radius: 28rpx;
|
||||
padding: 44rpx;
|
||||
margin-bottom: 36rpx;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.3s;
|
||||
min-height: 200rpx;
|
||||
}
|
||||
.card-item.data-v-f80331d8:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.card-header.data-v-f80331d8 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 32rpx;
|
||||
padding-bottom: 28rpx;
|
||||
border-bottom: 4rpx solid #e8eaed;
|
||||
}
|
||||
.card-id .label.data-v-f80331d8 {
|
||||
font-size: 34rpx;
|
||||
color: #555;
|
||||
}
|
||||
.card-id .value.data-v-f80331d8 {
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
.status-badge.data-v-f80331d8 {
|
||||
padding: 12rpx 28rpx;
|
||||
border-radius: 28rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
.status-badge.status-confirmed.data-v-f80331d8 {
|
||||
background: #f6ffed;
|
||||
color: #204e2b;
|
||||
border: 4rpx solid #204e2b;
|
||||
}
|
||||
.status-badge.status-pending.data-v-f80331d8 {
|
||||
background: #fff7e6;
|
||||
color: #fa8c16;
|
||||
border: 4rpx solid #ffd591;
|
||||
}
|
||||
.card-info.data-v-f80331d8 {
|
||||
margin-bottom: 28rpx;
|
||||
}
|
||||
.info-row.data-v-f80331d8 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
.info-row .info-label.data-v-f80331d8 {
|
||||
font-size: 34rpx;
|
||||
color: #555;
|
||||
min-width: 200rpx;
|
||||
}
|
||||
.info-row .info-value.data-v-f80331d8 {
|
||||
font-size: 36rpx;
|
||||
color: #1a1a1a;
|
||||
font-weight: 500;
|
||||
}
|
||||
.card-footer.data-v-f80331d8 {
|
||||
padding-top: 28rpx;
|
||||
border-top: 4rpx solid #e8eaed;
|
||||
}
|
||||
.card-actions.data-v-f80331d8 {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
margin-top: 28rpx;
|
||||
padding-top: 28rpx;
|
||||
border-top: 4rpx solid #e8eaed;
|
||||
}
|
||||
.card-action-btn.data-v-f80331d8 {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12rpx;
|
||||
padding: 24rpx 12rpx;
|
||||
background: #f6faff;
|
||||
border-radius: 20rpx;
|
||||
border: 2rpx solid #d6e6fb;
|
||||
min-height: 80rpx;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.card-action-btn.data-v-f80331d8:active {
|
||||
transform: scale(0.98);
|
||||
opacity: 0.85;
|
||||
}
|
||||
.card-action-btn.primary.data-v-f80331d8 {
|
||||
background: linear-gradient(135deg, #1890ff, #0ea5a4);
|
||||
border-color: transparent;
|
||||
}
|
||||
.card-action-btn.primary .card-action-icon.data-v-f80331d8,
|
||||
.card-action-btn.primary .card-action-text.data-v-f80331d8 {
|
||||
color: #ffffff;
|
||||
}
|
||||
.card-action-icon.data-v-f80331d8 {
|
||||
font-size: 36rpx;
|
||||
color: #1890ff;
|
||||
}
|
||||
.card-action-text.data-v-f80331d8 {
|
||||
font-size: 30rpx;
|
||||
color: #1890ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
.time-info.data-v-f80331d8 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.time-info .time-label.data-v-f80331d8 {
|
||||
font-size: 30rpx;
|
||||
color: #555;
|
||||
min-width: 180rpx;
|
||||
}
|
||||
.time-info .time-value.data-v-f80331d8 {
|
||||
font-size: 32rpx;
|
||||
color: #555;
|
||||
}
|
||||
.view-count.data-v-f80331d8 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
.view-count .count-icon.data-v-f80331d8 {
|
||||
font-size: 34rpx;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
.view-count .count-text.data-v-f80331d8 {
|
||||
font-size: 30rpx;
|
||||
color: #555;
|
||||
}
|
||||
.empty-state.data-v-f80331d8 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 160rpx 0;
|
||||
}
|
||||
.empty-state .empty-icon.data-v-f80331d8 {
|
||||
font-size: 140rpx;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
.empty-state .empty-text.data-v-f80331d8 {
|
||||
font-size: 40rpx;
|
||||
color: #555;
|
||||
margin-bottom: 56rpx;
|
||||
}
|
||||
.add-card-btn.data-v-f80331d8 {
|
||||
padding: 36rpx 88rpx;
|
||||
background: #1890ff;
|
||||
color: #ffffff;
|
||||
font-size: 40rpx;
|
||||
font-weight: 500;
|
||||
border-radius: 56rpx;
|
||||
min-height: 100rpx;
|
||||
}
|
||||
.loading-state.data-v-f80331d8 {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 120rpx 0;
|
||||
}
|
||||
.loading-state .loading-text.data-v-f80331d8 {
|
||||
font-size: 36rpx;
|
||||
color: #555;
|
||||
}
|
||||
.card-container.data-v-f80331d8{min-height:100vh;background:linear-gradient(180deg,#e8f0fa,#fff);padding-bottom:56rpx}.header.data-v-f80331d8{background:#fff;padding:48rpx 40rpx;box-shadow:0 2rpx 12rpx rgba(0,0,0,.06)}.header .header-title.data-v-f80331d8{font-size:48rpx;font-weight:700;color:#1890ff}.card-list.data-v-f80331d8{padding:40rpx}.card-item.data-v-f80331d8{background:#fff;border-radius:28rpx;padding:44rpx;margin-bottom:36rpx;box-shadow:0 4rpx 20rpx rgba(0,0,0,.08);transition:all .3s;min-height:200rpx}.card-item.data-v-f80331d8:active{transform:scale(.98);box-shadow:0 2rpx 12rpx rgba(0,0,0,.1)}.card-header.data-v-f80331d8{display:flex;justify-content:space-between;align-items:center;margin-bottom:32rpx;padding-bottom:28rpx;border-bottom:4rpx solid #e8eaed}.card-id .label.data-v-f80331d8{font-size:34rpx;color:#555}.card-id .value.data-v-f80331d8{font-size:40rpx;font-weight:700;color:#1a1a1a}.status-badge.data-v-f80331d8{padding:12rpx 28rpx;border-radius:28rpx;font-size:32rpx;font-weight:500}.status-badge.status-confirmed.data-v-f80331d8{background:#f6ffed;color:#204e2b;border:4rpx solid #204e2b}.status-badge.status-pending.data-v-f80331d8{background:#fff7e6;color:#fa8c16;border:4rpx solid #ffd591}.card-info.data-v-f80331d8{margin-bottom:28rpx}.info-row.data-v-f80331d8{display:flex;align-items:center;margin-bottom:24rpx}.info-row .info-label.data-v-f80331d8{font-size:34rpx;color:#555;min-width:200rpx}.info-row .info-value.data-v-f80331d8{font-size:36rpx;color:#1a1a1a;font-weight:500}.card-footer.data-v-f80331d8{padding-top:28rpx;border-top:4rpx solid #e8eaed}.card-actions.data-v-f80331d8{display:flex;gap:20rpx;margin-top:28rpx;padding-top:28rpx;border-top:4rpx solid #e8eaed}.card-action-btn.data-v-f80331d8{flex:1;display:flex;align-items:center;justify-content:center;gap:12rpx;padding:24rpx 12rpx;background:#f6faff;border-radius:20rpx;border:2rpx solid #d6e6fb;min-height:80rpx;transition:all .2s}.card-action-btn.data-v-f80331d8:active{transform:scale(.98);opacity:.85}.card-action-btn.primary.data-v-f80331d8{background:linear-gradient(135deg,#1890ff,#0ea5a4);border-color:transparent}.card-action-btn.primary .card-action-icon.data-v-f80331d8,.card-action-btn.primary .card-action-text.data-v-f80331d8{color:#fff}.card-action-icon.data-v-f80331d8{font-size:36rpx;color:#1890ff}.card-action-text.data-v-f80331d8{font-size:30rpx;color:#1890ff;font-weight:500}.time-info.data-v-f80331d8{display:flex;align-items:center;margin-bottom:20rpx}.time-info .time-label.data-v-f80331d8{font-size:30rpx;color:#555;min-width:180rpx}.time-info .time-value.data-v-f80331d8{font-size:32rpx;color:#555}.view-count.data-v-f80331d8{display:flex;align-items:center;margin-top:12rpx}.view-count .count-icon.data-v-f80331d8{font-size:34rpx;margin-right:12rpx}.view-count .count-text.data-v-f80331d8{font-size:30rpx;color:#555}.empty-state.data-v-f80331d8{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:160rpx 0}.empty-state .empty-icon.data-v-f80331d8{font-size:140rpx;margin-bottom:40rpx}.empty-state .empty-text.data-v-f80331d8{font-size:40rpx;color:#555;margin-bottom:56rpx}.add-card-btn.data-v-f80331d8{padding:36rpx 88rpx;background:#1890ff;color:#fff;font-size:40rpx;font-weight:500;border-radius:56rpx;min-height:100rpx}.loading-state.data-v-f80331d8{display:flex;justify-content:center;padding:120rpx 0}.loading-state .loading-text.data-v-f80331d8{font-size:36rpx;color:#555}
|
||||
@@ -1,46 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const _sfc_main = {
|
||||
__name: "contact",
|
||||
setup(__props) {
|
||||
const { proxy } = common_vendor.getCurrentInstance();
|
||||
const data = common_vendor.ref({});
|
||||
const loading = common_vendor.ref(false);
|
||||
const type = common_vendor.ref("");
|
||||
common_vendor.onMounted(() => {
|
||||
loadCardList();
|
||||
});
|
||||
const loadCardList = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1];
|
||||
type.value = currentPage.options.type;
|
||||
const res = await proxy.apiUrl({
|
||||
url: "/api/index/policy",
|
||||
method: "GET",
|
||||
data: {
|
||||
type: type.value
|
||||
}
|
||||
});
|
||||
data.value = res.data;
|
||||
common_vendor.index.setNavigationBarTitle({
|
||||
title: res.data.title
|
||||
});
|
||||
} catch (err) {
|
||||
common_vendor.index.__f__("error", "at pages/Card/contact.vue:54", "加载就诊卡列表失败:", err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
return (_ctx, _cache) => {
|
||||
return {
|
||||
a: common_vendor.t(data.value.title),
|
||||
b: data.value.content
|
||||
};
|
||||
};
|
||||
}
|
||||
};
|
||||
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-9c9e5aa4"]]);
|
||||
wx.createPage(MiniProgramPage);
|
||||
"use strict";const t=require("../../common/vendor.js"),l={__name:"contact",setup(_){const{proxy:s}=t.getCurrentInstance(),a=t.ref({}),n=t.ref(!1),r=t.ref("");t.onMounted(()=>{i()});const i=async()=>{n.value=!0;try{const e=getCurrentPages(),c=e[e.length-1];r.value=c.options.type;const o=await s.apiUrl({url:"/api/index/policy",method:"GET",data:{type:r.value}});a.value=o.data,t.index.setNavigationBarTitle({title:o.data.title})}catch(e){t.index.__f__("error","at pages/Card/contact.vue:54","加载就诊卡列表失败:",e)}finally{n.value=!1}};return(e,c)=>({a:t.t(a.value.title),b:a.value.content})}},u=t._export_sfc(l,[["__scopeId","data-v-9c9e5aa4"]]);wx.createPage(u);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/Card/contact.js.map
|
||||
|
||||
@@ -1,136 +1 @@
|
||||
.card-container.data-v-9c9e5aa4 {
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(180deg, #f0f7ff 0%, #ffffff 100%);
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
.header.data-v-9c9e5aa4 {
|
||||
background: #ffffff;
|
||||
padding: 40rpx 30rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.header .header-title.data-v-9c9e5aa4 {
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
color: #1890ff;
|
||||
}
|
||||
.card-list.data-v-9c9e5aa4 {
|
||||
padding: 30rpx;
|
||||
}
|
||||
.card-item.data-v-9c9e5aa4 {
|
||||
background: #ffffff;
|
||||
border-radius: 20rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 24rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.card-item.data-v-9c9e5aa4:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.card-header.data-v-9c9e5aa4 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
padding-bottom: 20rpx;
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
}
|
||||
.card-id .label.data-v-9c9e5aa4 {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
.card-id .value.data-v-9c9e5aa4 {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
.status-badge.data-v-9c9e5aa4 {
|
||||
padding: 8rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
.status-badge.status-confirmed.data-v-9c9e5aa4 {
|
||||
background: #f6ffed;
|
||||
color: #52c41a;
|
||||
border: 2rpx solid #b7eb8f;
|
||||
}
|
||||
.status-badge.status-pending.data-v-9c9e5aa4 {
|
||||
background: #fff7e6;
|
||||
color: #fa8c16;
|
||||
border: 2rpx solid #ffd591;
|
||||
}
|
||||
.card-info.data-v-9c9e5aa4 {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.info-row.data-v-9c9e5aa4 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.info-row .info-label.data-v-9c9e5aa4 {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
min-width: 160rpx;
|
||||
}
|
||||
.info-row .info-value.data-v-9c9e5aa4 {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
.card-footer.data-v-9c9e5aa4 {
|
||||
padding-top: 20rpx;
|
||||
border-top: 2rpx solid #f0f0f0;
|
||||
}
|
||||
.time-info.data-v-9c9e5aa4 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
.time-info .time-label.data-v-9c9e5aa4 {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
min-width: 140rpx;
|
||||
}
|
||||
.time-info .time-value.data-v-9c9e5aa4 {
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
}
|
||||
.view-count.data-v-9c9e5aa4 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
.view-count .count-icon.data-v-9c9e5aa4 {
|
||||
font-size: 28rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
.view-count .count-text.data-v-9c9e5aa4 {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
}
|
||||
.empty-state.data-v-9c9e5aa4 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 120rpx 0;
|
||||
}
|
||||
.empty-state .empty-icon.data-v-9c9e5aa4 {
|
||||
font-size: 120rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
.empty-state .empty-text.data-v-9c9e5aa4 {
|
||||
font-size: 32rpx;
|
||||
color: #999999;
|
||||
}
|
||||
.loading-state.data-v-9c9e5aa4 {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 80rpx 0;
|
||||
}
|
||||
.loading-state .loading-text.data-v-9c9e5aa4 {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
.card-container.data-v-9c9e5aa4{min-height:100vh;background:linear-gradient(180deg,#f0f7ff,#fff);padding-bottom:40rpx}.header.data-v-9c9e5aa4{background:#fff;padding:40rpx 30rpx;box-shadow:0 2rpx 8rpx rgba(0,0,0,.05)}.header .header-title.data-v-9c9e5aa4{font-size:40rpx;font-weight:700;color:#1890ff}.card-list.data-v-9c9e5aa4{padding:30rpx}.card-item.data-v-9c9e5aa4{background:#fff;border-radius:20rpx;padding:30rpx;margin-bottom:24rpx;box-shadow:0 4rpx 12rpx rgba(0,0,0,.08);transition:all .3s}.card-item.data-v-9c9e5aa4:active{transform:scale(.98);box-shadow:0 2rpx 8rpx rgba(0,0,0,.1)}.card-header.data-v-9c9e5aa4{display:flex;justify-content:space-between;align-items:center;margin-bottom:24rpx;padding-bottom:20rpx;border-bottom:2rpx solid #f0f0f0}.card-id .label.data-v-9c9e5aa4{font-size:28rpx;color:#666}.card-id .value.data-v-9c9e5aa4{font-size:32rpx;font-weight:700;color:#333}.status-badge.data-v-9c9e5aa4{padding:8rpx 20rpx;border-radius:20rpx;font-size:24rpx;font-weight:500}.status-badge.status-confirmed.data-v-9c9e5aa4{background:#f6ffed;color:#52c41a;border:2rpx solid #b7eb8f}.status-badge.status-pending.data-v-9c9e5aa4{background:#fff7e6;color:#fa8c16;border:2rpx solid #ffd591}.card-info.data-v-9c9e5aa4{margin-bottom:20rpx}.info-row.data-v-9c9e5aa4{display:flex;align-items:center;margin-bottom:16rpx}.info-row .info-label.data-v-9c9e5aa4{font-size:28rpx;color:#666;min-width:160rpx}.info-row .info-value.data-v-9c9e5aa4{font-size:30rpx;color:#333;font-weight:500}.card-footer.data-v-9c9e5aa4{padding-top:20rpx;border-top:2rpx solid #f0f0f0}.time-info.data-v-9c9e5aa4{display:flex;align-items:center;margin-bottom:12rpx}.time-info .time-label.data-v-9c9e5aa4{font-size:24rpx;color:#999;min-width:140rpx}.time-info .time-value.data-v-9c9e5aa4{font-size:26rpx;color:#666}.view-count.data-v-9c9e5aa4{display:flex;align-items:center;margin-top:8rpx}.view-count .count-icon.data-v-9c9e5aa4{font-size:28rpx;margin-right:8rpx}.view-count .count-text.data-v-9c9e5aa4{font-size:24rpx;color:#999}.empty-state.data-v-9c9e5aa4{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:120rpx 0}.empty-state .empty-icon.data-v-9c9e5aa4{font-size:120rpx;margin-bottom:30rpx}.empty-state .empty-text.data-v-9c9e5aa4{font-size:32rpx;color:#999}.loading-state.data-v-9c9e5aa4{display:flex;justify-content:center;padding:80rpx 0}.loading-state .loading-text.data-v-9c9e5aa4{font-size:28rpx;color:#999}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-121
@@ -1,122 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const DevTrainingEntry = () => "../../components/dev-training-entry/index.js";
|
||||
const TabBarDock = () => "../../components/app-tab-bar/tab-bar-dock.js";
|
||||
const _sfc_main = {
|
||||
name: "profileB",
|
||||
components: { DevTrainingEntry, TabBarDock },
|
||||
data() {
|
||||
return {
|
||||
userInfo: {
|
||||
avatar: "",
|
||||
nickname: "",
|
||||
userId: "",
|
||||
balance: "0",
|
||||
points: "0",
|
||||
coupons: "5"
|
||||
},
|
||||
orderTypes: [
|
||||
{
|
||||
name: "待付款",
|
||||
image: "/static/images/my/payment.png",
|
||||
path: "/pages/order/list?type=1",
|
||||
count: 2
|
||||
},
|
||||
{
|
||||
name: "待发货",
|
||||
image: "/static/images/my/delivery.png",
|
||||
path: "/pages/order/list?type=2",
|
||||
count: 1
|
||||
},
|
||||
{
|
||||
name: "待收货",
|
||||
image: "/static/images/my/shipping.png",
|
||||
path: "/pages/order/list?type=3",
|
||||
count: 0
|
||||
},
|
||||
{
|
||||
name: "待评价",
|
||||
image: "/static/images/my/review.png",
|
||||
path: "/pages/order/list?type=4",
|
||||
count: 3
|
||||
},
|
||||
{
|
||||
name: "退换/售后",
|
||||
image: "/static/images/my/after-sale.png",
|
||||
path: "/pages/order/list?type=5",
|
||||
count: 0
|
||||
}
|
||||
],
|
||||
allServices: [
|
||||
{ name: "就诊卡", icon: "folder-add", path: "/pages/Card/Card", class: "bg-cyan" },
|
||||
{ name: "设置", icon: "gear", path: "/pages/user/userinfo", class: "bg-gray" }
|
||||
// ,
|
||||
// { name: '客服中心', icon: 'headphones', path: '/pages/service/index', class: 'bg-orange', desc: '在线客服' }
|
||||
]
|
||||
};
|
||||
},
|
||||
onShow() {
|
||||
this.userInfo = common_vendor.index.getStorageSync("userData");
|
||||
},
|
||||
methods: {
|
||||
navigateTo(path) {
|
||||
common_vendor.index.navigateTo({ url: path });
|
||||
},
|
||||
showQRCode() {
|
||||
}
|
||||
}
|
||||
};
|
||||
if (!Array) {
|
||||
const _easycom_uni_icons2 = common_vendor.resolveComponent("uni-icons");
|
||||
const _component_dev_training_entry = common_vendor.resolveComponent("dev-training-entry");
|
||||
const _component_TabBarDock = common_vendor.resolveComponent("TabBarDock");
|
||||
(_easycom_uni_icons2 + _component_dev_training_entry + _component_TabBarDock)();
|
||||
}
|
||||
const _easycom_uni_icons = () => "../../uni_modules/uni-icons/components/uni-icons/uni-icons.js";
|
||||
if (!Math) {
|
||||
_easycom_uni_icons();
|
||||
}
|
||||
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
return {
|
||||
a: $data.userInfo.avatar,
|
||||
b: common_vendor.t($data.userInfo.nickname || "未登录"),
|
||||
c: common_vendor.t($data.userInfo.balance || 0),
|
||||
d: common_vendor.t($data.userInfo.points || 0),
|
||||
e: common_vendor.t($data.userInfo.coupons || 0),
|
||||
f: common_vendor.o(($event) => $options.navigateTo("/pages/user/userinfo"), "39"),
|
||||
g: common_vendor.f($data.allServices, (item, index, i0) => {
|
||||
return common_vendor.e({
|
||||
a: "0f7520f0-0-" + i0,
|
||||
b: common_vendor.p({
|
||||
type: item.icon,
|
||||
size: "28",
|
||||
color: "#fff"
|
||||
}),
|
||||
c: common_vendor.n(item.class),
|
||||
d: common_vendor.t(item.name),
|
||||
e: item.desc
|
||||
}, item.desc ? {
|
||||
f: common_vendor.t(item.desc)
|
||||
} : {}, {
|
||||
g: "0f7520f0-1-" + i0,
|
||||
h: index,
|
||||
i: common_vendor.o(($event) => $options.navigateTo(item.path), index)
|
||||
});
|
||||
}),
|
||||
h: common_vendor.p({
|
||||
type: "right",
|
||||
size: "20",
|
||||
color: "#666"
|
||||
}),
|
||||
i: common_vendor.p({
|
||||
bottom: 360
|
||||
}),
|
||||
j: common_vendor.p({
|
||||
active: 1
|
||||
})
|
||||
};
|
||||
}
|
||||
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-0f7520f0"]]);
|
||||
_sfc_main.__runtimeHooks = 2;
|
||||
wx.createPage(MiniProgramPage);
|
||||
"use strict";const e=require("../../common/vendor.js"),g=()=>"../../components/dev-training-entry/index.js",m=()=>"../../components/app-tab-bar/tab-bar-dock.js",p={name:"profileB",components:{DevTrainingEntry:g,TabBarDock:m},data(){return{userInfo:{avatar:"",nickname:"",userId:"",balance:"0",points:"0",coupons:"5"},orderTypes:[{name:"待付款",image:"/static/images/my/payment.png",path:"/pages/order/list?type=1",count:2},{name:"待发货",image:"/static/images/my/delivery.png",path:"/pages/order/list?type=2",count:1},{name:"待收货",image:"/static/images/my/shipping.png",path:"/pages/order/list?type=3",count:0},{name:"待评价",image:"/static/images/my/review.png",path:"/pages/order/list?type=4",count:3},{name:"退换/售后",image:"/static/images/my/after-sale.png",path:"/pages/order/list?type=5",count:0}],allServices:[{name:"就诊卡",icon:"folder-add",path:"/pages/Card/Card",class:"bg-cyan"},{name:"设置",icon:"gear",path:"/pages/user/userinfo",class:"bg-gray"}]}},onShow(){this.userInfo=e.index.getStorageSync("userData")},methods:{navigateTo(a){e.index.navigateTo({url:a})},showQRCode(){}}};if(!Array){const a=e.resolveComponent("uni-icons"),s=e.resolveComponent("dev-training-entry"),t=e.resolveComponent("TabBarDock");(a+s+t)()}const u=()=>"../../uni_modules/uni-icons/components/uni-icons/uni-icons.js";Math||u();function f(a,s,t,_,o,r){return{a:o.userInfo.avatar,b:e.t(o.userInfo.nickname||"未登录"),c:e.t(o.userInfo.balance||0),d:e.t(o.userInfo.points||0),e:e.t(o.userInfo.coupons||0),f:e.o(n=>r.navigateTo("/pages/user/userinfo"),"39"),g:e.f(o.allServices,(n,c,i)=>e.e({a:"0f7520f0-0-"+i,b:e.p({type:n.icon,size:"28",color:"#fff"}),c:e.n(n.class),d:e.t(n.name),e:n.desc},n.desc?{f:e.t(n.desc)}:{},{g:"0f7520f0-1-"+i,h:c,i:e.o(l=>r.navigateTo(n.path),c)})),h:e.p({type:"right",size:"20",color:"#666"}),i:e.p({bottom:360}),j:e.p({active:1})}}const d=e._export_sfc(p,[["render",f],["__scopeId","data-v-0f7520f0"]]);p.__runtimeHooks=2;wx.createPage(d);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/user/user.js.map
|
||||
|
||||
+1
-261
@@ -1,261 +1 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
/* 颜色变量 */
|
||||
/* 行为相关颜色 */
|
||||
/* 文字基本颜色 */
|
||||
/* 背景颜色 */
|
||||
/* 边框颜色 */
|
||||
/* 尺寸变量 */
|
||||
/* 文字尺寸 */
|
||||
/* 图片尺寸 */
|
||||
/* Border Radius */
|
||||
/* 水平间距 */
|
||||
/* 垂直间距 */
|
||||
/* 透明度 */
|
||||
/* 文章场景相关 */
|
||||
/* 适老化设计:50-80岁老人 - 大字号、高对比、大触控区 */
|
||||
.mine-page.data-v-0f7520f0 {
|
||||
min-height: 100vh;
|
||||
background: #e8eaed;
|
||||
padding: 40rpx;
|
||||
padding-bottom: calc(240rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
.user-card.data-v-0f7520f0 {
|
||||
background: #fff;
|
||||
border-radius: 28rpx;
|
||||
padding: 48rpx;
|
||||
margin-bottom: 40rpx;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.user-card .user-header.data-v-0f7520f0 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 48rpx;
|
||||
}
|
||||
.user-card .user-header .avatar.data-v-0f7520f0 {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 80rpx;
|
||||
margin-right: 36rpx;
|
||||
border: 4rpx solid #e0e0e0;
|
||||
}
|
||||
.user-card .user-header .user-info.data-v-0f7520f0 {
|
||||
flex: 1;
|
||||
}
|
||||
.user-card .user-header .user-info .nickname.data-v-0f7520f0 {
|
||||
font-size: 48rpx;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 16rpx;
|
||||
display: block;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
.user-card .user-header .user-info .vip-tag.data-v-0f7520f0 {
|
||||
background: linear-gradient(90deg, #FFD700 0%, #FFA500 100%);
|
||||
color: #fff;
|
||||
font-size: 28rpx;
|
||||
padding: 6rpx 20rpx;
|
||||
border-radius: 24rpx;
|
||||
display: inline-block;
|
||||
}
|
||||
.user-card .user-header .qr-code.data-v-0f7520f0 {
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
border-radius: 44rpx;
|
||||
background: #f5f6fa;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.user-card .stat-row.data-v-0f7520f0 {
|
||||
display: flex;
|
||||
padding-top: 40rpx;
|
||||
border-top: 4rpx solid #e8eaed;
|
||||
}
|
||||
.user-card .stat-row .stat-item.data-v-0f7520f0 {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
min-height: 120rpx;
|
||||
}
|
||||
.user-card .stat-row .stat-item .value.data-v-0f7520f0 {
|
||||
font-size: 52rpx;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 12rpx;
|
||||
display: block;
|
||||
}
|
||||
.user-card .stat-row .stat-item .label.data-v-0f7520f0 {
|
||||
font-size: 32rpx;
|
||||
color: #555;
|
||||
font-weight: 500;
|
||||
}
|
||||
.order-card.data-v-0f7520f0 {
|
||||
background: #fff;
|
||||
border-radius: 24rpx;
|
||||
padding: 40rpx;
|
||||
margin-bottom: 30rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.order-card .card-header.data-v-0f7520f0 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
.order-card .card-header .title.data-v-0f7520f0 {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
.order-card .card-header .more.data-v-0f7520f0 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.order-card .card-header .more text.data-v-0f7520f0 {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
.order-card .order-list.data-v-0f7520f0 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.order-card .order-list .order-item.data-v-0f7520f0 {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
.order-card .order-list .order-item .icon-wrapper.data-v-0f7520f0 {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
margin: 0 auto 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.order-card .order-list .order-item .icon-wrapper .count-badge.data-v-0f7520f0 {
|
||||
position: absolute;
|
||||
top: -10rpx;
|
||||
right: -10rpx;
|
||||
background: #ff4d4f;
|
||||
color: #fff;
|
||||
font-size: 20rpx;
|
||||
min-width: 32rpx;
|
||||
height: 32rpx;
|
||||
line-height: 32rpx;
|
||||
text-align: center;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 8rpx;
|
||||
}
|
||||
.order-card .order-list .order-item .icon-wrapper .order-icon.data-v-0f7520f0 {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
}
|
||||
.order-card .order-list .order-item .order-name.data-v-0f7520f0 {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
.quick-actions.data-v-0f7520f0 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
.quick-actions .action-item.data-v-0f7520f0 {
|
||||
background: #fff;
|
||||
border-radius: 24rpx;
|
||||
padding: 30rpx 20rpx;
|
||||
text-align: center;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.quick-actions .action-item .action-icon.data-v-0f7520f0 {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
margin: 0 auto 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.quick-actions .action-item .action-name.data-v-0f7520f0 {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
.service-list.data-v-0f7520f0 {
|
||||
background: #fff;
|
||||
border-radius: 28rpx;
|
||||
padding: 20rpx 40rpx;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.service-list .service-item.data-v-0f7520f0 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 44rpx 0;
|
||||
border-bottom: 4rpx solid #e8eaed;
|
||||
min-height: 120rpx;
|
||||
}
|
||||
.service-list .service-item.data-v-0f7520f0:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.service-list .service-item .left.data-v-0f7520f0 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.service-list .service-item .left .service-icon.data-v-0f7520f0 {
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
border-radius: 44rpx;
|
||||
margin-right: 32rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.service-list .service-item .left .service-name.data-v-0f7520f0 {
|
||||
font-size: 38rpx;
|
||||
color: #1a1a1a;
|
||||
font-weight: 500;
|
||||
}
|
||||
.service-list .service-item .right.data-v-0f7520f0 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.service-list .service-item .right .desc.data-v-0f7520f0 {
|
||||
font-size: 30rpx;
|
||||
color: #555;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
.bg-red.data-v-0f7520f0 {
|
||||
background: #ff4d4f;
|
||||
}
|
||||
.bg-blue.data-v-0f7520f0 {
|
||||
background: #1890ff;
|
||||
}
|
||||
.bg-green.data-v-0f7520f0 {
|
||||
background: #52c41a;
|
||||
}
|
||||
.bg-purple.data-v-0f7520f0 {
|
||||
background: #722ed1;
|
||||
}
|
||||
.bg-orange.data-v-0f7520f0 {
|
||||
background: #fa8c16;
|
||||
}
|
||||
.bg-cyan.data-v-0f7520f0 {
|
||||
background: #13c2c2;
|
||||
}
|
||||
.bg-pink.data-v-0f7520f0 {
|
||||
background: #eb2f96;
|
||||
}
|
||||
.bg-gray.data-v-0f7520f0 {
|
||||
background: #666666;
|
||||
}
|
||||
.mine-page.data-v-0f7520f0{min-height:100vh;background:#e8eaed;padding:40rpx;padding-bottom:calc(240rpx + env(safe-area-inset-bottom))}.user-card.data-v-0f7520f0{background:#fff;border-radius:28rpx;padding:48rpx;margin-bottom:40rpx;box-shadow:0 4rpx 20rpx rgba(0,0,0,.06)}.user-card .user-header.data-v-0f7520f0{display:flex;align-items:center;margin-bottom:48rpx}.user-card .user-header .avatar.data-v-0f7520f0{width:160rpx;height:160rpx;border-radius:80rpx;margin-right:36rpx;border:4rpx solid #e0e0e0}.user-card .user-header .user-info.data-v-0f7520f0{flex:1}.user-card .user-header .user-info .nickname.data-v-0f7520f0{font-size:48rpx;font-weight:600;color:#1a1a1a;margin-bottom:16rpx;display:block;letter-spacing:1rpx}.user-card .user-header .user-info .vip-tag.data-v-0f7520f0{background:linear-gradient(90deg,gold,orange);color:#fff;font-size:28rpx;padding:6rpx 20rpx;border-radius:24rpx;display:inline-block}.user-card .user-header .qr-code.data-v-0f7520f0{width:88rpx;height:88rpx;border-radius:44rpx;background:#f5f6fa;display:flex;align-items:center;justify-content:center}.user-card .stat-row.data-v-0f7520f0{display:flex;padding-top:40rpx;border-top:4rpx solid #e8eaed}.user-card .stat-row .stat-item.data-v-0f7520f0{flex:1;text-align:center;min-height:120rpx}.user-card .stat-row .stat-item .value.data-v-0f7520f0{font-size:52rpx;font-weight:600;color:#1a1a1a;margin-bottom:12rpx;display:block}.user-card .stat-row .stat-item .label.data-v-0f7520f0{font-size:32rpx;color:#555;font-weight:500}.order-card.data-v-0f7520f0{background:#fff;border-radius:24rpx;padding:40rpx;margin-bottom:30rpx;box-shadow:0 4rpx 16rpx rgba(0,0,0,.04)}.order-card .card-header.data-v-0f7520f0{display:flex;justify-content:space-between;align-items:center;margin-bottom:40rpx}.order-card .card-header .title.data-v-0f7520f0{font-size:32rpx;font-weight:600;color:#333}.order-card .card-header .more.data-v-0f7520f0{display:flex;align-items:center}.order-card .card-header .more text.data-v-0f7520f0{font-size:26rpx;color:#999;margin-right:8rpx}.order-card .order-list.data-v-0f7520f0{display:flex;justify-content:space-between}.order-card .order-list .order-item.data-v-0f7520f0{flex:1;text-align:center}.order-card .order-list .order-item .icon-wrapper.data-v-0f7520f0{width:100rpx;height:100rpx;margin:0 auto;position:relative;display:flex;align-items:center;justify-content:center}.order-card .order-list .order-item .icon-wrapper .count-badge.data-v-0f7520f0{position:absolute;top:-10rpx;right:-10rpx;background:#ff4d4f;color:#fff;font-size:20rpx;min-width:32rpx;height:32rpx;line-height:32rpx;text-align:center;border-radius:16rpx;padding:0 8rpx}.order-card .order-list .order-item .icon-wrapper .order-icon.data-v-0f7520f0{width:56rpx;height:56rpx}.order-card .order-list .order-item .order-name.data-v-0f7520f0{font-size:26rpx;color:#666}.quick-actions.data-v-0f7520f0{display:grid;grid-template-columns:repeat(4,1fr);gap:30rpx;margin-bottom:30rpx}.quick-actions .action-item.data-v-0f7520f0{background:#fff;border-radius:24rpx;padding:30rpx 20rpx;text-align:center;box-shadow:0 4rpx 16rpx rgba(0,0,0,.04)}.quick-actions .action-item .action-icon.data-v-0f7520f0{width:80rpx;height:80rpx;border-radius:40rpx;margin:0 auto 16rpx;display:flex;align-items:center;justify-content:center}.quick-actions .action-item .action-name.data-v-0f7520f0{font-size:26rpx;color:#666}.service-list.data-v-0f7520f0{background:#fff;border-radius:28rpx;padding:20rpx 40rpx;box-shadow:0 4rpx 20rpx rgba(0,0,0,.06)}.service-list .service-item.data-v-0f7520f0{display:flex;align-items:center;justify-content:space-between;padding:44rpx 0;border-bottom:4rpx solid #e8eaed;min-height:120rpx}.service-list .service-item.data-v-0f7520f0:last-child{border-bottom:none}.service-list .service-item .left.data-v-0f7520f0{display:flex;align-items:center}.service-list .service-item .left .service-icon.data-v-0f7520f0{width:88rpx;height:88rpx;border-radius:44rpx;margin-right:32rpx;display:flex;align-items:center;justify-content:center}.service-list .service-item .left .service-name.data-v-0f7520f0{font-size:38rpx;color:#1a1a1a;font-weight:500}.service-list .service-item .right.data-v-0f7520f0{display:flex;align-items:center}.service-list .service-item .right .desc.data-v-0f7520f0{font-size:30rpx;color:#555;margin-right:20rpx}.bg-red.data-v-0f7520f0{background:#ff4d4f}.bg-blue.data-v-0f7520f0{background:#1890ff}.bg-green.data-v-0f7520f0{background:#52c41a}.bg-purple.data-v-0f7520f0{background:#722ed1}.bg-orange.data-v-0f7520f0{background:#fa8c16}.bg-cyan.data-v-0f7520f0{background:#13c2c2}.bg-pink.data-v-0f7520f0{background:#eb2f96}.bg-gray.data-v-0f7520f0{background:#666}
|
||||
@@ -1,193 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
if (!Array) {
|
||||
const _easycom_uni_icons2 = common_vendor.resolveComponent("uni-icons");
|
||||
_easycom_uni_icons2();
|
||||
}
|
||||
const _easycom_uni_icons = () => "../../uni_modules/uni-icons/components/uni-icons/uni-icons.js";
|
||||
if (!Math) {
|
||||
_easycom_uni_icons();
|
||||
}
|
||||
const _sfc_main = {
|
||||
__name: "userinfo",
|
||||
setup(__props) {
|
||||
const { proxy } = common_vendor.getCurrentInstance();
|
||||
const instance = common_vendor.getCurrentInstance();
|
||||
const $url = instance.appContext.config.globalProperties.$url;
|
||||
const loading = common_vendor.ref(false);
|
||||
const submitting = common_vendor.ref(false);
|
||||
const formData = common_vendor.ref({
|
||||
avatar: "",
|
||||
patient_name: "",
|
||||
phone: "",
|
||||
nickname: "",
|
||||
sex: 1,
|
||||
age: ""
|
||||
});
|
||||
common_vendor.onMounted(() => {
|
||||
loadUserInfo();
|
||||
});
|
||||
const loadUserInfo = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await proxy.apiUrl({
|
||||
url: "/api/user/info",
|
||||
method: "GET",
|
||||
data: {}
|
||||
});
|
||||
if (res.code === 1) {
|
||||
const userInfo = res.data;
|
||||
formData.value = {
|
||||
avatar: userInfo.avatar || "",
|
||||
patient_name: userInfo.patient_name || userInfo.nickname || "",
|
||||
phone: userInfo.phone || "",
|
||||
nickname: userInfo.nickname || "",
|
||||
sex: userInfo.sex == "男" ? 1 : 2,
|
||||
age: userInfo.age || ""
|
||||
};
|
||||
} else {
|
||||
common_vendor.index.showToast({ title: res.msg || "加载失败", icon: "none" });
|
||||
}
|
||||
} catch (err) {
|
||||
common_vendor.index.__f__("error", "at pages/user/userinfo.vue:142", "加载用户信息失败:", err);
|
||||
common_vendor.index.showToast({ title: "加载失败", icon: "none" });
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
const uploadAvatar = () => {
|
||||
common_vendor.index.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ["compressed"],
|
||||
sourceType: ["album", "camera"],
|
||||
success: async (res) => {
|
||||
const tempFilePath = res.tempFilePaths[0];
|
||||
try {
|
||||
common_vendor.index.showLoading({ title: "上传中..." });
|
||||
const token = common_vendor.index.getStorageSync("token");
|
||||
const uploadRes = await new Promise((resolve, reject) => {
|
||||
common_vendor.index.uploadFile({
|
||||
url: $url + "/api/upload/image",
|
||||
filePath: tempFilePath,
|
||||
name: "file",
|
||||
header: {
|
||||
token,
|
||||
"content-type": "multipart/form-data"
|
||||
},
|
||||
success: (res2) => {
|
||||
const data = JSON.parse(res2.data);
|
||||
resolve(data);
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
common_vendor.index.hideLoading();
|
||||
if (uploadRes.code === 1) {
|
||||
formData.value.avatar = uploadRes.data.uri || uploadRes.data;
|
||||
common_vendor.index.showToast({ title: "头像上传成功", icon: "success" });
|
||||
} else {
|
||||
common_vendor.index.showToast({ title: uploadRes.msg || "上传失败", icon: "none" });
|
||||
}
|
||||
} catch (err) {
|
||||
common_vendor.index.hideLoading();
|
||||
common_vendor.index.__f__("error", "at pages/user/userinfo.vue:195", "上传头像失败:", err);
|
||||
common_vendor.index.showToast({ title: "上传失败", icon: "none" });
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
common_vendor.index.__f__("error", "at pages/user/userinfo.vue:200", "选择图片失败:", err);
|
||||
common_vendor.index.showToast({ title: "选择图片失败", icon: "none" });
|
||||
}
|
||||
});
|
||||
};
|
||||
const validatePhone = (phone) => {
|
||||
if (!phone)
|
||||
return true;
|
||||
return /^1[3-9]\d{9}$/.test(phone);
|
||||
};
|
||||
const submitForm = async () => {
|
||||
if (!formData.value.patient_name) {
|
||||
common_vendor.index.showToast({ title: "姓名不能为空", icon: "none" });
|
||||
return;
|
||||
}
|
||||
if (formData.value.phone && !validatePhone(formData.value.phone)) {
|
||||
common_vendor.index.showToast({ title: "手机号格式不正确", icon: "none" });
|
||||
return;
|
||||
}
|
||||
submitting.value = true;
|
||||
try {
|
||||
const res = await proxy.apiUrl({
|
||||
url: "/api/user/setInfo",
|
||||
method: "POST",
|
||||
data: {
|
||||
avatar: formData.value.avatar,
|
||||
phone: formData.value.phone,
|
||||
nickname: formData.value.nickname,
|
||||
sex: formData.value.sex,
|
||||
age: formData.value.age,
|
||||
patient_name: formData.value.patient_name
|
||||
}
|
||||
});
|
||||
if (res.code === 1) {
|
||||
const userData = common_vendor.index.getStorageSync("userData");
|
||||
const updatedData = {
|
||||
...userData,
|
||||
avatar: formData.value.avatar,
|
||||
phone: formData.value.phone,
|
||||
nickname: formData.value.nickname,
|
||||
sex: formData.value.sex,
|
||||
age: formData.value.age,
|
||||
patient_name: formData.value.patient_name,
|
||||
diagnosis: {
|
||||
...userData.diagnosis,
|
||||
patient_name: formData.value.patient_name
|
||||
}
|
||||
};
|
||||
common_vendor.index.setStorageSync("userData", updatedData);
|
||||
common_vendor.index.showToast({ title: "保存成功", icon: "success" });
|
||||
setTimeout(() => {
|
||||
common_vendor.index.navigateBack();
|
||||
}, 1500);
|
||||
} else {
|
||||
common_vendor.index.showToast({ title: res.msg || "保存失败", icon: "none" });
|
||||
}
|
||||
} catch (err) {
|
||||
common_vendor.index.__f__("error", "at pages/user/userinfo.vue:269", "保存失败:", err);
|
||||
common_vendor.index.showToast({ title: "保存失败", icon: "none" });
|
||||
} finally {
|
||||
submitting.value = false;
|
||||
}
|
||||
};
|
||||
return (_ctx, _cache) => {
|
||||
return common_vendor.e({
|
||||
a: loading.value
|
||||
}, loading.value ? {} : {
|
||||
b: formData.value.avatar,
|
||||
c: common_vendor.p({
|
||||
type: "upload-filled",
|
||||
size: "24",
|
||||
color: "#FFA500"
|
||||
}),
|
||||
d: common_vendor.o(uploadAvatar, "bf"),
|
||||
e: formData.value.nickname,
|
||||
f: common_vendor.o(($event) => formData.value.nickname = $event.detail.value, "6d"),
|
||||
g: formData.value.sex === 1 ? 1 : "",
|
||||
h: common_vendor.o(($event) => formData.value.sex = 1, "e9"),
|
||||
i: formData.value.sex === 2 ? 1 : "",
|
||||
j: common_vendor.o(($event) => formData.value.sex = 2, "53"),
|
||||
k: formData.value.age,
|
||||
l: common_vendor.o(common_vendor.m(($event) => formData.value.age = $event.detail.value, {
|
||||
number: true
|
||||
}), "cf"),
|
||||
m: common_vendor.t(submitting.value ? "保存中..." : "保存修改"),
|
||||
n: common_vendor.o(submitForm, "84"),
|
||||
o: submitting.value
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-103261b1"]]);
|
||||
wx.createPage(MiniProgramPage);
|
||||
"use strict";const e=require("../../common/vendor.js");Array||e.resolveComponent("uni-icons")();const h=()=>"../../uni_modules/uni-icons/components/uni-icons/uni-icons.js";Math||h();const y={__name:"userinfo",setup(l){const{proxy:c}=e.getCurrentInstance(),d=e.getCurrentInstance().appContext.config.globalProperties.$url,s=e.ref(!1),i=e.ref(!1),a=e.ref({avatar:"",patient_name:"",phone:"",nickname:"",sex:1,age:""});e.onMounted(()=>{v()});const v=async()=>{s.value=!0;try{const n=await c.apiUrl({url:"/api/user/info",method:"GET",data:{}});if(n.code===1){const t=n.data;a.value={avatar:t.avatar||"",patient_name:t.patient_name||t.nickname||"",phone:t.phone||"",nickname:t.nickname||"",sex:t.sex=="男"?1:2,age:t.age||""}}else e.index.showToast({title:n.msg||"加载失败",icon:"none"})}catch(n){e.index.__f__("error","at pages/user/userinfo.vue:142","加载用户信息失败:",n),e.index.showToast({title:"加载失败",icon:"none"})}finally{s.value=!1}},m=()=>{e.index.chooseImage({count:1,sizeType:["compressed"],sourceType:["album","camera"],success:async n=>{const t=n.tempFilePaths[0];try{e.index.showLoading({title:"上传中..."});const o=e.index.getStorageSync("token"),r=await new Promise((f,x)=>{e.index.uploadFile({url:d+"/api/upload/image",filePath:t,name:"file",header:{token:o,"content-type":"multipart/form-data"},success:u=>{const g=JSON.parse(u.data);f(g)},fail:u=>{x(u)}})});e.index.hideLoading(),r.code===1?(a.value.avatar=r.data.uri||r.data,e.index.showToast({title:"头像上传成功",icon:"success"})):e.index.showToast({title:r.msg||"上传失败",icon:"none"})}catch(o){e.index.hideLoading(),e.index.__f__("error","at pages/user/userinfo.vue:195","上传头像失败:",o),e.index.showToast({title:"上传失败",icon:"none"})}},fail:n=>{e.index.__f__("error","at pages/user/userinfo.vue:200","选择图片失败:",n),e.index.showToast({title:"选择图片失败",icon:"none"})}})},p=n=>n?/^1[3-9]\d{9}$/.test(n):!0,_=async()=>{if(!a.value.patient_name){e.index.showToast({title:"姓名不能为空",icon:"none"});return}if(a.value.phone&&!p(a.value.phone)){e.index.showToast({title:"手机号格式不正确",icon:"none"});return}i.value=!0;try{const n=await c.apiUrl({url:"/api/user/setInfo",method:"POST",data:{avatar:a.value.avatar,phone:a.value.phone,nickname:a.value.nickname,sex:a.value.sex,age:a.value.age,patient_name:a.value.patient_name}});if(n.code===1){const t=e.index.getStorageSync("userData"),o={...t,avatar:a.value.avatar,phone:a.value.phone,nickname:a.value.nickname,sex:a.value.sex,age:a.value.age,patient_name:a.value.patient_name,diagnosis:{...t.diagnosis,patient_name:a.value.patient_name}};e.index.setStorageSync("userData",o),e.index.showToast({title:"保存成功",icon:"success"}),setTimeout(()=>{e.index.navigateBack()},1500)}else e.index.showToast({title:n.msg||"保存失败",icon:"none"})}catch(n){e.index.__f__("error","at pages/user/userinfo.vue:269","保存失败:",n),e.index.showToast({title:"保存失败",icon:"none"})}finally{i.value=!1}};return(n,t)=>e.e({a:s.value},s.value?{}:{b:a.value.avatar,c:e.p({type:"upload-filled",size:"24",color:"#FFA500"}),d:e.o(m,"bf"),e:a.value.nickname,f:e.o(o=>a.value.nickname=o.detail.value,"6d"),g:a.value.sex===1?1:"",h:e.o(o=>a.value.sex=1,"e9"),i:a.value.sex===2?1:"",j:e.o(o=>a.value.sex=2,"53"),k:a.value.age,l:e.o(e.m(o=>a.value.age=o.detail.value,{number:!0}),"cf"),m:e.t(i.value?"保存中...":"保存修改"),n:e.o(_,"84"),o:i.value})}},w=e._export_sfc(y,[["__scopeId","data-v-103261b1"]]);wx.createPage(w);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/user/userinfo.js.map
|
||||
|
||||
@@ -1,188 +1 @@
|
||||
/* 适老化设计:50-80岁 - 大字号、高对比、大触控区 */
|
||||
.userinfo-container.data-v-103261b1 {
|
||||
min-height: 100vh;
|
||||
background: #e8eaed;
|
||||
}
|
||||
.header.data-v-103261b1 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: #ffffff;
|
||||
padding: 24rpx 40rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.header-back.data-v-103261b1 {
|
||||
font-size: 48rpx;
|
||||
color: #FFA500;
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.header-title.data-v-103261b1 {
|
||||
font-size: 44rpx;
|
||||
font-weight: bold;
|
||||
color: #1a1a1a;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
.header-placeholder.data-v-103261b1 {
|
||||
width: 88rpx;
|
||||
}
|
||||
.loading-state.data-v-103261b1 {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
font-size: 36rpx;
|
||||
color: #555;
|
||||
}
|
||||
.form-wrapper.data-v-103261b1 {
|
||||
padding: 40rpx;
|
||||
}
|
||||
.form-section.data-v-103261b1 {
|
||||
background: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
padding: 40rpx;
|
||||
margin-bottom: 36rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.section-title.data-v-103261b1 {
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
color: #FFA500;
|
||||
margin-bottom: 32rpx;
|
||||
display: block;
|
||||
padding-bottom: 24rpx;
|
||||
border-bottom: 4rpx solid #f0f0f0;
|
||||
}
|
||||
.form-group.data-v-103261b1 {
|
||||
margin-bottom: 36rpx;
|
||||
}
|
||||
.form-group.data-v-103261b1:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.form-label.data-v-103261b1 {
|
||||
display: block;
|
||||
font-size: 36rpx;
|
||||
color: #1a1a1a;
|
||||
font-weight: 500;
|
||||
margin-bottom: 20rpx;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.form-input.data-v-103261b1 {
|
||||
width: 100%;
|
||||
padding: 28rpx;
|
||||
border: 4rpx solid #e0e0e0;
|
||||
border-radius: 16rpx;
|
||||
font-size: 36rpx;
|
||||
line-height: 1.6;
|
||||
color: #1a1a1a;
|
||||
background: #ffffff;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
height: auto;
|
||||
min-height: 96rpx;
|
||||
}
|
||||
.form-input.data-v-103261b1::-webkit-input-placeholder {
|
||||
color: #999;
|
||||
font-size: 34rpx;
|
||||
}
|
||||
.form-input.data-v-103261b1::placeholder {
|
||||
color: #999;
|
||||
font-size: 34rpx;
|
||||
}
|
||||
.avatar-container.data-v-103261b1 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 32rpx;
|
||||
}
|
||||
.avatar-image.data-v-103261b1 {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 80rpx;
|
||||
background: #f0f0f0;
|
||||
border: 4rpx solid #e0e0e0;
|
||||
}
|
||||
.avatar-upload.data-v-103261b1 {
|
||||
flex: 1;
|
||||
padding: 36rpx;
|
||||
border: 4rpx dashed #FFA500;
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16rpx;
|
||||
min-height: 120rpx;
|
||||
}
|
||||
.upload-icon.data-v-103261b1 {
|
||||
font-size: 56rpx;
|
||||
}
|
||||
.upload-text.data-v-103261b1 {
|
||||
font-size: 34rpx;
|
||||
color: #FFA500;
|
||||
font-weight: 500;
|
||||
}
|
||||
.sex-group.data-v-103261b1 {
|
||||
display: flex;
|
||||
gap: 28rpx;
|
||||
}
|
||||
.sex-btn.data-v-103261b1 {
|
||||
flex: 1;
|
||||
padding: 32rpx;
|
||||
border: 4rpx solid #e0e0e0;
|
||||
border-radius: 16rpx;
|
||||
text-align: center;
|
||||
font-size: 38rpx;
|
||||
line-height: 1.5;
|
||||
color: #555;
|
||||
background: #ffffff;
|
||||
transition: all 0.3s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 96rpx;
|
||||
}
|
||||
.sex-btn.active.data-v-103261b1 {
|
||||
border-color: #FFA500;
|
||||
background: #fff7e6;
|
||||
color: #FFA500;
|
||||
font-weight: bold;
|
||||
}
|
||||
.button-group.data-v-103261b1 {
|
||||
display: flex;
|
||||
gap: 28rpx;
|
||||
margin-top: 56rpx;
|
||||
margin-bottom: 56rpx;
|
||||
}
|
||||
.btn.data-v-103261b1 {
|
||||
flex: 1;
|
||||
padding: 36rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
min-height: 100rpx;
|
||||
}
|
||||
.btn.data-v-103261b1:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
.btn.data-v-103261b1:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.btn-cancel.data-v-103261b1 {
|
||||
background: #f0f0f0;
|
||||
color: #555;
|
||||
}
|
||||
.btn-submit.data-v-103261b1 {
|
||||
background: #FFA500;
|
||||
color: #ffffff;
|
||||
}
|
||||
.btn-submit.data-v-103261b1:active:not(:disabled) {
|
||||
background: #e69500;
|
||||
}
|
||||
.userinfo-container.data-v-103261b1{min-height:100vh;background:#e8eaed}.header.data-v-103261b1{display:flex;justify-content:space-between;align-items:center;background:#fff;padding:24rpx 40rpx;box-shadow:0 2rpx 12rpx rgba(0,0,0,.06)}.header-back.data-v-103261b1{font-size:48rpx;color:orange;width:88rpx;height:88rpx;display:flex;align-items:center;justify-content:center}.header-title.data-v-103261b1{font-size:44rpx;font-weight:700;color:#1a1a1a;flex:1;text-align:center}.header-placeholder.data-v-103261b1{width:88rpx}.loading-state.data-v-103261b1{display:flex;justify-content:center;align-items:center;height:100vh;font-size:36rpx;color:#555}.form-wrapper.data-v-103261b1{padding:40rpx}.form-section.data-v-103261b1{background:#fff;border-radius:24rpx;padding:40rpx;margin-bottom:36rpx;box-shadow:0 4rpx 16rpx rgba(0,0,0,.06)}.section-title.data-v-103261b1{font-size:40rpx;font-weight:700;color:orange;margin-bottom:32rpx;display:block;padding-bottom:24rpx;border-bottom:4rpx solid #f0f0f0}.form-group.data-v-103261b1{margin-bottom:36rpx}.form-group.data-v-103261b1:last-child{margin-bottom:0}.form-label.data-v-103261b1{display:block;font-size:36rpx;color:#1a1a1a;font-weight:500;margin-bottom:20rpx;line-height:1.6}.form-input.data-v-103261b1{width:100%;padding:28rpx;border:4rpx solid #e0e0e0;border-radius:16rpx;font-size:36rpx;line-height:1.6;color:#1a1a1a;background:#fff;box-sizing:border-box;display:block;height:auto;min-height:96rpx}.form-input.data-v-103261b1::-webkit-input-placeholder{color:#999;font-size:34rpx}.form-input.data-v-103261b1::placeholder{color:#999;font-size:34rpx}.avatar-container.data-v-103261b1{display:flex;align-items:center;gap:32rpx}.avatar-image.data-v-103261b1{width:160rpx;height:160rpx;border-radius:80rpx;background:#f0f0f0;border:4rpx solid #e0e0e0}.avatar-upload.data-v-103261b1{flex:1;padding:36rpx;border:4rpx dashed #FFA500;border-radius:20rpx;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16rpx;min-height:120rpx}.upload-icon.data-v-103261b1{font-size:56rpx}.upload-text.data-v-103261b1{font-size:34rpx;color:orange;font-weight:500}.sex-group.data-v-103261b1{display:flex;gap:28rpx}.sex-btn.data-v-103261b1{flex:1;padding:32rpx;border:4rpx solid #e0e0e0;border-radius:16rpx;text-align:center;font-size:38rpx;line-height:1.5;color:#555;background:#fff;transition:all .3s;display:flex;align-items:center;justify-content:center;min-height:96rpx}.sex-btn.active.data-v-103261b1{border-color:orange;background:#fff7e6;color:orange;font-weight:700}.button-group.data-v-103261b1{display:flex;gap:28rpx;margin-top:56rpx;margin-bottom:56rpx}.btn.data-v-103261b1{flex:1;padding:36rpx;border-radius:20rpx;font-size:40rpx;font-weight:700;border:none;cursor:pointer;transition:all .3s;min-height:100rpx}.btn.data-v-103261b1:active{transform:scale(.98)}.btn.data-v-103261b1:disabled{opacity:.6;cursor:not-allowed}.btn-cancel.data-v-103261b1{background:#f0f0f0;color:#555}.btn-submit.data-v-103261b1{background:orange;color:#fff}.btn-submit.data-v-103261b1:active:not(:disabled){background:#e69500}
|
||||
@@ -9,12 +9,11 @@
|
||||
"postcss": false,
|
||||
"minified": true,
|
||||
"newFeature": true,
|
||||
"bigPackageSizeSupport": true,
|
||||
"minifyWXML": true
|
||||
"bigPackageSizeSupport": true
|
||||
},
|
||||
"compileType": "miniprogram",
|
||||
"libVersion": "",
|
||||
"appid": "wx79b9a0bfbfe7cbcd",
|
||||
"appid": "wx0c2a9d5ebad26a3f",
|
||||
"projectname": "tongji-uniapp",
|
||||
"condition": {
|
||||
"search": {
|
||||
|
||||
+1
-85
@@ -1,86 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
if (!Math) {
|
||||
TongjiIcon();
|
||||
}
|
||||
const TongjiIcon = () => "./TongjiIcon.js";
|
||||
const _sfc_main = {
|
||||
__name: "CelebrateBurst",
|
||||
props: {
|
||||
show: { type: Boolean, default: false },
|
||||
title: { type: String, default: "" },
|
||||
subtitle: { type: String, default: "" }
|
||||
},
|
||||
setup(__props) {
|
||||
const props = __props;
|
||||
const particles = common_vendor.ref([]);
|
||||
const cardPop = common_vendor.ref(false);
|
||||
const COLORS = ["#204E2B", "#386641", "#AFE2B3", "#FBBF24", "#727970", "#DC2626"];
|
||||
function buildParticles() {
|
||||
const list = [];
|
||||
for (let i = 0; i < 18; i++) {
|
||||
const left = 8 + Math.random() * 84;
|
||||
const delay = Math.random() * 0.35;
|
||||
const hue = COLORS[i % COLORS.length];
|
||||
const size = 10 + Math.floor(Math.random() * 14);
|
||||
list.push({
|
||||
id: `${Date.now()}_${i}`,
|
||||
style: {
|
||||
left: `${left}%`,
|
||||
width: `${size}rpx`,
|
||||
height: `${size}rpx`,
|
||||
background: hue,
|
||||
animationDelay: `${delay}s`
|
||||
}
|
||||
});
|
||||
}
|
||||
return list;
|
||||
}
|
||||
common_vendor.watch(
|
||||
() => props.show,
|
||||
(v) => {
|
||||
if (v) {
|
||||
particles.value = buildParticles();
|
||||
cardPop.value = false;
|
||||
setTimeout(() => {
|
||||
cardPop.value = true;
|
||||
}, 30);
|
||||
} else {
|
||||
particles.value = [];
|
||||
cardPop.value = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
return (_ctx, _cache) => {
|
||||
return common_vendor.e({
|
||||
a: __props.show
|
||||
}, __props.show ? common_vendor.e({
|
||||
b: common_vendor.f(particles.value, (p, k0, i0) => {
|
||||
return {
|
||||
a: p.id,
|
||||
b: common_vendor.s(p.style)
|
||||
};
|
||||
}),
|
||||
c: __props.title
|
||||
}, __props.title ? common_vendor.e({
|
||||
d: common_vendor.p({
|
||||
name: "sparkles",
|
||||
size: "lg",
|
||||
color: "#204E2B"
|
||||
}),
|
||||
e: common_vendor.t(__props.title),
|
||||
f: __props.subtitle
|
||||
}, __props.subtitle ? {
|
||||
g: common_vendor.t(__props.subtitle)
|
||||
} : {}, {
|
||||
h: cardPop.value ? 1 : ""
|
||||
}) : {}, {
|
||||
i: common_vendor.o(() => {
|
||||
}, "49")
|
||||
}) : {});
|
||||
};
|
||||
}
|
||||
};
|
||||
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-313f45d6"]]);
|
||||
wx.createComponent(Component);
|
||||
"use strict";const t=require("../../common/vendor.js");Math||h();const h=()=>"./TongjiIcon.js",m={__name:"CelebrateBurst",props:{show:{type:Boolean,default:!1},title:{type:String,default:""},subtitle:{type:String,default:""}},setup(e){const f=e,s=t.ref([]),l=t.ref(!1),i=["#204E2B","#386641","#AFE2B3","#FBBF24","#727970","#DC2626"];function d(){const a=[];for(let n=0;n<18;n++){const o=8+Math.random()*84,c=Math.random()*.35,u=i[n%i.length],r=10+Math.floor(Math.random()*14);a.push({id:`${Date.now()}_${n}`,style:{left:`${o}%`,width:`${r}rpx`,height:`${r}rpx`,background:u,animationDelay:`${c}s`}})}return a}return t.watch(()=>f.show,a=>{a?(s.value=d(),l.value=!1,setTimeout(()=>{l.value=!0},30)):(s.value=[],l.value=!1)}),(a,n)=>t.e({a:e.show},e.show?t.e({b:t.f(s.value,(o,c,u)=>({a:o.id,b:t.s(o.style)})),c:e.title},e.title?t.e({d:t.p({name:"sparkles",size:"lg",color:"#204E2B"}),e:t.t(e.title),f:e.subtitle},e.subtitle?{g:t.t(e.subtitle)}:{},{h:l.value?1:""}):{},{i:t.o(()=>{},"49")}):{})}},b=t._export_sfc(m,[["__scopeId","data-v-313f45d6"]]);wx.createComponent(b);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/tongji/components/CelebrateBurst.js.map
|
||||
|
||||
+1
-95
@@ -1,95 +1 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
/* 颜色变量 */
|
||||
/* 行为相关颜色 */
|
||||
/* 文字基本颜色 */
|
||||
/* 背景颜色 */
|
||||
/* 边框颜色 */
|
||||
/* 尺寸变量 */
|
||||
/* 文字尺寸 */
|
||||
/* 图片尺寸 */
|
||||
/* Border Radius */
|
||||
/* 水平间距 */
|
||||
/* 垂直间距 */
|
||||
/* 透明度 */
|
||||
/* 文章场景相关 */
|
||||
.celebrate-root.data-v-313f45d6 {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 9999;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
.celebrate-particle.data-v-313f45d6 {
|
||||
position: absolute;
|
||||
top: -20rpx;
|
||||
border-radius: 4rpx;
|
||||
opacity: 0.9;
|
||||
animation: celebrate-fall-313f45d6 1.6s ease-in forwards;
|
||||
}
|
||||
@keyframes celebrate-fall-313f45d6 {
|
||||
0% {
|
||||
transform: translateY(0) rotate(0deg) scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(110vh) rotate(540deg) scale(0.4);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.celebrate-card.data-v-313f45d6 {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 38%;
|
||||
transform: translate(-50%, -50%) scale(0.82);
|
||||
width: 78%;
|
||||
max-width: 560rpx;
|
||||
padding: 36rpx 32rpx 32rpx;
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
border-radius: 28rpx;
|
||||
box-shadow: 0 20rpx 60rpx rgba(8, 145, 178, 0.22);
|
||||
border: 2rpx solid rgba(8, 145, 178, 0.12);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
opacity: 0;
|
||||
transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.25s ease;
|
||||
}
|
||||
.celebrate-card.pop.data-v-313f45d6 {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
}
|
||||
.celebrate-card-glow.data-v-313f45d6 {
|
||||
position: absolute;
|
||||
inset: -20rpx;
|
||||
border-radius: 36rpx;
|
||||
background: radial-gradient(circle, rgba(34, 211, 238, 0.2), transparent 70%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.celebrate-card-title.data-v-313f45d6 {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-top: 16rpx;
|
||||
font-size: 36rpx;
|
||||
font-weight: 800;
|
||||
color: #1b1c1a;
|
||||
}
|
||||
.celebrate-card-sub.data-v-313f45d6 {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-top: 10rpx;
|
||||
font-size: 26rpx;
|
||||
color: #475569;
|
||||
line-height: 1.45;
|
||||
}
|
||||
.celebrate-root.data-v-313f45d6{position:fixed;top:0;right:0;bottom:0;left:0;z-index:9999;pointer-events:none;overflow:hidden}.celebrate-particle.data-v-313f45d6{position:absolute;top:-20rpx;border-radius:4rpx;opacity:.9;animation:celebrate-fall-313f45d6 1.6s ease-in forwards}@keyframes celebrate-fall-313f45d6{0%{transform:translateY(0) rotate(0) scale(1);opacity:1}to{transform:translateY(110vh) rotate(540deg) scale(.4);opacity:0}}.celebrate-card.data-v-313f45d6{position:absolute;left:50%;top:38%;transform:translate(-50%,-50%) scale(.82);width:78%;max-width:560rpx;padding:36rpx 32rpx 32rpx;background:rgba(255,255,255,.96);border-radius:28rpx;box-shadow:0 20rpx 60rpx rgba(8,145,178,.22);border:2rpx solid rgba(8,145,178,.12);display:flex;flex-direction:column;align-items:center;text-align:center;opacity:0;transition:transform .35s cubic-bezier(.34,1.56,.64,1),opacity .25s ease}.celebrate-card.pop.data-v-313f45d6{opacity:1;transform:translate(-50%,-50%) scale(1)}.celebrate-card-glow.data-v-313f45d6{position:absolute;top:-20rpx;right:-20rpx;bottom:-20rpx;left:-20rpx;border-radius:36rpx;background:radial-gradient(circle,rgba(34,211,238,.2),transparent 70%);pointer-events:none}.celebrate-card-title.data-v-313f45d6{position:relative;z-index:1;margin-top:16rpx;font-size:36rpx;font-weight:800;color:#1b1c1a}.celebrate-card-sub.data-v-313f45d6{position:relative;z-index:1;margin-top:10rpx;font-size:26rpx;color:#475569;line-height:1.45}
|
||||
+6
-93
@@ -1,100 +1,13 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const tongji_utils_svgDataUrl = require("../utils/svgDataUrl.js");
|
||||
const tongji_utils_treeLevels = require("../utils/treeLevels.js");
|
||||
const _sfc_main = {
|
||||
__name: "SugarTreeGraphic",
|
||||
props: {
|
||||
level: { type: Number, default: 0 },
|
||||
size: { type: String, default: "md" },
|
||||
watering: { type: Boolean, default: false }
|
||||
},
|
||||
setup(__props) {
|
||||
const MAX_LEVEL = tongji_utils_treeLevels.TREE_MAX_LEVEL;
|
||||
const treeUseFallback = common_vendor.ref(true);
|
||||
const props = __props;
|
||||
const clampedLevel = common_vendor.computed(() => Math.min(MAX_LEVEL, Math.max(0, Number(props.level) || 0)));
|
||||
const visualTier = common_vendor.computed(() => {
|
||||
const lv = clampedLevel.value;
|
||||
if (lv <= 0)
|
||||
return 0;
|
||||
if (lv <= 2)
|
||||
return 1;
|
||||
if (lv <= 4)
|
||||
return 2;
|
||||
if (lv <= 6)
|
||||
return 3;
|
||||
if (lv <= 8)
|
||||
return 4;
|
||||
return 5;
|
||||
});
|
||||
const treeEmoji = common_vendor.computed(() => (tongji_utils_treeLevels.TREE_LEVELS[clampedLevel.value] || tongji_utils_treeLevels.TREE_LEVELS[0]).emoji);
|
||||
function buildTreeSvg(level) {
|
||||
const pot = `
|
||||
"use strict";const c=require("../../common/vendor.js"),L=require("../utils/svgDataUrl.js"),v=require("../utils/treeLevels.js"),M={__name:"SugarTreeGraphic",props:{level:{type:Number,default:0},size:{type:String,default:"md"},watering:{type:Boolean,default:!1}},setup(n){const l=v.TREE_MAX_LEVEL,o=c.ref(!0),x=n,r=c.computed(()=>Math.min(l,Math.max(0,Number(x.level)||0))),y=c.computed(()=>{const t=r.value;return t<=0?0:t<=2?1:t<=4?2:t<=6?3:t<=8?4:5}),$=c.computed(()=>(v.TREE_LEVELS[r.value]||v.TREE_LEVELS[0]).emoji);function h(t){const s=`
|
||||
<ellipse cx="24" cy="50" rx="15" ry="3" fill="#204e2b" opacity="0.12"/>
|
||||
<path d="M11 46h26c1.2 0 2 1 2 2.2v3.8c0 1-.8 1.8-1.8 1.8H10.8c-1 0-1.8-.8-1.8-1.8v-3.8c0-1.2.8-2.2 2-2.2z" fill="#E7E5E4"/>
|
||||
<path d="M12.5 46h23c.8 0 1.5.7 1.5 1.5v2.2c0 .6-.5 1.1-1.1 1.1H12.1c-.6 0-1.1-.5-1.1-1.1v-2.2c0-.8.7-1.5 1.5-1.5z" fill="#D6D3D1"/>
|
||||
<ellipse cx="24" cy="46.5" rx="9" ry="1.6" fill="#A8A29E" opacity="0.35"/>
|
||||
`;
|
||||
const soil = `<ellipse cx="24" cy="44.5" rx="8" ry="2.2" fill="#386641" opacity="0.18"/>`;
|
||||
if (level <= 0) {
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 56" fill="none">
|
||||
${pot}${soil}
|
||||
`,u='<ellipse cx="24" cy="44.5" rx="8" ry="2.2" fill="#386641" opacity="0.18"/>';if(t<=0)return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 56" fill="none">
|
||||
${s}${u}
|
||||
<circle cx="24" cy="41.5" r="2.2" fill="#a8a29e" opacity="0.7"/>
|
||||
<path d="M24 41.5v3.5" stroke="#78716c" stroke-width="1" stroke-linecap="round"/>
|
||||
</svg>`;
|
||||
}
|
||||
const trunkH = level >= 6 ? 16 : level >= 3 ? 14 : 10;
|
||||
const trunkY = 46 - trunkH;
|
||||
const trunk = `<rect x="22.2" y="${trunkY}" width="3.6" height="${trunkH}" rx="1.8" fill="#78716C"/>
|
||||
<rect x="22.6" y="${trunkY + 1}" width="2.8" height="${trunkH - 1}" rx="1.4" fill="#A8A29E" opacity="0.35"/>`;
|
||||
const leaf = (cx, cy, r, fill, opacity = 1) => `<circle cx="${cx}" cy="${cy}" r="${r}" fill="${fill}" opacity="${opacity}"/>
|
||||
<circle cx="${cx - r * 0.25}" cy="${cy - r * 0.2}" r="${r * 0.35}" fill="#eef6ef" opacity="0.55"/>`;
|
||||
const bloom = level >= 7 ? leaf(17, 18, 3, "#fda4af", 0.95) + leaf(31, 17, 2.8, "#f9a8d4", 0.9) + leaf(24, 13, 3.2, "#fb7185", 0.95) + `<circle cx="24" cy="12" r="1.3" fill="#fef3c7"/>` : "";
|
||||
const crown = level >= 9 ? leaf(12, 22, 6, "#34d399", 0.9) + leaf(36, 22, 6, "#34d399", 0.9) + leaf(24, 10, 7, "#386641", 0.95) + bloom : bloom;
|
||||
let canopy = "";
|
||||
if (level === 1) {
|
||||
canopy = leaf(24, 38, 4, "#afe2b3") + `<path d="M24 38v-5" stroke="#386641" stroke-width="1.2" stroke-linecap="round"/>`;
|
||||
} else if (level === 2) {
|
||||
canopy = leaf(24, 32, 5.5, "#34d399") + leaf(20, 34, 3.5, "#6ee7b7", 0.9);
|
||||
} else if (level <= 4) {
|
||||
canopy = leaf(24, 28, 7, "#34d399") + leaf(17, 30, 5, "#6ee7b7", 0.9) + leaf(31, 30, 5, "#6ee7b7", 0.9);
|
||||
} else if (level <= 6) {
|
||||
canopy = leaf(24, 24, 9, "#22c55e") + leaf(14, 26, 7, "#4ade80", 0.92) + leaf(34, 26, 7, "#4ade80", 0.92) + leaf(24, 16, 6, "#386641", 0.88);
|
||||
} else {
|
||||
canopy = leaf(24, 20, 10, "#204e2b") + leaf(13, 24, 8, "#34d399", 0.95) + leaf(35, 24, 8, "#34d399", 0.95) + crown;
|
||||
}
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 56" fill="none">${pot}${soil}${trunk}${canopy}</svg>`;
|
||||
}
|
||||
const treeImageSrc = common_vendor.computed(() => tongji_utils_svgDataUrl.svgToDataUrl(buildTreeSvg(clampedLevel.value)));
|
||||
return (_ctx, _cache) => {
|
||||
return common_vendor.e({
|
||||
a: clampedLevel.value >= 7
|
||||
}, clampedLevel.value >= 7 ? {} : {}, {
|
||||
b: !treeUseFallback.value
|
||||
}, !treeUseFallback.value ? {
|
||||
c: treeImageSrc.value,
|
||||
d: common_vendor.o(($event) => treeUseFallback.value = true, "20")
|
||||
} : {
|
||||
e: common_vendor.t(treeEmoji.value)
|
||||
}, {
|
||||
f: clampedLevel.value >= 7
|
||||
}, clampedLevel.value >= 7 ? {} : {}, {
|
||||
g: clampedLevel.value >= 8
|
||||
}, clampedLevel.value >= 8 ? {} : {}, {
|
||||
h: clampedLevel.value >= common_vendor.unref(MAX_LEVEL)
|
||||
}, clampedLevel.value >= common_vendor.unref(MAX_LEVEL) ? {} : {}, {
|
||||
i: common_vendor.n(`lv-${clampedLevel.value}`),
|
||||
j: common_vendor.n(`tier-${visualTier.value}`),
|
||||
k: common_vendor.n(`size-${__props.size}`),
|
||||
l: common_vendor.n({
|
||||
watering: __props.watering,
|
||||
"is-max": clampedLevel.value >= common_vendor.unref(MAX_LEVEL)
|
||||
})
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-d91cb5e7"]]);
|
||||
wx.createComponent(Component);
|
||||
</svg>`;const f=t>=6?16:t>=3?14:10,d=46-f,w=`<rect x="22.2" y="${d}" width="3.6" height="${f}" rx="1.8" fill="#78716C"/>
|
||||
<rect x="22.6" y="${d+1}" width="2.8" height="${f-1}" rx="1.4" fill="#A8A29E" opacity="0.35"/>`,e=(m,g,a,b,k=1)=>`<circle cx="${m}" cy="${g}" r="${a}" fill="${b}" opacity="${k}"/>
|
||||
<circle cx="${m-a*.25}" cy="${g-a*.2}" r="${a*.35}" fill="#eef6ef" opacity="0.55"/>`,p=t>=7?e(17,18,3,"#fda4af",.95)+e(31,17,2.8,"#f9a8d4",.9)+e(24,13,3.2,"#fb7185",.95)+'<circle cx="24" cy="12" r="1.3" fill="#fef3c7"/>':"",_=t>=9?e(12,22,6,"#34d399",.9)+e(36,22,6,"#34d399",.9)+e(24,10,7,"#386641",.95)+p:p;let i="";return t===1?i=e(24,38,4,"#afe2b3")+'<path d="M24 38v-5" stroke="#386641" stroke-width="1.2" stroke-linecap="round"/>':t===2?i=e(24,32,5.5,"#34d399")+e(20,34,3.5,"#6ee7b7",.9):t<=4?i=e(24,28,7,"#34d399")+e(17,30,5,"#6ee7b7",.9)+e(31,30,5,"#6ee7b7",.9):t<=6?i=e(24,24,9,"#22c55e")+e(14,26,7,"#4ade80",.92)+e(34,26,7,"#4ade80",.92)+e(24,16,6,"#386641",.88):i=e(24,20,10,"#204e2b")+e(13,24,8,"#34d399",.95)+e(35,24,8,"#34d399",.95)+_,`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 56" fill="none">${s}${u}${w}${i}</svg>`}const E=c.computed(()=>L.svgToDataUrl(h(r.value)));return(t,s)=>c.e({a:r.value>=7},r.value>=7?{}:{},{b:!o.value},o.value?{e:c.t($.value)}:{c:E.value,d:c.o(u=>o.value=!0,"20")},{f:r.value>=7},r.value>=7?{}:{},{g:r.value>=8},r.value>=8?{}:{},{h:r.value>=c.unref(l)},r.value>=c.unref(l)?{}:{},{i:c.n(`lv-${r.value}`),j:c.n(`tier-${y.value}`),k:c.n(`size-${n.size}`),l:c.n({watering:n.watering,"is-max":r.value>=c.unref(l)})})}},T=c._export_sfc(M,[["__scopeId","data-v-d91cb5e7"]]);wx.createComponent(T);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/tongji/components/SugarTreeGraphic.js.map
|
||||
|
||||
+1
-153
@@ -1,153 +1 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
/* 颜色变量 */
|
||||
/* 行为相关颜色 */
|
||||
/* 文字基本颜色 */
|
||||
/* 背景颜色 */
|
||||
/* 边框颜色 */
|
||||
/* 尺寸变量 */
|
||||
/* 文字尺寸 */
|
||||
/* 图片尺寸 */
|
||||
/* Border Radius */
|
||||
/* 水平间距 */
|
||||
/* 垂直间距 */
|
||||
/* 透明度 */
|
||||
/* 文章场景相关 */
|
||||
.sugar-tree-graphic.data-v-d91cb5e7 {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.size-sm.data-v-d91cb5e7 {
|
||||
width: 64rpx;
|
||||
height: 72rpx;
|
||||
}
|
||||
.size-md.data-v-d91cb5e7 {
|
||||
width: 80rpx;
|
||||
height: 88rpx;
|
||||
}
|
||||
.size-lg.data-v-d91cb5e7 {
|
||||
width: 112rpx;
|
||||
height: 124rpx;
|
||||
}
|
||||
.stg-glow.data-v-d91cb5e7 {
|
||||
position: absolute;
|
||||
inset: 6%;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(32, 78, 43, 0.22) 0%, transparent 68%);
|
||||
pointer-events: none;
|
||||
}
|
||||
.lv-0 .stg-glow.data-v-d91cb5e7 {
|
||||
background: radial-gradient(circle, rgba(148, 163, 184, 0.25) 0%, transparent 70%);
|
||||
}
|
||||
.tier-4 .stg-glow.data-v-d91cb5e7,
|
||||
.tier-5 .stg-glow.data-v-d91cb5e7,
|
||||
.is-max .stg-glow.data-v-d91cb5e7 {
|
||||
background: radial-gradient(circle, rgba(251, 191, 36, 0.3) 0%, rgba(32, 78, 43, 0.15) 55%, transparent 72%);
|
||||
}
|
||||
.stg-aura.data-v-d91cb5e7 {
|
||||
position: absolute;
|
||||
inset: -8%;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid rgba(253, 224, 71, 0.35);
|
||||
animation: stg-aura-pulse-d91cb5e7 2.4s ease-in-out infinite;
|
||||
pointer-events: none;
|
||||
}
|
||||
@keyframes stg-aura-pulse-d91cb5e7 {
|
||||
0%, 100% {
|
||||
transform: scale(0.92);
|
||||
opacity: 0.5;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.05);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.stg-image.data-v-d91cb5e7 {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: transform 0.35s ease;
|
||||
}
|
||||
.sugar-tree-graphic.watering .stg-image.data-v-d91cb5e7,
|
||||
.sugar-tree-graphic.watering .stg-emoji.data-v-d91cb5e7 {
|
||||
animation: stg-water-bounce-d91cb5e7 0.65s ease;
|
||||
}
|
||||
.stg-emoji.data-v-d91cb5e7 {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
line-height: 1;
|
||||
font-size: 72rpx;
|
||||
}
|
||||
.size-sm .stg-emoji.data-v-d91cb5e7 {
|
||||
font-size: 48rpx;
|
||||
}
|
||||
.size-md .stg-emoji.data-v-d91cb5e7 {
|
||||
font-size: 60rpx;
|
||||
}
|
||||
.size-lg .stg-emoji.data-v-d91cb5e7 {
|
||||
font-size: 88rpx;
|
||||
}
|
||||
@keyframes stg-water-bounce-d91cb5e7 {
|
||||
0%, 100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
35% {
|
||||
transform: scale(1.1) translateY(-6rpx);
|
||||
}
|
||||
60% {
|
||||
transform: scale(0.96) translateY(2rpx);
|
||||
}
|
||||
}
|
||||
.stg-sparkle.data-v-d91cb5e7 {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
border-radius: 50%;
|
||||
background: #fde68a;
|
||||
box-shadow: 0 0 6rpx rgba(253, 224, 71, 0.8);
|
||||
pointer-events: none;
|
||||
animation: stg-sparkle-twinkle-d91cb5e7 1.8s ease-in-out infinite;
|
||||
}
|
||||
.stg-sparkle-a.data-v-d91cb5e7 {
|
||||
top: 4%;
|
||||
right: 16%;
|
||||
}
|
||||
.stg-sparkle-b.data-v-d91cb5e7 {
|
||||
top: 12%;
|
||||
left: 10%;
|
||||
width: 6rpx;
|
||||
height: 6rpx;
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
.stg-sparkle-c.data-v-d91cb5e7 {
|
||||
top: 22%;
|
||||
right: 28%;
|
||||
width: 10rpx;
|
||||
height: 10rpx;
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
@keyframes stg-sparkle-twinkle-d91cb5e7 {
|
||||
0%, 100% {
|
||||
opacity: 0.4;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: scale(1.2);
|
||||
}
|
||||
}
|
||||
.sugar-tree-graphic.data-v-d91cb5e7{position:relative;display:flex;align-items:center;justify-content:center;box-sizing:border-box}.size-sm.data-v-d91cb5e7{width:64rpx;height:72rpx}.size-md.data-v-d91cb5e7{width:80rpx;height:88rpx}.size-lg.data-v-d91cb5e7{width:112rpx;height:124rpx}.stg-glow.data-v-d91cb5e7{position:absolute;top:6%;right:6%;bottom:6%;left:6%;border-radius:50%;background:radial-gradient(circle,rgba(32,78,43,.22) 0%,transparent 68%);pointer-events:none}.lv-0 .stg-glow.data-v-d91cb5e7{background:radial-gradient(circle,rgba(148,163,184,.25) 0%,transparent 70%)}.tier-4 .stg-glow.data-v-d91cb5e7,.tier-5 .stg-glow.data-v-d91cb5e7,.is-max .stg-glow.data-v-d91cb5e7{background:radial-gradient(circle,rgba(251,191,36,.3) 0%,rgba(32,78,43,.15) 55%,transparent 72%)}.stg-aura.data-v-d91cb5e7{position:absolute;top:-8%;right:-8%;bottom:-8%;left:-8%;border-radius:50%;border:2rpx solid rgba(253,224,71,.35);animation:stg-aura-pulse-d91cb5e7 2.4s ease-in-out infinite;pointer-events:none}@keyframes stg-aura-pulse-d91cb5e7{0%,to{transform:scale(.92);opacity:.5}50%{transform:scale(1.05);opacity:1}}.stg-image.data-v-d91cb5e7{position:relative;z-index:1;width:100%;height:100%;transition:transform .35s ease}.sugar-tree-graphic.watering .stg-image.data-v-d91cb5e7,.sugar-tree-graphic.watering .stg-emoji.data-v-d91cb5e7{animation:stg-water-bounce-d91cb5e7 .65s ease}.stg-emoji.data-v-d91cb5e7{position:relative;z-index:1;line-height:1;font-size:72rpx}.size-sm .stg-emoji.data-v-d91cb5e7{font-size:48rpx}.size-md .stg-emoji.data-v-d91cb5e7{font-size:60rpx}.size-lg .stg-emoji.data-v-d91cb5e7{font-size:88rpx}@keyframes stg-water-bounce-d91cb5e7{0%,to{transform:scale(1)}35%{transform:scale(1.1) translateY(-6rpx)}60%{transform:scale(.96) translateY(2rpx)}}.stg-sparkle.data-v-d91cb5e7{position:absolute;z-index:2;width:8rpx;height:8rpx;border-radius:50%;background:#fde68a;box-shadow:0 0 6rpx rgba(253,224,71,.8);pointer-events:none;animation:stg-sparkle-twinkle-d91cb5e7 1.8s ease-in-out infinite}.stg-sparkle-a.data-v-d91cb5e7{top:4%;right:16%}.stg-sparkle-b.data-v-d91cb5e7{top:12%;left:10%;width:6rpx;height:6rpx;animation-delay:.4s}.stg-sparkle-c.data-v-d91cb5e7{top:22%;right:28%;width:10rpx;height:10rpx;animation-delay:.8s}@keyframes stg-sparkle-twinkle-d91cb5e7{0%,to{opacity:.4;transform:scale(.8)}50%{opacity:1;transform:scale(1.2)}}
|
||||
+1
-128
File diff suppressed because one or more lines are too long
+1
-75
@@ -1,75 +1 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
/* 颜色变量 */
|
||||
/* 行为相关颜色 */
|
||||
/* 文字基本颜色 */
|
||||
/* 背景颜色 */
|
||||
/* 边框颜色 */
|
||||
/* 尺寸变量 */
|
||||
/* 文字尺寸 */
|
||||
/* 图片尺寸 */
|
||||
/* Border Radius */
|
||||
/* 水平间距 */
|
||||
/* 垂直间距 */
|
||||
/* 透明度 */
|
||||
/* 文章场景相关 */
|
||||
.tj-icon-wrap.data-v-f41c6626 {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.tj-icon-wrap--sm.data-v-f41c6626 {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
.tj-icon-wrap--md.data-v-f41c6626 {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
.tj-icon-wrap--lg.data-v-f41c6626 {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
.tj-icon-wrap--xl.data-v-f41c6626 {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
}
|
||||
.tj-icon.data-v-f41c6626 {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Lucide send 路径重心偏右上,微调使圆形按钮内视觉居中 */
|
||||
.tj-icon--send.data-v-f41c6626 {
|
||||
transform: translate(-10%, 10%);
|
||||
}
|
||||
.tj-icon-fallback.data-v-f41c6626 {
|
||||
display: block;
|
||||
line-height: 1;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
}
|
||||
.tj-icon-fallback--sm.data-v-f41c6626 {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.tj-icon-fallback--md.data-v-f41c6626 {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.tj-icon-fallback--lg.data-v-f41c6626 {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
.tj-icon-fallback--xl.data-v-f41c6626 {
|
||||
font-size: 42rpx;
|
||||
}
|
||||
.tj-icon-wrap.data-v-f41c6626{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.tj-icon-wrap--sm.data-v-f41c6626{width:32rpx;height:32rpx}.tj-icon-wrap--md.data-v-f41c6626{width:40rpx;height:40rpx}.tj-icon-wrap--lg.data-v-f41c6626{width:48rpx;height:48rpx}.tj-icon-wrap--xl.data-v-f41c6626{width:56rpx;height:56rpx}.tj-icon.data-v-f41c6626{display:block;width:100%;height:100%}.tj-icon--send.data-v-f41c6626{transform:translate(-10%,10%)}.tj-icon-fallback.data-v-f41c6626{display:block;line-height:1;font-weight:700;text-align:center}.tj-icon-fallback--sm.data-v-f41c6626{font-size:24rpx}.tj-icon-fallback--md.data-v-f41c6626{font-size:30rpx}.tj-icon-fallback--lg.data-v-f41c6626{font-size:36rpx}.tj-icon-fallback--xl.data-v-f41c6626{font-size:42rpx}
|
||||
+1
-27
@@ -1,28 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const _sfc_main = {
|
||||
__name: "VoiceSpeakMascot",
|
||||
props: {
|
||||
/** 正在按住说话 / 录音中 */
|
||||
active: { type: Boolean, default: false },
|
||||
/** 深色条背景上使用浅色卡通 */
|
||||
onDark: { type: Boolean, default: false },
|
||||
size: { type: String, default: "md" }
|
||||
},
|
||||
setup(__props) {
|
||||
return (_ctx, _cache) => {
|
||||
return common_vendor.e({
|
||||
a: __props.active
|
||||
}, __props.active ? {} : {}, {
|
||||
b: common_vendor.n(`vsm--${__props.size}`),
|
||||
c: common_vendor.n({
|
||||
"vsm--active": __props.active,
|
||||
"vsm--on-dark": __props.onDark
|
||||
})
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-e1de3b0a"]]);
|
||||
wx.createComponent(Component);
|
||||
"use strict";const t=require("../../common/vendor.js"),a={__name:"VoiceSpeakMascot",props:{active:{type:Boolean,default:!1},onDark:{type:Boolean,default:!1},size:{type:String,default:"md"}},setup(e){return(c,o)=>t.e({a:e.active},e.active?{}:{},{b:t.n(`vsm--${e.size}`),c:t.n({"vsm--active":e.active,"vsm--on-dark":e.onDark})})}},n=t._export_sfc(a,[["__scopeId","data-v-e1de3b0a"]]);wx.createComponent(n);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/tongji/components/VoiceSpeakMascot.js.map
|
||||
|
||||
+1
-230
@@ -1,230 +1 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
/* 颜色变量 */
|
||||
/* 行为相关颜色 */
|
||||
/* 文字基本颜色 */
|
||||
/* 背景颜色 */
|
||||
/* 边框颜色 */
|
||||
/* 尺寸变量 */
|
||||
/* 文字尺寸 */
|
||||
/* 图片尺寸 */
|
||||
/* Border Radius */
|
||||
/* 水平间距 */
|
||||
/* 垂直间距 */
|
||||
/* 透明度 */
|
||||
/* 文章场景相关 */
|
||||
.vsm.data-v-e1de3b0a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.vsm--md.data-v-e1de3b0a {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
}
|
||||
.vsm--sm.data-v-e1de3b0a {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
}
|
||||
.vsm-body.data-v-e1de3b0a {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.vsm-leaf.data-v-e1de3b0a {
|
||||
position: absolute;
|
||||
top: 2rpx;
|
||||
left: 50%;
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
margin-left: -8rpx;
|
||||
border-radius: 0 100% 0 100%;
|
||||
background: #34d399;
|
||||
transform: rotate(-18deg);
|
||||
z-index: 2;
|
||||
}
|
||||
.vsm--on-dark .vsm-leaf.data-v-e1de3b0a {
|
||||
background: #a7f3d0;
|
||||
}
|
||||
.vsm-face.data-v-e1de3b0a {
|
||||
position: relative;
|
||||
width: 52rpx;
|
||||
height: 52rpx;
|
||||
border-radius: 50%;
|
||||
background: #fef9c3;
|
||||
border: 3rpx solid #047857;
|
||||
box-shadow: 0 4rpx 10rpx rgba(4, 120, 87, 0.18);
|
||||
z-index: 1;
|
||||
}
|
||||
.vsm--sm .vsm-face.data-v-e1de3b0a {
|
||||
width: 46rpx;
|
||||
height: 46rpx;
|
||||
}
|
||||
.vsm--on-dark .vsm-face.data-v-e1de3b0a {
|
||||
background: #fffbeb;
|
||||
border-color: rgba(255, 255, 255, 0.85);
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
.vsm-eye.data-v-e1de3b0a {
|
||||
position: absolute;
|
||||
top: 16rpx;
|
||||
width: 6rpx;
|
||||
height: 8rpx;
|
||||
border-radius: 50%;
|
||||
background: #064e3b;
|
||||
}
|
||||
.vsm--sm .vsm-eye.data-v-e1de3b0a {
|
||||
top: 14rpx;
|
||||
width: 5rpx;
|
||||
height: 7rpx;
|
||||
}
|
||||
.vsm--on-dark .vsm-eye.data-v-e1de3b0a {
|
||||
background: #134e4a;
|
||||
}
|
||||
.vsm-eye--l.data-v-e1de3b0a {
|
||||
left: 12rpx;
|
||||
}
|
||||
.vsm-eye--r.data-v-e1de3b0a {
|
||||
right: 12rpx;
|
||||
}
|
||||
.vsm--sm .vsm-eye--l.data-v-e1de3b0a {
|
||||
left: 10rpx;
|
||||
}
|
||||
.vsm--sm .vsm-eye--r.data-v-e1de3b0a {
|
||||
right: 10rpx;
|
||||
}
|
||||
.vsm-blush.data-v-e1de3b0a {
|
||||
position: absolute;
|
||||
top: 24rpx;
|
||||
width: 10rpx;
|
||||
height: 6rpx;
|
||||
border-radius: 50%;
|
||||
background: rgba(251, 113, 133, 0.45);
|
||||
opacity: 0.85;
|
||||
}
|
||||
.vsm--sm .vsm-blush.data-v-e1de3b0a {
|
||||
top: 21rpx;
|
||||
width: 8rpx;
|
||||
height: 5rpx;
|
||||
}
|
||||
.vsm-blush--l.data-v-e1de3b0a {
|
||||
left: 6rpx;
|
||||
}
|
||||
.vsm-blush--r.data-v-e1de3b0a {
|
||||
right: 6rpx;
|
||||
}
|
||||
.vsm--on-dark .vsm-blush.data-v-e1de3b0a {
|
||||
background: rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
.vsm-mouth.data-v-e1de3b0a {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 10rpx;
|
||||
width: 18rpx;
|
||||
height: 8rpx;
|
||||
margin-left: -9rpx;
|
||||
border-radius: 0 0 18rpx 18rpx;
|
||||
background: #047857;
|
||||
transform-origin: center top;
|
||||
}
|
||||
.vsm--sm .vsm-mouth.data-v-e1de3b0a {
|
||||
bottom: 9rpx;
|
||||
width: 16rpx;
|
||||
height: 7rpx;
|
||||
margin-left: -8rpx;
|
||||
}
|
||||
.vsm--on-dark .vsm-mouth.data-v-e1de3b0a {
|
||||
background: #ecfdf5;
|
||||
}
|
||||
.vsm-waves.data-v-e1de3b0a {
|
||||
position: absolute;
|
||||
right: -2rpx;
|
||||
top: 50%;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: 4rpx;
|
||||
height: 28rpx;
|
||||
margin-top: -14rpx;
|
||||
z-index: 0;
|
||||
}
|
||||
.vsm-wave.data-v-e1de3b0a {
|
||||
width: 5rpx;
|
||||
border-radius: 4rpx;
|
||||
background: #047857;
|
||||
animation: vsm-wave-jump-e1de3b0a 0.72s ease-in-out infinite;
|
||||
}
|
||||
.vsm--on-dark .vsm-wave.data-v-e1de3b0a {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
.vsm-wave--1.data-v-e1de3b0a {
|
||||
height: 10rpx;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
.vsm-wave--2.data-v-e1de3b0a {
|
||||
height: 18rpx;
|
||||
animation-delay: 0.12s;
|
||||
}
|
||||
.vsm-wave--3.data-v-e1de3b0a {
|
||||
height: 12rpx;
|
||||
animation-delay: 0.24s;
|
||||
}
|
||||
.vsm--active .vsm-body.data-v-e1de3b0a {
|
||||
animation: vsm-bob-e1de3b0a 0.9s ease-in-out infinite;
|
||||
}
|
||||
.vsm--active .vsm-mouth.data-v-e1de3b0a {
|
||||
animation: vsm-talk-e1de3b0a 0.32s ease-in-out infinite alternate;
|
||||
}
|
||||
.vsm--active .vsm-eye.data-v-e1de3b0a {
|
||||
animation: vsm-blink-e1de3b0a 2.4s ease-in-out infinite;
|
||||
}
|
||||
@keyframes vsm-bob-e1de3b0a {
|
||||
0%, 100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-4rpx);
|
||||
}
|
||||
}
|
||||
@keyframes vsm-talk-e1de3b0a {
|
||||
0% {
|
||||
transform: scaleY(0.45);
|
||||
border-radius: 0 0 18rpx 18rpx;
|
||||
}
|
||||
100% {
|
||||
transform: scaleY(1.15);
|
||||
height: 12rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
@keyframes vsm-blink-e1de3b0a {
|
||||
0%, 42%, 46%, 100% {
|
||||
transform: scaleY(1);
|
||||
}
|
||||
44% {
|
||||
transform: scaleY(0.15);
|
||||
}
|
||||
}
|
||||
@keyframes vsm-wave-jump-e1de3b0a {
|
||||
0%, 100% {
|
||||
transform: scaleY(0.45);
|
||||
opacity: 0.55;
|
||||
}
|
||||
50% {
|
||||
transform: scaleY(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.vsm.data-v-e1de3b0a{display:flex;align-items:center;justify-content:center;flex-shrink:0}.vsm--md.data-v-e1de3b0a{width:72rpx;height:72rpx}.vsm--sm.data-v-e1de3b0a{width:64rpx;height:64rpx}.vsm-body.data-v-e1de3b0a{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center}.vsm-leaf.data-v-e1de3b0a{position:absolute;top:2rpx;left:50%;width:16rpx;height:16rpx;margin-left:-8rpx;border-radius:0 100%;background:#34d399;transform:rotate(-18deg);z-index:2}.vsm--on-dark .vsm-leaf.data-v-e1de3b0a{background:#a7f3d0}.vsm-face.data-v-e1de3b0a{position:relative;width:52rpx;height:52rpx;border-radius:50%;background:#fef9c3;border:3rpx solid #047857;box-shadow:0 4rpx 10rpx rgba(4,120,87,.18);z-index:1}.vsm--sm .vsm-face.data-v-e1de3b0a{width:46rpx;height:46rpx}.vsm--on-dark .vsm-face.data-v-e1de3b0a{background:#fffbeb;border-color:rgba(255,255,255,.85);box-shadow:0 4rpx 12rpx rgba(0,0,0,.12)}.vsm-eye.data-v-e1de3b0a{position:absolute;top:16rpx;width:6rpx;height:8rpx;border-radius:50%;background:#064e3b}.vsm--sm .vsm-eye.data-v-e1de3b0a{top:14rpx;width:5rpx;height:7rpx}.vsm--on-dark .vsm-eye.data-v-e1de3b0a{background:#134e4a}.vsm-eye--l.data-v-e1de3b0a{left:12rpx}.vsm-eye--r.data-v-e1de3b0a{right:12rpx}.vsm--sm .vsm-eye--l.data-v-e1de3b0a{left:10rpx}.vsm--sm .vsm-eye--r.data-v-e1de3b0a{right:10rpx}.vsm-blush.data-v-e1de3b0a{position:absolute;top:24rpx;width:10rpx;height:6rpx;border-radius:50%;background:rgba(251,113,133,.45);opacity:.85}.vsm--sm .vsm-blush.data-v-e1de3b0a{top:21rpx;width:8rpx;height:5rpx}.vsm-blush--l.data-v-e1de3b0a{left:6rpx}.vsm-blush--r.data-v-e1de3b0a{right:6rpx}.vsm--on-dark .vsm-blush.data-v-e1de3b0a{background:rgba(255,255,255,.35)}.vsm-mouth.data-v-e1de3b0a{position:absolute;left:50%;bottom:10rpx;width:18rpx;height:8rpx;margin-left:-9rpx;border-radius:0 0 18rpx 18rpx;background:#047857;transform-origin:center top}.vsm--sm .vsm-mouth.data-v-e1de3b0a{bottom:9rpx;width:16rpx;height:7rpx;margin-left:-8rpx}.vsm--on-dark .vsm-mouth.data-v-e1de3b0a{background:#ecfdf5}.vsm-waves.data-v-e1de3b0a{position:absolute;right:-2rpx;top:50%;display:flex;align-items:flex-end;gap:4rpx;height:28rpx;margin-top:-14rpx;z-index:0}.vsm-wave.data-v-e1de3b0a{width:5rpx;border-radius:4rpx;background:#047857;animation:vsm-wave-jump-e1de3b0a .72s ease-in-out infinite}.vsm--on-dark .vsm-wave.data-v-e1de3b0a{background:rgba(255,255,255,.9)}.vsm-wave--1.data-v-e1de3b0a{height:10rpx;animation-delay:0s}.vsm-wave--2.data-v-e1de3b0a{height:18rpx;animation-delay:.12s}.vsm-wave--3.data-v-e1de3b0a{height:12rpx;animation-delay:.24s}.vsm--active .vsm-body.data-v-e1de3b0a{animation:vsm-bob-e1de3b0a .9s ease-in-out infinite}.vsm--active .vsm-mouth.data-v-e1de3b0a{animation:vsm-talk-e1de3b0a .32s ease-in-out infinite alternate}.vsm--active .vsm-eye.data-v-e1de3b0a{animation:vsm-blink-e1de3b0a 2.4s ease-in-out infinite}@keyframes vsm-bob-e1de3b0a{0%,to{transform:translateY(0)}50%{transform:translateY(-4rpx)}}@keyframes vsm-talk-e1de3b0a{0%{transform:scaleY(.45);border-radius:0 0 18rpx 18rpx}to{transform:scaleY(1.15);height:12rpx;border-radius:50%}}@keyframes vsm-blink-e1de3b0a{0%,42%,46%,to{transform:scaleY(1)}44%{transform:scaleY(.15)}}@keyframes vsm-wave-jump-e1de3b0a{0%,to{transform:scaleY(.45);opacity:.55}50%{transform:scaleY(1);opacity:1}}
|
||||
+1
-306
@@ -1,307 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const tongji_utils_aiStreamRequest = require("../utils/aiStreamRequest.js");
|
||||
const DIET_AI_PREFILL_KEY = "tongji_diet_ai_prefill";
|
||||
const emptyDietAiRecommend = () => ({
|
||||
breakfast: "",
|
||||
drinks: "",
|
||||
lunch: "",
|
||||
dinner: "",
|
||||
tips: "",
|
||||
avoid: [],
|
||||
analysis: [],
|
||||
exercise: null,
|
||||
disclaimer: "",
|
||||
rules_summary: "",
|
||||
source: "",
|
||||
date: ""
|
||||
});
|
||||
function useDietAi(proxy, { diagnosisId, showUserToast, formatUserMessage }) {
|
||||
const dietAiRecommend = common_vendor.ref(emptyDietAiRecommend());
|
||||
const dietAiLoading = common_vendor.ref(false);
|
||||
const dietAiStreaming = common_vendor.ref(false);
|
||||
const dietAiReplacing = common_vendor.ref(false);
|
||||
const dietAiStreamField = common_vendor.ref("");
|
||||
let dietStreamBuffer = "";
|
||||
const dietAiAskText = common_vendor.ref("");
|
||||
const dietAiAsking = common_vendor.ref(false);
|
||||
const dietAiAskResult = common_vendor.ref({ advice: "", level: "", level_label: "", portion: "", food: "" });
|
||||
const hasDietAiMealContent = common_vendor.computed(() => {
|
||||
const r = dietAiRecommend.value;
|
||||
return !!(r.breakfast || r.drinks || r.lunch || r.dinner || r.tips);
|
||||
});
|
||||
function detectDietStreamField(text) {
|
||||
const tail = String(text || "").match(/(?:^|\n)(早餐|喝的|午餐|晚餐|提示|少碰)[::]\s*([^\n]*)$/);
|
||||
if (!tail)
|
||||
return "breakfast";
|
||||
const map = { "早餐": "breakfast", "喝的": "drinks", "午餐": "lunch", "晚餐": "dinner", "提示": "tips", "少碰": "tips" };
|
||||
return map[tail[1]] || "breakfast";
|
||||
}
|
||||
function mergePartialDietFromStream() {
|
||||
const partial = tongji_utils_aiStreamRequest.parsePartialDietPlainText(dietStreamBuffer);
|
||||
const next = { ...dietAiRecommend.value };
|
||||
for (const key of ["breakfast", "drinks", "lunch", "dinner", "tips"]) {
|
||||
if (partial[key] != null)
|
||||
next[key] = partial[key];
|
||||
}
|
||||
if (Array.isArray(partial.avoid))
|
||||
next.avoid = partial.avoid;
|
||||
dietAiRecommend.value = next;
|
||||
dietAiStreamField.value = detectDietStreamField(dietStreamBuffer);
|
||||
}
|
||||
function applyDietRecommendPayload(payload) {
|
||||
if (!payload)
|
||||
return;
|
||||
const prevAnalysis = dietAiRecommend.value.analysis;
|
||||
const prevExercise = dietAiRecommend.value.exercise;
|
||||
dietAiRecommend.value = {
|
||||
...emptyDietAiRecommend(),
|
||||
...payload,
|
||||
avoid: Array.isArray(payload.avoid) ? payload.avoid : [],
|
||||
analysis: Array.isArray(payload.analysis) && payload.analysis.length ? payload.analysis : Array.isArray(prevAnalysis) ? prevAnalysis : [],
|
||||
exercise: payload.exercise && typeof payload.exercise === "object" ? payload.exercise : prevExercise || null
|
||||
};
|
||||
}
|
||||
function resolveDietDonePayload(payload) {
|
||||
if (!payload)
|
||||
return payload;
|
||||
if (payload.source !== "rule" || !dietStreamBuffer)
|
||||
return payload;
|
||||
const streamed = tongji_utils_aiStreamRequest.parsePartialDietPlainText(dietStreamBuffer);
|
||||
if (!streamed.breakfast)
|
||||
return payload;
|
||||
return {
|
||||
...emptyDietAiRecommend(),
|
||||
...payload,
|
||||
breakfast: streamed.breakfast,
|
||||
drinks: streamed.drinks || payload.drinks || "",
|
||||
lunch: streamed.lunch || payload.lunch || "",
|
||||
dinner: streamed.dinner || payload.dinner || "",
|
||||
tips: streamed.tips || payload.tips || "",
|
||||
avoid: Array.isArray(streamed.avoid) && streamed.avoid.length ? streamed.avoid : payload.avoid || [],
|
||||
source: "ai",
|
||||
disclaimer: "AI 建议供参考,仍请结合医嘱与血糖监测。"
|
||||
};
|
||||
}
|
||||
function onDietAiStreamEvent(event, payload) {
|
||||
if (event === "analysis") {
|
||||
if (Array.isArray(payload == null ? void 0 : payload.analysis)) {
|
||||
dietAiRecommend.value = { ...dietAiRecommend.value, analysis: payload.analysis };
|
||||
}
|
||||
} else if (event === "exercise") {
|
||||
if ((payload == null ? void 0 : payload.exercise) && typeof payload.exercise === "object") {
|
||||
dietAiRecommend.value = { ...dietAiRecommend.value, exercise: payload.exercise };
|
||||
}
|
||||
} else if (event === "delta") {
|
||||
dietAiStreaming.value = true;
|
||||
if (payload.buffer != null) {
|
||||
dietStreamBuffer = payload.buffer;
|
||||
} else {
|
||||
dietStreamBuffer += payload.text || "";
|
||||
}
|
||||
mergePartialDietFromStream();
|
||||
} else if (event === "done") {
|
||||
applyDietRecommendPayload(resolveDietDonePayload(payload));
|
||||
dietStreamBuffer = "";
|
||||
dietAiStreamField.value = "";
|
||||
} else if (event === "error") {
|
||||
showUserToast(formatUserMessage(payload == null ? void 0 : payload.message, "饮食建议加载失败"));
|
||||
}
|
||||
}
|
||||
async function fetchDietAiRecommendFallback(refresh) {
|
||||
const res = await proxy.apiUrl({
|
||||
url: "/api/tcm/dailyDietAiRecommend",
|
||||
method: "GET",
|
||||
timeout: 35e3,
|
||||
data: {
|
||||
diagnosis_id: diagnosisId.value,
|
||||
refresh: refresh ? 1 : 0,
|
||||
...refresh ? { _t: Date.now() } : {}
|
||||
}
|
||||
}, false);
|
||||
if ((res == null ? void 0 : res.code) === 1 && res.data) {
|
||||
applyDietRecommendPayload(res.data);
|
||||
} else if (res == null ? void 0 : res.msg) {
|
||||
showUserToast(res.msg);
|
||||
}
|
||||
}
|
||||
async function fetchDietAiRecommend(refresh = false) {
|
||||
if (!diagnosisId.value || dietAiLoading.value)
|
||||
return;
|
||||
dietAiLoading.value = true;
|
||||
dietAiStreaming.value = false;
|
||||
dietAiReplacing.value = !!refresh;
|
||||
dietStreamBuffer = "";
|
||||
dietAiStreamField.value = "";
|
||||
if (refresh) {
|
||||
applyDietRecommendPayload(emptyDietAiRecommend());
|
||||
}
|
||||
try {
|
||||
await tongji_utils_aiStreamRequest.requestAiStream({
|
||||
baseUrl: proxy.$url,
|
||||
url: "/api/tcm/dailyDietAiRecommendStream",
|
||||
method: "GET",
|
||||
data: {
|
||||
diagnosis_id: diagnosisId.value,
|
||||
refresh: refresh ? 1 : 0,
|
||||
...refresh ? { _t: Date.now() } : {}
|
||||
},
|
||||
onEvent: onDietAiStreamEvent,
|
||||
fallback: () => fetchDietAiRecommendFallback(refresh)
|
||||
});
|
||||
} catch (e) {
|
||||
try {
|
||||
await fetchDietAiRecommendFallback(refresh);
|
||||
} catch (e2) {
|
||||
showUserToast("饮食建议加载失败");
|
||||
}
|
||||
} finally {
|
||||
dietAiLoading.value = false;
|
||||
dietAiStreaming.value = false;
|
||||
dietAiReplacing.value = false;
|
||||
dietAiStreamField.value = "";
|
||||
}
|
||||
}
|
||||
function refreshDietAiRecommend() {
|
||||
if (dietAiLoading.value)
|
||||
return;
|
||||
fetchDietAiRecommend(true);
|
||||
}
|
||||
async function askDietAiFoodFallback(q) {
|
||||
const res = await proxy.apiUrl({
|
||||
url: "/api/tcm/dailyDietAiAsk",
|
||||
method: "POST",
|
||||
timeout: 35e3,
|
||||
data: {
|
||||
diagnosis_id: diagnosisId.value,
|
||||
question: q
|
||||
}
|
||||
}, false);
|
||||
if ((res == null ? void 0 : res.code) === 1 && res.data) {
|
||||
dietAiAskResult.value = {
|
||||
advice: res.data.advice || "",
|
||||
level: res.data.level || "",
|
||||
level_label: res.data.level_label || "",
|
||||
portion: res.data.portion || "",
|
||||
food: res.data.food || q
|
||||
};
|
||||
} else {
|
||||
showUserToast(formatUserMessage(res == null ? void 0 : res.msg, "咨询失败"));
|
||||
}
|
||||
}
|
||||
async function askDietAiFood() {
|
||||
const q = String(dietAiAskText.value || "").trim();
|
||||
if (!q) {
|
||||
showUserToast("请输入想咨询的食物");
|
||||
return;
|
||||
}
|
||||
if (!diagnosisId.value)
|
||||
return;
|
||||
dietAiAskText.value = "";
|
||||
dietAiAsking.value = true;
|
||||
dietAiAskResult.value = { advice: "", level: "", level_label: "", portion: "", food: "" };
|
||||
try {
|
||||
await tongji_utils_aiStreamRequest.requestAiStream({
|
||||
baseUrl: proxy.$url,
|
||||
url: "/api/tcm/dailyDietAiAskStream",
|
||||
method: "POST",
|
||||
data: {
|
||||
diagnosis_id: diagnosisId.value,
|
||||
question: q
|
||||
},
|
||||
onEvent: (event, payload) => {
|
||||
if (event === "start" && !dietAiAskResult.value.advice) {
|
||||
dietAiAskResult.value = { ...dietAiAskResult.value, advice: payload.message || "正在想…" };
|
||||
} else if (event === "delta") {
|
||||
dietAiAskResult.value = {
|
||||
...dietAiAskResult.value,
|
||||
advice: payload.advice || dietAiAskResult.value.advice
|
||||
};
|
||||
} else if (event === "done") {
|
||||
dietAiAskResult.value = {
|
||||
advice: payload.advice || "",
|
||||
level: payload.level || "",
|
||||
level_label: payload.level_label || "",
|
||||
portion: payload.portion || "",
|
||||
food: payload.food || q
|
||||
};
|
||||
} else if (event === "error") {
|
||||
showUserToast(formatUserMessage(payload == null ? void 0 : payload.message, "咨询失败"));
|
||||
}
|
||||
},
|
||||
fallback: () => askDietAiFoodFallback(q)
|
||||
});
|
||||
} catch (e) {
|
||||
try {
|
||||
await askDietAiFoodFallback(q);
|
||||
} catch (e2) {
|
||||
showUserToast("网络异常,请稍后再试");
|
||||
}
|
||||
} finally {
|
||||
dietAiAsking.value = false;
|
||||
}
|
||||
}
|
||||
function onDietAiAskInput(e) {
|
||||
var _a;
|
||||
dietAiAskText.value = ((_a = e == null ? void 0 : e.detail) == null ? void 0 : _a.value) ?? "";
|
||||
}
|
||||
function saveDietPrefillToStorage() {
|
||||
const r = dietAiRecommend.value;
|
||||
if (!r.breakfast)
|
||||
return;
|
||||
try {
|
||||
common_vendor.index.setStorageSync(DIET_AI_PREFILL_KEY, {
|
||||
breakfast: r.breakfast,
|
||||
drinks: r.drinks || "",
|
||||
lunch: r.lunch,
|
||||
dinner: r.dinner,
|
||||
tips: r.tips || ""
|
||||
});
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
function goMoreDietForm(withPrefill = false) {
|
||||
if (withPrefill)
|
||||
saveDietPrefillToStorage();
|
||||
common_vendor.index.navigateTo({ url: "/tongji/pages/more?openDiet=1" });
|
||||
}
|
||||
async function applyDietAiToForm() {
|
||||
if (!dietAiRecommend.value.breakfast) {
|
||||
await fetchDietAiRecommend(false);
|
||||
}
|
||||
goMoreDietForm(true);
|
||||
}
|
||||
function openDietForm() {
|
||||
goMoreDietForm(false);
|
||||
}
|
||||
return {
|
||||
dietAiRecommend,
|
||||
dietAiLoading,
|
||||
dietAiStreaming,
|
||||
dietAiReplacing,
|
||||
dietAiStreamField,
|
||||
dietAiAskText,
|
||||
dietAiAsking,
|
||||
dietAiAskResult,
|
||||
hasDietAiMealContent,
|
||||
fetchDietAiRecommend,
|
||||
refreshDietAiRecommend,
|
||||
askDietAiFood,
|
||||
onDietAiAskInput,
|
||||
applyDietAiToForm,
|
||||
openDietForm
|
||||
};
|
||||
}
|
||||
function consumeDietAiPrefill() {
|
||||
try {
|
||||
const data = common_vendor.index.getStorageSync(DIET_AI_PREFILL_KEY);
|
||||
common_vendor.index.removeStorageSync(DIET_AI_PREFILL_KEY);
|
||||
if (data && typeof data === "object" && data.breakfast)
|
||||
return data;
|
||||
} catch (e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.consumeDietAiPrefill = consumeDietAiPrefill;
|
||||
exports.useDietAi = useDietAi;
|
||||
"use strict";const r=require("../../common/vendor.js"),d=require("../utils/aiStreamRequest.js"),_="tongji_diet_ai_prefill",A=()=>({breakfast:"",drinks:"",lunch:"",dinner:"",tips:"",avoid:[],analysis:[],exercise:null,disclaimer:"",rules_summary:"",source:"",date:""});function B(a,{diagnosisId:u,showUserToast:c,formatUserMessage:k}){const n=r.ref(A()),f=r.ref(!1),v=r.ref(!1),D=r.ref(!1),o=r.ref("");let s="";const m=r.ref(""),b=r.ref(!1),l=r.ref({advice:"",level:"",level_label:"",portion:"",food:""}),R=r.computed(()=>{const e=n.value;return!!(e.breakfast||e.drinks||e.lunch||e.dinner||e.tips)});function F(e){const i=String(e||"").match(/(?:^|\n)(早餐|喝的|午餐|晚餐|提示|少碰)[::]\s*([^\n]*)$/);return i&&{早餐:"breakfast",喝的:"drinks",午餐:"lunch",晚餐:"dinner",提示:"tips",少碰:"tips"}[i[1]]||"breakfast"}function E(){const e=d.parsePartialDietPlainText(s),i={...n.value};for(const t of["breakfast","drinks","lunch","dinner","tips"])e[t]!=null&&(i[t]=e[t]);Array.isArray(e.avoid)&&(i.avoid=e.avoid),n.value=i,o.value=F(s)}function g(e){if(!e)return;const i=n.value.analysis,t=n.value.exercise;n.value={...A(),...e,avoid:Array.isArray(e.avoid)?e.avoid:[],analysis:Array.isArray(e.analysis)&&e.analysis.length?e.analysis:Array.isArray(i)?i:[],exercise:e.exercise&&typeof e.exercise=="object"?e.exercise:t||null}}function q(e){if(!e||e.source!=="rule"||!s)return e;const i=d.parsePartialDietPlainText(s);return i.breakfast?{...A(),...e,breakfast:i.breakfast,drinks:i.drinks||e.drinks||"",lunch:i.lunch||e.lunch||"",dinner:i.dinner||e.dinner||"",tips:i.tips||e.tips||"",avoid:Array.isArray(i.avoid)&&i.avoid.length?i.avoid:e.avoid||[],source:"ai",disclaimer:"AI 建议供参考,仍请结合医嘱与血糖监测。"}:e}function j(e,i){e==="analysis"?Array.isArray(i==null?void 0:i.analysis)&&(n.value={...n.value,analysis:i.analysis}):e==="exercise"?i!=null&&i.exercise&&typeof i.exercise=="object"&&(n.value={...n.value,exercise:i.exercise}):e==="delta"?(v.value=!0,i.buffer!=null?s=i.buffer:s+=i.text||"",E()):e==="done"?(g(q(i)),s="",o.value=""):e==="error"&&c(k(i==null?void 0:i.message,"饮食建议加载失败"))}async function x(e){const i=await a.apiUrl({url:"/api/tcm/dailyDietAiRecommend",method:"GET",timeout:35e3,data:{diagnosis_id:u.value,refresh:e?1:0,...e?{_t:Date.now()}:{}}},!1);(i==null?void 0:i.code)===1&&i.data?g(i.data):i!=null&&i.msg&&c(i.msg)}async function S(e=!1){if(!(!u.value||f.value)){f.value=!0,v.value=!1,D.value=!!e,s="",o.value="",e&&g(A());try{await d.requestAiStream({baseUrl:a.$url,url:"/api/tcm/dailyDietAiRecommendStream",method:"GET",data:{diagnosis_id:u.value,refresh:e?1:0,...e?{_t:Date.now()}:{}},onEvent:j,fallback:()=>x(e)})}catch{try{await x(e)}catch{c("饮食建议加载失败")}}finally{f.value=!1,v.value=!1,D.value=!1,o.value=""}}}function T(){f.value||S(!0)}async function h(e){const i=await a.apiUrl({url:"/api/tcm/dailyDietAiAsk",method:"POST",timeout:35e3,data:{diagnosis_id:u.value,question:e}},!1);(i==null?void 0:i.code)===1&&i.data?l.value={advice:i.data.advice||"",level:i.data.level||"",level_label:i.data.level_label||"",portion:i.data.portion||"",food:i.data.food||e}:c(k(i==null?void 0:i.msg,"咨询失败"))}async function w(){const e=String(m.value||"").trim();if(!e){c("请输入想咨询的食物");return}if(u.value){m.value="",b.value=!0,l.value={advice:"",level:"",level_label:"",portion:"",food:""};try{await d.requestAiStream({baseUrl:a.$url,url:"/api/tcm/dailyDietAiAskStream",method:"POST",data:{diagnosis_id:u.value,question:e},onEvent:(i,t)=>{i==="start"&&!l.value.advice?l.value={...l.value,advice:t.message||"正在想…"}:i==="delta"?l.value={...l.value,advice:t.advice||l.value.advice}:i==="done"?l.value={advice:t.advice||"",level:t.level||"",level_label:t.level_label||"",portion:t.portion||"",food:t.food||e}:i==="error"&&c(k(t==null?void 0:t.message,"咨询失败"))},fallback:()=>h(e)})}catch{try{await h(e)}catch{c("网络异常,请稍后再试")}}finally{b.value=!1}}}function L(e){var i;m.value=((i=e==null?void 0:e.detail)==null?void 0:i.value)??""}function $(){const e=n.value;if(e.breakfast)try{r.index.setStorageSync(_,{breakfast:e.breakfast,drinks:e.drinks||"",lunch:e.lunch,dinner:e.dinner,tips:e.tips||""})}catch{}}function P(e=!1){e&&$(),r.index.navigateTo({url:"/tongji/pages/more?openDiet=1"})}async function G(){n.value.breakfast||await S(!1),P(!0)}function O(){P(!1)}return{dietAiRecommend:n,dietAiLoading:f,dietAiStreaming:v,dietAiReplacing:D,dietAiStreamField:o,dietAiAskText:m,dietAiAsking:b,dietAiAskResult:l,hasDietAiMealContent:R,fetchDietAiRecommend:S,refreshDietAiRecommend:T,askDietAiFood:w,onDietAiAskInput:L,applyDietAiToForm:G,openDietForm:O}}function C(){try{const a=r.index.getStorageSync(_);if(r.index.removeStorageSync(_),a&&typeof a=="object"&&a.breakfast)return a}catch{}return null}exports.consumeDietAiPrefill=C;exports.useDietAi=B;
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/tongji/composables/useDietAi.js.map
|
||||
|
||||
+1
-290
@@ -1,291 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const MIN_HOLD_MS = 280;
|
||||
function isBenignSttError(msg, retcode) {
|
||||
const m = String(msg || "").toLowerCase();
|
||||
if (/internal voice data failed/i.test(m))
|
||||
return true;
|
||||
if (/voice data failed/i.test(m))
|
||||
return true;
|
||||
if (/recordfailed|record failed|record manager/i.test(m))
|
||||
return true;
|
||||
if (/please stop after start/i.test(m))
|
||||
return true;
|
||||
if (/no recognition|not start|未开始|无识别/i.test(m))
|
||||
return true;
|
||||
const code = Number(retcode);
|
||||
if (code === -30002 || code === -30003 || code === -30012)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
function friendlySttError(msg) {
|
||||
const m = String(msg || "").trim();
|
||||
if (!m || isBenignSttError(m))
|
||||
return "";
|
||||
if (/not allowed|auth|permission|权限|麦克风/i.test(m))
|
||||
return "请允许使用麦克风";
|
||||
if (/network|网络|timeout/i.test(m))
|
||||
return "网络异常,请稍后再试";
|
||||
return "语音识别失败,请重试";
|
||||
}
|
||||
let sharedManager = null;
|
||||
let sharedManagerInited = false;
|
||||
let sharedRecording = false;
|
||||
let activeCtl = null;
|
||||
function getSharedRecordManager() {
|
||||
if (sharedManagerInited)
|
||||
return sharedManager;
|
||||
sharedManagerInited = true;
|
||||
try {
|
||||
const plugin = requirePlugin("WechatSI");
|
||||
sharedManager = plugin.getRecordRecognitionManager();
|
||||
} catch (e) {
|
||||
common_vendor.index.__f__("warn", "at tongji/composables/useSpeechToText.js:44", "WechatSI record recognition not available", e);
|
||||
sharedManager = null;
|
||||
return null;
|
||||
}
|
||||
if (!sharedManager)
|
||||
return null;
|
||||
sharedManager.onStart = () => {
|
||||
sharedRecording = true;
|
||||
if (activeCtl)
|
||||
activeCtl.handleStart();
|
||||
};
|
||||
sharedManager.onRecognize = (res) => {
|
||||
if (activeCtl)
|
||||
activeCtl.handleRecognize(res);
|
||||
};
|
||||
sharedManager.onStop = (res) => {
|
||||
sharedRecording = false;
|
||||
if (activeCtl)
|
||||
activeCtl.handleStop(res);
|
||||
};
|
||||
sharedManager.onError = (res) => {
|
||||
sharedRecording = false;
|
||||
if (activeCtl)
|
||||
activeCtl.handleError(res);
|
||||
};
|
||||
return sharedManager;
|
||||
}
|
||||
function useSpeechToText({ onResult, onSettle, onPartial, onError, showToast } = {}) {
|
||||
const sttListening = common_vendor.ref(false);
|
||||
const sttHolding = common_vendor.ref(false);
|
||||
const sttSupported = common_vendor.ref(false);
|
||||
let wxRecordManager = null;
|
||||
let holdStartTs = 0;
|
||||
let holdSessionId = 0;
|
||||
let startRequested = false;
|
||||
let recordAuthorized = null;
|
||||
let pendingStartSession = 0;
|
||||
function notify(msg) {
|
||||
if (!msg)
|
||||
return;
|
||||
if (typeof showToast === "function") {
|
||||
showToast(msg);
|
||||
return;
|
||||
}
|
||||
common_vendor.index.showToast({ title: msg, icon: "none", duration: 2e3 });
|
||||
}
|
||||
function emitResult(text) {
|
||||
const t = String(text || "").trim();
|
||||
const heldMs = Date.now() - holdStartTs;
|
||||
if (typeof onSettle === "function") {
|
||||
const handled = onSettle(t, { heldMs });
|
||||
if (handled === true)
|
||||
return;
|
||||
}
|
||||
if (!t) {
|
||||
if (heldMs < MIN_HOLD_MS)
|
||||
return;
|
||||
notify("没听清,请再试一次");
|
||||
return;
|
||||
}
|
||||
if (typeof onResult === "function") {
|
||||
onResult(t);
|
||||
}
|
||||
}
|
||||
function stopListening() {
|
||||
const ownsRecording = sharedRecording && activeCtl === controller;
|
||||
if (wxRecordManager && (sttListening.value || ownsRecording)) {
|
||||
try {
|
||||
wxRecordManager.stop();
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
startRequested = false;
|
||||
sttHolding.value = false;
|
||||
sttListening.value = false;
|
||||
}
|
||||
function ensureRecordAuth(onGranted) {
|
||||
if (recordAuthorized === true) {
|
||||
onGranted();
|
||||
return;
|
||||
}
|
||||
common_vendor.index.authorize({
|
||||
scope: "scope.record",
|
||||
success() {
|
||||
recordAuthorized = true;
|
||||
onGranted();
|
||||
},
|
||||
fail() {
|
||||
recordAuthorized = false;
|
||||
sttHolding.value = false;
|
||||
common_vendor.index.showModal({
|
||||
title: "需要麦克风权限",
|
||||
content: "请在设置中允许使用麦克风,以便长按说话",
|
||||
confirmText: "去设置",
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
common_vendor.index.openSetting({});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
function actuallyStartWechat(session) {
|
||||
if (!wxRecordManager || session !== holdSessionId || !sttHolding.value) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
startRequested = true;
|
||||
wxRecordManager.start({
|
||||
duration: 6e4,
|
||||
lang: "zh_CN"
|
||||
});
|
||||
} catch (e) {
|
||||
startRequested = false;
|
||||
sharedRecording = false;
|
||||
sttHolding.value = false;
|
||||
notify("无法开始录音");
|
||||
}
|
||||
}
|
||||
function startWechatRecord(session) {
|
||||
if (!wxRecordManager || session !== holdSessionId || !sttHolding.value) {
|
||||
return;
|
||||
}
|
||||
if (sharedRecording || startRequested) {
|
||||
pendingStartSession = session;
|
||||
try {
|
||||
wxRecordManager.stop();
|
||||
} catch (e) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
actuallyStartWechat(session);
|
||||
}
|
||||
function beginHoldSpeech() {
|
||||
if (!sttSupported.value) {
|
||||
notify("当前环境不支持语音输入");
|
||||
return;
|
||||
}
|
||||
if (sttHolding.value)
|
||||
return;
|
||||
const session = ++holdSessionId;
|
||||
holdStartTs = Date.now();
|
||||
sttHolding.value = true;
|
||||
activeCtl = controller;
|
||||
ensureRecordAuth(() => startWechatRecord(session));
|
||||
}
|
||||
function endHoldSpeech(force = false) {
|
||||
let recording = false;
|
||||
recording = sharedRecording && activeCtl === controller;
|
||||
if (!force && !sttHolding.value && !sttListening.value && !startRequested && !recording) {
|
||||
return;
|
||||
}
|
||||
sttHolding.value = false;
|
||||
pendingStartSession = 0;
|
||||
if (sttListening.value || recording) {
|
||||
stopListening();
|
||||
return;
|
||||
}
|
||||
if (startRequested) {
|
||||
startRequested = false;
|
||||
holdSessionId += 1;
|
||||
return;
|
||||
}
|
||||
holdSessionId += 1;
|
||||
}
|
||||
const controller = {
|
||||
handleStart() {
|
||||
if (!sttHolding.value) {
|
||||
startRequested = false;
|
||||
sttListening.value = false;
|
||||
return;
|
||||
}
|
||||
startRequested = false;
|
||||
sttListening.value = true;
|
||||
},
|
||||
handleRecognize(res) {
|
||||
if (typeof onPartial !== "function")
|
||||
return;
|
||||
const t = String((res == null ? void 0 : res.result) || "").trim();
|
||||
if (t)
|
||||
onPartial(t);
|
||||
},
|
||||
handleStop(res) {
|
||||
sttListening.value = false;
|
||||
startRequested = false;
|
||||
if (pendingStartSession && pendingStartSession === holdSessionId && sttHolding.value) {
|
||||
const s = pendingStartSession;
|
||||
pendingStartSession = 0;
|
||||
actuallyStartWechat(s);
|
||||
return;
|
||||
}
|
||||
pendingStartSession = 0;
|
||||
emitResult(res == null ? void 0 : res.result);
|
||||
},
|
||||
handleError(res) {
|
||||
sttListening.value = false;
|
||||
startRequested = false;
|
||||
const msg = res && res.msg || "";
|
||||
const retcode = res && (res.retcode ?? res.errCode ?? res.code);
|
||||
if (/please stop after start/i.test(msg)) {
|
||||
try {
|
||||
wxRecordManager.stop();
|
||||
} catch (e) {
|
||||
}
|
||||
pendingStartSession = sttHolding.value ? holdSessionId : 0;
|
||||
return;
|
||||
}
|
||||
pendingStartSession = 0;
|
||||
sttHolding.value = false;
|
||||
const heldMs = Date.now() - holdStartTs;
|
||||
if (isBenignSttError(msg, retcode) || heldMs < MIN_HOLD_MS) {
|
||||
if (typeof onError === "function")
|
||||
onError(msg || "");
|
||||
return;
|
||||
}
|
||||
if (typeof onError === "function") {
|
||||
const handled = onError(msg || "");
|
||||
if (handled === true)
|
||||
return;
|
||||
}
|
||||
const tip = friendlySttError(msg);
|
||||
if (tip)
|
||||
notify(tip);
|
||||
}
|
||||
};
|
||||
wxRecordManager = getSharedRecordManager();
|
||||
sttSupported.value = !!wxRecordManager;
|
||||
common_vendor.onUnmounted(() => {
|
||||
sttHolding.value = false;
|
||||
holdSessionId += 1;
|
||||
pendingStartSession = 0;
|
||||
stopListening();
|
||||
if (activeCtl === controller) {
|
||||
activeCtl = null;
|
||||
}
|
||||
});
|
||||
return {
|
||||
sttListening,
|
||||
sttHolding,
|
||||
sttSupported,
|
||||
beginHoldSpeech,
|
||||
endHoldSpeech,
|
||||
stopSpeechToText: endHoldSpeech
|
||||
};
|
||||
}
|
||||
exports.isBenignSttError = isBenignSttError;
|
||||
exports.useSpeechToText = useSpeechToText;
|
||||
"use strict";const s=require("../../common/vendor.js"),C=280;function w(n,u){const d=String(n||"").toLowerCase();if(/internal voice data failed/i.test(d)||/voice data failed/i.test(d)||/recordfailed|record failed|record manager/i.test(d)||/please stop after start/i.test(d)||/no recognition|not start|未开始|无识别/i.test(d))return!0;const h=Number(u);return h===-30002||h===-30003||h===-30012}function N(n){const u=String(n||"").trim();return!u||w(u)?"":/not allowed|auth|permission|权限|麦克风/i.test(u)?"请允许使用麦克风":/network|网络|timeout/i.test(u)?"网络异常,请稍后再试":"语音识别失败,请重试"}let c=null,D=!1,g=!1,i=null;function j(){if(D)return c;D=!0;try{c=requirePlugin("WechatSI").getRecordRecognitionManager()}catch(n){return s.index.__f__("warn","at tongji/composables/useSpeechToText.js:44","WechatSI record recognition not available",n),c=null,null}return c?(c.onStart=()=>{g=!0,i&&i.handleStart()},c.onRecognize=n=>{i&&i.handleRecognize(n)},c.onStop=n=>{g=!1,i&&i.handleStop(n)},c.onError=n=>{g=!1,i&&i.handleError(n)},c):null}function A({onResult:n,onSettle:u,onPartial:d,onError:h,showToast:M}={}){const l=s.ref(!1),r=s.ref(!1),y=s.ref(!1);let f=null,R=0,p=0,o=!1,x=null,a=0;function v(e){if(e){if(typeof M=="function"){M(e);return}s.index.showToast({title:e,icon:"none",duration:2e3})}}function H(e){const t=String(e||"").trim(),m=Date.now()-R;if(!(typeof u=="function"&&u(t,{heldMs:m})===!0)){if(!t){if(m<C)return;v("没听清,请再试一次");return}typeof n=="function"&&n(t)}}function T(){const e=g&&i===S;if(f&&(l.value||e))try{f.stop()}catch{}o=!1,r.value=!1,l.value=!1}function L(e){if(x===!0){e();return}s.index.authorize({scope:"scope.record",success(){x=!0,e()},fail(){x=!1,r.value=!1,s.index.showModal({title:"需要麦克风权限",content:"请在设置中允许使用麦克风,以便长按说话",confirmText:"去设置",success(t){t.confirm&&s.index.openSetting({})}})}})}function _(e){if(!(!f||e!==p||!r.value))try{o=!0,f.start({duration:6e4,lang:"zh_CN"})}catch{o=!1,g=!1,r.value=!1,v("无法开始录音")}}function W(e){if(!(!f||e!==p||!r.value)){if(g||o){a=e;try{f.stop()}catch{}return}_(e)}}function q(){if(!y.value){v("当前环境不支持语音输入");return}if(r.value)return;const e=++p;R=Date.now(),r.value=!0,i=S,L(()=>W(e))}function z(e=!1){let t=!1;if(t=g&&i===S,!(!e&&!r.value&&!l.value&&!o&&!t)){if(r.value=!1,a=0,l.value||t){T();return}if(o){o=!1,p+=1;return}p+=1}}const S={handleStart(){if(!r.value){o=!1,l.value=!1;return}o=!1,l.value=!0},handleRecognize(e){if(typeof d!="function")return;const t=String((e==null?void 0:e.result)||"").trim();t&&d(t)},handleStop(e){if(l.value=!1,o=!1,a&&a===p&&r.value){const t=a;a=0,_(t);return}a=0,H(e==null?void 0:e.result)},handleError(e){l.value=!1,o=!1;const t=e&&e.msg||"",m=e&&(e.retcode??e.errCode??e.code);if(/please stop after start/i.test(t)){try{f.stop()}catch{}a=r.value?p:0;return}a=0,r.value=!1;const I=Date.now()-R;if(w(t,m)||I<C){typeof h=="function"&&h(t||"");return}if(typeof h=="function"&&h(t||"")===!0)return;const b=N(t);b&&v(b)}};return f=j(),y.value=!!f,s.onUnmounted(()=>{r.value=!1,p+=1,a=0,T(),i===S&&(i=null)}),{sttListening:l,sttHolding:r,sttSupported:y,beginHoldSpeech:q,endHoldSpeech:z,stopSpeechToText:z}}exports.isBenignSttError=w;exports.useSpeechToText=A;
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/tongji/composables/useSpeechToText.js.map
|
||||
|
||||
+1
-63
@@ -1,64 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../../common/vendor.js");
|
||||
function useGameAuth(proxy) {
|
||||
let loginPromise = null;
|
||||
function hasToken() {
|
||||
return !!String(common_vendor.index.getStorageSync("token") || "").trim();
|
||||
}
|
||||
function clearToken() {
|
||||
common_vendor.index.removeStorageSync("token");
|
||||
}
|
||||
function wxLoginCode() {
|
||||
return new Promise((resolve, reject) => {
|
||||
common_vendor.index.login({
|
||||
provider: "weixin",
|
||||
success: (res) => (res == null ? void 0 : res.code) ? resolve(res.code) : reject(new Error("微信登录未返回 code")),
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
}
|
||||
async function loginWithCode(code) {
|
||||
var _a;
|
||||
const res = await proxy.apiUrl({
|
||||
url: "/api/login/mnpLogin",
|
||||
method: "POST",
|
||||
data: { code }
|
||||
}, false);
|
||||
if ((res == null ? void 0 : res.code) !== 1 || !((_a = res.data) == null ? void 0 : _a.token)) {
|
||||
clearToken();
|
||||
throw new Error((res == null ? void 0 : res.msg) || "登录失败");
|
||||
}
|
||||
common_vendor.index.setStorageSync("token", res.data.token);
|
||||
common_vendor.index.setStorageSync("userData", res.data);
|
||||
return true;
|
||||
}
|
||||
async function verifyOrLogin() {
|
||||
if (hasToken()) {
|
||||
try {
|
||||
const res = await proxy.apiUrl({ url: "/api/user/info", method: "POST" }, false);
|
||||
if ((res == null ? void 0 : res.code) === 1 && res.data) {
|
||||
common_vendor.index.setStorageSync("userData", res.data);
|
||||
return true;
|
||||
}
|
||||
if ((res == null ? void 0 : res.code) !== -1)
|
||||
return true;
|
||||
} catch (_) {
|
||||
return true;
|
||||
}
|
||||
clearToken();
|
||||
}
|
||||
const code = await wxLoginCode();
|
||||
return loginWithCode(code);
|
||||
}
|
||||
async function ensureLoggedIn() {
|
||||
if (loginPromise)
|
||||
return loginPromise;
|
||||
loginPromise = verifyOrLogin().then((ok) => !!ok).catch(() => false).finally(() => {
|
||||
loginPromise = null;
|
||||
});
|
||||
return loginPromise;
|
||||
}
|
||||
return { ensureLoggedIn };
|
||||
}
|
||||
exports.useGameAuth = useGameAuth;
|
||||
"use strict";const o=require("../../../common/vendor.js");function g(r){let i=null;function u(){return!!String(o.index.getStorageSync("token")||"").trim()}function a(){o.index.removeStorageSync("token")}function c(){return new Promise((e,n)=>{o.index.login({provider:"weixin",success:t=>t!=null&&t.code?e(t.code):n(new Error("微信登录未返回 code")),fail:n})})}async function d(e){var t;const n=await r.apiUrl({url:"/api/login/mnpLogin",method:"POST",data:{code:e}},!1);if((n==null?void 0:n.code)!==1||!((t=n.data)!=null&&t.token))throw a(),new Error((n==null?void 0:n.msg)||"登录失败");return o.index.setStorageSync("token",n.data.token),o.index.setStorageSync("userData",n.data),!0}async function l(){if(u()){try{const n=await r.apiUrl({url:"/api/user/info",method:"POST"},!1);if((n==null?void 0:n.code)===1&&n.data)return o.index.setStorageSync("userData",n.data),!0;if((n==null?void 0:n.code)!==-1)return!0}catch{return!0}a()}const e=await c();return d(e)}async function f(){return i||(i=l().then(e=>!!e).catch(()=>!1).finally(()=>{i=null}),i)}return{ensureLoggedIn:f}}exports.useGameAuth=g;
|
||||
//# sourceMappingURL=../../../../.sourcemap/mp-weixin/tongji/endless-game/composables/useGameAuth.js.map
|
||||
|
||||
Vendored
+1
-239
@@ -1,240 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../../common/vendor.js");
|
||||
const EMPTY_BOARD = {
|
||||
week_start: "",
|
||||
week_end: "",
|
||||
sex_label: "同行",
|
||||
group_size: 7,
|
||||
member_count: 0,
|
||||
players: [],
|
||||
me: { count: 0, rank: 1, best_score: 0, distance: 0, is_first: true },
|
||||
invite_code: ""
|
||||
};
|
||||
const PENDING_SYNC_KEY = "tongji_endless_pending_sync_v1";
|
||||
function createSessionKey() {
|
||||
const random = Math.random().toString(36).slice(2, 12);
|
||||
return `game_${Date.now().toString(36)}_${random}`;
|
||||
}
|
||||
function readPendingPayloads() {
|
||||
try {
|
||||
const stored = common_vendor.index.getStorageSync(PENDING_SYNC_KEY);
|
||||
if (!Array.isArray(stored))
|
||||
return [];
|
||||
return stored.filter((item) => item && /^[A-Za-z0-9_-]{16,64}$/.test(String(item.session_key || "")) && Number(item.learned_count) >= 0).slice(-8);
|
||||
} catch (_) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
function useGamePlatform(proxy, ensureLoggedIn) {
|
||||
const connected = common_vendor.ref(false);
|
||||
const loading = common_vendor.ref(false);
|
||||
const syncStatus = common_vendor.ref("idle");
|
||||
const leaderboard = common_vendor.ref({ ...EMPTY_BOARD });
|
||||
const confirmedSessionLearned = common_vendor.ref(0);
|
||||
let sessionKey = createSessionKey();
|
||||
let syncTimer = null;
|
||||
let syncing = false;
|
||||
let queuedPayloads = readPendingPayloads();
|
||||
let connectPromise = null;
|
||||
function persistPendingPayloads() {
|
||||
try {
|
||||
common_vendor.index.setStorageSync(PENDING_SYNC_KEY, queuedPayloads.slice(-8));
|
||||
} catch (_) {
|
||||
}
|
||||
}
|
||||
async function api(request) {
|
||||
if (!(proxy == null ? void 0 : proxy.apiUrl))
|
||||
throw new Error("平台接口未初始化");
|
||||
return proxy.apiUrl(request, false);
|
||||
}
|
||||
function applyLeaderboard(data, confirmedForSession = "") {
|
||||
if (!data || !Array.isArray(data.players))
|
||||
return;
|
||||
const inactiveSessionResponse = confirmedForSession && confirmedForSession !== sessionKey;
|
||||
if (!inactiveSessionResponse) {
|
||||
leaderboard.value = {
|
||||
...EMPTY_BOARD,
|
||||
...data,
|
||||
me: { ...EMPTY_BOARD.me, ...data.me || {} },
|
||||
players: data.players
|
||||
};
|
||||
}
|
||||
if (confirmedForSession === sessionKey && data.confirmed_session_learned != null) {
|
||||
confirmedSessionLearned.value = Number(data.confirmed_session_learned) || 0;
|
||||
}
|
||||
connected.value = true;
|
||||
syncStatus.value = "synced";
|
||||
}
|
||||
async function refreshLeaderboard() {
|
||||
const res = await api({
|
||||
url: "/api/tcm/gameWeeklyLeaderboard",
|
||||
method: "GET"
|
||||
});
|
||||
if ((res == null ? void 0 : res.code) !== 1 || !res.data) {
|
||||
throw new Error((res == null ? void 0 : res.msg) || "同行榜加载失败");
|
||||
}
|
||||
applyLeaderboard(res.data);
|
||||
return res.data;
|
||||
}
|
||||
async function acceptShare(inviteCode) {
|
||||
const code = String(inviteCode || "").trim().toUpperCase();
|
||||
if (!code)
|
||||
return;
|
||||
try {
|
||||
await api({
|
||||
url: "/api/tcm/gameAcceptShare",
|
||||
method: "POST",
|
||||
data: { invite_code: code }
|
||||
});
|
||||
} catch (_) {
|
||||
}
|
||||
}
|
||||
async function connect(inviteCode = "") {
|
||||
if (connectPromise)
|
||||
return connectPromise;
|
||||
connectPromise = (async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const loggedIn = await ensureLoggedIn();
|
||||
if (!loggedIn)
|
||||
throw new Error("登录失败");
|
||||
await acceptShare(inviteCode);
|
||||
await refreshLeaderboard();
|
||||
if (queuedPayloads.length)
|
||||
flushProgress();
|
||||
return true;
|
||||
} catch (_) {
|
||||
connected.value = false;
|
||||
syncStatus.value = "offline";
|
||||
return false;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
connectPromise = null;
|
||||
}
|
||||
})();
|
||||
return connectPromise;
|
||||
}
|
||||
function beginSession() {
|
||||
if (syncTimer)
|
||||
clearTimeout(syncTimer);
|
||||
sessionKey = createSessionKey();
|
||||
confirmedSessionLearned.value = 0;
|
||||
syncStatus.value = queuedPayloads.length ? "pending" : connected.value ? "synced" : "offline";
|
||||
return sessionKey;
|
||||
}
|
||||
function queueProgress(learnedCount, score, ended = false) {
|
||||
const nextPayload = {
|
||||
session_key: sessionKey,
|
||||
learned_count: Math.max(0, Number(learnedCount) || 0),
|
||||
score: Math.max(0, Number(score) || 0),
|
||||
ended: ended ? 1 : 0
|
||||
};
|
||||
const existingIndex = queuedPayloads.findIndex((item) => item.session_key === sessionKey);
|
||||
if (existingIndex >= 0) {
|
||||
const existing = queuedPayloads[existingIndex];
|
||||
queuedPayloads[existingIndex] = {
|
||||
...nextPayload,
|
||||
learned_count: Math.max(existing.learned_count, nextPayload.learned_count),
|
||||
score: Math.max(existing.score, nextPayload.score),
|
||||
ended: Math.max(existing.ended, nextPayload.ended)
|
||||
};
|
||||
} else {
|
||||
queuedPayloads.push(nextPayload);
|
||||
}
|
||||
persistPendingPayloads();
|
||||
syncStatus.value = "pending";
|
||||
if (syncTimer)
|
||||
clearTimeout(syncTimer);
|
||||
if (ended) {
|
||||
flushProgress();
|
||||
} else {
|
||||
syncTimer = setTimeout(flushProgress, 1e3);
|
||||
}
|
||||
}
|
||||
async function flushProgress() {
|
||||
if (syncTimer)
|
||||
clearTimeout(syncTimer);
|
||||
syncTimer = null;
|
||||
if (syncing || !queuedPayloads.length)
|
||||
return;
|
||||
const payload = queuedPayloads[0];
|
||||
syncing = true;
|
||||
syncStatus.value = "syncing";
|
||||
try {
|
||||
if (!connected.value) {
|
||||
const loggedIn = await ensureLoggedIn();
|
||||
if (!loggedIn)
|
||||
throw new Error("未登录");
|
||||
}
|
||||
const res = await api({
|
||||
url: "/api/tcm/gameSubmitProgress",
|
||||
method: "POST",
|
||||
data: payload
|
||||
});
|
||||
if ((res == null ? void 0 : res.code) !== 1 || !res.data) {
|
||||
throw new Error((res == null ? void 0 : res.msg) || "成绩保存失败");
|
||||
}
|
||||
applyLeaderboard(res.data, payload.session_key);
|
||||
queuedPayloads = queuedPayloads.filter((item) => item.session_key !== payload.session_key || Number(item.learned_count) > Number(payload.learned_count) || Number(item.score) > Number(payload.score) || Number(item.ended) > Number(payload.ended));
|
||||
persistPendingPayloads();
|
||||
} catch (_) {
|
||||
connected.value = false;
|
||||
syncStatus.value = "offline";
|
||||
persistPendingPayloads();
|
||||
} finally {
|
||||
syncing = false;
|
||||
if (queuedPayloads.length && connected.value) {
|
||||
setTimeout(flushProgress, 80);
|
||||
}
|
||||
}
|
||||
}
|
||||
async function syncAndRefresh(learnedCount, score) {
|
||||
queueProgress(learnedCount, score, false);
|
||||
await flushProgress();
|
||||
if (!connected.value) {
|
||||
await connect();
|
||||
if (queuedPayloads.length)
|
||||
await flushProgress();
|
||||
} else {
|
||||
try {
|
||||
await refreshLeaderboard();
|
||||
} catch (_) {
|
||||
}
|
||||
}
|
||||
}
|
||||
async function recordShare() {
|
||||
var _a;
|
||||
try {
|
||||
if (!connected.value && !await connect())
|
||||
return;
|
||||
const res = await api({ url: "/api/tcm/gameRecordShare", method: "POST" });
|
||||
if ((res == null ? void 0 : res.code) === 1 && ((_a = res.data) == null ? void 0 : _a.invite_code)) {
|
||||
leaderboard.value = { ...leaderboard.value, invite_code: res.data.invite_code };
|
||||
}
|
||||
} catch (_) {
|
||||
}
|
||||
}
|
||||
function dispose() {
|
||||
if (syncTimer)
|
||||
clearTimeout(syncTimer);
|
||||
syncTimer = null;
|
||||
persistPendingPayloads();
|
||||
}
|
||||
return {
|
||||
connected,
|
||||
loading,
|
||||
syncStatus,
|
||||
leaderboard,
|
||||
confirmedSessionLearned,
|
||||
connect,
|
||||
beginSession,
|
||||
queueProgress,
|
||||
flushProgress,
|
||||
syncAndRefresh,
|
||||
refreshLeaderboard,
|
||||
recordShare,
|
||||
dispose
|
||||
};
|
||||
}
|
||||
exports.useGamePlatform = useGamePlatform;
|
||||
"use strict";const l=require("../../../common/vendor.js"),N={week_start:"",week_end:"",sex_label:"同行",group_size:7,member_count:0,players:[],me:{count:0,rank:1,best_score:0,distance:0,is_first:!0},invite_code:""},x="tongji_endless_pending_sync_v1";function E(){const s=Math.random().toString(36).slice(2,12);return`game_${Date.now().toString(36)}_${s}`}function O(){try{const s=l.index.getStorageSync(x);return Array.isArray(s)?s.filter(u=>u&&/^[A-Za-z0-9_-]{16,64}$/.test(String(u.session_key||""))&&Number(u.learned_count)>=0).slice(-8):[]}catch{return[]}}function q(s,u){const i=l.ref(!1),v=l.ref(!1),o=l.ref("idle"),y=l.ref({...N}),w=l.ref(0);let d=E(),a=null,p=!1,t=O(),f=null;function g(){try{l.index.setStorageSync(x,t.slice(-8))}catch{}}async function h(e){if(!(s!=null&&s.apiUrl))throw new Error("平台接口未初始化");return s.apiUrl(e,!1)}function T(e,n=""){if(!e||!Array.isArray(e.players))return;n&&n!==d||(y.value={...N,...e,me:{...N.me,...e.me||{}},players:e.players}),n===d&&e.confirmed_session_learned!=null&&(w.value=Number(e.confirmed_session_learned)||0),i.value=!0,o.value="synced"}async function S(){const e=await h({url:"/api/tcm/gameWeeklyLeaderboard",method:"GET"});if((e==null?void 0:e.code)!==1||!e.data)throw new Error((e==null?void 0:e.msg)||"同行榜加载失败");return T(e.data),e.data}async function A(e){const n=String(e||"").trim().toUpperCase();if(n)try{await h({url:"/api/tcm/gameAcceptShare",method:"POST",data:{invite_code:n}})}catch{}}async function b(e=""){return f||(f=(async()=>{v.value=!0;try{if(!await u())throw new Error("登录失败");return await A(e),await S(),t.length&&c(),!0}catch{return i.value=!1,o.value="offline",!1}finally{v.value=!1,f=null}})(),f)}function M(){return a&&clearTimeout(a),d=E(),w.value=0,o.value=t.length?"pending":i.value?"synced":"offline",d}function k(e,n,r=!1){const m={session_key:d,learned_count:Math.max(0,Number(e)||0),score:Math.max(0,Number(n)||0),ended:r?1:0},P=t.findIndex(_=>_.session_key===d);if(P>=0){const _=t[P];t[P]={...m,learned_count:Math.max(_.learned_count,m.learned_count),score:Math.max(_.score,m.score),ended:Math.max(_.ended,m.ended)}}else t.push(m);g(),o.value="pending",a&&clearTimeout(a),r?c():a=setTimeout(c,1e3)}async function c(){if(a&&clearTimeout(a),a=null,p||!t.length)return;const e=t[0];p=!0,o.value="syncing";try{if(!i.value&&!await u())throw new Error("未登录");const n=await h({url:"/api/tcm/gameSubmitProgress",method:"POST",data:e});if((n==null?void 0:n.code)!==1||!n.data)throw new Error((n==null?void 0:n.msg)||"成绩保存失败");T(n.data,e.session_key),t=t.filter(r=>r.session_key!==e.session_key||Number(r.learned_count)>Number(e.learned_count)||Number(r.score)>Number(e.score)||Number(r.ended)>Number(e.ended)),g()}catch{i.value=!1,o.value="offline",g()}finally{p=!1,t.length&&i.value&&setTimeout(c,80)}}async function I(e,n){if(k(e,n,!1),await c(),!i.value)await b(),t.length&&await c();else try{await S()}catch{}}async function R(){var e;try{if(!i.value&&!await b())return;const n=await h({url:"/api/tcm/gameRecordShare",method:"POST"});(n==null?void 0:n.code)===1&&((e=n.data)!=null&&e.invite_code)&&(y.value={...y.value,invite_code:n.data.invite_code})}catch{}}function G(){a&&clearTimeout(a),a=null,g()}return{connected:i,loading:v,syncStatus:o,leaderboard:y,confirmedSessionLearned:w,connect:b,beginSession:M,queueProgress:k,flushProgress:c,syncAndRefresh:I,refreshLeaderboard:S,recordShare:R,dispose:G}}exports.useGamePlatform=q;
|
||||
//# sourceMappingURL=../../../../.sourcemap/mp-weixin/tongji/endless-game/composables/useGamePlatform.js.map
|
||||
|
||||
+1
-365
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-2061
File diff suppressed because one or more lines are too long
+1
-2264
File diff suppressed because one or more lines are too long
+1
-4687
File diff suppressed because one or more lines are too long
+1
-3548
File diff suppressed because one or more lines are too long
+1
-5577
File diff suppressed because one or more lines are too long
+1
-2115
File diff suppressed because one or more lines are too long
+1
-1255
File diff suppressed because one or more lines are too long
+6
-140
@@ -1,141 +1,7 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
function joinApiUrl(base, path) {
|
||||
const b = String(base || "").replace(/\/+$/, "");
|
||||
const p = String(path || "").replace(/^\/+/, "");
|
||||
return p ? `${b}/${p}` : b;
|
||||
}
|
||||
function appendQuery(url, data) {
|
||||
if (!data || typeof data !== "object")
|
||||
return url;
|
||||
const keys = Object.keys(data);
|
||||
if (!keys.length)
|
||||
return url;
|
||||
const qs = keys.map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(data[k] ?? "")}`).join("&");
|
||||
return url + (url.includes("?") ? "&" : "?") + qs;
|
||||
}
|
||||
function decodeChunkData(data) {
|
||||
if (typeof data === "string")
|
||||
return data;
|
||||
if (!data)
|
||||
return "";
|
||||
if (typeof TextDecoder !== "undefined" && data instanceof ArrayBuffer) {
|
||||
return new TextDecoder("utf-8").decode(new Uint8Array(data));
|
||||
}
|
||||
if (data instanceof ArrayBuffer) {
|
||||
const bytes = new Uint8Array(data);
|
||||
let str = "";
|
||||
for (let i = 0; i < bytes.length; i++)
|
||||
str += String.fromCharCode(bytes[i]);
|
||||
try {
|
||||
return decodeURIComponent(escape(str));
|
||||
} catch (e) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
function consumeSseBuffer(buffer, onEvent) {
|
||||
let rest = buffer;
|
||||
let idx = rest.indexOf("\n\n");
|
||||
while (idx !== -1) {
|
||||
const block = rest.slice(0, idx);
|
||||
rest = rest.slice(idx + 2);
|
||||
let event = "message";
|
||||
let dataLine = "";
|
||||
block.split("\n").forEach((line) => {
|
||||
if (line.startsWith("event:"))
|
||||
event = line.slice(6).trim();
|
||||
else if (line.startsWith("data:"))
|
||||
dataLine += line.slice(5).trim();
|
||||
});
|
||||
if (dataLine) {
|
||||
try {
|
||||
onEvent(event, JSON.parse(dataLine));
|
||||
} catch (e) {
|
||||
onEvent(event, dataLine);
|
||||
}
|
||||
}
|
||||
idx = rest.indexOf("\n\n");
|
||||
}
|
||||
return rest;
|
||||
}
|
||||
function parsePartialDietPlainText(text) {
|
||||
const out = {};
|
||||
if (!text)
|
||||
return out;
|
||||
const lineRe = /^(早餐|喝的|午餐|晚餐|提示|少碰)[::]\s*(.*)$/gm;
|
||||
let match;
|
||||
while ((match = lineRe.exec(text)) !== null) {
|
||||
const key = { "早餐": "breakfast", "喝的": "drinks", "午餐": "lunch", "晚餐": "dinner", "提示": "tips", "少碰": "avoid" }[match[1]];
|
||||
const val = (match[2] || "").trim();
|
||||
if (key === "avoid") {
|
||||
out.avoid = val.split(/[、,,;;\s]+/).map((s) => s.trim()).filter(Boolean);
|
||||
} else {
|
||||
out[key] = val;
|
||||
}
|
||||
}
|
||||
const tail = text.match(/(?:^|\n)(早餐|喝的|午餐|晚餐|提示|少碰)[::]\s*([^\n]*)$/);
|
||||
if (tail) {
|
||||
const key = { "早餐": "breakfast", "喝的": "drinks", "午餐": "lunch", "晚餐": "dinner", "提示": "tips", "少碰": "avoid" }[tail[1]];
|
||||
const val = (tail[2] || "").trim();
|
||||
if (key === "avoid") {
|
||||
if (val)
|
||||
out.avoid = val.split(/[、,,;;\s]+/).map((s) => s.trim()).filter(Boolean);
|
||||
} else {
|
||||
out[key] = val;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
function requestAiStream(opts) {
|
||||
const {
|
||||
baseUrl,
|
||||
url,
|
||||
method = "GET",
|
||||
data = {},
|
||||
onEvent,
|
||||
fallback
|
||||
} = opts;
|
||||
return new Promise((resolve, reject) => {
|
||||
const token = common_vendor.index.getStorageSync("token") || "";
|
||||
let sseBuffer = "";
|
||||
let requestUrl = joinApiUrl(baseUrl, url);
|
||||
if (method === "GET") {
|
||||
requestUrl = appendQuery(requestUrl, data);
|
||||
}
|
||||
const task = common_vendor.wx$1.request({
|
||||
url: requestUrl,
|
||||
method,
|
||||
data: method === "POST" ? data : {},
|
||||
enableChunked: true,
|
||||
timeout: 6e4,
|
||||
header: {
|
||||
token,
|
||||
"content-type": "application/x-www-form-urlencoded",
|
||||
"Cache-Control": "no-cache"
|
||||
},
|
||||
success: (res) => {
|
||||
if (res && res.data) {
|
||||
sseBuffer += decodeChunkData(res.data);
|
||||
sseBuffer = consumeSseBuffer(sseBuffer, onEvent);
|
||||
}
|
||||
resolve(res);
|
||||
},
|
||||
fail: (err) => reject(err)
|
||||
});
|
||||
if (task && typeof task.onChunkReceived === "function") {
|
||||
task.onChunkReceived((res) => {
|
||||
sseBuffer += decodeChunkData(res.data);
|
||||
sseBuffer = consumeSseBuffer(sseBuffer, onEvent);
|
||||
});
|
||||
} else if (typeof fallback === "function") {
|
||||
fallback().then(resolve).catch(reject);
|
||||
} else {
|
||||
reject(new Error("当前环境不支持流式请求"));
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.parsePartialDietPlainText = parsePartialDietPlainText;
|
||||
exports.requestAiStream = requestAiStream;
|
||||
"use strict";const p=require("../../common/vendor.js");function k(e,n){const r=String(e||"").replace(/\/+$/,""),t=String(n||"").replace(/^\/+/,"");return t?`${r}/${t}`:r}function v(e,n){if(!n||typeof n!="object")return e;const r=Object.keys(n);if(!r.length)return e;const t=r.map(c=>`${encodeURIComponent(c)}=${encodeURIComponent(n[c]??"")}`).join("&");return e+(e.includes("?")?"&":"?")+t}function m(e){if(typeof e=="string")return e;if(!e)return"";if(typeof TextDecoder<"u"&&e instanceof ArrayBuffer)return new TextDecoder("utf-8").decode(new Uint8Array(e));if(e instanceof ArrayBuffer){const n=new Uint8Array(e);let r="";for(let t=0;t<n.length;t++)r+=String.fromCharCode(n[t]);try{return decodeURIComponent(escape(r))}catch{return r}}return""}function h(e,n){let r=e,t=r.indexOf(`
|
||||
|
||||
`);for(;t!==-1;){const c=r.slice(0,t);r=r.slice(t+2);let o="message",i="";if(c.split(`
|
||||
`).forEach(s=>{s.startsWith("event:")?o=s.slice(6).trim():s.startsWith("data:")&&(i+=s.slice(5).trim())}),i)try{n(o,JSON.parse(i))}catch{n(o,i)}t=r.indexOf(`
|
||||
|
||||
`)}return r}function w(e){const n={};if(!e)return n;const r=/^(早餐|喝的|午餐|晚餐|提示|少碰)[::]\s*(.*)$/gm;let t;for(;(t=r.exec(e))!==null;){const o={早餐:"breakfast",喝的:"drinks",午餐:"lunch",晚餐:"dinner",提示:"tips",少碰:"avoid"}[t[1]],i=(t[2]||"").trim();o==="avoid"?n.avoid=i.split(/[、,,;;\s]+/).map(s=>s.trim()).filter(Boolean):n[o]=i}const c=e.match(/(?:^|\n)(早餐|喝的|午餐|晚餐|提示|少碰)[::]\s*([^\n]*)$/);if(c){const o={早餐:"breakfast",喝的:"drinks",午餐:"lunch",晚餐:"dinner",提示:"tips",少碰:"avoid"}[c[1]],i=(c[2]||"").trim();o==="avoid"?i&&(n.avoid=i.split(/[、,,;;\s]+/).map(s=>s.trim()).filter(Boolean)):n[o]=i}return n}function C(e){const{baseUrl:n,url:r,method:t="GET",data:c={},onEvent:o,fallback:i}=e;return new Promise((s,l)=>{const y=p.index.getStorageSync("token")||"";let f="",u=k(n,r);t==="GET"&&(u=v(u,c));const d=p.wx$1.request({url:u,method:t,data:t==="POST"?c:{},enableChunked:!0,timeout:6e4,header:{token:y,"content-type":"application/x-www-form-urlencoded","Cache-Control":"no-cache"},success:a=>{a&&a.data&&(f+=m(a.data),f=h(f,o)),s(a)},fail:a=>l(a)});d&&typeof d.onChunkReceived=="function"?d.onChunkReceived(a=>{f+=m(a.data),f=h(f,o)}):typeof i=="function"?i().then(s).catch(l):l(new Error("当前环境不支持流式请求"))})}exports.parsePartialDietPlainText=w;exports.requestAiStream=C;
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/tongji/utils/aiStreamRequest.js.map
|
||||
|
||||
@@ -1,48 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
function utf8ToBytes(str) {
|
||||
const encoded = encodeURIComponent(str);
|
||||
const bytes = [];
|
||||
for (let i = 0; i < encoded.length; i++) {
|
||||
if (encoded.charCodeAt(i) === 37) {
|
||||
bytes.push(parseInt(encoded.substring(i + 1, i + 3), 16));
|
||||
i += 2;
|
||||
} else {
|
||||
bytes.push(encoded.charCodeAt(i));
|
||||
}
|
||||
}
|
||||
return new Uint8Array(bytes);
|
||||
}
|
||||
function bytesToBase64(bytes) {
|
||||
if (typeof common_vendor.index !== "undefined" && typeof common_vendor.index.arrayBufferToBase64 === "function") {
|
||||
return common_vendor.index.arrayBufferToBase64(bytes.buffer);
|
||||
}
|
||||
if (typeof btoa !== "undefined") {
|
||||
let binary = "";
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
return btoa(binary);
|
||||
}
|
||||
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
let result = "";
|
||||
for (let i = 0; i < bytes.length; i += 3) {
|
||||
const a = bytes[i];
|
||||
const b = i + 1 < bytes.length ? bytes[i + 1] : 0;
|
||||
const c = i + 2 < bytes.length ? bytes[i + 2] : 0;
|
||||
result += chars[a >> 2];
|
||||
result += chars[(a & 3) << 4 | b >> 4];
|
||||
result += i + 1 < bytes.length ? chars[(b & 15) << 2 | c >> 6] : "=";
|
||||
result += i + 2 < bytes.length ? chars[c & 63] : "=";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function svgToDataUrl(svg) {
|
||||
const normalized = String(svg || "").trim();
|
||||
if (!normalized)
|
||||
return "";
|
||||
const base64 = bytesToBase64(utf8ToBytes(normalized));
|
||||
return `data:image/svg+xml;base64,${base64}`;
|
||||
}
|
||||
exports.svgToDataUrl = svgToDataUrl;
|
||||
"use strict";const a=require("../../common/vendor.js");function u(e){const t=encodeURIComponent(e),r=[];for(let n=0;n<t.length;n++)t.charCodeAt(n)===37?(r.push(parseInt(t.substring(n+1,n+3),16)),n+=2):r.push(t.charCodeAt(n));return new Uint8Array(r)}function c(e){if(typeof a.index<"u"&&typeof a.index.arrayBufferToBase64=="function")return a.index.arrayBufferToBase64(e.buffer);if(typeof btoa<"u"){let n="";for(let o=0;o<e.length;o++)n+=String.fromCharCode(e[o]);return btoa(n)}const t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";let r="";for(let n=0;n<e.length;n+=3){const o=e[n],i=n+1<e.length?e[n+1]:0,f=n+2<e.length?e[n+2]:0;r+=t[o>>2],r+=t[(o&3)<<4|i>>4],r+=n+1<e.length?t[(i&15)<<2|f>>6]:"=",r+=n+2<e.length?t[f&63]:"="}return r}function s(e){const t=String(e||"").trim();return t?`data:image/svg+xml;base64,${c(u(t))}`:""}exports.svgToDataUrl=s;
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/tongji/utils/svgDataUrl.js.map
|
||||
|
||||
@@ -1,60 +1,2 @@
|
||||
"use strict";
|
||||
const TREE_MAX_LEVEL = 9;
|
||||
const TREE_XP_PER_LEVEL = 50;
|
||||
const TREE_LEVELS = [
|
||||
{ level: 0, name: "种子眠", emoji: "🫘", mood: "困困", desc: "稳糖种子在土里打盹" },
|
||||
{ level: 1, name: "破土芽", emoji: "🌱", mood: "探头", desc: "探出第一抹新绿" },
|
||||
{ level: 2, name: "展两叶", emoji: "🌿", mood: "好奇", desc: "两片嫩叶迎风展" },
|
||||
{ level: 3, name: "小树苗", emoji: "🪴", mood: "精神", desc: "身子骨硬朗起来" },
|
||||
{ level: 4, name: "青枝繁", emoji: "🌳", mood: "茁壮", desc: "枝叶渐密,元气足" },
|
||||
{ level: 5, name: "拔节高", emoji: "🌲", mood: "挺拔", desc: "一节一节往上蹿" },
|
||||
{ level: 6, name: "稳糖冠", emoji: "💚", mood: "沉稳", desc: "树冠成形,习惯成自然" },
|
||||
{ level: 7, name: "初绽香", emoji: "🌸", mood: "开心", desc: "枝头冒出第一朵花" },
|
||||
{ level: 8, name: "漫开花", emoji: "🌺", mood: "灿烂", desc: "花开满枝,越记越稳" },
|
||||
{ level: 9, name: "圆满树", emoji: "🏆", mood: "荣耀", desc: "满级大树,习惯大师" }
|
||||
];
|
||||
const WHISPERS_BY_LEVEL = {
|
||||
0: ["种子在睡觉,记一笔就醒啦。", "今天浇第一滴水,芽就要冒出来。"],
|
||||
1: ["破土啦!再坚持几天就长高。", "小芽最喜欢规律的记录了。"],
|
||||
2: ["两片叶子为你鼓掌。", "空腹餐后都记全,我会长得更快。"],
|
||||
3: ["我已经是一棵小树啦。", "家人点赞的时候,我也会发光。"],
|
||||
4: ["枝叶越来越密,您真棒。", "连续记录,我会开出更多叶子。"],
|
||||
5: ["拔节中!习惯比完美更重要。", "再浇一点水,我就更高啦。"],
|
||||
6: ["习惯成自然,树冠成形啦。", "您今天的坚持,小树都记得。"],
|
||||
7: ["开花啦!闻到春天的味道了吗?", "稳糖花只开给坚持的人。"],
|
||||
8: ["满树花香,您已是控糖达人。", "明天继续来,花儿会更艳。"],
|
||||
9: ["满级大树陪您一路稳糖。", "圆满不是终点,习惯才是。"]
|
||||
};
|
||||
function calcTreeFromPoints(points) {
|
||||
const pts = Math.max(0, Number(points) || 0);
|
||||
const level = Math.min(TREE_MAX_LEVEL, Math.floor(pts / TREE_XP_PER_LEVEL));
|
||||
const xpInLevel = level >= TREE_MAX_LEVEL ? TREE_XP_PER_LEVEL : pts % TREE_XP_PER_LEVEL;
|
||||
const progress = level >= TREE_MAX_LEVEL ? 100 : Math.round(xpInLevel / TREE_XP_PER_LEVEL * 100);
|
||||
const meta = TREE_LEVELS[level] || TREE_LEVELS[0];
|
||||
const nextMeta = level < TREE_MAX_LEVEL ? TREE_LEVELS[level + 1] : null;
|
||||
const pointsToNext = level >= TREE_MAX_LEVEL ? 0 : TREE_XP_PER_LEVEL - xpInLevel;
|
||||
return {
|
||||
level,
|
||||
progress,
|
||||
name: meta.name,
|
||||
emoji: meta.emoji,
|
||||
mood: meta.mood,
|
||||
desc: meta.desc,
|
||||
xpInLevel,
|
||||
xpNeed: TREE_XP_PER_LEVEL,
|
||||
pointsToNext,
|
||||
nextName: (nextMeta == null ? void 0 : nextMeta.name) || "",
|
||||
isMax: level >= TREE_MAX_LEVEL
|
||||
};
|
||||
}
|
||||
function pickTreeWhisper(level) {
|
||||
const lv = Math.min(TREE_MAX_LEVEL, Math.max(0, Number(level) || 0));
|
||||
const list = WHISPERS_BY_LEVEL[lv] || WHISPERS_BY_LEVEL[0];
|
||||
return list[Math.floor(Math.random() * list.length)];
|
||||
}
|
||||
exports.TREE_LEVELS = TREE_LEVELS;
|
||||
exports.TREE_MAX_LEVEL = TREE_MAX_LEVEL;
|
||||
exports.TREE_XP_PER_LEVEL = TREE_XP_PER_LEVEL;
|
||||
exports.calcTreeFromPoints = calcTreeFromPoints;
|
||||
exports.pickTreeWhisper = pickTreeWhisper;
|
||||
"use strict";const _=[{level:0,name:"种子眠",emoji:"🫘",mood:"困困",desc:"稳糖种子在土里打盹"},{level:1,name:"破土芽",emoji:"🌱",mood:"探头",desc:"探出第一抹新绿"},{level:2,name:"展两叶",emoji:"🌿",mood:"好奇",desc:"两片嫩叶迎风展"},{level:3,name:"小树苗",emoji:"🪴",mood:"精神",desc:"身子骨硬朗起来"},{level:4,name:"青枝繁",emoji:"🌳",mood:"茁壮",desc:"枝叶渐密,元气足"},{level:5,name:"拔节高",emoji:"🌲",mood:"挺拔",desc:"一节一节往上蹿"},{level:6,name:"稳糖冠",emoji:"💚",mood:"沉稳",desc:"树冠成形,习惯成自然"},{level:7,name:"初绽香",emoji:"🌸",mood:"开心",desc:"枝头冒出第一朵花"},{level:8,name:"漫开花",emoji:"🌺",mood:"灿烂",desc:"花开满枝,越记越稳"},{level:9,name:"圆满树",emoji:"🏆",mood:"荣耀",desc:"满级大树,习惯大师"}],s={0:["种子在睡觉,记一笔就醒啦。","今天浇第一滴水,芽就要冒出来。"],1:["破土啦!再坚持几天就长高。","小芽最喜欢规律的记录了。"],2:["两片叶子为你鼓掌。","空腹餐后都记全,我会长得更快。"],3:["我已经是一棵小树啦。","家人点赞的时候,我也会发光。"],4:["枝叶越来越密,您真棒。","连续记录,我会开出更多叶子。"],5:["拔节中!习惯比完美更重要。","再浇一点水,我就更高啦。"],6:["习惯成自然,树冠成形啦。","您今天的坚持,小树都记得。"],7:["开花啦!闻到春天的味道了吗?","稳糖花只开给坚持的人。"],8:["满树花香,您已是控糖达人。","明天继续来,花儿会更艳。"],9:["满级大树陪您一路稳糖。","圆满不是终点,习惯才是。"]};function l(m){const e=Math.max(0,Number(m)||0),E=Math.min(9,Math.floor(e/50)),L=E>=9?50:e%50,c=E>=9?100:Math.round(L/50*100),o=_[E]||_[0],n=E<9?_[E+1]:null,t=E>=9?0:50-L;return{level:E,progress:c,name:o.name,emoji:o.emoji,mood:o.mood,desc:o.desc,xpInLevel:L,xpNeed:50,pointsToNext:t,nextName:(n==null?void 0:n.name)||"",isMax:E>=9}}function R(m){const e=Math.min(9,Math.max(0,Number(m)||0)),E=s[e]||s[0];return E[Math.floor(Math.random()*E.length)]}exports.TREE_LEVELS=_;exports.TREE_MAX_LEVEL=9;exports.TREE_XP_PER_LEVEL=50;exports.calcTreeFromPoints=l;exports.pickTreeWhisper=R;
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/tongji/utils/treeLevels.js.map
|
||||
|
||||
@@ -1,68 +1,2 @@
|
||||
"use strict";
|
||||
const tongji_utils_treeLevels = require("./treeLevels.js");
|
||||
const TREE_SPECIES_LIST = [
|
||||
{
|
||||
id: "classic",
|
||||
name: "稳糖灵树",
|
||||
tagline: "经典路线,从种子到圆满",
|
||||
stages: tongji_utils_treeLevels.TREE_LEVELS.map((l) => l.emoji)
|
||||
},
|
||||
{
|
||||
id: "bonsai",
|
||||
name: "雅韵盆景",
|
||||
tagline: "小巧精致,书桌旁的温柔陪伴",
|
||||
stages: ["🫘", "🌱", "🪴", "🎋", "🪴", "🌳", "🎍", "🌸", "🏵️", "🏆"]
|
||||
},
|
||||
{
|
||||
id: "pine",
|
||||
name: "苍劲青松",
|
||||
tagline: "挺拔向上,越记越稳",
|
||||
stages: ["🫘", "🌱", "🌿", "🌲", "🌲", "🌲", "⛰️", "🌲", "🏔️", "🏆"]
|
||||
},
|
||||
{
|
||||
id: "sakura",
|
||||
name: "樱花小树",
|
||||
tagline: "坚持打卡,枝头渐开",
|
||||
stages: ["🫘", "🌱", "🌿", "🌳", "🌸", "🌸", "🌸", "🌸", "🌺", "🏆"]
|
||||
},
|
||||
{
|
||||
id: "ginkgo",
|
||||
name: "金秋银杏",
|
||||
tagline: "叶色渐变,见证每一天",
|
||||
stages: ["🫘", "🌱", "🍃", "🌳", "🍂", "🍂", "🌳", "🍁", "🌟", "🏆"]
|
||||
}
|
||||
];
|
||||
const DAILY_MAX_TASK_POINTS = 40;
|
||||
function getTreeSpecies(id) {
|
||||
return TREE_SPECIES_LIST.find((s) => s.id === id) || TREE_SPECIES_LIST[0];
|
||||
}
|
||||
function speciesEmojiAtLevel(speciesId, level) {
|
||||
const sp = getTreeSpecies(speciesId);
|
||||
const lv = Math.min(tongji_utils_treeLevels.TREE_MAX_LEVEL, Math.max(0, Number(level) || 0));
|
||||
return sp.stages[lv] || sp.stages[0] || "🌱";
|
||||
}
|
||||
function speciesGrowthRoadmap(speciesId) {
|
||||
const sp = getTreeSpecies(speciesId);
|
||||
return tongji_utils_treeLevels.TREE_LEVELS.map((meta, i) => {
|
||||
const xpTotal = i * tongji_utils_treeLevels.TREE_XP_PER_LEVEL;
|
||||
const daysHint = i === 0 ? 0 : Math.max(1, Math.ceil(xpTotal / DAILY_MAX_TASK_POINTS));
|
||||
return {
|
||||
level: i,
|
||||
name: meta.name,
|
||||
emoji: sp.stages[i] || meta.emoji,
|
||||
desc: meta.desc,
|
||||
xpTotal,
|
||||
daysHint
|
||||
};
|
||||
});
|
||||
}
|
||||
function estimateDaysToMaxLevel() {
|
||||
const totalXp = tongji_utils_treeLevels.TREE_MAX_LEVEL * tongji_utils_treeLevels.TREE_XP_PER_LEVEL;
|
||||
return Math.max(1, Math.ceil(totalXp / DAILY_MAX_TASK_POINTS));
|
||||
}
|
||||
exports.TREE_SPECIES_LIST = TREE_SPECIES_LIST;
|
||||
exports.estimateDaysToMaxLevel = estimateDaysToMaxLevel;
|
||||
exports.getTreeSpecies = getTreeSpecies;
|
||||
exports.speciesEmojiAtLevel = speciesEmojiAtLevel;
|
||||
exports.speciesGrowthRoadmap = speciesGrowthRoadmap;
|
||||
"use strict";const a=require("./treeLevels.js"),i=[{id:"classic",name:"稳糖灵树",tagline:"经典路线,从种子到圆满",stages:a.TREE_LEVELS.map(e=>e.emoji)},{id:"bonsai",name:"雅韵盆景",tagline:"小巧精致,书桌旁的温柔陪伴",stages:["🫘","🌱","🪴","🎋","🪴","🌳","🎍","🌸","🏵️","🏆"]},{id:"pine",name:"苍劲青松",tagline:"挺拔向上,越记越稳",stages:["🫘","🌱","🌿","🌲","🌲","🌲","⛰️","🌲","🏔️","🏆"]},{id:"sakura",name:"樱花小树",tagline:"坚持打卡,枝头渐开",stages:["🫘","🌱","🌿","🌳","🌸","🌸","🌸","🌸","🌺","🏆"]},{id:"ginkgo",name:"金秋银杏",tagline:"叶色渐变,见证每一天",stages:["🫘","🌱","🍃","🌳","🍂","🍂","🌳","🍁","🌟","🏆"]}],c=40;function E(e){return i.find(n=>n.id===e)||i[0]}function _(e,n){const t=E(e),s=Math.min(a.TREE_MAX_LEVEL,Math.max(0,Number(n)||0));return t.stages[s]||t.stages[0]||"🌱"}function r(e){const n=E(e);return a.TREE_LEVELS.map((t,s)=>{const o=s*a.TREE_XP_PER_LEVEL,m=s===0?0:Math.max(1,Math.ceil(o/c));return{level:s,name:t.name,emoji:n.stages[s]||t.emoji,desc:t.desc,xpTotal:o,daysHint:m}})}function L(){const e=a.TREE_MAX_LEVEL*a.TREE_XP_PER_LEVEL;return Math.max(1,Math.ceil(e/c))}exports.TREE_SPECIES_LIST=i;exports.estimateDaysToMaxLevel=L;exports.getTreeSpecies=E;exports.speciesEmojiAtLevel=_;exports.speciesGrowthRoadmap=r;
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/tongji/utils/treeSpecies.js.map
|
||||
|
||||
@@ -1,310 +1,2 @@
|
||||
"use strict";
|
||||
const CN_DIGIT = {
|
||||
零: 0,
|
||||
"〇": 0,
|
||||
一: 1,
|
||||
壹: 1,
|
||||
幺: 1,
|
||||
二: 2,
|
||||
贰: 2,
|
||||
两: 2,
|
||||
三: 3,
|
||||
叁: 3,
|
||||
四: 4,
|
||||
肆: 4,
|
||||
五: 5,
|
||||
伍: 5,
|
||||
六: 6,
|
||||
陆: 6,
|
||||
七: 7,
|
||||
柒: 7,
|
||||
八: 8,
|
||||
捌: 8,
|
||||
九: 9,
|
||||
玖: 9
|
||||
};
|
||||
const CN_UNIT = { 十: 10, 拾: 10, 百: 100, 佰: 100, 千: 1e3, 仟: 1e3, 万: 1e4, 亿: 1e8 };
|
||||
function cnIntToNumber(s) {
|
||||
let total = 0;
|
||||
let section = 0;
|
||||
let number = 0;
|
||||
let hadUnit = false;
|
||||
let lastUnit = 0;
|
||||
let sawZeroAfterUnit = false;
|
||||
for (const ch of s) {
|
||||
if (CN_DIGIT[ch] !== void 0) {
|
||||
number = CN_DIGIT[ch];
|
||||
if (number === 0)
|
||||
sawZeroAfterUnit = true;
|
||||
} else if (CN_UNIT[ch] !== void 0) {
|
||||
hadUnit = true;
|
||||
const unit = CN_UNIT[ch];
|
||||
lastUnit = unit;
|
||||
sawZeroAfterUnit = false;
|
||||
if (unit >= 1e4) {
|
||||
section = (section + number) * unit;
|
||||
total += section;
|
||||
section = 0;
|
||||
} else {
|
||||
if (number === 0)
|
||||
number = 1;
|
||||
section += number * unit;
|
||||
}
|
||||
number = 0;
|
||||
}
|
||||
}
|
||||
if (!hadUnit && s.length > 1) {
|
||||
let joined = "";
|
||||
for (const ch of s) {
|
||||
if (CN_DIGIT[ch] !== void 0)
|
||||
joined += CN_DIGIT[ch];
|
||||
}
|
||||
if (joined)
|
||||
return Number(joined);
|
||||
}
|
||||
if (number > 0 && lastUnit >= 100 && !sawZeroAfterUnit) {
|
||||
number = number * (lastUnit / 10);
|
||||
}
|
||||
return total + section + number;
|
||||
}
|
||||
function cnSeqToNumber(seq) {
|
||||
if (seq.includes("点")) {
|
||||
const parts = seq.split("点");
|
||||
const intPart = parts[0];
|
||||
const decPart = parts.slice(1).join("");
|
||||
const intVal = intPart ? cnIntToNumber(intPart) : 0;
|
||||
let decStr = "";
|
||||
for (const ch of decPart) {
|
||||
if (CN_DIGIT[ch] !== void 0)
|
||||
decStr += CN_DIGIT[ch];
|
||||
}
|
||||
if (!decStr)
|
||||
return intVal;
|
||||
return Number(`${intVal}.${decStr}`);
|
||||
}
|
||||
return cnIntToNumber(seq);
|
||||
}
|
||||
function hasCnDigit(seq) {
|
||||
for (const ch of seq) {
|
||||
if (CN_DIGIT[ch] !== void 0 || CN_UNIT[ch] !== void 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function normalizeNumbers(text) {
|
||||
const raw = String(text || "");
|
||||
return raw.replace(/[零〇一壹幺二贰两三叁四肆五伍六陆七柒八捌九玖十拾百佰千仟万亿点]+/g, (m) => {
|
||||
if (!hasCnDigit(m))
|
||||
return m;
|
||||
const n = cnSeqToNumber(m);
|
||||
return Number.isFinite(n) ? String(n) : m;
|
||||
});
|
||||
}
|
||||
function numAfter(text, keys) {
|
||||
for (const k of keys) {
|
||||
const i = text.indexOf(k);
|
||||
if (i >= 0) {
|
||||
const rest = text.slice(i + k.length);
|
||||
const m = rest.match(/-?\d+(?:\.\d+)?/);
|
||||
if (m)
|
||||
return m[0];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
function textAfter(text, keys, stopKeys = []) {
|
||||
for (const k of keys) {
|
||||
const i = text.indexOf(k);
|
||||
if (i >= 0) {
|
||||
let rest = text.slice(i + k.length);
|
||||
rest = rest.replace(/^[是为吃了喝了吃的喝的有打了用了::,,、。\s]+/, "");
|
||||
let end = rest.length;
|
||||
const mStop = rest.match(/[,,。.;;!!??\n]/);
|
||||
if (mStop && mStop.index < end)
|
||||
end = mStop.index;
|
||||
for (const sk of stopKeys) {
|
||||
const si = rest.indexOf(sk);
|
||||
if (si >= 0 && si < end)
|
||||
end = si;
|
||||
}
|
||||
const seg = rest.slice(0, end).trim();
|
||||
if (seg)
|
||||
return seg;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
function parseGlucose(raw) {
|
||||
const t = normalizeNumbers(raw);
|
||||
const result = {};
|
||||
const fasting = numAfter(t, ["空腹"]);
|
||||
const post = numAfter(t, ["餐后", "饭后"]);
|
||||
const other = numAfter(t, ["其他", "随机", "睡前", "凌晨", "夜间", "晚上"]);
|
||||
if (fasting)
|
||||
result.fasting_blood_sugar = fasting;
|
||||
if (post)
|
||||
result.postprandial_blood_sugar = post;
|
||||
if (other)
|
||||
result.other_blood_sugar = other;
|
||||
if (!fasting && !post && !other) {
|
||||
const nums = t.match(/\d+(?:\.\d+)?/g);
|
||||
if (nums && nums.length === 1)
|
||||
result.other_blood_sugar = nums[0];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function parseBloodPressure(raw) {
|
||||
const t = normalizeNumbers(raw);
|
||||
const result = {};
|
||||
let sys = numAfter(t, ["高压", "收缩压", "收缩"]);
|
||||
let dia = numAfter(t, ["低压", "舒张压", "舒张"]);
|
||||
if (!sys || !dia) {
|
||||
const nums = (t.match(/\d{2,3}/g) || []).map(Number).filter((n) => n >= 30 && n <= 300);
|
||||
if (!sys && !dia && nums.length >= 2) {
|
||||
sys = String(nums[0]);
|
||||
dia = String(nums[1]);
|
||||
} else if (!sys && nums.length === 1 && nums[0] >= 90) {
|
||||
sys = String(nums[0]);
|
||||
}
|
||||
}
|
||||
if (sys && dia && Number(sys) < Number(dia)) {
|
||||
const tmp = sys;
|
||||
sys = dia;
|
||||
dia = tmp;
|
||||
}
|
||||
if (sys)
|
||||
result.systolic_pressure = sys;
|
||||
if (dia)
|
||||
result.diastolic_pressure = dia;
|
||||
const insulin = textAfter(raw, ["胰岛素"], ["高压", "低压", "血压", "西药", "备注"]);
|
||||
if (insulin)
|
||||
result.insulin = insulin;
|
||||
const western = textAfter(raw, ["西药", "降糖药", "口服药"], ["胰岛素", "高压", "低压", "血压", "备注"]);
|
||||
if (western)
|
||||
result.western_medicine = western;
|
||||
return result;
|
||||
}
|
||||
const DIET_MARKERS = [
|
||||
{ keys: ["早餐", "早饭", "早上", "早点", "早晨"], field: "breakfast_foods" },
|
||||
{ keys: ["午餐", "午饭", "中午"], field: "lunch_foods" },
|
||||
{ keys: ["晚餐", "晚饭", "晚上", "夜宵", "夜里"], field: "dinner_foods" }
|
||||
];
|
||||
function cleanFoodSeg(seg) {
|
||||
return String(seg || "").replace(/^[是为吃了吃的喝了喝的有::,,、。\s]+/, "").replace(/[。.\s]+$/, "").trim();
|
||||
}
|
||||
function parseDiet(raw) {
|
||||
const t = String(raw || "").trim();
|
||||
const result = {};
|
||||
const hits = [];
|
||||
DIET_MARKERS.forEach((m) => {
|
||||
for (const k of m.keys) {
|
||||
const idx = t.indexOf(k);
|
||||
if (idx >= 0) {
|
||||
hits.push({ idx, field: m.field, klen: k.length });
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!hits.length) {
|
||||
if (t)
|
||||
result.note = t;
|
||||
return result;
|
||||
}
|
||||
hits.sort((a, b) => a.idx - b.idx);
|
||||
hits.forEach((h, i) => {
|
||||
const start = h.idx + h.klen;
|
||||
const end = i + 1 < hits.length ? hits[i + 1].idx : t.length;
|
||||
const seg = cleanFoodSeg(t.slice(start, end));
|
||||
if (seg && !result[h.field])
|
||||
result[h.field] = seg;
|
||||
});
|
||||
const head = cleanFoodSeg(t.slice(0, hits[0].idx));
|
||||
if (head)
|
||||
result.note = head;
|
||||
return result;
|
||||
}
|
||||
const EXERCISE_FILLERS = [
|
||||
"今天",
|
||||
"我",
|
||||
"做了",
|
||||
"做",
|
||||
"进行了",
|
||||
"进行",
|
||||
"运动了",
|
||||
"运动",
|
||||
"锻炼了",
|
||||
"锻炼",
|
||||
"了",
|
||||
"大概",
|
||||
"左右",
|
||||
"持续",
|
||||
"差不多",
|
||||
"一共",
|
||||
"总共",
|
||||
"的",
|
||||
"走了",
|
||||
"打了",
|
||||
"跑了"
|
||||
];
|
||||
function parseExercise(raw) {
|
||||
const t = normalizeNumbers(raw);
|
||||
const result = {};
|
||||
const durMatch = t.match(/(\d+(?:\.\d+)?)\s*(个小时|小时|钟头|时|分钟|分)/);
|
||||
if (durMatch) {
|
||||
const val = parseFloat(durMatch[1]);
|
||||
const isHour = /个小时|小时|钟头|时/.test(durMatch[2]);
|
||||
result.duration = String(Math.round(isHour ? val * 60 : val));
|
||||
}
|
||||
if (/高强度|剧烈|很累|大汗|气喘/.test(t))
|
||||
result.intensity = 3;
|
||||
else if (/中强度|中等强度|中等|有点累|微微出汗|微汗/.test(t))
|
||||
result.intensity = 2;
|
||||
else if (/低强度|轻松|轻微|溜达|缓慢/.test(t))
|
||||
result.intensity = 1;
|
||||
let type = t;
|
||||
if (durMatch)
|
||||
type = type.replace(durMatch[0], "");
|
||||
type = type.replace(/高强度|中强度|中等强度|低强度|剧烈|很累|大汗|气喘|有点累|微微出汗|微汗|轻松|轻微|缓慢/g, "").replace(/\d+(?:\.\d+)?/g, "").replace(/[,,。.;;、\s]+/g, "");
|
||||
EXERCISE_FILLERS.forEach((f) => {
|
||||
type = type.split(f).join("");
|
||||
});
|
||||
type = type.trim();
|
||||
if (type && type.length <= 20)
|
||||
result.exercise_type = type;
|
||||
return result;
|
||||
}
|
||||
const FIELD_LABELS = {
|
||||
fasting_blood_sugar: "空腹",
|
||||
postprandial_blood_sugar: "餐后",
|
||||
other_blood_sugar: "其他血糖",
|
||||
systolic_pressure: "高压",
|
||||
diastolic_pressure: "低压",
|
||||
western_medicine: "西药",
|
||||
insulin: "胰岛素",
|
||||
breakfast_foods: "早餐",
|
||||
lunch_foods: "午餐",
|
||||
dinner_foods: "晚餐",
|
||||
note: "备注",
|
||||
exercise_type: "运动",
|
||||
duration: "时长",
|
||||
intensity: "强度"
|
||||
};
|
||||
const INTENSITY_LABELS = { 1: "低强度", 2: "中强度", 3: "高强度" };
|
||||
function summarizeParsed(parsed) {
|
||||
const parts = [];
|
||||
Object.keys(parsed).forEach((k) => {
|
||||
const label = FIELD_LABELS[k] || k;
|
||||
let val = parsed[k];
|
||||
if (k === "intensity")
|
||||
val = INTENSITY_LABELS[val] || val;
|
||||
parts.push(`${label}${val}`);
|
||||
});
|
||||
return parts.join(" · ");
|
||||
}
|
||||
exports.normalizeNumbers = normalizeNumbers;
|
||||
exports.parseBloodPressure = parseBloodPressure;
|
||||
exports.parseDiet = parseDiet;
|
||||
exports.parseExercise = parseExercise;
|
||||
exports.parseGlucose = parseGlucose;
|
||||
exports.summarizeParsed = summarizeParsed;
|
||||
"use strict";const l={零:0,"〇":0,一:1,壹:1,幺:1,二:2,贰:2,两:2,三:3,叁:3,四:4,肆:4,五:5,伍:5,六:6,陆:6,七:7,柒:7,八:8,捌:8,九:9,玖:9},p={十:10,拾:10,百:100,佰:100,千:1e3,仟:1e3,万:1e4,亿:1e8};function h(r){let i=0,t=0,e=0,n=!1,s=0,o=!1;for(const c of r)if(l[c]!==void 0)e=l[c],e===0&&(o=!0);else if(p[c]!==void 0){n=!0;const f=p[c];s=f,o=!1,f>=1e4?(t=(t+e)*f,i+=t,t=0):(e===0&&(e=1),t+=e*f),e=0}if(!n&&r.length>1){let c="";for(const f of r)l[f]!==void 0&&(c+=l[f]);if(c)return Number(c)}return e>0&&s>=100&&!o&&(e=e*(s/10)),i+t+e}function b(r){if(r.includes("点")){const i=r.split("点"),t=i[0],e=i.slice(1).join(""),n=t?h(t):0;let s="";for(const o of e)l[o]!==void 0&&(s+=l[o]);return s?+`${n}.${s}`:n}return h(r)}function S(r){for(const i of r)if(l[i]!==void 0||p[i]!==void 0)return!0;return!1}function d(r){return String(r||"").replace(/[零〇一壹幺二贰两三叁四肆五伍六陆七柒八捌九玖十拾百佰千仟万亿点]+/g,t=>{if(!S(t))return t;const e=b(t);return Number.isFinite(e)?String(e):t})}function u(r,i){for(const t of i){const e=r.indexOf(t);if(e>=0){const s=r.slice(e+t.length).match(/-?\d+(?:\.\d+)?/);if(s)return s[0]}}return""}function _(r,i,t=[]){for(const e of i){const n=r.indexOf(e);if(n>=0){let s=r.slice(n+e.length);s=s.replace(/^[是为吃了喝了吃的喝的有打了用了::,,、。\s]+/,"");let o=s.length;const c=s.match(/[,,。.;;!!??\n]/);c&&c.index<o&&(o=c.index);for(const a of t){const g=s.indexOf(a);g>=0&&g<o&&(o=g)}const f=s.slice(0,o).trim();if(f)return f}}return""}function y(r){const i=d(r),t={},e=u(i,["空腹"]),n=u(i,["餐后","饭后"]),s=u(i,["其他","随机","睡前","凌晨","夜间","晚上"]);if(e&&(t.fasting_blood_sugar=e),n&&(t.postprandial_blood_sugar=n),s&&(t.other_blood_sugar=s),!e&&!n&&!s){const o=i.match(/\d+(?:\.\d+)?/g);o&&o.length===1&&(t.other_blood_sugar=o[0])}return t}function E(r){const i=d(r),t={};let e=u(i,["高压","收缩压","收缩"]),n=u(i,["低压","舒张压","舒张"]);if(!e||!n){const c=(i.match(/\d{2,3}/g)||[]).map(Number).filter(f=>f>=30&&f<=300);!e&&!n&&c.length>=2?(e=String(c[0]),n=String(c[1])):!e&&c.length===1&&c[0]>=90&&(e=String(c[0]))}if(e&&n&&Number(e)<Number(n)){const c=e;e=n,n=c}e&&(t.systolic_pressure=e),n&&(t.diastolic_pressure=n);const s=_(r,["胰岛素"],["高压","低压","血压","西药","备注"]);s&&(t.insulin=s);const o=_(r,["西药","降糖药","口服药"],["胰岛素","高压","低压","血压","备注"]);return o&&(t.western_medicine=o),t}const x=[{keys:["早餐","早饭","早上","早点","早晨"],field:"breakfast_foods"},{keys:["午餐","午饭","中午"],field:"lunch_foods"},{keys:["晚餐","晚饭","晚上","夜宵","夜里"],field:"dinner_foods"}];function m(r){return String(r||"").replace(/^[是为吃了吃的喝了喝的有::,,、。\s]+/,"").replace(/[。.\s]+$/,"").trim()}function N(r){const i=String(r||"").trim(),t={},e=[];if(x.forEach(s=>{for(const o of s.keys){const c=i.indexOf(o);if(c>=0){e.push({idx:c,field:s.field,klen:o.length});break}}}),!e.length)return i&&(t.note=i),t;e.sort((s,o)=>s.idx-o.idx),e.forEach((s,o)=>{const c=s.idx+s.klen,f=o+1<e.length?e[o+1].idx:i.length,a=m(i.slice(c,f));a&&!t[s.field]&&(t[s.field]=a)});const n=m(i.slice(0,e[0].idx));return n&&(t.note=n),t}const k=["今天","我","做了","做","进行了","进行","运动了","运动","锻炼了","锻炼","了","大概","左右","持续","差不多","一共","总共","的","走了","打了","跑了"];function I(r){const i=d(r),t={},e=i.match(/(\d+(?:\.\d+)?)\s*(个小时|小时|钟头|时|分钟|分)/);if(e){const s=parseFloat(e[1]),o=/个小时|小时|钟头|时/.test(e[2]);t.duration=String(Math.round(o?s*60:s))}/高强度|剧烈|很累|大汗|气喘/.test(i)?t.intensity=3:/中强度|中等强度|中等|有点累|微微出汗|微汗/.test(i)?t.intensity=2:/低强度|轻松|轻微|溜达|缓慢/.test(i)&&(t.intensity=1);let n=i;return e&&(n=n.replace(e[0],"")),n=n.replace(/高强度|中强度|中等强度|低强度|剧烈|很累|大汗|气喘|有点累|微微出汗|微汗|轻松|轻微|缓慢/g,"").replace(/\d+(?:\.\d+)?/g,"").replace(/[,,。.;;、\s]+/g,""),k.forEach(s=>{n=n.split(s).join("")}),n=n.trim(),n&&n.length<=20&&(t.exercise_type=n),t}const L={fasting_blood_sugar:"空腹",postprandial_blood_sugar:"餐后",other_blood_sugar:"其他血糖",systolic_pressure:"高压",diastolic_pressure:"低压",western_medicine:"西药",insulin:"胰岛素",breakfast_foods:"早餐",lunch_foods:"午餐",dinner_foods:"晚餐",note:"备注",exercise_type:"运动",duration:"时长",intensity:"强度"},T={1:"低强度",2:"中强度",3:"高强度"};function A(r){const i=[];return Object.keys(r).forEach(t=>{const e=L[t]||t;let n=r[t];t==="intensity"&&(n=T[n]||n),i.push(`${e}${n}`)}),i.join(" · ")}exports.normalizeNumbers=d;exports.parseBloodPressure=E;exports.parseDiet=N;exports.parseExercise=I;exports.parseGlucose=y;exports.summarizeParsed=A;
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/tongji/utils/voiceParse.js.map
|
||||
|
||||
@@ -1,238 +1,2 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
||||
var __publicField = (obj, key, value) => {
|
||||
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
||||
return value;
|
||||
};
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
class AudioPool {
|
||||
constructor(src, size, volume = 1) {
|
||||
__publicField(this, "list", []);
|
||||
__publicField(this, "cursor", 0);
|
||||
__publicField(this, "warmedUp", false);
|
||||
__publicField(this, "targetVolume", 1);
|
||||
this.src = src;
|
||||
this.size = size;
|
||||
this.targetVolume = volume;
|
||||
}
|
||||
create() {
|
||||
for (let i = 0; i < this.size; i++) {
|
||||
const ctx = common_vendor.index.createInnerAudioContext();
|
||||
ctx.src = this.src;
|
||||
ctx.obeyMuteSwitch = false;
|
||||
ctx.autoplay = false;
|
||||
ctx.volume = this.targetVolume;
|
||||
this.list.push(ctx);
|
||||
}
|
||||
}
|
||||
setVolume(volume) {
|
||||
this.targetVolume = Math.max(0, Math.min(1, volume));
|
||||
this.list.forEach((ctx) => {
|
||||
try {
|
||||
ctx.volume = this.targetVolume;
|
||||
} catch (_) {
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 预热:短暂播放,让音频文件下载/解码到内存
|
||||
* 真正首次 play 不会再卡冷启动
|
||||
*/
|
||||
warmUp() {
|
||||
if (this.warmedUp)
|
||||
return;
|
||||
if (this.list.length === 0)
|
||||
this.create();
|
||||
this.list.forEach((ctx) => {
|
||||
try {
|
||||
ctx.volume = 0;
|
||||
ctx.play();
|
||||
setTimeout(() => {
|
||||
try {
|
||||
ctx.stop();
|
||||
ctx.volume = this.targetVolume;
|
||||
} catch (_) {
|
||||
}
|
||||
}, 60);
|
||||
} catch (_) {
|
||||
}
|
||||
});
|
||||
this.warmedUp = true;
|
||||
}
|
||||
play() {
|
||||
if (this.list.length === 0) {
|
||||
this.create();
|
||||
this.warmUp();
|
||||
}
|
||||
const ctx = this.list[this.cursor];
|
||||
this.cursor = (this.cursor + 1) % this.list.length;
|
||||
try {
|
||||
this.list.forEach((c) => {
|
||||
try {
|
||||
c.stop();
|
||||
} catch (_) {
|
||||
}
|
||||
});
|
||||
ctx.play();
|
||||
} catch (_) {
|
||||
try {
|
||||
ctx.play();
|
||||
} catch (__) {
|
||||
}
|
||||
}
|
||||
}
|
||||
destroy() {
|
||||
this.list.forEach((ctx) => {
|
||||
var _a;
|
||||
try {
|
||||
(_a = ctx.destroy) == null ? void 0 : _a.call(ctx);
|
||||
} catch (_) {
|
||||
}
|
||||
});
|
||||
this.list = [];
|
||||
this.warmedUp = false;
|
||||
}
|
||||
}
|
||||
const DEFAULT_CLICK_SRC = "https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/uploads/file/20260526/20260526105128557ef8669.mp3";
|
||||
function useMetronome(options = {}) {
|
||||
const {
|
||||
initialBpm = 80,
|
||||
bpmMin = 40,
|
||||
bpmMax = 240,
|
||||
clickSrc = DEFAULT_CLICK_SRC,
|
||||
accentSrc,
|
||||
poolSize = 4,
|
||||
volume = 1,
|
||||
silent = false,
|
||||
onBeat
|
||||
} = options;
|
||||
const bpm = common_vendor.ref(initialBpm);
|
||||
const isPlaying = common_vendor.ref(false);
|
||||
const beatIndex = common_vendor.ref(0);
|
||||
const isAccent = common_vendor.ref(false);
|
||||
const accentEveryRef = common_vendor.ref(options.accentEvery ?? 4);
|
||||
const intervalMs = common_vendor.computed(() => 6e4 / bpm.value);
|
||||
let clickPool = null;
|
||||
let accentPool = null;
|
||||
let timer = null;
|
||||
let nextTickAt = 0;
|
||||
const ensureAudio = () => {
|
||||
if (silent)
|
||||
return;
|
||||
if (!clickPool) {
|
||||
clickPool = new AudioPool(clickSrc, poolSize, volume);
|
||||
clickPool.warmUp();
|
||||
}
|
||||
if (accentSrc && !accentPool) {
|
||||
accentPool = new AudioPool(accentSrc, Math.max(2, Math.ceil(poolSize / 2)), volume);
|
||||
accentPool.warmUp();
|
||||
}
|
||||
};
|
||||
const playSound = (accent) => {
|
||||
if (accent && accentPool) {
|
||||
accentPool.play();
|
||||
} else if (clickPool) {
|
||||
clickPool.play();
|
||||
}
|
||||
};
|
||||
const tick = () => {
|
||||
if (!isPlaying.value)
|
||||
return;
|
||||
const every = Math.max(1, accentEveryRef.value);
|
||||
const accent = beatIndex.value % every === 0;
|
||||
isAccent.value = accent;
|
||||
playSound(accent);
|
||||
onBeat == null ? void 0 : onBeat(beatIndex.value, accent);
|
||||
beatIndex.value++;
|
||||
nextTickAt += intervalMs.value;
|
||||
const nextDelay = Math.max(0, nextTickAt - Date.now());
|
||||
timer = setTimeout(tick, nextDelay);
|
||||
};
|
||||
const start = () => {
|
||||
if (isPlaying.value)
|
||||
return;
|
||||
ensureAudio();
|
||||
isPlaying.value = true;
|
||||
beatIndex.value = 0;
|
||||
nextTickAt = Date.now();
|
||||
tick();
|
||||
};
|
||||
const stop = () => {
|
||||
isPlaying.value = false;
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
}
|
||||
};
|
||||
const setBpm = (val) => {
|
||||
bpm.value = Math.max(bpmMin, Math.min(bpmMax, Math.round(val)));
|
||||
};
|
||||
const setAccentEvery = (n) => {
|
||||
accentEveryRef.value = Math.max(1, Math.min(16, Math.round(n)));
|
||||
beatIndex.value = 0;
|
||||
};
|
||||
const updateAudioSrc = (newClickSrc, newAccentSrc) => {
|
||||
const wasPlaying = isPlaying.value;
|
||||
if (wasPlaying)
|
||||
stop();
|
||||
clickPool == null ? void 0 : clickPool.destroy();
|
||||
accentPool == null ? void 0 : accentPool.destroy();
|
||||
clickPool = null;
|
||||
accentPool = null;
|
||||
clickPool = new AudioPool(newClickSrc, poolSize);
|
||||
if (newAccentSrc) {
|
||||
accentPool = new AudioPool(newAccentSrc, Math.max(2, Math.ceil(poolSize / 2)));
|
||||
}
|
||||
const previewCtx = common_vendor.index.createInnerAudioContext();
|
||||
previewCtx.src = newClickSrc;
|
||||
previewCtx.obeyMuteSwitch = false;
|
||||
previewCtx.volume = 0.4;
|
||||
try {
|
||||
previewCtx.play();
|
||||
setTimeout(() => {
|
||||
var _a;
|
||||
try {
|
||||
(_a = previewCtx.destroy) == null ? void 0 : _a.call(previewCtx);
|
||||
} catch (_) {
|
||||
}
|
||||
}, 500);
|
||||
} catch (_) {
|
||||
}
|
||||
if (wasPlaying)
|
||||
start();
|
||||
};
|
||||
const preload = () => {
|
||||
try {
|
||||
common_vendor.index.setInnerAudioOption({
|
||||
obeyMuteSwitch: false,
|
||||
mixWithOther: true
|
||||
});
|
||||
} catch (_) {
|
||||
}
|
||||
ensureAudio();
|
||||
};
|
||||
common_vendor.onUnmounted(() => {
|
||||
stop();
|
||||
clickPool == null ? void 0 : clickPool.destroy();
|
||||
accentPool == null ? void 0 : accentPool.destroy();
|
||||
clickPool = null;
|
||||
accentPool = null;
|
||||
});
|
||||
return {
|
||||
bpm,
|
||||
isPlaying,
|
||||
beatIndex,
|
||||
isAccent,
|
||||
intervalMs,
|
||||
accentEvery: accentEveryRef,
|
||||
start,
|
||||
stop,
|
||||
setBpm,
|
||||
setAccentEvery,
|
||||
updateAudioSrc,
|
||||
preload
|
||||
};
|
||||
}
|
||||
exports.useMetronome = useMetronome;
|
||||
"use strict";var R=Object.defineProperty;var B=(l,t,e)=>t in l?R(l,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):l[t]=e;var m=(l,t,e)=>(B(l,typeof t!="symbol"?t+"":t,e),e);const i=require("../../common/vendor.js");class d{constructor(t,e,o=1){m(this,"list",[]);m(this,"cursor",0);m(this,"warmedUp",!1);m(this,"targetVolume",1);this.src=t,this.size=e,this.targetVolume=o}create(){for(let t=0;t<this.size;t++){const e=i.index.createInnerAudioContext();e.src=this.src,e.obeyMuteSwitch=!1,e.autoplay=!1,e.volume=this.targetVolume,this.list.push(e)}}setVolume(t){this.targetVolume=Math.max(0,Math.min(1,t)),this.list.forEach(e=>{try{e.volume=this.targetVolume}catch{}})}warmUp(){this.warmedUp||(this.list.length===0&&this.create(),this.list.forEach(t=>{try{t.volume=0,t.play(),setTimeout(()=>{try{t.stop(),t.volume=this.targetVolume}catch{}},60)}catch{}}),this.warmedUp=!0)}play(){this.list.length===0&&(this.create(),this.warmUp());const t=this.list[this.cursor];this.cursor=(this.cursor+1)%this.list.length;try{this.list.forEach(e=>{try{e.stop()}catch{}}),t.play()}catch{try{t.play()}catch{}}}destroy(){this.list.forEach(t=>{var e;try{(e=t.destroy)==null||e.call(t)}catch{}}),this.list=[],this.warmedUp=!1}}const F="https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/uploads/file/20260526/20260526105128557ef8669.mp3";function K(l={}){const{initialBpm:t=80,bpmMin:e=40,bpmMax:o=240,clickSrc:z=F,accentSrc:U,poolSize:f=4,volume:A=1,silent:I=!1,onBeat:v}=l,M=i.ref(t),u=i.ref(!1),c=i.ref(0),E=i.ref(!1),w=i.ref(l.accentEvery??4),b=i.computed(()=>6e4/M.value);let s=null,a=null,y=null,g=0;const S=()=>{I||(s||(s=new d(z,f,A),s.warmUp()),U&&!a&&(a=new d(U,Math.max(2,Math.ceil(f/2)),A),a.warmUp()))},D=r=>{r&&a?a.play():s&&s.play()},V=()=>{if(!u.value)return;const r=Math.max(1,w.value),h=c.value%r===0;E.value=h,D(h),v==null||v(c.value,h),c.value++,g+=b.value;const p=Math.max(0,g-Date.now());y=setTimeout(V,p)},T=()=>{u.value||(S(),u.value=!0,c.value=0,g=Date.now(),V())},_=()=>{u.value=!1,y&&(clearTimeout(y),y=null)},C=r=>{M.value=Math.max(e,Math.min(o,Math.round(r)))},q=r=>{w.value=Math.max(1,Math.min(16,Math.round(r))),c.value=0},L=(r,h)=>{const p=u.value;p&&_(),s==null||s.destroy(),a==null||a.destroy(),s=null,a=null,s=new d(r,f),h&&(a=new d(h,Math.max(2,Math.ceil(f/2))));const n=i.index.createInnerAudioContext();n.src=r,n.obeyMuteSwitch=!1,n.volume=.4;try{n.play(),setTimeout(()=>{var x;try{(x=n.destroy)==null||x.call(n)}catch{}},500)}catch{}p&&T()},O=()=>{try{i.index.setInnerAudioOption({obeyMuteSwitch:!1,mixWithOther:!0})}catch{}S()};return i.onUnmounted(()=>{_(),s==null||s.destroy(),a==null||a.destroy(),s=null,a=null}),{bpm:M,isPlaying:u,beatIndex:c,isAccent:E,intervalMs:b,accentEvery:w,start:T,stop:_,setBpm:C,setAccentEvery:q,updateAudioSrc:L,preload:O}}exports.useMetronome=K;
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/training/hooks/useMetronome.js.map
|
||||
|
||||
+1
-465
File diff suppressed because one or more lines are too long
+1
-15
@@ -1,15 +1 @@
|
||||
.crush-canvas-container.data-v-e11c993f {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
}
|
||||
.crush-canvas.data-v-e11c993f {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
}
|
||||
.crush-canvas-container.data-v-e11c993f{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:10}.crush-canvas.data-v-e11c993f{display:block;width:100%;height:100%;background:transparent}
|
||||
+1
-277
File diff suppressed because one or more lines are too long
+1
-15
@@ -1,15 +1 @@
|
||||
.walker-canvas-container.data-v-782dd882 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.walker-canvas.data-v-782dd882 {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: transparent; /* Pure transparent to blend into page */
|
||||
}
|
||||
.walker-canvas-container.data-v-782dd882{width:100%;height:100%;position:absolute;top:0;left:0;right:0;bottom:0}.walker-canvas.data-v-782dd882{display:block;width:100%;height:100%;background:transparent}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1079
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,150 +1,2 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const training_hooks_useMetronome = require("../hooks/useMetronome.js");
|
||||
if (!Math) {
|
||||
WalkerCanvas();
|
||||
}
|
||||
const WalkerCanvas = () => "./components/walker-canvas.js";
|
||||
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
|
||||
__name: "metronome",
|
||||
setup(__props) {
|
||||
const LOOP_PRESETS = [
|
||||
{ id: "slow", bpm: 110, label: "慢走", desc: "热身 · 恢复" },
|
||||
{ id: "normal", bpm: 130, label: "健走", desc: "日常 · 通勤" },
|
||||
{ id: "brisk", bpm: 150, label: "快走", desc: "提速 · 燃脂" }
|
||||
];
|
||||
const customExpanded = common_vendor.ref(false);
|
||||
const currentLoop = common_vendor.ref("normal");
|
||||
const currentSound = common_vendor.ref("crisp");
|
||||
const walkerCanvasRef = common_vendor.ref(null);
|
||||
const SOUND_PRESETS = {
|
||||
crisp: {
|
||||
normal: "https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/uploads/file/20260527/202605271539371ebe13672.mp3",
|
||||
accent: "https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/uploads/file/20260527/202605271539376ff628472.mp3"
|
||||
},
|
||||
wood: {
|
||||
normal: "https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/uploads/file/20260526/202605261051282a0a94508.mp3",
|
||||
accent: "https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/uploads/file/20260526/202605261051282a0a94508.mp3"
|
||||
}
|
||||
};
|
||||
const fg = training_hooks_useMetronome.useMetronome({
|
||||
initialBpm: 130,
|
||||
accentEvery: 2,
|
||||
clickSrc: SOUND_PRESETS.crisp.normal,
|
||||
accentSrc: SOUND_PRESETS.crisp.accent,
|
||||
poolSize: 4,
|
||||
// 【完美音画同步核心】
|
||||
onBeat: (index, isAccent) => {
|
||||
if (walkerCanvasRef.value && walkerCanvasRef.value.triggerBeat) {
|
||||
walkerCanvasRef.value.triggerBeat();
|
||||
}
|
||||
}
|
||||
});
|
||||
const isPlaying = common_vendor.computed(() => fg.isPlaying.value);
|
||||
const currentBpm = common_vendor.computed(() => fg.bpm.value);
|
||||
const customAccent = common_vendor.computed(() => fg.accentEvery.value);
|
||||
const intervalMs = common_vendor.computed(() => 6e4 / fg.bpm.value);
|
||||
const onCenterTap = () => {
|
||||
if (fg.isPlaying.value) {
|
||||
fg.stop();
|
||||
common_vendor.index.setKeepScreenOn({ keepScreenOn: false });
|
||||
} else {
|
||||
fg.start();
|
||||
common_vendor.index.setKeepScreenOn({ keepScreenOn: true });
|
||||
}
|
||||
};
|
||||
const onPresetTap = (id) => {
|
||||
const preset = LOOP_PRESETS.find((p) => p.id === id);
|
||||
if (!preset)
|
||||
return;
|
||||
currentLoop.value = id;
|
||||
fg.setBpm(preset.bpm);
|
||||
if (!fg.isPlaying.value) {
|
||||
fg.start();
|
||||
common_vendor.index.setKeepScreenOn({ keepScreenOn: true });
|
||||
}
|
||||
};
|
||||
const onToggleCustom = () => {
|
||||
customExpanded.value = !customExpanded.value;
|
||||
if (customExpanded.value) {
|
||||
fg.preload();
|
||||
} else {
|
||||
const matched = LOOP_PRESETS.find((p) => p.bpm === fg.bpm.value);
|
||||
currentLoop.value = matched ? matched.id : null;
|
||||
}
|
||||
};
|
||||
const onBpmDelta = (delta) => {
|
||||
fg.setBpm(fg.bpm.value + delta);
|
||||
currentLoop.value = null;
|
||||
};
|
||||
const onAccentSelect = (n) => {
|
||||
fg.setAccentEvery(n);
|
||||
};
|
||||
const onSoundSelect = (sound) => {
|
||||
currentSound.value = sound;
|
||||
const preset = SOUND_PRESETS[sound];
|
||||
fg.updateAudioSrc(preset.normal, preset.accent);
|
||||
};
|
||||
const rootStyle = common_vendor.computed(() => ({
|
||||
"--beat-duration": `${intervalMs.value}ms`
|
||||
}));
|
||||
common_vendor.onShow(() => {
|
||||
fg.preload();
|
||||
});
|
||||
function cleanupMetronome() {
|
||||
fg.stop();
|
||||
common_vendor.index.setKeepScreenOn({ keepScreenOn: false });
|
||||
}
|
||||
common_vendor.onHide(cleanupMetronome);
|
||||
common_vendor.onUnload(cleanupMetronome);
|
||||
common_vendor.onUnmounted(cleanupMetronome);
|
||||
return (_ctx, _cache) => {
|
||||
return common_vendor.e({
|
||||
a: common_vendor.sr(walkerCanvasRef, "a75aa31b-0", {
|
||||
"k": "walkerCanvasRef"
|
||||
}),
|
||||
b: common_vendor.o(onCenterTap, "0f"),
|
||||
c: common_vendor.p({
|
||||
bpm: currentBpm.value,
|
||||
["is-playing"]: isPlaying.value
|
||||
}),
|
||||
d: currentSound.value === "crisp" ? 1 : "",
|
||||
e: common_vendor.o(($event) => onSoundSelect("crisp"), "8c"),
|
||||
f: currentSound.value === "wood" ? 1 : "",
|
||||
g: common_vendor.o(($event) => onSoundSelect("wood"), "43"),
|
||||
h: common_vendor.f(LOOP_PRESETS, (p, k0, i0) => {
|
||||
return {
|
||||
a: common_vendor.t(p.label),
|
||||
b: common_vendor.t(p.bpm),
|
||||
c: common_vendor.t(p.desc),
|
||||
d: p.id,
|
||||
e: currentLoop.value === p.id ? 1 : "",
|
||||
f: common_vendor.o(($event) => onPresetTap(p.id), p.id)
|
||||
};
|
||||
}),
|
||||
i: common_vendor.t(customExpanded.value ? "✕ 收起自定义" : "⚙ 自定义节奏"),
|
||||
j: common_vendor.o(onToggleCustom, "29"),
|
||||
k: customExpanded.value
|
||||
}, customExpanded.value ? {
|
||||
l: common_vendor.o(($event) => onBpmDelta(-5), "71"),
|
||||
m: common_vendor.o(($event) => onBpmDelta(-1), "5b"),
|
||||
n: common_vendor.t(currentBpm.value),
|
||||
o: common_vendor.o(($event) => onBpmDelta(1), "90"),
|
||||
p: common_vendor.o(($event) => onBpmDelta(5), "b0"),
|
||||
q: common_vendor.f([2, 3, 4], (n, k0, i0) => {
|
||||
return {
|
||||
a: common_vendor.t(n),
|
||||
b: n,
|
||||
c: customAccent.value === n ? 1 : "",
|
||||
d: common_vendor.o(($event) => onAccentSelect(n), n)
|
||||
};
|
||||
})
|
||||
} : {}, {
|
||||
r: common_vendor.s(rootStyle.value)
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-a75aa31b"]]);
|
||||
wx.createPage(MiniProgramPage);
|
||||
"use strict";const e=require("../../common/vendor.js"),x=require("../hooks/useMetronome.js");Math||z();const z=()=>"./components/walker-canvas.js",$=e.defineComponent({__name:"metronome",setup(E){const u=[{id:"slow",bpm:110,label:"慢走",desc:"热身 · 恢复"},{id:"normal",bpm:130,label:"健走",desc:"日常 · 通勤"},{id:"brisk",bpm:150,label:"快走",desc:"提速 · 燃脂"}],c=e.ref(!1),s=e.ref("normal"),p=e.ref("crisp"),l=e.ref(null),i={crisp:{normal:"https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/uploads/file/20260527/202605271539371ebe13672.mp3",accent:"https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/uploads/file/20260527/202605271539376ff628472.mp3"},wood:{normal:"https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/uploads/file/20260526/202605261051282a0a94508.mp3",accent:"https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/uploads/file/20260526/202605261051282a0a94508.mp3"}},o=x.useMetronome({initialBpm:130,accentEvery:2,clickSrc:i.crisp.normal,accentSrc:i.crisp.accent,poolSize:4,onBeat:(t,a)=>{l.value&&l.value.triggerBeat&&l.value.triggerBeat()}}),f=e.computed(()=>o.isPlaying.value),d=e.computed(()=>o.bpm.value),g=e.computed(()=>o.accentEvery.value),b=e.computed(()=>6e4/o.bpm.value),S=()=>{o.isPlaying.value?(o.stop(),e.index.setKeepScreenOn({keepScreenOn:!1})):(o.start(),e.index.setKeepScreenOn({keepScreenOn:!0}))},_=t=>{const a=u.find(n=>n.id===t);a&&(s.value=t,o.setBpm(a.bpm),o.isPlaying.value||(o.start(),e.index.setKeepScreenOn({keepScreenOn:!0})))},k=()=>{if(c.value=!c.value,c.value)o.preload();else{const t=u.find(a=>a.bpm===o.bpm.value);s.value=t?t.id:null}},r=t=>{o.setBpm(o.bpm.value+t),s.value=null},h=t=>{o.setAccentEvery(t)},v=t=>{p.value=t;const a=i[t];o.updateAudioSrc(a.normal,a.accent)},y=e.computed(()=>({"--beat-duration":`${b.value}ms`}));e.onShow(()=>{o.preload()});function m(){o.stop(),e.index.setKeepScreenOn({keepScreenOn:!1})}return e.onHide(m),e.onUnload(m),e.onUnmounted(m),(t,a)=>e.e({a:e.sr(l,"a75aa31b-0",{k:"walkerCanvasRef"}),b:e.o(S,"0f"),c:e.p({bpm:d.value,"is-playing":f.value}),d:p.value==="crisp"?1:"",e:e.o(n=>v("crisp"),"8c"),f:p.value==="wood"?1:"",g:e.o(n=>v("wood"),"43"),h:e.f(u,(n,O,P)=>({a:e.t(n.label),b:e.t(n.bpm),c:e.t(n.desc),d:n.id,e:s.value===n.id?1:"",f:e.o(w=>_(n.id),n.id)})),i:e.t(c.value?"✕ 收起自定义":"⚙ 自定义节奏"),j:e.o(k,"29"),k:c.value},c.value?{l:e.o(n=>r(-5),"71"),m:e.o(n=>r(-1),"5b"),n:e.t(d.value),o:e.o(n=>r(1),"90"),p:e.o(n=>r(5),"b0"),q:e.f([2,3,4],(n,O,P)=>({a:e.t(n),b:n,c:g.value===n?1:"",d:e.o(w=>h(n),n)}))}:{},{r:e.s(y.value)})}}),B=e._export_sfc($,[["__scopeId","data-v-a75aa31b"]]);wx.createPage(B);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/training/pages/metronome.js.map
|
||||
|
||||
@@ -1,311 +1 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
/* 颜色变量 */
|
||||
/* 行为相关颜色 */
|
||||
/* 文字基本颜色 */
|
||||
/* 背景颜色 */
|
||||
/* 边框颜色 */
|
||||
/* 尺寸变量 */
|
||||
/* 文字尺寸 */
|
||||
/* 图片尺寸 */
|
||||
/* Border Radius */
|
||||
/* 水平间距 */
|
||||
/* 垂直间距 */
|
||||
/* 透明度 */
|
||||
/* 文章场景相关 */
|
||||
/* ============================================================
|
||||
* 设计 token —— 浅色清爽
|
||||
* ============================================================ */
|
||||
/* ============================================================
|
||||
* 页面容器
|
||||
* ============================================================ */
|
||||
.page.data-v-a75aa31b {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
padding: 30rpx 28rpx 50rpx;
|
||||
background: #f8fafc;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 统一运动律动视区 (Canvas)
|
||||
* ============================================================ */
|
||||
.stage-canvas-wrapper.data-v-a75aa31b {
|
||||
width: 100vw;
|
||||
margin-left: -28rpx;
|
||||
margin-right: -28rpx;
|
||||
flex-shrink: 0;
|
||||
/* 防止被压缩 */
|
||||
height: 600rpx;
|
||||
/* 固定高度,不随内容变化 */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 音色选择器
|
||||
* ============================================================ */
|
||||
.sound-selector.data-v-a75aa31b {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
gap: 14rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.sound-option.data-v-a75aa31b {
|
||||
flex: 1;
|
||||
background: #ffffff;
|
||||
border: 2rpx solid rgba(15, 23, 42, 0.06);
|
||||
border-radius: 24rpx;
|
||||
padding: 20rpx 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(15, 23, 42, 0.04);
|
||||
transition: all 0.18s;
|
||||
}
|
||||
.sound-option .sound-icon.data-v-a75aa31b {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
.sound-option .sound-label.data-v-a75aa31b {
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
color: #475569;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
.sound-option.data-v-a75aa31b:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
.sound-option.active.data-v-a75aa31b {
|
||||
background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
|
||||
border-color: #10b981;
|
||||
box-shadow: 0 8rpx 20rpx rgba(16, 185, 129, 0.18), inset 0 0 0 2rpx rgba(16, 185, 129, 0.4);
|
||||
}
|
||||
.sound-option.active .sound-label.data-v-a75aa31b {
|
||||
color: #047857;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 三档位推荐
|
||||
* ============================================================ */
|
||||
.presets.data-v-a75aa31b {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
gap: 14rpx;
|
||||
}
|
||||
.preset.data-v-a75aa31b {
|
||||
flex: 1;
|
||||
background: #ffffff;
|
||||
border: 2rpx solid rgba(15, 23, 42, 0.06);
|
||||
border-radius: 24rpx;
|
||||
padding: 26rpx 8rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(15, 23, 42, 0.04);
|
||||
transition: all 0.18s;
|
||||
}
|
||||
.preset .preset-name.data-v-a75aa31b {
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
color: #0f172a;
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
.preset .preset-bpm.data-v-a75aa31b {
|
||||
font-size: 22rpx;
|
||||
color: #475569;
|
||||
font-weight: 600;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.preset .preset-desc.data-v-a75aa31b {
|
||||
font-size: 18rpx;
|
||||
color: #94a3b8;
|
||||
letter-spacing: 1rpx;
|
||||
margin-top: 2rpx;
|
||||
}
|
||||
.preset.data-v-a75aa31b:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
.preset.active.data-v-a75aa31b {
|
||||
background: #d1fae5;
|
||||
border-color: #10b981;
|
||||
box-shadow: 0 8rpx 20rpx rgba(16, 185, 129, 0.18), inset 0 0 0 2rpx rgba(16, 185, 129, 0.4);
|
||||
}
|
||||
.preset.active .preset-name.data-v-a75aa31b {
|
||||
color: #047857;
|
||||
}
|
||||
.preset.active .preset-bpm.data-v-a75aa31b {
|
||||
color: #047857;
|
||||
}
|
||||
.preset.active .preset-desc.data-v-a75aa31b {
|
||||
color: #10b981;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 自定义节奏区域(标题栏 + 折叠内容)
|
||||
* ============================================================ */
|
||||
.custom-section.data-v-a75aa31b {
|
||||
width: 100%;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
.custom-header.data-v-a75aa31b {
|
||||
width: 100%;
|
||||
padding: 16rpx 6rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.custom-header .custom-title.data-v-a75aa31b {
|
||||
font-size: 22rpx;
|
||||
color: #94a3b8;
|
||||
letter-spacing: 0.5rpx;
|
||||
}
|
||||
.custom-header .custom-title.data-v-a75aa31b:active {
|
||||
color: #475569;
|
||||
}
|
||||
.custom-content.data-v-a75aa31b {
|
||||
width: 100%;
|
||||
background: #ffffff;
|
||||
border: 2rpx solid rgba(245, 158, 11, 0.25);
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 6rpx 18rpx rgba(245, 158, 11, 0.08);
|
||||
padding: 20rpx 24rpx 22rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
.custom-warn.data-v-a75aa31b {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
.custom-warn .warn-dot.data-v-a75aa31b {
|
||||
font-size: 18rpx;
|
||||
color: #f59e0b;
|
||||
}
|
||||
.custom-warn .warn-text.data-v-a75aa31b {
|
||||
font-size: 22rpx;
|
||||
color: #b45309;
|
||||
letter-spacing: 0.5rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
.row.data-v-a75aa31b {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12rpx;
|
||||
}
|
||||
.row .row-label.data-v-a75aa31b {
|
||||
font-size: 24rpx;
|
||||
color: #475569;
|
||||
font-weight: 600;
|
||||
letter-spacing: 1rpx;
|
||||
flex-shrink: 0;
|
||||
width: 70rpx;
|
||||
}
|
||||
.bpm-stepper.data-v-a75aa31b {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6rpx;
|
||||
flex: 1;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.bpm-stepper .step-btn.data-v-a75aa31b {
|
||||
min-width: 56rpx;
|
||||
height: 52rpx;
|
||||
line-height: 52rpx;
|
||||
text-align: center;
|
||||
font-size: 22rpx;
|
||||
color: #475569;
|
||||
background: #f1f5f9;
|
||||
border-radius: 10rpx;
|
||||
font-weight: 600;
|
||||
padding: 0 10rpx;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.bpm-stepper .step-btn.data-v-a75aa31b:active {
|
||||
background: #e2e8f0;
|
||||
transform: scale(0.94);
|
||||
}
|
||||
.bpm-stepper .step-val.data-v-a75aa31b {
|
||||
min-width: 84rpx;
|
||||
height: 52rpx;
|
||||
line-height: 52rpx;
|
||||
text-align: center;
|
||||
font-size: 30rpx;
|
||||
font-weight: 800;
|
||||
color: #0f172a;
|
||||
font-variant-numeric: tabular-nums;
|
||||
background: #fef3c7;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
.meter-tabs.data-v-a75aa31b {
|
||||
display: flex;
|
||||
gap: 8rpx;
|
||||
}
|
||||
.meter-tabs .meter-tab.data-v-a75aa31b {
|
||||
height: 52rpx;
|
||||
line-height: 52rpx;
|
||||
padding: 0 18rpx;
|
||||
font-size: 22rpx;
|
||||
color: #475569;
|
||||
background: #f1f5f9;
|
||||
border-radius: 10rpx;
|
||||
font-weight: 600;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
.meter-tabs .meter-tab.active.data-v-a75aa31b {
|
||||
background: #f59e0b;
|
||||
color: #fff;
|
||||
box-shadow: 0 4rpx 10rpx rgba(245, 158, 11, 0.3);
|
||||
}
|
||||
.meter-tabs .meter-tab.data-v-a75aa31b:active {
|
||||
transform: scale(0.94);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* 底部行(已废弃,保留样式以防引用)
|
||||
* ============================================================ */
|
||||
.bottom-row.data-v-a75aa31b {
|
||||
width: 100%;
|
||||
margin-top: 6rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 6rpx;
|
||||
}
|
||||
.bottom-link.data-v-a75aa31b {
|
||||
font-size: 22rpx;
|
||||
color: #94a3b8;
|
||||
letter-spacing: 0.5rpx;
|
||||
padding: 8rpx 4rpx;
|
||||
}
|
||||
.bottom-link.data-v-a75aa31b:active {
|
||||
color: #475569;
|
||||
}
|
||||
.bottom-hint.data-v-a75aa31b {
|
||||
font-size: 22rpx;
|
||||
color: #94a3b8;
|
||||
letter-spacing: 0.5rpx;
|
||||
}
|
||||
.page.data-v-a75aa31b{position:relative;min-height:100vh;box-sizing:border-box;padding:30rpx 28rpx 50rpx;background:#f8fafc;display:flex;flex-direction:column;align-items:center;gap:20rpx;color:#0f172a}.stage-canvas-wrapper.data-v-a75aa31b{width:100vw;margin-left:-28rpx;margin-right:-28rpx;flex-shrink:0;height:600rpx;display:flex;justify-content:center;align-items:center;margin-bottom:24rpx;position:relative}.sound-selector.data-v-a75aa31b{width:100%;display:flex;gap:14rpx;margin-bottom:20rpx}.sound-option.data-v-a75aa31b{flex:1;background:#fff;border:2rpx solid rgba(15,23,42,.06);border-radius:24rpx;padding:20rpx 16rpx;display:flex;align-items:center;justify-content:center;gap:10rpx;box-shadow:0 4rpx 12rpx rgba(15,23,42,.04);transition:all .18s}.sound-option .sound-icon.data-v-a75aa31b{font-size:32rpx}.sound-option .sound-label.data-v-a75aa31b{font-size:26rpx;font-weight:600;color:#475569;letter-spacing:1rpx}.sound-option.data-v-a75aa31b:active{transform:scale(.97)}.sound-option.active.data-v-a75aa31b{background:linear-gradient(135deg,#d1fae5,#a7f3d0);border-color:#10b981;box-shadow:0 8rpx 20rpx rgba(16,185,129,.18),inset 0 0 0 2rpx rgba(16,185,129,.4)}.sound-option.active .sound-label.data-v-a75aa31b{color:#047857}.presets.data-v-a75aa31b{width:100%;display:flex;gap:14rpx}.preset.data-v-a75aa31b{flex:1;background:#fff;border:2rpx solid rgba(15,23,42,.06);border-radius:24rpx;padding:26rpx 8rpx;display:flex;flex-direction:column;align-items:center;gap:8rpx;box-shadow:0 4rpx 12rpx rgba(15,23,42,.04);transition:all .18s}.preset .preset-name.data-v-a75aa31b{font-size:28rpx;font-weight:700;color:#0f172a;letter-spacing:2rpx}.preset .preset-bpm.data-v-a75aa31b{font-size:22rpx;color:#475569;font-weight:600;font-variant-numeric:tabular-nums}.preset .preset-desc.data-v-a75aa31b{font-size:18rpx;color:#94a3b8;letter-spacing:1rpx;margin-top:2rpx}.preset.data-v-a75aa31b:active{transform:scale(.97)}.preset.active.data-v-a75aa31b{background:#d1fae5;border-color:#10b981;box-shadow:0 8rpx 20rpx rgba(16,185,129,.18),inset 0 0 0 2rpx rgba(16,185,129,.4)}.preset.active .preset-name.data-v-a75aa31b,.preset.active .preset-bpm.data-v-a75aa31b{color:#047857}.preset.active .preset-desc.data-v-a75aa31b{color:#10b981}.custom-section.data-v-a75aa31b{width:100%;margin-top:12rpx}.custom-header.data-v-a75aa31b{width:100%;padding:16rpx 6rpx;display:flex;align-items:center;justify-content:center}.custom-header .custom-title.data-v-a75aa31b{font-size:22rpx;color:#94a3b8;letter-spacing:.5rpx}.custom-header .custom-title.data-v-a75aa31b:active{color:#475569}.custom-content.data-v-a75aa31b{width:100%;background:#fff;border:2rpx solid rgba(245,158,11,.25);border-radius:24rpx;box-shadow:0 6rpx 18rpx rgba(245,158,11,.08);padding:20rpx 24rpx 22rpx;display:flex;flex-direction:column;gap:16rpx;margin-top:8rpx}.custom-warn.data-v-a75aa31b{display:flex;align-items:center;gap:8rpx;margin-bottom:4rpx}.custom-warn .warn-dot.data-v-a75aa31b{font-size:18rpx;color:#f59e0b}.custom-warn .warn-text.data-v-a75aa31b{font-size:22rpx;color:#b45309;letter-spacing:.5rpx;font-weight:600}.row.data-v-a75aa31b{display:flex;align-items:center;justify-content:space-between;gap:12rpx}.row .row-label.data-v-a75aa31b{font-size:24rpx;color:#475569;font-weight:600;letter-spacing:1rpx;flex-shrink:0;width:70rpx}.bpm-stepper.data-v-a75aa31b{display:flex;align-items:center;gap:6rpx;flex:1;justify-content:flex-end}.bpm-stepper .step-btn.data-v-a75aa31b{min-width:56rpx;height:52rpx;line-height:52rpx;text-align:center;font-size:22rpx;color:#475569;background:#f1f5f9;border-radius:10rpx;font-weight:600;padding:0 10rpx;font-variant-numeric:tabular-nums}.bpm-stepper .step-btn.data-v-a75aa31b:active{background:#e2e8f0;transform:scale(.94)}.bpm-stepper .step-val.data-v-a75aa31b{min-width:84rpx;height:52rpx;line-height:52rpx;text-align:center;font-size:30rpx;font-weight:800;color:#0f172a;font-variant-numeric:tabular-nums;background:#fef3c7;border-radius:10rpx}.meter-tabs.data-v-a75aa31b{display:flex;gap:8rpx}.meter-tabs .meter-tab.data-v-a75aa31b{height:52rpx;line-height:52rpx;padding:0 18rpx;font-size:22rpx;color:#475569;background:#f1f5f9;border-radius:10rpx;font-weight:600;letter-spacing:1rpx}.meter-tabs .meter-tab.active.data-v-a75aa31b{background:#f59e0b;color:#fff;box-shadow:0 4rpx 10rpx rgba(245,158,11,.3)}.meter-tabs .meter-tab.data-v-a75aa31b:active{transform:scale(.94)}.bottom-row.data-v-a75aa31b{width:100%;margin-top:6rpx;display:flex;align-items:center;justify-content:space-between;padding:0 6rpx}.bottom-link.data-v-a75aa31b{font-size:22rpx;color:#94a3b8;letter-spacing:.5rpx;padding:8rpx 4rpx}.bottom-link.data-v-a75aa31b:active{color:#475569}.bottom-hint.data-v-a75aa31b{font-size:22rpx;color:#94a3b8;letter-spacing:.5rpx}
|
||||
File diff suppressed because one or more lines are too long
+1
-1079
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user