| # | 测试步骤 | 预期结果 | 通过 |
|---|---|---|---|
| 1 | 浏览器打开 https://letcareme.com |
显示登录表单 (用户名+密码) | |
| 2 | 输入错误密码, 点登录 | 显示错误提示, 不跳转 | |
| 3 | 输入 admin / CKdyRPSqJA5KZTXuR8Qgfg, 点登录 |
跳转到 /dashboard |
|
| 4 | 未登录直接访问 /dashboard |
自动重定向到 / 登录页 |
| # | 测试步骤 | 预期结果 | 通过 |
|---|---|---|---|
| 5 | 登录后查看 dashboard | 显示今日统计卡片 (对话数/分析数/告警数) | |
| 6 | 检查左侧 sidebar | 含: 今日概览/买家全景/案例库/对话复盘/流失预警/每日日报/话术库/登录日志/用户管理/系统设置 | |
| 7 | 点击深色/浅色模式切换按钮 | 主题正确切换 |
| # | 测试步骤 | 预期结果 | 通过 |
|---|---|---|---|
| 8 | 点击 sidebar "买家全景" | 显示买家列表 (应有 16 条) | |
| 9 | 点击某个买家行 | 展开详情, 显示 insights (情感分析/购买意向) | |
| 10 | 使用搜索框输入买家昵称 | 过滤结果正确 |
| # | 测试步骤 | 预期结果 | 通过 |
|---|---|---|---|
| 11 | 点击 sidebar "案例库" | 显示案例列表 (应有 19 条) | |
| 12 | 翻页 (如有分页) | 分页正常, 数据不重复 | |
| 13 | 点击 CSV 导出按钮 | 下载 .csv 文件, 内容完整 |
| # | 测试步骤 | 预期结果 | 通过 |
|---|---|---|---|
| 14 | 点击 sidebar "话术库" | 显示话术列表 (3+ 条) | |
| 15 | 使用状态筛选: "草稿" | 仅显示 draft 状态话术 | |
| 16 | 使用状态筛选: "已批准" | 仅显示 active 状态话术 | |
| 17 | 点击 "新建话术" | 弹出表单, 可输入名称/内容/场景 | |
| 18 | 填写话术并提交 | 创建成功, 状态为 "草稿" | |
| 19 | 对草稿话术点击 "审批" | 状态变为 "已批准" | |
| 20 | 对已批准话术点击 "下架" | 状态变为 "已下架" |
| # | 测试步骤 | 预期结果 | 通过 |
|---|---|---|---|
| 21 | 点击 sidebar "对话复盘" | 显示对话列表 |
| # | 测试步骤 | 预期结果 | 通过 |
|---|---|---|---|
| 22 | 点击 sidebar "流失预警" | 显示预警列表 (可为空) |
| # | 测试步骤 | 预期结果 | 通过 |
|---|---|---|---|
| 23 | 点击 sidebar "每日日报" | 显示日报列表 | |
| 24 | 选择日期 | 加载对应日期日报 (无数据显示空) |
| # | 测试步骤 | 预期结果 | 通过 |
|---|---|---|---|
| 25 | 点击 sidebar "登录日志" | 显示登录记录 (含本次登录) | |
| 26 | 翻页 | 分页正常 |
| # | 测试步骤 | 预期结果 | 通过 |
|---|---|---|---|
| 27 | 点击 sidebar "用户管理" | 显示用户列表 |
| # | 测试步骤 | 预期结果 | 通过 |
|---|---|---|---|
| 28 | 点击 sidebar "系统设置" | 显示 LLM Key 配置界面 | |
| 29 | 查看已配置的 Key | Key 显示为脱敏格式 (****xxxx) |
|
| 30 | 修改密码 (底部按钮) | 弹出修改密码对话框 |
ssh root@8.138.11.105 "docker exec qn-api printenv QN_INTERNAL_TOKEN"
| # | 命令 | 预期 | 通过 |
|---|---|---|---|
| 31 | curl https://letcareme.com/health |
200, {"status":"ok"} |
|
| 32 | curl http://127.0.0.1:8007/ready |
200, 含 checks 对象 | |
| 33 | curl http://127.0.0.1:8007/api/v1/qianniu-pc/version |
200, {"latest":"0.8.0"} |
| # | 命令 | 预期 | 通过 |
|---|---|---|---|
| 34 | curl http://127.0.0.1:8007/api/v1/config (无 token) |
401 | |
| 35 | curl -X POST http://127.0.0.1:8007/api/v1/analyze (无 token) |
401 | |
| 36 | curl http://127.0.0.1:8007/api/v1/scripts (无 token) |
401 | |
| 37 | curl http://127.0.0.1:8007/api/v1/qianniu-pc/sellers (无 token) |
401 | |
| 38 | curl -H "X-Internal-Token: WRONG" http://127.0.0.1:8007/api/v1/config |
401 |
-H "X-Internal-Token: $TOKEN"
| # | 端点 | 方法 | 预期状态 | 验证点 | 通过 |
|---|---|---|---|---|---|
| 39 | /api/v1/config | GET | 200 | 含 has_dashscope_key 字段 | |
| 40 | /api/v1/scripts | GET | 200 | 返回话术数组 | |
| 41 | /api/v1/qianniu-pc/today-stats | GET | 200 | 含 conversations/analyzed 计数 | |
| 42 | /api/v1/qianniu-pc/buyers | GET | 200 | 返回买家列表 | |
| 43 | /api/v1/qianniu-pc/cases | GET | 200 | 返回案例列表 | |
| 44 | /api/v1/qianniu-pc/cases.csv | GET | 200 | Content-Type 含 csv | |
| 45 | /api/v1/qianniu-pc/churn-alerts | GET | 200 | 返回告警数组 | |
| 46 | /api/v1/qianniu-pc/status | GET | 200 | 含 events_24h 计数 | |
| 47 | /api/v1/qianniu-pc/cost-status | GET | 200 | 含 daily_limit_usd | |
| 48 | /api/v1/qianniu-pc/sellers | GET | 200 | 返回卖家列表 | |
| 49 | /api/v1/qianniu-pc/cookie-status | GET | 200 | 含 nick + h5tk_valid | |
| 50 | /api/v1/qianniu-pc/account | GET | 200 | 返回账户信息 | |
| 51 | /api/v1/qianniu-pc/settings/llm-keys | GET | 200 | Key 脱敏显示 | |
| 52 | /api/v1/qianniu-pc/settings/models | GET | 200 | 模型配置列表 | |
| 53 | /api/v1/playbooks/stats | GET | 200 | 含 total_triggers | |
| 54 | /api/v1/playbooks/list | GET | 200 | playbook 数组 | |
| 55 | /api/v1/daily-reports | GET | 200 | 日报列表 | |
| 56 | /api/v1/qianniu-pc/buyer-insights/{nick} | GET | 200 | insight 记录 |
| # | 端点 | 方法 | 请求体 | 预期 | 通过 |
|---|---|---|---|---|---|
| 57 | /api/v1/scripts | POST | {"name":"测试话术","content":"您好","scene":"greeting"} | 201, 返回 id | |
| 58 | /api/v1/scripts/{id} | GET | — | 200, 状态 draft | |
| 59 | /api/v1/scripts/{id}/approve | POST | — | 200, 状态变 active | |
| 60 | /api/v1/scripts/{id}/retire | POST | — | 200, 状态变 deprecated | |
| 61 | /api/v1/scripts/{id} | PUT | {"content":"更新"} | 409 (deprecated 禁改) | |
| 62 | /api/v1/qianniu-pc/notify-change | POST | {"hash":"x","seller_id":"test","worker_id":"w1"} | 200 或 422 | |
| 63 | /api/v1/daily-reports/trigger | POST | — | 200, accepted | |
| 64 | /api/v1/scripts/assist/suggest | POST | {"scene":"greeting","buyer_msg":"你好"} | 200 (LLM 建议) 或 429 | |
| 65 | /api/v1/qianniu-pc/analyze-conversation | POST | {"worker_id":"w","buyer_nick":"test","messages":[]} | 200 或 422 | |
| 66 | /api/v1/qianniu-pc/append-messages | POST | {"sid":"test","messages":[]} | 200 或 422 | |
| 67 | /api/v1/qianniu-pc/reanalyze/{nick} | POST | — | 200 触发重分析 | |
| 68 | /api/v1/qianniu-pc/refresh-cookie | POST | {"cookie":"..."} | 200 或 422 | |
| 69 | /api/v1/qianniu/send-reply | POST | {"buyer_nick":"test","content":"你好"} | 200 或 422 | |
| 70 | /api/v1/qianniu/send-reply/probe | POST | — | 200 (probe disabled) | |
| 71 | /api/v1/qianniu-pc/buyer-cache/{nick} | GET | — | 200 或 404 (无缓存) | |
| 72 | /api/v1/daily-reports/{date} | GET | — | 200 或 404 (无该日报告) | |
| 73 | /api/v1/qianniu-pc/settings/llm-keys | PUT | {"provider":"qwen","api_key":"sk-test"} | 200 | |
| 74 | /api/v1/qianniu-pc/settings/llm-keys/test | POST | {"provider":"qwen","api_key":"sk-test"} | 200 或 422 | |
| 75 | /api/v1/qianniu-pc/settings/models | PUT | {"screenshot":"qwen-vl-max"} | 200 |
| # | 端点 | 请求体 | 预期 | 通过 |
|---|---|---|---|---|
| 76 | POST /api/activate |
{"license_key":"SHORT"} |
400/422 (格式错误) | |
| 77 | POST /api/activate |
{"license_key":"AAAAAAAAAAAAAAAA"} |
403 (无效 key) |
| # | 测试 | 预期 | 通过 |
|---|---|---|---|
| 78 | 无 token 访问任意 /api/v1/* 端点 |
401 | |
| 79 | 错误 token 访问 | 401 | |
| 80 | 公开端点 (/health, /version) 无 token |
200 (正常) |
| # | 测试 | 预期 | 通过 |
|---|---|---|---|
| 81 | 连续 11 次 POST /api/v1/analyze (带 token) |
前 10 次 200, 第 11 次 429 | |
| 82 | 429 响应含 Retry-After 头 |
有, 值 > 0 | |
| 83 | 连续 6 次 POST /api/activate |
前 5 次正常, 第 6 次 429 |
| # | 测试 | 预期 | 通过 |
|---|---|---|---|
| 84 | POST /api/v1/qianniu/send-reply 含违规话术 ("加我微信") |
422, code=content_violation |
|
| 85 | POST /api/activate 超长 license_key (100 字符) |
400/422 格式拒绝 |
| # | 测试 | 预期 | 通过 |
|---|---|---|---|
| 86 | docker compose ps |
4 容器全部 healthy | |
| 87 | docker exec qn-api whoami |
appuser (非 root) |
|
| 88 | docker exec qn-web whoami |
node (非 root) |
| # | 测试 | 预期 | 通过 |
|---|---|---|---|
| 89 | 重启 qn-api, 检查 Redis 中 qn:analyzer:buf:* |
buffer 数据保留 | |
| 90 | 重启 qn-fetcher, 检查 Redis 中 qn:fetcher:seen_mids |
mid 集合保留 |
| # | 测试 | 预期 | 通过 |
|---|---|---|---|
| 91 | docker compose logs qn-api --tail 10 |
无 ERROR, 有 rate_limit/auth 日志 |
| # | 测试场景 | 步骤 | 预期 | 通过 |
|---|---|---|---|---|
| 92 | 话术完整生命周期 | 创建→审批→下架, 验证每步状态 | draft → active → deprecated |
|
| 93 | 买家 insights 查看 | GET /buyers → 选买家 → GET buyer-insights/{nick} | 返回情感分析数据 | |
| 94 | 成本控制状态 | GET /cost-status | 显示日限/已用/百分比 | |
| 95 | Playbook 统计 | GET /playbooks/stats | 触发次数/采纳率 | |
| 96 | 日报触发 | POST /daily-reports/trigger → GET /daily-reports | 异步接受, 后查可见 |
#!/bin/bash
TOKEN=$(docker exec qn-api printenv QN_INTERNAL_TOKEN)
BASE="http://127.0.0.1:8007"
PASS=0; FAIL=0; TOTAL=0
check() {
local method=$1 path=$2 expect=$3 data=$4
TOTAL=$((TOTAL+1))
if [ -n "$data" ]; then
code=$(curl -s -o /dev/null -w '%{http_code}' -X $method \
-H "X-Internal-Token: $TOKEN" -H "Content-Type: application/json" \
-d "$data" "$BASE$path")
else
code=$(curl -s -o /dev/null -w '%{http_code}' -X $method \
-H "X-Internal-Token: $TOKEN" "$BASE$path")
fi
if [ "$code" = "$expect" ]; then
echo " PASS $method $path -> $code"
PASS=$((PASS+1))
else
echo " FAIL $method $path -> $code (expected $expect)"
FAIL=$((FAIL+1))
fi
}
echo "=== 公开端点 ==="
check GET /health 200
check GET /ready 200
check GET /api/v1/qianniu-pc/version 200
echo "=== 认证拒绝 (无 token) ==="
TOKEN_BAK=$TOKEN; TOKEN=""
check GET /api/v1/config 401
check GET /api/v1/scripts 401
check GET /api/v1/qianniu-pc/sellers 401
TOKEN=$TOKEN_BAK
echo "=== 受保护读取 ==="
check GET /api/v1/config 200
check GET /api/v1/scripts 200
check GET /api/v1/qianniu-pc/today-stats 200
check GET /api/v1/qianniu-pc/buyers 200
check GET /api/v1/qianniu-pc/cases 200
check GET /api/v1/qianniu-pc/churn-alerts 200
check GET /api/v1/qianniu-pc/status 200
check GET /api/v1/qianniu-pc/cost-status 200
check GET /api/v1/qianniu-pc/sellers 200
check GET /api/v1/qianniu-pc/cookie-status 200
check GET /api/v1/qianniu-pc/account 200
check GET /api/v1/qianniu-pc/settings/llm-keys 200
check GET /api/v1/qianniu-pc/settings/models 200
check GET /api/v1/playbooks/stats 200
check GET /api/v1/playbooks/list 200
check GET /api/v1/daily-reports 200
echo "=== 写入操作 ==="
check POST /api/v1/daily-reports/trigger 200
echo ""
echo "=============================="
echo " PASS: $PASS / $TOTAL"
echo " FAIL: $FAIL"
echo "=============================="
| 日期 | 执行人 | 通过/总数 | 备注 |
|---|---|---|---|
| 2026-05-22 | AI E2E | 56 / 56 | 全量自动化, /config 漏洞已修复 |