- 范围:全仓除已完成的 game-cloud/game-admin(及排除区);91 文件 - cn.iocoder.yudao→com.wanxiang.huijing / cn.wanxiang.game→com.wanxiang.huijing.game / cn.iocoder.cloud→com.wanxiang / Yudao*→Huijing* / bare yudao→huijing - 含 contracts/api-schemas(apiInterface FQCN)、docs/architecture+agent-specs(含中文名,git ls-files -z 修复)、AGENTS.md/CLAUDE.md 等根文档 - 保留不动:上游归属 URL(gitee/github yudaocode·YunaiV,改则断链+违反署名)、game-cloud Flyway 迁移注释(保 checksum)、lockfile(装包重生) - 纯文档/字符串,零构建影响(game-cloud/game-admin 字节码未动) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
442 lines
23 KiB
YAML
442 lines
23 KiB
YAML
openapi: 3.0.3
|
||
# 契约 #8 API | 模块:biz(B/G 端轻量定制 lead form 信息流:询单→报价→进度→demo 验收)| owner:WS5,全员 review
|
||
# 设计依据:docs/agent-specs/2026-06-11-Wave4-community-biz-execution.md §4.2/§4.5(D-A 轻量 lead form 先行,覆盖 6 P0)。
|
||
# 端:/app-api(客户侧 game-studio:提单 / 我的订单 / 进度看板 / 选模板 / 试玩反馈确认,用户 Token + Mapper 强制 getLoginUserId() 归属谓词,WS3)
|
||
# /admin-api(运营侧 game-admin:处理队列 / 代客发起 / 指派 / 报价 / 推进状态机 / 线下签署兜底,RBAC @PreAuthorize,WS4)
|
||
# 前缀由 huijing 框架按 controller.app/admin 包名自动添加(@RequestMapping 只写 /biz);本文件 path 直接写含前缀的完整对外路径。
|
||
# 错误码段(落 game 业务段 1-110-***-***,模块归属决定,contracts/README.md §四 已在册):
|
||
# 1-110-001-*** = 询单(询单不存在/非本人订单/状态机非法流转…)
|
||
# 1-110-002-*** = 报价(报价不存在/询单状态不允许报价…)
|
||
# 1-110-003-*** = 进度(非法状态推进/demo 未就绪不允许进入待验收…)
|
||
# 1-110-004-*** = 验收(验收记录不存在/未到待验收态/重复确认…)
|
||
# 响应统一 Huijing CommonResult 信封:{ code, data, msg };code=0 成功。
|
||
# 状态机:game_biz_lead.status 单线性五态 0待跟进→1已报价→2制作中→3待验收→4已交付;
|
||
# 非法流转由 BizLeadService 写前校验拒绝(复用 project ProjectServiceImpl 流转校验内联范式,无独立 StateService,不引 Flowable)。
|
||
# 归属隔离(R-medium PII 红线):客户侧 /app-api/biz/* 必须在 Mapper 查询里强制以登录态 user_id(customer_user_id)作谓词 enforce
|
||
# (可信边界,非 @DataPermission),前端不够;客户只见自己询单/进度/报价。
|
||
# 资金流边界(D-A):本波只到状态机走通 + 线下签署后台标记兜底(signed_offline);收款(T-BIZ-08)/在线电子签章(T-BIZ-03)/分账留 M4。
|
||
# demo 试玩取包复用 runtime 真实双路由(见文末 paths 注释),不在 biz 自建取包端点。
|
||
# 权限点登记(§7.4 必做):biz:lead:query/create/assign/advance、biz:quote:create/query、biz:acceptance:sign
|
||
# 需在 huijing system_menu 登记后 RBAC 才放行(范本=project:review:query 登记方式)。
|
||
# 边界 OUT:不接 ip seam(D-C 维持 D5 推迟,直接复用 aigc 4 模板 + runtime 沙箱);P-BIZ-11 学生防沉迷已划归 compliance(不计入 biz)。
|
||
info:
|
||
title: 绘境AI biz 模块 API
|
||
version: 1.0.0
|
||
description: >-
|
||
B/G 端轻量定制 lead form 信息流闭环:客户在线提单(询单落库即开状态机)→ 运营报价(参数化估价,报价≠可支付订单)→
|
||
进度看板(状态机各节点流转时间线)→ demo 试玩验收(复用 aigc 4 模板生成 + runtime 沙箱取包,客户反馈→确认)。
|
||
资金流(收款/分账/在线签章)留 M4,本波仅线下签署后台标记兜底。
|
||
覆盖产品功能 P-BIZ-01(在线提单)/02(选模板)/03(进度看板)/04(试玩验收)/08(报价编排)/12(运营代客发起)。
|
||
前端据此 vite-plugin-mock 自动生成 mock。
|
||
|
||
servers:
|
||
- url: http://localhost:48080
|
||
description: 本地(Swagger/Knife4j http://localhost:48080/doc.html)
|
||
|
||
paths:
|
||
# ===========================================================================
|
||
# 客户侧(产品端 game-studio,WS3):提单 / 我的订单 / 详情 / 进度看板 / 选模板 / 试玩反馈确认
|
||
# 全部用户 Token,Mapper 强制 customer_user_id = getLoginUserId() 归属谓词,客户只见自己订单。
|
||
# ===========================================================================
|
||
/app-api/biz/leads:
|
||
post:
|
||
tags: [app-biz]
|
||
summary: 提交定制需求询单(P-BIZ-01)
|
||
description: >-
|
||
客户在线提交定制需求,落库即开状态机=待跟进0 + 落 game_biz_progress 首条 to_status=0。
|
||
customer_user_id = getLoginUserId()。
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/BizLeadCreateReqVO' }
|
||
responses:
|
||
'200':
|
||
description: 新建询单 ID(CommonResult<Long>)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
code: { type: integer, example: 0 }
|
||
data: { type: integer, format: int64, description: '新建询单 ID' }
|
||
msg: { type: string, example: '' }
|
||
|
||
/app-api/biz/leads/my:
|
||
get:
|
||
tags: [app-biz]
|
||
summary: 我的定制订单列表(P-BIZ-03)
|
||
description: >-
|
||
我的定制订单列表,customer_user_id 过滤(客户只见自己)。
|
||
归属隔离:Mapper 强制 customer_user_id = getLoginUserId() 谓词(可信边界)。
|
||
parameters:
|
||
- { name: status, in: query, required: false, schema: { type: integer, enum: [0, 1, 2, 3, 4] }, description: '状态筛选(可选)' }
|
||
- { name: cursor, in: query, required: false, schema: { type: integer, format: int64 }, description: '游标分页(可选)' }
|
||
- { name: size, in: query, required: false, schema: { type: integer, default: 20 }, description: '每页条数' }
|
||
responses:
|
||
'200':
|
||
description: 我的订单分页(CommonResult)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
code: { type: integer, example: 0 }
|
||
data:
|
||
type: object
|
||
properties:
|
||
list: { type: array, items: { $ref: '#/components/schemas/BizLeadRespVO' } }
|
||
nextCursor: { type: integer, format: int64, nullable: true }
|
||
msg: { type: string, example: '' }
|
||
|
||
/app-api/biz/leads/{id}:
|
||
get:
|
||
tags: [app-biz]
|
||
summary: 询单详情
|
||
description: >-
|
||
询单详情:含当前状态 / 最新报价 / 进度时间线 / demo 可预览判定。
|
||
归属隔离:service 校验 customer_user_id == getLoginUserId(),非本人订单拒绝(1-110-001-***)。
|
||
parameters:
|
||
- { name: id, in: path, required: true, schema: { type: integer, format: int64 }, description: '询单 ID' }
|
||
responses:
|
||
'200':
|
||
description: 询单详情(CommonResult)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
code: { type: integer, example: 0 }
|
||
data: { $ref: '#/components/schemas/BizLeadDetailRespVO' }
|
||
msg: { type: string, example: '' }
|
||
|
||
/app-api/biz/leads/{id}/progress:
|
||
get:
|
||
tags: [app-biz]
|
||
summary: 进度看板时间线(P-BIZ-03)
|
||
description: 进度看板时间线(game_biz_progress 按 create_time)。归属隔离同上。
|
||
parameters:
|
||
- { name: id, in: path, required: true, schema: { type: integer, format: int64 }, description: '询单 ID' }
|
||
responses:
|
||
'200':
|
||
description: 进度时间线(CommonResult)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
code: { type: integer, example: 0 }
|
||
data: { type: array, items: { $ref: '#/components/schemas/BizProgressRespVO' } }
|
||
msg: { type: string, example: '' }
|
||
|
||
/app-api/biz/templates:
|
||
get:
|
||
tags: [app-biz]
|
||
summary: 按场景检索可选模板(P-BIZ-02)
|
||
description: 按场景检索可选玩法模板(复用 aigc 4 模板 clicker/merge/idle/tycoon)。
|
||
parameters:
|
||
- { name: bizType, in: query, required: false, schema: { type: integer, enum: [1, 2, 3] }, description: '定制场景:1品牌营销 2文旅 3通用定制(可选)' }
|
||
responses:
|
||
'200':
|
||
description: 可选模板列表(CommonResult)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
code: { type: integer, example: 0 }
|
||
data: { type: array, items: { $ref: '#/components/schemas/BizTemplateRespVO' } }
|
||
msg: { type: string, example: '' }
|
||
|
||
/app-api/biz/acceptances/{leadId}/feedback:
|
||
post:
|
||
tags: [app-biz]
|
||
summary: 客户试玩后提交反馈(P-BIZ-04)
|
||
description: 客户试玩 demo 后提交反馈(落 game_biz_acceptance.feedback)。归属隔离:询单须属当前客户。
|
||
parameters:
|
||
- { name: leadId, in: path, required: true, schema: { type: integer, format: int64 }, description: '询单 ID' }
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/BizFeedbackReqVO' }
|
||
responses:
|
||
'200':
|
||
description: CommonResult<Boolean>
|
||
content: { application/json: { schema: { $ref: '#/components/schemas/CommonResultBoolean' } } }
|
||
|
||
/app-api/biz/acceptances/{leadId}/confirm:
|
||
post:
|
||
tags: [app-biz]
|
||
summary: 客户确认验收(P-BIZ-04)
|
||
description: >-
|
||
客户确认验收,落 confirm_status=1 + confirmed_time,状态机 3待验收→4已交付。
|
||
归属隔离:询单须属当前客户;service 校验当前为待验收态(1-110-004-***)。
|
||
parameters:
|
||
- { name: leadId, in: path, required: true, schema: { type: integer, format: int64 }, description: '询单 ID' }
|
||
requestBody:
|
||
required: false
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
demoVersionId: { type: integer, format: int64, description: '确认的 demo 版本 ID' }
|
||
responses:
|
||
'200':
|
||
description: CommonResult<Boolean>
|
||
content: { application/json: { schema: { $ref: '#/components/schemas/CommonResultBoolean' } } }
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# demo 试玩取包:复用 runtime 真实双路由,不在 biz 自建端点(评审版 R2-3,两条须写全)
|
||
# GET /app-api/runtime/package/{versionId} —— 清单 meta(CommonResult<RuntimePackageRespVO>),
|
||
# biz 看板「是否可预览」判定走此条;
|
||
# GET /app-api/runtime/package/{versionId}/manifest —— 原始 JSON,宿主 sha256 比对后注入。
|
||
# (仅文档声明复用,端点定义见 contracts/api-schemas/runtime.yaml,biz 不重复定义。)
|
||
# ---------------------------------------------------------------------------
|
||
|
||
# ===========================================================================
|
||
# 运营侧(管理端 game-admin,WS4):处理队列 / 代客发起 / 指派 / 报价 / 推进状态机 / 线下签署兜底
|
||
# 全部 RBAC @PreAuthorize,权限点需在 system_menu 登记(§7.4)。
|
||
# ===========================================================================
|
||
/admin-api/biz/leads/page:
|
||
get:
|
||
tags: [admin-biz]
|
||
summary: 处理队列(按 owner/status/bizType 筛选)
|
||
description: '运营处理队列分页。权限点:biz:lead:query。'
|
||
parameters:
|
||
- { name: ownerUserId, in: query, required: false, schema: { type: integer, format: int64 }, description: '按负责人筛选(可选)' }
|
||
- { name: status, in: query, required: false, schema: { type: integer, enum: [0, 1, 2, 3, 4] }, description: '按状态筛选(可选)' }
|
||
- { name: bizType, in: query, required: false, schema: { type: integer, enum: [1, 2, 3] }, description: '按场景筛选(可选)' }
|
||
- { name: pageNo, in: query, required: false, schema: { type: integer, default: 1 }, description: '页码' }
|
||
- { name: pageSize, in: query, required: false, schema: { type: integer, default: 10 }, description: '每页条数' }
|
||
responses:
|
||
'200':
|
||
description: 处理队列分页(CommonResult<PageResult>)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
code: { type: integer, example: 0 }
|
||
data:
|
||
type: object
|
||
properties:
|
||
list: { type: array, items: { $ref: '#/components/schemas/BizLeadRespVO' } }
|
||
total: { type: integer, format: int64 }
|
||
msg: { type: string, example: '' }
|
||
|
||
/admin-api/biz/leads:
|
||
post:
|
||
tags: [admin-biz]
|
||
summary: 运营代客发起定制单(P-BIZ-08/12)
|
||
description: '运营代客发起定制单(customer_user_id 可空)。权限点:biz:lead:create。'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/BizLeadCreateReqVO' }
|
||
responses:
|
||
'200':
|
||
description: 新建询单 ID(CommonResult<Long>)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
code: { type: integer, example: 0 }
|
||
data: { type: integer, format: int64 }
|
||
msg: { type: string, example: '' }
|
||
|
||
/admin-api/biz/leads/{id}/assign:
|
||
put:
|
||
tags: [admin-biz]
|
||
summary: 认领/指派负责人
|
||
description: '认领/指派负责人(owner_user_id)。权限点:biz:lead:assign。'
|
||
parameters:
|
||
- { name: id, in: path, required: true, schema: { type: integer, format: int64 }, description: '询单 ID' }
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
ownerUserId: { type: integer, format: int64, description: '负责人用户 ID' }
|
||
responses:
|
||
'200':
|
||
description: CommonResult<Boolean>
|
||
content: { application/json: { schema: { $ref: '#/components/schemas/CommonResultBoolean' } } }
|
||
|
||
/admin-api/biz/leads/{id}/quotes:
|
||
post:
|
||
tags: [admin-biz]
|
||
summary: 报价输出(P-BIZ-08)
|
||
description: >-
|
||
报价输出(参数化估价,报价≠可支付订单);状态机 0待跟进→1已报价。quote_no 由 service 串行 max+1 生成。
|
||
权限点:biz:quote:create。
|
||
parameters:
|
||
- { name: id, in: path, required: true, schema: { type: integer, format: int64 }, description: '询单 ID' }
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/BizQuoteCreateReqVO' }
|
||
responses:
|
||
'200':
|
||
description: 报价 ID(CommonResult<Long>)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
code: { type: integer, example: 0 }
|
||
data: { type: integer, format: int64 }
|
||
msg: { type: string, example: '' }
|
||
get:
|
||
tags: [admin-biz]
|
||
summary: 报价历史
|
||
description: '报价历史(按询单查)。权限点:biz:quote:query。'
|
||
parameters:
|
||
- { name: id, in: path, required: true, schema: { type: integer, format: int64 }, description: '询单 ID' }
|
||
responses:
|
||
'200':
|
||
description: 报价历史列表(CommonResult)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
code: { type: integer, example: 0 }
|
||
data: { type: array, items: { $ref: '#/components/schemas/BizQuoteRespVO' } }
|
||
msg: { type: string, example: '' }
|
||
|
||
/admin-api/biz/leads/{id}/advance:
|
||
post:
|
||
tags: [admin-biz]
|
||
summary: 推进状态机(P-BIZ-03)
|
||
description: >-
|
||
推进状态机(→2制作中 / →3待验收,→3 守 demo 可预览即 demoVersionId 必填且 runtime 包就绪);
|
||
落 game_biz_progress 流转记录。权限点:biz:lead:advance。
|
||
parameters:
|
||
- { name: id, in: path, required: true, schema: { type: integer, format: int64 }, description: '询单 ID' }
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: { $ref: '#/components/schemas/BizAdvanceReqVO' }
|
||
responses:
|
||
'200':
|
||
description: CommonResult<Boolean>
|
||
content: { application/json: { schema: { $ref: '#/components/schemas/CommonResultBoolean' } } }
|
||
|
||
/admin-api/biz/acceptances/{id}/sign-offline:
|
||
put:
|
||
tags: [admin-biz]
|
||
summary: 线下签署后台标记兜底(P-BIZ-04)
|
||
description: >-
|
||
线下签署后台标记兜底(signed_offline=1),M4 接在线签章前的过渡手段。权限点:biz:acceptance:sign。
|
||
parameters:
|
||
- { name: id, in: path, required: true, schema: { type: integer, format: int64 }, description: '验收记录 ID' }
|
||
responses:
|
||
'200':
|
||
description: CommonResult<Boolean>
|
||
content: { application/json: { schema: { $ref: '#/components/schemas/CommonResultBoolean' } } }
|
||
|
||
components:
|
||
schemas:
|
||
CommonResultBoolean:
|
||
type: object
|
||
description: Huijing 统一响应信封(Boolean 数据)
|
||
properties:
|
||
code: { type: integer, example: 0 }
|
||
data: { type: boolean, example: true }
|
||
msg: { type: string, example: '' }
|
||
BizLeadCreateReqVO:
|
||
type: object
|
||
description: 定制询单创建请求(客户自助 / 运营代客共用)
|
||
required: [bizType, title]
|
||
properties:
|
||
bizType: { type: integer, enum: [1, 2, 3], description: '定制场景:1品牌营销 2文旅 3通用定制' }
|
||
title: { type: string, maxLength: 120, description: '需求标题' }
|
||
sceneDesc: { type: string, maxLength: 2000, description: '场景需求描述' }
|
||
contactName: { type: string, maxLength: 64, description: '联系人' }
|
||
contactPhone: { type: string, maxLength: 32, description: '联系电话' }
|
||
company: { type: string, maxLength: 128, description: '企业/机构名称' }
|
||
templateId: { type: string, maxLength: 64, description: '选定的玩法模板 ID(可选)' }
|
||
customerUserId: { type: integer, format: int64, nullable: true, description: '客户用户 ID(运营代客发起可填,自助提单取登录态)' }
|
||
BizLeadRespVO:
|
||
type: object
|
||
description: 询单列表项
|
||
properties:
|
||
id: { type: integer, format: int64, description: '询单 ID' }
|
||
bizType: { type: integer, description: '定制场景:1品牌营销 2文旅 3通用定制' }
|
||
title: { type: string, description: '需求标题' }
|
||
status: { type: integer, description: '状态机:0待跟进 1已报价 2制作中 3待验收 4已交付' }
|
||
ownerUserId: { type: integer, format: int64, nullable: true, description: '跟进负责人用户 ID' }
|
||
demoVersionId: { type: integer, format: int64, nullable: true, description: 'demo 预览版本 ID' }
|
||
createTime: { type: string, format: date-time, description: '创建时间' }
|
||
updateTime: { type: string, format: date-time, description: '更新时间' }
|
||
BizLeadDetailRespVO:
|
||
type: object
|
||
description: 询单详情(含最新报价 / 进度时间线 / demo 可预览判定)
|
||
properties:
|
||
lead: { $ref: '#/components/schemas/BizLeadRespVO' }
|
||
latestQuote: { $ref: '#/components/schemas/BizQuoteRespVO' }
|
||
progressList: { type: array, items: { $ref: '#/components/schemas/BizProgressRespVO' } }
|
||
demoPreviewable: { type: boolean, description: 'demo 是否可预览(demoVersionId 非空且 runtime 包就绪)' }
|
||
BizQuoteCreateReqVO:
|
||
type: object
|
||
description: 报价创建请求(参数化估价表单)
|
||
required: [amountFen]
|
||
properties:
|
||
amountFen: { type: integer, format: int64, description: '报价金额(分,与 trade 同口径;本波仅展示不收款)' }
|
||
serviceItems: { type: string, maxLength: 1000, description: '服务项明细(编排内容)' }
|
||
validDays: { type: integer, default: 30, description: '报价有效天数' }
|
||
remark: { type: string, maxLength: 500, description: '备注' }
|
||
BizQuoteRespVO:
|
||
type: object
|
||
description: 报价记录
|
||
properties:
|
||
id: { type: integer, format: int64, description: '报价 ID' }
|
||
leadId: { type: integer, format: int64, description: '所属询单 ID' }
|
||
quoteNo: { type: integer, description: '报价版本号' }
|
||
amountFen: { type: integer, format: int64, description: '报价金额(分)' }
|
||
serviceItems: { type: string, description: '服务项明细' }
|
||
validDays: { type: integer, description: '报价有效天数' }
|
||
remark: { type: string, description: '备注' }
|
||
createTime: { type: string, format: date-time, description: '创建时间' }
|
||
BizProgressRespVO:
|
||
type: object
|
||
description: 进度工单(看板时间线项)
|
||
properties:
|
||
id: { type: integer, format: int64, description: '进度工单 ID' }
|
||
fromStatus: { type: integer, nullable: true, description: '流转前状态(首条 null)' }
|
||
toStatus: { type: integer, description: '流转后状态(0-4)' }
|
||
operatorUserId: { type: integer, format: int64, nullable: true, description: '操作人用户 ID' }
|
||
note: { type: string, description: '进度说明' }
|
||
createTime: { type: string, format: date-time, description: '流转时间' }
|
||
BizTemplateRespVO:
|
||
type: object
|
||
description: 可选玩法模板(复用 aigc 4 模板)
|
||
properties:
|
||
templateId: { type: string, description: '模板 ID(clicker/merge/idle/tycoon)' }
|
||
name: { type: string, description: '模板名称' }
|
||
bizType: { type: integer, description: '适配场景:1品牌营销 2文旅 3通用定制' }
|
||
description: { type: string, description: '模板说明' }
|
||
BizFeedbackReqVO:
|
||
type: object
|
||
description: 客户试玩反馈请求
|
||
required: [demoVersionId]
|
||
properties:
|
||
demoVersionId: { type: integer, format: int64, description: 'demo 版本 ID(runtime game_version.id)' }
|
||
feedback: { type: string, maxLength: 1000, description: '客户试玩反馈' }
|
||
BizAdvanceReqVO:
|
||
type: object
|
||
description: 状态机推进请求(运营)
|
||
required: [toStatus]
|
||
properties:
|
||
toStatus: { type: integer, enum: [2, 3], description: '推进目标状态:2制作中 3待验收' }
|
||
note: { type: string, maxLength: 500, description: '进度说明' }
|
||
demoVersionId: { type: integer, format: int64, nullable: true, description: 'demo 版本 ID(→3待验收时必填,runtime 包须就绪)' }
|