Compare commits

...
4 Commits
Author SHA1 Message Date
lik 031227710d 修改了样式 2026-10-18 22:14:49 +08:00
lik ed36a0db0a 有新版本提示升级 2026-10-07 16:57:09 +08:00
lik 60a7c1fd56 删除不用的图片,增加页面转发给朋友 2026-10-07 16:47:28 +08:00
lik 179b059250 增加了商务合作,去掉了医院页面 2026-10-07 16:28:04 +08:00
52 changed files with 821 additions and 1461 deletions
+20 -36
View File
@@ -35,36 +35,6 @@ App({
})
})
this.globalData.hospitalInfoReady = new Promise((resolve) => {
API.resource.getHospitalInfo().then((data) => {
this.globalData.hospitalInfo = data.data.hospitalInfo
resolve(data.data.hospitalInfo)
}).catch((err) => {
console.error('获取医院信息失败', err)
resolve([])
})
})
this.globalData.hospitalRankingReady = new Promise((resolve) => {
API.resource.getHospitalRanking().then((data) => {
this.globalData.hospitalRanking = data.data.hospitalRanking
resolve(data.data.hospitalRanking)
}).catch((err) => {
console.error('获取医院排名失败', err)
resolve([])
})
})
this.globalData.departmentRankingsReady = new Promise((resolve) => {
API.resource.getDepartmentRankings().then((data) => {
this.globalData.departmentRankings = data.data.departmentRankings
resolve(data.data.departmentRankings)
}).catch((err) => {
console.error('获取科室排名失败', err)
resolve([])
})
})
this.checkUpdate();
},
@@ -153,32 +123,49 @@ App({
},
checkUpdate() {
// 老基础库(< 1.9.90)没有 getUpdateManager,先挡一层:
// 否则下面直接 .onCheckForUpdate 会抛 TypeError
if (!wx.canIUse('getUpdateManager')) {
return;
}
// 获取小程序更新管理器实例
const updateManager = wx.getUpdateManager();
// 监听检查更新事件,当小程序有新版本时会触发此回调
updateManager.onCheckForUpdate(function (res) {
// 请求完新版本信息的回调
console.log(res.hasUpdate); // 打印是否有新版本
console.log('[App] 是否有新版本:', res.hasUpdate); // 打印是否有新版本
});
// 监听更新准备就绪事件,当新版本下载完成时会触发此回调
updateManager.onUpdateReady(function () {
wx.showModal({
title: '更新提示',
content: '新版本已经准备好,可以重启应用小程序了!',
content: '新版本已经准备好,是否重启应用?',
confirmText: '立即重启',
cancelText: '稍后',
success(res) {
if (res.confirm) {
// 用户确认更新,调用 applyUpdate 应用新版本并重启小程序
updateManager.applyUpdate();
return;
}
// 用户选了「稍后」:新版本此时不会生效,要等下次冷启动才自动应用。
// 这里必须说清楚,否则用户以为已经升级完了
wx.showToast({
title: '下次打开将自动更新',
icon: 'none'
});
}
});
});
// 监听更新失败事件,当新版本下载失败时会触发此回调
updateManager.onUpdateFailed(function () {
// 新版本下载失败,可以在这里处理失败逻辑,例如提示用户稍后再试
// 下载失败没有可交给用户的动作(微信会在下次启动时重试),
// 只留日志便于线上排查,不打断用户
console.warn('[App] 新版本下载失败');
});
},
@@ -188,8 +175,5 @@ App({
chatSocket: null,
services: [],
agreement: null,
hospitalInfo: [],
hospitalRanking: [],
departmentRankings: [],
}
})
+2 -3
View File
@@ -17,9 +17,8 @@
"pages/mine/addressedit",
"pages/mine/about",
"pages/mine/contact",
"pages/hospital/contact",
"pages/hospital/ranking",
"pages/home/webview"
"pages/home/webview",
"pages/mine/business"
],
"window": {
"backgroundTextStyle": "light",
+10 -6
View File
@@ -30,7 +30,7 @@
|---|---|---|---|
| `--brand-strong` | `#B8520A` | 主按钮、价格数字、选中态、实心强调块 | 纸面 4.66:1,白卡 4.94:1;白字压其上 4.94:1 |
| `--brand-ink` | `#9B4508` | 标签文字、文字链、暖色小标题、图标 | 浅橙底 5.96:1,纸面 6.10:1,白卡 6.46:1 |
| `--brand-line` | `#FFE0C2` | 浅橙块描边、浅橙档的状态描边 | 仅做描边 |
| `--brand-line` | `#FFE0C2` | 浅橙块描边、浅橙档的状态描边;`itemlist` 预约按钮软填充(§2.1 例外已登记) | 仅做描边;按钮填充见例外 |
| `--brand-soft` | `#FFF4E8` | 浅橙底:说明砖、图标衬底、按钮按下态 | 仅做底 |
用法边界:
@@ -38,8 +38,8 @@
- `--brand-strong` 是唯一可当"实心大色块"的值;全页同类实心块不超过一处。
- `--brand-soft` 只能当底,不能当文字色或描边色。
- 浅橙底上的文字一律走 `--brand-ink`(`--brand-strong` 落其上仅 4.56:1,余量小)。
- 例外(已登记):`escort/itemlist` 价格数字改走 `--muted` + 字重 500,让「预约」空心胶囊独占焦点;同页价格列只用这一个色值、一种字重。
- 例外(已登记):`escort/itemlist`「预约」按钮走**空心胶囊**——3rpx `--brand-strong` 环 + 28rpx 满圆角 + `--brand-ink` 字 30rpx/500,无填充无阴影,按下填 `--brand-line`。同行规格签已是"浅橙底 + 6rpx 圆角",按钮若同族会与之撞形;**同一行只允许一个填充物**,按钮独占"环"形态。该页因此无实心大色块。
- 备注(2026-10-18):`escort/itemlist` 价格数字走回默认 `--brand-strong` + 字重 500(本表「价格数字」用途原位,白卡 4.94:1),同页价格列只用这一个色值、一种字重;其间短暂用过 `--ink-2`,已回退,不再是例外。
- 例外(已登记,2026-10-18 修订):`escort/itemlist`「预约」按钮走**软填充胶囊**——3rpx `--brand-strong` 环 + `--brand-line` 填充 + 28rpx 满圆角 + `--brand-ink` 字 30rpx/500,按下整粒 `opacity .85`。沿革:原为空心胶囊(按下才填 `--brand-line`),规格签删底后"撞形"根因消失,改常填。环不可撤——`--brand-line` 填充落白卡仅约 1.1:1,非文本 3:1 由环承担(4.94:1)。**同一行只允许一个填充物**仍成立(规格签已是纯文字)。
### 2.2 第二色:暖墨文字层
@@ -69,8 +69,8 @@
- 线是切分工具,不表意,不上主色或状态色。浅橙底上必须用 `--sep`(`--brand-line` 落 `--brand-soft` 上仅 1.16:1,肉眼看不出)。
- `--paper` 与 `--brand-soft` 明度差仅约 1.03:1,浅橙块落纸面须靠 **2rpx `--brand-line` 描边**托形,不加阴影。
- **白卡一律走中性阴影** `--shadow-card: 0 2rpx 10rpx rgba(63, 43, 25, 0.07)`,圆角 28rpx。彩色(暖橙)阴影不得用在 `--white` 面上;它只允许用于实心 CTA、品牌印记等小体量元素(`--shadow-cta: 0 2rpx 8rpx rgba(184, 82, 10, 0.16)`)。
- 例外(已登记):`escort/itemlist` 两个服务分组做成**通栏白底块**——`--white` + 上下各 2rpx `--line` + `--shadow-card`,**圆角 0**;做法 `margin: 36rpx -32rpx 0` + `padding: 28rpx 32rpx`,行宽仍为 686rpx(若内缩,卡的左右内距会白吃 48rpx 行宽,长名称 + 右区更易挤出)。圆角必须为 0,否则满宽块的圆角会切在屏幕边上。页首 `.notice` 仍是内缩 28rpx 圆角白卡。
- 例外(已登记):`escort/itemlist` 的**人工客服旁路卡**做浅橙面(`--brand-soft` + 2rpx `--brand-line` + 28rpx 圆角 + 去阴影),与首页 `.quick-item-full` 同源,补回该页"暖色只剩线、没有面"的那一档。位置在**页首披露卡下方、清单上方**(原为页尾的"收口卡",已上移):文案走本页"情形 + 动作"两段式(muted「不想线上预约?」+ 暖橙链「直接联系人工客服」)。页尾不设卡,改由一行**文档级元信息**收尾——细竖线分隔的「服务指南 │ 用户协议」(从页首披露卡下移,不加卡、不加 chevron,文字链自身即点击暗示);披露卡因此退回纯声明,只留城市与费用披露。
- 例外(已登记,2026-10-18 修订):`escort/itemlist` 服务分组改为**组头落纸面 + 每项一张白卡**——项卡 `--white` + 2rpx `--line` + 24rpx 圆角 + `--shadow-card`、内距 28rpx、卡间距 20rpx(相邻选择器给出);原"通栏白底块(圆角 0)+ 虚线行"撤销——白带与项卡会叠成两层底。行宽由 686rpx 降至约 626rpx。组头副题说明砖走浅橙面配方:`--brand-soft` 填充 + 2rpx `--brand-line` 描边 + 14rpx 圆角(§四.5 说明砖填充必须中性,`--brand-line` 仅作描边;落纸面靠描边托形)。页首 `.notice` 由白卡降为纸面一行「圆点 + 26rpx `--ink-2` 小字」,费用披露不降 `--muted`。
- 例外(已登记):`escort/itemlist` 的**人工客服旁路卡**做浅橙面(`--brand-soft` + 2rpx `--brand-line` + 28rpx 圆角 + 去阴影),与首页 `.quick-item-full` 同源,补回该页"暖色只剩线、没有面"的那一档。位置在**清单之后、文档行之前**(沿革:页尾"收口卡"→页首清单上方→2026-10-18 下沉回清单之后——旁路属兜底,压在清单前会把不打算自助的用户先引走,也白占首屏):文案走本页"情形 + 动作"两段式(muted「不想线上预约?」+ 暖橙链「直接联系人工客服」)。页尾不设卡,改由一行**文档级元信息**收尾——细竖线分隔的「服务指南 │ 用户协议」(从页首披露卡下移,不加卡、不加 chevron,文字链自身即点击暗示);披露卡因此退回纯声明,只留城市与费用披露。
- 例外(已登记):`mine/about` 的「联系我们」做成**浅橙入口卡**(`--brand-soft` + 2rpx `--brand-line` + 28rpx 圆角 + 去阴影,同首页 `.quick-item-full` 配方),是该页尾部唯一的暖色面。卡内**不再平铺联系方式**——热线/微信/邮箱/工作时间四项与 `mine/contact` 页逐项重合,平铺即"同一意图两个入口";只留「联系我们」+ 一行摘要(「人工客服」,与首页同卡同文案)+ muted chevron,整卡可点跳 `mine/contact`。另注:该页品牌印记(`home-w.png` 白色线稿)必须落 `--brand-strong` 实心底,不能用 `--brand-soft`,白色线稿在浅橙底上看不见。
- 例外(已登记):`mine/mine` 的菜单与「退出登录」做成**通栏白底块**(`--white` + 上下各 2rpx `--line` + `--shadow-card`,圆角 0)。其中「退出登录」是**动作而非导航**,与菜单行不同族:单独一块、一行居中、**无图标无 chevron**、字色 `--muted`。状态色不得用于按钮(§三),退出因此不走红/橙,区分只靠结构与位置。
@@ -134,6 +134,10 @@
已完成(2026-10-06):`escort/attendantlist` 4 文件迁至 `attendant/attendantlist`,同目录新增 `attendant/attendantdetail`(4 文件),两页一并并入暖橙体系——`attendantlist.wxss` 的 page 级令牌副本(停在旧值 `#C2410C` / `#9A3412`)整块删除,改用 `app.wxss` 唯一来源,`page{}` 只留 `background-color: var(--paper)`(同 `guide`);`.wxml` 的 `t-icon` 硬编码 `#9A3412`→`#9B4508`,两处竖分隔线 `#E5DACC`→`--sep`。结构:列表卡右侧补 `chevron-right`(`#6F655C`)作点击暗示,整卡可点进详情;详情页按国标 4.2.1.5 分区——主卡(头像 / 脱敏名 / 已核验徽标 / 服务年限 · 累计服务次数,居中)+ 擅长场景(全量,不截断)+ 服务信息(性别 / 服务区域 / 服务语言,空项整行隐藏)+ 个人简介(未填整块隐藏),全页无实心色块、不新增色相,说明行仍是「公示信息,不含联系方式」。入口仍在首页介绍卡信任行(`goToAttendants`),`app.json` 两条路由同步改路径。同日按国标 4.2.1.5 补全公示项:详情页加「资质与培训」(健康证明有效期 + 培训记录)与「过往服务评价」两个分区,两区均无数据时整块隐藏;区块内条目用 `--line` 发丝线分隔,评分用 48rpx `--ink` 大字 + `--muted` 小数(`/ 5`)与条数,无实心色块。
已完成(2026-10-18):`health/profilelist` 卡片重构为「身份牌」结构——首字牌 + 姓名/性别签 + 竖线分隔元信息行(空值整项剔除,不留「未填写」)+ 备注单行省略,与 `recorddetail` 就诊人卡同语言。删除动作由「卡内操作行」改为**右上角安静图标**(`catchtap` 防冒泡、确认弹窗兜底):孤行删除撑不满一行、反而拉高卡片;上文「删除动作下沉到卡内操作行」的描述就此被替代。
已完成(2026-10-18):`escort/itemlist` 版式重排并同步本档——结构由「通栏白底章节带」改「组头落纸面 + 每项一张白卡」,虚线行与章线撤销;`.notice` 降为纸面披露行,客服旁路卡下沉到清单之后(§2.3 两条例外同步修订);价格 `--muted`→`--brand-strong`(回到「价格数字」默认用途)、「预约」改软填充胶囊(§2.1 按钮例外同步修订);组头副题说明砖按 §四.5 走 `--brand-soft` 填充 + `--brand-line` 描边;规格签删底(`--brand-soft` 落白卡仅 1.08:1 形同虚设),仅时长服务保留签,「按次」删;按钮补透明热区(`::after` 外扩 6rpx,触控 56→68rpx)。全页仍单色相、无新色。
### 5.2 系统级(不在页面里,最易漏)
| 位置 | 现状 | 应改为 |
@@ -195,7 +199,7 @@
| 3 | `pages/home/index.wxss` | `.brand-mark` 的 `box-shadow` | `rgba(184, 82, 10, 0.16)` | `rgba(194, 65, 12, 0.16)` |
| 4 | `pages/home/index.wxss` | 8 个 base64 线图标的 `stroke` | `#B8520A` | `#C2410C` |
| 5 | `pages/home/index.wxml` | 第 119 行 `t-icon` 的 `color` | `#9B4508` | `#9A3412` |
| 6 | `pages/escort/itemlist.wxml` | 第 25 / 30 / 96 行 `t-icon` 的 `color` | `#9B4508` | `#9A3412` |
| 6 | `pages/escort/itemlist.wxml` | 第 82 行 `t-icon` 的 `color`(客服卡 chevron,全页唯一一处) | `#9B4508` | `#9A3412` |
| 7 | `custom-tab-bar/index.js` | 第 8 行 `activeColor` | `#B8520A` | `#C2410C` |
| 8 | `custom-tab-bar/index.wxss` | 第 39 行 `.tab-item.is-active .tab-text` | `#B8520A` | `#C2410C` |
| 9 | `app.json` | 第 30 行 `tabBar.selectedColor` | `#B8520A` | `#C2410C` |
+2 -3
View File
@@ -49,8 +49,7 @@ doc/
| `pages/mine/mine` | 我的 |
| `pages/mine/about` | 关于 |
| `pages/mine/contact` | 联系我们 |
| `pages/hospital/contact` | 医院联系 |
| `pages/hospital/ranking` | 医院排行 |
| `pages/mine/business` | 合作与入驻(商务合作 / 陪诊师入驻 / 陪诊师培训,入口自首页与「我的」页页脚) |
| `pages/home/webview` | 网页容器 |
## 约定
@@ -58,4 +57,4 @@ doc/
- **配色**:见 `doc/DESIGN.md`。色板令牌集中在 `app.wxss` 的 `page{}`,改配色只改这一处。
- **接口**:统一走 `utils/request.js`,基址 `https://api.huashengtec.com`(本地调试可改用文件内注释的 `127.0.0.1:9004`);请求自动携带 `appId=wxapp-escort` 与登录 token。
- **登录**:`app.js` 的 `onShow` 调 `wx.login` 换 token,存于 `globalData.user`。
- **全局数据**:服务列表 / 协议 / 医院信息 / 排行在 `onLaunch` 预取,挂到 `globalData` 供各页取用。
- **全局数据**:服务列表 / 协议在 `onLaunch` 预取,挂到 `globalData` 供各页取用。
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 38 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

+19
View File
@@ -134,5 +134,24 @@ Page({
title: `暖橙陪诊 · ${attendant.name}`,
path: `/pages/attendant/attendantdetail?id=${attendant.id}`
}
},
// 朋友圈只能分享当前页,陪诊师 id 只能靠 query 带上;
// 详情还没回来(attendant 为 null)时不带 query,好友打开是列表页口径的空态
onShareTimeline() {
const {
attendant
} = this.data
if (!attendant) {
return {
title: '暖橙陪诊 · 陪诊师团队'
}
}
return {
title: `暖橙陪诊 · ${attendant.name}`,
query: `id=${attendant.id}`
}
}
})
+4 -4
View File
@@ -80,8 +80,8 @@ page {
align-items: center;
flex-shrink: 0;
margin-left: 14rpx;
padding: 4rpx 12rpx;
border-radius: 8rpx;
padding: 4rpx 14rpx;
border-radius: 10rpx;
background: var(--brand-soft);
border: 2rpx solid var(--brand-line);
}
@@ -154,8 +154,8 @@ page {
.tag {
margin: 0 12rpx 12rpx 0;
padding: 8rpx 18rpx;
border-radius: 8rpx;
padding: 6rpx 14rpx;
border-radius: 10rpx;
background: var(--brand-soft);
border: 2rpx solid var(--brand-line);
font-size: 26rpx;
+3 -3
View File
@@ -135,8 +135,8 @@ page {
align-items: center;
flex-shrink: 0;
margin-left: 14rpx;
padding: 4rpx 12rpx;
border-radius: 8rpx;
padding: 4rpx 14rpx;
border-radius: 10rpx;
background: var(--brand-soft);
border: 2rpx solid var(--brand-line);
}
@@ -183,7 +183,7 @@ page {
.staff-tag {
margin: 0 12rpx 12rpx 0;
padding: 6rpx 14rpx;
border-radius: 8rpx;
border-radius: 10rpx;
background: var(--brand-soft);
border: 2rpx solid var(--brand-line);
font-size: 24rpx;
+6
View File
@@ -75,5 +75,11 @@ Page({
title: '暖橙陪诊服务协议',
path: '/pages/escort/agreement'
}
},
onShareTimeline() {
return {
title: '暖橙陪诊服务协议'
}
}
})
+21 -19
View File
@@ -9,7 +9,27 @@
<text class="header-subtitle">第一次用陪诊?三分钟看懂全流程</text>
</view>
<!-- ① 服务流程:下单到完成的通用环节 -->
<!-- ① 就诊前准备:到院前建议提前办妥或备齐的事项。
放在服务流程之前——用户打开指南时最急的是"我该带什么、先办什么",
流程是读完之后才需要的背景 -->
<view class="card">
<view class="card-head">
<view class="card-mark">
<!-- 原 info-circle 只是个「信息」圆标,与「准备清单」无关;
换成 task-checked(勾选清单),与卡内逐条勾对的读法一致 -->
<t-icon name="task-checked" size="26rpx" color="#9B4508" />
</view>
<text class="card-title">就诊前准备</text>
</view>
<view class="dot-list">
<view class="dot-item" wx:for="{{ preparations }}" wx:key="*this">
<view class="dot"></view>
<text class="dot-text">{{ item }}</text>
</view>
</view>
</view>
<!-- ② 服务流程:下单到完成的通用环节 -->
<view class="card">
<view class="card-head">
<!-- 卡片头标识走全站「浅橙衬底 + 暖橙图标」语言,实心橙只留给底部 CTA(DESIGN.md §2.1)。
@@ -32,24 +52,6 @@
</view>
</view>
<!-- ② 就诊前准备:到院前建议提前办妥或备齐的事项 -->
<view class="card">
<view class="card-head">
<view class="card-mark">
<!-- 原 info-circle 只是个「信息」圆标,与「准备清单」无关;
换成 task-checked(勾选清单),与卡内逐条勾对的读法一致 -->
<t-icon name="task-checked" size="26rpx" color="#9B4508" />
</view>
<text class="card-title">就诊前准备</text>
</view>
<view class="dot-list">
<view class="dot-item" wx:for="{{ preparations }}" wx:key="*this">
<view class="dot"></view>
<text class="dot-text">{{ item }}</text>
</view>
</view>
</view>
<!-- ③ 温馨提示:通用注意事项,不涉及具体规则 -->
<view class="card">
<view class="card-head">
+31
View File
@@ -83,10 +83,24 @@ Page({
const totalPrice = this.calculateTotal(service.price, 1)
this.setData({
service: service,
serviceIcon: this.getServiceIcon(service.title),
totalPrice: totalPrice
})
},
// 弹窗服务标记:原占位图是全服务共用的一张白色线稿,落在浅橙面板上看不见,
// 改用暖橙 t-icon(名称均已核对 tdesign 图标表,写错不报错只会渲染为空)。
// 图标按服务名选:夜间→月亮,陪诊→时钟,其余(取报告/代取药品等代办)→人像
getServiceIcon(title) {
if (title.indexOf('夜间') > -1) {
return 'moon'
}
if (title.indexOf('陪诊') > -1) {
return 'time'
}
return 'user-business'
},
calculateTotal(price) {
return price
},
@@ -402,5 +416,22 @@ Page({
title: `${service.title} - 专业陪诊服务`,
path: `/pages/escort/itemdetail?id=${service.id}`
}
},
// 朋友圈只能分享当前页,服务 id 只能靠 query 带上;
// 服务未加载完(service.id 为 null)时不带 query,落到默认项,避免拼出 id=null
onShareTimeline() {
const {
service
} = this.data
if (!service.id) {
return {
title: '暖橙陪诊 · 专业陪诊服务'
}
}
return {
title: `${service.title} - 专业陪诊服务`,
query: `id=${service.id}`
}
}
})
+4 -2
View File
@@ -66,7 +66,7 @@
<text class="price-sym">¥</text>
<text class="total-price">{{ totalPrice }}</text>
</view>
<button class="order-btn" bindtap="openOrderPopup">立即预约</button>
<button class="order-btn" bindtap="openOrderPopup">预约</button>
</view>
<!-- 下单弹窗遮罩 -->
@@ -84,7 +84,9 @@
<scroll-view class="popup-body" scroll-y>
<!-- 服务信息 -->
<view class="order-service-info">
<image class="order-service-image" src="{{service.image}}" mode="aspectFill"></image>
<view class="order-service-mark">
<t-icon name="{{serviceIcon}}" size="48rpx" color="#9B4508" />
</view>
<view class="order-service-text">
<text class="order-service-title">{{service.title}}</text>
<text class="order-service-price">¥{{service.price}}/次</text>
+8 -4
View File
@@ -71,7 +71,7 @@ page {
background: var(--brand-soft);
border: 2rpx solid var(--brand-line);
color: var(--brand-ink);
font-size: 22rpx;
font-size: 24rpx;
font-weight: 700;
letter-spacing: 1rpx;
white-space: nowrap;
@@ -390,12 +390,16 @@ page {
border: 2rpx solid var(--brand-line);
}
.order-service-image {
/* 服务标记:暖橙 t-icon 直接落在浅橙面板上(--brand-ink 5.96:1)。
原占位图是全服务共用的白色线稿,白底白图等于隐形;
保留 96×96 定宽让标题列与旧版对齐,只换内容不挪版 */
.order-service-mark {
display: flex;
align-items: center;
justify-content: center;
width: 96rpx;
height: 96rpx;
border-radius: 14rpx;
flex-shrink: 0;
background: var(--white);
}
.order-service-text {
+8 -11
View File
@@ -9,12 +9,13 @@
// 拿成员名当组名,另外三项会读成"剩下的";用「就医代办」则不与任何一项重名,
// 也与组内已有的「出入院代办」共用同一个动作词。
// note 是每组标题下的一句副题(这组是给谁的),只讲"什么情况适合选这一组",
// 不重复列服务;在页面上挂 .group-sub,是扁平小字而非卡片
// 不重复列服务;在页面上挂 .group-sub(暖橙说明砖:--brand-soft 底 + --brand-line 描边)。
// 收在 22 字以内:砖内文字宽约 642rpx,28rpx 字号一行约 23 字,超了会折行、砖变高
// ids 对应 services.js 里的服务 id,取不到的项会被跳过
const SERVICE_GROUPS = [{
key: 'accompany',
title: '陪同就医',
note: '不熟悉医院流程、上班脱不开身、不便独自就诊、需要夜间陪诊的情况都适合,就诊当天有人全程陪着。',
note: '有人全程陪同就诊,适合不便独自前往的情况',
ids: [1, 2, 7] // 全天陪诊 / 半天陪诊 / 夜间陪诊
},
{
@@ -22,22 +23,18 @@ const SERVICE_GROUPS = [{
title: '就医代办',
// 「开药」已改为「取药」:国标 8.1 只列「领取药物」,开药属开具处方的医疗行为,
// 会擦 8.2「提供医疗建议」「代替选择用药方案」;取药是凭已有处方代领,口径与 id 8 一致
note: '代问诊、预约检查时间、取报告、办手续、取药等跑腿服务都可以代劳,本人不必到场。',
note: '代问诊、跑腿取药取报告,本人不必到场。',
ids: [3, 4, 5, 6, 8] // 代问诊 / 检查预约 / 出入院代办 / 跑腿服务 / 取药快递
}
]
// 规格签:把"这一单买的是什么"从说明句里提出来,各行口径一致——
// 按时长计费的服务标出时长,按次计费的标"按次"。id 对应 services.js,取不到就不显示
// 规格签:只在有时长信息时出现——按时长计费的服务标出时长。
// 「按次」已删:第二组五项全是按次,组内全员同签等于没信息,五个相同的签连排只是噪音。
// id 对应 services.js,取不到就不显示
const UNIT_BY_ID = {
1: '8小时/次',
2: '4小时/次',
3: '按次',
4: '按次',
5: '按次',
6: '2小时/次',
7: '4小时/次',
8: '按次'
7: '4小时/次'
}
// 价目表上的价格去掉无意义的 .00(各行都是整元),扫起来更快
+28 -37
View File
@@ -6,12 +6,11 @@
所以这里不写页名,只让用户动手挑(下面两组就是可选项);
记号沿用详情页页首那一支(64×8rpx 短横 + 22rpx 间距),
两页共用同一套页面级抬头语言;
② 一张说明白卡:只放城市与费用披露(原"披露 → 发丝线 → 两个条款入口"
三段中的后两段已下移到页尾文档行)。
卡首不放短横色标——短横是页面级记号,区块级留给两个组头的竖条。
先给一句引导再读披露,首屏是"引导 → 声明 → 清单"三层。
卡面走"白卡 + 发丝边 + 紧阴影"(中性 --shadow-card,与首页白卡同值),
把首屏从纸面上拎起来;形状仍是内缩圆角卡,不改成通栏白条 -->
② 一行"圆点 + 小字"的费用披露(本轮由白卡降为纸面行):
只放城市与费用披露,圆点沿用详情页「注意事项」的注意项语言。
先给一句引导再读披露,首屏仍是"引导 → 声明 → 清单"三层,
但"声明"这一层不再占一张卡,服务与价格因此更早露出首屏
(详见 itemlist.wxss 文件头「本轮样式调整」) -->
<view class="page-lead">
<view class="page-accent"></view>
<text class="page-lead-text">请选择相应的服务</text>
@@ -21,44 +20,23 @@
<text class="notice-text">目前已开通北京、天津。费用仅含人工服务费,不含就医费用。</text>
</view>
<!-- 人工客服旁路:紧接披露卡、压在清单上方,翻到清单前就给它一个出口。
原来是页尾那张浅橙"收口卡",现上移为"不想线上预约"的旁路——
语句也从"没有合适的?"(扫完清单后的兜底)换成"不想线上预约?"(未看先问的情形)。
形状与页首披露卡同为内缩圆角卡,但走暖色面。
为什么仍要有这一张暖色面:首页的节奏是"白卡 … 白卡 … 一张浅橙卡"
(陪诊服务收在介绍卡、常用功能收在联系我们);本页原先四张白面
一张暖色面都没有,暖色只剩"线"(竖条 / 按钮环 / 暖橙字),整页比首页轻一档,
这张卡就是补回来的那张"面"。
浅橙底与纸面的填充差只有约 1.03:1,但面积够大、大面积暖色自身可辨,
再配 --brand-line 描边就够,与首页 .quick-item-full 同源、同样不加阴影 -->
<view class="contact-card">
<text class="contact-ask">不想线上预约?</text>
<view class="contact-link" bindtap="goToContact">
<text class="contact-link-text">直接联系人工客服</text>
<t-icon name="chevron-right" size="22rpx" color="#9B4508" />
</view>
</view>
<!-- 服务按"要办的事"分两组,每组一块通栏白底:组头(竖条 + 36rpx 标题 +
一句副题)→ 通栏章线 → 清单,整页由此读成两张一体的价目表。
白底做成"通栏截面":左右 -32rpx 顶到屏幕两侧,左右内距复用容器的 32rpx,
行的可用宽度因此仍是 686rpx、一分未变(原理详见 itemlist.wxss 的 .group)。
副题(原来压在组末的浅橙说明砖)搬到标题下并剥成扁平小字:
位置对了——读到标题就知道这组是给谁的;形状也对了——
它待在组头内部,"卡顶 → 组头 → 章线 → 行"的读法不断。
条目一律一条一行:规则线而已,卡只到"组"这一级。
<!-- 服务按"要办的事"分两组,每组是"组头 + 每项一张白卡":
组头(竖条 + 36rpx 标题 + 暖橙底副题)落在纸面上,下面直接堆叠服务白卡。
分组本轮由"通栏白底章节带"改为"组头在纸面上、卡片逐张堆叠"(原理详见 itemlist.wxss 的 .group)。
白底从分组下移到每一项(.ledger-row),卡内距 28rpx,行宽由 686rpx 降到约 626rpx。
副题(组头内、标题下一句"这组是给谁的")为暖橙说明砖:--brand-soft 底 + --brand-line 描边。
条目本轮改为"每项一张白卡",不再是通栏白底里的规则线行。
每行分两层,不是左右两栏:
第一层 = 名称 +(规格签 · 价格 · 预约),四样同一横向中线,右区整体贴右边缘;
第二层 = 说明,直接放 subtitle 原文(不截任何前缀)、满宽 686rpx,允许折行。
价格从右栏提回名称行,是为了与名称同基线(原先两栏垂直居中,
两行的行里价格会掉到说明那一行的高度);说明因此拿到满宽,
第二层 = 说明,直接放 subtitle 原文(不截任何前缀)、卡内满宽,允许折行。
价格从右栏提回名称行,是为了与名称同基线;说明因此拿到卡内满宽,
「磁共振预约、CT预约、彩超等其他预约」与「送资料/代排队/买药/取报告等一小时陪诊服务」
这两条不再折行。
这两条在卡内满宽下也基本不折行。
带时段的副标题(全天 / 半天陪诊)会折成两行,属预期:说明按原文完整给出,
行高由内容决定,不再靠截文案来换行数。
规格签放在价格左边而不是名称右边:时长与价格本来是一对(规格决定价格),
紧挨着读成「4小时/次 ¥300」;各行的签右侧也因此对齐成一列。
项间分隔线是虚线,横跨整行、拉到卡的内边缘;末行不画,收口交给卡底 -->
预约按钮本轮由"空心胶囊"改为"暖橙环 + --brand-line 软填充"的胶囊(详见 .book-btn) -->
<view class="group" wx:for="{{ groups }}" wx:key="key">
<view class="group-head">
@@ -92,6 +70,19 @@
</view>
<!-- 人工客服旁路(本轮下沉):从"披露卡下方、清单上方"移到"清单之后、文档行之前"。
它是"不想线上预约"的旁路、属兜底——压在清单前会先把不打算自助的用户引走,
也白占首屏;下沉后收口位置与首页「常用功能」收在「联系我们」同构,
仍是本页唯一的暖色面。
形状不变:与首页 .quick-item-full 同源(--brand-soft 底 + --brand-line 描边 + 去阴影) -->
<view class="contact-card">
<text class="contact-ask">不想线上预约?</text>
<view class="contact-link" bindtap="goToContact">
<text class="contact-link-text">直接联系人工客服</text>
<t-icon name="chevron-right" size="22rpx" color="#9B4508" />
</view>
</view>
<!-- 页尾文档行:服务指南 / 用户协议,从页首披露卡下移到此处。
不做卡——清单已由末组的卡边收口,页尾只补一行"文档级"元信息,重量压到最低;
细竖线分隔(与首页场景行、页脚元信息行同一套写法),不用中点字符。
+183 -204
View File
@@ -7,15 +7,15 @@
- 八条服务按"要办的事"分两组,每组是一块通栏白底:组头(竖条 + 36rpx 标题 +
一句 28rpx 的副题)→ 通栏章线 → 清单,整页读起来像两张一体的价目表;
组与组之间是 36rpx 纸面留白,卡的边界由各自的发丝边与紧阴影承担
- 两块白底做成"通栏截面":负外边距 -32rpx 顶到屏幕两侧,左右内距直接复用
页面容器已有的 32rpx——行的可用宽度因此仍是 686rpx,一分未变、零折行风险。
这是"白底 card"敢做的唯一方式:若卡内缩 32rpx 再自带 24rpx 内距,
内容宽会掉到 638rpx,长名称与右区更易挤到折行(详见 .group)。
代价是形不再是"浮起的小卡"而是"一条白色章节带",圆角因此为 0
(满宽块的圆角会切在屏幕边上);与页首 .notice 那张内缩圆角卡是两种角色两种形
- 副题是扁平小字,不用浅橙砖:浅橙砖会和下一组的强组头贴在一起,
两个重元素相邻反而糊掉组界;也不留在橙砖形式,是因为它必须待在组头内部,
让"卡顶 → 组头 → 章线 → 行"这条读法不断
- 分组本轮由"通栏白底章节带"改为"组头 + 每项一张白卡":
组头(竖条 + 标题 + 暖橙底副题)落在纸面上,下面直接堆叠服务白卡(详见 .group / .ledger-row)。
白面从分组下移到每一项,行宽由 686rpx 降到约 626rpx(卡内距 28×2 + 边 2×2 = 60);
最长名称「出入院代办」约 160rpx、可用约 220rpx,仍容得下。
放弃通栏白带的原因:那是为"一组一张表"选的形,本轮要"每项一张卡",白带与卡会叠成两层底
- 副题本轮回到"暖橙淡底块"(按用户要求):占组头内一行,--brand-line 底 + --brand-ink 字。
沿革:浅橙砖(压在组末)→ 扁平小字(搬到标题下)→ 现在暖橙底块(仍在标题下)。
之前否掉浅橙砖是因为它与下一组强组头相贴、糊掉组界;本轮组头在上、卡片在下,
且副题收在组头内部,不再夹在两组之间,故可回到有底的形
- 条目一律一条一行:只有规则线没有卡片(卡只到"组"这一级)。
原先是 2×2 价目表,但半栏只有 317rpx——说明句要折行、名称要被迫缩短,
而这份数据里真正能横向比价的只有第一组(全天/半天/夜间)三格,代价不值,故改单行
@@ -25,29 +25,43 @@
- 项间虚线挂在 .ledger-row 上、通栏到卡的内边缘;每组最后一行不画
(.ledger-row:last-child)——卡的底边已经替它收了口,留着会叠出
"虚线 + 28rpx + 卡边发丝线"的双线。章线开、卡边收,每章仍是一张闭合的表
- 按钮走"空心胶囊":3rpx --brand-strong 环 + 满圆角 + 暖橙字(纸面 6.10:1),
无填充无阴影,按下填 --brand-line。之所以不用填充,是因为按钮挪到价格左边后
与规格签撞了形——签是"浅橙底 + 小圆角",按钮若也做成"浅橙底 + 圆角",
同一行就出现两个同形物体,读起来是两个标签,分不清哪个能点。
现在签 = 暖橙小字、按钮 = 满圆角空心环,一行只剩一个填充物。
字重也从 700 降到 500:可点性改由环承担,字不必再靠粗度喊话
(代价是 500 在部分 Android 上会落回常规,详见 .book-btn 注释)
- 价格按用户要求弱化:--muted + 字重 500(本页对 §2.1「价格数字」的例外,已登记)
- 按钮本轮改"软填充胶囊"(按用户要求):3rpx --brand-strong 环 + --brand-line 填充 + --brand-ink 字。
填充之所以现在才成立:上一版否掉它的原因是"按钮与规格签同形相撞",而本轮签已删底,根因消失;
但环不能撤——--brand-line 填充单独落在白卡上只有约 1.1:1、边界几乎不可见,3:1 非文本对比要由环承担。
字重 500 不变(可点性由"环 + 填充 + 胶囊轮廓"三重承担)
- 价格本轮由 --muted 提到 --ink-2(详见 .price 注释);字重仍 500
- 字号阶梯:正文对齐 agreement 页的 28rpx,本页据此排成
组标题 36 / 名称 · 价格 32 / 按钮 30 / 副题 · 说明 · 披露 · 入口 · 客服卡 28 /
规格签 26(rpx)。比原来整页抬了一档,是为老人可读性;
全页最小字号因此从 24rpx(12px) 升到 26rpx(13px)
- 形状锁定:页首说明卡与客服卡 28rpx(与首页白卡 / .quick-item-full 同值)、
预约按钮 28rpx(= 高 56rpx 的一半,成胶囊)、
规格签 6rpx(已按用户要求去掉左竖条)、分组白底 0(通栏块);其余圆角一律不做
组标题 36 / 名称 · 价格 32 / 按钮 30 / 副题 · 说明 · 入口 · 客服卡 28 / 规格签 · 披露 26(rpx)。
比原来整页抬了一档,是为老人可读性;全页最小字号 26rpx(13px)
- 形状锁定:客服卡 28rpx(与首页白卡 / .quick-item-full 同值)、服务白卡 24rpx、
预约按钮 28rpx(= 高 56rpx 的一半,成胶囊)、组头副题块 14rpx;规格签本轮已去底去圆角;其余圆角一律不做
- 白面的托形语言全页一套,且与首页一致:白面走 2rpx --line + --shadow-card
(中性暖墨 0 2rpx 10rpx rgba(63,43,25,.07));客服卡那张浅橙面走 2rpx
--brand-line、去阴影(与首页 intro-card / quick-item-full 相同)。
全页因此仍没有彩色阴影
- 与首页的对齐账(本轮):① 区块竖条回到首页同一支(8×36,此前被放大到 12×48);
② 补一张浅橙客服卡(页首披露卡下方、清单上方),把"暖色只剩线、没有面"这一档补回来。
落差只剩一处,且是分工使然:首页「立即预约」是实心 --brand-strong 胶囊(1 个主 CTA),
本页「预约」是 3rpx 空心环(8 个并列动作)——8 个实心橙排一列会撞 §2.1,故不跟 */
② 补一张浅橙客服卡(本轮由"披露下方"下沉到"清单之后"),把"暖色只剩线、没有面"这一档补回来。
与首页「立即预约」的落差本轮缩小:首页是实心 --brand-strong 胶囊(1 个主 CTA),
本页改为"暖橙环 + --brand-line 软填充"(8 个并列动作)——软填充给足分量,
又不至把 8 格做成 8 块实心橙(那会撞 §2.1);主 CTA 仍只有首页那一个 */
/* ===== 本轮样式调整(压缩首屏 + 每项一张卡 + 软填充按钮)=====
目标承接首页讨论的"缩短下单路径":这是一张价目单,用户进来该尽快看到"有哪些、多少钱"。
第一轮(结构压缩):
① 披露(.notice)由白卡降为纸面一行"圆点 + 小字",文字仍 --ink-2(费用披露不降 --muted);
② 客服卡(.contact-card)由"披露下方、清单上方"下沉到"清单之后、文档行之前";
③ 价格由 --muted 提到 --brand-strong(色板默认「价格数字」用途);④ 规格签删底;⑤ 按钮补透明热区(::after 外扩 6rpx)。
第二轮(按用户要求:填充按钮 + 每项一张卡 + 副题暖橙底):
⑥ 分组由"通栏白底章节带"改为"组头 + 每项一张白卡":组头落在纸面上,下面堆叠服务白卡
(--white + 2rpx --line + 24rpx 圆角 + --shadow-card,卡间距 20rpx),
撤销原通栏白底与虚线行(白带与卡会叠两层底)。代价:行宽 686 → 约 626rpx;
⑦ 按钮由"空心胶囊"改为"软填充胶囊":保留 3rpx --brand-strong 环,填 --brand-line,字 --brand-ink。
填充单独落在白卡上只有约 1.1:1,故环不能撤(3:1 由环承担);已在 DESIGN.md §2.1 登记修订;
⑧ 副题(.group-sub)改暖橙说明砖:--brand-soft 填充 + 2rpx --brand-line 描边 + --brand-ink 字。
填充走 --brand-soft 而非 --brand-line——DESIGN.md §四.5 说明砖填充必须中性、--brand-line 仅作描边,
落纸面靠描边托形(与客服卡同一配方);
全页仍无新色相、无色相外的阴影。注意:暖色面本轮增至多处(副题块 ×2 + 8 个按钮 + 客服卡),
若真机觉得过重,下一顺位是把按钮退回空心、或副题撤底 */
page {
/* 配色令牌已上移到 app.wxss(全站唯一来源,改配色只改那一处),本页不再留副本;
以下两段注释只作沿革留档。
@@ -76,10 +90,11 @@ page {
字号 32rpx/700/--ink:本页是价目单,真正的主结构是两个 36rpx 的组标题,
这行是导语,刻意压在组标题下一档、不跟它抢层级;但比 28rpx 的副题档重,
落在纸面上仍读得出"页面从这里开始"。
位置在说明卡之上、纸面上:先给一句引导,再读卡里的城市与费用披露,
位置在披露行之上、纸面上:先给一句引导,再读那句城市与费用披露,
首屏因此是"引导 → 声明 → 清单"三层,而不是一上来就撞条款 */
/* 首屏前言区(引导 → 披露卡 → 客服卡)三处上下间隙由 32 收到 24rpx:
前言是页级说明,比下面的章节(.group 的 36rpx 纸面留白)紧一档是刻意的 */
/* 首屏前言区(引导 → 披露行)两处上下间隙由 32 收到 24rpx:
前言是页级说明,比下面的章节(.group 的 36rpx 纸面留白)紧一档是刻意的;
客服卡本轮已下沉到清单之后,不再属于首屏前言 */
.page-lead {
margin-top: 24rpx;
}
@@ -100,35 +115,40 @@ page {
letter-spacing: 1rpx;
}
/* ===== 说明卡:页首第二块 =====
页内大标题与导航栏的「陪诊服务」重复,不重复写;
说明做成一张白卡(发丝边 + 紧阴影),卡内只放一句关键披露——
原"披露 → 发丝线 → 两个条款入口"三段里的后两段已下移到页尾文档行。
圆角与阴影按用户要求对齐首页的白卡语言:28rpx + 中性 --shadow-card
(首页带阴影的白卡 .assist-card / .quick-item 都是这两个值)。
形状仍是"内缩圆角卡",不改通栏白条:上方 24rpx 纸面缺口只有配圆角才成立——
方角通栏顶上留一道纸,会读成"这条被切掉了一截" */
/* ===== 费用披露:纸面上一行"圆点 + 小字" =====
沿革:白卡 → 本轮降为纸面一行(降因见文件头「本轮样式调整」①)。
本页是价目单,首屏应尽快让服务与价格露出来,一张说明白卡白占约 55rpx。
形状:去掉白底 / 发丝边 / 圆角 / 阴影,只留"圆点 + 一行小字";
圆点沿用详情页「注意事项」与指南页的注意项语言,说明这是"须知"而非普通说明。
文字仍给 --ink-2:费用披露不是可有可无的说明,不降到 --muted(沿用原判断);
字号 28 → 26rpx,随"降为一行"一起收轻,仍落在全页最小字号档 */
.notice {
display: flex;
align-items: flex-start;
margin-top: 24rpx;
/* 上下内距对称:原先 20/8 是给卡底的入口行让位,入口行撤走后收回 24/24 */
padding: 24rpx 28rpx;
background: var(--white);
border: 2rpx solid var(--line);
border-radius: 28rpx;
box-shadow: var(--shadow-card);
}
/* 这句是费用披露,不是可有可无的说明,所以白卡上给 --ink-2 而不是 --muted */
/* 圆点:12rpx 实心暖橙,抬到约首行字高的中线,与不折行的首行对齐 */
.notice::before {
content: '';
flex-shrink: 0;
width: 12rpx;
height: 12rpx;
margin: 14rpx 12rpx 0 2rpx;
border-radius: 50%;
background: var(--brand-strong);
}
.notice-text {
display: block;
font-size: 28rpx;
font-size: 26rpx;
color: var(--ink-2);
line-height: 1.7;
}
/* ===== 页尾文档行 =====
服务指南 / 用户协议两枚链接,从页首披露卡下移到这里。
不做卡:清单已由末组的卡边收口,页尾只补一行"文档级"元信息,重量压到最低。
不做卡:清单已由末张服务卡收口,页尾只补一行"文档级"元信息,重量压到最低。
细竖线分隔(2rpx 宽 × 20rpx 高,--sep #E5DACC),与首页场景行、页脚元信息行
同一套写法,不用中点字符(一行多点违规)。
文字走 --brand-ink + 700——与上方说明的 --muted 常规字重拉开,读成"能点的动作"
@@ -167,48 +187,23 @@ page {
background: var(--sep);
}
/* ===== 分组:每组一块通栏白底 =====
白面走"发丝边 + 紧阴影",阴影与说明卡、与首页白卡同一个 --shadow-card(中性暖墨)。
组头做成"表头":竖条 + 标题,下面接一句副题(这组是给谁的),
再压一条通栏章线,线下面直接是清单第一行——"章线 → 行"的读法不断。
白底卡的做法:左右 -32rpx 负外边距顶到屏幕两侧,再用等量 padding 补回来。
目的只有一个——让白面变宽而不让行宽变宽:行仍落在容器原有的 686rpx 上。
这是唯一可行解,因为这一行已经没有余量:
686 − 16(右区外边距) − 122(最长签) − 12 − 104(价格槽) − 24 − 128(按钮)
= 280rpx 可用;现最长名称「出入院代办」约 160rpx,余量约 120rpx。
卡若内缩 32rpx 再自带 24rpx 内距,仍会白吃 48rpx 行宽、压缩名称余量,故继续走通栏。
代价是圆角为 0——满宽块的圆角会切在屏幕边上,留下纸色缺口。
组界:卡与卡之间只留 36rpx 纸面。原先是 68rpx 的"两条通栏线夹白",
现在两侧各有发丝边与阴影托形,不需要那么宽的留白来分段;
36rpx 也够把两张卡的边线读成"上一张的边 + 纸面 + 下一张的边",
而不会读成一条粗双线。卡上下的 28rpx 内距给组头与末行留出呼吸,
它比原来的组界留白(68rpx)小,净高度因此只增约 24rpx/组。
对比度:行内所有文字与色值由纸面移到了白卡上,对比度各高一档——
--muted 5.28→5.69:1、--brand-ink 6.89→7.31:1、--brand-strong 4.89→5.18:1。
下文各处标注的"纸面上 x:1"是沿革里的历史值,落到白卡上只增不减,
AA 与"非文本 3:1"的结论全部不变,因此不再逐处改写 */
/* ===== 分组:组头 + 每项一张白卡(本轮改,原为通栏白底章节带) =====
组头(竖条 + 标题 + 暖橙底副题)落在纸面上,下面直接堆叠服务白卡。
白面(--white + 2rpx --line + --shadow-card)本轮下移到每一项 .ledger-row 上,
分组自身不再有底色 / 边线 / 阴影——否则白带与白卡会叠成两层底。
代价:行宽由 686(通栏)降到约 626rpx(卡内距 28×2 + 边 2×2 = 60);
最长名称「出入院代办」约 160rpx、可用约 220rpx,仍容得下。
组与组之间只留 36rpx 纸面;
组头到第一张卡的间距由副题块的下沿 + 卡的 margin-top 给出(不再靠章线) */
.group {
box-sizing: border-box;
margin: 36rpx -32rpx 0;
padding: 28rpx 32rpx;
background: var(--white);
border-top: 2rpx solid var(--line);
border-bottom: 2rpx solid var(--line);
box-shadow: var(--shadow-card);
margin: 36rpx 0 0;
}
/* 表头 = 标题行 + 副题 + 章线。三样合成一块,章线因此落在副题之下、紧贴第一行。
全页三条线分工固定(都落在白卡上,比落在纸面时略清楚一点):
卡边 2rpx solid --line ← 最轻,只托卡的边界
章线 3rpx solid --sep ← 最重
行线 3rpx dashed --sep ← 同宽同色,但虚线读起来轻
行线色 --sep 比卡边色 --line 深,所以实线的重音给章线(--sep 3rpx solid)、
轻音给行线(--sep 3rpx dashed),层级交由实/虚区分,不靠继续加深线色。
原先还有第四条"页脚 2rpx solid --line"收尾;页脚已撤销(客服卡上移到披露卡下),
页面由末组的卡边(--line 发丝边)收尾,线种仍是三 */
/* 组头 = 竖条行 + 暖橙底副题。本轮起组头落在纸面上(分组不再是白带)。
原"通栏章线"撤销:卡片自身已有边线与阴影分隔,再压章线会与第一张卡的顶边叠成双线。
组头与第一张卡之间的间距由副题块的下沿 + 卡的 margin-top 给出,不再靠章线分段 */
.group-head {
padding-bottom: 18rpx;
border-bottom: 3rpx solid var(--sep);
padding-bottom: 0;
}
.group-head-row {
@@ -216,14 +211,23 @@ page {
align-items: center;
}
/* 副题:原先压在组末的浅橙说明砖挪到这里,剥掉底、描边与阴影,只留一行小字。
扁平处理是刻意的——它必须待在组头内部,才能在"卡顶 → 组头 → 章线 → 行"
这条读法中间不插入第二个方块 */
/* 副题:暖橙说明砖(按用户要求加底,配方对齐 DESIGN.md)。
沿革:浅橙砖(压在组末)→ 扁平小字(搬到标题下)→ 暖橙砖(仍在标题下)。
配方与客服卡同源:--brand-soft 填充 + 2rpx --brand-line 描边——
DESIGN.md §四.5 说明砖填充必须中性(--white/--paper/--brand-soft),--brand-line 仅作描边;
--brand-soft 落纸面只有约 1.03:1,砖形由描边托出(§2.3 浅橙块落纸面的既定做法)。
字走 --brand-ink(浅橙底 5.96:1,过 AA),不用 --muted。
圆角 14rpx 走小圆角族(卡 24rpx、胶囊按钮 28rpx,三者分层)。
文案由 js 收在 22 字内,砖不折行 */
.group-sub {
display: block;
margin-top: 14rpx;
margin-top: 16rpx;
padding: 12rpx 20rpx;
background: var(--brand-soft);
border: 2rpx solid var(--brand-line);
border-radius: 14rpx;
font-size: 28rpx;
color: var(--muted);
color: var(--brand-ink);
line-height: 1.7;
}
@@ -251,10 +255,11 @@ page {
color: var(--ink);
}
/* ===== 价格:按用户要求弱化,只作信息展示 =====
--muted + 字重 500:比说明只靠字号(32 vs 26rpx)与字重分开一档,
既不抢名称的重心,也不走 --brand-strong。
这是本页对 DESIGN.md §2.1「价格数字」用途的例外,已在页首注释登记。
/* ===== 价格:决策数字,走主色(DESIGN.md §2.1 默认用法) =====
沿革:--muted + 500(刻意弱化)→ --ink-2(提一档)→ --brand-strong(回到色板默认)。
§2.1 色板表里「价格数字」本就列在 --brand-strong 名下,白卡 4.94:1 过 AA;
价格是全页唯一的决策数字,主色让它与按钮环同频——扫价即扫 CTA。
字重仍 500、字号不变,只动字色。
min-width 104rpx + justify-content:flex-end 是"固定槽":
各行的价格右边缘对齐成一列,同时把左边规格签的右边缘也钉在同一位置。
不固定的话,3 位数价格(约 80rpx)与 4 位数(约 100rpx)差 18rpx,
@@ -270,76 +275,65 @@ page {
.price-sym {
font-size: 26rpx;
font-weight: 500;
color: var(--muted);
color: var(--brand-strong);
}
.price-num {
margin-left: 2rpx;
font-size: 32rpx;
font-weight: 500;
color: var(--muted);
color: var(--brand-strong);
}
/* ===== 规格签:暖橙小字(按用户要求去掉左竖条) =====
沿革:整圈描边 → 4rpx 左竖条 + 浅橙底(色标式)→ 现在只剩字 + 一层极浅的底。
去竖条的原因:页面上已经有一套竖条语言——两个组头的 8×36rpx 实心竖条。
每行再插一道 4rpx 小竖条,全页竖向重音就从 2 处涨到 10 处,与组头抢同一个记号。
签退回纯文字后,每行的竖条只剩组头一处,记号重新变回"章"级。
代价要记住:底仍是 --brand-soft,它落在白卡上只有 1.08:1(纸面上 1.02:1),
实际都看不出来——签现在是"暖橙字 + 一层几乎不可见的暖底",
辨识全部由字色承担。这也正是它当初选 --brand-ink(白卡 7.31:1)而不是
--brand-strong 的原因。
若日后想要一个看得见的签形,两条路:
① 底换 --brand-line(白卡上 1.26:1,比现在明显);② 底整个删掉,承认它就是一段暖色小字。
位置在价格左边(与价格成对、整体右对齐),因此补 flex-shrink:0
与 white-space:nowrap,保证各行的签不被压扁、右边缘对齐成一列 */
/* ===== 规格签:暖橙小字,无框无底(本轮删底) =====
沿革:整圈描边 → 4rpx 左竖条 + 浅橙底(色标式)→ 只剩字 + 一层极浅的底 → 现在连底也删。
删底原因:那层 --brand-soft 在白卡上只有 1.08:1,肉眼几乎看不见——"看得见的签形"
与"根本不存在的签形"之间骑墙,不如干脆承认它就是一段暖色小字。
本页是"名称 + 说明"的文件感版式,一行已有"价格 + 按钮"两处右区物件,
再多一个若有若无的色块只是噪音。
删底后签的辨识全部由字色承担,故仍用 --brand-ink(白卡 7.31:1)而非 --brand-strong。
位置在价格左边(与价格成对、整体右对齐),补 flex-shrink:0 与 white-space:nowrap
保证各行的签不被压扁、右边缘对齐成一列 */
.unit-chip {
flex-shrink: 0;
white-space: nowrap;
padding: 2rpx 8rpx;
border-radius: 6rpx;
background: var(--brand-soft);
font-size: 26rpx;
color: var(--brand-ink);
letter-spacing: 1rpx;
line-height: 1.3;
}
/* ===== 清单:一条一行,只有规则线没有卡片(卡只到"组"这一级) ===== */
/* ===== 清单:每项一张白卡(本轮改,卡从"组"降到"项"这一级) =====
列方向堆叠;项间纸面由相邻选择器 .ledger-row + .ledger-row 给出(不用 gap,与全站一致)。
margin-top 24rpx 拉开"副题砖 → 第一张卡":砖自带描边、比裸文字重,
20rpx 会显得贴,24rpx 退半步;仍小于组间 36rpx,保住"组头带着它的卡片"的从属感 */
.ledger {
display: flex;
flex-direction: column;
margin-top: 24rpx;
}
/* 一行分两层,不是左右两栏:
第一层 .row-head —— 名称在左;右区(规格签 → 价格 → 预约)整体贴右边缘,
四样对齐在同一横向中线上;
第二层 .row-desc —— 说明单独成行(放 subtitle 原文,内容可折行),满宽 686rpx。
为什么把价格从右栏提回名称行、说明改成独占一行:
① 价格与名称同基线,扫价格时眼睛不用跨行去找。原先两栏是行内垂直居中,
两行的行里价格会落到说明那一行的高度上,名称与价格被拆开;
② 说明因此从 436rpx 拿到满宽 686rpx,全页少折两行——按 28rpx 估算,
「磁共振预约、CT预约、彩超等其他预约」约 504rpx、
「送资料/代排队/买药/取报告等一小时陪诊服务」约 588rpx,原先都在 436rpx 里折成两行;
③ 去掉"右栏"这一层后,一行只回答一件事:上行是"是什么 / 买多久 / 多少钱 / 就选它",
下行是补充说明。
代价:名称行的行盒被按钮撑开(按钮 56rpx,比名称行本身还高),
每行比原先的两栏版高约 11rpx。
上下内距与项间分隔虚线都放在这一层,虚线因此横跨整行、一直拉到卡的内边缘
(组变成白底卡之后,虚线不再顶到屏幕边——卡本身已经框住了这一列)。
每组最后一行的虚线由 :last-child 撤掉:组的底边已经由卡的发丝边收口,
留着会叠成"虚线 + 卡内距 28rpx + 卡边发丝线"的双线。
于是每章的读法是:卡顶发丝边 → 组头 → 章线 → 各行(行间虚线)→ 卡底发丝边,
章线开、卡边收,仍是一张闭合的小表 */
/* 一行 = 一张白卡(本轮改,原为通栏白底里的虚线行)。
卡形:--white + 2rpx --line + 24rpx 圆角 + --shadow-card,内距 28rpx。
行内分两层,不是左右两栏:
第一层 .row-head —— 名称在左;右区(规格签 → 价格 → 预约)整体贴右边缘,同一横向中线;
第二层 .row-desc —— 说明独占一行,卡内满宽(约 570rpx = 626 − 28×2),放 subtitle 原文、允许折行。
保留"价格与名称同基线"的旧决定:扫价格时眼睛不用跨行去找;说明因此拿到卡内满宽、长句少折行。
虚线行分隔本轮撤销:卡与卡之间已有纸面 + 边线分隔,行内不再画线
(原"行线用 --sep 3rpx dashed 承担行边界"的整套说明随之作废)。
圆角分层:服务卡 24rpx / 组头副题块 14rpx / 胶囊按钮 28rpx */
.ledger-row {
padding-top: 32rpx;
padding-bottom: 32rpx;
border-bottom: 3rpx dashed var(--sep);
box-sizing: border-box;
padding: 28rpx;
background: var(--white);
border: 2rpx solid var(--line);
border-radius: 24rpx;
box-shadow: var(--shadow-card);
}
/* 末行不封底:收口交给卡底的发丝边,避免双线 */
.ledger-row:last-child {
border-bottom: none;
/* 卡间距:相邻选择器给 20rpx 纸面,不用容器的 gap(与全站一致) */
.ledger-row + .ledger-row {
margin-top: 20rpx;
}
/* 第一层:名称 + 右区。名称 flex:1 吸走全部余量,右区因此被顶到右边缘,
@@ -350,13 +344,12 @@ page {
}
/* 名称给 min-width:0 兜底:过长时折行,不会把右区挤出去。
字号 30 → 32rpx(与价格数字同档),字距收到 0——
32rpx 的粗体中文本来就不需要额外字距,最长那行能退回约 11rpx。
可用宽度约 280rpx:
686 − 16(本行右区外边距) − 122(最长签「8小时/次」,已去左竖条)
− 12 − 104(价格固定槽) − 24(与按钮的间距,按用户要求由 12 加到 24) − 128(按钮)。
最长名称「出入院代办」约 160rpx,余量约 120rpx。
真机若仍折行,下一顺位是把 .price-num 从 32rpx 降到 28rpx(约让出 8rpx) */
字号 32rpx(与价格数字同档),字距收到 0——32rpx 的粗体中文不需要额外字距。
可用宽度约 220rpx(本轮卡片化后行宽由 686 降到约 626rpx,右区占用约 406rpx):
626 − 16(本行右区外边距) − 122(最长签「8小时/次」)
− 12 − 104(价格固定槽) − 24(与按钮的间距) − 128(按钮)。
最长名称「出入院代办」约 160rpx,余量约 60rpx;真机若折行,
下一顺位是把 .price-num 从 32rpx 降到 28rpx(约让出 8rpx) */
.row-name {
flex: 1;
min-width: 0;
@@ -377,60 +370,37 @@ page {
margin-left: 16rpx;
}
/* 说明:独占一行,满宽。
虚线用 --sep(分隔线专用,比 --line 深一档,浅橙底上也能看见)。
线宽 3rpx 而非 2rpx:2rpx 的虚线在真机强光下几乎看不见,
加粗到 3rpx 让它稳稳承担"行边界",不靠加深线色来解决 */
/* 说明:卡内独占一行、满宽(约 570rpx),允许折行。
margin-top 8rpx:卡片化后名称与说明同处 28rpx 内距的卡内,
2rpx 是行版式时代的紧凑值,两行会贴死;提到 8rpx,卡内上下呼吸才匀 */
.row-desc {
display: block;
margin-top: 2rpx;
margin-top: 8rpx;
font-size: 28rpx;
color: var(--muted);
line-height: 1.7;
}
/* ===== 预约:空心胶囊(暖橙环 + 暖橙字) =====
沿革:描边版 → 实心 --brand-strong → 软色块 → 现在这版空心胶囊,第四次调整。
为什么又回到"无填充":上一版软色块本身没问题,问题是它挪到价格左边之后,
和紧邻的规格签撞了形——签是"浅橙底 + 暖橙字 + 小圆角",按钮也是
"浅橙底 + 暖橙字 + 圆角",两个同形物体在同一行相距 450rpx,读起来像两个标签。
签和按钮的身份不同:签是标签(静态、可无边界),按钮是控件(必须一眼看出能点)。
两者只能靠"形"分开,靠"深浅"分不开。于是这里把按钮做成一行里唯一的"环":
签 = 浅橙底 + 暖橙字,无框,也不再有左竖条;
按钮 = 满圆角空心环,无底。
同时它也不再是行内第二个浅色实心块,一行只剩一个填充物(签),主次不再打架。
为什么是满圆角:圆角 6rpx 是签的语言,12rpx 与签仍在同一族;
28rpx(= 高度 56rpx 的一半)让它成为胶囊,轮廓与签一眼可分。
为什么环 3rpx 而不是 2rpx:按钮是本页唯一的转化入口,56rpx 高度下 2rpx 的环
在真机强光里发虚;3rpx 的 --brand-strong 在纸面上 4.66:1,稳稳过非文本 3:1。
字走 --brand-ink(纸面上 6.10:1),比环的 --brand-strong(4.66:1)再稳一档:
环承担"这是动作"的色,字承担"读得清"的对比度。
去掉填充与阴影:原先的暖色紧阴影是为了把 1.02:1 的浅橙底托出形状,
没有底就不需要拖形,8 圈阴影一并撤掉,整页顺带更轻。
按下把胶囊填上 --brand-line:同色阶、可感知(1.19:1→填充可见),
暖橙字在其上 5.14:1,仍过 AA。不引入新色。
注意"淡"仍不能走"提亮填充 + 白字"——白字对 #EA6A2E 只剩约 3.2:1、
对 #F97316 约 2.8:1,都不达 AA。
与 DESIGN.md §3 的禁用态不撞:禁用是 --muted 字 + --sep 描边 + 透明底,
本按钮是暖橙字 + 暖橙环,字色与环色两个维度都不同,不会被读成不可点。
真机若觉得环太空、抓力不够,下一顺位是只把 background 换成 --brand-line
(就是现在的按下色),形不动——那是一步就能上的台阶,不必换风格。
字重按用户要求 700 → 500。要记住 500 在中文里不稳定:iOS 的苹方有 Medium(500),
但不少 Android 的系统中文只有"常规/粗体"两档,500 会落回常规——同一份代码
在两种机器上不是同一个结果。敢降,是因为这个按钮的可点性已经不由字重承担了:
3rpx 的环 + 满圆角轮廓已经足够说明"这是一个控件",字只负责读得清。
若日后发现轮廓的抓力也不够,优先把字重调回 700,而不是加深字色。
box-sizing 保持 border-box:3rpx 的环画在框内,外框尺寸不变(128×56rpx)。
尺寸按用户要求再收一档:高 64 → 56rpx(28px),圆角随高度取半 28rpx。
最小宽 128rpx、左右内距 24rpx 不变;字号 30rpx 不并入说明那一档(28rpx)。
副作用是行高跟着降:按钮是 .row-head 里最高的元素,64 → 56rpx 之后
每行随之矮约 8rpx,8 行共矮约 64rpx,正好抵掉上一轮"说明改满宽"带来的一部分增高。
代价是 28px 明显低于 iOS 44px 的建议触控高度,这是"视觉更轻"换来的。
要让手指更容易点中而视觉不变,可以加一个透明伪元素(::after,四边各外扩 6rpx)
把热区撑回 68rpx,形不动——需要时再加,别提前加。
水平位置由 .row-side 决定,与左侧价格之间的 24rpx 由 margin-left 给出
(按用户要求由 12rpx 加大);垂直位置由 .row-side 的 align-items:center 居中 */
/* ===== 预约:软填充胶囊(暖橙环 + --brand-line 填充 + 深字)(本轮改) =====
沿革:描边 → 实心 --brand-strong → 软色块 → 空心胶囊 → 现在软填充胶囊,第五次调整。
本轮改填充(按用户要求):填充之所以现在才成立——上一版否掉它的原因是
"按钮与规格签同形相撞"(签 = 浅橙底 + 小圆角),而本轮签已删底(见 .unit-chip),
相撞的根因消失,一行里"两个浅色实心块"只剩按钮一个。
但环不能撤:--brand-line 填充单独落在白卡上只有约 1.1:1,边界几乎不可见,
"非文本 3:1"必须由 3rpx --brand-strong 环承担(白卡上 5.18:1,稳)。
于是形 = 3rpx --brand-strong 环 + --brand-line 填充 + 满圆角 28rpx(= 高 56rpx 的一半)。
为什么环 3rpx 而非 2rpx:按钮是本页唯一的转化入口,56rpx 高度下 2rpx 的环在强光里发虚。
字走 --brand-ink(白卡上 7.31:1):填充是浅橙,深字在其上对比足够;
不换白字——白字在 --brand-strong/#B8520A 上大概率不达 AA(配色沿革里提过)。
按下:整个胶囊 opacity 0.85(与全站文字链按下同族),不再改填色——填色已是默认态。
不引入新色;8 个软填充不构成"同类实心色块枚举"问题(填的是 --brand-line 软色阶、面积极小,
与首页那一个 --brand-strong 实心主 CTA 仍是主次两档)。
尺寸 / 热区沿用上一轮:高 56rpx、最小宽 128rpx、::after 外扩 6rpx 把触控撑到 68rpx。
字重 500 不变(可点性由"环 + 填充 + 胶囊轮廓"三重承担,不再依赖字重);
box-sizing 保持 border-box,3rpx 环画在框内(128×56rpx 外框不变)。
水平位置由 .row-side 决定,与价格之间的 24rpx 由 margin-left 给出 */
.book-btn {
position: relative;
display: flex;
align-items: center;
justify-content: center;
@@ -441,13 +411,24 @@ page {
margin-left: 24rpx;
border: 3rpx solid var(--brand-strong);
border-radius: 28rpx;
background: transparent;
background: var(--brand-line);
flex-shrink: 0;
transition: background-color 0.15s ease;
transition: opacity 0.15s ease;
}
.book-btn:active {
background: var(--brand-line);
opacity: 0.85;
}
/* 透明热区:高 56rpx(28px) 低于 iOS 44px 建议,四边各外扩 6rpx 把热区撑到 68rpx,
视觉与形完全不变。absolute 脱离文档流,不占布局、不推挤右区其它元素 */
.book-btn::after {
content: '';
position: absolute;
top: -6rpx;
right: -6rpx;
bottom: -6rpx;
left: -6rpx;
}
.book-btn-text {
@@ -460,22 +441,20 @@ page {
/* ===== 人工客服:浅橙旁路卡 =====
它就是首页「常用功能」区块尾部的「联系我们」卡(.quick-item-full),
同一套做法:--brand-soft 底 + 2rpx --brand-line 描边 + 去阴影 + 28rpx 圆角。
位置:紧接页首披露卡、压在清单上方。原是守在页尾的"收口卡",
现上移为"不想线上预约"的旁路——页尾因此不再设卡,由末组的卡边收尾。
文案是本页的"情形 + 动作"两段式:muted 情形问句 + 暖橙动作链,
情形从"没有合适的?"(扫完清单后的兜底)换成"不想线上预约?"(未看先问)。
为什么保留这一张暖色面:首页的节奏是"白卡 … 白卡 … 一张浅橙卡收口"
(陪诊服务收在介绍卡上,常用功能收在联系我们上)。本页原先 4 张白面
一张暖色面都没有,暖色只剩"线"——竖条、按钮环、暖橙字,
整页因此比首页轻一大截;这张卡就是补回来的那一张"面"。
位置(本轮调整):从"披露下方、清单上方"下沉到"清单之后、文档行之前"(见文件头 ②)。
它是"不想线上预约"的旁路、属兜底——压在清单前会先把不打算自助的用户引走,也白占首屏;
下沉后收口位置与首页「常用功能」收在联系我们同构。
文案是本页的"情形 + 动作"两段式:muted 情形问句 + 暖橙动作链。
浅橙底与纸面的填充差只有约 1.03:1,但面积够大,大面积暖色自身可辨,
再配 --brand-line 描边就够,与首页那张一样不加阴影。
上距 24rpx 与页首两层之间的节奏同值;到清单的 36rpx 由后面 .group 自己给出 */
暖色面本轮已不止它一处(副题块 ×2 + 8 个按钮),它是其中面积最大的一块;
仍用 --brand-soft(最浅一档)而非 --brand-line,以守住"这块不与按钮、副题抢"的层次。
上距 36rpx 与组间留白同值(它现在跟在末组之后,读法上与"再起一块"一致) */
.contact-card {
display: flex;
align-items: center;
justify-content: center;
margin-top: 24rpx;
margin-top: 36rpx;
padding: 24rpx 28rpx;
background: var(--brand-soft);
border: 2rpx solid var(--brand-line);
+2
View File
@@ -580,6 +580,8 @@ Page({
})
},
// 本页含就诊人姓名 / 手机号 / 身份证号与订单号,转发卡片不指向本页,统一落到首页;
// 也不提供朋友圈分享——朋友圈只能分享当前页 URL,会把订单页地址带出去
onShareAppMessage() {
return {
title: '暖橙陪诊 - 专业陪诊服务',
+2 -2
View File
@@ -56,9 +56,9 @@ page {
.status-chip {
display: inline-flex;
align-items: center;
padding: 6rpx 18rpx;
padding: 4rpx 16rpx;
border: 2rpx solid transparent;
border-radius: 12rpx;
border-radius: 10rpx;
font-size: 24rpx;
font-weight: 700;
letter-spacing: 1rpx;
+7 -2
View File
@@ -97,14 +97,19 @@ page {
color: var(--brand-ink);
}
/* ===== 记录列表 ===== */
/* ===== 记录列表 =====
卡间距用相邻兄弟 margin,不用 flex 的 gap:
gap 在部分微信基础库 / 老设备上不生效,失效后几张卡会挨成一条白条 */
.record-list {
display: flex;
flex-direction: column;
gap: 24rpx;
margin-top: 12rpx;
}
.record-card + .record-card {
margin-top: 24rpx;
}
.record-card {
padding: 28rpx 28rpx 24rpx;
border-radius: 28rpx;
+10
View File
@@ -232,5 +232,15 @@ Page({
saving: false
})
})
},
// 本页是就诊人档案表单(姓名 / 手机号 / 身份证号),转发卡片不指向本页,
// 统一落到首页,避免好友打开一个需要登录的空表单;
// 也不提供朋友圈分享——朋友圈只能分享当前页 URL,会把档案页地址带出去
onShareAppMessage() {
return {
title: '暖橙陪诊 · 专业陪诊服务',
path: '/pages/home/index'
}
}
})
+17 -7
View File
@@ -59,23 +59,33 @@ Page({
const profile = item.profile || {}
const health = item.health || {}
// 元信息行只收非空项(空值连同分隔线一起消失,不留「未填写」噪音),
// 顺序:出生年月 → 联系电话 → 证件号(脱敏)
const metaList = []
if (profile.birth) {
metaList.push(profile.birth)
}
if (profile.mobile) {
metaList.push(profile.mobile)
}
if (profile.idnumber) {
metaList.push(this.maskIdNumber(profile.idnumber))
}
return {
_id: item._id,
// 首字牌取姓氏首字;无姓名时 wxml 退到 user 图标
initial: (profile.name || '').slice(0, 1),
name: profile.name || '未命名',
sexText: profile.sex === 'male' ? '男' : (profile.sex === 'female' ? '女' : ''),
birth: profile.birth || '',
mobile: profile.mobile || '',
idnumberText: this.maskIdNumber(profile.idnumber),
metaList,
remark: health.remark || ''
}
},
// 证件号脱敏:仅保留前 4 位与后 4 位
// 证件号脱敏:仅保留前 4 位与后 4 位(只在有值时调用)
maskIdNumber(idnumber) {
const value = String(idnumber || '')
if (!value) {
return '未填写'
}
if (value.length <= 8) {
return value
}
+19 -24
View File
@@ -8,44 +8,39 @@
</view>
<!-- 就诊人列表:一卡一人(白面 + 2rpx 发丝边 + 28rpx 圆角 + 中性紧阴影),
与预约记录卡同一配方,卡间留出 24rpx 纸面。
卡面走「身份牌」结构,与订单详情页的就诊人卡同一套语言:
首字牌定位「是谁」→ 姓名 + 性别签 → 一行竖线分隔的元信息(空值整项剔除)→ 备注省略行。
每条主体可点进编辑,点击暗示由按下态承担(hover-class="profile-main-hover");
删除动作另起一行、与主体隔一条发丝线,走 --muted -->
删除收在卡片右上角、走 --muted 图标(catchtap 不冒泡,不触发整卡进编辑) -->
<view class="profile-list" wx:if="{{profiles.length > 0}}">
<view
class="profile-card"
wx:for="{{profiles}}"
wx:key="_id"
>
<!-- 删除:右上角安静图标(catchtap 不冒泡,点它不会触发整卡进编辑);
确认弹窗仍兜底防误触。不再单设动作行——孤零零一个删除撑不满一行,
只会把身份牌拉高、显得头轻脚重 -->
<view class="profile-delete" catchtap="onDelete" data-id="{{item._id}}">
<t-icon name="delete" size="32rpx" color="#6F655C" />
</view>
<view class="profile-main" data-id="{{item._id}}" bindtap="onEdit" hover-class="profile-main-hover">
<view class="profile-mark">
<text wx:if="{{item.initial}}" class="profile-mark-text">{{item.initial}}</text>
<t-icon wx:else name="user" size="44rpx" color="#9B4508" />
</view>
<view class="profile-info">
<view class="profile-top">
<text class="profile-name">{{item.name}}</text>
<text class="sex-tag" wx:if="{{item.sexText}}">{{item.sexText}}</text>
</view>
<view class="info-row">
<text class="info-label">出生年月</text>
<text class="info-value">{{item.birth || '未填写'}}</text>
<view class="meta-list" wx:if="{{item.metaList.length > 0}}">
<block wx:for="{{item.metaList}}" wx:for-item="meta" wx:key="*this">
<view class="meta-sep" wx:if="{{index > 0}}"></view>
<text class="meta-item">{{meta}}</text>
</block>
</view>
<view class="info-row">
<text class="info-label">联系电话</text>
<text class="info-value">{{item.mobile || '未填写'}}</text>
</view>
<view class="info-row">
<text class="info-label">证件号</text>
<text class="info-value">{{item.idnumberText}}</text>
</view>
<view class="info-row" wx:if="{{item.remark}}">
<text class="info-label">健康备注</text>
<text class="info-value">{{item.remark}}</text>
</view>
</view>
</view>
<view class="profile-actions">
<view class="profile-action" data-id="{{item._id}}" bindtap="onDelete">
<t-icon name="delete" class="profile-action-icon" size="32rpx" />
<text class="profile-action-text">删除</text>
<text class="profile-remark" wx:if="{{item.remark}}">健康备注 {{item.remark}}</text>
</view>
</view>
</view>
+77 -50
View File
@@ -47,6 +47,7 @@ page {
}
.profile-card {
position: relative;
padding: 28rpx 28rpx 24rpx;
border-radius: 28rpx;
background: var(--white);
@@ -60,28 +61,70 @@ page {
margin-top: 24rpx;
}
/* 主体整块可点进编辑。chevron 已去掉,点击暗示由按下态(.profile-main-hover)承担 */
/* 主体整块可点进编辑。chevron 已去掉,点击暗示由按下态(.profile-main-hover)承担:
transform: scale(0.99)——与记录卡(recordlist .record-card:active)同一套按压语言 */
.profile-main {
display: flex;
align-items: center;
justify-content: space-between;
transition: transform 0.15s ease;
}
.profile-main-hover {
opacity: 0.7;
transform: scale(0.99);
}
/* 首字牌:浅橙衬底 + --brand-line 描边,与订单详情页就诊人身份牌同源
(88rpx、24rpx 圆角、40rpx/700 暖橙姓氏首字;无姓名退到 user 图标) */
.profile-mark {
box-sizing: border-box;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
width: 88rpx;
height: 88rpx;
border: 2rpx solid var(--brand-line);
border-radius: 24rpx;
background: var(--brand-soft);
}
.profile-mark-text {
font-size: 40rpx;
font-weight: 700;
color: var(--brand-ink);
letter-spacing: 1rpx;
}
.profile-info {
flex: 1;
min-width: 0;
margin-left: 20rpx;
}
/* 删除:右上角安静图标。56rpx 热区 + 12rpx 内缩,不压卡边;
图标走 --muted 档(#6F655C 与令牌同步),按下整粒变淡作反馈 */
.profile-delete {
position: absolute;
top: 8rpx;
right: 8rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 56rpx;
height: 56rpx;
border-radius: 16rpx;
}
.profile-delete:active {
opacity: 0.5;
}
.profile-top {
display: flex;
align-items: center;
margin-bottom: 12rpx;
/* 右侧给删除图标留位,长姓名 + 性别签不被压住 */
padding-right: 64rpx;
}
/* 姓名是本页最重的字,走 --ink 700(标题档) */
@@ -92,68 +135,52 @@ page {
}
/* 性别签:浅橙衬底档(--brand-soft + 2rpx --brand-line + --brand-ink),
圆角 10rpx 与记录页状态胶囊同一族(徽章/标签圆角规范值),
字号 24rpx 是中文最小字号下限,不得再小 */
.sex-tag {
margin-left: 16rpx;
padding: 4rpx 12rpx;
border-radius: 6rpx;
padding: 4rpx 14rpx;
border-radius: 10rpx;
background: var(--brand-soft);
border: 2rpx solid var(--brand-line);
font-size: 24rpx;
color: var(--brand-ink);
}
/* 标签走 --muted、值走 --ink-2:只表示文字层级,不给可点性上色 */
.info-row {
/* 元信息行:出生年月 | 电话 | 证件号,空值在 JS 里整项剔除(连同分隔线),
竖线 2rpx×20rpx 取 --sep——与订单详情页 meta 行同一套写法 */
.meta-list {
display: flex;
align-items: flex-start;
align-items: center;
margin-top: 12rpx;
}
.info-row + .info-row {
margin-top: 8rpx;
.meta-item {
font-size: 24rpx;
color: var(--muted);
letter-spacing: 1rpx;
line-height: 1.6;
}
.info-label {
.meta-sep {
flex-shrink: 0;
width: 140rpx;
font-size: 26rpx;
color: var(--muted);
}
.info-value {
flex: 1;
min-width: 0;
font-size: 28rpx;
color: var(--ink-2);
word-break: break-all;
}
/* 卡片操作行:与主体隔一条发丝线,删除靠右排(与「邮寄地址」卡同一位置) */
.profile-actions {
display: flex;
align-items: center;
justify-content: flex-end;
margin-top: 24rpx;
padding-top: 20rpx;
border-top: 2rpx solid var(--line);
}
/* 文字只有 26rpx 高,用 padding 撑热区、等量负外边距抵消,不改变行高 */
.profile-action {
display: flex;
align-items: center;
padding: 16rpx 0;
margin: -16rpx 0;
}
.profile-action-icon {
margin-right: 10rpx;
color: var(--muted);
}
.profile-action-text {
font-size: 26rpx;
width: 2rpx;
height: 20rpx;
margin: 0 14rpx;
background: var(--sep);
}
/* 健康备注:单行省略——列表只做提示,全文进编辑页看 */
.profile-remark {
display: block;
margin-top: 8rpx;
font-size: 24rpx;
color: var(--muted);
letter-spacing: 1rpx;
line-height: 1.6;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* ===== 空态 ===== */
+5 -14
View File
@@ -22,9 +22,6 @@ const SERVICE_ORDER = [1, 2, 7, 3, 4, 5, 8, 6]
// 计入"待服务订单"的订单状态:待确认 / 已确认 / 进行中
const PENDING_ORDER_STATUS = ['pending', 'confirmed', 'in_progress']
// 人工客服电话
const SERVICE_PHONE = '18618162956'
Page({
data: {
escortServices: [], // 陪诊服务(来自后端,按 SERVICE_ORDER 展示)
@@ -138,10 +135,11 @@ Page({
})
},
// 页脚 B 端合作入口仍直接转服务电话
goToContact() {
wx.makePhoneCall({
phoneNumber: SERVICE_PHONE
// 页脚三个 B 端入口:都进「合作与入驻」页,用 section 定位到各自的卡片
goToBusiness(e) {
const section = e.currentTarget.dataset.section || ''
wx.navigateTo({
url: `/pages/mine/business?section=${section}`
});
},
@@ -160,13 +158,6 @@ Page({
});
},
// 介绍卡信任行:「实名专业陪诊师」→ 陪诊师公示页
goToAttendants() {
wx.navigateTo({
url: '/pages/attendant/attendantlist'
});
},
// 点击陪诊服务,直达服务详情下单
goToServiceDetail(e) {
const id = e.currentTarget.dataset.id
+9 -12
View File
@@ -81,15 +81,11 @@
<view class="intro-card">
<text class="intro-desc">做你和医生之间,最省心的那座桥。</text>
<!-- 信任行:三项信任背书单行小字,从首屏下沉至此。
"专业"是定性描述,故不称"可验证事实" -->
"专业"是定性描述,故不称"可验证事实"。
三项现状均纯展示不可点——「实名专业陪诊师」原先带 chevron 跳陪诊师公示页,
现已摘掉入口,故连 chevron 一并去掉,否则会留一个点了没反应的点击暗示 -->
<view class="intro-trust">
<!-- 「实名专业陪诊师」是陪诊师公示页的入口。
按全站约定「可点项必须有显性暗示」,故在其后补一个 chevron;
另两项保持纯展示 -->
<view class="intro-trust-link" bindtap="goToAttendants">
<text class="intro-trust-item">实名专业陪诊师</text>
<t-icon name="chevron-right" size="22rpx" color="#6F655C" />
</view>
<text class="intro-trust-item">实名专业陪诊师</text>
<view class="intro-trust-sep"></view>
<text class="intro-trust-item">熟悉医院流程</text>
<view class="intro-trust-sep"></view>
@@ -132,14 +128,15 @@
</view>
<!-- ④ 页脚:B 端合作入口(商务合作 / 陪诊师入驻 / 陪诊师考证),
点击统一转服务电话,与「我的」页页脚同构 -->
三条都进「合作与入驻」页,各自用 section 定位到对应卡片。
该页底部再转「联系我们」——咨询出口只保留一个,避免同一意图两个入口 -->
<view class="page-footer">
<view class="footer-links">
<text class="footer-link" bindtap="goToContact">商务合作</text>
<text class="footer-link" data-section="sec-biz" bindtap="goToBusiness">商务合作</text>
<view class="footer-sep"></view>
<text class="footer-link" bindtap="goToContact">陪诊师入驻</text>
<text class="footer-link" data-section="sec-join" bindtap="goToBusiness">陪诊师入驻</text>
<view class="footer-sep"></view>
<text class="footer-link" bindtap="goToContact">陪诊师考证</text>
<text class="footer-link" data-section="sec-train" bindtap="goToBusiness">陪诊师考证</text>
</view>
<text class="footer-note">WARM ESCORT · 用心陪好每一步</text>
</view>
-18
View File
@@ -214,24 +214,6 @@ page {
flex-shrink: 0;
}
/* 信任行里唯一的可点项:「实名专业陪诊师」→ 陪诊师公示页。
用 padding 16rpx 把热区撑到 56rpx(28px),再配等量负外边距抵消,
信任行的行高与另两项保持完全不变 */
.intro-trust-link {
display: flex;
align-items: center;
padding: 16rpx 0;
margin: -16rpx 0;
}
.intro-trust-link:active {
opacity: 0.6;
}
.intro-trust-link .intro-trust-item {
margin-right: 4rpx;
}
/* ===== 通用区块 ===== */
.section {
margin-top: 56rpx;
-57
View File
@@ -1,57 +0,0 @@
const app = getApp()
Page({
data: {
hospitalInfo: [],
loading: true,
},
onLoad(options) {
this.loadhospitalInfo()
},
loadhospitalInfo() {
const appData = app.globalData
if (appData.hospitalInfo && appData.hospitalInfo.length > 0) {
this.setData({
hospitalInfo: appData.hospitalInfo,
loading: false,
})
} else if (appData.hospitalInfoReady) {
appData.hospitalInfoReady.then((data) => {
this.setData({
hospitalInfo: data || [],
loading: false,
})
}).catch(() => {
this.setData({
hospitalInfo: [],
loading: false,
})
})
} else {
this.setData({
hospitalInfo: [],
loading: false,
})
}
},
onCallPhone(e) {
const phone = e.currentTarget.dataset.phone
if (!phone) return
wx.makePhoneCall({
phoneNumber: phone,
fail: (err) => {
console.error('拨打电话失败', err)
},
})
},
onShareAppMessage() {
return {
title: '医院联系电话',
path: '/pages/hospital/contact',
}
},
})
-3
View File
@@ -1,3 +0,0 @@
{
"usingComponents": {}
}
-38
View File
@@ -1,38 +0,0 @@
<view class="container">
<view class="header">
<text class="title">主要医院联系电话</text>
<text class="subtitle">持续更新中, 仅供参考</text>
</view>
<view wx:if="{{loading}}" class="loading">
<text>加载中...</text>
</view>
<view wx:elif="{{hospitalInfo.length === 0}}" class="empty">
<text>暂无医院信息</text>
</view>
<view wx:else class="list">
<view
class="item"
wx:for="{{hospitalInfo}}"
wx:key="id"
>
<view class="info">
<text class="name">{{item.name}}</text>
<view class="phones">
<view
class="phone-wrap"
wx:for="{{item.phone}}"
wx:for-item="phone"
wx:key="*this"
data-phone="{{phone.number}}"
bindtap="onCallPhone"
>
<text class="phone">{{phone.number}} </text>
</view>
</view>
</view>
</view>
</view>
</view>
-132
View File
@@ -1,132 +0,0 @@
page {
background-color: #F5F7F6;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
.container {
min-height: 100vh;
padding-bottom: 32rpx;
}
/* 顶部导航栏 */
.nav-bar {
display: flex;
align-items: center;
padding: 120rpx 32rpx 20rpx 32rpx;
background: #FFFFFF;
}
.nav-logo {
display: flex;
align-items: center;
}
.logo-icon {
width: 56rpx;
height: 56rpx;
border-radius: 16rpx;
background: #FFFFFF;
padding: 4rpx;
}
.logo-text {
font-size: 36rpx;
font-weight: 700;
color: #1F2937;
margin-left: 16rpx;
}
/* Header区域 */
.header {
background: #FFFFFF;
padding: 16rpx 24rpx 20rpx 24rpx;
margin-bottom: 12rpx;
}
.title {
display: block;
font-size: 32rpx;
font-weight: 700;
color: #1F2937;
}
.subtitle {
display: block;
font-size: 24rpx;
color: #6B8E7B;
margin-top: 6rpx;
}
/* 加载和空状态 */
.loading,
.empty {
text-align: center;
padding: 80rpx 24rpx;
color: #6B7280;
font-size: 26rpx;
}
/* 列表区域 */
.list {
padding: 0 24rpx;
}
.item {
display: flex;
align-items: center;
justify-content: space-between;
background: #FFFFFF;
border-radius: 20rpx;
padding: 20rpx 24rpx;
margin-bottom: 12rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
}
.info {
display: flex;
flex-direction: column;
flex: 1;
overflow: hidden;
}
.name {
font-size: 30rpx;
font-weight: 600;
color: #1F2937;
line-height: 1.3;
margin-bottom: 10rpx;
word-wrap: break-word;
}
.phones {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 8rpx;
}
.phone-wrap {
display: flex;
align-items: center;
gap: 8rpx;
padding: 8rpx 14rpx;
background: #FAFAFA;
border-radius: 8rpx;
width: fit-content;
}
.phone {
font-size: 26rpx;
color: #2D6A4F;
line-height: 1.3;
font-weight: 500;
}
.action {
margin-left: 16rpx;
flex-shrink: 0;
}
.icon {
font-size: 36rpx;
}
-192
View File
@@ -1,192 +0,0 @@
// pages/hospital/ranking.js
const app = getApp()
Page({
data: {
activeTab: 'overall',
searchKeyword: '',
selectedDepartment: '',
rankingYear: '',
rankingNote: '',
departmentList: [],
allHospitals: [],
filteredHospitals: [],
currentDepartmentRanking: {
top10: [],
nominated: []
},
hospitalRankingData: null,
departmentRankingsData: null
},
onLoad(options) {
this.loadData()
},
onShow() {
if (!this.data.hospitalRankingData || !this.data.departmentRankingsData) {
this.loadData()
}
},
async loadData() {
try {
const appData = app.globalData
let hospitalRanking = appData.hospitalRanking
let departmentRankings = appData.departmentRankings
if (!hospitalRanking) {
hospitalRanking = await appData.hospitalRankingReady
}
if (!departmentRankings) {
departmentRankings = await appData.departmentRankingsReady
}
this.setData({
hospitalRankingData: hospitalRanking,
departmentRankingsData: departmentRankings
})
this.processHospitalRanking(hospitalRanking)
this.processDepartmentRankings(departmentRankings)
} catch (err) {
console.error('加载排行榜数据失败', err)
wx.showToast({
title: '数据加载失败',
icon: 'none'
})
}
},
processHospitalRanking(data) {
if (!data || !data.rankings) return
const gradeClassMap = {
'A+++++': 'grade-a5',
'A++++': 'grade-a4',
'A+++': 'grade-a3',
'A++': 'grade-a2',
'A+': 'grade-a1'
}
const hospitals = data.rankings.map(item => {
const allDeps = (item.depart || [])
.sort((a, b) => a.rank - b.rank)
return {
...item,
gradeClass: gradeClassMap[item.grade] || 'grade-a1',
topDepartments: allDeps,
expanded: false
}
})
this.setData({
rankingYear: data.year || '',
rankingNote: data.note || '',
allHospitals: hospitals,
filteredHospitals: hospitals
})
},
processDepartmentRankings(data) {
if (!data || !data.departments) return
const departments = Object.keys(data.departments)
const firstDept = departments[0] || ''
this.setData({
departmentList: departments,
selectedDepartment: firstDept
})
if (firstDept) {
this.updateCurrentDepartmentRanking(firstDept)
}
},
updateCurrentDepartmentRanking(deptName) {
const data = this.data.departmentRankingsData
if (!data || !data.departments || !data.departments[deptName]) {
this.setData({
currentDepartmentRanking: { top10: [], nominated: [] }
})
return
}
const deptData = data.departments[deptName]
this.setData({
currentDepartmentRanking: {
top10: deptData.top10 || [],
nominated: deptData.nominated || []
}
})
},
switchTab(e) {
const tab = e.currentTarget.dataset.tab
if (tab === this.data.activeTab) return
this.setData({ activeTab: tab })
},
selectDepartment(e) {
const dept = e.currentTarget.dataset.dept
this.setData({ selectedDepartment: dept })
this.updateCurrentDepartmentRanking(dept)
},
onSearchInput(e) {
const keyword = e.detail.value
this.setData({ searchKeyword: keyword })
this.filterHospitals(keyword)
},
onSearch(e) {
const keyword = e.detail.value
this.filterHospitals(keyword)
},
clearSearch() {
this.setData({ searchKeyword: '' })
this.filterHospitals('')
},
filterHospitals(keyword) {
let result = this.data.allHospitals
if (keyword && keyword.trim()) {
const lowerKeyword = keyword.trim().toLowerCase()
result = result.filter(item => {
const nameMatch = item.name && item.name.toLowerCase().includes(lowerKeyword)
const deptMatch = item.depart && item.depart.some(d => d.name && d.name.toLowerCase().includes(lowerKeyword))
return nameMatch || deptMatch
})
}
this.setData({ filteredHospitals: result })
},
toggleHospital(e) {
const name = e.currentTarget.dataset.name
const hospitals = this.data.filteredHospitals.map(item => {
if (item.name === name) {
return { ...item, expanded: !item.expanded }
}
return item
})
this.setData({ filteredHospitals: hospitals })
},
onPullDownRefresh() {
this.loadData().finally(() => {
wx.stopPullDownRefresh()
})
},
onShareAppMessage() {
return {
title: '复旦中国医院排行榜',
path: '/pages/hospital/ranking'
}
}
})
-6
View File
@@ -1,6 +0,0 @@
{
"usingComponents": {},
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark",
"navigationBarTitleText": "医院排行榜"
}
-104
View File
@@ -1,104 +0,0 @@
<!--pages/hospital/ranking.wxml-->
<view class="container">
<!-- 顶部标题 -->
<view class="header">
<text class="header-title">{{rankingYear}}复旦中国医院排行榜</text>
<text class="header-note">{{rankingNote}}</text>
</view>
<!-- Tab 切换 -->
<view class="tab-bar">
<view class="tab-item {{activeTab === 'overall' ? 'active' : ''}}" bindtap="switchTab" data-tab="overall">
<text class="tab-text">综合榜</text>
<view class="tab-line" wx:if="{{activeTab === 'overall'}}"></view>
</view>
<view class="tab-item {{activeTab === 'department' ? 'active' : ''}}" bindtap="switchTab" data-tab="department">
<text class="tab-text">专科榜</text>
<view class="tab-line" wx:if="{{activeTab === 'department'}}"></view>
</view>
</view>
<!-- 综合榜内容 -->
<view class="content" wx:if="{{activeTab === 'overall'}}">
<!-- 医院列表 -->
<view class="hospital-list">
<view class="hospital-card" wx:for="{{filteredHospitals}}" wx:key="name" bindtap="toggleHospital" data-name="{{item.name}}">
<view class="hospital-rank-badge">
<text class="rank-grade {{item.gradeClass}}">{{item.grade}}</text>
</view>
<view class="hospital-header">
<view class="hospital-info">
<text class="hospital-name">{{item.name}}</text>
<view class="hospital-tags">
<text class="tag" wx:for="{{item.topDepartments}}" wx:for-item="dep" wx:key="name">{{dep.name}}</text>
</view>
</view>
<view class="hospital-arrow">
<t-icon name="chevron-down" size="36rpx" color="#999" class="{{item.expanded ? 'arrow-up' : ''}}"/>
</view>
</view>
<!-- 展开详情 -->
<view class="hospital-detail" wx:if="{{item.expanded}}">
<view class="detail-title">专科排名详情</view>
<view class="dept-grid">
<view class="dept-item" wx:for="{{item.depart}}" wx:for-item="dep" wx:key="name">
<text class="dept-name">{{dep.name}}</text>
<view class="dept-rank">
<text class="rank-num">第{{dep.rank}}名</text>
<text class="rank-score">{{dep.score}}分</text>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 专科榜内容 -->
<view class="content" wx:if="{{activeTab === 'department'}}">
<!-- 科室筛选 -->
<scroll-view class="dept-filter" scroll-y enhanced show-scrollbar="{{true}}" style="height: calc(100vh - 340rpx);">
<view class="dept-sidebar">
<view class="sidebar-item {{selectedDepartment === item ? 'active' : ''}}" wx:for="{{departmentList}}" wx:key="*this" bindtap="selectDepartment" data-dept="{{item}}">
<text class="sidebar-text">{{item}}</text>
</view>
</view>
</scroll-view>
<!-- 科室排名详情 -->
<view class="dept-ranking-content">
<view class="dept-ranking-header">
<text class="dept-ranking-title">{{selectedDepartment}}</text>
<text class="dept-ranking-subtitle">{{rankingYear}}年度专科声誉排名</text>
</view>
<!-- Top10 列表 -->
<view class="top10-list">
<view class="top10-item {{index < 3 ? 'top3' : ''}}" wx:for="{{currentDepartmentRanking.top10}}" wx:key="name">
<view class="top10-rank">
<text class="rank-badge" wx:if="{{index < 3}}">{{item.rank}}</text>
<text class="rank-num" wx:else>{{item.rank}}</text>
</view>
<view class="top10-info">
<text class="top10-name">{{item.name}}</text>
<text class="top10-score">{{item.score}}分</text>
</view>
</view>
</view>
<!-- 获提名医院 -->
<view class="nominated-section" wx:if="{{currentDepartmentRanking.nominated && currentDepartmentRanking.nominated.length > 0}}">
<view class="nominated-title">获提名医院</view>
<view class="nominated-list">
<text class="nominated-item" wx:for="{{currentDepartmentRanking.nominated}}" wx:key="*this">{{item}}</text>
</view>
</view>
</view>
</view>
<!-- 空状态 -->
<view class="empty-state" wx:if="{{activeTab === 'overall' && filteredHospitals.length === 0}}">
<t-icon name="info-circle" size="80rpx" color="#ccc"/>
<text class="empty-text">未找到匹配的医院</text>
</view>
</view>
-450
View File
@@ -1,450 +0,0 @@
/* pages/hospital/ranking.wxss */
page {
background-color: #F5F7F6;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
.container {
min-height: 100vh;
padding-bottom: 60rpx;
}
/* ========== 顶部标题 ========== */
.header {
padding: 32rpx 32rpx 16rpx 32rpx;
text-align: center;
}
.header-title {
font-size: 36rpx;
font-weight: 700;
color: #1F2937;
display: block;
}
.header-note {
font-size: 24rpx;
color: #6B8E7B;
margin-top: 8rpx;
display: block;
}
/* ========== 搜索栏 ========== */
.search-bar {
padding: 16rpx 32rpx;
}
.search-input-wrap {
display: flex;
align-items: center;
background: #FFFFFF;
border-radius: 40rpx;
padding: 16rpx 24rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
}
.search-input {
flex: 1;
font-size: 28rpx;
color: #1F2937;
margin-left: 16rpx;
margin-right: 16rpx;
}
.search-input::placeholder {
color: #6B7280;
}
.search-clear {
padding: 4rpx;
}
/* ========== Tab 切换 ========== */
.tab-bar {
display: flex;
justify-content: center;
padding: 0 32rpx;
margin-top: 8rpx;
border-bottom: 1rpx solid #F3F4F6;
}
.tab-item {
position: relative;
padding: 24rpx 48rpx;
cursor: pointer;
}
.tab-text {
font-size: 30rpx;
color: #6B7280;
font-weight: 500;
}
.tab-item.active .tab-text {
color: #2D6A4F;
font-weight: 700;
}
.tab-line {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 48rpx;
height: 4rpx;
background: #2D6A4F;
border-radius: 2rpx;
}
/* ========== 综合榜内容 ========== */
.content {
padding: 0 24rpx;
}
/* 医院列表 */
.hospital-list {
margin-top: 16rpx;
}
.hospital-card {
position: relative;
background: #FFFFFF;
border-radius: 20rpx;
margin-bottom: 16rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
overflow: hidden;
}
.hospital-rank-badge {
position: absolute;
top: 0;
right: 0;
z-index: 10;
}
.hospital-rank-badge .rank-grade {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 8rpx 16rpx;
border-radius: 0 20rpx 0 12rpx;
font-size: 22rpx;
font-weight: 700;
min-width: 80rpx;
text-align: center;
}
.hospital-header {
display: flex;
align-items: center;
padding: 24rpx 100rpx 24rpx 24rpx;
}
.rank-grade {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 8rpx 16rpx;
border-radius: 12rpx;
font-size: 24rpx;
font-weight: 700;
min-width: 80rpx;
text-align: center;
}
.rank-grade.grade-a5 {
background: linear-gradient(135deg, #FEF3C7 0%, #FDE68A 100%);
color: #92400E;
}
.rank-grade.grade-a4 {
background: linear-gradient(135deg, #DBEAFE 0%, #BFDBFE 100%);
color: #1E40AF;
}
.rank-grade.grade-a3 {
background: linear-gradient(135deg, #D1FAE5 0%, #A7F3D0 100%);
color: #065F46;
}
.rank-grade.grade-a2 {
background: linear-gradient(135deg, #E0E7FF 0%, #C7D2FE 100%);
color: #3730A3;
}
.rank-grade.grade-a1 {
background: linear-gradient(135deg, #F3E8FF 0%, #E9D5FF 100%);
color: #6B21A8;
}
.hospital-info {
flex: 1;
min-width: 0;
}
.hospital-name {
font-size: 32rpx;
font-weight: 600;
color: #1F2937;
display: block;
}
.hospital-tags {
display: flex;
flex-wrap: wrap;
margin-top: 8rpx;
gap: 8rpx;
}
.tag {
font-size: 24rpx;
color: #2D6A4F;
background: rgba(45, 106, 79, 0.08);
padding: 4rpx 12rpx;
border-radius: 8rpx;
}
.hospital-arrow {
margin-left: 16rpx;
transition: transform 0.3s;
}
.arrow-up {
transform: rotate(180deg);
}
/* 医院详情展开 */
.hospital-detail {
padding: 0 24rpx 24rpx 24rpx;
border-top: 1rpx solid #F3F4F6;
}
.detail-title {
font-size: 26rpx;
font-weight: 600;
color: #374151;
padding: 16rpx 0 12rpx 0;
}
.dept-grid {
display: flex;
flex-wrap: wrap;
gap: 12rpx;
}
.dept-item {
background: #F9FAFB;
border-radius: 12rpx;
padding: 12rpx 16rpx;
flex: 1;
min-width: 200rpx;
max-width: calc(50% - 6rpx);
}
.dept-name {
font-size: 24rpx;
color: #4B5563;
display: block;
}
.dept-rank {
display: flex;
justify-content: space-between;
margin-top: 4rpx;
}
.rank-num {
font-size: 22rpx;
color: #2D6A4F;
font-weight: 600;
}
.rank-score {
font-size: 22rpx;
color: #9CA3AF;
}
/* ========== 专科榜内容 ========== */
.content:has(.dept-filter) {
display: flex;
padding: 0;
}
.dept-filter {
width: 200rpx;
background: #FFFFFF;
border-right: 1rpx solid #F3F4F6;
}
.dept-sidebar {
padding: 8rpx 0;
}
.sidebar-item {
padding: 24rpx 16rpx;
text-align: center;
border-left: 4rpx solid transparent;
transition: all 0.2s;
}
.sidebar-item.active {
background: #F0FDF4;
border-left-color: #2D6A4F;
}
.sidebar-text {
font-size: 26rpx;
color: #4B5563;
}
.sidebar-item.active .sidebar-text {
color: #2D6A4F;
font-weight: 600;
}
.dept-ranking-content {
flex: 1;
padding: 16rpx 24rpx 24rpx 24rpx;
overflow-y: auto;
}
.dept-ranking-header {
margin-bottom: 16rpx;
}
.dept-ranking-title {
font-size: 32rpx;
font-weight: 700;
color: #1F2937;
display: block;
}
.dept-ranking-subtitle {
font-size: 24rpx;
color: #6B8E7B;
margin-top: 4rpx;
display: block;
}
/* Top10 列表 */
.top10-list {
background: #FFFFFF;
border-radius: 20rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
overflow: hidden;
}
.top10-item {
display: flex;
align-items: center;
padding: 20rpx 24rpx;
border-bottom: 1rpx solid #F3F4F6;
}
.top10-item:last-child {
border-bottom: none;
}
.top10-item.top3 {
background: linear-gradient(90deg, rgba(254, 243, 199, 0.3) 0%, rgba(255, 255, 255, 0) 100%);
}
.top10-rank {
margin-right: 20rpx;
min-width: 56rpx;
text-align: center;
}
.rank-badge {
display: inline-flex;
align-items: center;
justify-content: center;
width: 48rpx;
height: 48rpx;
border-radius: 50%;
font-size: 26rpx;
font-weight: 700;
color: #FFFFFF;
}
.top10-item:nth-child(1) .rank-badge {
background: linear-gradient(135deg, #F59E0B 0%, #D97706 100%);
}
.top10-item:nth-child(2) .rank-badge {
background: linear-gradient(135deg, #9CA3AF 0%, #6B7280 100%);
}
.top10-item:nth-child(3) .rank-badge {
background: linear-gradient(135deg, #B45309 0%, #92400E 100%);
}
.rank-num {
font-size: 28rpx;
font-weight: 600;
color: #6B7280;
}
.top10-info {
flex: 1;
min-width: 0;
}
.top10-name {
font-size: 28rpx;
color: #1F2937;
font-weight: 500;
display: block;
}
.top10-score {
font-size: 24rpx;
color: #6B7280;
margin-top: 4rpx;
display: block;
}
/* 获提名医院 */
.nominated-section {
margin-top: 24rpx;
background: #FFFFFF;
border-radius: 20rpx;
padding: 20rpx 24rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
}
.nominated-title {
font-size: 26rpx;
font-weight: 600;
color: #374151;
margin-bottom: 12rpx;
}
.nominated-list {
display: flex;
flex-wrap: wrap;
gap: 12rpx;
}
.nominated-item {
font-size: 24rpx;
color: #4B5563;
background: #F9FAFB;
padding: 8rpx 16rpx;
border-radius: 8rpx;
}
/* ========== 空状态 ========== */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 32rpx;
}
.empty-text {
font-size: 28rpx;
color: #6B7280;
margin-top: 24rpx;
}
-7
View File
@@ -70,13 +70,6 @@ Page({
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
},
// 跳转「联系我们」页:本页不再平铺联系方式,四项内容与那一页重合,
// 且那一页每行还带「拨打」「复制」动作词,是更完整的一份
goToContact() {
+94
View File
@@ -0,0 +1,94 @@
// pages/mine/business.js
// 商务合作 / 陪诊师入驻 / 陪诊师培训 三个方向共用本页:入口分别来自首页与
// 「我的」页页脚,靠 ?section= 定位到对应卡片(对应 wxml 里 wx:for 的 id)。
//
// 规则口径只写两类内容:国家标准 GB/T 47801—2026《社会化陪同就医服务 基本要求》
// 第 4.2 章(服务管理)、第 7 章(服务人员)已明确的要求,以及平台的通用流程。
// 不写任何未公示的收费标准——费用与排期一律指向客服确认,避免出现未公示费项。
//
// 培训卡里的证书口径:发证主体是国家开放大学培训中心,不是本平台,故只陈述
// 证书名称、颁发主体与证书性质(培训合格证明),不写"国家认可""全国通用"
// "持证上岗"等评价性或承诺性表述——那类说法无法核实,且涉嫌虚假宣传。
// 三个锚点白名单:?section= 来自页面路径,只接受这三张卡自己的 id
const SECTION_IDS = ['sec-biz', 'sec-join', 'sec-train']
Page({
data: {
// 三张卡的数据源:改文案只改这里,wxml 结构不动
sections: [{
id: 'sec-biz',
icon: 'user-business',
title: '商务合作',
points: [
'合作对象:医疗机构、社区、健康管理及养老服务机构,以及有员工就医协助需求的企业',
'合作方式:具体事项请联系客服沟通'
],
note: '以上为通用说明,具体合作方案请联系客服沟通'
},
{
id: 'sec-join',
icon: 'user-add',
title: '陪诊师入驻',
points: [
'基本条件:持有效健康证明,遵守医院规定,不干预医务人员判断',
'上岗要求:完成岗前培训并考核通过,上岗后定期参加专项培训',
'职业素养:守时、有责任心,尊重服务对象,保护其隐私',
'入驻流程:联系客服沟通'
],
note: '以上依据国家标准 GB/T 47801—2026《社会化陪同就医服务 基本要求》第 7 章,最终以资料核验结果为准'
},
{
id: 'sec-train',
icon: 'education',
title: '陪诊师培训',
points: [
'培训内容:操作、专业能力、安全应急、心理健康、人文素养',
'专业知识:挂号流程、科室分布、设备使用与应急常识',
'培训证书:国家开放大学培训中心《医疗陪诊顾问职业技能培训证书》(培训合格证明,非职业资格证书)',
'培训费用:980 元,报名请联系客服确认'
],
note: '本页仅作说明,不办理报名与收费'
}
]
},
// 从哪个入口进来就定位到哪张卡,避免点「陪诊师培训」却落在页首自己找
onLoad(options) {
const section = options && options.section
this.sectionId = SECTION_IDS.indexOf(section) > -1 ? section : ''
},
onReady() {
if (!this.sectionId) {
return
}
wx.pageScrollTo({
selector: `#${this.sectionId}`,
duration: 0
})
},
// 底部出口:合作咨询统一转联系我们页(热线、微信、邮箱都在那一页,
// 不在此页重复铺一遍联系方式,避免同一意图两个入口)
goToContact() {
wx.navigateTo({
url: '/pages/mine/contact'
})
},
onShareAppMessage() {
return {
title: '暖橙陪诊 · 合作与入驻',
path: '/pages/mine/business'
}
},
// 朋友圈只能分享当前页,本页无需带入 ?section=,好友打开即为页首
onShareTimeline() {
return {
title: '暖橙陪诊 · 合作与入驻'
}
}
})
+6
View File
@@ -0,0 +1,6 @@
{
"navigationBarTitleText": "合作与入驻",
"usingComponents": {
"t-icon": "tdesign-miniprogram/icon/icon"
}
}
+49
View File
@@ -0,0 +1,49 @@
<!--pages/mine/business.wxml-->
<view class="page-bg">
<view class="container">
<!-- 头部:小色带 + 深墨标题(内页规范,不做整块主色面板) -->
<view class="page-header">
<view class="header-accent"></view>
<text class="header-title">与我们合作</text>
<text class="header-subtitle">商务合作 · 陪诊师入驻 · 陪诊师培训</text>
</view>
<!-- 三个方向各一张白卡,结构完全相同:图标 + 标题 + 圆点规则 + 尾注。
区分只靠图标与标题,不靠颜色(DESIGN.md 硬约束 3「需区分时先改结构」) -->
<view class="card" wx:for="{{ sections }}" wx:key="id" id="{{ item.id }}">
<view class="card-head">
<!-- 卡头标识走全站「浅橙衬底 + 暖橙图标」语言;
t-icon 的 color 读不到 CSS 变量,硬编码对应 --brand-ink #9B4508 -->
<view class="card-mark">
<t-icon name="{{ item.icon }}" size="26rpx" color="#9B4508" />
</view>
<text class="card-title">{{ item.title }}</text>
</view>
<!-- 规则条目用陪诊指南页同一套圆点语言 -->
<view class="dot-list">
<view class="dot-item" wx:for="{{ item.points }}" wx:for-item="point" wx:key="*this">
<view class="dot"></view>
<text class="dot-text">{{ point }}</text>
</view>
</view>
<!-- 尾注:与条目用发丝线分开,说明口径而非补充规则 -->
<text class="card-note">{{ item.note }}</text>
</view>
<!-- 底部出口:浅橙入口卡(--brand-soft + 2rpx 描边托形 + 去阴影,
同 about 页「联系我们」配方)。整卡可点,右侧 chevron 作点击暗示。
chevron 用 muted 而非暖橙——项目里 chevron 一律 muted,不抢主色焦点 -->
<view class="contact-entry" bindtap="goToContact" hover-class="contact-entry-hover">
<!-- 一行两段:前半句作说明、后半"联系我们"留暖橙主色形成指向。
两段之间的间隙交给 .entry-title 的 margin-left,不靠空白字符——
text 节点内外的空白在 WXML 编译时会被压缩,不可靠 -->
<text class="entry-prefix">具体事项,请直接</text><text class="entry-title">联系我们</text>
<t-icon class="entry-arrow" name="chevron-right" size="28rpx" color="#6F655C" />
</view>
<view class="footer-space"></view>
</view>
</view>
+165
View File
@@ -0,0 +1,165 @@
/* pages/mine/business.wxss
配色令牌来自 app.wxss(全站唯一来源),本页不留副本;
卡片、卡头标识、圆点清单与陪诊指南页同一套语言,保证内页风格一致 */
page {
background-color: var(--paper);
}
.page-bg {
min-height: 100vh;
background: var(--paper);
}
.container {
padding: 32rpx 32rpx 0;
}
/* ===== 头部:小色带 + 深墨标题 ===== */
.page-header {
padding: 24rpx 0 8rpx;
}
.header-accent {
width: 64rpx;
height: 8rpx;
border-radius: 4rpx;
background: var(--brand-strong);
}
.header-title {
display: block;
margin-top: 20rpx;
font-size: 46rpx;
font-weight: 700;
color: var(--ink);
letter-spacing: 1rpx;
}
.header-subtitle {
display: block;
margin-top: 12rpx;
font-size: 26rpx;
color: var(--muted);
letter-spacing: 1rpx;
}
/* ===== 方向卡:白面走发丝边 + 中性紧阴影 ===== */
.card {
margin-top: 32rpx;
padding: 28rpx 26rpx;
border-radius: 28rpx;
background: var(--white);
border: 2rpx solid var(--line);
box-shadow: var(--shadow-card);
}
.card-head {
display: flex;
align-items: center;
margin-bottom: 20rpx;
}
/* 卡头标识:浅橙衬底 + 2rpx 描边托形,不用实心橙(全页无实心大色块) */
.card-mark {
width: 44rpx;
height: 44rpx;
border-radius: 12rpx;
background: var(--brand-soft);
border: 2rpx solid var(--brand-line);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.card-title {
margin-left: 14rpx;
font-size: 32rpx;
font-weight: 700;
color: var(--ink);
letter-spacing: 1rpx;
}
/* ===== 规则条目:与陪诊指南页同一套圆点语言 ===== */
.dot-item {
display: flex;
padding: 12rpx 0;
}
.dot {
width: 10rpx;
height: 10rpx;
border-radius: 50%;
background: var(--brand-strong);
margin: 16rpx 18rpx 0 4rpx;
flex-shrink: 0;
}
.dot-text {
flex: 1;
font-size: 28rpx;
color: var(--ink-2);
line-height: 1.7;
}
/* 尾注:与条目用发丝线切开,读到的是口径说明而非又一条规则 */
.card-note {
display: block;
margin-top: 8rpx;
padding-top: 20rpx;
border-top: 2rpx solid var(--line);
font-size: 24rpx;
color: var(--muted);
line-height: 1.7;
}
/* ===== 底部出口:浅橙入口卡(同 about 页「联系我们」配方)=====
靠 2rpx --brand-line 描边托形,不加阴影 */
.contact-entry {
position: relative;
display: flex;
align-items: center;
justify-content: center;
margin-top: 48rpx;
padding: 28rpx 26rpx;
border-radius: 28rpx;
background: var(--brand-soft);
border: 2rpx solid var(--brand-line);
transition: transform 0.15s ease;
}
.contact-entry:active,
.contact-entry-hover {
transform: scale(0.99);
}
/* chevron 绝对定位贴右缘:只作点击暗示,不参与居中计算,
否则会把文字往左挤偏半个箭头宽 */
.entry-arrow {
position: absolute;
right: 26rpx;
top: 50%;
transform: translateY(-50%);
}
/* 说明句:比主色文字小一号(26rpx)并转灰,退到背景层;
--muted 在浅橙底上 5.24:1,过 AA;26rpx 高于中文最小字号 24rpx */
.entry-prefix {
font-size: 26rpx;
color: var(--muted);
}
/* 落在"联系我们"上,保留暖橙主色与字重,成为这行文字的指向;
--brand-ink 就是为「浅橙底上的文字」定义的令牌(浅橙底 5.96:1,过 AA)。
margin-left 是两段之间的唯一间隙来源(不靠空白字符),
8rpx 约半个汉字宽,够断开语气又不至于把一句话读散 */
.entry-title {
margin-left: 8rpx;
font-size: 30rpx;
font-weight: 700;
color: var(--brand-ink);
}
.footer-space {
height: 60rpx;
}
+5 -4
View File
@@ -188,10 +188,11 @@ Page({
})
},
// 页脚 B 端合作链接:暂无独立页面,统一转接人工客服
onFooterTap() {
wx.makePhoneCall({
phoneNumber: '18618162956'
// 页脚三个 B 端入口:都进「合作与入驻」页,用 section 定位到各自的卡片
onFooterTap(e) {
const section = e.currentTarget.dataset.section || ''
wx.navigateTo({
url: `/pages/mine/business?section=${section}`
})
},
+5 -4
View File
@@ -85,16 +85,17 @@
</view>
<view class="footer-section">
<!-- B 端合作入口:与首页页脚取同一组三条。
<!-- B 端合作入口:与首页页脚取同一组三条,且同样都进「合作与入驻」页
(各自用 section 定位),咨询出口由该页底部统一转「联系我们」。
原先本页是「企业/机构合作 · 陪诊师入驻 · 商务合作」,
其中前两条同义(都转同一个服务电话),
违反「同一意图只保留一个入口」,故整体对齐首页那组 -->
<view class="footer-links">
<text class="footer-link" bindtap="onFooterTap">商务合作</text>
<text class="footer-link" data-section="sec-biz" bindtap="onFooterTap">商务合作</text>
<view class="footer-sep"></view>
<text class="footer-link" bindtap="onFooterTap">陪诊师入驻</text>
<text class="footer-link" data-section="sec-join" bindtap="onFooterTap">陪诊师入驻</text>
<view class="footer-sep"></view>
<text class="footer-link" bindtap="onFooterTap">陪诊师考证</text>
<text class="footer-link" data-section="sec-train" bindtap="onFooterTap">陪诊师考证</text>
</view>
<!-- 版本与版权合并为一行:两行元信息体量都很小,分行只制造空白;
中间复用 .footer-sep 细竖线,与上方链接行同一分隔语言(不用中点字符) -->
-3
View File
@@ -37,9 +37,6 @@ const API = {
resource: {
getServices: (params) => request.get('/health/service', params),
getAgreement: (params) => request.get('/health/agreement', params),
getHospitalInfo: (params) => request.get('/health/hospital-info', params),
getHospitalRanking: (params) => request.get('/health/hospital-ranking', params),
getDepartmentRankings: (params) => request.get('/health/department-rankings', params),
getAiQuickQuestions: (params) => request.get('/health/ai-quick-questions', params),
},