9.3 KiB
9.3 KiB
QuyUn Tenant Admin(frontend/admin)页面与功能规划
基于 backend/docs/swagger.json 中 /t/{tenantCode}/v1/admin/* 管理端接口(租户维度),规划 frontend/admin/ 的信息架构、页面路由与核心交互。
当前
frontend/admin/src/tenant.ts的路由基座为/t/:tenantCode/admin/,API 基座为/t/:tenantCode/v1;本文中 API 路径均以该 baseURL 为前缀(即请求/admin/...)。
0. 全局约定(前端通用能力)
- 租户上下文:从 URL 解析
tenantCode(已存在getTenantCodeFromPath),所有接口都带上路径参数{tenantCode}。 - 分页/排序:多数列表接口使用
page/limit,部分支持asc/desc;统一封装Pager查询参数与列表组件。 - 过滤条件同步 URL:列表页筛选项写入 query(便于分享/刷新不丢失)。
- 危险操作二次确认 + 审计信息:退款、禁用邀请码、审批加入申请、移除成员、删除媒体资源等,弹窗确认并强制填写
reason(后端字段标注为可选,但管理端建议必填以便追溯)。 - 枚举展示:基于 swagger 的
consts.*枚举做 label 映射(见文末“枚举”)。
1. 路由与菜单(建议)
路由均相对 getAdminRouterBase()(/t/:tenantCode/admin/):
/dashboard:概览/members:成员管理/invites:邀请码管理/join-requests:加入申请/orders:订单管理/orders/:orderID:订单详情/ledgers:余额流水(审计)/media:媒体资源库/media/upload:上传媒体资源/media/:assetID:媒体资源详情/contents:内容管理(接口缺口见“待补接口/风险”)/contents/new:创建内容(草稿)/contents/:contentID:内容编辑(基础信息/价格/绑定资源)
2. 页面规格(页面 → 功能 → API)
2.1 概览 /dashboard
目标:提供“运营入口 + 关键待办”。
- 待办卡片:
加入申请待处理数量、最近退款/退款中订单、最近上传失败媒体资源 - 快捷入口:跳转到成员/订单/媒体/内容
- 数据来源(可先不做聚合,使用列表接口取前 N 条):
- 加入申请列表:
GET /admin/join-requests?status=pending&limit=10&page=1 - 订单列表:
GET /admin/orders?status=refunding,refunded,paid&limit=10&page=1(按paid_at/created_at排序) - 媒体资源列表:
GET /admin/media_assets?status=failed,processing&limit=10&page=1
- 加入申请列表:
2.2 成员管理 /members
核心对象:租户成员关系 + 用户基础信息(dto.AdminTenantUserItem 组合 models.TenantUser + models.User)。
- 成员列表(带筛选/分页)
- 过滤:
username、user_id、role、status - API:
GET /admin/users
- 过滤:
- 添加成员(通过
userID加入)- 交互:输入
userID(或未来可通过用户名搜索,当前 swagger 未提供) - API:
POST /admin/users/{userID}/join
- 交互:输入
- 设置角色
- 交互:角色下拉(
member/tenant_admin) - API:
PATCH /admin/users/{userID}/role(dto.AdminTenantUserRoleUpdateForm)
- 交互:角色下拉(
- 移除成员
- API:
DELETE /admin/users/{userID}
- API:
2.3 邀请码管理 /invites
- 邀请码列表(筛选/分页)
- 过滤:
code、status - API:
GET /admin/invites
- 过滤:
- 创建邀请码
- 表单字段:
code?、expires_at?、max_uses?、remark?(dto.AdminTenantInviteCreateForm) - API:
POST /admin/invites
- 表单字段:
- 禁用邀请码
- 表单字段:
reason?(建议必填;dto.AdminTenantInviteDisableForm) - API:
PATCH /admin/invites/{inviteID}/disable
- 表单字段:
2.4 加入申请 /join-requests
- 加入申请列表(筛选/分页)
- 过滤:
status、user_id - API:
GET /admin/join-requests
- 过滤:
- 审核通过 / 拒绝
- 表单字段:
reason?(建议必填;dto.AdminTenantJoinRequestDecideForm) - API:
POST /admin/join-requests/{requestID}/approvePOST /admin/join-requests/{requestID}/reject
- 表单字段:
2.5 订单管理 /orders
- 订单列表(筛选/分页/导出)
- 过滤:
- 金额:
amount_paid_min/amount_paid_max(单位分) - 订单:
status、type - 用户:
user_id、username - 内容:
content_id、content_title - 时间:
created_at_from/to、paid_at_from/to
- 金额:
- 排序:
asc/desc - API:
- 列表:
GET /admin/orders - 导出:
GET /admin/orders/export(应与当前筛选条件一致)
- 列表:
- 过滤:
- 订单详情入口:点击行跳
/orders/:orderID
2.6 订单详情 /orders/:orderID
- 详情展示
- API:
GET /admin/orders/{orderID}(返回dto.AdminOrderDetail,内含models.Order,其中items为订单项)
- API:
- 退款操作
- 表单字段:
reason(建议必填)、idempotency_key(前端生成 UUID)、force(受控开关,默认 false) - API:
POST /admin/orders/{orderID}/refund(dto.AdminOrderRefundForm) - 交互:退款前展示校验信息(当前接口描述存在“paid_at + 24h”窗口逻辑),并将强制退款标注为高危操作
- 表单字段:
2.7 余额流水(审计)/ledgers
- 流水列表(筛选/分页)
- 过滤:
user_id、order_id、operator_user_id、biz_ref_type、biz_ref_id、type、created_at_from/to - API:
GET /admin/ledgers
- 过滤:
- 展示重点:
dto.AdminLedgerItem.type_description直接用于 UI 展示- 金额字段以“分”为单位的,统一格式化为元(保留两位)
2.8 媒体资源库 /media
- 资源列表(筛选/分页/排序)
- 过滤:
type、status、created_at_from/to - 排序:
asc/desc - API:
GET /admin/media_assets
- 过滤:
- 删除资源(软删)
- API:
DELETE /admin/media_assets/{assetID}
- API:
- 进入详情:跳
/media/:assetID
2.9 上传媒体资源 /media/upload
建议采用“上传任务”模型(可多文件队列):
- 初始化上传(创建资源记录 + 获取上传参数)
- API:
POST /admin/media_assets/upload_init(dto.AdminMediaAssetUploadInitForm→dto.AdminMediaAssetUploadInitResponse) - 表单字段:
type(必填)、variant、source_asset_id?、sha256?、file_size?、content_type?
- 直传到对象存储
- 使用返回的
upload_url+form_fields/headers完成上传
- 确认上传完成,触发后端处理
- API:
POST /admin/media_assets/{assetID}/upload_complete(dto.AdminMediaAssetUploadCompleteForm)
2.10 媒体资源详情 /media/:assetID
- API:
GET /admin/media_assets/{assetID} - 展示:
type/variant/status/provider/bucket/object_key/meta/created_at等;对failed状态展示失败原因(若后端写在meta)
2.11 内容管理 /contents(待补接口)
swagger 中目前仅提供:
- 创建草稿:
POST /admin/contents(dto.ContentCreateForm) - 更新内容:
PATCH /admin/contents/{contentID}(dto.ContentUpdateForm) - 设置价格:
PUT /admin/contents/{contentID}/price(dto.ContentPriceUpsertForm) - 绑定媒体资源:
POST /admin/contents/{contentID}/assets(dto.ContentAssetAttachForm)
建议页面拆分:
- 内容列表
/contents:需要后端补GET /admin/contents(支持状态/可见性/标题搜索/分页),否则前端无法管理草稿/下架内容。 - 内容创建
/contents/new:填写title/description/preview_seconds/visibility - 内容编辑
/contents/:contentID:- 基础信息:
PATCH /admin/contents/{contentID} - 价格与折扣:
PUT /admin/contents/{contentID}/price - 资源绑定:从媒体资源库选择
asset_id,按role(main/cover/preview)绑定到内容
- 基础信息:
3. 枚举(UI 需要的固定值)
(直接来自 swagger definitions/consts.*)
- 成员角色
consts.TenantUserRole:member、tenant_admin - 邀请码状态
consts.TenantInviteStatus:active、disabled、expired - 加入申请状态
consts.TenantJoinRequestStatus:pending、approved、rejected - 媒体类型
consts.MediaAssetType:video、audio、image - 媒体状态
consts.MediaAssetStatus:uploaded、processing、ready、failed、deleted - 订单状态
consts.OrderStatus:created、paid、refunding、refunded、canceled、failed - 订单类型
consts.OrderType:content_purchase - 流水类型
consts.TenantLedgerType:debit_purchase、credit_refund、freeze、unfreeze、adjustment - 内容可见性
consts.ContentVisibility:public、tenant_only、private - 内容状态
consts.ContentStatus:draft、reviewing、published、unpublished、blocked - 内容资源角色
consts.ContentAssetRole:main、cover、preview - 折扣类型
consts.DiscountType:none、percent、amount - 币种
consts.Currency:CNY
4. 待补接口 / 风险点(从 swagger 反推)
- 内容列表缺失:没有
GET /admin/contents;无法做内容管理主列表、草稿管理、下架列表等。 - 分页返回结构疑似不完整:多个列表接口在 swagger 中将
items描述为单个 object($ref models.*),但实际应为数组;前端需以实际返回为准,或推动后端修正 swagger(items: { type: array, items: ... })。 - 鉴权机制未在 swagger 体现:
securityDefinitions仅有BasicAuth,且各接口未标注security;前端需确认实际鉴权方式(JWT/Cookie/BasicAuth),并统一处理 401/403。