feat(web): 08 后台四个页面落地(内容治理 / 订单与权益 / 创作者审核 / 数据看板)

为什么:08 运营后台的接口在前几轮已经实现,但运营在界面上点不到——
评论审核、举报工单、敏感词维护、订单补发/退款、权益回收、金币补发、对账、
创作者入驻与内容提交审核、运营大盘,都只能靠 curl。本轮把这四个页面补齐,
08 才算真正闭环。

- 内容治理:评论审核(通过/驳回/删除)、举报工单处理(可联动封禁)、敏感词库增删改查
- 订单与权益:订单检索与流水、补发、退款、权益检索/人工补发/回收、金币流水与人工补币、对账运行与历史
- 创作者审核:入驻审核(通过/驳回原因码/冻结)+ 资质抽屉;内容提交审核(通过/驳回)
- 数据看板:overview 五组指标 + transcode 队列与失败任务,只读;取不到的指标显示「暂无数据源」而不是 0
- 新增 console.css(工具条/抽屉/看板卡片,含深色模式),四个页面共用;时间列统一 yyyy-MM-dd HH:mm:ss
- 按钮按权限点显隐(没有 *:update / *:audit 的角色看到的是只读态),表格列与后端字段一一对应
This commit is contained in:
Vicky committed 2026-10-15 13:28:46 +08:00
1 parent 44c2c46a68
commit f037d243cd
13 files changed
+2680

No files matched your search

