246 lines
7.9 KiB
Markdown
246 lines
7.9 KiB
Markdown
# 游客端票务页面迁移设计
|
||
|
||
## 背景与目标
|
||
|
||
将 `/Users/gleen/OneFeel/xiaoqi-seji/需求交付物/前端原型.html` 中的“游客端预览”迁移到 `src/pages-service/tickets/`,并以用户提供的截图作为首页视觉基准。
|
||
|
||
本次实现覆盖游客端完整链路:
|
||
|
||
1. 景区票务首页
|
||
2. 商品详情
|
||
3. 预订选择与实名游客填写
|
||
4. 常用出行人管理
|
||
5. 模拟支付结果
|
||
6. 我的订单与订单详情
|
||
7. 退款申请与退款结果
|
||
8. 我的凭证
|
||
|
||
后台管理端和员工核销端不在本次范围内。页面不接真实接口,使用结构化默认数据演示完整交互。刷新或重新进入页面后恢复默认数据。
|
||
|
||
## 技术方案
|
||
|
||
采用“单 uni-app 路由 + 同目录组件化状态流”。
|
||
|
||
- `src/pages-service/tickets/index.vue` 是唯一页面入口,负责共享业务状态、页面状态切换、来源记录和返回规则。
|
||
- 复杂视图拆为 `src/pages-service/tickets/components/` 下的 Vue 组件。
|
||
- 默认数据集中放在 `src/pages-service/tickets/data.js`。
|
||
- 价格、年龄、订单和退款等可独立验证的纯逻辑放在 `src/pages-service/tickets/model.mjs`。
|
||
- 在 `src/pages.json` 的 `pages-service` 分包注册 `tickets/index`,使用自定义导航。
|
||
|
||
页面内部不为每个步骤新增 uni-app 路由,以避免跨页传递预订草稿、游客和订单状态。首页左上角在没有内部历史时调用 `uni.navigateBack`;其余页面按进入来源返回。
|
||
|
||
## 组件边界
|
||
|
||
| 模块 | 职责 |
|
||
| --- | --- |
|
||
| `index.vue` | 页面状态编排、共享默认数据、返回策略、下单和退款命令 |
|
||
| `TicketHome.vue` | 景区头图、分类导航、商品分组、商品卡片与分类滚动联动 |
|
||
| `ProductDetail.vue` | 商品图片、价格、权益、使用说明、购买须知和预订入口 |
|
||
| `BookingFlow.vue` | 日期、场次、数量、游客、联系人、保险与提交订单 |
|
||
| `TravelerManager.vue` | 常用出行人列表、新增与选择 |
|
||
| `PaymentResult.vue` | 模拟支付成功信息以及订单、凭证入口 |
|
||
| `OrderList.vue` | 默认订单和本次新订单列表 |
|
||
| `OrderDetail.vue` | 状态、场次、游客、权益、费用、凭证与退款入口 |
|
||
| `RefundFlow.vue` | 退款权益选择、原因、预计金额和提交结果 |
|
||
| `CredentialsView.vue` | 第三方票务凭证与自营园内权益凭证 |
|
||
|
||
简单的商品卡片、状态标签和空状态可以继续拆为小组件,但不引入与当前需求无关的通用组件体系。
|
||
|
||
## 页面与交互
|
||
|
||
### 票务首页
|
||
|
||
- 顶部使用景区实景占位图,展示返回、常用出行人、我的订单、景区名称、等级、地址、联系电话和导航入口。
|
||
- 电话按钮调用 `uni.makePhoneCall`;导航按钮调用 `uni.openLocation`,若缺少平台能力则提示用户。
|
||
- 头图下方是一个统一圆角内容壳:左侧为固定分类栏,右侧为独立滚动商品区。
|
||
- 默认分类为景点门票,包含景点门票、VIP 速通、直通车、门票+观光车、一日游和玩乐体验。
|
||
- 点击左侧分类时将右侧对应分组标题滚动到内容区顶部;右侧滚动进入新分组时同步高亮左侧分类。
|
||
- 点击商品图片或标题进入详情;点击“选购”直接进入预订选择。
|
||
|
||
### 商品详情与预订
|
||
|
||
- 详情展示图片、短标题、价格、销量、标签、费用包含、费用不含、详情和购买须知。
|
||
- 预订先选择日期和场次,再选择数量、游客、联系人和可选保险。
|
||
- 实名商品要求游客数量不少于购买数量;年龄限制商品根据证件信息和使用日期校验年龄。
|
||
- 常用出行人可以直接勾选,也可以手动新增。新增数据只保留在当前页面会话。
|
||
- 提交前重新校验日期、场次、库存、游客、联系方式和年龄规则。
|
||
|
||
### 支付、订单、退款与凭证
|
||
|
||
- “提交订单并模拟支付”不会调用支付接口;它会生成一条已支付订单并扣减当前会话内的展示库存。
|
||
- 订单详情展示订单状态、使用场次、游客、联系手机、履约权益、费用、退款规则和支付时间。
|
||
- 支持选择可退款权益、选择退款原因并提交模拟退款。提交后更新订单、权益和退款状态。
|
||
- 第三方履约权益显示第三方票务凭证;自营权益显示园内权益凭证。二维码使用本地可渲染的视觉占位,不依赖远程二维码服务。
|
||
|
||
## 默认数据结构
|
||
|
||
### 景区
|
||
|
||
```js
|
||
{
|
||
id,
|
||
name,
|
||
level,
|
||
heritage,
|
||
address,
|
||
phone,
|
||
latitude,
|
||
longitude,
|
||
heroImage
|
||
}
|
||
```
|
||
|
||
### 商品分组
|
||
|
||
```js
|
||
{
|
||
id,
|
||
name,
|
||
subtitle,
|
||
description,
|
||
tag,
|
||
productIds,
|
||
sortOrder,
|
||
enabled
|
||
}
|
||
```
|
||
|
||
### 商品
|
||
|
||
```js
|
||
{
|
||
id,
|
||
name,
|
||
shortTitle,
|
||
category,
|
||
description,
|
||
salePrice,
|
||
marketPrice,
|
||
stock,
|
||
sold,
|
||
status,
|
||
highlights,
|
||
ageRule,
|
||
included,
|
||
excluded,
|
||
detail,
|
||
purchaseNotice,
|
||
images,
|
||
reservation: {
|
||
requiresDate,
|
||
advanceDays,
|
||
requiresTimeSlot,
|
||
timeSlots,
|
||
realNameRequired,
|
||
idTypes,
|
||
maxQuantity,
|
||
contactPhoneRequired
|
||
},
|
||
entitlements
|
||
}
|
||
```
|
||
|
||
### 出行人
|
||
|
||
```js
|
||
{
|
||
id,
|
||
name,
|
||
idType,
|
||
idNumber,
|
||
phone
|
||
}
|
||
```
|
||
|
||
### 订单
|
||
|
||
```js
|
||
{
|
||
id,
|
||
orderNo,
|
||
productId,
|
||
productName,
|
||
status,
|
||
visitDate,
|
||
timeSlot,
|
||
quantity,
|
||
travelers,
|
||
contactName,
|
||
phone,
|
||
productAmount,
|
||
insurance,
|
||
paidAmount,
|
||
paidAt,
|
||
entitlements,
|
||
gateCredential,
|
||
selfCredential,
|
||
refundStatus,
|
||
logs
|
||
}
|
||
```
|
||
|
||
### 页面状态
|
||
|
||
页面状态使用固定枚举:
|
||
|
||
```js
|
||
home
|
||
detail
|
||
booking
|
||
travelers
|
||
paid
|
||
orders
|
||
orderDetail
|
||
refundApply
|
||
refundResult
|
||
credentials
|
||
```
|
||
|
||
`index.vue` 同时记录当前商品、当前订单、预订草稿和页面来源,避免组件自行修改跨页面业务数据。子组件只通过 props 接收数据,并通过 emits 发出明确事件。
|
||
|
||
## 视觉与样式
|
||
|
||
- 所有新增或调整的布局使用可静态扫描的 Tailwind CSS 完整类名。
|
||
- 不新增 SCSS 布局类,不通过字符串拼接生成 Tailwind 类名。
|
||
- 首页复刻截图中的大幅景区头图、深色渐变遮罩、白色景区信息、统一圆角票务内容壳、左侧绿色分类高亮、浅灰商品区域、白色商品卡片和橙色购买按钮。
|
||
- 内页延续白色卡片、浅灰背景、蓝色信息标签和橙色主操作的视觉语言。
|
||
- 景区头图和所有商品图片统一使用:
|
||
`https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/oneFeel/2082673896938569729.jpg`
|
||
- 页面适配微信小程序常见手机宽度,并保留安全区底部间距。
|
||
|
||
## 校验、异常和空状态
|
||
|
||
- 未选择日期或场次、购买数量无效、游客数量不足、实名信息不完整、年龄不符、联系人缺失、退款权益未选择时禁止提交,并用 `uni.showToast` 提供明确提示。
|
||
- 日期或场次无库存时显示售罄并不可选。
|
||
- 商品、订单、出行人均提供空状态,避免默认数组被清空时页面失去反馈。
|
||
- 电话、地图等平台能力失败时不阻断主流程,只显示失败提示。
|
||
- 默认数据不需要网络加载,因此不设计加载失败重试。
|
||
|
||
## 测试与验收
|
||
|
||
采用 Node 内置测试能力验证 `model.mjs` 中的纯逻辑,并遵循测试先行:
|
||
|
||
- 商品总价与保险价格计算
|
||
- 身份证年龄与适用年龄判断
|
||
- 预订草稿必填项验证
|
||
- 模拟订单生成及权益拆分
|
||
- 退款金额计算与状态更新
|
||
- 页面状态返回规则
|
||
|
||
实现后执行:
|
||
|
||
```bash
|
||
node --test src/pages-service/tickets/model.test.mjs
|
||
git diff --check
|
||
yarn build:mp-weixin
|
||
```
|
||
|
||
人工验收完整点击链路:首页分类联动、商品详情、直接选购、日期场次、游客选择/新增、模拟支付、订单列表、订单详情、凭证、退款申请和退款结果。
|
||
|
||
## 非目标
|
||
|
||
- 不迁移后台管理端或员工核销端。
|
||
- 不接入商品、库存、支付、出票、退款和地图等真实服务。
|
||
- 不实现本地持久化、登录校验或跨设备订单同步。
|
||
- 不修改 `src/uni_modules/` 或现有票务以外业务页面。
|