基于产品/架构/流程/前端/后端五维度并行review,澄清并落地22项关键决策: 架构层:Governance按消费者归属拆散、MetaSchema独立模块、 Source传播改为事件驱动自治、去掉Candidate Decision Envelope 和needs_recheck中间状态、Neo4j决策为依赖RAGFlow GraphRAG 后端层:Entitlement统一为可变表+审计日志、API版本策略采用 X-API-Version Header、知识实体唯一键加scope字段 前端层:SSE实时通信(AI stream独立+事件统一)、正文持久化 IndexedDB安全网、Block粒度为场景/小节级 产品层:范围不变UX解决复杂度、知识确认默认自动+冲突时人工
30 KiB
前端-04:市场与个人中心交互
- 版本:v1
- 更新日期:2026-05-24
- 目标读者:前端开发者
- 阅读时间:40-60 分钟
- 归属仓库:
muse-studio/(用户端)+muse-admin/(管理端市场治理) - 边界说明:本文件定义市场空间和个人中心空间在
muse-studio用户端的前端交互设计,包括页面结构、组件职责、API 调用、状态管理、Handoff 消费和错误处理。精确 API 看后端-05,产品功能规格看产品-02F和产品-02G,Handoff 机制看架构-01。
1. 路由结构
基于 前端-01 的路由约定,市场和个人中心在 muse-studio/ 中的路由组织如下:
muse-studio/
app/
(user)/
marketplace/
page.tsx # 市场首页与发现
categories/
page.tsx # 分类推荐与曝光
assets/
[assetId]/
page.tsx # 资产详情
acquire/page.tsx # 获取授权确认
install/page.tsx # 安装与跳转授权入口
records/page.tsx # 资产级记录
governance/page.tsx # 治理结果与申诉
publish/
page.tsx # 发布者资产与提交状态
[draftId]/page.tsx # 发布提交
profile/
page.tsx # 账户总览
info/page.tsx # 个人资料与账号信息
security/page.tsx # 安全与登录
preferences/page.tsx # 偏好与通知
usage/page.tsx # Token 与用量总览
entitlements/page.tsx # 权益与配额
authorizations/page.tsx # 授权获取记录
purchases/page.tsx # 购买记录
installations/page.tsx # 安装与绑定摘要
publications/page.tsx # 发布记录总览
components/
marketplace/
personal-center/
2. 市场空间
2.1 页面结构总览
| 页面 | 路由 | 核心组件 | 主要 API |
|---|---|---|---|
| 市场首页与发现 | /marketplace |
MarketSearch, AssetTypeTab, RecommendSection, AssetList |
GET /app-api/muse/marketplace/assets, GET /app-api/muse/marketplace/categories |
| 分类推荐与曝光 | /marketplace/categories |
CategoryTree, TopicCard, ExposureSummary |
GET /app-api/muse/marketplace/categories |
| 资产详情 | /marketplace/assets/[assetId] |
AssetHeader, LicensePanel, VersionInfo, GovernanceAlert, ActionBar |
GET /app-api/muse/marketplace/assets/{assetId} |
| 获取授权确认 | /marketplace/assets/[assetId]/acquire |
LicenseConfirm, RestrictionList, ExternalAuthRef |
POST /app-api/muse/marketplace/assets/{assetId}/purchase |
| 安装与跳转授权 | /marketplace/assets/[assetId]/install |
InstallPanel, TargetSelector, HandoffGenerator |
POST /app-api/muse/marketplace/assets/{assetId}/install, POST /app-api/muse/marketplace/handoffs |
| 发布者资产 | /marketplace/publish |
PublisherAssetList, StatusFilter, ExposureBadge |
GET /app-api/muse/marketplace/my-publish-records |
| 发布提交 | /marketplace/publish/[draftId] |
PublishForm, CheckRunner, SubmitConfirm |
POST /app-api/muse/marketplace/publish-drafts, POST /app-api/muse/marketplace/publish-drafts/{draftId}/checks, POST /app-api/muse/marketplace/publish-requests |
| 治理结果与申诉 | /marketplace/assets/[assetId]/governance |
GovernanceResult, ImpactList, AppealForm |
GET /app-api/muse/marketplace/assets/{assetId}/governance-impact, POST /app-api/muse/marketplace/appeals |
| 资产级记录 | /marketplace/assets/[assetId]/records |
RecordTimeline, RecordFilter |
资产级记录通过详情页内嵌展示 |
2.2 资产发现交互
2.2.1 搜索与筛选
// lib/queries/marketplace.ts
// 市场资产列表查询 hook
export function useMarketplaceAssets(params: MarketplaceAssetsParams) {
return useQuery({
queryKey: ['marketplace', 'assets', params],
queryFn: () => fetchMarketplaceAssets(params),
// 保持搜索词、分类、筛选和滚动位置
// 注意:keepPreviousData 是 TanStack Query v4 写法,v5 改用 placeholderData: keepPreviousData(从 @tanstack/react-query 导入)
keepPreviousData: true,
});
}
interface MarketplaceAssetsParams {
keyword?: string; // 搜索关键词
assetType?: 'work' | 'agent' | 'knowledge_base'; // 资产类型
categoryId?: string; // 分类 ID
licenseType?: string; // 许可类型筛选
status?: string; // 状态筛选
sortBy?: 'relevance' | 'newest' | 'popular'; // 排序
pageNo: number;
pageSize: number;
}
交互规则:
- 搜索框支持即时搜索(debounce 300ms),按资产类型 Tab 切换不清空搜索词。
- 筛选条件变化时重置分页到第一页,保留搜索词。
- 从详情页返回时恢复搜索词、分类、筛选和滚动位置(通过 URL searchParams 持久化)。
- 未登录用户只能浏览公开摘要,获取、安装、绑定和收藏操作需要登录。
2.2.2 推荐位
推荐区独立加载,失败不阻断列表渲染:
// 推荐位独立查询,失败时静默降级
export function useMarketplaceRecommendations() {
return useQuery({
queryKey: ['marketplace', 'recommendations'],
queryFn: () => fetchCategories(), // GET /app-api/muse/marketplace/categories
retry: 1,
// 注意:useErrorBoundary 是 TanStack Query v4 写法,v5 改用 throwOnError
// 推荐位加载失败不影响主列表
useErrorBoundary: false,
});
}
2.2.3 收藏
// 收藏/取消收藏 mutation
export function useFavoriteAsset() {
return useMutation({
mutationFn: ({ assetId, action }: { assetId: string; action: 'add' | 'remove' }) =>
action === 'add'
? postFavorite(assetId) // POST /app-api/muse/marketplace/assets/{assetId}/favorite
: deleteFavorite(assetId), // DELETE /app-api/muse/marketplace/assets/{assetId}/favorite
onSuccess: () => {
queryClient.invalidateQueries(['marketplace', 'assets']);
},
});
}
2.3 购买/安装流程 UI
2.3.1 获取授权确认页
获取授权确认页展示许可、版本、限制和外部授权引用状态。核心交互流程:
- 进入页面时加载资产详情和获取确认信息。
- 展示许可范围、允许用途、禁止用途、有效期。
- 用户确认后调用购买接口,必须携带
commandId幂等键。 - 获取成功后可选择进入安装页或返回详情。
// 获取授权 mutation
export function usePurchaseAsset() {
return useMutation({
mutationFn: (params: {
assetId: string;
commandId: string; // 幂等键,前端生成 UUID
}) => postPurchase(params.assetId, { commandId: params.commandId }),
// POST /app-api/muse/marketplace/assets/{assetId}/purchase
});
}
状态管理:
| 状态 | UI 表现 | 用户动作 |
|---|---|---|
| 可获取 | 主按钮"确认获取"可用 | 点击确认 |
| 需登录 | 主按钮禁用,提示登录 | 跳转登录 |
| 外部授权待确认 | 主按钮禁用,展示外部状态 | 刷新外部授权 |
| 授权失败 | 展示失败原因 | 重试或返回 |
| 已拥有 | 展示"已获取",引导安装 | 跳转安装页 |
| 资产不可获取 | 展示原因(下架/召回) | 返回列表 |
2.3.2 安装流程
安装只适用于智能体和知识库资产。安装成功只表示资产进入账户可用列表,不等于绑定到作品。
// 安装 mutation
export function useInstallAsset() {
return useMutation({
mutationFn: (params: {
assetId: string;
commandId: string;
}) => postInstall(params.assetId, { commandId: params.commandId }),
// POST /app-api/muse/marketplace/assets/{assetId}/install
});
}
2.3.3 安装进度与结果
安装为同步操作,响应直接返回安装状态。UI 展示:
- 安装中:按钮 loading 态。
- 安装成功:展示"已安装"标记,显示可绑定目标摘要和跳转入口。
- 安装失败:展示失败原因(授权失效、版本不可用、来源下架)。
2.4 Handoff 机制的前端消费
2.4.1 Handoff 概述
市场跨空间跳转使用服务端签发的一次性 handoff token。前端职责:
- 在市场空间发起 handoff 创建请求。
- 获取 handoff token 和目标页 URL。
- 携带 token 跳转到目标 owner 空间。
- 目标空间落地后消费 token,获取 handoff session。
- 基于 session 执行目标 owner 的预检和确认。
2.4.2 创建 Handoff
// 创建市场 handoff
export function useCreateHandoff() {
return useMutation({
mutationFn: (params: CreateHandoffParams) =>
postHandoff(params),
// POST /app-api/muse/marketplace/handoffs
});
}
interface CreateHandoffParams {
assetId: string;
targetOwner: 'knowledge' | 'agent' | 'content';
targetAction: 'bind' | 'slot_bind' | 'asset_use';
targetWorkId?: string;
returnUrl: string; // 返回点
commandId: string; // 幂等键
}
2.4.3 目标空间消费 Handoff
目标空间(如作品知识来源页)落地时:
// 目标空间消费 handoff token
export function useConsumeHandoff(handoffToken: string | null) {
return useQuery({
queryKey: ['handoff', handoffToken],
queryFn: () => getHandoffStatus(handoffToken!),
// GET /app-api/muse/marketplace/handoffs/{handoffToken}
enabled: !!handoffToken,
});
}
2.4.4 Token 过期处理
| 场景 | 错误码 | 前端处理 |
|---|---|---|
| Token 不存在 | MARKET_HANDOFF_INVALID |
返回市场刷新状态 |
| Token 已过期 | PRECHECK_EXPIRED |
提示过期,引导重新发起 |
| Token 已消费 | MARKET_HANDOFF_INVALID |
展示已消费状态 |
| Token 已取消 | MARKET_HANDOFF_INVALID |
返回市场 |
| 目标 owner 不匹配 | MARKET_HANDOFF_INVALID |
返回市场刷新 |
2.4.5 Handoff 状态轮询
对于需要等待目标空间确认的场景,市场侧可轮询 handoff 状态:
// 轮询 handoff 状态(用户从目标空间返回后刷新)
export function useHandoffStatus(handoffToken: string) {
return useQuery({
queryKey: ['handoff', 'status', handoffToken],
queryFn: () => getHandoffStatus(handoffToken),
// GET /app-api/muse/marketplace/handoffs/{handoffToken}
refetchOnWindowFocus: true, // 用户从目标空间返回时自动刷新
});
}
2.5 发布准备 UI
2.5.1 发布提交流程
发布提交页面按资产类型(作品、智能体、知识库)分型展示不同表单字段和检查项。
流程步骤:
- 保存发布草稿 →
POST /app-api/muse/marketplace/publish-drafts - 运行发布检查 →
POST /app-api/muse/marketplace/publish-drafts/{draftId}/checks - 检查通过后提交审核 →
POST /app-api/muse/marketplace/publish-requests
// 发布检查 mutation
export function useRunPublishCheck() {
return useMutation({
mutationFn: (draftId: string) =>
postPublishCheck(draftId),
// POST /app-api/muse/marketplace/publish-drafts/{draftId}/checks
});
}
// 提交发布申请 mutation
export function useSubmitPublishRequest() {
return useMutation({
mutationFn: (params: {
draftId: string;
marketPublishCheckId: string; // 消费发布检查结果
commandId: string;
}) => postPublishRequest(params),
// POST /app-api/muse/marketplace/publish-requests
});
}
2.5.2 发布检查状态
| 检查状态 | UI 表现 | 用户动作 |
|---|---|---|
| 未检查 | "运行检查"按钮可用 | 点击运行 |
| 检查中 | 按钮 loading,展示进度 | 等待 |
| 检查通过 | 展示通过项,"提交审核"可用 | 提交 |
| 检查失败 | 展示阻断项和警告项 | 修正后重新检查 |
| 检查过期 | 提示过期,需重新检查 | 重新运行 |
2.5.3 来源状态确认
发布前必须确认来源资产状态。前端调用来源状态查询:
// 查询来源状态
export function useSourceStatus(params: SourceStatusParams) {
return useQuery({
queryKey: ['source-status', params],
queryFn: () => postSourceStatusQuery(params),
// POST /app-api/muse/source-status/query
});
}
来源状态异常时禁用发布提交按钮,展示原因和处理建议。
2.6 治理结果展示
2.6.1 下架/召回通知
资产详情页顶部展示治理状态 Alert:
// 治理影响查询
export function useGovernanceImpact(assetId: string) {
return useQuery({
queryKey: ['marketplace', 'governance-impact', assetId],
queryFn: () => getGovernanceImpact(assetId),
// GET /app-api/muse/marketplace/assets/{assetId}/governance-impact
enabled: !!assetId,
});
}
UI 展示规则:
| 治理状态 | Alert 类型 | 展示内容 | 可用动作 |
|---|---|---|---|
| 已下架 | warning | 下架原因、影响范围 | 查看替代、申诉 |
| 召回中 | error | 召回原因、影响范围、处理期限 | 停用安装、申诉 |
| 授权撤销 | error | 撤销原因、影响绑定 | 重新获取、替代 |
| 申诉中 | info | 申诉进度、预计处理时间 | 补充材料、撤回 |
2.6.2 违规说明
违规说明展示在治理结果页,包含:
- 结果类型和原因摘要
- 生效时间
- 影响范围(新获取、新安装、新绑定、生成使用是否停止)
- 替代方案建议
- 申诉入口和期限
2.7 来源状态反馈
2.7.1 来源失效 UI
当资产来源失效时,前端根据 sourceStatus 和 actionPolicy 展示不同 UI:
| sourceStatus | actionPolicy | UI 表现 |
|---|---|---|
active |
allowed |
正常展示,所有操作可用 |
stale |
needs_recheck |
黄色提示条,建议重验,提供重验按钮 |
revoked |
blocked |
红色提示,禁用绑定/生成 |
recalled |
blocked |
红色提示,展示召回说明 |
delisted |
blocked |
灰色提示,展示下架原因 |
2.7.2 授权变化展示
授权状态变化时,资产详情页和安装页实时反映:
// 资产详情页监听授权状态
// 通过 refetchOnWindowFocus 和 refetchInterval 保持最新
export function useAssetDetail(assetId: string) {
return useQuery({
queryKey: ['marketplace', 'asset', assetId],
queryFn: () => getAssetDetail(assetId),
// GET /app-api/muse/marketplace/assets/{assetId}
refetchOnWindowFocus: true,
staleTime: 30_000, // 30 秒内不重复请求
});
}
2.8 错误处理和边界情况
2.8.1 通用错误处理策略
// lib/api/error-handler.ts
// 市场空间错误处理映射
const marketplaceErrorHandlers: Record<string, ErrorHandler> = {
UNAUTHENTICATED: () => redirectToLogin(),
FORBIDDEN: (ctx) => showNoPermissionToast(ctx.msg),
RESOURCE_NOT_FOUND: () => redirectToMarketplaceHome(),
SOURCE_NEEDS_RECHECK: (ctx) => showRecheckPrompt(ctx.data),
SOURCE_BLOCKED: (ctx) => showBlockedAlert(ctx.data),
PRECHECK_EXPIRED: (ctx) => showExpiredPrompt(ctx.data),
MARKET_HANDOFF_INVALID: () => redirectToMarketplaceWithRefresh(),
IDEMPOTENCY_CONFLICT: (ctx) => showConflictToast(ctx.msg),
FEATURE_DISABLED: (ctx) => hideOrDisableEntry(ctx.data),
};
2.8.2 边界情况处理
| 边界情况 | 处理方式 |
|---|---|
| 资产在浏览过程中被下架 | 详情页展示下架提示,禁用获取/安装按钮 |
| 获取过程中授权失效 | 中断获取流程,展示失效原因 |
| Handoff 跳转后目标空间不可用 | 展示错误页,提供返回市场按钮 |
| 发布检查过程中资产版本变化 | 检查结果标记为过期,需重新检查 |
| 网络中断 | TanStack Query 自动重试,展示离线提示 |
| 分页加载失败 | 保留已加载数据,展示重试按钮 |
3. 个人中心空间
3.1 页面结构总览
| 页面 | 路由 | 核心组件 | 主要 API |
|---|---|---|---|
| 账户总览 | /profile |
OverviewCard, SecurityCard, UsageCard, AssetSummaryCard, AlertBar |
GET /app-api/muse/me, GET /app-api/muse/account/entitlements, GET /app-api/muse/account/usage |
| 个人资料 | /profile/info |
ProfileForm, ContactVerification, AvatarUpload |
GET /app-api/muse/profile, PATCH /app-api/muse/profile |
| 安全与登录 | /profile/security |
PasswordSection, MFASection, SessionList, SecurityEventList |
GET /app-api/muse/account/security-events |
| 偏好与通知 | /profile/preferences |
PreferenceForm, NotificationSettings |
偏好相关接口(复用 Yudao 基础能力) |
| Token 与用量 | /profile/usage |
UsageTrend, UsageTable, AttributionDetail |
GET /app-api/muse/account/usage, GET /app-api/muse/account/entitlements |
| 权益与配额 | /profile/entitlements |
EntitlementCard, QuotaProgress, ChangeLog |
GET /app-api/muse/account/entitlements |
| 授权获取记录 | /profile/authorizations |
AuthRecordTable, SnapshotDrawer |
GET /app-api/muse/account/licenses |
| 购买记录 | /profile/purchases |
PurchaseTable, ReceiptDrawer |
GET /app-api/muse/account/purchases |
| 安装与绑定摘要 | /profile/installations |
InstalledList, BindingAnomalyList |
通过 /app-api/muse/me 和相关接口聚合 |
| 发布记录总览 | /profile/publications |
PublishRecordTable, StatusBadge |
GET /app-api/muse/account/publish-records |
3.2 权益摘要展示
3.2.1 /app-api/muse/me 数据消费
应用入口初始化时调用 /app-api/muse/me,获取当前用户权益摘要和可见产品空间:
// lib/queries/me.ts
// 当前用户信息和权益摘要
export function useCurrentUser() {
return useQuery({
queryKey: ['me'],
queryFn: () => fetchMe(),
// GET /app-api/muse/me
staleTime: 5 * 60 * 1000, // 5 分钟缓存
refetchOnWindowFocus: true,
});
}
// 返回数据结构(前端类型定义)
interface MeResponse {
userId: string;
nickname: string;
avatar: string;
entitlementSummary: {
planName: string;
tokenQuota: number;
tokenUsed: number;
expiresAt: string | null;
isLimited: boolean;
};
visibleSpaces: string[]; // 可见产品空间列表
defaultEntry: string; // 默认入口
securityRisk: boolean; // 是否有安全风险
pendingAlerts: number; // 待处理提醒数
}
3.2.2 账户总览页数据聚合
账户总览页并行加载多个摘要接口:
// 账户总览页数据加载
export function useProfileOverview() {
const me = useCurrentUser();
const entitlements = useEntitlements();
const usage = useUsageSummary();
const securityEvents = useSecurityEvents({ limit: 5 });
return {
me,
entitlements,
usage,
securityEvents,
isLoading: me.isLoading || entitlements.isLoading,
};
}
// 权益与配额查询
function useEntitlements() {
return useQuery({
queryKey: ['account', 'entitlements'],
queryFn: () => fetchEntitlements(),
// GET /app-api/muse/account/entitlements
});
}
// 用量摘要查询
function useUsageSummary() {
return useQuery({
queryKey: ['account', 'usage'],
queryFn: () => fetchUsage(),
// GET /app-api/muse/account/usage
});
}
3.3 配额和用量可视化
3.3.1 配额进度条
权益与配额页使用进度条可视化展示额度消耗:
// components/personal-center/QuotaProgress.tsx
interface QuotaProgressProps {
label: string; // 配额名称
total: number; // 总额度
used: number; // 已用
unit: string; // 单位(如 "Token")
expiresAt?: string; // 到期时间
isLimited?: boolean; // 是否被限流
}
展示规则:
- 使用率 < 70%:绿色进度条
- 使用率 70%-90%:黄色进度条 + 提醒文案
- 使用率 > 90%:红色进度条 + 额度不足警告
- 已过期:灰色进度条 + 过期提示
- 被限流:红色进度条 + 限流原因和恢复路径
3.3.2 用量趋势图
Token 与用量页展示近 30 天用量趋势:
// 用量趋势数据
export function useUsageTrend(params: { days: number; groupBy: 'day' | 'week' }) {
return useQuery({
queryKey: ['account', 'usage', 'trend', params],
queryFn: () => fetchUsage(),
// GET /app-api/muse/account/usage(带时间范围参数)
});
}
用量明细表支持按来源筛选:
| 筛选维度 | 说明 |
|---|---|
| 时间范围 | 近 7 天 / 30 天 / 自定义 |
| 归属对象 | 作品 / 智能体 / 知识库 |
| 状态 | 已归属 / 待归属 / 异常 |
3.3.3 跳转来源记录
用量明细中的归属对象支持跳转到对应 owner 空间:
// 跨空间跳转(从个人中心到作品/智能体/知识库记录)
function handleJumpToSource(record: UsageRecord) {
const targetUrl = buildSourceUrl(record.sourceType, record.sourceId);
// 使用 router 跳转,携带返回点
router.push(`${targetUrl}?returnTo=/profile/usage`);
}
3.4 安全事件列表和处理交互
3.4.1 安全事件列表
// 安全事件查询
export function useSecurityEvents(params: { pageNo: number; pageSize: number }) {
return useQuery({
queryKey: ['account', 'security-events', params],
queryFn: () => fetchSecurityEvents(params),
// GET /app-api/muse/account/security-events
});
}
安全事件列表展示:
| 字段 | 说明 |
|---|---|
| 事件类型 | 异地登录、密码修改、二次验证变更、会话异常 |
| 时间 | 事件发生时间 |
| 设备/地点 | 脱敏展示 |
| 风险等级 | 高/中/低 |
| 处理状态 | 未处理、已确认本人、已处理 |
3.4.2 确认非本人操作
高风险安全事件支持"确认本人操作"交互:
// 确认安全事件为本人操作
export function useAcknowledgeSecurityEvent() {
return useMutation({
mutationFn: (params: {
eventId: string;
confirmation: string; // 确认说明
commandId: string;
}) => postAcknowledgeSecurityEvent(params),
// POST /app-api/muse/account/security-events/{eventId}/acknowledge
onSuccess: () => {
queryClient.invalidateQueries(['account', 'security-events']);
},
});
}
交互流程:
- 用户点击"这是我本人"按钮。
- 高风险事件触发 step-up 验证(二次验证或密码确认)。
- step-up 通过后展示事件摘要和确认影响。
- 用户确认后追加处置标记。
- 刷新安全事件列表和风险提示。
如果用户认为非本人操作,引导:修改密码 → 撤销可疑会话 → 联系客服。
3.5 购买/发布记录的分页和筛选
3.5.1 购买记录
// 购买记录查询
export function usePurchaseRecords(params: PurchaseRecordParams) {
return useQuery({
queryKey: ['account', 'purchases', params],
queryFn: () => fetchPurchases(params),
// GET /app-api/muse/account/purchases
// 注意:keepPreviousData 是 TanStack Query v4 写法,v5 改用 placeholderData: keepPreviousData(从 @tanstack/react-query 导入)
keepPreviousData: true,
});
}
interface PurchaseRecordParams {
pageNo: number;
pageSize: number;
status?: 'completed' | 'processing' | 'failed';
assetType?: 'work' | 'agent' | 'knowledge_base';
startTime?: string;
endTime?: string;
}
购买记录表格列:
| 列 | 数据 | 操作 |
|---|---|---|
| 时间 | 购买时间 | - |
| 资产 | 资产名称和类型 | 跳转市场详情 |
| 来源 | 购买/免费/管理员授权 | - |
| 金额 | 金额或"免费" | - |
| 状态 | 已完成/处理中/失败 | 查看凭证 |
| 授权结果 | 是否已生成授权 | 跳转授权记录 |
3.5.2 发布记录
// 发布记录查询
export function usePublishRecords(params: PublishRecordParams) {
return useQuery({
queryKey: ['account', 'publish-records', params],
queryFn: () => fetchPublishRecords(params),
// GET /app-api/muse/account/publish-records
// 注意:keepPreviousData 是 TanStack Query v4 写法,v5 改用 placeholderData: keepPreviousData(从 @tanstack/react-query 导入)
keepPreviousData: true,
});
}
interface PublishRecordParams {
pageNo: number;
pageSize: number;
assetType?: 'work' | 'agent' | 'knowledge_base';
reviewStatus?: 'draft' | 'submitted' | 'reviewing' | 'needs_supplement' | 'approved' | 'rejected';
marketStatus?: 'listed' | 'delisted' | 'recalled';
}
3.5.3 通用分页组件
所有记录页使用统一分页组件,支持:
- 页码切换和每页条数选择
- URL searchParams 持久化(刷新不丢失筛选)
- 加载中保留上一页数据(
keepPreviousData) - 空态展示和跳转入口
3.6 跳转规则
3.6.1 从个人中心跳转到其他空间
个人中心是 read model 和跳转入口,所有业务处理必须跳转到对应 owner 空间。
| 来源页面 | 跳转目标 | 触发条件 | 携带参数 |
|---|---|---|---|
| 授权获取记录 | 市场资产详情 | 点击资产名称 | assetId, returnTo |
| 授权获取记录 | 智能体已安装页 | 点击"去安装" | assetId, returnTo |
| 授权获取记录 | 知识库已安装页 | 点击"去安装" | assetId, returnTo |
| 安装与绑定摘要 | 作品智能体关联 | 点击异常处理 | workId, slotKey, returnTo |
| 安装与绑定摘要 | 作品知识来源 | 点击异常处理 | workId, bindingId, returnTo |
| 发布记录总览 | 市场发布提交 | 点击"去补充" | draftId, returnTo |
| 发布记录总览 | 智能体发布准备 | 点击"去处理" | agentId, returnTo |
| 发布记录总览 | 知识库发布准备 | 点击"去处理" | kbId, returnTo |
| Token 与用量 | 作品记录与用量 | 点击归属作品 | workId, returnTo |
| 权益与配额 | 市场(补充权益) | 点击"补充权益" | returnTo |
3.6.2 返回规则
所有跳转携带 returnTo 参数,目标空间处理完成后通过该参数返回个人中心并刷新对应数据:
// 跳转工具函数
function navigateToOwnerSpace(target: string, returnTo: string) {
const url = new URL(target, window.location.origin);
url.searchParams.set('returnTo', returnTo);
router.push(url.pathname + url.search);
}
// 返回个人中心时刷新数据
function handleReturnFromOwnerSpace() {
const returnTo = searchParams.get('returnTo');
if (returnTo?.startsWith('/profile')) {
// 失效相关查询缓存,触发重新加载
queryClient.invalidateQueries(['account']);
router.push(returnTo);
}
}
4. 状态管理策略
4.1 市场空间状态分层
| 状态类型 | 管理方式 | 示例 |
|---|---|---|
| 服务器数据 | TanStack Query | 资产列表、详情、授权状态、治理结果 |
| 搜索/筛选状态 | URL searchParams | 搜索词、分类、排序、分页 |
| UI 临时态 | React useState | 弹窗开关、表单编辑中、loading |
| 跨页面共享 | Zustand store | 当前 handoff session、返回点 |
4.2 个人中心状态分层
| 状态类型 | 管理方式 | 示例 |
|---|---|---|
| 服务器数据 | TanStack Query | 权益、用量、记录列表、安全事件 |
| 筛选/分页 | URL searchParams | 时间范围、状态筛选、页码 |
| 表单状态 | React Hook Form | 个人资料编辑、偏好设置 |
| step-up 状态 | Zustand store | 二次验证流程状态 |
4.3 缓存失效策略
// 市场操作后的缓存失效
const marketplaceMutationConfig = {
// 购买成功后失效资产详情和授权记录
onPurchaseSuccess: () => {
queryClient.invalidateQueries(['marketplace', 'asset']);
queryClient.invalidateQueries(['account', 'licenses']);
queryClient.invalidateQueries(['me']); // 权益可能变化
},
// 安装成功后失效安装状态
onInstallSuccess: () => {
queryClient.invalidateQueries(['marketplace', 'asset']);
queryClient.invalidateQueries(['account', 'installations']);
},
// 发布提交后失效发布记录
onPublishSuccess: () => {
queryClient.invalidateQueries(['account', 'publish-records']);
queryClient.invalidateQueries(['marketplace', 'my-publish-records']);
},
};
5. 管理端市场治理(muse-admin)
管理端市场治理页面在 muse-admin/ 中实现,使用 Vben Admin 框架,调用 /admin-api/**。
5.1 管理端市场页面
| 页面 | API | 说明 |
|---|---|---|
| 市场资产列表 | GET /admin-api/muse/market/assets |
查看所有市场资产和治理摘要 |
| 发布申请审核 | GET /admin-api/muse/market/publish-requests |
审核发布申请 |
| 审核通过/拒绝 | POST /admin-api/muse/market/publish-requests/{id}/approve |
审核决策 |
| 资产下架 | POST /admin-api/muse/market/assets/{id}/delist |
下架资产 |
| 资产召回 | POST /admin-api/muse/market/assets/{id}/recall |
召回资产 |
| 申诉处理 | GET /admin-api/muse/market/appeals |
查看和处理申诉 |
管理端不承载普通用户的市场发现、购买、安装或绑定流程。
6. 关联阅读
| 文档 | 关联内容 |
|---|---|
产品-02F-市场功能规格.md |
市场产品定义、页面规格、操作规格、跨空间跳转 |
产品-02G-个人中心功能规格.md |
个人中心产品定义、页面规格、权限和安全规则 |
后端-05-统一API契约-v1.md |
所有 API 路径、请求响应格式、错误码定义 |
架构-01-系统全貌与边界上下文.md |
Handoff 机制、BC 边界、Source/Authorization 横切契约 |
前端-01-工程结构与核心依赖.md |
工程结构、路由约定、状态分层、接口边界 |
前端-02-写作台与候选交互.md |
写作台交互模式参考 |
前端-03-元引擎与动态表单.md |
MetaSchema 消费和动态表单渲染 |
架构-04-状态机与约束清单.md |
资产状态机、授权状态机 |