+122
View File
@@ -0,0 +1,122 @@
import request from '@/axios'
import type { PageResult } from './types'
export interface OrderItem {
id: number
orderNo: string
userId: number
productCode: string
productName: string
type: string
platform: string
amount: number
currency: string
coinAmount: number
/** CREATED / PAID / DELIVERED / REFUNDED / CLOSED */
status: string
paidAt?: string
deliveredAt?: string
refundReason: string
failReason: string
createdAt?: string
}
export interface OrderEventItem {
id: number
orderNo: string
event: string
fromStatus: string
toStatus: string
source: string
payload: string
operatorId: number
createdAt?: string
}
export interface EntitlementItem {
id: number
userId: number
dramaId: number
episodeId: number
/** EPISODE / DRAMA */
type: string
/** ORDER / ADMIN / ACTIVITY */
source: string
/** ACTIVE / REVOKED / EXPIRED */
status: string
orderNo: string
startAt?: string
revokeReason: string
}
export interface LedgerItem {
id: number
userId: number
changeAmount: number
balanceAfter: number
bizType: string
bizId: string
remark: string
operatorId: number
createdAt?: string
}
export interface ReconcileItem {
id: number
bizDate: string
platform: string
totalCount: number
matchedCount: number
diffCount: number
amountSum: number
status: string
detail: string
finishedAt?: string
}
export const pageOrdersApi = (params: Record<string, unknown>) => {
return request.get<PageResult<OrderItem>>({ url: '/admin/orders/page', params })
}
export const listOrderEventsApi = (orderNo: string) => {
return request.get<OrderEventItem[]>({ url: `/admin/orders/${orderNo}/events` })
}
export const compensateOrderApi = (orderNo: string) => {
return request.post<OrderItem>({ url: `/admin/orders/${orderNo}/compensate` })
}
export const refundOrderApi = (orderNo: string, reason: string) => {
return request.post<OrderItem>({ url: `/admin/orders/${orderNo}/refund`, data: { reason } })
}
export const pageEntitlementsApi = (params: Record<string, unknown>) => {
return request.get<PageResult<EntitlementItem>>({ url: '/admin/entitlements/page', params })
}
export const grantEntitlementApi = (data: Record<string, unknown>) => {
return request.post<EntitlementItem>({ url: '/admin/entitlements', data })
}
export const revokeEntitlementApi = (id: number, reason: string) => {
return request.put<void>({ url: `/admin/entitlements/${id}/revoke`, params: { reason } })
}
export const listWalletLedgerApi = (userId: number, limit = 20) => {
return request.get<LedgerItem[]>({
url: `/admin/wallets/${userId}/ledger`,
params: { limit }
})
}
export const adjustCoinsApi = (data: Record<string, unknown>) => {
return request.post<LedgerItem>({ url: '/admin/wallets/coins', data })
}
export const pageReconcileApi = (params: Record<string, unknown>) => {
return request.get<PageResult<ReconcileItem>>({ url: '/admin/reconcile/page', params })
}
export const runReconcileApi = (params: Record<string, unknown>) => {
return request.post<ReconcileItem>({ url: '/admin/reconcile/run', params })
}
+72
View File
@@ -0,0 +1,72 @@
import request from '@/axios'
import type { PageResult } from './types'
export interface CreatorItem {
id: number
userId: number
code: string
name: string
/** INDIVIDUAL / COMPANY */
type: string
contactName: string
contactMobile: string
contactEmail: string
countryCode: string
/** pending / approved / rejected / frozen */
status: string
auditNote: string
auditBy: number
auditAt?: string
settlementCurrency: string
createdAt?: string
}
export interface CreatorDocumentItem {
id: number
creatorId: number
/** ID_CARD / BUSINESS_LICENSE / CONTRACT */
type: string
fileUrl: string
status: string
auditNote: string
createdAt?: string
}
export interface SubmissionItem {
id: number
creatorId: number
dramaId: number
/** CREATE / UPDATE / PUBLISH / OFFLINE */
type: string
/** DRAFT / SUBMITTED / REVIEWING / APPROVED / REJECTED / WITHDRAWN */
status: string
version: number
submitAt?: string
reviewerId: number
reviewAt?: string
reviewNote: string
rejectCode: string
createdAt?: string
}
export const pageCreatorsApi = (params: Record<string, unknown>) => {
return request.get<PageResult<CreatorItem>>({ url: '/admin/creators/page', params })
}
export const listCreatorDocumentsApi = (id: number) => {
return request.get<CreatorDocumentItem[]>({ url: `/admin/creators/${id}/documents` })
}
/** action: APPROVE / REJECT / FREEZE */
export const auditCreatorApi = (id: number, data: Record<string, unknown>) => {
return request.put<CreatorItem>({ url: `/admin/creators/${id}/audit`, data })
}
export const pageSubmissionsApi = (params: Record<string, unknown>) => {
return request.get<PageResult<SubmissionItem>>({ url: '/admin/submissions/page', params })
}
/** action: APPROVE / REJECT / WITHDRAW */
export const auditSubmissionApi = (id: number, data: Record<string, unknown>) => {
return request.put<SubmissionItem>({ url: `/admin/submissions/${id}/audit`, data })
}
+34
View File
@@ -0,0 +1,34 @@
import request from '@/axios'
/** 指标口径见后端 DashboardService 注释与 docs/api-phase1.md「2.8 数据看板」 */
export interface DashboardOverview {
generatedAt: string
user: Record<string, number>
content: Record<string, number>
playback: Record<string, number>
revenue: Record<string, number>
cost: Record<string, number | null>
notes: string[]
}
export interface TranscodeBoard {
generatedAt: string
queue: Record<string, number>
failedTasks: {
id: number
episodeId: number
status: string
retryCount: number
errorMsg: string
createdAt?: string
}[]
notes: string[]
}
export const getDashboardOverviewApi = () => {
return request.get<DashboardOverview>({ url: '/admin/dashboard/overview' })
}
export const getTranscodeBoardApi = () => {
return request.get<TranscodeBoard>({ url: '/admin/dashboard/transcode' })
}
+49
View File
@@ -0,0 +1,49 @@
import request from '@/axios'
import type { PageResult, CommentItem, ReportItem, SensitiveWordItem } from './types'
export const pageCommentsApi = (params: Record<string, unknown>) => {
return request.get<PageResult<CommentItem>>({ url: '/admin/comments/page', params })
}
export const listCommentAuditRecordsApi = (id: number) => {
return request.get<Record<string, unknown>[]>({
url: `/admin/comments/${id}/audit-records`
})
}
/** result: PASS / REJECT */
export const auditCommentApi = (id: number, data: Record<string, unknown>) => {
return request.put<void>({ url: `/admin/comments/${id}/audit`, data })
}
export const deleteCommentApi = (id: number) => {
return request.delete<void>({ url: `/admin/comments/${id}` })
}
export const pageReportsApi = (params: Record<string, unknown>) => {
return request.get<PageResult<ReportItem>>({ url: '/admin/reports/page', params })
}
/** status: handled / rejected;banTarget=true 时联动封禁被举报用户 */
export const handleReportApi = (id: number, data: Record<string, unknown>) => {
return request.put<void>({ url: `/admin/reports/${id}/handle`, data })
}
export const pageSensitiveWordsApi = (params: Record<string, unknown>) => {
return request.get<PageResult<SensitiveWordItem>>({
url: '/admin/sensitive-words/page',
params
})
}
export const createSensitiveWordApi = (data: Record<string, unknown>) => {
return request.post<number>({ url: '/admin/sensitive-words', data })
}
export const updateSensitiveWordApi = (id: number, data: Record<string, unknown>) => {
return request.put<void>({ url: `/admin/sensitive-words/${id}`, data })
}
export const deleteSensitiveWordApi = (id: number) => {
return request.delete<void>({ url: `/admin/sensitive-words/${id}` })
}