侧边栏壁纸
博主头像
mnshy 博主等级

行动起来,活在当下

  • 累计撰写 7 篇文章
  • 累计创建 3 个标签
  • 累计收到 6 条评论

目 录CONTENT

文章目录

软件设计方案初稿

mnshy
2026-02-27 / 0 评论 / 0 点赞 / 1 阅读 / 0 字

软件设计方案书(细致版)——陪玩端/老板端/管理后台(三端系统)

版本:v1.0(方案级)
数据库:MySQL 8.1(既有实例接入)
配置方式.env(分环境可切换)
目标:实现与演示站 功能一致,但 UI/交互风格不同 的新系统


目录

    1. 文档说明与术语
    1. 项目目标与范围
    1. 角色与权限设计
    1. 业务流程设计(核心链路)
    1. 功能模块设计(详细到页面级)
    1. 数据库设计(MySQL 8.1 落地)
    1. API 接口设计(建议 REST + 版本化)
    1. 状态机设计(建议稿)
    1. UI/UX 设计与差异化方案
    1. 配置与 .env 规范(分环境)
    1. 非功能需求(NFR)
    1. 部署与运维方案
    1. 测试方案
  • 附录 A:建表 SQL(可执行)
  • 附录 B:待确认清单(用于升级为可直接开发版本)

0. 文档说明与术语

0.1 演示站入口(现状参考)

  • 陪玩端https://demo.club.logoracle.com/player/
  • 老板端https://demo.club.logoracle.com/boss/
  • 后台https://demo.club.logoracle.com/admin/(demo 账号:admin / 123)

0.2 基于演示站可见信息的功能梳理(标题/导航级)

  • Player
    • 主导航:排行 / 报单 / 我的
    • 排行页标题:收入排行榜
    • 报单中心:开始报单、报单记录
    • 我的:查看账单记录、退出登录
  • Boss
    • 主导航:排行 / 订单 / 我的
    • 排行页标题:消费排行榜
    • 订单中心:订单记录
    • 我的:查看账单记录、退出登录
  • Admin(左侧菜单)
    • 订单管理、老板管理、陪玩管理、客服管理
    • 类目管理、附加项、等级管理
    • 提现管理、管理员、系统设置

0.3 术语

  • 报单:陪玩端发起订单创建行为(为后续结算/统计提供依据)
  • 订单:围绕陪玩与老板的消费/收入记录(可能存在确认/完成/取消等状态)
  • 账单:资金或统计流水(收入、消费、提现、调整等)
  • RBAC:基于角色的访问控制(后台为主)
  • NFR:非功能需求(性能、安全、可用性、可观测等)

1. 项目目标与范围

1.1 建设目标

  • 业务一致性
    • 与演示站保持同等功能、权限边界、数据口径
    • 登录态检查/跳转逻辑保持一致(login-check -> main / logout)
  • UI 差异化
    • 视觉体系、布局与组件重做
    • 交互体验提升(空状态、加载、校验、筛选、详情展示方式)
  • 工程化与可运维
    • 前后端分离、接口规范化
    • .env 分环境配置
    • 日志、审计、备份、监控

1.2 范围(按端)

  • 陪玩端(Player)
    • 登录/注册/登出
    • 收入排行榜
    • 报单:创建报单、报单记录
    • 我的:个人信息入口、账单记录入口
  • 老板端(Boss)
    • 登录/注册/登出
    • 消费排行榜
    • 订单记录
    • 我的:账单记录入口
  • 管理后台(Admin)
    • 登录/登出
    • 订单管理、老板管理、陪玩管理、客服管理
    • 类目管理、附加项、等级管理
    • 提现管理、管理员、系统设置
    • 操作审计日志(建议)

1.3 约束与假设

  • 数据库使用你现成的 MySQL 8.1
  • 订单与账单统计口径以最终业务确认单为准(本方案提供默认建议)

2. 角色与权限设计

2.1 角色定义

  • Player(陪玩)
    • 创建报单
    • 查看收入排行
    • 查看个人账单
  • Boss(老板)
    • 查看订单记录
    • 查看消费排行
    • 查看个人账单
  • Admin(管理员)
    • 后台模块管理(按角色细分)

2.2 权限边界

  • 强制数据隔离
    • Player/Boss 端的所有“订单/账单”接口必须在服务端按登录用户过滤
    • 不允许通过传参访问他人数据
  • 后台 RBAC
    • 最小权限原则
    • 敏感动作强审计(提现审核、系统设置、管理员变更)

2.3 后台权限点建议(示例)

  • 订单管理order:view order:update order:export
  • 老板管理boss:view boss:create boss:update boss:disable
  • 陪玩管理player:view player:create player:update player:disable
  • 提现管理withdraw:view withdraw:approve withdraw:reject withdraw:mark_paid
  • 配置类category:* addon:* level:*
  • 系统/管理员admin_user:* settings:* audit_log:view

3. 业务流程设计(核心链路)

3.1 登录态检查与登出(与演示站一致)

  • 检查:访问端首页触发 login-check
    • 已登录 -> 跳转到 /main/index
    • 未登录 -> 跳转 /logout 清 cookie -> /login/login
  • 登出:清会话 + 清 cookie + 跳转登录页

3.2 报单/订单核心流程(已确认)

新流程:Boss下单 → 客服处理 → 分配/发布任务 → 陪玩抢单/接单 → 陪玩服务 → 陪玩完成确认 → 客服确认 → 金额到账 → 24小时后可提现

3.2.1 Boss发起下单(Boss端)

下单入口

  • Boss端底部Tab "下单" 或首页快捷入口
  • 未登录用户需先登录

下单流程详细步骤

  1. 选择类目(必填)
    • 下拉选择后台配置的类目列表
    • 显示类目单价和预计服务时长
  2. 选择附加项(可选)
    • 多选框选择附加项
    • 实时显示附加项价格和数量选择
    • 金额实时累加到预览金额
  3. 填写服务要求(必填,最多200字)
    • 文本框输入具体服务需求
    • 如:"需要上分到钻石段位"、"指定英雄XXX"等
  4. 预览金额(实时计算)
    • 计算公式:类目单价 × 时长 + Σ(附加项单价 × 数量)
    • 显示明细:类目金额、附加项金额、合计金额
  5. 确认下单
    • 余额校验逻辑
      • 查询Boss当前可用余额
      • 若余额 ≥ 订单金额:允许下单,余额进入冻结状态
      • 若余额 < 订单金额:禁止下单,提示"余额不足,请联系客服充值"
    • 生成订单号(格式:YYYYMMDD + 6位随机数)
    • 订单初始状态:submitted(下单成功)
    • 生成订单快照(记录当时类目/附加项价格,防后续改价影响)

关键控制点

  • 幂等控制:前端生成 client_request_id(UUID),后端幂等表防重复提交
  • 金额计算:服务端按后台配置计算,前端仅展示,防止篡改
  • 余额冻结:下单成功立即冻结Boss余额,非扣款,订单完成才真正扣款
  • 实时提醒:订单提交后,所有在线客服通过WebSocket收到 new_order 事件通知
  • 订单可见性submitted 状态的订单对所有客服可见,首个点击查看的客服获得优先处理权

3.2.2 客服处理订单(后台)

1. 订单提醒机制

  • 实时推送:Boss下单后,所有在线客服通过WebSocket收到 new_order 事件
    • 推送内容:订单号、Boss昵称、金额、下单时间、状态
    • 前端播放提示音(可选)并显示红点标记
  • 列表标记:新订单列表中 submitted 状态的订单显示"新"标记

2. 查看冲突处理逻辑

  • 并发查看场景
    • 客服A和客服B同时点击同一订单查看详情
    • 系统记录首个点击的客服 viewed_by 和时间 viewed_at
  • 冲突提示
    • 客服A(首个查看):正常进入订单详情页,显示"您正在处理此订单"
    • 客服B(后查看):进入详情页,顶部提示"该订单已有 XXX客服 于 12:30:45 优先查看,是否继续处理?"
      • 点击"继续处理":可继续查看和处理
      • 点击"返回列表":返回订单列表
  • 查看记录规则
    • 只记录首个查看的客服
    • 查看后订单标记为"处理中",但其他客服仍可处理
    • 5分钟内无操作,自动释放"处理中"状态

3. 处理方式选择(二选一)

方式A - 分配任务

  • 适用场景:知道哪个陪玩适合此订单(如老客户的专属陪玩)
  • 操作步骤:
    1. 点击"分配任务"按钮
    2. 下拉选择陪玩账号(支持按昵称/等级筛选)
    3. 显示陪玩当前状态(空闲/服务中)
    4. 确认分配
  • 状态变更:submittedpending_dispatch
  • 实时通知:被分配陪玩收到 new_task WebSocket推送

