oh-my-muse/docs/superpowers/plans/2026-05-24-P3-muse-admin.md

422 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# P3: muse-admin 管理端搭建 — 执行计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task.
**目标:** 在 Vben Admin fork 基础上搭建 muse-admin实现 MetaSchema 管理、系统治理、AI 配置、市场治理、全局知识管理 5 个功能域。
**架构:** Vue 3 + Vben Admin + TypeScriptComposition API + SFC script setupdefHttp API 集成Vben 内置表格/表单组件复用。
**技术栈:** Vue 3.5, TypeScript 5, Vben Admin 5, Pinia, Vitest + Vue Test Utils + Playwright
注: muse-admin 已 fork 完成,存在 `apps/web-antd``packages/` 结构。
---
## Step 1: 工程调整
### Task 1.1: 业务目录结构建立
**仓库路径:** `muse-admin/`
- [ ] **Step 1: 创建业务模块目录**
```bash
mkdir -p muse-admin/apps/web-antd/src/views/{governance,ai,knowledge,market,account,jobs,audit}
mkdir -p muse-admin/apps/web-antd/src/api/muse/{governance,ai,knowledge,market,account,jobs,audit}
```
- [ ] **Step 2: 检查现有结构**
```bash
ls muse-admin/apps/web-antd/src/views/
ls muse-admin/packages/@core/
```
- [ ] **Step 3: 提交**
```bash
git add muse-admin/apps/web-antd/src/views/governance/ muse-admin/apps/web-antd/src/api/muse/
git commit -m "feat(struct): 建立管理端业务模块目录governance/ai/knowledge/market/account"
```
### Task 1.2: API 类型集成
- [ ] **Step 1: 复制 OpenAPI 生成的类型**
```bash
cp docs/api-contracts/generated/typescript/*.ts muse-admin/apps/web-antd/src/api/types/
```
- [ ] **Step 2: 编写 API 客户端**
```typescript
// muse-admin/apps/web-antd/src/api/muse/client.ts
import { requestClient } from '#/api/request';
const BASE = '/admin-api/muse';
export const museAdminApi = {
get: <T>(url: string, params?: Record<string, unknown>) =>
requestClient.get<T>(`${BASE}${url}`, { params }),
post: <T>(url: string, data?: unknown) =>
requestClient.post<T>(`${BASE}${url}`, data),
put: <T>(url: string, data?: unknown) =>
requestClient.put<T>(`${BASE}${url}`, data),
delete: <T>(url: string) =>
requestClient.delete<T>(`${BASE}${url}`),
};
```
- [ ] **Step 3: 提交**
```bash
git add -A && git commit -m "feat(api): 集成管理端 API 客户端 + OpenAPI 类型包"
```
---
## Step 2: 管理页面开发(按优先级)
### Task 2.1: MetaSchema 管理 — 列表页
**文件:**
- 创建: `apps/web-antd/src/views/governance/MetaSchemaList.vue`
- 创建: `apps/web-antd/src/api/muse/governance/meta-schema.ts`
- [ ] **Step 1: 编写 API service**
```typescript
// apps/web-antd/src/api/muse/governance/meta-schema.ts
import { museAdminApi } from '../client';
export interface MetaSchemaSummary {
schemaKey: string;
displayName: string;
fieldType: string;
scope: string;
activeVersion: number;
status: string;
}
export function listMetaSchemas(params: {
pageNo: number;
pageSize: number;
scope?: string;
}) {
return museAdminApi.get<{
total: number;
list: MetaSchemaSummary[];
}>('/governance/meta-schemas', params);
}
export function getMetaSchema(schemaKey: string) {
return museAdminApi.get<any>(`/governance/meta-schemas/${schemaKey}`);
}
export function createMetaSchemaDraft(schemaKey: string, data: any) {
return museAdminApi.post<any>(`/governance/meta-schemas/${schemaKey}/drafts`, data);
}
export function publishMetaSchemaDraft(schemaKey: string, draftVersion: number, data: any) {
return museAdminApi.post<any>(
`/governance/meta-schemas/${schemaKey}/drafts/${draftVersion}/publish`,
data
);
}
```
- [ ] **Step 2: 编写列表页**
```vue
<!-- apps/web-antd/src/views/governance/MetaSchemaList.vue -->
<script setup lang="ts">
import { ref } from 'vue';
import { BasicTable, useTable, BasicColumn } from '@vben/common-ui';
import { listMetaSchemas, type MetaSchemaSummary } from '#/api/muse/governance/meta-schema';
import { useRouter } from 'vue-router';
const router = useRouter();
const [registerTable, { reload }] = useTable({
api: async ({ page, size, scope }) => {
const res = await listMetaSchemas({ pageNo: page, pageSize: size, scope });
return { items: res.list, total: res.total };
},
columns: [
{ title: 'Schema Key', dataIndex: 'schemaKey', width: 200 },
{ title: '显示名称', dataIndex: 'displayName', width: 200 },
{ title: '字段类型', dataIndex: 'fieldType', width: 100 },
{ title: '作用域', dataIndex: 'scope', width: 100 },
{ title: '活跃版本', dataIndex: 'activeVersion', width: 100 },
{ title: '状态', dataIndex: 'status', width: 100 },
] as BasicColumn[],
});
function handleDetail(record: MetaSchemaSummary) {
router.push(`/governance/meta-schemas/${record.schemaKey}`);
}
</script>
<template>
<div class="p-4">
<BasicTable @register="registerTable" @row-click="handleDetail">
<template #toolbar>
<a-button type="primary">新建 MetaSchema</a-button>
</template>
</BasicTable>
</div>
</template>
```
- [ ] **Step 3: 编写测试**
```typescript
// apps/web-antd/src/views/governance/__tests__/MetaSchemaList.spec.ts
import { describe, it, expect, vi } from 'vitest';
import { mount } from '@vue/test-utils';
import MetaSchemaList from '../MetaSchemaList.vue';
vi.mock('#/api/muse/governance/meta-schema', () => ({
listMetaSchemas: vi.fn().mockResolvedValue({
total: 2,
list: [
{ schemaKey: 'character_name', displayName: '角色名', fieldType: 'string', scope: 'work', activeVersion: 3, status: 'active' },
{ schemaKey: 'world_setting', displayName: '世界设定', fieldType: 'text', scope: 'global', activeVersion: 1, status: 'active' },
],
}),
}));
describe('MetaSchemaList', () => {
it('should render table', () => {
const wrapper = mount(MetaSchemaList);
expect(wrapper.find('.p-4').exists()).toBe(true);
});
});
```
- [ ] **Step 4: 提交**
```bash
git add -A && git commit -m "feat(governance): 实现 MetaSchema 列表页Vben Table + API 集成)"
```
### Task 2.2: MetaSchema 管理 — 详情/草稿编辑页
实现 MetaSchema 详情页,包含:
- 版本历史时间线
- 当前 active 版本字段展示
- 草稿编辑 + 校验 + 影响预览 + 发布流程
- 灰度规则配置
使用 Vben 内置表单组件 + 动态表单渲染。
### Task 2.3-2.5: 其余管理页面
按优先级依次实现:
**Task 2.3: 系统治理** — 用户管理(复用 Yudao system 模块)、角色权限配置、审计日志查看
**Task 2.4: AI 配置** — Prompt 模板管理、质量门控维度配置、保护节点注册管理、Tool Grant 配置
**Task 2.5: 市场治理 + 全局知识管理** — 资产审核(上架/驳回)、下架/召回、申诉处理、全局知识库维护、知识来源管理
每个页面遵循相同模式API service → 组件实现 → 测试 → 提交。
---
### Task 2.6: Account 管理页面
**文件:**
- 创建: `apps/web-antd/src/api/muse/account/index.ts`
**页面清单:**
| 页面 | 路由 | 说明 |
|------|------|------|
| 用户权益列表 | `/account/entitlements` | 表格:用户 + 权益类型 + 上限 + 已用 + 过期时间 |
| 配额调整表单 | `/account/quota-adjustments` | 弹窗:用户 + 资源类型 + 调整量 + 原因 + commandId |
| New-API 绑定状态 | `/account/new-api-bindings` | 表格:用户 + 绑定状态 + 同步状态 |
| 购买/使用记录 | `/account/records` | 只读汇总表格 |
**API endpoints:**
```
GET /admin-api/muse/account/users # 用户列表
GET /admin-api/muse/account/users/{userId}/entitlements # 用户权益
POST /admin-api/muse/account/users/{userId}/quota-adjustments # 配额调整
GET /admin-api/muse/account/new-api-bindings # New-API 绑定状态
```
**代码示例 — API service:**
```typescript
// apps/web-antd/src/api/muse/account/index.ts
import { museAdminApi } from '../client';
export interface UserEntitlement {
userId: string;
entitlementType: string;
limit: number;
used: number;
expiry: string;
}
export interface QuotaAdjustment {
userId: string;
resourceType: string;
adjustmentAmount: number;
reason: string;
commandId: string;
}
export function getAccountUsers(params: { pageNo: number; pageSize: number }) {
return museAdminApi.get<{ total: number; list: any[] }>('/account/users', params);
}
export function getUserEntitlements(userId: string) {
return museAdminApi.get<UserEntitlement[]>(`/account/users/${userId}/entitlements`);
}
export function adjustQuota(userId: string, data: QuotaAdjustment) {
return museAdminApi.post<void>(`/account/users/${userId}/quota-adjustments`, data);
}
export function getNewApiBindings(params: { pageNo: number; pageSize: number }) {
return museAdminApi.get<{ total: number; list: any[] }>('/account/new-api-bindings', params);
}
```
### Task 2.7: 任务监控页面
**文件:**
- 创建: `apps/web-antd/src/api/muse/jobs/index.ts`
**页面清单:**
| 页面 | 路由 | 说明 |
|------|------|------|
| 任务列表 | `/jobs` | 表格job ID + 类型 + 状态 + 创建时间 + 重试次数 |
| 任务详情 | `/jobs/:jobId` | 状态 + 失败原因 + 重试/取消按钮 |
| 源事件列表 | `/jobs/source-events` | 表格:事件类型 + 来源 + 状态 + 影响摘要 |
**API endpoints:**
```
GET /admin-api/muse/jobs # 任务列表
GET /admin-api/muse/jobs/{jobId} # 任务详情
POST /admin-api/muse/jobs/{jobId}/retry # 重试任务
GET /admin-api/muse/source-events # 源事件列表
```
**代码示例 — API service:**
```typescript
// apps/web-antd/src/api/muse/jobs/index.ts
import { museAdminApi } from '../client';
export interface JobSummary {
jobId: string;
jobType: string;
status: string;
createdAt: string;
retryCount: number;
}
export interface JobDetail extends JobSummary {
failureReason?: string;
payload?: Record<string, unknown>;
result?: Record<string, unknown>;
}
export interface SourceEvent {
eventType: string;
source: string;
status: string;
impactSummary: string;
createdAt: string;
}
export function listJobs(params: { pageNo: number; pageSize: number; status?: string }) {
return museAdminApi.get<{ total: number; list: JobSummary[] }>('/jobs', params);
}
export function getJob(jobId: string) {
return museAdminApi.get<JobDetail>(`/jobs/${jobId}`);
}
export function retryJob(jobId: string) {
return museAdminApi.post<void>(`/jobs/${jobId}/retry`);
}
export function listSourceEvents(params: { pageNo: number; pageSize: number }) {
return museAdminApi.get<{ total: number; list: SourceEvent[] }>('/source-events', params);
}
```
### Task 2.8: 审计日志页面
**文件:**
- 创建: `apps/web-antd/src/api/muse/audit/index.ts`
**页面清单:**
| 页面 | 路由 | 说明 |
|------|------|------|
| 业务审计事件列表 | `/audit/business-events` | 表格:时间戳 + 操作者 + 操作 + 目标 + 结果 |
| 审计详情 | `/audit/business-events/:eventId` | 完整 before/after 快照对比 |
**API endpoints:**
```
GET /admin-api/muse/audit/business-events # 业务审计事件列表
```
**代码示例 — API service:**
```typescript
// apps/web-antd/src/api/muse/audit/index.ts
import { museAdminApi } from '../client';
export interface BusinessAuditEvent {
eventId: string;
timestamp: string;
actor: string;
action: string;
target: string;
result: string;
}
export interface BusinessAuditDetail extends BusinessAuditEvent {
beforeSnapshot?: Record<string, unknown>;
afterSnapshot?: Record<string, unknown>;
}
export function listBusinessAuditEvents(params: { pageNo: number; pageSize: number; actor?: string; action?: string }) {
return museAdminApi.get<{ total: number; list: BusinessAuditEvent[] }>('/audit/business-events', params);
}
export function getBusinessAuditDetail(eventId: string) {
return museAdminApi.get<BusinessAuditDetail>(`/audit/business-events/${eventId}`);
}
```
---
## Step 3: Mock API 配置
- [ ] **Step 1: 配置 MSW 或 Vben 内置 Mock**
为每个 `/admin-api/muse/**` 接口提供 mock 数据,使管理端可独立开发。
---
## 完成标准
- [ ] 5 个功能域管理页面可交互
- [ ] 组件单元测试覆盖率 ≥70%Vitest + Vue Test Utils
- [ ] E2E 测试覆盖核心管理流程Playwright
- [ ] ESLint + Prettier + TypeScript 类型检查通过
- [ ] Vite build 成功