DIP1 P3-B 师傅端 + 客户端业务测试 · 亲手操作指南¶
| 字段 | 值 |
|---|---|
| 指南编号 | DWLG-20260811-04 |
| 关联文档 | DWLG-20260811-02(P3-B 测试报告)/ 03(C-B7 师傅账号接入) |
| 目标 | 指导 TL 亲手执行师傅端 + 客户端全链路业务测试 |
| 预计耗时 | 30-45 分钟 |
| 后端地址 | http://localhost:8000/api/v1 |
| 执行日期 | 2026-08-11 |
〇、测试准备¶
0.1 环境确认¶
在 PowerShell 中执行,确认后端服务正常:
curl -s -o NUL -w "HTTP %{http_code}`n" http://localhost:8000/health
# 预期:HTTP 200
0.2 测试账号清单¶
师傅账号(C-B7 已接入)¶
| 账号 | 密码 | 师傅 | 手机号 | 级别 | 被指派订单数 |
|---|---|---|---|---|---|
| worker_uat_0001 | worker123 | 張師傅 | +85291130001 | L1 | 5 单(L4×2, L5, L6, L8) |
| worker_uat_0002 | worker123 | 劉師傅 | +85291130002 | L1 | - |
| worker_uat_0006 | worker123 | 周師傅 | +85291130006 | L3 | - |
客户账号(OTP 登录)¶
| 手机号 | 客户名 | 订单情况 |
|---|---|---|
| +85292230009 | 周太 | 2 单(L2 橱柜 676HKD + L6 电视柜 280HKD) |
| +85292230010 | 吴生 | 2 单(L2 + L7) |
| +85292230017 | 唐太 | 1 单(L8) |
管理员账号¶
| 账号 | 密码 | 角色 |
|---|---|---|
| admin | admin123 | TL(全权限) |
0.3 工具选择¶
| 工具 | 适用场景 | 推荐度 |
|---|---|---|
| PowerShell + curl | 本指南默认方式,可直接复制 | ⭐⭐⭐⭐⭐ |
| Apifox / Postman | 可视化 API 测试,支持环境变量 | ⭐⭐⭐⭐ |
| 浏览器 Swagger UI | http://localhost:8000/docs 交互式文档 | ⭐⭐⭐ |
本指南所有命令均在 PowerShell 中执行,可直接复制粘贴。
0.4 通用说明¶
- 所有请求的
Content-Type: application/json - Token 有效期 15 分钟,过期后需重新登录
- 师傅 token 的
role=FL,受 RLS 限制只能看自己的订单 - 客户 token 的
role=CST,受 RLS 限制只能看自己的订单
第一部分:师傅端业务测试(10 步)¶
Step W1:师傅账密登录 ⭐核心¶
操作说明:使用师傅账号 worker_uat_0001 登录,获取 access_token。
$workerResp = Invoke-RestMethod -Uri "http://localhost:8000/api/v1/auth/login" `
-Method Post -Body '{"username":"worker_uat_0001","password":"worker123"}' `
-ContentType "application/json"
$workerToken = $workerResp.access_token
$workerHeaders = @{"Authorization"="Bearer $workerToken"; "Content-Type"="application/json"}
$workerResp.user | ConvertTo-Json
预期响应:
{
"user_id": "USR-WKR-UAT0000001",
"username": "worker_uat_0001",
"display_name": "張師傅",
"roles": ["FL"],
"permissions": ["cpt:list:self"]
}
✅ 验证点:
- [ ] roles 包含 FL(一线师傅)
- [ ] display_name = "張師傅"
- [ ] permissions = ["cpt:list:self"](只能看自己的订单)
Step W2:师傅 OTP 登录(可选)¶
操作说明:使用师傅手机号 +85291130001 通过 OTP 登录。
$send = Invoke-RestMethod -Uri "http://localhost:8000/api/v1/auth/otp-send" `
-Method Post -Body '{"whatsapp":"+85291130001"}' `
-ContentType "application/json"
Write-Host "收到 OTP: $($send.otp)"
Start-Sleep -Seconds 1
$verify = Invoke-RestMethod -Uri "http://localhost:8000/api/v1/auth/otp-verify" `
-Method Post -Body "{`"otp_session_id`":`"$($send.otp_session_id)`",`"otp_code`":`"$($send.otp)`"}" `
-ContentType "application/json"
Write-Host "师傅 OTP 登录成功,worker_id: $($verify.customer_id)"
预期响应:customer_id 字段返回 WKR0UAT0000001(师傅场景返回 worker_id)。
✅ 验证点:
- [ ] OTP 6 位数字回显(开发环境)
- [ ] customer_id 以 WKR 开头(师傅身份判定正确)
Step W3:查看师傅个人信息(冷启动 hydrate)¶
操作说明:调用 /auth/me 获取当前登录师傅信息(模拟 App 冷启动后的会话恢复)。
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/auth/me" -Headers $workerHeaders | ConvertTo-Json
预期响应:
{
"user_id": "USR-WKR-UAT0000001",
"username": "worker_uat_0001",
"display_name": "張師傅",
"roles": ["FL"],
"worker_id": "WKR0UAT0000001"
}
✅ 验证点:
- [ ] worker_id = WKR0UAT0000001
- [ ] roles 包含 FL
Step W4:查看工作看板 ⭐核心¶
操作说明:师傅端首页看板,查看 6 个订单池的分组统计。
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cpt/orders/board" -Headers $workerHeaders | ConvertTo-Json -Depth 3
预期响应:返回 6 个池(POOL_L1_NEW_LEADS / POOL_L3_PENDING_QUOTE / POOL_L4_PENDING_ASSIGN / POOL_L6_INSTALL_TODAY / POOL_L8_PENDING_FOLLOWUP / POOL_EXCEPTION),每个池包含 count 和 items。
✅ 验证点:
- [ ] 6 个池全部返回
- [ ] POOL_L4_PENDING_ASSIGN 或 POOL_L6_INSTALL_TODAY 有订单(張師傅有 L4/L6 订单)
- [ ] 池中订单的 assigned_worker_id 都是 WKR0UAT0000001(RLS 限定)
Step W5:查看订单列表(按阶段筛选)¶
操作说明:查看师傅被指派的所有订单,并按 L6 阶段筛选。
# 查看所有订单
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cpt/orders?page=1&page_size=20" -Headers $workerHeaders | ConvertTo-Json -Depth 2
# 按 L6 筛选
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cpt/orders?stage=L6&page=1&page_size=10" -Headers $workerHeaders | ConvertTo-Json -Depth 2
预期响应:total=5(5 个被指派订单),L6 筛选后 total=1(订单 ORD0UAT0000036 周太 电视柜 280HKD)。
✅ 验证点:
- [ ] total = 5
- [ ] 所有订单的 assigned_worker_id = WKR0UAT0000001
- [ ] L6 筛选返回 1 个订单(ORD0UAT0000036)
Step W6:查看订单详情 ⭐核心¶
操作说明:查看 L6 订单(周太 电视柜)的完整详情,包含阶段时间线、报价、附件、审计日志。
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cpt/orders/ORD0UAT0000036" -Headers $workerHeaders | ConvertTo-Json -Depth 4
预期响应:包含 order_id / stage=L6 / customer_name=周太 / stages[](阶段时间线)/ attachments[] / audit_log[] 等字段。
✅ 验证点:
- [ ] order_id = ORD0UAT0000036
- [ ] stage = L6
- [ ] customer_name = 周太
- [ ] stages 是数组,包含 L1-L6 阶段记录
- [ ] attachments 字段存在(即使为空数组)
- [ ] audit_log 字段存在
Step W7:查看订单报价¶
操作说明:查看 L6 订单的报价详情(含因子展开)。
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cpt/orders/ORD0UAT0000036/quote" -Headers $workerHeaders | ConvertTo-Json -Depth 3
预期响应:包含 quote_id / final_hkd=280.00 / base_fee_hkd / factor_total / factor_breakdown(JSON 展开各因子系数)。
✅ 验证点:
- [ ] final_hkd = 280.00
- [ ] status = CONFIRMED(已确认报价)
- [ ] factor_breakdown 包含 category_base 等因子
Step W8:接单流转(L4 → L5 配送)⭐核心¶
操作说明:取一个 L4 阶段订单,执行状态流转 L4→L5(确认配送)。
# 先取一个 L4 订单
$l4Orders = (Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cpt/orders?stage=L4&page=1&page_size=5" -Headers $workerHeaders).items
$l4Orders | Select-Object order_id, stage, customer_name | Format-Table
# 执行 L4 → L5 流转(用第一个 L4 订单)
if ($l4Orders) {
$oid = $l4Orders[0].order_id
Write-Host "对订单 $oid 执行 L4→L5 流转"
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cpt/orders/$oid/transition" `
-Method Post -Body '{"to_stage":"L5"}' -Headers $workerHeaders | ConvertTo-Json
}
预期响应:返回 {"order_id":"...","stage":"L5","status":"IN_PROGRESS"}。
✅ 验证点:
- [ ] 流转后 stage = L5
- [ ] 订单状态变更记录写入审计日志
⚠️ 注意:此操作会改变订单状态,重复执行同一订单会返回 409(状态机不允许 L5→L5)。
Step W9:注册推送 Token¶
操作说明:模拟师傅端 App 注册 Expo Push Token(用于接收推送通知)。
$pushBody = @{
push_token = "ExponentPushToken[manual-test-worker-001]"
platform = "IOS"
app_type = "WKR"
app_version = "1.0.0"
device_id = "device-worker-manual-001"
} | ConvertTo-Json
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/push/register" `
-Method Post -Body $pushBody -Headers $workerHeaders | ConvertTo-Json
预期响应:{"token_id":"...","status":"REGISTERED"}。
✅ 验证点:
- [ ] status = REGISTERED(首次注册)
二次注册验证幂等性:
# 同一 push_token 再注册一次
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/push/register" `
-Method Post -Body $pushBody -Headers $workerHeaders | ConvertTo-Json
# 预期 status="UPDATED"(幂等更新)
✅ 验证点:
- [ ] 二次注册 status = UPDATED(C-B7 修复的 upsert 幂等性)
Step W10:RLS 权限验证(越权访问拦截)⭐安全红线¶
操作说明:尝试访问不分配给当前师傅的订单,验证 RLS 拦截。
# ORD0UAT0000001 不是分配给 worker_uat_0001 的订单
try {
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cpt/orders/ORD0UAT0000001" -Headers $workerHeaders
} catch {
$err = $_.Exception.Response
Write-Host "HTTP 状态码: $([int]$err.StatusCode)"
$reader = New-Object System.IO.StreamReader($err.GetResponseStream())
Write-Host "错误信息: $($reader.ReadToEnd())"
}
预期响应:HTTP 403 Forbidden,{"code":1002,"message":"无权限查看该订单(仅可查看本人被指派订单)"}。
✅ 验证点: - [ ] HTTP 状态码 = 403 - [ ] 错误信息包含"无权限" - [ ] 师傅无法越权访问他人订单
第二部分:客户端业务测试(12 步)¶
Step C1:客户 OTP 登录 ⭐核心¶
操作说明:客户周太(+85292230009)通过 OTP 登录。
$send = Invoke-RestMethod -Uri "http://localhost:8000/api/v1/auth/otp-send" `
-Method Post -Body '{"whatsapp":"+85292230009"}' `
-ContentType "application/json"
Write-Host "收到 OTP: $($send.otp)"
Start-Sleep -Seconds 1
$verify = Invoke-RestMethod -Uri "http://localhost:8000/api/v1/auth/otp-verify" `
-Method Post -Body "{`"otp_session_id`":`"$($send.otp_session_id)`",`"otp_code`":`"$($send.otp)`"}" `
-ContentType "application/json"
$custToken = $verify.access_token
$custHeaders = @{"Authorization"="Bearer $custToken"; "Content-Type"="application/json"}
Write-Host "客户登录成功,customer_id: $($verify.customer_id)"
预期响应:customer_id = CUS0UAT0000009(周太)。
✅ 验证点:
- [ ] OTP 6 位数字回显
- [ ] customer_id 以 CUS 开头(客户身份)
Step C2:查看客户个人信息¶
操作说明:查看客户档案(WhatsApp 脱敏展示)。
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/profile" -Headers $custHeaders | ConvertTo-Json -Depth 3
预期响应:包含 customer_id / name=周太 / whatsapp(脱敏如 +852-****) / total_orders / trust_badges 等字段。
✅ 验证点:
- [ ] name = 周太
- [ ] whatsapp 字段脱敏(不显示完整号码)
- [ ] customer_id = CUS0UAT0000009
Step C3:浏览首页品类¶
操作说明:客户端首页浏览 8 大品类入口。
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/categories" -Headers $custHeaders | ConvertTo-Json -Depth 2
预期响应:返回品类列表,每个品类包含 category_id / code / name_zh / base_fee_hkd / cap_price_hkd。
✅ 验证点:
- [ ] 至少 6 个品类
- [ ] 每个品类有 cap_price_hkd(封顶价)
- [ ] 品类包含床架(BED)/橱柜(KITCHEN_CABINET)/电视柜(TV_CABINET)等
Step C4:询价提交 ⭐核心¶
操作说明:提交一个询价表单,生成新订单(L1→L2)。
$inquiryBody = @{
category_id = "CAT2997234892DCFEB4907651" # 橱柜品类
product_model = "欧派 OP-1800"
size_info = "长1800×宽600×高850mm"
address = "新界沙田第一城 12 座 8 楼 3 室"
building_id = "BLD0UAT0000001"
preferred_slot = @{
date = "2026-08-20"
slot = "AM"
}
site_conditions = @{
elevator = $true
floor = 8
parking = $true
}
} | ConvertTo-Json -Depth 3
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/inquiries" `
-Method Post -Body $inquiryBody -Headers $custHeaders | ConvertTo-Json
预期响应:{"order_id":"ORD0UAT...","stage":"L2","lead_source":"CST_APP_SELF"}。
✅ 验证点:
- [ ] 返回 order_id(新生成的订单 ID)
- [ ] stage = L2
- [ ] lead_source = CST_APP_SELF(客户端自助询价)
Step C5:查看我的订单列表¶
操作说明:查看客户的所有订单。
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/orders?status=ALL&page=1&page_size=20" -Headers $custHeaders | ConvertTo-Json -Depth 2
预期响应:total ≥ 2(周太原有 2 单 + 刚询价的新单),包含订单基本信息。
✅ 验证点:
- [ ] total ≥ 2
- [ ] 包含 ORD0UAT0000009(L2 橱柜 676HKD)和 ORD0UAT0000036(L6 电视柜 280HKD)
- [ ] 询价生成的新订单出现在列表中
Step C6:查看订单详情 + Timeline ⭐核心¶
操作说明:查看 L6 订单的完整 Timeline(L1-L8 阶段时间线)。
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/orders/ORD0UAT0000036" -Headers $custHeaders | ConvertTo-Json -Depth 4
预期响应:包含 order_id / current_stage=L6 / timeline[](L1-L6 阶段记录)/ quote(报价信息)/ worker(师傅信息)。
✅ 验证点:
- [ ] current_stage = L6
- [ ] timeline 数组包含多个阶段节点
- [ ] quote 字段存在(报价已生成)
- [ ] worker 字段存在(师傅已派单)
Step C7:查看报价(含因子展开) ⭐核心一致性¶
操作说明:查看 L2 订单的报价详情。
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/orders/ORD0UAT0000009/quote" -Headers $custHeaders | ConvertTo-Json -Depth 3
预期响应:包含 quote_id / final_hkd=676.00 / base_fee_hkd / factor_total / factor_breakdown。
✅ 验证点:
- [ ] final_hkd = 676.00
- [ ] status = DRAFT(待确认)或 CONFIRMED
- [ ] factor_breakdown 包含因子展开
💡 三端一致性验证:此金额应与运营后台(admin token)查看的同一订单报价金额一致。
Step C8:确认报价 ⭐核心¶
操作说明:确认 L2 订单的报价(L2→L3 流转)。
try {
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cpt/orders/ORD0UAT0000009/quote/confirm" `
-Method Post -Body '{"action":"CONFIRM"}' -Headers $custHeaders | ConvertTo-Json
} catch {
$err = $_.Exception.Response
Write-Host "HTTP 状态码: $([int]$err.StatusCode)"
# 409 = 报价已被前次测试确认过(幂等保护),视为通过
if ([int]$err.StatusCode -eq 409) {
Write-Host "报价已被确认过(409 幂等保护),视为通过"
}
}
⚠️ 注意:客户端确认报价的端点是
/cst/orders/{id}/quote/confirm,不是/cpt/orders/。如果上面的端点报 404,请改用:Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/orders/ORD0UAT0000009/quote/confirm" ` -Method Post -Body '{"action":"CONFIRM"}' -Headers $custHeaders | ConvertTo-Json
预期响应:{"order_id":"...","quote_id":"...","status":"CONFIRMED"}。
✅ 验证点:
- [ ] status = CONFIRMED(或 409 幂等保护)
- [ ] 订单阶段从 L2 流转到 L3
Step C9:查看师傅信息(脱敏) ⭐安全红线¶
操作说明:查看 L6 订单已派单师傅的公开信息(脱敏,不返回电话)。
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/orders/ORD0UAT0000036/worker" -Headers $custHeaders | ConvertTo-Json -Depth 2
预期响应:包含 worker_id / display_name=張師傅 / level=L1 / avg_nps / total_orders,不包含 phone / whatsapp 字段。
✅ 验证点:
- [ ] display_name = 張師傅
- [ ] 无 phone 字段(脱敏)
- [ ] 无 whatsapp 字段(脱敏)
- [ ] avg_nps 和 total_orders 有值
Step C10:提交服务评价 ⭐核心¶
操作说明:对 L8 阶段订单提交评价(NPS + 星级 + 文字)。
# 先查看是否有 L8 订单(用唐太 +85292230017 登录)
$send2 = Invoke-RestMethod -Uri "http://localhost:8000/api/v1/auth/otp-send" `
-Method Post -Body '{"whatsapp":"+85292230017"}' -ContentType "application/json"
Start-Sleep -Seconds 1
$verify2 = Invoke-RestMethod -Uri "http://localhost:8000/api/v1/auth/otp-verify" `
-Method Post -Body "{`"otp_session_id`":`"$($send2.otp_session_id)`",`"otp_code`":`"$($send2.otp)`"}" `
-ContentType "application/json"
$tangToken = $verify2.access_token
$tangHeaders = @{"Authorization"="Bearer $tangToken"; "Content-Type"="application/json"}
# 查看唐太的订单
$tangOrders = (Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/orders?status=ALL&page=1&page_size=5" -Headers $tangHeaders).items
$tangOrders | Select-Object order_id, stage, category_name | Format-Table
# 对 L8 订单提交评价
$l8Order = $tangOrders | Where-Object { $_.stage -eq "L8" } | Select-Object -First 1
if ($l8Order) {
$reviewBody = @{
nps_score = 9
star_rating = 5
text_review = "張師傅安裝非常專業,準時到達,安裝後清理乾淨,強烈推薦!"
photo_urls = @()
} | ConvertTo-Json
try {
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/orders/$($l8Order.order_id)/review" `
-Method Post -Body $reviewBody -Headers $tangHeaders | ConvertTo-Json
} catch {
$err = $_.Exception.Response
if ([int]$err.StatusCode -eq 409) {
Write-Host "订单已评价过(409 幂等保护),视为通过"
}
}
}
预期响应:{"order_id":"...","nps_score":9,"star_rating":5,"status":"RECORDED"}。
✅ 验证点:
- [ ] status = RECORDED(或 409 幂等保护)
- [ ] nps_score = 9
- [ ] star_rating = 5
Step C11:生成推荐码¶
操作说明:生成/查询客户的推荐码(用于口碑营销)。
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/referral/code" `
-Method Post -Headers $custHeaders | ConvertTo-Json -Depth 2
预期响应:包含 referral_code / share_link。
✅ 验证点:
- [ ] referral_code 不为空(6 位大写字母数字)
- [ ] share_link 不为空
二次生成验证幂等性:
# 同一客户再生成一次,应返回相同推荐码
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/referral/code" `
-Method Post -Headers $custHeaders | ConvertTo-Json
✅ 验证点:
- [ ] 二次生成返回相同的 referral_code
Step C12:推送偏好查询与更新¶
操作说明:查看和修改推送偏好(8 类推送开关)。
# 查询当前推送偏好
Write-Host "=== 当前推送偏好 ==="
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/push-preferences" -Headers $custHeaders | ConvertTo-Json
# 关闭"系统通知"推送
$updateBody = '{"PUSH_SYSTEM":false}' | ConvertTo-Json
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/push-preferences" `
-Method Put -Body '{"PUSH_SYSTEM":false}' -Headers $custHeaders | ConvertTo-Json
# 再查询确认已关闭
Write-Host "=== 修改后推送偏好 ==="
Invoke-RestMethod -Uri "http://localhost:8000/api/v1/cst/push-preferences" -Headers $custHeaders | ConvertTo-Json
预期响应:8 类推送开关(PUSH_NEW_ORDER / PUSH_ORDER_REMINDER_1H / PUSH_ORDER_STATUS / PUSH_WORKER_DEPARTED / PUSH_REVIEW_INVITE / PUSH_REFERRAL_REWARD / PUSH_QUOTE_READY / PUSH_SYSTEM)。
✅ 验证点:
- [ ] 8 类推送开关全部返回
- [ ] 修改 PUSH_SYSTEM=false 后,再查询确认 PUSH_SYSTEM=false
- [ ] 其他开关保持不变
第三部分:验收 Checklist¶
师傅端验收(10 项)¶
| # | 验收项 | 验证结果 |
|---|---|---|
| W1 | 师傅账密登录返回 role=FL + worker_id | ☐ 通过 ☐ 失败 |
| W2 | 师傅 OTP 登录签发 FL token | ☐ 通过 ☐ 失败 |
| W3 | /auth/me 返回师傅信息 | ☐ 通过 ☐ 失败 |
| W4 | 看板 6 池结构完整 | ☐ 通过 ☐ 失败 |
| W5 | 订单列表 RLS 限定自己的订单 | ☐ 通过 ☐ 失败 |
| W6 | 订单详情字段完整(timeline+attachments+audit) | ☐ 通过 ☐ 失败 |
| W7 | 报价查看含因子展开 | ☐ 通过 ☐ 失败 |
| W8 | 接单流转 L4→L5 成功 | ☐ 通过 ☐ 失败 |
| W9 | Push Token 注册 + 幂等 UPDATED | ☐ 通过 ☐ 失败 |
| W10 | RLS 越权访问 → 403 | ☐ 通过 ☐ 失败 |
客户端验收(12 项)¶
| # | 验收项 | 验证结果 |
|---|---|---|
| C1 | 客户 OTP 登录签发 CST token | ☐ 通过 ☐ 失败 |
| C2 | 个人档案 WhatsApp 脱敏 | ☐ 通过 ☐ 失败 |
| C3 | 首页 ≥6 品类 + 封顶价 | ☐ 通过 ☐ 失败 |
| C4 | 询价提交生成订单 L2 + lead_source | ☐ 通过 ☐ 失败 |
| C5 | 我的订单列表正确 | ☐ 通过 ☐ 失败 |
| C6 | 订单 Timeline L1-L8 完整 | ☐ 通过 ☐ 失败 |
| C7 | 报价金额与运营后台一致 | ☐ 通过 ☐ 失败 |
| C8 | 确认报价 L2→L3(或 409 幂等) | ☐ 通过 ☐ 失败 |
| C9 | 师傅信息脱敏(无 phone/whatsapp) | ☐ 通过 ☐ 失败 |
| C10 | L8 评价提交 NPS+星级 | ☐ 通过 ☐ 失败 |
| C11 | 推荐码生成 + 幂等 | ☐ 通过 ☐ 失败 |
| C12 | 推送偏好 8 类开关可读写 | ☐ 通过 ☐ 失败 |
安全红线验收(5 项)¶
| # | 验收项 | 验证结果 |
|---|---|---|
| S1 | 师傅 RLS 只看自己订单(W10) | ☐ 通过 ☐ 失败 |
| S2 | 客户 RLS 只看自己订单 | ☐ 通过 ☐ 失败 |
| S3 | 师傅信息脱敏(C9) | ☐ 通过 ☐ 失败 |
| S4 | 客户 WhatsApp 脱敏(C2) | ☐ 通过 ☐ 失败 |
| S5 | 重复操作幂等保护(W9/C8/C10/C11) | ☐ 通过 ☐ 失败 |
附录:常用排障¶
A.1 Token 过期¶
Token 有效期 15 分钟,过期后需重新登录:
# 重新登录获取新 token
$workerResp = Invoke-RestMethod -Uri "http://localhost:8000/api/v1/auth/login" `
-Method Post -Body '{"username":"worker_uat_0001","password":"worker123"}' `
-ContentType "application/json"
$workerToken = $workerResp.access_token
$workerHeaders = @{"Authorization"="Bearer $workerToken"; "Content-Type"="application/json"}
A.2 OTP 60 秒频控¶
同一手机号 60 秒内只能发送一次 OTP,第二次会返回 429。如需重新发送,等待 60 秒或更换手机号。
A.3 后端服务未启动¶
# 检查后端健康
curl -s -o NUL -w "HTTP %{http_code}`n" http://localhost:8000/health
# 如果不是 200,启动后端:
cd D:\AC\TF\hk2026\dip1\backend
D:\AC\TF\hk2026\dip1\backend\.venv312\Scripts\python.exe -m uvicorn app.main:create_app --factory --port 8000
A.4 Swagger UI 交互式文档¶
浏览器打开 http://localhost:8000/docs,可直接在页面上测试所有 API。
修订记录¶
| 版本 | 日期 | 修订人 | 修订内容 |
|---|---|---|---|
| V1.0 | 2026-08-11 | DT | 初版:师傅端 10 步 + 客户端 12 步 + 验收 Checklist 22 项 + 安全红线 5 项 |
本指南对齐 DIP1-WLG V1.1 规范,编号 DWLG-20260811-04。