方式B - 发布任务

  • 适用场景:不确定哪个陪玩合适,让陪玩抢单
  • 操作步骤:
    1. 点击"发布到任务大厅"按钮
    2. 生成任务分享链接(格式:https://xxx.com/task/{share_token}
    3. 可复制链接分享到微信/QQ等社交工具
    4. 所有陪玩在任务大厅可见此订单
  • 状态变更:submittedpublished
  • 实时通知:所有在线陪玩收到 new_published_task WebSocket推送

4. 任务分享机制

  • 分享链接:包含订单基本信息(类目、金额、服务要求摘要)
  • 分享场景
    • 客服可将链接分享到微信群/QQ群,让不在线的陪玩也能看到
    • 陪玩点击链接后跳转任务大厅(需登录)
  • 链接有效期:与订单状态绑定,订单被接单后链接失效

5. 确认完成流程

  • 触发条件:陪玩提交完成申请(状态 completion_pending
  • 客服收到提醒:WebSocket推送 order_complete_request 事件
  • 核实步骤
    1. 查看订单详情中的服务记录和备注
    2. 如需核实,可联系陪玩或Boss确认
    3. 点击"确认完成"或"退回重打"
  • 状态变更completion_pendingcompleted
  • 金额到账:自动生成 ledger 流水,增加陪玩余额
  • 通知:陪玩收到 order_confirmed 通知

3.2.3 陪玩接单流程

方式A - 分配任务(客服指定陪玩)

  • 触发条件:客服执行"分配任务"操作,订单状态变为 pending_dispatch
  • 通知机制:被分配的陪玩收到多渠道通知
    • WebSocket实时推送:new_assigned_task 事件
    • 任务大厅显示"专属任务"标记
    • 我的订单列表显示"待确认"标记
  • 确认接单流程
    1. 陪玩点击订单进入详情页
    2. 显示完整订单信息(类目、附加项、服务要求、预估金额、Boss要求)
    3. 二次确认弹窗
      • 标题:"确认接单?"
      • 内容:显示订单金额、服务要求摘要
      • 按钮:"确认接单" / "拒绝接单"
    4. 校验逻辑
      • 检查订单状态仍为 pending_dispatch
      • 检查陪玩当前无进行中的订单(或允许同时接多单则跳过)
      • 使用乐观锁:UPDATE order SET status='player_accepted', player_id=?, accepted_at=NOW(), version=version+1 WHERE id=? AND status='pending_dispatch' AND version=?
    5. 成功处理
      • 订单状态变为 player_accepted
      • 通知客服:WebSocket推送 player_accepted 事件
      • 通知Boss:订单状态更新为"已接单"
    6. 拒绝处理
      • 陪玩点击"拒绝接单"
      • 订单状态回到 submitted(客服可重新分配或发布)
      • 通知客服:该陪玩拒绝了订单

方式B - 抢单模式(任务大厅)

  • 触发条件:客服执行"发布任务"操作,订单状态变为 published
  • 任务大厅显示
    • 所有陪玩在"任务大厅"Tab看到可抢订单列表
    • 列表字段:类目、预估金额、服务要求摘要(前20字)、发布时间、剩余可抢数量
    • 已抢订单标记为"已抢",不可再抢
  • 抢单流程
    1. 陪玩点击"抢单"按钮
    2. 二次确认弹窗
      • 标题:"确认抢单?"
      • 内容:显示完整订单信息(类目、附加项明细、服务要求、预估金额)
      • 按钮:"确认抢单" / "取消"
    3. 并发控制(乐观锁)
      UPDATE ipm_order 
      SET status='player_accepted', player_id=?, accepted_at=NOW(), version=version+1 
      WHERE id=? AND status='published' AND version=?
      
    4. 结果处理
      • 抢单成功(影响行数=1):
        • 显示"抢单成功,请尽快开始服务"
        • 订单从任务大厅移除或标记为"已抢"
        • 订单进入 player_accepted 状态
        • 通知客服:WebSocket推送 order_claimed 事件
        • 通知Boss:订单状态更新为"已接单"
      • 抢单失败(影响行数=0):
        • 返回错误码 ORDER_ALREADY_CLAIMED
        • 提示"该订单已被其他陪玩接单"
        • 前端刷新任务大厅列表

接单后可见性

  • 客服端:订单详情显示接单陪玩信息(昵称、等级、历史接单数、平均评分)
  • Boss端:订单详情显示接单陪玩信息(昵称、等级、评分)
  • 陪玩端:订单进入"我的订单"列表

3.2.4 服务与完成流程

1. 服务流程

  • 开始服务
    • 陪玩在"我的订单"中点击"开始服务"按钮
    • 状态变更:player_acceptedin_service
    • 记录开始时间 started_at
    • 通知客服和Boss:订单状态变为"服务中"
  • 服务中状态
    • 陪玩可查看订单详情和服务要求
    • 客服可监控服务进度(查看开始时间、预计完成时间)
    • Boss可查看订单状态为"服务中"
    • 客服可执行重新分配:如发现当前陪玩无法完成任务,客服可重新分配或重新发布

2. 放弃任务流程

  • 触发条件:陪玩因各种原因无法继续服务(如技术不够、时间冲突等)

  • 可操作状态player_accepted(已接单但未开始)、in_service(服务中)

  • 放弃流程

    1. 陪玩点击"放弃任务"按钮
    2. 二次确认弹窗
      • 标题:"确认放弃任务?"
      • 内容:"放弃后该订单将重新进入待分配状态,您将无法获得此订单收入。确定要放弃吗?"
      • 按钮:"确认放弃" / "取消"
    3. 填写放弃原因(可选,如"技术不够无法完成"、"时间冲突"等)
    4. 状态变更
      • player_acceptedin_servicesubmitted(回到初始状态)
      • 清空当前 player_id 和接单时间
      • 记录放弃历史到 ipm_order_player_history
    5. 通知机制
      • 通知客服:WebSocket推送 player_abandoned 事件,包含放弃原因
      • 通知Boss:订单状态变为"等待重新分配"
    6. 后续处理
      • 订单回到 submitted 状态,客服可重新分配或重新发布
      • 其他陪玩可以抢单或接受分配
  • 限制规则

    • 放弃次数限制:单个订单最多被放弃3次,超过后订单自动标记为异常需客服介入
    • 放弃惩罚(可选):频繁放弃任务的陪玩降低抢单优先级

3. 客服重新分配流程

  • 触发场景
    1. 陪玩放弃任务后,订单回到 submitted 状态
    2. 客服发现服务中的陪玩无法完成任务,主动重新分配
  • 重新分配操作(从 in_service 状态)
    1. 客服在订单详情点击"重新分配"按钮
    2. 确认重新分配原因(选择或输入)
    3. 选择新分配方式:
      • 分配给指定陪玩:选择新陪玩,原陪玩被移出
      • 发布到任务大厅:回到抢单模式
    4. 状态变更
      • in_servicepending_dispatch(新分配)或 published(新发布)
      • 记录原陪玩服务时长(如有收入结算需求)
      • 记录重新分配历史
    5. 通知机制
      • 通知原陪玩:任务被重新分配,服务终止
      • 通知新陪玩:新任务分配/抢单通知
      • 通知Boss:订单更换服务人员

4. 完成确认流程

  • 陪玩提交完成

    • 服务完成后,陪玩点击"完成任务"按钮
    • 二次确认弹窗
      • 标题:"确认完成服务?"
      • 内容:"确认后订单将提交给客服审核,审核通过后金额将到账"
      • 按钮:"确认完成" / "取消"
    • 状态变更:in_servicecompletion_pending
    • 记录完成时间 player_completed_at
    • 可填写服务备注(可选,如"已完成上分,从铂金3到钻石5")
  • 客服确认机制

    • 实时提醒:WebSocket推送 order_complete_request 事件给所有客服
    • 订单列表标记:completion_pending 状态订单显示"待确认"标记
    • 核实逻辑
      • 客服查看订单详情和服务备注
      • 如需核实,可:
        • 查看陪玩上传的完成截图(如有)
        • 联系陪玩确认完成情况
        • 联系Boss确认满意度
    • 确认完成操作
      • 点击"确认完成"按钮
      • 状态变更:completion_pendingcompleted
      • 记录完成时间 completed_at
      • 金额到账
        -- 生成ledger流水
        INSERT INTO ipm_ledger (user_type, user_id, biz_type, direction, amount, balance_after, ref_type, ref_id)
        VALUES ('player', {player_id}, 'order_income', 'in', {order_amount}, {new_balance}, 'order', {order_id})
        
        • 更新陪玩余额:UPDATE ipm_player SET balance = balance + {order_amount} WHERE id = {player_id}
      • 通知机制
        • 通知陪玩:订单已完成,金额已到账,24小时后可提现
        • 通知Boss:订单已完成,可前往评价
        • 通知客服:订单已确认完成
      • 评价入口:Boss订单详情显示"评价"按钮
  • 退回重打机制(可选):

    • 客服发现服务未达标,可点击"退回重打"
    • 状态变更:completion_pendingin_service
    • 通知陪玩:订单被退回,请继续服务
    • 记录退回原因

3.2.5 充值流程(客服-管理员)

  1. 客服申请:在后台提交充值申请(选择 Boss、输入金额、备注)
  2. 管理员审核:通过或拒绝
    • 通过:生成 ledger 流水,boss.balance 增加,即时到账
    • 拒绝:记录拒绝原因,客服可重新申请

3.2.6 提现流程(T+1)(陪玩-管理员)

  1. 申请提现时间:订单完成后需等待 1天(24小时) 才能申请提现该笔收入
  2. 到账时间提示:提现申请提交后,系统提示"5个工作日内到账,节假日顺延,如有疑问请联系客服"
  3. 陪玩申请:填写提现金额、收款方式、收款账号、收款人姓名(系统校验可提现余额)
  4. 管理员审核
    • 通过:生成 ledger 流水扣减余额,状态变为 approved
    • 拒绝:记录拒绝原因
  5. 手动转账:管理员线下转账后,在后台点击"已打款",状态变为 paid

3.2.7 订单评价系统(Boss对陪玩)

1. 评价开关控制

  • 系统设置:管理员在后台"系统设置"中控制评价功能开关
    • review_enabled = 1:开启评价功能
    • review_enabled = 0:关闭评价功能,所有评价入口隐藏
  • 动态生效:开关状态改变后即时生效,无需重启服务

2. 评价时机与条件

  • 可评价条件(需同时满足):

    1. 订单状态为 completed(已完成)
    2. 当前用户为订单的Boss(order.boss_id = 当前用户ID
    3. 评价功能已开启(review_enabled = 1
    4. 只有完成任务的陪玩才能被评价(陪玩必须将订单从in_service推进到completion_pending并最终completed
  • 不可评价的陪玩

    • 放弃任务的陪玩(从player_acceptedin_service放弃回到submitted
    • 被客服重新分配移出的陪玩(从in_service被重新分配)
    • 未接单的陪玩(处于pending_dispatch或抢单未成功)
  • 如何判断陪玩完成任务

    • 通过 ipm_order_player_history 表记录
    • 只有 status = 'completed'action = 'submit_complete' 的陪玩才能被评价
    • 该表记录了每个陪玩在订单中的完整生命周期
  • 评价时间:订单完成后任何时间均可评价,无时间限制

    • 示例:订单完成1个月后仍可评价
  • 评价次数限制

    • 每个订单中每个完成任务的陪玩只能被评价一次
    • 若订单由多个陪玩接力完成,可对每个实际完成任务的陪玩分别评价
    • 重复评价返回错误码 REVIEW_ALREADY_EXISTS
    • 放弃或被移出的陪玩不能被评价

3. 评价内容

  • 评分维度(每项1-5星,整数):
    • skill_score:技术评分(如游戏技术、代练效率)
    • interaction_score:互动评分(如沟通、配合度)
    • attitude_score:态度评分(如服务态度、守时)
    • 计算平均分:(skill_score + interaction_score + attitude_score) / 3
  • 文字评价(可选):
    • 最多30个中文字符
    • 支持敏感词过滤
    • 为空时只保存评分
  • 匿名选项
    • is_anonymous = 1:匿名评价,不显示Boss昵称
    • is_anonymous = 0:实名评价,显示Boss昵称

4. 评价流程

  • 入口:Boss在"订单中心"→"已完成订单"→点击"评价"按钮

  • 评价页面

    1. 显示订单信息(订单号、服务类目、完成时间)
    2. 显示待评价陪玩列表(多陪玩时分别显示)
    3. 对每个陪玩:
      • 显示陪玩信息(昵称、头像、等级)
      • 三维度评分组件(1-5星)
      • 文字评价输入框(30字限制)
      • 匿名勾选框
    4. 提交评价按钮
  • 提交逻辑

    -- 检查是否已评价
    SELECT COUNT(*) FROM ipm_order_review WHERE order_id=? AND player_id=? AND status!='deleted'
    -- 若返回>0,返回错误 REVIEW_ALREADY_EXISTS
    
    -- 插入评价记录
    INSERT INTO ipm_order_review (order_id, boss_id, player_id, skill_score, interaction_score, attitude_score, comment, is_anonymous, status, created_at)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'created', NOW())
    
  • 提交成功

    • 显示"评价成功,感谢您的反馈"
    • 更新陪玩平均评分(后台异步计算或实时更新)
    • 评价按钮变为"已评价",不可再次点击

5. 评价展示

  • Boss端
    • 订单详情显示"我的评价"
    • 显示评分(三维度+平均)、文字评价、评价时间
  • 陪玩端
    • "我的"页面显示"我的评价"入口
    • 评价列表显示:评分、文字评价(匿名时不显示Boss名)、评价时间
  • 客服端(评价管理)
    • 评价列表:被评价陪玩、评分、评价内容、是否匿名、评价时间
    • 筛选条件:陪玩ID、评分星级、时间范围
    • 统计报表:陪玩平均评分、评价数量、各维度平均分

6. 评价管理

  • 管理员权限
    • 查看所有评价
    • 删除违规评价(状态改为 deleted
    • 敏感词过滤(提交时自动检测或事后审核)
  • 评价状态
    • created:评价已创建
    • visible:评价可见(用于审核流程,可选)
    • deleted:评价已删除(管理员删除违规评价)

7. 评价数据应用

  • 排行榜:评价数据可用于"优质陪玩"排行榜计算
  • 陪玩等级:高评分陪玩可获得更高等级或奖励
  • 任务分配:客服可优先将订单分配给高评分陪玩

3.2.8 后台管理(Admin)

  • 订单查询、处理(分配/发布/确认完成)
  • 用户管理(老板、陪玩、客服)- 仅管理员可新增账号
  • 运营配置(类目、附加项、等级、评价开关)
  • 财务相关(充值申请审核、提现审核/打款登记)

3.3 订单状态流转图

Boss下单(submitted)
    ↓
客服处理(pending_dispatch) ──分配──> 指定陪玩
    ↓ 发布                              ↓ 确认接单
任务大厅(published) <──────────────────┘
    ↓ 抢单
陪玩接单(player_accepted)
    ↓
陪玩服务中(in_service)
    ↓ 陪玩完成任务
陪玩任务完成确认中(completion_pending)
    ↓ 客服确认
任务完成(completed) ──> 金额到账 ──> 24小时后可提现

4. 功能模块设计(详细到页面级)

4.1 陪玩端(Player)

4.1.1 登录

  • 系统自用,关闭自主注册,仅管理员可在后台新增账号
  • 登录方式:手机号+密码 或 用户名+密码(二选一)
  • 账号字段:手机号(登录用)、邮箱、用户名(展示用)、密码
  • 安全:暂不需要短信验证码(内部系统)

4.1.2 主界面(底部 Tab)

  • 排行(收入排行榜)
  • 任务大厅(新增:可抢订单列表)
  • 报单(原报单中心,现为历史记录)
  • 我的(个人中心)

4.1.3 任务大厅(新增)

  • 可抢订单列表
    • 显示客服发布的任务
    • 字段:类目、预估金额、服务要求摘要、发布时间
    • 抢单按钮(带二次确认弹窗)
  • 抢单确认弹窗
    • 显示完整订单信息(类目、附加项、服务要求、预估金额)
    • 确认接单/取消按钮
    • 抢单成功后显示"抢单成功,请尽快开始服务"
  • 已被抢订单:实时标记"已被接单",不可再抢

4.1.4 我的订单(接单后)

  • 待处理订单(分配或抢单后):
    • 确认接单按钮(分配模式下需二次确认)
    • 查看订单详情
  • 服务中订单
    • 开始服务按钮(进入服务中状态)
    • 完成任务按钮(提交完成申请)
  • 已完成订单
    • 查看详情与收入
    • 查看Boss评价(如有)

4.1.5 报单中心(原功能保留)

  • 历史报单记录
  • 账单记录入口

4.2 老板端(Boss)

4.2.1 登录

与 Player 端一致:关闭自主注册,仅管理员可在后台新增账号。登录方式:手机号+密码 或 用户名+密码。

4.2.2 下单页面(新增)

  • 入口:底部 Tab "下单" 或首页快捷入口
  • 下单流程
    1. 选择类目(下拉选择)
    2. 选择附加项(多选,可选)
    3. 填写服务要求/备注(文本框)
    4. 预览金额(实时计算)
    5. 确认下单
  • 余额校验:余额不足时提示充值并引导联系客服
  • 下单成功:显示订单号,跳转订单列表

4.2.3 订单中心

  • 订单记录列表
    • 字段:订单号、陪玩(接单后显示)、金额、状态、时间
    • 筛选:状态(全部/待处理/服务中/已完成)、时间范围
  • 订单详情
    • 金额构成:类目、附加项
    • 服务进度:状态流转时间线
    • 评价入口(订单完成后显示)
  • 评价功能(订单完成后):
    • 评分维度:技术、互动、态度(每项1-5星)
    • 文字评价:最多30字
    • 匿名选项:可勾选匿名评价
    • 多陪玩评价:可对每个参与服务的陪玩分别评价

4.2.4 排行(消费排行榜)

  • 展示:排名、用户昵称(可选)、消费金额
  • 筛选:日/周/月(建议)

4.2.5 我的

  • 余额展示:显示可用余额
  • 账单记录入口:查看余额变动历史
  • 退出登录

4.3 管理后台(Admin)

4.3.1 登录

  • 账号密码登录
  • 角色选择(管理员/客服)

4.3.2 仪表盘(首页)

  • 数据概览卡片
    • 今日订单数 / 今日订单金额
    • 今日新增陪玩 / 今日新增老板
    • 待处理提现申请数 / 待处理充值申请数
    • 账户余额总计(所有 Boss 余额汇总)
  • 趋势图表
    • 近7天订单金额趋势
    • 近7天新增用户趋势
  • 快捷入口
    • 订单管理、提现审核、充值审核、用户管理

4.3.3 提醒功能(消息中心)

  • 下单提醒(实时)
    • 新订单提交时,顶部导航栏显示红点提醒
    • 提醒内容:"新订单 #20240227001 待处理"
    • 点击跳转订单管理页面
    • 声音提醒(可选,浏览器通知)
  • 审核提醒
    • 提现申请提交时提醒管理员
    • 充值申请提交时提醒管理员
  • 系统通知
    • 异常订单标记提醒

4.3.4 菜单模块(参考演示站结构)

  • 仪表盘
  • 订单管理(客服处理)
    • 新订单列表(实时提醒标记)
    • 任务大厅管理(已发布订单)
    • 订单处理:分配/发布/确认完成
  • 任务大厅监控
  • 评价管理
  • 老板管理
  • 陪玩管理
  • 客服管理
  • 类目管理
  • 附加项管理
  • 等级管理
  • 提现管理
  • 充值管理
  • 管理员管理
  • 系统设置(评价开关)
  • 操作日志

4.3.5 订单管理(客服处理)

新订单列表

  • 实时提醒:顶部显示新订单数量,声音/视觉提醒
  • 列表字段:订单号、Boss昵称、金额、状态、下单时间、查看客服
  • 筛选条件:状态、时间范围、查看客服
  • 冲突提示:订单被其他客服查看时显示"已有XXX客服优先查看"

订单处理流程

  1. 查看订单

    • 点击订单进入详情
    • 记录 viewed_byviewed_at
    • 其他客服同时查看时提示优先查看信息
  2. 处理方式选择

    • 分配任务:下拉选择陪玩账号,确认分配
      • 分配后该陪玩收到实时通知
      • 订单状态变为 pending_dispatch(待陪玩确认)
    • 发布任务:点击"发布到任务大厅"
      • 生成任务分享链接(可复制到微信/QQ)
      • 订单状态变为 published
      • 所有陪玩在任务大厅可见
  3. 监控任务状态

    • 已分配:查看陪玩是否确认接单
    • 已发布:查看抢单情况
    • 服务中:查看服务进度
  4. 确认完成

    • 陪玩提交完成后,客服收到提醒
    • 核实服务情况,点击"确认完成"
    • 订单进入 completed,金额到账陪玩

任务大厅监控

  • 已发布订单列表
  • 抢单状态实时刷新
  • 分享链接管理

4.3.6 评价管理

  • 评价开关:管理员可全局开启/关闭评价功能
  • 评价列表:查看所有评价
    • 筛选:被评价陪玩、评分星级、是否匿名
  • 评价统计:陪玩维度评分汇总
  • 评价审核(可选):敏感词过滤、违规评价删除

5. 数据库设计(MySQL 8.1 落地)

5.1 MySQL 实例接入信息(现有)

  • Host192.168.6.99
  • Port3306
  • Databasecdb
  • Usercdb
  • Passwordcdb@2026
  • Version:MySQL 8.1

5.2 建议的库级参数

  • 字符集utf8mb4
  • 排序规则utf8mb4_0900_ai_ci
  • 引擎:InnoDB
  • 时区:建议应用与数据库统一(推荐 UTC;若业务强依赖本地时间可统一 +08:00

5.3 账号与安全建议(上线必做)

  • 生产环境建议创建业务专用账号,执行最小权限授权(避免使用高权限账号)
  • 限制账号允许连接来源(仅允许后端服务器 IP 或网段)
  • 数据库密码与密钥只通过环境变量/密钥管理注入,禁止写入前端与仓库

5.4 数据建模原则

  • 主键统一 BIGINT UNSIGNED 自增
  • 金额统一 DECIMAL(12,2),禁止浮点
  • 表必备:created_atupdated_at
  • 关键字段建索引:
    • 列表页查询:(status, created_at)
    • 用户维度查询:(user_id, created_at)
    • 订单号查询:UNIQUE(order_no)

5.5 核心表清单(v1.0)

  • 用户
    • ipm_player:陪玩账号
    • ipm_boss:老板账号
    • ipm_admin_user / ipm_admin_role:后台账号与角色
  • 业务配置
    • ipm_category:类目
    • ipm_addon_item:附加项
    • ipm_level:等级
    • ipm_system_setting:系统设置(评价开关等)
  • 订单与资金
    • ipm_order:订单主表(新增字段:viewed_by, viewed_at, share_token, player_ids支持多陪玩)
    • ipm_order_addon:订单附加项明细
    • ipm_ledger:账单流水(双端共用)
    • ipm_withdraw_request:提现申请
    • ipm_recharge_request:充值申请(客服申请-管理员审核)
  • 评价
    • ipm_order_review:订单评价表(Boss对陪玩)
  • 审计
    • ipm_admin_audit_log:后台关键操作审计

6. API 接口设计(建议 REST + 版本化)

6.1 通用约定

  • BasePath:/api/v1
  • Content-Type:application/json; charset=utf-8
  • 鉴权:
    • 建议使用 httpOnly Cookie + Session(和演示站 cookie 形态一致、前端无感)
    • 或 JWT(若未来要多端/开放接口,可再升级)
  • 返回结构(建议):
{
  "success": true,
  "data": {},
  "message": "",
  "code": "OK",
  "requestId": ""
}

6.2 错误码建议(示例)

通用错误码:

  • OK
  • AUTH_REQUIRED:未登录/登录过期
  • AUTH_FAILED:账号或密码错误
  • PERMISSION_DENIED:无权限
  • VALIDATION_ERROR:参数校验失败
  • NOT_FOUND:资源不存在
  • CONFLICT:冲突(如重复提交)
  • INTERNAL_ERROR:服务器内部错误

业务错误码:

  • INSUFFICIENT_BALANCE:Boss余额不足,需充值
  • WITHDRAW_TIME_LIMIT:提现时间限制,订单完成后需等待24小时
  • INSUFFICIENT_WITHDRAWABLE_BALANCE:可提现余额不足
  • ORDER_ALREADY_CLAIMED:订单已被其他陪玩接单
  • REVIEW_ALREADY_EXISTS:该订单已评价过此陪玩,不能重复评价
  • REVIEW_DISABLED:评价功能已关闭
  • ORDER_STATUS_INVALID:订单状态不支持此操作(如非completed订单不能评价)
  • PLAYER_NOT_AVAILABLE:陪玩当前不可接单(如已在服务中)

6.3 Player(陪玩端)接口清单

6.3.1 认证

  • POST /api/v1/player/auth/login(手机号/用户名 + 密码)
  • GET /api/v1/player/auth/login-check
  • POST /api/v1/player/auth/logout

注意:关闭自主注册,账号仅由管理员在后台创建。

6.3.2 排行榜

  • GET /api/v1/player/rank/income?range=day|week|month

6.3.3 任务大厅(新增)

  • GET /api/v1/player/tasks?status=published&page=&page_size=(可抢订单列表)
    • 只显示已发布状态的任务
  • POST /api/v1/player/tasks/{id}/claim(抢单)
    • 二次确认:前端弹窗展示订单详情,用户确认后调用
    • 并发控制机制
      1. 使用数据库原子操作:先INSERT接单记录,再统计当前已接单人数
      2. 如果已接单人数 ≤ required_players,抢单成功
      3. 如果已接单人数 > required_players,抢单失败,删除刚插入的记录,提示"订单已被其他用户抢走,请刷新页面"
    • 状态流转
      • 第1人抢单成功:publishedpartially_accepted(部分接单)
      • 最后1人抢单成功(人数达标):partially_acceptedplayer_accepted(全部接单完成)
    • 成功响应:返回订单详情 + 当前接单人数/所需人数
    • 失败响应ORDER_ALREADY_CLAIMED(已被其他陪玩接单,请刷新页面)

6.3.4 我的订单

  • GET /api/v1/player/orders?status=&date_from=&date_to=&page=&page_size=
    • 状态筛选:pending_dispatch(待确认)/player_accepted(待开始)/in_service(服务中)/completion_pending(待客服确认)/completed
  • GET /api/v1/player/orders/{id}(订单详情)
  • POST /api/v1/player/orders/{id}/accept(分配模式下确认接单)
    • 需要二次确认弹窗展示订单详情
  • POST /api/v1/player/orders/{id}/start-service(开始服务)
    • 状态从 player_accepted -> in_service
  • POST /api/v1/player/orders/{id}/complete(完成任务,提交客服确认)
    • 状态从 in_service -> completion_pending
  • 新增 POST /api/v1/player/orders/{id}/abandon(放弃任务)
    • 可操作状态:player_acceptedin_service
    • 请求字段:reason(放弃原因,可选)
    • 状态回到 submitted,订单重新进入待分配
    • 记录放弃历史到 ipm_order_player_history
    • 通知客服:player_abandoned 事件

6.3.5 账单

  • GET /api/v1/player/ledger?date_from=&date_to=&page=&page_size=

6.3.6 提现(T+1规则 + 到账提示)

  • POST /api/v1/player/withdraw
    • 请求字段:amount, pay_channel, pay_account, pay_name
    • T+1校验:系统校验 completed_at + 24h < NOW(),不满足返回错误码 WITHDRAW_TIME_LIMIT
    • 可提现余额 = 所有已完成订单金额(completed_at + 24h < NOW()) - 已申请提现金额
    • 到账提示:申请成功后返回消息"5个工作日内到账,节假日顺延,如有疑问请联系客服"
  • GET /api/v1/player/withdraw?status=&page=&page_size=

6.4 Boss(老板端)接口清单

6.4.1 认证

  • POST /api/v1/boss/auth/login(手机号/用户名 + 密码)
  • GET /api/v1/boss/auth/login-check
  • POST /api/v1/boss/auth/logout

注意:关闭自主注册,账号仅由管理员在后台创建。

6.4.2 排行榜

  • GET /api/v1/boss/rank/consume?range=day|week|month

6.4.3 下单(新增)

  • POST /api/v1/boss/orders(创建订单)
    • 请求字段:
      • category_id:类目ID
      • addons:附加项数组 [{addon_item_id, qty}]
      • remark:服务要求/备注
      • client_request_id:幂等键(防重复提交)
    • 余额校验:余额不足返回 INSUFFICIENT_BALANCE,提示充值
    • 成功返回:订单号、订单详情
  • GET /api/v1/boss/categories(获取类目列表,用于下单页)
  • GET /api/v1/boss/addons(获取附加项列表,用于下单页)
  • POST /api/v1/boss/orders/preview-amount(金额预览)
    • 请求字段:category_id, addons
    • 返回计算后金额

6.4.4 订单查询

  • GET /api/v1/boss/orders?status=&date_from=&date_to=&page=&page_size=
    • 状态:submitted(待处理)/player_accepted(已接单)/in_service(服务中)/completed
  • GET /api/v1/boss/orders/{id}(查看详情,含服务进度时间线)

6.4.5 评价(新增)

  • POST /api/v1/boss/orders/{id}/reviews(提交评价)
    • 请求字段:
      • player_id:被评价陪玩ID(支持多陪玩分别评价)
      • skill_score:技术评分(1-5)
      • interaction_score:互动评分(1-5)
      • attitude_score:态度评分(1-5)
      • comment:文字评价(最多30字)
      • is_anonymous:是否匿名(布尔值)
    • 校验:订单状态为 completed,且当前用户为订单 Boss
    • 每个陪玩只能评价一次,重复评价返回 REVIEW_ALREADY_EXISTS
  • GET /api/v1/boss/orders/{id}/reviews(查看订单评价)
    • 返回各陪玩的评分和评价详情

6.4.6 账单

  • GET /api/v1/boss/ledger?date_from=&date_to=&page=&page_size=

6.5 Admin(后台)接口清单

6.5.1 认证

  • POST /api/v1/admin/auth/login
  • GET /api/v1/admin/auth/login-check
  • POST /api/v1/admin/auth/logout

6.5.2 订单管理(客服处理)

  • GET /api/v1/admin/orders?status=&viewed_by=&date_from=&date_to=&page=&page_size=(订单列表)
    • 状态筛选:submitted(新订单)/pending_dispatch(待分配/发布)/published(已发布)/player_accepted(已接单)/in_service(服务中)/completion_pending(待确认完成)/completed
    • 新订单标记:is_new(submitted状态且未被查看)
  • GET /api/v1/admin/orders/{id}(订单详情)
    • 查看冲突处理:记录 viewed_by,如果已有其他客服查看,返回 viewer_nameviewed_at
    • 前端根据返回判断是否提示"已有XXX客服优先查看"
  • POST /api/v1/admin/orders/{id}/assign(分配任务给指定陪玩)
    • 请求字段:player_id(陪玩ID)
    • 状态变更:submitted -> pending_dispatch
    • 实时通知:该陪玩收到新任务通知
  • POST /api/v1/admin/orders/{id}/publish(发布到任务大厅)
    • 状态变更:submitted -> published
    • 生成分享链接,返回 share_url(可分享到微信/QQ)
  • POST /api/v1/admin/orders/{id}/confirm-complete(确认订单完成)
    • 状态变更:completion_pending -> completed
    • 触发金额到账(生成 ledger 流水,增加 player.balance)
    • 实时通知:陪玩收到完成确认通知
  • 新增 POST /api/v1/admin/orders/{id}/reassign(重新分配任务)
    • 可操作状态:in_service(服务中重新分配)或 submitted(放弃后重新分配)
    • 请求字段:player_id(新陪玩ID,可选,不传则发布到任务大厅)、reason(重新分配原因)
    • 状态变更:
      • 指定新陪玩:in_service/submitted -> pending_dispatch
      • 发布到任务大厅:in_service/submitted -> published
    • 记录原陪玩状态变更历史
    • 实时通知:原陪玩和新陪玩收到通知

6.5.3 任务大厅监控

  • GET /api/v1/admin/tasks/published(已发布任务列表)
  • GET /api/v1/admin/tasks/{id}/claim-status(抢单状态实时查询)

6.5.4 评价管理

  • GET /api/v1/admin/reviews?player_id=&order_id=&page=&page_size=(评价列表)
  • GET /api/v1/admin/reviews/{id}(评价详情)
  • DELETE /api/v1/admin/reviews/{id}(删除违规评价)
  • GET /api/v1/admin/reviews/stats?player_id=(陪玩评价统计)
    • 返回平均分、评价数量、各维度平均评分

6.5.5 系统设置

  • GET /api/v1/admin/settings(获取系统设置)
  • PUT /api/v1/admin/settings(更新系统设置)
    • 字段:review_enabled(评价功能开关,布尔值)

6.5.6 用户管理

  • Boss管理GET/POST/PUT /api/v1/admin/bosses...(新增时字段:手机号、邮箱、用户名、密码、昵称)
  • Player管理GET/POST/PUT /api/v1/admin/players...(新增时字段:手机号、邮箱、用户名、密码、昵称、等级)
  • 客服管理GET/POST/PUT /api/v1/admin/cs...(客服后台操作权限)
  • 重置密码POST /api/v1/admin/{user_type}/{id}/reset-password

6.5.7 配置管理

  • GET/POST/PUT/DELETE /api/v1/admin/categories...
  • GET/POST/PUT/DELETE /api/v1/admin/addons...
  • GET/POST/PUT/DELETE /api/v1/admin/levels...

6.5.8 提现管理

  • GET /api/v1/admin/withdraws?status=&date_from=&date_to=&page=&page_size=
  • GET /api/v1/admin/withdraws/{id}
  • POST /api/v1/admin/withdraws/{id}/approve
  • POST /api/v1/admin/withdraws/{id}/reject
  • POST /api/v1/admin/withdraws/{id}/mark-paid

6.5.9 充值管理

  • GET /api/v1/admin/recharge-requests?status=&page=&page_size=(查询充值申请)
  • POST /api/v1/admin/recharge-requests(客服提交充值申请)
  • POST /api/v1/admin/recharge-requests/{id}/approve(管理员审核通过)
  • POST /api/v1/admin/recharge-requests/{id}/reject(管理员审核拒绝)

6.5.10 管理员与系统设置

  • GET/POST/PUT /api/v1/admin/admin-users...
  • GET/PUT /api/v1/admin/settings
  • GET /api/v1/admin/audit-logs?...(建议)

6.5.11 仪表盘

  • GET /api/v1/admin/dashboard/summary(数据概览:今日订单数/金额、新增用户、待处理申请)
  • GET /api/v1/admin/dashboard/trend?days=7(趋势数据:近N天订单/用户趋势)

6.5.12 提醒功能(WebSocket/SSE)

  • WebSocket 连接:/ws/admin/notifications
  • 事件类型:
    • new_order:新订单提醒(payload: order_id, order_no, boss_name, amount, created_at)
    • order_viewed:订单被其他客服查看提醒
    • order_claimed:订单被陪玩接单提醒
    • order_completed:陪玩提交完成申请提醒
    • new_withdraw:新提现申请提醒
    • new_recharge:新充值申请提醒
  • REST 备用轮询:GET /api/v1/admin/notifications/poll(返回未读提醒列表)
  • 标记已读:POST /api/v1/admin/notifications/{id}/read

7. 状态机设计(建议稿)

7.1 订单状态(order.status

新流程:Boss下单 → 客服处理(分配/发布) → 陪玩接单 → 陪玩服务 → 陪玩完成确认 → 客服确认 → 金额到账

7.1.1 状态枚举(6个状态)

  • submitted:下单成功(Boss已下单,待客服处理)
  • pending_dispatch:客服处理中(已分配给指定陪玩,待陪玩确认)
  • published:已发布到任务大厅(陪玩可抢单)
  • partially_accepted:部分陪玩已接单(多人抢单场景,人数未满)
  • player_accepted:陪玩已接单(待开始服务,人数已满)
  • in_service:陪玩服务中
  • completion_pending:陪玩任务完成确认中(待客服确认)
  • completed:任务结束(客服已确认完成,金额已到账)
  • canceled:已取消(客服或后台作废)

7.1.2 状态转换图

                    ┌─ 分配 ─> pending_dispatch ── 陪玩确认 ──┐
                    │                                          ↓
submitted ──客服处理─┤                                   player_accepted
  (Boss下单)        │      ↑                    ↓ 放弃/重新分配      │
                    │      └───────────────────────────────────────┘
                    │                                          │
                    │                                          │ 开始服务
                    │                                          ↓
                    └─ 发布 ─> published ───── 陪玩抢单 ──> partially_accepted
                                                          │(人数未满)
                                                          │
                                                          │ 最后一人抢单成功
                                                          │(人数达标)
                                                          ↓
                                                     player_accepted
                                                          │(人数已满)
                                                          │ 开始服务
                                                          ↓
                                                      in_service
                                                                    │
                                                                    │ 放弃任务
                                                                    │ 客服重新分配
                                                                    ↓
                                                        completion_pending
                                                                    │
                                                                    │ 客服确认
                                                                    ↓
                                                                completed
                                                                    │
                                                              (金额到账)

多人抢单逻辑

  • 订单可设置 required_players(默认1,如需2人组队则为2)
  • 抢单采用"先抢先得"策略,根据INSERT时间判断先后顺序
  • 前N个(N=required_players)抢单成功,第N+1个及以后提示"订单已被抢走"
  • 第1人抢单成功:publishedpartially_accepted
  • 最后1人抢单成功:partially_acceptedplayer_accepted

状态流转说明

  • player_acceptedin_service 可放弃任务,回到 submitted
  • in_service 客服可重新分配,状态变为 pending_dispatchpublished
  • 只有 completion_pending -> completed 的陪玩才能获得收入并被评价

7.1.3 状态转换详情

当前状态操作下一状态操作人触发事件
submitted分配任务pending_dispatch客服指定陪玩
submitted发布任务published客服发布到任务大厅
pending_dispatch确认接单player_accepted陪玩陪玩接受分配
published抢单成功(第1人)partially_accepted陪玩陪玩抢单,人数未满
published抢单成功(最后1人)player_accepted陪玩单人订单抢单成功
partially_accepted抢单成功(最后1人)player_accepted陪玩多人订单人数达标
partially_accepted抢单成功partially_accepted陪玩多人订单人数未满
player_accepted开始服务in_service陪玩陪玩点击开始
player_accepted放弃任务submitted陪玩陪玩放弃,回到待分配
in_service完成任务completion_pending陪玩陪玩提交完成
in_service放弃任务submitted陪玩陪玩放弃,回到待分配
in_service重新分配pending_dispatch/published客服客服重新分配或发布
completion_pending确认完成completed客服客服确认服务完成
任意状态取消订单canceled客服/后台作废订单

7.1.4 关键规则

  • 余额冻结:Boss下单成功后立即冻结余额,订单完成时扣款,取消时解冻
  • 金额到账时机:只有 completed 状态才生成 ledger 流水增加陪玩余额
  • 到账后可提现completed 状态后24小时陪玩可申请提现
  • 查看冲突submitted 状态记录首个查看客服 viewed_by,其他客服查看时提示
  • 幂等控制:状态变更使用乐观锁(version字段),防止并发冲突
  • 实时通知:状态变更触发 WebSocket 通知相关方(Boss/陪玩/客服)

7.2 提现状态(withdraw_request.status

申请提现时间:订单完成后需等待 1天(24小时) 才能申请提现该笔收入。

到账时间提示:提现申请提交后,系统提示"5个工作日内到账,节假日顺延,如有疑问请联系客服"

7.2.1 状态枚举

  • pending:待审核
  • approved:已通过待打款
  • rejected:已拒绝
  • paid:已打款完成

7.2.2 状态转换

  • pending -> approved(管理员审核通过)
  • pending -> rejected(管理员审核拒绝)
  • approved -> paid(管理员登记打款完成)

7.2.3 账单联动

  • 提现申请通过(approved)时点,生成对应 ledger 流水:
    • biz_type=withdrawdirection=out
    • 扣减 player.balance
  • 若有手续费,可拆两条流水(提现金额 + 手续费)

7.2.4 T+1申请校验逻辑

  • 可提现金额计算公式:
    可提现金额 = SUM(order.amount WHERE status='completed' AND completed_at <= NOW() - INTERVAL 24 HOUR) 
               - SUM(withdraw_request.amount WHERE status IN ('pending', 'approved'))
    
  • 提交提现申请时校验:申请金额 ≤ 可提现金额,否则返回 INSUFFICIENT_WITHDRAWABLE_BALANCE
  • 到账时间文案(提交成功后显示):"5个工作日内到账,节假日顺延,如有疑问请联系客服"

7.3 充值申请状态(recharge_request.status

7.3.1 状态枚举

  • pending:待审核(客服提交后初始态)
  • approved:已通过(管理员审核通过,已到账)
  • rejected:已拒绝(管理员审核拒绝)

7.3.2 状态转换

pending ──> approved  (管理员审核通过,boss.balance 增加)
pending ──> rejected  (管理员审核拒绝)

7.3.3 关键规则

  • 审核通过后即时到账:生成 ledger 流水,boss.balance 增加
  • 拒绝后可重新申请:客服可针对同一 Boss 再次提交充值申请
  • 审核必须留痕audit_byaudit_ataudit_remark 必填

7.4 订单评价状态(order_review

7.4.1 评价规则

  • 评价开关:系统设置 review_enabled 控制全局是否允许评价
  • 评价时机:订单状态为 completed 后,Boss可随时评价,无时间限制
  • 评价次数:每个订单中每个陪玩只能被评价一次
  • 多陪玩支持:一个订单可由多个陪玩完成,Boss可分别对每个陪玩评价

7.4.2 评价状态

  • created:评价已创建
  • visible:评价可见(用于审核场景,可选)
  • deleted:评价已删除(管理员删除违规评价)

7.4.3 评价数据

  • 评分维度:技术(1-5星)、互动(1-5星)、态度(1-5星)
  • 文字评价:最多30字
  • 是否匿名:布尔值,匿名评价不显示Boss名称

7.5.1 乐观锁(状态机控制)

  • order 表增加 version INT DEFAULT 1 字段
  • 状态变更使用乐观锁模式:
UPDATE `order` 
SET status = 'completed', version = version + 1, completed_at = NOW()
WHERE id = ? AND version = ? AND status = 'created'
  • 影响行数 = 0 时,说明并发冲突或状态已变更,需返回错误提示前端重试

7.5.2 幂等表设计

CREATE TABLE idempotent_request (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  idempotent_key VARCHAR(64) NOT NULL,  -- client_request_id + user_id 组合
  user_type VARCHAR(16) NOT NULL,       -- player/boss/admin
  user_id BIGINT UNSIGNED NOT NULL,
  resource_type VARCHAR(32) NOT NULL,   -- order/withdraw
  resource_id BIGINT UNSIGNED NULL,
  response_body JSON NULL,              -- 首次请求的响应,用于幂等返回
  expired_at DATETIME NOT NULL,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id),
  UNIQUE KEY uk_idempotent_key (idempotent_key),
  KEY idx_expired_at (expired_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  • 报单、提现创建时必须传入 client_request_id(UUID 或业务端生成)
  • 服务端先查幂等表,存在则直接返回缓存的响应,不存在则执行业务并写入幂等记录
  • 设置 TTL(如 24h)自动清理过期记录

8. UI/UX 设计规范(Pro Max版)

8.1 设计愿景与美学方向

8.1.1 核心理念:赛博电竞奢华风

融合电竞文化的活力与高端服务的精致感,打造一套令人过目难忘的视觉系统。

美学关键词

  • 🎮 电竞基因:暗色基底 + 霓虹光效,传递游戏的激情与能量
  • 💎 奢华质感:玻璃拟态、细腻渐变、精密阴影
  • 动态交互:每一个交互都有反馈,每一次悬停都有惊喜
  • 🌊 流畅动效:页面转场如丝般顺滑,数据变化如呼吸般自然

8.1.2 色彩系统

主色调(暗黑基底)

--bg-primary: #0a0a0f;        /* 深邃黑 - 主背景 */
--bg-secondary: #12121a;      /* 暗灰蓝 - 卡片背景 */
--bg-tertiary: #1a1a25;       /* 浅暗色 - 悬浮层 */
--bg-elevated: #252535;       /* 提升层 - 输入框、按钮 */

强调色(霓虹光效)

--accent-cyan: #00f0ff;       /* 赛博青 - 主要交互 */
--accent-pink: #ff00aa;       /* 霓虹粉 - 次要强调 */
--accent-gold: #ffd700;       /* 电竞金 - 金额、收益 */
--accent-purple: #8b5cf6;     /* 紫罗兰 - 等级、VIP */
--accent-success: #00ff88;    /* 成功绿 */
--accent-warning: #ffaa00;    /* 警告橙 */
--accent-error: #ff3366;      /* 错误红 */

文字色阶

--text-primary: #ffffff;      /* 纯白 - 主标题 */
--text-secondary: #a0a0b0;    /* 灰白 - 正文 */
--text-tertiary: #6b6b7b;     /* 暗灰 - 辅助文字 */
--text-muted: #4a4a5a;        /* 静音灰 - 禁用、占位 */

光效与阴影

/* 霓虹发光 */
--glow-cyan: 0 0 20px rgba(0, 240, 255, 0.5);
--glow-pink: 0 0 20px rgba(255, 0, 170, 0.4);
--glow-gold: 0 0 20px rgba(255, 215, 0, 0.3);

/* 精密阴影 */
--shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 20px rgba(0, 0, 0, 0.4);
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.5);
--shadow-glass: 0 8px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1);

8.1.3 字体系统

字体家族

/* 标题字体 - 科技感几何 */
--font-display: 'Orbitron', 'Noto Sans SC', sans-serif;

/* 正文字体 - 清晰现代 */
--font-body: 'Exo 2', 'Noto Sans SC', sans-serif;

/* 数字字体 - 等宽易读 */
--font-mono: 'JetBrains Mono', 'Noto Sans SC', monospace;

字体层级

层级大小字重用途
Hero48px700大标题、金额
H132px700页面标题
H224px600卡片标题
H318px600小节标题
Body14px400正文内容
Small12px400辅助说明
Micro10px500标签、徽章

8.1.4 间距系统

基础单位:8px

--space-xs: 4px;
--space-sm: 8px;
--space-md: 16px;
--space-lg: 24px;
--space-xl: 32px;
--space-2xl: 48px;
--space-3xl: 64px;

圆角系统

--radius-sm: 4px;     /* 按钮、徽章 */
--radius-md: 8px;     /* 输入框、卡片 */
--radius-lg: 12px;    /* 大卡片、弹窗 */
--radius-xl: 16px;    /* 页面容器 */
--radius-full: 9999px;  /* 圆形元素 */

8.2 全局交互规范

8.2.1 按钮交互

主按钮(霓虹青)

.btn-primary {
  background: linear-gradient(135deg, #00f0ff 0%, #00c8d6 100%);
  color: #0a0a0f;
  border: none;
  padding: 12px 24px;
  border-radius: 8px;
  font-weight: 600;
  position: relative;
  overflow: hidden;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 悬停效果 */
.btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 0 30px rgba(0, 240, 255, 0.6), 0 4px 20px rgba(0, 240, 255, 0.3);
}

/* 点击效果 */
.btn-primary:active {
  transform: translateY(0) scale(0.98);
}

/* 光效流动动画 */
.btn-primary::after {
  content: '';
  position: absolute;
  top: -50%;
  left: -50%;
  width: 200%;
  height: 200%;
  background: linear-gradient(
    45deg,
    transparent 30%,
    rgba(255, 255, 255, 0.3) 50%,
    transparent 70%
  );
  animation: shimmer 3s infinite;
}

@keyframes shimmer {
  0% { transform: translateX(-100%) translateY(-100%); }
  100% { transform: translateX(100%) translateY(100%); }
}

次按钮(玻璃拟态)

.btn-secondary {
  background: rgba(255, 255, 255, 0.05);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(0, 240, 255, 0.3);
  color: #00f0ff;
  padding: 12px 24px;
  border-radius: 8px;
  transition: all 0.3s ease;
}

.btn-secondary:hover {
  background: rgba(0, 240, 255, 0.1);
  border-color: #00f0ff;
  box-shadow: 0 0 20px rgba(0, 240, 255, 0.3);
}

幽灵按钮

.btn-ghost {
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: #a0a0b0;
  transition: all 0.3s ease;
}

.btn-ghost:hover {
  border-color: rgba(255, 255, 255, 0.5);
  color: #ffffff;
  background: rgba(255, 255, 255, 0.05);
}

8.2.2 卡片交互

基础卡片(玻璃拟态)

.card {
  background: linear-gradient(135deg, rgba(26, 26, 37, 0.8) 0%, rgba(18, 18, 26, 0.9) 100%);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  padding: 24px;
  position: relative;
  overflow: hidden;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 顶部光条 */
.card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(0, 240, 255, 0.5), transparent);
}

/* 悬停效果 */
.card:hover {
  transform: translateY(-4px);
  border-color: rgba(0, 240, 255, 0.2);
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4), 0 0 30px rgba(0, 240, 255, 0.1);
}

可点击卡片

.card-clickable {
  cursor: pointer;
  position: relative;
}

.card-clickable:hover::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at var(--mouse-x, 50%) var(--mouse-y, 50%), rgba(0, 240, 255, 0.15) 0%, transparent 50%);
  opacity: 0;
  animation: pulse-in 0.4s ease forwards;
}

@keyframes pulse-in {
  to { opacity: 1; }
}

8.2.3 输入框交互

.input-field {
  background: rgba(37, 37, 53, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 8px;
  padding: 12px 16px;
  color: #ffffff;
  transition: all 0.3s ease;
}

.input-field:hover {
  border-color: rgba(255, 255, 255, 0.2);
}

.input-field:focus {
  border-color: #00f0ff;
  box-shadow: 0 0 0 3px rgba(0, 240, 255, 0.1), 0 0 20px rgba(0, 240, 255, 0.2);
  outline: none;
}

/* 输入时的光效 */
.input-field:focus::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, #00f0ff, transparent);
  animation: glow-line 0.3s ease;
}

8.2.4 列表项交互

.list-item {
  padding: 16px;
  border-radius: 8px;
  transition: all 0.2s ease;
  position: relative;
  overflow: hidden;
}

.list-item:hover {
  background: rgba(255, 255, 255, 0.03);
  transform: translateX(4px);
}

/* 选中状态 */
.list-item.active {
  background: rgba(0, 240, 255, 0.1);
  border-left: 3px solid #00f0ff;
}

/* 滑动删除(移动端) */
.list-item.swipeable {
  touch-action: pan-y;
}

.list-item.swiping-left {
  transform: translateX(-80px);
}

8.2.5 微交互动画

页面加载动画

/* 渐入 + 上滑 */
@keyframes page-enter {
  0% {
    opacity: 0;
    transform: translateY(20px);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

.page-container {
  animation: page-enter 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 交错动画 */
.stagger-item {
  opacity: 0;
  transform: translateY(20px);
  animation: page-enter 0.5s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

.stagger-item:nth-child(1) { animation-delay: 0.05s; }
.stagger-item:nth-child(2) { animation-delay: 0.1s; }
.stagger-item:nth-child(3) { animation-delay: 0.15s; }
.stagger-item:nth-child(4) { animation-delay: 0.2s; }
.stagger-item:nth-child(5) { animation-delay: 0.25s; }

数字滚动动画

@keyframes count-up {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.number-animate {
  animation: count-up 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

脉冲通知

@keyframes pulse-glow {
  0%, 100% { box-shadow: 0 0 5px rgba(255, 0, 170, 0.5); }
  50% { box-shadow: 0 0 20px rgba(255, 0, 170, 0.8), 0 0 40px rgba(255, 0, 170, 0.4); }
}

.notification-badge {
  animation: pulse-glow 2s ease-in-out infinite;
}

加载状态

/* 骨架屏 */
.skeleton {
  background: linear-gradient(90deg, #1a1a25 25%, #252535 50%, #1a1a25 75%);
  background-size: 200% 100%;
  animation: skeleton-loading 1.5s ease-in-out infinite;
  border-radius: 4px;
}

@keyframes skeleton-loading {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* 旋转加载 */
.spinner {
  width: 24px;
  height: 24px;
  border: 2px solid rgba(0, 240, 255, 0.2);
  border-top-color: #00f0ff;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

成功/失败反馈

/* 成功勾选动画 */
@keyframes check-stroke {
  0% { stroke-dashoffset: 100; }
  100% { stroke-dashoffset: 0; }
}

.success-icon path {
  stroke-dasharray: 100;
  animation: check-stroke 0.5s ease forwards;
}

/* 错误抖动 */
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-5px); }
  75% { transform: translateX(5px); }
}

.error-shake {
  animation: shake 0.4s ease;
}

8.3 导航组件设计

8.3.1 底部Tab栏(Player/Boss移动端)

.bottom-tab-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 70px;
  background: linear-gradient(180deg, rgba(10, 10, 15, 0.9) 0%, #0a0a0f 100%);
  backdrop-filter: blur(20px);
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  display: flex;
  justify-content: space-around;
  align-items: center;
  padding-bottom: env(safe-area-inset-bottom);
}

.tab-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 8px 24px;
  color: #6b6b7b;
  transition: all 0.3s ease;
  position: relative;
}

.tab-item.active {
  color: #00f0ff;
}

/* 选中指示器 */
.tab-item.active::before {
  content: '';
  position: absolute;
  top: -8px;
  width: 40px;
  height: 3px;
  background: linear-gradient(90deg, transparent, #00f0ff, transparent);
  border-radius: 2px;
  box-shadow: 0 0 10px rgba(0, 240, 255, 0.5);
}

/* 图标动画 */
.tab-item svg {
  transition: transform 0.3s ease;
}

.tab-item:hover svg,
.tab-item.active svg {
  transform: scale(1.1);
  filter: drop-shadow(0 0 8px rgba(0, 240, 255, 0.5));
}

8.3.2 侧边菜单栏(Admin后台)

.sidebar {
  width: 260px;
  height: 100vh;
  background: linear-gradient(180deg, #12121a 0%, #0a0a0f 100%);
  border-right: 1px solid rgba(255, 255, 255, 0.05);
  display: flex;
  flex-direction: column;
  position: fixed;
  left: 0;
  top: 0;
}

.sidebar-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 20px;
  margin: 4px 12px;
  border-radius: 8px;
  color: #a0a0b0;
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
}

.sidebar-item:hover {
  background: rgba(255, 255, 255, 0.03);
  color: #ffffff;
  transform: translateX(4px);
}

.sidebar-item.active {
  background: linear-gradient(90deg, rgba(0, 240, 255, 0.1) 0%, transparent 100%);
  color: #00f0ff;
  border-left: 2px solid #00f0ff;
}

/* 激活光效 */
.sidebar-item.active::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 20px;
  background: #00f0ff;
  border-radius: 0 2px 2px 0;
  box-shadow: 0 0 10px rgba(0, 240, 255, 0.8);
}

8.4 Player端(陪玩端)页面设计

8.4.1 登录页

布局结构

  • 全屏深紫渐变背景 + 动态粒子效果
  • 中央悬浮卡片(玻璃拟态)
  • Logo顶部居中 + 赛博光效

交互细节

/* 背景粒子动画 */
.particles-bg {
  position: fixed;
  inset: 0;
  background: 
    radial-gradient(ellipse at 20% 20%, rgba(139, 92, 246, 0.15) 0%, transparent 50%),
    radial-gradient(ellipse at 80% 80%, rgba(0, 240, 255, 0.1) 0%, transparent 50%),
    #0a0a0f;
}

/* 登录卡片 */
.login-card {
  width: 360px;
  padding: 48px 32px;
  background: rgba(18, 18, 26, 0.8);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 16px;
  box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5), 0 0 30px rgba(0, 240, 255, 0.1);
}

/* Logo光效 */
.logo-glow {
  filter: drop-shadow(0 0 20px rgba(0, 240, 255, 0.6));
  animation: logo-pulse 3s ease-in-out infinite;
}

/* 输入框聚焦光效 */
.login-input:focus {
  border-color: #00f0ff;
  box-shadow: 0 0 0 3px rgba(0, 240, 255, 0.2), 0 0 30px rgba(0, 240, 255, 0.3);
}

动画效果

  • 页面加载:卡片从下方滑入 + 淡入(0.6s)
  • 输入框:聚焦时底部光条从左到右流动
  • 登录按钮:悬停时霓虹光晕扩散
  • 错误提示:输入框抖动 + 红光闪烁

8.4.2 排行榜页

布局结构

  • 顶部:时间段切换器(日/周/月)
  • 中部:Top 3 奖牌展示区(大字突出)
  • 下部:4-20名列表

视觉设计

/* 时间段切换器 */
.time-switcher {
  display: flex;
  gap: 8px;
  padding: 4px;
  background: rgba(255, 255, 255, 0.05);
  border-radius: 12px;
}

.time-option {
  padding: 8px 20px;
  border-radius: 8px;
  transition: all 0.3s ease;
}

.time-option.active {
  background: linear-gradient(135deg, #00f0ff 0%, #00c8d6 100%);
  color: #0a0a0f;
  box-shadow: 0 0 20px rgba(0, 240, 255, 0.4);
}

/* Top 3 奖牌 */
.top-rank-1 {
  background: linear-gradient(135deg, rgba(255, 215, 0, 0.2) 0%, rgba(255, 215, 0, 0.05) 100%);
  border: 1px solid rgba(255, 215, 0, 0.3);
  box-shadow: 0 0 30px rgba(255, 215, 0, 0.2);
}

.top-rank-2 {
  background: linear-gradient(135deg, rgba(192, 192, 192, 0.2) 0%, rgba(192, 192, 192, 0.05) 100%);
  border: 1px solid rgba(192, 192, 192, 0.3);
}

.top-rank-3 {
  background: linear-gradient(135deg, rgba(205, 127, 50, 0.2) 0%, rgba(205, 127, 50, 0.05) 100%);
  border: 1px solid rgba(205, 127, 50, 0.3);
}

交互动画

  • 切换时间段:数字翻转动画(像老虎机一样滚动)
  • 列表项:悬停时右移 + 光效追踪鼠标
  • 排名变化:数字上下浮动提示(↑↓)
  • 自己的排名:整行高亮脉冲

8.4.3 任务大厅页

布局结构

  • 顶部:筛选栏(类目、价格区间)
  • 中部:可抢订单卡片网格
  • 底部:刷新按钮 + 最后更新时间

卡片设计

.task-card {
  background: linear-gradient(135deg, rgba(26, 26, 37, 0.9) 0%, rgba(18, 18, 26, 0.95) 100%);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  padding: 20px;
  position: relative;
  overflow: hidden;
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 紧急标签 */
.urgent-badge {
  position: absolute;
  top: 12px;
  right: 12px;
  background: linear-gradient(135deg, #ff3366 0%, #ff0066 100%);
  padding: 4px 12px;
  border-radius: 20px;
  font-size: 10px;
  font-weight: 600;
  animation: urgent-pulse 2s ease-in-out infinite;
}

/* 金额显示 */
.amount-display {
  font-family: 'JetBrains Mono', monospace;
  font-size: 24px;
  font-weight: 700;
  color: #ffd700;
  text-shadow: 0 0 10px rgba(255, 215, 0, 0.3);
}

/* 抢单按钮 */
.claim-btn {
  width: 100%;
  padding: 12px;
  background: linear-gradient(135deg, #00f0ff 0%, #00c8d6 100%);
  border: none;
  border-radius: 8px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
}

.claim-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 0 30px rgba(0, 240, 255, 0.5);
}

交互效果

  • 下拉刷新:顶部拉出加载动画 + 骨架屏
  • 抢单按钮点击:波纹扩散 + 按钮变灰加载
  • 新订单:卡片从顶部滑入(带音效提示)
  • 已被抢订单:变灰 + 半透明 + "已被抢"水印

8.4.4 我的订单页

布局结构

  • 顶部:状态标签栏(横向滑动)
  • 中部:订单列表
  • 底部:统计概览

状态标签

.status-tabs {
  display: flex;
  gap: 12px;
  padding: 16px;
  overflow-x: auto;
  scrollbar-width: none;
}

.status-tab {
  padding: 8px 16px;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  white-space: nowrap;
  transition: all 0.3s ease;
}

.status-tab.active {
  background: rgba(0, 240, 255, 0.15);
  border-color: #00f0ff;
  color: #00f0ff;
  box-shadow: 0 0 15px rgba(0, 240, 255, 0.3);
}

/* 小红点 */
.status-dot {
  width: 6px;
  height: 6px;
  background: #ff3366;
  border-radius: 50%;
  margin-left: 6px;
  animation: dot-pulse 2s ease-in-out infinite;
}

订单卡片状态色

  • 待确认:pending_dispatch - 黄色光晕
  • 待开始:player_accepted - 青色光晕
  • 服务中:in_service - 绿色脉冲光晕
  • 待确认完成:completion_pending - 橙色闪烁
  • 已完成:completed - 金色边框

交互效果

  • 状态切换:标签滑动 + 内容淡入淡出
  • 订单卡片左滑:显示快捷操作(开始服务/提交完成)
  • 下拉刷新:骨架屏 + 数字滚动更新
  • 空状态:动态插画 + 引导按钮

8.4.5 账单页

布局结构

  • 顶部:月份选择器 + 收支汇总
  • 中部:账单列表(按日期分组)

汇总卡片

.summary-card {
  display: flex;
  justify-content: space-around;
  padding: 24px;
  background: linear-gradient(135deg, rgba(0, 240, 255, 0.1) 0%, rgba(139, 92, 246, 0.1) 100%);
  border: 1px solid rgba(0, 240, 255, 0.2);
  border-radius: 16px;
}

.summary-item {
  text-align: center;
}

.summary-value {
  font-family: 'JetBrains Mono', monospace;
  font-size: 28px;
  font-weight: 700;
  background: linear-gradient(135deg, #ffd700 0%, #ffaa00 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

账单项交互

  • 收入:左侧绿色流入箭头 + 金额金色
  • 支出:左侧红色流出箭头 + 金额白色
  • 点击展开:显示详情(时间、订单号、备注)
  • 月份切换:上下滑动选择器 + 数字滚动

8.4.6 个人中心页

布局结构

  • 顶部:用户信息卡片(头像、昵称、等级)
  • 中部:数据统计(本月收入、完成订单)
  • 下部:功能菜单列表

用户卡片

.profile-card {
  padding: 32px 24px;
  background: linear-gradient(135deg, rgba(139, 92, 246, 0.2) 0%, rgba(0, 240, 255, 0.1) 100%);
  border-radius: 16px;
  position: relative;
  overflow: hidden;
}

/* 头像光晕 */
.avatar-glow {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  border: 3px solid rgba(0, 240, 255, 0.5);
  box-shadow: 0 0 30px rgba(0, 240, 255, 0.3);
}

/* 等级徽章 */
.level-badge {
  padding: 4px 12px;
  background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%);
  border-radius: 12px;
  font-size: 12px;
  font-weight: 600;
}

菜单列表

  • 每个菜单项:图标 + 文字 + 右箭头
  • 悬停效果:背景变亮 + 右移
  • 新功能标记:粉色"NEW"角标

8.5 Boss端(老板端)页面设计

8.5.1 首页/排行榜

布局结构

  • 顶部:欢迎语 + 快捷操作
  • 中部:消费统计概览
  • 下部:消费排行榜

消费统计卡片

.consume-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  padding: 24px;
}

.stat-card {
  padding: 20px;
  background: rgba(26, 26, 37, 0.8);
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.08);
}

.stat-value {
  font-family: 'JetBrains Mono', monospace;
  font-size: 24px;
  font-weight: 700;
  color: #ff00aa;
  text-shadow: 0 0 10px rgba(255, 0, 170, 0.3);
}

8.5.2 下单页

布局结构

  • 顶部:类目选择(横向卡片)
  • 中部:附加项选择
  • 底部:金额预览 + 提交按钮

类目卡片

.category-card {
  padding: 20px;
  background: rgba(26, 26, 37, 0.6);
  border: 2px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.category-card:hover {
  border-color: rgba(255, 0, 170, 0.5);
  background: rgba(255, 0, 170, 0.05);
}

.category-card.selected {
  border-color: #ff00aa;
  background: rgba(255, 0, 170, 0.1);
  box-shadow: 0 0 20px rgba(255, 0, 170, 0.3);
}

金额预览

  • 实时计算显示
  • 数字变化时滚动动画
  • 余额不足时红色警告 + 抖动

8.5.3 我的订单页

布局结构

  • 顶部:搜索栏 + 筛选器
  • 中部:订单列表
  • 底部:分页/加载更多

搜索栏

.search-bar {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  background: rgba(37, 37, 53, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  transition: all 0.3s ease;
}

.search-bar:focus-within {
  border-color: #ff00aa;
  box-shadow: 0 0 0 3px rgba(255, 0, 170, 0.1);
}

订单卡片

  • 显示:订单号、状态、金额、时间
  • 状态色:与Player端对应
  • 可评价订单:显示评价按钮(金色闪烁)

8.5.4 评价页

布局结构

  • 顶部:订单信息摘要
  • 中部:评分维度(三维度)
  • 下部:文字评价 + 匿名选项 + 提交

评分星星

.star-rating {
  display: flex;
  gap: 8px;
  font-size: 32px;
}

.star {
  color: #4a4a5a;
  cursor: pointer;
  transition: all 0.2s ease;
}

.star:hover,
.star.active {
  color: #ffd700;
  text-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
  transform: scale(1.2);
}

/* 评分动画 */
@keyframes star-pop {
  0% { transform: scale(1); }
  50% { transform: scale(1.3); }
  100% { transform: scale(1.1); }
}

.star.active {
  animation: star-pop 0.3s ease;
}

8.6 Admin端(后台管理)页面设计

8.6.1 仪表盘

布局结构

  • 顶部:数据概览卡片网格
  • 中部:趋势图表
  • 下部:待办事项列表

概览卡片

.dashboard-card {
  padding: 24px;
  background: linear-gradient(135deg, rgba(26, 26, 37, 0.9) 0%, rgba(18, 18, 26, 0.95) 100%);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  position: relative;
  overflow: hidden;
}

/* 卡片顶部色条 */
.dashboard-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, #00f0ff, #ff00aa);
}

.dashboard-value {
  font-family: 'JetBrains Mono', monospace;
  font-size: 36px;
  font-weight: 700;
  color: #ffffff;
}

/* 趋势指示 */
.trend-up {
  color: #00ff88;
}

.trend-down {
  color: #ff3366;
}

图表设计

  • 折线图:霓虹渐变线条(青到粉)
  • 柱状图:玻璃拟态柱子带光效
  • 悬停:数据点放大 + tooltip玻璃卡片

8.6.2 订单管理

布局结构

  • 左侧:筛选面板
  • 中部:订单表格
  • 右侧:订单详情抽屉

表格设计

.data-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0 8px;
}

.data-table th {
  padding: 12px 16px;
  text-align: left;
  color: #6b6b7b;
  font-weight: 500;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.data-table td {
  padding: 16px;
  background: rgba(26, 26, 37, 0.6);
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.data-table tr:hover td {
  background: rgba(255, 255, 255, 0.05);
}

/* 状态徽章 */
.status-badge {
  padding: 4px 12px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 500;
}

.status-badge.published {
  background: rgba(0, 240, 255, 0.15);
  color: #00f0ff;
}

.status-badge.in-service {
  background: rgba(0, 255, 136, 0.15);
  color: #00ff88;
}

交互效果

  • 行悬停:高亮 + 显示快捷操作按钮
  • 点击行:右侧滑出详情抽屉
  • 新订单:整行闪烁提醒(3秒后消失)
  • 批量选择:复选框动画 + 底部操作栏浮出

8.6.3 提现审核

布局结构

  • 顶部:统计卡片 + 筛选器
  • 中部:申请列表
  • 审核弹窗:详情 + 通过/拒绝

审核弹窗

.audit-modal {
  width: 480px;
  padding: 32px;
  background: linear-gradient(135deg, #12121a 0%, #0a0a0f 100%);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 16px;
  box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5);
}

.audit-amount {
  font-family: 'JetBrains Mono', monospace;
  font-size: 32px;
  font-weight: 700;
  color: #ffd700;
  text-align: center;
  margin: 24px 0;
}

.audit-buttons {
  display: flex;
  gap: 16px;
  margin-top: 24px;
}

.btn-approve {
  flex: 1;
  padding: 14px;
  background: linear-gradient(135deg, #00ff88 0%, #00cc6a 100%);
  border: none;
  border-radius: 8px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
}

.btn-reject {
  flex: 1;
  padding: 14px;
  background: rgba(255, 51, 102, 0.1);
  border: 1px solid #ff3366;
  color: #ff3366;
  border-radius: 8px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
}

8.6.4 用户管理

布局结构

  • 顶部:搜索 + 新增按钮
  • 中部:用户表格(头像、信息、状态)
  • 操作:编辑/禁用/重置密码

用户卡片

.user-cell {
  display: flex;
  align-items: center;
  gap: 12px;
}

.user-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.1);
}

.user-status {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #00ff88;
  box-shadow: 0 0 8px rgba(0, 255, 136, 0.5);
}

.user-status.disabled {
  background: #ff3366;
  box-shadow: 0 0 8px rgba(255, 51, 102, 0.5);
}

8.6.5 系统设置

布局结构

  • 左侧:设置分类菜单
  • 右侧:设置表单

设置项

.setting-item {
  padding: 24px;
  background: rgba(26, 26, 37, 0.6);
  border-radius: 12px;
  margin-bottom: 16px;
}

.setting-label {
  font-size: 14px;
  font-weight: 600;
  color: #ffffff;
  margin-bottom: 8px;
}

.setting-desc {
  font-size: 12px;
  color: #6b6b7b;
  margin-bottom: 16px;
}

/* 开关 */
.toggle-switch {
  width: 48px;
  height: 24px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  position: relative;
  cursor: pointer;
  transition: all 0.3s ease;
}

.toggle-switch.active {
  background: linear-gradient(135deg, #00f0ff 0%, #00c8d6 100%);
}

.toggle-switch::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  background: #ffffff;
  border-radius: 50%;
  transition: all 0.3s ease;
}

.toggle-switch.active::after {
  left: 26px;
}

8.7 响应式适配规则

8.7.1 断点定义

/* 移动端 */
@media (max-width: 767px) {
  /* 底部Tab导航 */
  /* 单列布局 */
  /* 全宽卡片 */
}

/* 平板 */
@media (min-width: 768px) and (max-width: 1023px) {
  /* 侧边导航 */
  /* 双列布局 */
}

/* 桌面 */
@media (min-width: 1024px) {
  /* 固定侧边栏 */
  /* 多列布局 */
  /* 最大宽度容器 */
}

8.7.2 移动端特殊处理

  • 所有点击区域 ≥ 44px
  • 列表项支持左滑操作
  • 模态框全屏显示
  • 底部固定操作栏(有安全区适配)

8.8 无障碍设计

  • 所有交互元素支持键盘导航
  • 焦点状态清晰可见(青色边框)
  • 颜色对比度符合WCAG 2.1 AA标准
  • 重要操作有文字提示(不仅是颜色)

9. 配置与 .env 规范(分环境)

9.1 目标

  • 配置与代码分离,便于你后续在生产环境快速修改
  • 支持 dev/staging/prod 分环境
  • 重要信息(DB 密码、会话密钥)不写死、不提交仓库

9.2 文件组织建议

  • env/.env.development
  • env/.env.staging
  • env/.env.production

部署时按环境注入对应文件内容或等价环境变量。

9.3 .env 模板(包含你的 MySQL 8.1)

APP_NAME=club-system
APP_ENV=development
APP_PORT=8080
APP_BASE_URL=http://localhost:8080

# Security
SESSION_SECRET=change_me
COOKIE_SECURE=false
COOKIE_SAMESITE=lax

# MySQL
DB_HOST=192.168.6.99
DB_PORT=3306
DB_NAME=cdb
DB_USER=cdb
DB_PASSWORD=cdb@2026
DB_CHARSET=utf8mb4
DB_TIMEZONE=+08:00

# Optional Redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=

# Logging
LOG_LEVEL=info

9.4 安全约束

  • .env 加入 .gitignore
  • 生产环境:
    • COOKIE_SECURE=true
    • SESSION_SECRET 使用强随机值
    • DB 账号建议最小权限 + 限制来源 IP

10. 非功能需求(NFR)

10.1 性能

  • 列表接口必须分页(默认 20/页)
  • 排行榜按维度缓存(day/week/month)
  • 慢查询监控(MySQL slow log)

10.2 可靠性与一致性

  • 报单/提现接口支持幂等(防重复提交)
  • 金额计算与关键校验必须在服务端完成
  • 订单状态变更必须校验“合法前置状态”

10.3 安全

  • 密码哈希:bcrypt/argon2
  • 登录限流、防暴力破解
  • 后台敏感操作审计(提现、管理员、系统设置)

10.4 实时通知(WebSocket/SSE)

  • 后台管理系统需支持实时通知(下单/提现/充值提醒)
  • 技术选型建议:
    • WebSocket:适合高实时性场景,支持双向通信
    • SSE(Server-Sent Events):适合单向推送,实现简单,自动重连
  • 降级方案:REST轮询接口 /api/v1/admin/notifications/poll
  • 连接管理:
    • 心跳机制(30秒间隔)
    • 断线自动重连
    • 多标签页同步(避免重复提醒)

10.5 可观测

  • 请求日志:requestId、userId、端类型、耗时、错误码
  • 审计日志:操作人、操作内容、前后差异、IP、时间
  • WebSocket日志:连接数、消息推送成功率

11. 部署与运维方案

11.1 部署拓扑建议

  • Nginx/网关
    • HTTPS
    • 反向代理到后端
    • 静态资源缓存策略
  • 后端服务
    • Docker 化
    • 水平扩展(无状态)
  • MySQL 8.1
    • 定期备份
    • 慢查询与性能监控

11.2 备份与回滚

  • 数据:每日全量备份 + binlog
  • 应用:镜像版本化,可快速回滚

11.3 迁移与初始化

  • 建议使用 migrations(按版本管理建表/改表)
  • 初始化数据:
    • 管理员角色、管理员账号
    • 示例类目/等级/附加项(可选)

12. 测试方案

12.1 接口测试(必须覆盖)

  • 认证:login、login-check、logout
  • Player:报单创建、报单记录查询、账单查询
  • Boss:订单记录查询、账单查询
  • Admin:订单查询、提现审核链路、配置 CRUD

12.2 E2E(端到端)

  • Player 创建报单 -> Boss 订单记录可见 -> Admin 订单管理可查
  • Admin 提现审核(若启用)-> 状态流转正确 -> 账单流水生成

12.3 权限与越权

  • Player/Boss 无法访问他人订单/账单
  • Admin 不同角色权限隔离生效

附录 A:建表 SQL(可执行)

执行前请确认当前库为 cdb,并确保账号具备建表权限。

CREATE TABLE IF NOT EXISTS ipm_player (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  phone VARCHAR(20) NOT NULL COMMENT '手机号,登录用',
  email VARCHAR(128) NOT NULL DEFAULT '' COMMENT '邮箱',
  username VARCHAR(64) NOT NULL COMMENT '用户名,展示用',
  password_hash VARCHAR(255) NOT NULL,
  nickname VARCHAR(64) NOT NULL DEFAULT '',
  avatar_url VARCHAR(255) NOT NULL DEFAULT '',
  level_id BIGINT UNSIGNED NULL,
  balance DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '可提现余额',
  status TINYINT NOT NULL DEFAULT 1,
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  UNIQUE KEY uk_player_phone (phone),
  UNIQUE KEY uk_player_username (username),
  KEY idx_player_level_id (level_id),
  KEY idx_player_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='陪玩账号表';

CREATE TABLE IF NOT EXISTS ipm_boss (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  phone VARCHAR(20) NOT NULL COMMENT '手机号,登录用',
  email VARCHAR(128) NOT NULL DEFAULT '' COMMENT '邮箱',
  username VARCHAR(64) NOT NULL COMMENT '用户名,展示用',
  password_hash VARCHAR(255) NOT NULL,
  nickname VARCHAR(64) NOT NULL DEFAULT '',
  balance DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '可用余额,用于下单',
  status TINYINT NOT NULL DEFAULT 1,
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  UNIQUE KEY uk_boss_phone (phone),
  UNIQUE KEY uk_boss_username (username),
  KEY idx_boss_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='老板账号表';

CREATE TABLE IF NOT EXISTS ipm_admin_role (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  name VARCHAR(64) NOT NULL,
  status TINYINT NOT NULL DEFAULT 1,
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  UNIQUE KEY uk_admin_role_name (name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='后台角色表';

CREATE TABLE IF NOT EXISTS ipm_admin_user (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  username VARCHAR(64) NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  role_id BIGINT UNSIGNED NOT NULL,
  status TINYINT NOT NULL DEFAULT 1,
  last_login_at DATETIME(3) NULL,
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  UNIQUE KEY uk_admin_user_username (username),
  KEY idx_admin_user_role_id (role_id),
  CONSTRAINT fk_admin_user_role FOREIGN KEY (role_id) REFERENCES ipm_admin_role(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='后台用户表';

CREATE TABLE IF NOT EXISTS ipm_category (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  name VARCHAR(64) NOT NULL,
  status TINYINT NOT NULL DEFAULT 1,
  sort INT NOT NULL DEFAULT 0,
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  UNIQUE KEY uk_category_name (name),
  KEY idx_category_status_sort (status, sort)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='类目表';

CREATE TABLE IF NOT EXISTS ipm_addon_item (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  name VARCHAR(64) NOT NULL,
  price DECIMAL(12,2) NOT NULL DEFAULT 0.00,
  status TINYINT NOT NULL DEFAULT 1,
  sort INT NOT NULL DEFAULT 0,
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  UNIQUE KEY uk_addon_item_name (name),
  KEY idx_addon_item_status_sort (status, sort)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='附加项表';

CREATE TABLE IF NOT EXISTS ipm_level (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  name VARCHAR(64) NOT NULL,
  threshold DECIMAL(12,2) NOT NULL DEFAULT 0.00,
  benefits_json JSON NULL,
  status TINYINT NOT NULL DEFAULT 1,
  sort INT NOT NULL DEFAULT 0,
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  UNIQUE KEY uk_level_name (name),
  KEY idx_level_status_sort (status, sort)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='等级表';

-- 订单/账单/提现/审计表在下一段继续

CREATE TABLE IF NOT EXISTS ipm_order (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  order_no VARCHAR(32) NOT NULL,
  boss_id BIGINT UNSIGNED NOT NULL COMMENT '下单Boss',
  player_id BIGINT UNSIGNED NULL COMMENT '主接单陪玩(多陪玩场景保留第一个或NULL,具体看ipm_order_player_history)',
  category_id BIGINT UNSIGNED NULL COMMENT '类目',
  amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '订单金额',
  required_players INT NOT NULL DEFAULT 1 COMMENT '需要陪玩数量(默认1,如需要2人组队则为2)',
  status VARCHAR(32) NOT NULL COMMENT 'submitted/pending_dispatch/published/partially_accepted/player_accepted/in_service/completion_pending/completed/canceled',
  remark VARCHAR(255) NOT NULL DEFAULT '' COMMENT '服务要求/备注',
  viewed_by BIGINT UNSIGNED NULL COMMENT '首个查看的客服ID(查看冲突处理)',
  viewed_at DATETIME(3) NULL COMMENT '首个查看时间',
  share_token VARCHAR(64) NULL COMMENT '任务分享Token(用于微信/QQ分享链接)',
  version INT NOT NULL DEFAULT 1 COMMENT '乐观锁版本号',
  accepted_at DATETIME(3) NULL COMMENT '陪玩接单时间(第一个接单时记录)',
  started_at DATETIME(3) NULL COMMENT '开始服务时间',
  player_completed_at DATETIME(3) NULL COMMENT '陪玩提交完成时间',
  completed_at DATETIME(3) NULL COMMENT '客服确认完成时间',
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  UNIQUE KEY uk_order_no (order_no),
  KEY idx_order_boss_created (boss_id, created_at),
  KEY idx_order_status_created (status, created_at),
  KEY idx_order_viewed_by (viewed_by),
  KEY idx_order_status_completed (status, completed_at),
  CONSTRAINT fk_order_boss FOREIGN KEY (boss_id) REFERENCES ipm_boss(id),
  CONSTRAINT fk_order_category FOREIGN KEY (category_id) REFERENCES ipm_category(id),
  CONSTRAINT fk_order_viewed_by FOREIGN KEY (viewed_by) REFERENCES ipm_admin_user(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单主表';

CREATE TABLE IF NOT EXISTS ipm_order_addon (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  order_id BIGINT UNSIGNED NOT NULL,
  addon_item_id BIGINT UNSIGNED NOT NULL,
  price DECIMAL(12,2) NOT NULL DEFAULT 0.00,
  qty INT NOT NULL DEFAULT 1,
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  KEY idx_order_addon_order_id (order_id),
  CONSTRAINT fk_order_addon_order FOREIGN KEY (order_id) REFERENCES ipm_order(id),
  CONSTRAINT fk_order_addon_item FOREIGN KEY (addon_item_id) REFERENCES ipm_addon_item(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单附加项明细表';

CREATE TABLE IF NOT EXISTS ipm_ledger (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  user_type VARCHAR(16) NOT NULL,
  user_id BIGINT UNSIGNED NOT NULL,
  biz_type VARCHAR(32) NOT NULL,
  direction VARCHAR(8) NOT NULL,
  amount DECIMAL(12,2) NOT NULL DEFAULT 0.00,
  balance_after DECIMAL(12,2) NULL,
  ref_type VARCHAR(32) NULL,
  ref_id BIGINT UNSIGNED NULL,
  note VARCHAR(255) NOT NULL DEFAULT '',
  status TINYINT NOT NULL DEFAULT 1,          -- 1有效 0已冲正
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  KEY idx_ledger_user_created (user_type, user_id, created_at),
  KEY idx_ledger_biz_created (biz_type, created_at),
  KEY idx_ledger_ref (ref_type, ref_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='账单流水表';

CREATE TABLE IF NOT EXISTS ipm_withdraw_request (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  player_id BIGINT UNSIGNED NOT NULL,
  amount DECIMAL(12,2) NOT NULL DEFAULT 0.00,
  pay_channel VARCHAR(32) NOT NULL COMMENT '收款方式:bank/alipay/wechat',
  pay_account VARCHAR(128) NOT NULL COMMENT '收款账号',
  pay_name VARCHAR(64) NOT NULL DEFAULT '' COMMENT '收款人姓名',
  status VARCHAR(16) NOT NULL,
  audit_by BIGINT UNSIGNED NULL,
  audit_at DATETIME(3) NULL,
  audit_remark VARCHAR(255) NOT NULL DEFAULT '' COMMENT '审核备注',
  pay_at DATETIME(3) NULL,
  pay_remark VARCHAR(255) NOT NULL DEFAULT '' COMMENT '打款备注',
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  KEY idx_withdraw_player_created (player_id, created_at),
  KEY idx_withdraw_status_created (status, created_at),
  CONSTRAINT fk_withdraw_player FOREIGN KEY (player_id) REFERENCES ipm_player(id),
  CONSTRAINT fk_withdraw_audit_by FOREIGN KEY (audit_by) REFERENCES ipm_admin_user(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='提现申请表';

CREATE TABLE IF NOT EXISTS ipm_recharge_request (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  boss_id BIGINT UNSIGNED NOT NULL COMMENT '充值的Boss账号',
  amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '充值金额',
  status VARCHAR(16) NOT NULL DEFAULT 'pending' COMMENT 'pending/approved/rejected',
  apply_by BIGINT UNSIGNED NOT NULL COMMENT '申请人(客服)',
  apply_remark VARCHAR(255) NOT NULL DEFAULT '' COMMENT '申请备注',
  audit_by BIGINT UNSIGNED NULL COMMENT '审核人(管理员)',
  audit_at DATETIME(3) NULL,
  audit_remark VARCHAR(255) NOT NULL DEFAULT '' COMMENT '审核备注',
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  KEY idx_recharge_boss_created (boss_id, created_at),
  KEY idx_recharge_status_created (status, created_at),
  KEY idx_recharge_apply_by (apply_by),
  CONSTRAINT fk_recharge_boss FOREIGN KEY (boss_id) REFERENCES ipm_boss(id),
  CONSTRAINT fk_recharge_apply_by FOREIGN KEY (apply_by) REFERENCES ipm_admin_user(id),
  CONSTRAINT fk_recharge_audit_by FOREIGN KEY (audit_by) REFERENCES ipm_admin_user(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='充值申请表';

CREATE TABLE IF NOT EXISTS ipm_admin_audit_log (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  admin_user_id BIGINT UNSIGNED NOT NULL,
  action VARCHAR(64) NOT NULL,
  resource_type VARCHAR(32) NOT NULL,
  resource_id BIGINT UNSIGNED NULL,
  before_json JSON NULL,
  after_json JSON NULL,
  ip VARCHAR(64) NOT NULL DEFAULT '',
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  KEY idx_audit_admin_created (admin_user_id, created_at),
  KEY idx_audit_resource (resource_type, resource_id),
  CONSTRAINT fk_audit_admin FOREIGN KEY (admin_user_id) REFERENCES ipm_admin_user(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='后台操作审计日志表';

-- 幂等控制表(生产必须)
CREATE TABLE IF NOT EXISTS ipm_idempotent_request (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  idempotent_key VARCHAR(64) NOT NULL COMMENT 'client_request_id + user_id',
  user_type VARCHAR(16) NOT NULL,
  user_id BIGINT UNSIGNED NOT NULL,
  resource_type VARCHAR(32) NOT NULL,
  resource_id BIGINT UNSIGNED NULL,
  response_body JSON NULL,
  expired_at DATETIME NOT NULL,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id),
  UNIQUE KEY uk_idempotent_key (idempotent_key),
  KEY idx_expired_at (expired_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='幂等请求控制表';

-- 排行榜缓存表(避免实时聚合)
CREATE TABLE IF NOT EXISTS ipm_rank_cache (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  rank_type VARCHAR(32) NOT NULL COMMENT 'income_player/consume_boss',
  range_type VARCHAR(16) NOT NULL COMMENT 'day/week/month',
  user_id BIGINT UNSIGNED NOT NULL,
  user_type VARCHAR(16) NOT NULL,
  rank_num INT NOT NULL,
  amount DECIMAL(12,2) NOT NULL,
  snapshot_date DATE NOT NULL,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id),
  UNIQUE KEY uk_rank_snapshot (rank_type, range_type, snapshot_date, user_id),
  KEY idx_rank_query (rank_type, range_type, snapshot_date, rank_num)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='排行榜快照缓存表';

-- 系统设置表
CREATE TABLE IF NOT EXISTS ipm_system_setting (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  setting_key VARCHAR(64) NOT NULL COMMENT '设置键名',
  setting_value VARCHAR(255) NOT NULL DEFAULT '' COMMENT '设置值',
  description VARCHAR(255) NOT NULL DEFAULT '' COMMENT '设置说明',
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  UNIQUE KEY uk_setting_key (setting_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统设置表';

-- 订单评价表
CREATE TABLE IF NOT EXISTS ipm_order_review (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  order_id BIGINT UNSIGNED NOT NULL COMMENT '订单ID',
  boss_id BIGINT UNSIGNED NOT NULL COMMENT '评价者BossID',
  player_id BIGINT UNSIGNED NOT NULL COMMENT '被评价陪玩ID',
  skill_score TINYINT NOT NULL DEFAULT 0 COMMENT '技术评分(1-5)',
  interaction_score TINYINT NOT NULL DEFAULT 0 COMMENT '互动评分(1-5)',
  attitude_score TINYINT NOT NULL DEFAULT 0 COMMENT '态度评分(1-5)',
  comment VARCHAR(30) NOT NULL DEFAULT '' COMMENT '文字评价(最多30字)',
  is_anonymous TINYINT NOT NULL DEFAULT 0 COMMENT '是否匿名:0否 1是',
  status VARCHAR(16) NOT NULL DEFAULT 'created' COMMENT '状态:created/visible/deleted',
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  UNIQUE KEY uk_review_order_player (order_id, player_id) COMMENT '每个订单每个陪玩只能评价一次',
  KEY idx_review_player (player_id),
  KEY idx_review_order (order_id),
  KEY idx_review_status (status),
  CONSTRAINT fk_review_order FOREIGN KEY (order_id) REFERENCES ipm_order(id),
  CONSTRAINT fk_review_boss FOREIGN KEY (boss_id) REFERENCES ipm_boss(id),
  CONSTRAINT fk_review_player FOREIGN KEY (player_id) REFERENCES ipm_player(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单评价表';

-- 初始化系统设置数据
INSERT INTO ipm_system_setting (setting_key, setting_value, description) VALUES
('review_enabled', '1', '评价功能开关:1开启 0关闭');

-- 订单陪玩历史记录表(支持多陪玩、放弃任务、重新分配场景)
CREATE TABLE IF NOT EXISTS ipm_order_player_history (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  order_id BIGINT UNSIGNED NOT NULL COMMENT '订单ID',
  player_id BIGINT UNSIGNED NOT NULL COMMENT '陪玩ID',
  action VARCHAR(32) NOT NULL COMMENT '动作:accept/started/abandoned/reassigned/submit_complete/confirmed',
  action_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '动作发生时间',
  reason VARCHAR(255) NULL COMMENT '原因(放弃时填写)',
  started_at DATETIME(3) NULL COMMENT '开始服务时间',
  completed_at DATETIME(3) NULL COMMENT '完成服务时间',
  status VARCHAR(16) NOT NULL DEFAULT 'active' COMMENT '状态:active/completed/abandoned/replaced',
  created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (id),
  UNIQUE KEY uk_order_player_action (order_id, player_id, action) COMMENT '同一订单同一陪玩同一动作只能有一条记录',
  KEY idx_order_id (order_id),
  KEY idx_player_id (player_id),
  KEY idx_action (action),
  KEY idx_status (status),
  CONSTRAINT fk_history_order FOREIGN KEY (order_id) REFERENCES ipm_order(id),
  CONSTRAINT fk_history_player FOREIGN KEY (player_id) REFERENCES ipm_player(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单陪玩历史记录表';

-- 定期清理幂等表过期数据的事件(可选)
-- CREATE EVENT IF NOT EXISTS cleanup_idempotent 
--   ON SCHEDULE EVERY 1 HOUR
--   DO DELETE FROM ipm_idempotent_request WHERE expired_at < NOW();

附录 B:待确认清单(用于升级为可直接开发版本)

已确认

  • Boss下单 → 客服处理(分配/发布) → 陪玩接单 → 陪玩服务 → 陪玩完成确认 → 客服确认 → 金额到账
  • 客服查看订单冲突处理:首个查看优先,后查看的提示"已有XXX客服优先查看"
  • 任务分享:支持微信/QQ等社交工具分享
  • 陪玩抢单需二次确认,显示订单详情
  • 多人抢单并发控制:订单可设置所需陪玩数量(required_players),采用"先抢先得"策略,前N个成功,第N+1个及以后提示"订单已被抢走,请刷新页面"
  • 陪玩放弃任务:服务中或已接单状态可放弃,回到待分配状态,其他陪玩可继续抢单
  • 客服重新分配:服务中发现陪玩无法完成,可重新分配或重新发布
  • 订单评价:技术/互动/态度三维度,最高5星,最多30字,可匿名,多陪玩分别评价,只有完成任务的陪玩才能被评价
  • 账号体系:系统自用,注册只能管理员新增,需手机号、邮箱、用户名、密码
  • 余额:显示余额,可用余额直接下单,充值流程为客服申请-管理员审核
  • 提现:手动输入-管理员审核-手动转账,需有记录,24小时后可申请提现,5个工作日内到账

B.1 账号体系

  • 系统自用,关闭自主注册
  • 账号字段:手机号(登录用)、邮箱、用户名(展示用)、密码
  • 账号来源:仅管理员可在后台新增/禁用/重置密码
  • 登录方式:手机号+密码,或 用户名+密码(二选一)
  • 安全:暂不需要短信验证码(系统自用,内部人员)

B.2 Boss下单流程

  • 下单入口:Boss端底部Tab或首页快捷入口
  • 下单字段:类目(选择)、附加项(多选)、服务要求/备注(文本)
  • 金额计算:服务端按后台配置计算,前端预览
  • 余额校验:余额不足禁止下单,提示联系客服充值
  • 下单成功后:所有客服收到实时提醒,订单进入 submitted 状态

B.3 客服订单处理流程

  • 订单提醒:新订单实时推送,订单列表标记新订单
  • 查看冲突:首个客服点击查看时记录 viewed_by,其他客服同时查看提示"已有XXX客服优先查看,是否继续处理"
  • 处理方式二选一
    • 分配任务:指定陪玩,该陪玩收到通知,订单进入 pending_dispatch
    • 发布任务:生成分享链接,可分享到微信/QQ,订单进入 published,所有陪玩在任务大厅可见
  • 确认完成:陪玩提交完成后,客服核实并确认,订单进入 completed,金额到账陪玩账号

B.4 陪玩接单流程

  • 分配任务:收到通知,查看详情,二次确认后接单,进入 player_accepted
  • 抢单模式:任务大厅查看可抢订单,抢单按钮,二次确认弹窗显示详情,成功进入 player_accepted
    • 多人抢单并发控制:订单可设置所需陪玩数量(required_players),采用"先抢先得"策略
      • 第1人抢单成功:订单变为 partially_accepted(部分接单)
      • 最后1人抢单成功:订单变为 player_accepted(全部接单完成)
      • 第N+1人及以后:提示"订单已被其他用户抢走,请刷新页面"
    • 并发实现:数据库原子操作,先INSERT接单记录,再统计当前人数判断是否在限额内
  • 服务流程:开始服务(in_service)→ 完成任务提交(completion_pending)→ 等待客服确认
  • 放弃任务:在 player_acceptedin_service 状态可主动放弃,订单回到 submitted,其他陪玩可继续抢单

B.5 订单评价规则

  • 开关控制:管理员可在后台开启/关闭评价功能
  • 评价时机:订单 completed 后,Boss可随时评价,无时间限制
  • 评价维度:技术、互动、态度,每项1-5星
  • 文字评价:最多30个字
  • 匿名评价:可勾选匿名,匿名后不显示Boss名称
  • 多陪玩评价:一个订单可由多个陪玩完成,Boss可分别对每个陪玩评价
  • 评价次数限制:每个订单中每个陪玩只能被评价一次
  • 重要规则:只有完成任务的陪玩(从in_service->completion_pending->completed)才能被评价,放弃任务的陪玩不能被评价

B.6 订单状态定义

状态说明触发条件
submitted下单成功Boss提交订单
pending_dispatch客服处理中(已分配)客服指定陪玩
published已发布到任务大厅客服发布任务
partially_accepted部分陪玩已接单(多人抢单场景)抢单成功但人数未满
player_accepted陪玩已接单(人数已满)抢单或分配完成,人数达标
in_service陪玩服务中陪玩点击开始服务
completion_pending陪玩任务完成确认中陪玩提交完成
completed任务结束客服确认完成,金额到账
canceled已取消客服或后台作废

状态流转补充

  • player_acceptedin_service 可放弃任务,回到 submitted
  • in_service 客服可重新分配,状态变为 pending_dispatchpublished
  • 多人抢单:订单可设置所需陪玩数量(required_players),采用"先抢先得"策略,根据INSERT时间判断先后顺序

B.7 排行榜统计口径

  • 统计维度:日/周/月(历史累计可选)
  • 刷新策略:页面刷新时实时查询(不走缓存),TopN 默认 100
  • 数据来源order.status = 'completed'completed_at 在统计周期内

B.8 余额与充值流程

  • 余额显示:Boss 端展示可用余额,账单展示余额变动
  • 余额使用:下单时优先使用余额支付,余额不足禁止下单
  • 充值流程
    1. 客服在后台提交充值申请(选择 Boss、输入金额、备注)
    2. 管理员审核(通过/拒绝)
    3. 通过后:生成 ledger 流水,boss.balance 增加,即时到账
    4. 拒绝后:记录拒绝原因,客服可重新申请
  • ledger 类型recharge(充值)、order_pay(订单扣款)、refund(退款)

B.9 提现流程(T+1申请 + 5个工作日到账)

  • 提现入口:陪玩端提交提现申请
  • 提现方式:手动输入(银行卡/支付宝/微信账号),仅文本记录,不校验
  • 申请提现时间规则
    • 订单完成后需等待 1天(24小时) 才能申请提现该笔收入
    • 系统校验 completed_at + 24h < NOW() 才允许提交提现申请
  • 到账时间提示
    • 提现申请提交成功后,系统提示:"5个工作日内到账,节假日顺延,如有疑问请联系客服"
  • 流程
    1. 陪玩填写提现金额、收款账号(系统自动校验金额是否可提现)
    2. 管理员审核(通过/拒绝)
    3. 通过后:生成 ledger 流水扣减余额,标记为 approved
    4. 管理员线下手动转账(需在5个工作日内完成)
    5. 转账完成后,管理员在后台点击"已打款",进入 paid
  • 记录withdraw_request 完整记录申请-审核-打款全链路

B.10 后台模块字段与操作

  • 每个模块列表字段、筛选项、详情字段
  • 是否需要导出、批量操作、重置密码、禁用/启用
0

评论区