新增 AutoRDO 需求清洗工作台与消息中枢,迭代 OneOS V2 设计规范及租赁合同/工作台/车辆等原型,同步云效技能与导航注册;并归档一批 legacy 原型快照。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
548
docs/superpowers/plans/2026-07-22-message-hub.md
Normal file
548
docs/superpowers/plans/2026-07-22-message-hub.md
Normal file
@@ -0,0 +1,548 @@
|
||||
# Message Hub 实施计划
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 落地统一消息中枢(模型 + 本地路由表 + Web 消息中心原型),并让工作台/外壳铃铛读同一中枢。
|
||||
|
||||
**Architecture:** `src/common/message-hub/` 持有 Message、ChannelDelivery、RouteRule 与 `resolve()`;新原型 `message-center` 提供筛选/列表/详情/端模拟器/去处理;工作台与 `notice-bridge` 通过适配层映射为铃铛摘要。真推送与真唤端不做。
|
||||
|
||||
**Tech Stack:** React + TypeScript(现有 Axhub Make 原型)、Vitest(`resolve` 单测)、localStorage(可选已读)、现有 `oneos-app-shell` 铃铛 UI。
|
||||
|
||||
**Spec:** [docs/superpowers/specs/2026-07-22-message-hub-design.md](../specs/2026-07-22-message-hub-design.md)
|
||||
|
||||
---
|
||||
|
||||
## 文件结构(锁定)
|
||||
|
||||
| 路径 | 职责 |
|
||||
|------|------|
|
||||
| `src/common/message-hub/types.ts` | Message / Channel / RouteRule 类型 |
|
||||
| `src/common/message-hub/routes.ts` | 五端 × 多系统路由表常量 |
|
||||
| `src/common/message-hub/resolve.ts` | `resolveMessageTarget()` |
|
||||
| `src/common/message-hub/resolve.test.ts` | 路由优先级与失败态单测 |
|
||||
| `src/common/message-hub/seed.ts` | 宽首期种子消息(含旧 notices 映射) |
|
||||
| `src/common/message-hub/store.ts` | 读列表、标已读、未读数(内存 + localStorage) |
|
||||
| `src/common/message-hub/shell-adapter.ts` | Message → `ShellNoticeItem` |
|
||||
| `src/common/message-hub/index.ts` | 公共导出 |
|
||||
| `src/prototypes/message-center/index.tsx` | 原型入口 |
|
||||
| `src/prototypes/message-center/MessageCenterApp.tsx` | 主 UI |
|
||||
| `src/prototypes/message-center/styles/index.css` | 样式 |
|
||||
| `src/prototypes/message-center/annotation-source.json` | 标注目录 |
|
||||
| `src/prototypes/message-center/.spec/route-resolve.md` | 路由判定全文 |
|
||||
| `src/prototypes/message-center/.spec/requirements-prd.md` | AutoPRD |
|
||||
| `src/resources/prd/message-center-autoprd.md` | PRD 副本 |
|
||||
| 修改 `oneos-app-shell/ShellNoticeCenter.tsx` | 「查看全部」→ 消息中心;详情优先于行内直跳 |
|
||||
| 修改 `oneos-web-workbench-new` | 铃铛数据改读 message-hub |
|
||||
| 修改 `nav-menu.json` | 增加「消息中心」菜单项 |
|
||||
|
||||
---
|
||||
|
||||
### Task 1: message-hub 类型 + resolve + 单测
|
||||
|
||||
**Files:**
|
||||
- Create: `src/common/message-hub/types.ts`
|
||||
- Create: `src/common/message-hub/resolve.ts`
|
||||
- Create: `src/common/message-hub/resolve.test.ts`
|
||||
- Create: `src/common/message-hub/index.ts`(先导出类型与 resolve)
|
||||
|
||||
- [ ] **Step 1: 写入类型**
|
||||
|
||||
```ts
|
||||
// src/common/message-hub/types.ts
|
||||
export type SourceSystem = 'oneos' | 'vehicle-mid' | 'other-system' | 'external';
|
||||
export type MessageClient = 'web' | 'ios' | 'android' | 'harmony' | 'wechat_oa';
|
||||
export type ChannelStatus = 'pending' | 'sent' | 'failed' | 'skipped';
|
||||
export type MessagePriority = 'normal' | 'high';
|
||||
export type ExternalAppId = 'external-app-a' | 'external-app-b';
|
||||
|
||||
export type ChannelDelivery = {
|
||||
client: MessageClient;
|
||||
status: ChannelStatus;
|
||||
updatedAt?: string;
|
||||
};
|
||||
|
||||
export type HubMessage = {
|
||||
id: string;
|
||||
sourceSystem: SourceSystem;
|
||||
bizType: string;
|
||||
bizId: string;
|
||||
title: string;
|
||||
summary: string;
|
||||
detail: string;
|
||||
priority: MessagePriority;
|
||||
createdAt: string;
|
||||
readAt?: string;
|
||||
/** 角色占位;空数组表示全员可见 */
|
||||
audienceRoleIds: string[];
|
||||
channels: ChannelDelivery[];
|
||||
/** 展示用业务标签,如「交车任务」 */
|
||||
bizTag: string;
|
||||
};
|
||||
|
||||
export type RouteRule = {
|
||||
sourceSystem: SourceSystem;
|
||||
bizType: string;
|
||||
client: MessageClient;
|
||||
targetTemplate: string;
|
||||
label: string;
|
||||
externalApp?: ExternalAppId;
|
||||
/** 精确未命中时,再试该 client(如 harmony → android) */
|
||||
fallbackClient?: MessageClient;
|
||||
};
|
||||
|
||||
export type ResolveOk = {
|
||||
ok: true;
|
||||
uri: string;
|
||||
label: string;
|
||||
externalApp?: ExternalAppId;
|
||||
rule: RouteRule;
|
||||
};
|
||||
|
||||
export type ResolveFail = {
|
||||
ok: false;
|
||||
reason: 'no_rule';
|
||||
message: '当前端暂无可跳转目标';
|
||||
};
|
||||
|
||||
export type ResolveResult = ResolveOk | ResolveFail;
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 写失败单测(先不实现 resolve 逻辑体)**
|
||||
|
||||
```ts
|
||||
// src/common/message-hub/resolve.test.ts
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { resolveMessageTarget } from './resolve';
|
||||
import type { HubMessage, RouteRule } from './types';
|
||||
|
||||
const baseMsg: HubMessage = {
|
||||
id: 'm1',
|
||||
sourceSystem: 'oneos',
|
||||
bizType: 'approval.arrive',
|
||||
bizId: 'AP-1',
|
||||
title: '待审',
|
||||
summary: '',
|
||||
detail: '详情',
|
||||
priority: 'normal',
|
||||
createdAt: '2026-07-22T10:00:00+08:00',
|
||||
audienceRoleIds: [],
|
||||
channels: [],
|
||||
bizTag: '租赁合同',
|
||||
};
|
||||
|
||||
describe('resolveMessageTarget', () => {
|
||||
it('精确匹配 web 规则', () => {
|
||||
const rules: RouteRule[] = [
|
||||
{
|
||||
sourceSystem: 'oneos',
|
||||
bizType: 'approval.arrive',
|
||||
client: 'web',
|
||||
targetTemplate: '/prototypes/oneos-web-approval-todo?id={bizId}',
|
||||
label: '审批待办',
|
||||
},
|
||||
];
|
||||
const r = resolveMessageTarget(baseMsg, 'web', rules);
|
||||
expect(r.ok).toBe(true);
|
||||
if (r.ok) expect(r.uri).toBe('/prototypes/oneos-web-approval-todo?id=AP-1');
|
||||
});
|
||||
|
||||
it('harmony 可 fallback 到 android', () => {
|
||||
const rules: RouteRule[] = [
|
||||
{
|
||||
sourceSystem: 'oneos',
|
||||
bizType: 'approval.arrive',
|
||||
client: 'android',
|
||||
targetTemplate: 'oneos://approval/{bizId}',
|
||||
label: '安卓审批',
|
||||
fallbackClient: undefined,
|
||||
},
|
||||
{
|
||||
sourceSystem: 'oneos',
|
||||
bizType: 'approval.arrive',
|
||||
client: 'harmony',
|
||||
targetTemplate: '',
|
||||
label: '鸿蒙走安卓模板',
|
||||
fallbackClient: 'android',
|
||||
},
|
||||
];
|
||||
// 实现约定:harmony 行若 targetTemplate 为空且带 fallbackClient,则用 fallback 的模板
|
||||
const r = resolveMessageTarget(baseMsg, 'harmony', rules);
|
||||
expect(r.ok).toBe(true);
|
||||
if (r.ok) expect(r.uri).toBe('oneos://approval/AP-1');
|
||||
});
|
||||
|
||||
it('无规则返回固定文案', () => {
|
||||
const r = resolveMessageTarget(baseMsg, 'wechat_oa', []);
|
||||
expect(r).toEqual({
|
||||
ok: false,
|
||||
reason: 'no_rule',
|
||||
message: '当前端暂无可跳转目标',
|
||||
});
|
||||
});
|
||||
|
||||
it('带 externalApp', () => {
|
||||
const msg = { ...baseMsg, sourceSystem: 'external' as const, bizType: 'order.action', bizId: 'O-9' };
|
||||
const rules: RouteRule[] = [
|
||||
{
|
||||
sourceSystem: 'external',
|
||||
bizType: 'order.action',
|
||||
client: 'web',
|
||||
targetTemplate: 'ext-app-a://order/{bizId}',
|
||||
label: '外部 App A 订单',
|
||||
externalApp: 'external-app-a',
|
||||
},
|
||||
];
|
||||
const r = resolveMessageTarget(msg, 'web', rules);
|
||||
expect(r.ok).toBe(true);
|
||||
if (r.ok) {
|
||||
expect(r.uri).toBe('ext-app-a://order/O-9');
|
||||
expect(r.externalApp).toBe('external-app-a');
|
||||
}
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 跑测确认失败**
|
||||
|
||||
Run: `npx vitest --run src/common/message-hub/resolve.test.ts`
|
||||
Expected: FAIL(模块不存在或函数未导出)
|
||||
|
||||
- [ ] **Step 4: 实现 resolve**
|
||||
|
||||
```ts
|
||||
// src/common/message-hub/resolve.ts
|
||||
import type { HubMessage, MessageClient, ResolveResult, RouteRule } from './types';
|
||||
|
||||
function fillTemplate(template: string, msg: HubMessage): string {
|
||||
return template
|
||||
.replaceAll('{bizId}', encodeURIComponent(msg.bizId))
|
||||
.replaceAll('{id}', encodeURIComponent(msg.id));
|
||||
}
|
||||
|
||||
function findRule(
|
||||
rules: RouteRule[],
|
||||
sourceSystem: HubMessage['sourceSystem'],
|
||||
bizType: string,
|
||||
client: MessageClient,
|
||||
): RouteRule | undefined {
|
||||
return rules.find(
|
||||
(r) => r.sourceSystem === sourceSystem && r.bizType === bizType && r.client === client,
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveMessageTarget(
|
||||
msg: HubMessage,
|
||||
client: MessageClient,
|
||||
rules: RouteRule[],
|
||||
): ResolveResult {
|
||||
const primary = findRule(rules, msg.sourceSystem, msg.bizType, client);
|
||||
if (primary) {
|
||||
const useFallback =
|
||||
(!primary.targetTemplate || primary.targetTemplate.trim() === '') && primary.fallbackClient;
|
||||
if (useFallback && primary.fallbackClient) {
|
||||
const fb = findRule(rules, msg.sourceSystem, msg.bizType, primary.fallbackClient);
|
||||
if (fb?.targetTemplate) {
|
||||
return {
|
||||
ok: true,
|
||||
uri: fillTemplate(fb.targetTemplate, msg),
|
||||
label: primary.label || fb.label,
|
||||
externalApp: fb.externalApp ?? primary.externalApp,
|
||||
rule: fb,
|
||||
};
|
||||
}
|
||||
}
|
||||
if (primary.targetTemplate?.trim()) {
|
||||
return {
|
||||
ok: true,
|
||||
uri: fillTemplate(primary.targetTemplate, msg),
|
||||
label: primary.label,
|
||||
externalApp: primary.externalApp,
|
||||
rule: primary,
|
||||
};
|
||||
}
|
||||
}
|
||||
return { ok: false, reason: 'no_rule', message: '当前端暂无可跳转目标' };
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 5: 跑测通过**
|
||||
|
||||
Run: `npx vitest --run src/common/message-hub/resolve.test.ts`
|
||||
Expected: PASS(4 tests)
|
||||
|
||||
- [ ] **Step 6: Commit**(仅当用户要求提交时执行)
|
||||
|
||||
```bash
|
||||
git add src/common/message-hub/
|
||||
git commit -m "$(cat <<'EOF'
|
||||
feat(message-hub): add types and resolve() with vitest coverage
|
||||
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: 路由表 + 种子消息
|
||||
|
||||
**Files:**
|
||||
- Create: `src/common/message-hub/routes.ts`
|
||||
- Create: `src/common/message-hub/seed.ts`
|
||||
- Modify: `src/common/message-hub/index.ts`
|
||||
|
||||
- [ ] **Step 1: 写入 `ROUTE_RULES`**
|
||||
|
||||
至少覆盖(每个 listed bizType 需含 web/ios/android/harmony/wechat_oa 五行;wechat 无办理页可用空 template + 不配 fallback,使 resolve 失败并在 UI 显示 skipped 通道态):
|
||||
|
||||
| sourceSystem | bizType | web 目标示例 |
|
||||
|--------------|---------|--------------|
|
||||
| oneos | approval.arrive | `/prototypes/oneos-web-approval-todo?id={bizId}` |
|
||||
| oneos | urge.remind | `/prototypes/oneos-web-ops`(可带 query) |
|
||||
| oneos | contract.expire | `/prototypes/customer-management` |
|
||||
| oneos | license.expire | `/prototypes/customer-management` |
|
||||
| oneos | bill.ready | `/prototypes/lease-business-ledger` |
|
||||
| oneos | h2.balance | `/prototypes/payment-records` |
|
||||
| oneos | system.release | (无跳转或打开版本说明占位 path) |
|
||||
| vehicle-mid | fault.overdue | `/prototypes/vehicle-fault-handling#page=detail&id={bizId}` |
|
||||
| vehicle-mid | vehicle.status | `/prototypes/vehicle-management` |
|
||||
| other-system | generic.notice | `/prototypes/message-center`(仅详情,无外跳也可失败) |
|
||||
| external | order.action | `ext-app-a://order/{bizId}` + `externalApp: external-app-a` |
|
||||
| external | settle.action | `ext-app-b://settle/{bizId}` + `externalApp: external-app-b` |
|
||||
|
||||
harmony 行:`targetTemplate: ''`, `fallbackClient: 'android'`。
|
||||
ios/android:`oneos://…` / `oneos-android://…` 占位 scheme。
|
||||
wechat_oa:对可 H5 办理的给 `https://oa.example.com/...` 占位;纯 PC 办理给空 template。
|
||||
|
||||
- [ ] **Step 2: 写入 `SEED_MESSAGES`**
|
||||
|
||||
映射旧 `SEED_NOTICES`(保留原 id 如 `n-1`、`RELEASE_NOTICE_ID` 便于对照)+ 新增 vehicle-mid / other-system / external 各至少规格要求条数。
|
||||
`audienceRoleIds` 对齐原 `roleIds`;无角色限制用 `[]`。
|
||||
`channels`:web=sent,移动三端=sent 或 pending,wechat_oa 按样例 sent/skipped。
|
||||
|
||||
- [ ] **Step 3: 导出**
|
||||
|
||||
```ts
|
||||
// index.ts
|
||||
export * from './types';
|
||||
export * from './resolve';
|
||||
export { ROUTE_RULES } from './routes';
|
||||
export { SEED_MESSAGES } from './seed';
|
||||
```
|
||||
|
||||
- [ ] **Step 4: 用真实 ROUTE_RULES 补一条集成断言(可选放 resolve.test)**
|
||||
|
||||
```ts
|
||||
import { ROUTE_RULES } from './routes';
|
||||
import { SEED_MESSAGES } from './seed';
|
||||
|
||||
it('种子 approval 在 web 可解析', () => {
|
||||
const msg = SEED_MESSAGES.find((m) => m.bizType === 'approval.arrive');
|
||||
expect(msg).toBeTruthy();
|
||||
const r = resolveMessageTarget(msg!, 'web', ROUTE_RULES);
|
||||
expect(r.ok).toBe(true);
|
||||
});
|
||||
```
|
||||
|
||||
Run: `npx vitest --run src/common/message-hub/resolve.test.ts` → PASS
|
||||
|
||||
- [ ] **Step 5: Commit**(用户要求时)
|
||||
|
||||
```bash
|
||||
git add src/common/message-hub/
|
||||
git commit -m "$(cat <<'EOF'
|
||||
feat(message-hub): add route table and wide-scope seed messages
|
||||
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 3: store + shell 适配
|
||||
|
||||
**Files:**
|
||||
- Create: `src/common/message-hub/store.ts`
|
||||
- Create: `src/common/message-hub/shell-adapter.ts`
|
||||
- Modify: `src/common/message-hub/index.ts`
|
||||
|
||||
- [ ] **Step 1: store**
|
||||
|
||||
```ts
|
||||
// 要点
|
||||
const STORAGE_KEY = 'oneos.message-hub.readAt.v1';
|
||||
// loadSeed(): HubMessage[] — 合并 SEED 与 localStorage 中的 readAt
|
||||
// markRead(id): void
|
||||
// unreadCount(messages, roleId?): number
|
||||
// listForRole(messages, roleId?): HubMessage[]
|
||||
// sort: 未读优先 → priority high → createdAt desc
|
||||
```
|
||||
|
||||
- [ ] **Step 2: shell-adapter**
|
||||
|
||||
```ts
|
||||
import type { ShellNoticeItem } from '../oneos-app-shell/notice-bridge';
|
||||
import type { HubMessage } from './types';
|
||||
import { resolveMessageTarget } from './resolve';
|
||||
import { ROUTE_RULES } from './routes';
|
||||
|
||||
export function toShellNoticeItem(msg: HubMessage): ShellNoticeItem {
|
||||
const web = resolveMessageTarget(msg, 'web', ROUTE_RULES);
|
||||
return {
|
||||
id: msg.id,
|
||||
type: msg.priority === 'high' && msg.bizType.startsWith('urge') ? '催办提醒' : msg.bizTag,
|
||||
bizTag: msg.bizTag,
|
||||
title: msg.title,
|
||||
summary: msg.summary,
|
||||
detail: msg.detail,
|
||||
time: msg.createdAt.replace('T', ' ').slice(0, 16),
|
||||
read: !!msg.readAt,
|
||||
href: web.ok && web.uri.startsWith('/') ? web.uri : undefined,
|
||||
taskId: msg.bizId,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
注意:铃铛点击按规格**只打开详情、不在行上直跳**;`href` 仍可供详情内「去处理」使用。`type === '催办提醒'` 用于外壳排序/标签,adapter 对 `urge.remind` 必须输出 `'催办提醒'`。
|
||||
|
||||
- [ ] **Step 3: 导出 store / adapter**
|
||||
|
||||
- [ ] **Step 4: Commit**(用户要求时)
|
||||
|
||||
---
|
||||
|
||||
### Task 4: message-center 原型 UI
|
||||
|
||||
**Files:**
|
||||
- Create: `src/prototypes/message-center/index.tsx`
|
||||
- Create: `src/prototypes/message-center/MessageCenterApp.tsx`
|
||||
- Create: `src/prototypes/message-center/styles/index.css`
|
||||
- 实现前 Read: `~/.agents/skills/ui-ux-pro-max/SKILL.md`,并跑
|
||||
`python3 ~/.agents/skills/ui-ux-pro-max/scripts/search.py "admin dashboard notification inbox" --design-system -p "OneOS message-center"`
|
||||
视觉对齐现有工作台,不用营销风。
|
||||
|
||||
- [ ] **Step 1: 入口**
|
||||
|
||||
```tsx
|
||||
/**
|
||||
* @name 消息中心
|
||||
*/
|
||||
import React from 'react';
|
||||
import { PrototypeAnnotationHost } from '../../common/prototype-annotation-host';
|
||||
import annotationSource from './annotation-source.json';
|
||||
import MessageCenterApp from './MessageCenterApp';
|
||||
import './styles/index.css';
|
||||
|
||||
export default function MessageCenterPage() {
|
||||
return (
|
||||
<>
|
||||
<MessageCenterApp />
|
||||
<PrototypeAnnotationHost source={annotationSource as any} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
(若项目 annotation 挂载方式与 fault-handling 不同,以同目录近期原型为准。)
|
||||
|
||||
- [ ] **Step 2: MessageCenterApp 行为清单(必须全部有)**
|
||||
|
||||
1. 左栏:全部/未读/已读;系统源多选或下拉;业务类型下拉;**端模拟器**五端
|
||||
2. 右栏列表:未读点、bizTag、title、时间
|
||||
3. 选中详情:detail、channels 触达态表、`resolve` 预览(随端模拟器变)、「去处理」
|
||||
4. 去处理:`markRead` → resolve →
|
||||
- `uri` 以 `/` 开头:`window.location.href` 或外壳 `postMessage({ type: 'ONEOS_SHELL_NAV', href })`(与工作台 `protoNav` 一致)
|
||||
- 否则:模态「将打开 {externalApp} / {uri}」(不 `window.open` scheme)
|
||||
- fail:页面内固定文案「当前端暂无可跳转目标」
|
||||
5. 触控/对比度遵循 ui-ux-pro-max;表格数字可用 tabular-nums
|
||||
|
||||
- [ ] **Step 3: 本地预览**
|
||||
|
||||
打开 `/prototypes/message-center`,手测:切换端模拟器预览变化;external 消息出示意模态;无 wechat 规则时提示不可跳。
|
||||
|
||||
- [ ] **Step 4: Commit**(用户要求时)
|
||||
|
||||
---
|
||||
|
||||
### Task 5: 业务规格 + AutoPRD + 标注
|
||||
|
||||
**Files:**
|
||||
- Create: `src/prototypes/message-center/.spec/route-resolve.md`(判定优先级表、前置条件、数据源、用户可见结果、种子 vs 未接 API)
|
||||
- Create: `src/prototypes/message-center/.spec/requirements-prd.md`(用户故事:起点→运作→闭环;摘要链到 route-resolve)
|
||||
- Create: `src/resources/prd/message-center-autoprd.md`(与 PRD 同步)
|
||||
- Create/Update: `annotation-source.json` 顶层 `directory.nodes` 含「产品需求说明(PRD)」全文
|
||||
|
||||
- [ ] **Step 1: 按 oneos-autoprd 写 PRD**(产品语言,不写文件路径堆砌)
|
||||
|
||||
- [ ] **Step 2: route-resolve.md 必须含**
|
||||
|
||||
| 优先级 | 条件 | 结果 |
|
||||
|--------|------|------|
|
||||
| 1 | 精确 source+bizType+client 且 template 非空 | 填充 URI |
|
||||
| 2 | template 空且 fallbackClient 有对应规则 | 用 fallback URI |
|
||||
| 3 | 否则 | 不可跳转文案 |
|
||||
|
||||
- [ ] **Step 3: 若存在脚本则运行**
|
||||
|
||||
`node scripts/sync-annotation-directory.mjs`(或项目内同等命令)
|
||||
|
||||
- [ ] **Step 4: Commit**(用户要求时)
|
||||
|
||||
---
|
||||
|
||||
### Task 6: 导航登记
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/prototypes/oneos-prototype-nav/nav-menu.json`(在「工作台」旁或系统能力区增加「消息中心」→ `prototypes/message-center`)
|
||||
- Run: `npm run nav:sync -- --prototype message-center --note "新增统一消息中心原型"`
|
||||
|
||||
- [ ] **Step 1: 加菜单项**
|
||||
- [ ] **Step 2: nav:sync**
|
||||
- [ ] **Step 3: 刷新原型导航页确认可见**
|
||||
- [ ] **Step 4: Commit**(用户要求时)
|
||||
|
||||
---
|
||||
|
||||
### Task 7: 工作台铃铛 + 外壳对接中枢
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/prototypes/oneos-web-workbench-new/components/WorkbenchPage.tsx`(及 NoticePanel 数据源)
|
||||
- Modify: `src/prototypes/oneos-web-workbench-new/data/notices.ts` — 改为从 hub re-export 适配函数,或标记 deprecated 并改调用方
|
||||
- Modify: `src/common/oneos-app-shell/ShellNoticeCenter.tsx`
|
||||
- 列表项点击:`onOpen` 打开详情(勿直接 `onHandle`)
|
||||
- 「查看全部」主按钮导航到 `/prototypes/message-center`
|
||||
- Modify: `.spec/notice-center.md` 注明数据源迁移至 message-hub
|
||||
- Update workbench AutoPRD 中通知章节(行为变更需 sync)
|
||||
|
||||
- [ ] **Step 1: Workbench 使用 `loadMessages` + `toShellNoticeItem` / 自有列表组件读 hub**
|
||||
- [ ] **Step 2: postNoticesSync 仍发 `ShellNoticeItem[]`(adapter 输出)**
|
||||
- [ ] **Step 3: 外壳「查看全部」→ message-center**
|
||||
- [ ] **Step 4: 手测:原型演示嵌入工作台时铃铛未读与中枢一致;查看全部进入消息中心**
|
||||
- [ ] **Step 5: Commit**(用户要求时)
|
||||
|
||||
---
|
||||
|
||||
### Task 8: 验收对照 + 收尾
|
||||
|
||||
- [ ] **Step 1: 对照规格 §10 验收清单逐条勾选**
|
||||
- [ ] **Step 2: `npx vitest --run src/common/message-hub/resolve.test.ts`**
|
||||
- [ ] **Step 3: 更新设计文档状态旁注明「已实现原型」(若本轮做完)**
|
||||
- [ ] **Step 4: 停止 brainstorm companion(可选)**
|
||||
`/Users/sylvawong/.agents/skills/brainstorming/scripts/stop-server.sh /Users/sylvawong/oneos1.2/.superpowers/brainstorm/82675-1784712939`
|
||||
|
||||
---
|
||||
|
||||
## Spec 覆盖自检
|
||||
|
||||
| 规格要求 | 任务 |
|
||||
|----------|------|
|
||||
| Message / Channel / RouteRule 模型 | Task 1–2 |
|
||||
| 本地路由 + 优先级 + 固定失败文案 | Task 1, 5 |
|
||||
| 五端 × 多系统种子与外部 A/B | Task 2 |
|
||||
| 消息中心 UI + 端模拟器 + 去处理 | Task 4 |
|
||||
| 铃铛快捷 + 查看全部 | Task 7 |
|
||||
| 独立中枢架构 | Task 1–4 |
|
||||
| .spec + AutoPRD + 标注 | Task 5 |
|
||||
| 导航登记 | Task 6 |
|
||||
| 不做真推送/真唤端 | Task 4 模态示意 |
|
||||
|
||||
无 TBD 占位;`resolveMessageTarget` / `HubMessage` / `ROUTE_RULES` 命名全计划一致。
|
||||
62
docs/superpowers/plans/2026-07-22-vehicle-fault-handling.md
Normal file
62
docs/superpowers/plans/2026-07-22-vehicle-fault-handling.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# 故障处置 Implementation Plan
|
||||
|
||||
> **For agentic workers:** Use inline execution in this session (user requested 执行). Steps use checkbox syntax.
|
||||
|
||||
**Goal:** 交付 `vehicle-fault-handling` 原型(列表+独立详情),共享故障数据驱动工作台预警与运维看板「故障登记」,并挂到 OneOS → 车辆运维 → 故障处置。
|
||||
|
||||
**Architecture:** `src/common/vehicle-fault/` 持有类型、种子、localStorage、时限/归档校验与统计聚合;原型页读写该模块;工作台 KPI / OpsCockpit 改读同一聚合。AI 上报无 UI,仅种子模拟待处理原始记录。
|
||||
|
||||
**Tech Stack:** React + Ant Design + TypeScript;`useHashPage`(list / detail / stats-placeholder / proof-placeholder);`PrototypeAnnotationHost`;localStorage。
|
||||
|
||||
**Spec:** `docs/superpowers/specs/2026-07-22-vehicle-fault-handling-design.md`
|
||||
|
||||
---
|
||||
|
||||
## File map
|
||||
|
||||
| Path | Responsibility |
|
||||
|------|----------------|
|
||||
| `src/common/vehicle-fault/types.ts` | 状态、附件、通知、FaultRecord |
|
||||
| `src/common/vehicle-fault/sla.ts` | 截止日、剩余天数、临期/逾期判定、归档硬门槛 |
|
||||
| `src/common/vehicle-fault/seed.ts` | 演示种子(含临期、逾期、待处理、处理中、挂起、已归档) |
|
||||
| `src/common/vehicle-fault/storage.ts` | load/save localStorage |
|
||||
| `src/common/vehicle-fault/stats.ts` | KPI 明细 + 看板 faultStats |
|
||||
| `src/common/vehicle-fault/notify.ts` | 短信/邮件模板渲染与演示发送记录 |
|
||||
| `src/common/vehicle-fault/index.ts` | 导出 |
|
||||
| `src/prototypes/vehicle-fault-handling/*` | UI:列表、详情、占位页、样式、PRD、标注 |
|
||||
| `src/prototypes/oneos-web-workbench-new/data/kpi.ts` 等 | 接入故障 KPI |
|
||||
| `src/prototypes/oneos-web-workbench-new/data/ops-cockpit.ts` + OpsCockpit | 故障登记同源统计 |
|
||||
| `src/prototypes/oneos-prototype-nav/nav-menu.json` | 车辆运维菜单 |
|
||||
|
||||
---
|
||||
|
||||
### Task 1: 共享数据模块
|
||||
|
||||
- [x] Create types, sla, seed, storage, stats, notify, index under `src/common/vehicle-fault/`
|
||||
|
||||
### Task 2: 故障处置原型 UI
|
||||
|
||||
- [x] list / detail / placeholders + PRD + annotation
|
||||
|
||||
### Task 3: 工作台接入
|
||||
|
||||
- [x] KPI + OpsCockpit 同源
|
||||
|
||||
### Task 4: 导航与收尾
|
||||
|
||||
- [x] sidebar + nav-menu 车辆运维 → 故障处置
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Spec coverage
|
||||
|
||||
| Spec 节 | Task |
|
||||
|---------|------|
|
||||
| §2 菜单/新原型 | 2, 4 |
|
||||
| §3 状态机 | 1, 2 |
|
||||
| §4 时限与模板 | 1 notify, 2 UI |
|
||||
| §5 列表+独立详情 | 2 |
|
||||
| §5.3 硬门槛 | 1 sla, 2 |
|
||||
| §6 工作台 | 3 |
|
||||
| 二期占位 | 2, 4 |
|
||||
@@ -0,0 +1,103 @@
|
||||
# 车辆采购合同 + 验车入库 Linear UI Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 按规格将采购合同、验车入库、外勤三端对齐 Linear 产品浅色(`--ln-*` / `#32a06e`)与 vm-page 壳层,一波交付,不改业务规则。
|
||||
|
||||
**Architecture:** PC 两原型继续引用 `vehicle-management/style.css`;列表改为筛选卡 + KPI + `OperationActions` + `TablePagination`;表单/详情用顶栏返回 + 分区卡片;外勤三端共享一份 `field-theme.css`(`--ln-*` 子集)并改各 `index.html` 内联色。业务仍走 `src/common/vehicle-purchase/*`。
|
||||
|
||||
**Tech Stack:** React + Ant Design + Lucide;vm-/ln- CSS;静态 HTML/JS 外勤页。
|
||||
|
||||
**Spec:** `docs/superpowers/specs/2026-07-22-vehicle-purchase-inspection-linear-ui-design.md`
|
||||
|
||||
---
|
||||
|
||||
## File map
|
||||
|
||||
| 文件 | 职责 |
|
||||
|------|------|
|
||||
| `vehicle-purchase-contract/VehiclePurchaseContractApp.tsx` | 列表壳、KPI、表单分区、主题色 |
|
||||
| `vehicle-purchase-contract/styles/index.css` | vpc 收敛到 vm/ln |
|
||||
| `vehicle-purchase-contract/DESIGN.md` | 声明设计基底 |
|
||||
| `vehicle-inspection/VehicleInspectionApp.tsx` | 同上(验车) |
|
||||
| `vehicle-inspection/styles/index.css` | vi 收敛 |
|
||||
| `vehicle-inspection/DESIGN.md` | 声明设计基底 |
|
||||
| `vehicle-inspection-*/field-theme.css`(新建,三端各一份或同源复制) | 外勤 Linear 浅色 token |
|
||||
| `vehicle-inspection-*/index.html` | 引用 theme、触控与对比度 |
|
||||
|
||||
---
|
||||
|
||||
### Task 1: 采购合同列表壳 + 主题色
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/prototypes/vehicle-purchase-contract/VehiclePurchaseContractApp.tsx`
|
||||
- Modify: `src/prototypes/vehicle-purchase-contract/styles/index.css`
|
||||
- Create: `src/prototypes/vehicle-purchase-contract/DESIGN.md`
|
||||
|
||||
- [ ] **Step 1:** `vmTheme.token.colorPrimary` 改为 `#32a06e`;`colorLink` 同步。
|
||||
- [ ] **Step 2:** 列表去掉 `vpc-header` h1/副标题;结构改为:
|
||||
- `vm-page vpc-page`
|
||||
- 筛选:`vm-filter-card` / 或 Card `title="筛选条件"` + 关键词/状态/审批 + 查询重置
|
||||
- KPI 四卡(草稿、审批中合集、已通过、已生成验车),可点驱动 filter
|
||||
- `vm-table-section`:右对齐「新建合同」;表格;`OperationActions` 替换散落链接(若尚未用)
|
||||
- `vm-table-footer` + `TablePagination`
|
||||
- [ ] **Step 3:** CSS 用 `var(--ln-*)` / `var(--vm-*)` 替换 `#10b981`、`#f8fafc` 等硬编码;保留审批 banner、表单 grid 类名但换 token。
|
||||
- [ ] **Step 4:** 写入 `DESIGN.md`:基底 = linear 产品浅色 + vm-shared。
|
||||
- [ ] **Step 5:** 浏览器打开 `/prototypes/vehicle-purchase-contract/` 目视:无大标题、主色绿、分页在底。
|
||||
|
||||
### Task 2: 采购合同创建/编辑/查看分区
|
||||
|
||||
**Files:**
|
||||
- Modify: `VehiclePurchaseContractApp.tsx`(create/edit/view 分支)
|
||||
- Modify: `styles/index.css`
|
||||
|
||||
- [ ] **Step 1:** 顶栏:返回 + 标题 + 主操作(保存/提交/关闭)。
|
||||
- [ ] **Step 2:** 表单/详情字段按规格五分区包进 `vpc-section` 卡片(主体 / 车型价格 / 分期 / 交付 / 附件质保)。
|
||||
- [ ] **Step 3:** 审批提示条用 `--ln-primary-soft` 背景;总价 `tabular-nums`。
|
||||
- [ ] **Step 4:** 目视创建页分区与返回可用。
|
||||
|
||||
### Task 3: 验车入库列表 + 详情
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/prototypes/vehicle-inspection/VehicleInspectionApp.tsx`
|
||||
- Modify: `src/prototypes/vehicle-inspection/styles/index.css`
|
||||
- Create: `src/prototypes/vehicle-inspection/DESIGN.md`
|
||||
|
||||
- [ ] **Step 1:** 同 Task1:主题色、去大标题、筛选卡、KPI(待验/验车中/已完成)、表格+分页、`OperationActions`。
|
||||
- [ ] **Step 2:** 详情:返回顶栏;摘要;外勤按钮(绑定 + open);车辆表;主操作右对齐。
|
||||
- [ ] **Step 3:** CSS 换 `--ln-*`;`DESIGN.md` 声明基底。
|
||||
- [ ] **Step 4:** 目视列表与详情;点小程序 URL 200。
|
||||
|
||||
### Task 4: 外勤三端 Linear 浅色
|
||||
|
||||
**Files:**
|
||||
- Create: `field-theme.css` 于 web(内容含 `:root` `--ln-primary` 等),复制到 miniprogram、app
|
||||
- Modify: 各 `index.html` link stylesheet;调整内联 style 引用 var
|
||||
- Modify: 如有冲突的 `app.js` 内联色则改为 class
|
||||
|
||||
- [ ] **Step 1:** 定义 `--ln-primary: #32a06e`、canvas、ink、muted、hairline、radius、error。
|
||||
- [ ] **Step 2:** 卡片/按钮/底栏用 token;触控按钮 min-height 44px;body ≥16px。
|
||||
- [ ] **Step 3:** 三端同步;curl 三个 index.html 为 200;目视一页。
|
||||
|
||||
### Task 5: 文档与验收
|
||||
|
||||
- [ ] **Step 1:** 若仅样式:PRD 可跳过全量;若分区标题有语义变化,轻量更新 `.spec/requirements-prd.md` 一句「UI 对齐 Linear 产品浅色」。
|
||||
- [ ] **Step 2:** 对照规格 §7 验收清单自检。
|
||||
- [ ] **Step 3:** 不自动 commit(除非用户要求)。
|
||||
|
||||
---
|
||||
|
||||
## Spec coverage
|
||||
|
||||
| 规格节 | Task |
|
||||
|--------|------|
|
||||
| §2 Linear 浅色 | 1–4 |
|
||||
| §3.1 合同 | 1–2 |
|
||||
| §3.2 验车 | 3 |
|
||||
| §3.3 外勤 | 4 |
|
||||
| §5 业务冻结 | 全程不改 common |
|
||||
| §7 验收 | 5 |
|
||||
|
||||
## Placeholder scan
|
||||
|
||||
无 TBD;提交步骤尊重用户「未要求不 commit」。
|
||||
716
docs/superpowers/plans/2026-07-25-autorodo-web.md
Normal file
716
docs/superpowers/plans/2026-07-25-autorodo-web.md
Normal file
@@ -0,0 +1,716 @@
|
||||
# AutoRDO Web 工作台 Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 落地 Axhub 原型 `autorodo-web`:粘贴素材 → 复制 AutoRDO 清洗提示词 → 粘回初稿 → 按需求分页确认待确认并回填描述 → 填写优先级/标签/提交部门/提交人 → 一键复制 YunxiaoPMapp 多条记录需求提示词。
|
||||
|
||||
**Architecture:** 纯函数放在原型内 `lib/`(解析初稿、出题回填、拼提示词、识别部门/提交人),UI 为三步工作台(React + OneOS V2 Token)。MVP 不连云效、不嵌 OCR/ASR;Cursor 往返靠剪贴板。预留 `agentAdapter` 接口形状供组织 Agent。
|
||||
|
||||
**Tech Stack:** React + TypeScript(Axhub Make 原型)、Vitest、OneOS V2(`oneos-ds-tokens.css` + `UIComponents` 按需)、`PrototypeAnnotationHost`。
|
||||
|
||||
**Spec:** [docs/superpowers/specs/2026-07-25-autorodo-web-design.md](../specs/2026-07-25-autorodo-web-design.md)
|
||||
|
||||
---
|
||||
|
||||
## 文件结构(锁定)
|
||||
|
||||
| 路径 | 职责 |
|
||||
|------|------|
|
||||
| `src/prototypes/autorodo-web/lib/types.ts` | 需求稿、待确认点、元数据、步骤状态类型 |
|
||||
| `src/prototypes/autorodo-web/lib/parseDraft.ts` | 解析粘回的 AutoRDO Markdown → `RequirementDraft[]` |
|
||||
| `src/prototypes/autorodo-web/lib/parseDraft.test.ts` | 解析单测 |
|
||||
| `src/prototypes/autorodo-web/lib/applyAnswer.ts` | 选择题/补充 → 回填描述、消待确认 |
|
||||
| `src/prototypes/autorodo-web/lib/applyAnswer.test.ts` | 回填单测 |
|
||||
| `src/prototypes/autorodo-web/lib/buildCleanPrompt.ts` | 步骤 1 清洗提示词 |
|
||||
| `src/prototypes/autorodo-web/lib/buildRecordPrompt.ts` | 步骤 3 YunxiaoPMapp 多条口令 |
|
||||
| `src/prototypes/autorodo-web/lib/buildRecordPrompt.test.ts` | 上报词单测 |
|
||||
| `src/prototypes/autorodo-web/lib/inferMeta.ts` | 从原文推断提交部门/提交人 |
|
||||
| `src/prototypes/autorodo-web/lib/inferMeta.test.ts` | 推断单测 |
|
||||
| `src/prototypes/autorodo-web/lib/agentAdapter.ts` | 预留 `clean` / `record` 接口类型(MVP 空实现) |
|
||||
| `src/prototypes/autorodo-web/lib/clipboard.ts` | `navigator.clipboard.writeText` 封装 |
|
||||
| `src/prototypes/autorodo-web/lib/pendingQuestions.ts` | 从「待确认」文案生成选择题选项(词典摘要常量) |
|
||||
| `src/prototypes/autorodo-web/components/StepPaste.tsx` | 步骤 1 UI |
|
||||
| `src/prototypes/autorodo-web/components/StepConfirm.tsx` | 步骤 2 UI |
|
||||
| `src/prototypes/autorodo-web/components/StepExport.tsx` | 步骤 3 UI |
|
||||
| `src/prototypes/autorodo-web/AutorodoWebApp.tsx` | 三步状态机主壳 |
|
||||
| `src/prototypes/autorodo-web/index.tsx` | 入口 `@name` + AnnotationHost |
|
||||
| `src/prototypes/autorodo-web/style.css` | 布局与触控样式 |
|
||||
| `src/prototypes/autorodo-web/annotation-source.json` | 标注目录 |
|
||||
| `src/prototypes/autorodo-web/.spec/requirements-prd.md` | AutoPRD |
|
||||
| `src/prototypes/autorodo-web/.spec/confirm-flow.md` | 确认与回填规则全文 |
|
||||
| `src/resources/prd/autorodo-web-autoprd.md` | PRD 副本(若项目惯例需要) |
|
||||
| 修改 `.axhub/make/project.json` | 注册原型(若 Make 未自动发现) |
|
||||
| 修改 `~/.cursor/skills/YunxiaoPMapp` + 项目内副本 | 记录需求解析四字段(Task 8,可同迭代或紧随) |
|
||||
|
||||
**不放入 `src/common/`**:逻辑仅本原型使用,避免污染公共层。
|
||||
|
||||
---
|
||||
|
||||
### Task 1: 类型 + parseDraft + 单测
|
||||
|
||||
**Files:**
|
||||
- Create: `src/prototypes/autorodo-web/lib/types.ts`
|
||||
- Create: `src/prototypes/autorodo-web/lib/parseDraft.ts`
|
||||
- Create: `src/prototypes/autorodo-web/lib/parseDraft.test.ts`
|
||||
|
||||
- [ ] **Step 1: 写入类型**
|
||||
|
||||
```ts
|
||||
// src/prototypes/autorodo-web/lib/types.ts
|
||||
export type Priority = '紧急' | '高' | '中' | '低';
|
||||
|
||||
export type RequirementMeta = {
|
||||
priority: Priority | '';
|
||||
tags: string[];
|
||||
submitDept: string;
|
||||
submitter: string;
|
||||
titleKind: '新增' | '优化' | '';
|
||||
};
|
||||
|
||||
export type PendingItem = {
|
||||
id: string;
|
||||
raw: string;
|
||||
question: string;
|
||||
options: string[];
|
||||
resolved: boolean;
|
||||
answer?: string;
|
||||
};
|
||||
|
||||
export type RequirementDraft = {
|
||||
index: number;
|
||||
title: string;
|
||||
description: string;
|
||||
pendings: PendingItem[];
|
||||
meta: RequirementMeta;
|
||||
confirmed: boolean;
|
||||
};
|
||||
|
||||
export type WizardStep = 1 | 2 | 3;
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 写失败单测(多条 + 待确认)**
|
||||
|
||||
```ts
|
||||
// src/prototypes/autorodo-web/lib/parseDraft.test.ts
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { parseAutorodoDraft } from './parseDraft';
|
||||
|
||||
const SAMPLE = `共 2 条
|
||||
|
||||
### 1
|
||||
## 原始诉求(AutoRDO)
|
||||
|
||||
**标题**:合同台账批量导出
|
||||
|
||||
**描述**:
|
||||
在租赁合同台账支持批量导出
|
||||
|
||||
待确认:
|
||||
- 导出范围未说明
|
||||
|
||||
### 2
|
||||
## 原始诉求(AutoRDO)
|
||||
|
||||
**标题**:证照到期提醒
|
||||
|
||||
**描述**:
|
||||
调整证照到期提醒口径
|
||||
|
||||
待确认:
|
||||
无
|
||||
`;
|
||||
|
||||
describe('parseAutorodoDraft', () => {
|
||||
it('splits multiple requirements and pending items', () => {
|
||||
const list = parseAutorodoDraft(SAMPLE);
|
||||
expect(list).toHaveLength(2);
|
||||
expect(list[0].title).toContain('合同台账');
|
||||
expect(list[0].pendings).toHaveLength(1);
|
||||
expect(list[0].pendings[0].raw).toContain('导出范围');
|
||||
expect(list[1].pendings).toHaveLength(0);
|
||||
expect(list[1].confirmed).toBe(true);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 跑测确认失败**
|
||||
|
||||
Run: `npx vitest run src/prototypes/autorodo-web/lib/parseDraft.test.ts`
|
||||
Expected: FAIL(模块不存在或 `parseAutorodoDraft` 未定义)
|
||||
|
||||
- [ ] **Step 4: 实现解析**
|
||||
|
||||
```ts
|
||||
// src/prototypes/autorodo-web/lib/parseDraft.ts
|
||||
import type { RequirementDraft, PendingItem, RequirementMeta } from './types';
|
||||
|
||||
const emptyMeta = (): RequirementMeta => ({
|
||||
priority: '',
|
||||
tags: [],
|
||||
submitDept: '',
|
||||
submitter: '',
|
||||
titleKind: '',
|
||||
});
|
||||
|
||||
function parsePendings(block: string, reqIndex: number): PendingItem[] {
|
||||
const m = block.match(/待确认[::]\s*([\s\S]*?)(?=\n###|\n##\s*原始诉求|$)/);
|
||||
if (!m) return [];
|
||||
const body = m[1].trim();
|
||||
if (!body || body === '无') return [];
|
||||
const lines = body
|
||||
.split('\n')
|
||||
.map((l) => l.replace(/^[-*•\d.、)\s]+/, '').trim())
|
||||
.filter(Boolean);
|
||||
return lines.map((raw, i) => ({
|
||||
id: `r${reqIndex}-p${i}`,
|
||||
raw,
|
||||
question: raw,
|
||||
options: [],
|
||||
resolved: false,
|
||||
}));
|
||||
}
|
||||
|
||||
export function parseAutorodoDraft(md: string): RequirementDraft[] {
|
||||
const parts = md.split(/(?=^###\s*\d+)/m).filter((p) => /原始诉求(AutoRDO)/.test(p) || /\*\*标题\*\*/.test(p));
|
||||
const chunks =
|
||||
parts.length > 0
|
||||
? parts
|
||||
: md.includes('**标题**')
|
||||
? [md]
|
||||
: [];
|
||||
|
||||
return chunks.map((chunk, index) => {
|
||||
const title = (chunk.match(/\*\*标题\*\*[::]\s*(.+)/)?.[1] ?? '').trim();
|
||||
const descMatch = chunk.match(/\*\*描述\*\*[::]\s*\n?([\s\S]*?)(?=\n待确认|$)/);
|
||||
const description = (descMatch?.[1] ?? '').trim();
|
||||
const pendings = parsePendings(chunk, index);
|
||||
return {
|
||||
index,
|
||||
title,
|
||||
description,
|
||||
pendings,
|
||||
meta: emptyMeta(),
|
||||
confirmed: pendings.length === 0,
|
||||
};
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 5: 跑测确认通过**
|
||||
|
||||
Run: `npx vitest run src/prototypes/autorodo-web/lib/parseDraft.test.ts`
|
||||
Expected: PASS
|
||||
|
||||
- [ ] **Step 6: Commit**(仅当用户要求提交时执行;否则跳过所有 Commit 步骤)
|
||||
|
||||
```bash
|
||||
git add src/prototypes/autorodo-web/lib/types.ts src/prototypes/autorodo-web/lib/parseDraft.ts src/prototypes/autorodo-web/lib/parseDraft.test.ts
|
||||
git commit -m "$(cat <<'EOF'
|
||||
feat(autorodo-web): add AutoRDO draft parser and types
|
||||
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: applyAnswer + pendingQuestions
|
||||
|
||||
**Files:**
|
||||
- Create: `src/prototypes/autorodo-web/lib/applyAnswer.ts`
|
||||
- Create: `src/prototypes/autorodo-web/lib/applyAnswer.test.ts`
|
||||
- Create: `src/prototypes/autorodo-web/lib/pendingQuestions.ts`
|
||||
|
||||
- [ ] **Step 1: 写回填单测**
|
||||
|
||||
```ts
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { applyPendingAnswer } from './applyAnswer';
|
||||
import type { RequirementDraft } from './types';
|
||||
|
||||
const base: RequirementDraft = {
|
||||
index: 0,
|
||||
title: '合同台账批量导出',
|
||||
description: '在租赁合同台账支持批量导出\n导出范围:待确认',
|
||||
pendings: [
|
||||
{
|
||||
id: 'r0-p0',
|
||||
raw: '导出范围未说明',
|
||||
question: '导出范围指什么?',
|
||||
options: ['当前筛选结果', '全部合同', '仅勾选行'],
|
||||
resolved: false,
|
||||
},
|
||||
],
|
||||
meta: { priority: '', tags: [], submitDept: '', submitter: '', titleKind: '' },
|
||||
confirmed: false,
|
||||
};
|
||||
|
||||
describe('applyPendingAnswer', () => {
|
||||
it('merges answer into description and marks pending resolved', () => {
|
||||
const next = applyPendingAnswer(base, 'r0-p0', '当前筛选结果');
|
||||
expect(next.pendings[0].resolved).toBe(true);
|
||||
expect(next.pendings[0].answer).toBe('当前筛选结果');
|
||||
expect(next.description).toContain('当前筛选结果');
|
||||
expect(next.description).not.toMatch(/导出范围:待确认/);
|
||||
expect(next.confirmed).toBe(true);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 跑测确认失败**
|
||||
|
||||
Run: `npx vitest run src/prototypes/autorodo-web/lib/applyAnswer.test.ts`
|
||||
Expected: FAIL
|
||||
|
||||
- [ ] **Step 3: 实现 applyAnswer + 简易出题**
|
||||
|
||||
```ts
|
||||
// applyAnswer.ts
|
||||
import type { RequirementDraft } from './types';
|
||||
|
||||
export function applyPendingAnswer(
|
||||
draft: RequirementDraft,
|
||||
pendingId: string,
|
||||
answer: string,
|
||||
): RequirementDraft {
|
||||
const pendings = draft.pendings.map((p) =>
|
||||
p.id === pendingId ? { ...p, resolved: true, answer: answer.trim() } : p,
|
||||
);
|
||||
const hit = draft.pendings.find((p) => p.id === pendingId);
|
||||
let description = draft.description;
|
||||
if (hit) {
|
||||
const label = hit.raw.replace(/未说明|待确认|不清楚/g, '').trim() || hit.raw;
|
||||
if (/待确认/.test(description)) {
|
||||
description = description.replace(/待确认/g, answer.trim());
|
||||
} else {
|
||||
description = `${description.replace(/\s+$/, '')}\n${label}:${answer.trim()}`;
|
||||
}
|
||||
}
|
||||
const confirmed = pendings.every((p) => p.resolved);
|
||||
return { ...draft, description, pendings, confirmed };
|
||||
}
|
||||
|
||||
// pendingQuestions.ts — MVP:关键词启发式;无匹配则「是 / 否 / 需补充」
|
||||
export function buildOptionsForPending(raw: string): { question: string; options: string[] } {
|
||||
if (/导出范围|范围/.test(raw)) {
|
||||
return {
|
||||
question: '「导出范围」指什么?',
|
||||
options: ['当前筛选结果', '全部数据', '仅勾选行'],
|
||||
};
|
||||
}
|
||||
if (/模块|归属/.test(raw)) {
|
||||
return {
|
||||
question: '归属哪个业务模块?',
|
||||
options: ['租赁合同管理', '车辆管理', '证照管理', '还车应结款'],
|
||||
};
|
||||
}
|
||||
return {
|
||||
question: raw.endsWith('?') || raw.endsWith('?') ? raw : `${raw}?`,
|
||||
options: ['确认按原文理解', '暂不纳入本需求', '需文字补充'],
|
||||
};
|
||||
}
|
||||
|
||||
export function enrichPendingsWithQuestions(draft: RequirementDraft): RequirementDraft {
|
||||
return {
|
||||
...draft,
|
||||
pendings: draft.pendings.map((p) => {
|
||||
const q = buildOptionsForPending(p.raw);
|
||||
return { ...p, question: q.question, options: q.options };
|
||||
}),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
在 `parseAutorodoDraft` 返回前对每条调用 `enrichPendingsWithQuestions`,或在 UI 粘回后统一 enrich(二选一,推荐 UI 粘回后调用,保持 parse 纯净)。
|
||||
|
||||
- [ ] **Step 4: 跑测确认通过**
|
||||
|
||||
Run: `npx vitest run src/prototypes/autorodo-web/lib/applyAnswer.test.ts`
|
||||
Expected: PASS
|
||||
|
||||
- [ ] **Step 5: Commit**(用户要求时)
|
||||
|
||||
---
|
||||
|
||||
### Task 3: inferMeta + buildCleanPrompt + buildRecordPrompt
|
||||
|
||||
**Files:**
|
||||
- Create: `src/prototypes/autorodo-web/lib/inferMeta.ts`
|
||||
- Create: `src/prototypes/autorodo-web/lib/inferMeta.test.ts`
|
||||
- Create: `src/prototypes/autorodo-web/lib/buildCleanPrompt.ts`
|
||||
- Create: `src/prototypes/autorodo-web/lib/buildRecordPrompt.ts`
|
||||
- Create: `src/prototypes/autorodo-web/lib/buildRecordPrompt.test.ts`
|
||||
- Create: `src/prototypes/autorodo-web/lib/clipboard.ts`
|
||||
- Create: `src/prototypes/autorodo-web/lib/agentAdapter.ts`
|
||||
|
||||
- [ ] **Step 1: inferMeta 单测**
|
||||
|
||||
```ts
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { inferSubmitMeta } from './inferMeta';
|
||||
|
||||
describe('inferSubmitMeta', () => {
|
||||
it('detects dept and person from free text', () => {
|
||||
const r = inferSubmitMeta('业务管理组张三反馈:合同导出不好用');
|
||||
expect(r.submitDept).toMatch(/业务/);
|
||||
expect(r.submitter).toContain('张三');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 实现 inferMeta**
|
||||
|
||||
```ts
|
||||
const DEPT_PATTERNS = [
|
||||
/(?:提交部门|部门)[::]\s*([^\s,,;;]+)/,
|
||||
/(业务管理组|产品部|安全部|运营部|财务部|技术部)/,
|
||||
];
|
||||
const PERSON_PATTERNS = [
|
||||
/(?:提交人|反馈人|提出人)[::]\s*([^\s,,;;]+)/,
|
||||
/@([\u4e00-\u9fa5]{2,4})/,
|
||||
/([\u4e00-\u9fa5]{2,4})反馈/,
|
||||
];
|
||||
|
||||
export function inferSubmitMeta(text: string): { submitDept: string; submitter: string } {
|
||||
let submitDept = '';
|
||||
let submitter = '';
|
||||
for (const re of DEPT_PATTERNS) {
|
||||
const m = text.match(re);
|
||||
if (m?.[1]) {
|
||||
submitDept = m[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (const re of PERSON_PATTERNS) {
|
||||
const m = text.match(re);
|
||||
if (m?.[1]) {
|
||||
submitter = m[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return { submitDept, submitter };
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: buildRecordPrompt 单测 + 实现**
|
||||
|
||||
```ts
|
||||
// buildRecordPrompt.test.ts
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { buildYunxiaoRecordPrompt } from './buildRecordPrompt';
|
||||
import type { RequirementDraft } from './types';
|
||||
|
||||
const one: RequirementDraft = {
|
||||
index: 0,
|
||||
title: '合同台账批量导出',
|
||||
description: '在租赁合同台账支持按筛选结果批量导出 Excel',
|
||||
pendings: [],
|
||||
meta: {
|
||||
priority: '中',
|
||||
tags: ['租赁合同'],
|
||||
submitDept: '产品部',
|
||||
submitter: '王冕',
|
||||
titleKind: '新增',
|
||||
},
|
||||
confirmed: true,
|
||||
};
|
||||
|
||||
describe('buildYunxiaoRecordPrompt', () => {
|
||||
it('includes priority tags dept submitter', () => {
|
||||
const text = buildYunxiaoRecordPrompt([one]);
|
||||
expect(text).toContain('YunxiaoPMapp');
|
||||
expect(text).toContain('记录需求:【新增】合同台账批量导出');
|
||||
expect(text).toContain('优先级=中');
|
||||
expect(text).toContain('标签=租赁合同');
|
||||
expect(text).toContain('提交部门=产品部');
|
||||
expect(text).toContain('提交人=王冕');
|
||||
expect(text).toContain('推进至=暂不推进');
|
||||
});
|
||||
|
||||
it('throws when meta incomplete', () => {
|
||||
expect(() =>
|
||||
buildYunxiaoRecordPrompt([{ ...one, meta: { ...one.meta, submitter: '' } }]),
|
||||
).toThrow(/提交人/);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
```ts
|
||||
// buildRecordPrompt.ts
|
||||
import type { RequirementDraft } from './types';
|
||||
|
||||
export function metaComplete(d: RequirementDraft): boolean {
|
||||
const m = d.meta;
|
||||
return Boolean(
|
||||
m.priority && m.tags.length > 0 && m.submitDept.trim() && m.submitter.trim() && m.titleKind,
|
||||
);
|
||||
}
|
||||
|
||||
export function buildYunxiaoRecordPrompt(drafts: RequirementDraft[]): string {
|
||||
for (const d of drafts) {
|
||||
if (!d.confirmed) throw new Error(`需求 ${d.index + 1} 仍有未确认项`);
|
||||
if (!metaComplete(d)) throw new Error(`需求 ${d.index + 1} 缺少优先级/标签/提交部门/提交人/类型`);
|
||||
}
|
||||
const lines = drafts.map((d) => {
|
||||
const title = `【${d.meta.titleKind}】${d.title.replace(/^【(?:新增|优化)】/, '')}`;
|
||||
const tags = d.meta.tags.join('、');
|
||||
return `记录需求:${title};描述=${d.description.replace(/\n/g, ' ')};优先级=${d.meta.priority};标签=${tags};提交部门=${d.meta.submitDept};提交人=${d.meta.submitter};推进至=暂不推进`;
|
||||
});
|
||||
return [
|
||||
'YunxiaoPMapp',
|
||||
'请按下列条目依次记录需求;每条保持独立,不要合并。',
|
||||
'',
|
||||
...lines,
|
||||
].join('\n');
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
// buildCleanPrompt.ts
|
||||
export function buildCleanPrompt(payload: {
|
||||
text: string;
|
||||
attachmentNames: string[];
|
||||
}): string {
|
||||
const files =
|
||||
payload.attachmentNames.length > 0
|
||||
? `附件:${payload.attachmentNames.join('、')}(请用多模态识读图/语音内容)`
|
||||
: '附件:无';
|
||||
return [
|
||||
'AutoRDO',
|
||||
'请按 AutoRDO 规则清洗下列素材:多条独立诉求拆成多份;提炼标题与书面描述;不确定处标「待确认」;描述无结尾句号。',
|
||||
files,
|
||||
'',
|
||||
'—— 素材开始 ——',
|
||||
payload.text.trim() || '(仅附件,无正文)',
|
||||
'—— 素材结束 ——',
|
||||
].join('\n');
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
// clipboard.ts
|
||||
export async function copyText(text: string): Promise<void> {
|
||||
await navigator.clipboard.writeText(text);
|
||||
}
|
||||
|
||||
// agentAdapter.ts
|
||||
export type CleanRequest = { text: string; attachmentNames: string[] };
|
||||
export type RecordRequest = { drafts: import('./types').RequirementDraft[] };
|
||||
|
||||
/** MVP:未接组织 Agent;后续替换实现即可 */
|
||||
export const agentAdapter = {
|
||||
async clean(_req: CleanRequest): Promise<null> {
|
||||
return null;
|
||||
},
|
||||
async record(_req: RecordRequest): Promise<null> {
|
||||
return null;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
- [ ] **Step 4: 跑全部 lib 单测**
|
||||
|
||||
Run: `npx vitest run src/prototypes/autorodo-web/lib`
|
||||
Expected: 全部 PASS
|
||||
|
||||
- [ ] **Step 5: Commit**(用户要求时)
|
||||
|
||||
---
|
||||
|
||||
### Task 4: 原型壳 + 步骤 1 UI
|
||||
|
||||
**Files:**
|
||||
- Create: `src/prototypes/autorodo-web/index.tsx`
|
||||
- Create: `src/prototypes/autorodo-web/AutorodoWebApp.tsx`
|
||||
- Create: `src/prototypes/autorodo-web/style.css`
|
||||
- Create: `src/prototypes/autorodo-web/components/StepPaste.tsx`
|
||||
- Create: `src/prototypes/autorodo-web/annotation-source.json`(先最小目录)
|
||||
- Modify: `.axhub/make/project.json`(若启动后未出现在列表则补注册)
|
||||
|
||||
前置:Read `src/resources/design-system/DESIGN.md`(Token、触控 ≥44px、禁止原生 select)。
|
||||
|
||||
- [ ] **Step 1: 入口与主壳骨架**
|
||||
|
||||
```tsx
|
||||
// index.tsx
|
||||
/**
|
||||
* @name AutoRDO 需求清洗工作台
|
||||
*/
|
||||
import './style.css';
|
||||
import '../../../resources/design-system/oneos-ds-tokens.css';
|
||||
import React from 'react';
|
||||
import { PrototypeAnnotationHost } from '../../common/prototype-annotation-host';
|
||||
import type { AnnotationSourceDocument } from '@axhub/annotation';
|
||||
import annotationSourceDocument from './annotation-source.json';
|
||||
import { AutorodoWebApp } from './AutorodoWebApp';
|
||||
|
||||
export default function AutorodoWebEntry() {
|
||||
return (
|
||||
<>
|
||||
<AutorodoWebApp />
|
||||
<PrototypeAnnotationHost
|
||||
source={annotationSourceDocument as AnnotationSourceDocument}
|
||||
options={{}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
`AutorodoWebApp`:左侧步骤 1/2/3;`step` state;步骤 1 渲染 `StepPaste`。
|
||||
|
||||
- [ ] **Step 2: StepPaste**
|
||||
|
||||
- contentEditable 或 textarea 接收粘贴;`onPaste` 收集 `clipboardData.files`(image/*、audio/*)为附件名列表(原型阶段可用 File.name,不上传)
|
||||
- 按钮「确认并复制清洗提示词」→ `buildCleanPrompt` + `copyText`;toast「已复制,请粘到 Cursor 跑 AutoRDO」
|
||||
- 可选 checkbox「粘贴后自动复制」(默认关)
|
||||
- 控件:优先 `V2` 封装;按钮 min-height 44px
|
||||
|
||||
- [ ] **Step 3: 本地预览**
|
||||
|
||||
Run: 打开 Make 预览 `/prototypes/autorodo-web`
|
||||
Expected: 能粘贴、点确认后剪贴板为 AutoRDO 提示词
|
||||
|
||||
- [ ] **Step 4: Commit**(用户要求时)
|
||||
|
||||
---
|
||||
|
||||
### Task 5: 步骤 2 确认 UI
|
||||
|
||||
**Files:**
|
||||
- Create: `src/prototypes/autorodo-web/components/StepConfirm.tsx`
|
||||
- Modify: `src/prototypes/autorodo-web/AutorodoWebApp.tsx`
|
||||
|
||||
- [ ] **Step 1: 粘回区 + 解析**
|
||||
|
||||
- textarea「粘回 AutoRDO 初稿」
|
||||
- 按钮「解析初稿」→ `parseAutorodoDraft` → `enrichPendingsWithQuestions` → 对每条 `inferSubmitMeta(description + title)` 预填 meta
|
||||
- Pill 切换需求 index
|
||||
|
||||
- [ ] **Step 2: 左右分栏确认**
|
||||
|
||||
- 左:标题(可编辑)+ 描述(只读展示实时稿)
|
||||
- 右:当前未解决 pending;单选 options;补充 input;「确认并下一题」调用 `applyPendingAnswer`
|
||||
- 元数据:优先级四选一;标签用可增删 chip(自由输入 MVP);提交部门/提交人 input;类型 新增/优化
|
||||
- 全部 confirmed 且 `metaComplete` 后可进步骤 3
|
||||
|
||||
- [ ] **Step 3: 手动验收路径**
|
||||
|
||||
1. 粘贴 Task1 SAMPLE 初稿
|
||||
2. 答完题后描述含答案且无「待确认」
|
||||
3. 填齐元数据
|
||||
|
||||
- [ ] **Step 4: Commit**(用户要求时)
|
||||
|
||||
---
|
||||
|
||||
### Task 6: 步骤 3 导出 + 样式打磨
|
||||
|
||||
**Files:**
|
||||
- Create: `src/prototypes/autorodo-web/components/StepExport.tsx`
|
||||
- Modify: `style.css`、`AutorodoWebApp.tsx`
|
||||
|
||||
- [ ] **Step 1: StepExport**
|
||||
|
||||
- 预览 `buildYunxiaoRecordPrompt(drafts)`
|
||||
- 「一键复制上报提示词」
|
||||
- 「复制定稿 Markdown」(输出多份已确认 `## 原始诉求(AutoRDO)`,待确认:无)
|
||||
- 错误态:捕获 throw,页面内提示缺哪条哪字段
|
||||
|
||||
- [ ] **Step 2: 响应式**
|
||||
|
||||
- ≤767px:步骤条顶置;确认区改为上下堆叠;触控 ≥44px;正文 ≥14px
|
||||
|
||||
- [ ] **Step 3: 预览验收**
|
||||
|
||||
全路径走通:粘贴 → 复制清洗词 →(模拟)粘回 SAMPLE → 确认 → 复制上报词,粘贴到文本编辑器检查字段齐全。
|
||||
|
||||
- [ ] **Step 4: Commit**(用户要求时)
|
||||
|
||||
---
|
||||
|
||||
### Task 7: AutoPRD + 标注 + 导航同步
|
||||
|
||||
**Files:**
|
||||
- Create: `src/prototypes/autorodo-web/.spec/confirm-flow.md`
|
||||
- Create: `src/prototypes/autorodo-web/.spec/requirements-prd.md`
|
||||
- Create: `src/resources/prd/autorodo-web-autoprd.md`(与 PRD 同步)
|
||||
- Modify: `annotation-source.json`(产品需求说明节点)
|
||||
|
||||
- [ ] **Step 1: 写 confirm-flow.md**
|
||||
|
||||
含:判定顺序表、前置条件、数据源(粘回 Markdown / 本地启发式选项)、用户可见结果、标明未接真 API。
|
||||
|
||||
- [ ] **Step 2: 写 requirements-prd.md**
|
||||
|
||||
按 oneos-autoprd 结构:总览/目标/边界/角色/用户故事(起点→运作→闭环)/验收;链到 `confirm-flow.md`。
|
||||
|
||||
- [ ] **Step 3: 同步标注与导航**
|
||||
|
||||
```bash
|
||||
npm run nav:sync -- --prototype autorodo-web --note "新增 AutoRDO 网页清洗与云效上报提示词工作台"
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Commit**(用户要求时)
|
||||
|
||||
---
|
||||
|
||||
### Task 8: YunxiaoPMapp 消费四字段(Skill 扩展)
|
||||
|
||||
**Files:**
|
||||
- Modify: `~/.claude/skills/YunxiaoPMapp/references/commands.md`(及项目 `.cursor` / `.claude` 同步副本)
|
||||
- Modify: YunxiaoPMapp `SKILL.md` 记录需求参数说明
|
||||
- 可选:`references/record-meta-fields.md` 新文件
|
||||
|
||||
- [ ] **Step 1: 文档约定口令字段**
|
||||
|
||||
在口令面增加:
|
||||
|
||||
```text
|
||||
记录需求:…;优先级=紧急|高|中|低;标签=…;提交部门=…;提交人=…;推进至=…
|
||||
```
|
||||
|
||||
说明:网页上报词已带齐时,**禁止**再 Plan 重复问这四项(除非缺省);缺省则仍问。
|
||||
|
||||
- [ ] **Step 2: 实现侧**
|
||||
|
||||
若现有 live 脚本已支持 priority/tag:把提交部门/提交人映射到云效字段(查 `runtime-ids.json`;未验证字段则先写入描述尾部 `提交部门/提交人`,并在文档标明「字段 ID 待验证」)。
|
||||
|
||||
- [ ] **Step 3: 与网页联调**
|
||||
|
||||
用步骤 3 复制出的提示词在 Cursor 跑一次「记录需求」(测试项目或 dry-run 策略按团队惯例)。
|
||||
|
||||
- [ ] **Step 4: Commit**(用户要求时)
|
||||
|
||||
---
|
||||
|
||||
## 规格覆盖自检
|
||||
|
||||
| Spec 要求 | Task |
|
||||
|-----------|------|
|
||||
| 粘贴文/图/语音 + 复制清洗词 | 4 |
|
||||
| 粘回初稿 + 分页确认 + 回填 | 1,2,5 |
|
||||
| 优先级/标签/部门/提交人 | 3,5,6 |
|
||||
| 一键 Yunxiao 多条口令 | 3,6 |
|
||||
| 预留组织 Agent | 3 `agentAdapter` |
|
||||
| AutoPRD / 业务规则文档 | 7 |
|
||||
| Yunxiao 消费四字段 | 8 |
|
||||
| 不直连云效 / 无 OCR | 全程遵守 |
|
||||
|
||||
---
|
||||
|
||||
## 执行说明
|
||||
|
||||
- 所有 **Commit 步骤默认跳过**,除非用户明确要求提交。
|
||||
- Task 8 可与 Task 4–7 并行由另一会话做;网页 MVP 以 Task 1–7 为可演示闭环(上报词已含四字段,即使 Skill 暂未写入云效自定义字段,口令仍可用于人工/后续 Skill)。
|
||||
|
||||
---
|
||||
|
||||
Plan complete and saved to `docs/superpowers/plans/2026-07-25-autorodo-web.md`.
|
||||
|
||||
**两种执行方式:**
|
||||
|
||||
1. **Subagent-Driven(推荐)** — 每任务开新子代理,任务间复核,迭代快
|
||||
2. **Inline Execution** — 本会话按 executing-plans 连续执行,设检查点
|
||||
|
||||
要哪一种?
|
||||
193
docs/superpowers/specs/2026-07-22-message-hub-design.md
Normal file
193
docs/superpowers/specs/2026-07-22-message-hub-design.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# 消息中枢(Message Hub)重构设计
|
||||
|
||||
> 日期:2026-07-22
|
||||
> 状态:已确认并完成首期原型(2026-07-22,分支 `feat/message-hub`)
|
||||
> 范围:产品架构规格 + Web 统一消息中心原型(宽首期)
|
||||
|
||||
## 1. 背景与问题
|
||||
|
||||
当前 OneOS 原型中的「消息/通知」能力偏弱,实质是工作台站内铃铛阅知(`oneos-web-workbench-new` + `oneos-app-shell` 桥),外加若干业务侧短信/邮件演示。缺少:
|
||||
|
||||
- 独立消息中心
|
||||
- Web / iOS / 安卓 / 鸿蒙 / 微信服务号的统一触达与跳转模型
|
||||
- 多系统消息源(OneOS、车辆数据中台、其他系统)的接入约定
|
||||
- 清晰的「详情 → 来源表单/办理页」深链规则(含外部端双 App)
|
||||
|
||||
本设计定义统一消息中枢,并指导首期 Web 原型落地。
|
||||
|
||||
## 2. 已确认产品决策
|
||||
|
||||
| 决策点 | 选择 |
|
||||
|--------|------|
|
||||
| 本轮交付 | 规格文档 + Web 统一消息中心原型;移动/服务号以路由表与示意为主,不接真推送/服务号 API |
|
||||
| 产品入口 | 独立「消息中心」菜单页 + 顶栏铃铛作为未读快捷入口(「查看全部」进入消息中心) |
|
||||
| 首期广度 | 宽首期:五端触达矩阵 + 多系统消息源样例 |
|
||||
| 跳转解析 | 消息只携带业务键;各端用**本地路由表**解析目标(不下发各端 URL) |
|
||||
| 消息与触达 | 一条业务事件 = 一条 Message;多通道(站内/推送/服务号)挂在同一条上 |
|
||||
| 外部双 App | 占位名 `external-app-a` / `external-app-b`,真名后续替换 |
|
||||
| 落地架构 | 独立消息中枢:`src/common/message-hub/` + 新原型 `message-center`;工作台铃铛改读中枢 |
|
||||
|
||||
## 3. 目标用户与核心任务
|
||||
|
||||
- **目标用户**:OneOS 内部运营/业务人员(Web 为主);五端与外部 App 在原型中用「端模拟器」与路由表示意。
|
||||
- **核心任务**:
|
||||
1. 在统一列表中看到来自多系统的待办/提醒类消息
|
||||
2. 打开详情理解上下文与通道触达状态
|
||||
3. 「去处理」按当前端解析并跳到来源办理页(或明确不可跳)
|
||||
|
||||
## 4. 范围
|
||||
|
||||
### 4.1 本轮做
|
||||
|
||||
- 统一 Message 模型、通道触达态、本地 RouteRule 与 `resolve()`
|
||||
- 新原型 `message-center`:筛选、列表、详情、端模拟器、去处理
|
||||
- 工作台/外壳铃铛对接同一中枢(旧 notices 迁移或适配)
|
||||
- 五端 × 多系统种子与路由表样例(含外部 App A/B 占位)
|
||||
- `.spec` 路由规则全文 + AutoPRD / 导航登记(实现轮)
|
||||
|
||||
### 4.2 本轮不做
|
||||
|
||||
- 真实推送 SDK、厂商通道、微信服务号模板下发
|
||||
- 跨端已读强一致、服务端已读同步
|
||||
- 外部 App 真唤端 / Universal Link 联调
|
||||
- 车辆中台真实事件流接入(仅占位样例)
|
||||
- 独立移动端/鸿蒙原生 UI 工程
|
||||
|
||||
## 5. 架构
|
||||
|
||||
```text
|
||||
业务系统(OneOS / vehicle-mid / other / external)
|
||||
│ 产生业务事件(原型内为种子写入)
|
||||
▼
|
||||
┌───────────────────┐
|
||||
│ message-hub │ Message 池 · ChannelDelivery · RouteRule · resolve()
|
||||
└─────────┬─────────┘
|
||||
│
|
||||
┌─────┴─────┐
|
||||
▼ ▼
|
||||
消息中心页 顶栏铃铛 / 外壳 bridge
|
||||
(完整 IA) (未读摘要 + 快捷)
|
||||
│
|
||||
▼
|
||||
resolve(client) → 原型内导航 / 深链示意 / 不可跳提示
|
||||
```
|
||||
|
||||
### 5.1 目录约定
|
||||
|
||||
| 路径 | 职责 |
|
||||
|------|------|
|
||||
| `src/common/message-hub/` | 类型、种子、路由表、resolve、读写状态(localStorage 可选用) |
|
||||
| `src/prototypes/message-center/` | 消息中心主 UI |
|
||||
| `src/prototypes/message-center/.spec/` | 路由规则、通道矩阵、验收 |
|
||||
| `src/common/oneos-app-shell/` | 铃铛桥升级为 Message 摘要同步(兼容旧字段可选) |
|
||||
| `src/prototypes/oneos-web-workbench-new/` | 铃铛数据源改为中枢 |
|
||||
|
||||
## 6. 数据模型
|
||||
|
||||
### 6.1 Message
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `id` | 稳定 ID |
|
||||
| `sourceSystem` | `oneos` \| `vehicle-mid` \| `other-system` \| `external` |
|
||||
| `bizType` | 如 `approval.arrive`、`urge.remind`、`contract.expire`、`fault.overdue`、`order.action` |
|
||||
| `bizId` | 来源业务主键 |
|
||||
| `title` / `summary` / `detail` | 展示文案 |
|
||||
| `priority` | 如 normal / high(催办类可 high) |
|
||||
| `createdAt` | ISO 时间 |
|
||||
| `readAt` | 可选;本地已读 |
|
||||
| `audience` | 角色/用户占位(原型可按角色过滤,对齐现工作台习惯) |
|
||||
| `channels` | `ChannelDelivery[]` |
|
||||
|
||||
### 6.2 ChannelDelivery
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `client` | `web` \| `ios` \| `android` \| `harmony` \| `wechat_oa` |
|
||||
| `status` | `pending` \| `sent` \| `failed` \| `skipped`(原型模拟) |
|
||||
| `updatedAt` | 可选 |
|
||||
|
||||
说明:通道状态表示「是否对该端做过触达尝试」的演示态,不是跳转 URL。
|
||||
|
||||
### 6.3 RouteRule
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `sourceSystem` | 与 Message 一致 |
|
||||
| `bizType` | 与 Message 一致 |
|
||||
| `client` | 目标端 |
|
||||
| `targetTemplate` | URI 模板,支持 `{bizId}` 等占位 |
|
||||
| `externalApp` | 可选:`external-app-a` \| `external-app-b` |
|
||||
| `label` | 人读说明 |
|
||||
|
||||
**解析优先级**
|
||||
|
||||
1. 精确匹配 `sourceSystem + bizType + client`
|
||||
2. 同系统同 `bizType` 的 fallback(如 `harmony` → `android` 模板,若配置了 fallback)
|
||||
3. 无规则 → 不跳转,UI 明确提示「当前端暂无可跳转目标」
|
||||
|
||||
**禁止**:根据标题猜路径;无规则时静默跳首页。
|
||||
|
||||
## 7. 交互与闭环
|
||||
|
||||
### 7.1 铃铛
|
||||
|
||||
- 展示未读数与最近 N 条
|
||||
- 点击单条:标已读并打开详情卡片(含「去处理」);不在列表行上直接跳转,避免未看清上下文就离开
|
||||
- 「查看全部」→ `/prototypes/message-center`
|
||||
|
||||
### 7.2 消息中心页
|
||||
|
||||
- 左:筛选(全部/未读/已读、系统源、业务类型)+ **端模拟器**(切换 `client`,影响解析预览与去处理)
|
||||
- 右:列表 + 详情(正文、通道触达态、解析预览、去处理)
|
||||
|
||||
### 7.3 去处理
|
||||
|
||||
1. 标记已读(本地)
|
||||
2. `resolve(message, simulatedClient)`
|
||||
3. 命中且为 Web 原型 path → 站内导航(直链或外壳 `ONEOS_SHELL_NAV`)
|
||||
4. 命中且为外部/原生 scheme → 展示示意面板(将打开哪一 App/URI),不真唤端
|
||||
5. 未命中 → Toast/详情内错误态,文案固定可验收
|
||||
|
||||
## 8. 种子与路由样例(宽首期)
|
||||
|
||||
消息源至少覆盖:
|
||||
|
||||
- **oneos**:审批到达、催办、合同/证照到期、账单、系统通知(从现有工作台 notices 映射迁入)
|
||||
- **vehicle-mid**:故障逾期、车辆状态事件各 ≥1
|
||||
- **other-system**:通用接入槽 ≥1
|
||||
- **external**:跳转 App A、App B 的操作类各 ≥1
|
||||
|
||||
五端:每条关键 `bizType` 在路由表中为 `web/ios/android/harmony/wechat_oa` 提供模板或显式 `skipped` 说明(如纯 Web 办理类在 wechat_oa 可 skipped + 文案)。
|
||||
|
||||
## 9. 视觉与设计基底
|
||||
|
||||
沿用现有 OneOS Web 管理端语言(工作台、vm 列表习惯、外壳顶栏铃铛),不另起营销风或新主题。实现前对照项目 UI 规范;复杂判定写入 `.spec`。
|
||||
|
||||
## 10. 验收重点
|
||||
|
||||
1. 消息中心可按系统源/已读态筛选,列表与详情一致
|
||||
2. 端模拟器切换后,同一条消息的解析预览随路由表变化
|
||||
3. 「去处理」仅在命中规则时跳转;未命中有明确提示
|
||||
4. 外部 App A/B 仅示意,不真唤端
|
||||
5. 铃铛未读数与中枢一致;「查看全部」进入消息中心
|
||||
6. 旧工作台通知种子可在中枢中看到对应映射条目
|
||||
7. 规格中路由优先级表与代码 `resolve()` 行为一致
|
||||
|
||||
## 11. 风险与后续
|
||||
|
||||
- 真名替换 `external-app-a/b` 时只改路由表与文案,不改模型
|
||||
- 接真 API 时 Message 写入改为服务端,客户端仍只持业务键 + 本地/下发的路由表副本
|
||||
- 跨端已读、推送回执可作为下一阶段,不阻塞本轮原型
|
||||
|
||||
## 12. 决策快照(对齐记录)
|
||||
|
||||
| 问题 | 用户选择 |
|
||||
|------|----------|
|
||||
| 交付深度 | 规格 + Web 消息中心原型 |
|
||||
| 与铃铛关系 | 独立消息中心 + 铃铛快捷 |
|
||||
| 首期广度 | 宽(五端 + 多系统) |
|
||||
| 跳转方式 | 业务键 + 本地路由表(由「服务端多 URL」改为此案) |
|
||||
| 消息与推送 | 一条事件多通道同一条消息 |
|
||||
| 外部 App | 占位 A/B |
|
||||
| 架构 | 独立 message-hub + message-center 原型 |
|
||||
@@ -0,0 +1,63 @@
|
||||
# OneOS 设计规范 v2 · 设计决策
|
||||
|
||||
| 项 | 内容 |
|
||||
|----|------|
|
||||
| 日期 | 2026-07-22 |
|
||||
| 状态 | 已落地文档包 |
|
||||
| 产物 | `src/resources/design-system/`(DESIGN.md + chapters/00–09 + tokens.json + oneos-ds-tokens.css) |
|
||||
|
||||
## 背景
|
||||
|
||||
既有 v1 规范仅覆盖中后台列表页(筛选 / KPI / 表 / 分页)。产品需要基于当前平台重做设计规范,约束 Web 与 App 全部页面的显示与组件,实现全站统一。
|
||||
|
||||
## 决策
|
||||
|
||||
### App 范围
|
||||
|
||||
**原生 App + 微信小程序 + H5 现场端**(三端全含),与仓库中 `vehicle-inspection-app` / `miniprogram` / `web` 及 PC 中后台并列。
|
||||
|
||||
### 文档策略
|
||||
|
||||
在现有 [`src/resources/design-system/`](../../src/resources/design-system/) **扩写为 v2**,不另建 `design-system-v2` 目录。
|
||||
|
||||
- 根 `DESIGN.md`:总览与导航
|
||||
- `chapters/00–09`:完整约束清单落地
|
||||
- v1 列表强制规则并入 `04-patterns.md`,并继续指向 `vm-shared/DESIGN.md`
|
||||
|
||||
### 主色
|
||||
|
||||
沿用原型现行 **`#32a06e`**(`vehicle-management` / `field-theme`)。
|
||||
`oneos-web-legacy` 的 `#10b981` 标为遗留,新页禁止。
|
||||
|
||||
### 暗色模式
|
||||
|
||||
本版明确 **仅浅色**;若未来需要,须先补映射表。
|
||||
|
||||
### 工程入口
|
||||
|
||||
- `tokens.json` schemaVersion **2**
|
||||
- 新增 `oneos-ds-tokens.css` 供非列表页与共享变量引用
|
||||
- 列表页仍强制 `vehicle-management/style.css` + 公共组件
|
||||
|
||||
## 章节结构
|
||||
|
||||
```text
|
||||
00 总则 → 01 Foundations → 02 Layout → 03 Components
|
||||
→ 04 Patterns → 05 Content → 06 A11y → 07 Platform
|
||||
→ 08 Tokens 附录 → 09 迁移检查清单
|
||||
```
|
||||
|
||||
编写优先级见 `PRIORITY.md`:Foundations / Tokens → Layout 模板 → Patterns → Components → 平台差异 → Content/A11y → 检查清单。
|
||||
|
||||
## 成功标准
|
||||
|
||||
- 任意新页可定位到唯一页面模板与 Token 来源
|
||||
- Web 列表验收项不弱于 v1
|
||||
- App/小程序/H5 有热区、安全区、导航对照表
|
||||
- AI 提示词指向 v2 章节
|
||||
|
||||
## 非目标(本轮)
|
||||
|
||||
- 不批量改既有业务页面样式代码
|
||||
- 不实现暗色主题
|
||||
- 不合并改造 legacy `oneos-tokens.css` 文件内容(仅在规范中标注弃用路径)
|
||||
@@ -0,0 +1,214 @@
|
||||
# 故障处置(车辆运维)设计规格
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| 日期 | 2026-07-22 |
|
||||
| 状态 | 已确认 |
|
||||
| 方案 | 方案一:新建原型 + 工作台同源数据 |
|
||||
| 原型 ID(拟定) | `vehicle-fault-handling` |
|
||||
| 菜单 | OneOS → 车辆运维 → 故障处置 |
|
||||
| 关联 | `oneos-web-workbench-new`(预警 KPI + 运维看板故障登记) |
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题与目标
|
||||
|
||||
运维需要承接 **AI 故障机器人**上报的原始故障(聊天摘要、图片、视频),在系统内完成处置、挂起与归档,并满足 **30 天闭环** 时限与催办。处置记录须足够详细,作为日后向整车厂索赔的**证据链**基础。
|
||||
|
||||
**本期目标**
|
||||
|
||||
1. 新建「故障处置」列表 + **独立详情页**,完成待处理 → 处理中 → 挂起 → 已归档。
|
||||
2. 证据链多附件与归档硬门槛。
|
||||
3. 时限与通知规则演示(含短信/邮件模板与发送记录,不接真实通道)。
|
||||
4. 工作台预警 KPI + 运维看板「故障登记」与本模块同口径。
|
||||
|
||||
**非目标(二期 / 占位)**
|
||||
|
||||
- AI 对话上报界面(机器人仅作数据来源)
|
||||
- 真实短信 / 邮件网关
|
||||
- 品牌 · 车型 · 部位 · 等级完整分类统计看板
|
||||
- 按品牌车型一键出具故障证明与自动分析结论(本期仅入口占位)
|
||||
|
||||
---
|
||||
|
||||
## 2. 信息架构
|
||||
|
||||
```text
|
||||
OneOS
|
||||
└── 车辆运维(新一级菜单)
|
||||
├── 故障处置 ← 本期主功能
|
||||
├── 分类统计 ← 二期占位
|
||||
└── 故障证明 ← 二期占位
|
||||
```
|
||||
|
||||
- 新建原型目录:`src/prototypes/vehicle-fault-handling/`
|
||||
- 不改造旧合包 `oneos-web-ops` 内「故障管理」页为唯一入口;旧页可暂并存,导航以新菜单为准。
|
||||
- AI 上报:无 UI;以种子数据模拟「已入库的待处理原始记录」。
|
||||
|
||||
---
|
||||
|
||||
## 3. 状态机
|
||||
|
||||
| 状态 | 进入条件 |
|
||||
|------|----------|
|
||||
| 待处理 | AI 上报后系统自动入库 |
|
||||
| 处理中 | 运维首次保存处置内容(可分次保存) |
|
||||
| 挂起 | 运维选择暂时挂起,**必须填写挂起原因** |
|
||||
| 已归档 | 通过归档硬门槛,完成闭环 |
|
||||
|
||||
**流转规则**
|
||||
|
||||
- `待处理` → 首次保存 → `处理中`
|
||||
- `待处理` / `处理中` → 挂起 → `挂起`
|
||||
- `挂起` → 恢复继续 → `处理中`
|
||||
- `处理中` → 归档校验通过 → `已归档`
|
||||
- **挂起不可直接归档**;须先恢复为处理中,补齐硬门槛后再归档
|
||||
|
||||
---
|
||||
|
||||
## 4. 时限规则(文档中的「SLA」含义)
|
||||
|
||||
此处 **SLA = 处理时效约定**,非另有系统模块:
|
||||
|
||||
- 时针从 **故障记录上报时刻** 起算,**30 个自然日内必须已归档**
|
||||
- **暂时挂起不停表**(挂起期间仍计入 30 天)
|
||||
|
||||
| 时机 | 条件 | 收件人 | 通道 | 频次 |
|
||||
|------|------|--------|------|------|
|
||||
| 临期 | 未归档,且剩余天数 ≤ 7(未逾期),进入临期窗口时触发 | 当前处理人;无人接手 → 运维主管 | 短信 + 邮件 | 进入临期窗口触发一次 |
|
||||
| 逾期升级 | 已超 30 天,仍未归档 | **固定运维主管** | 短信 + 邮件 | 逾期当天 1 次;之后 **每周 1 次**,直至归档 |
|
||||
|
||||
原型:展示「通知记录」列表与模板正文;标记「已发送(演示)」,不接真实通道。
|
||||
|
||||
### 4.1 通知模板
|
||||
|
||||
**临 7 天 · 短信**
|
||||
|
||||
```text
|
||||
【OneOS故障】${故障号} ${车牌/车型} 将于 ${截止日} 到期(剩7天)仍未归档,请尽快处置。详情见故障处置。
|
||||
```
|
||||
|
||||
**临 7 天 · 邮件**
|
||||
|
||||
- 标题:`【故障临期提醒】${故障号} 距闭环截止还剩 7 天`
|
||||
- 正文须含:故障号、车辆、上报时间、当前状态、截止日、处理人、系统链接
|
||||
|
||||
**超 30 天 · 短信**
|
||||
|
||||
```text
|
||||
【OneOS故障·逾期】${故障号} 已超 30 天未归档(状态:${状态}),请主管督促闭环。
|
||||
```
|
||||
|
||||
**超 30 天 · 邮件**
|
||||
|
||||
- 标题:`【故障逾期升级】${故障号} 已超过 30 天未归档`
|
||||
- 正文须含:上述字段 + 逾期天数、历史挂起原因摘要、末次催办时间
|
||||
|
||||
---
|
||||
|
||||
## 5. 页面结构
|
||||
|
||||
采用 **列表 + 独立详情页**(非抽屉)。
|
||||
|
||||
### 5.1 列表页
|
||||
|
||||
- 筛选:状态、等级、品牌/车型、临期、逾期
|
||||
- 搜索:故障号、车牌
|
||||
- 列:故障号/车辆、部位·等级、状态、剩余天数(或逾期天数)、操作「处置」
|
||||
- 临期 / 逾期视觉标识
|
||||
|
||||
### 5.2 详情页分区
|
||||
|
||||
1. **原始记录(只读)**:AI 聊天摘要、图、视频
|
||||
2. **处置主档**:故障时间、地点、部位、等级、处置结果、备注、关联车辆(品牌/车型/车牌)
|
||||
3. **证据链**:多附件(图片、视频、PDF、Word 等常用类型);可预览示意;记录文件名、类型、上传人、时间
|
||||
4. **挂起与通知**:挂起原因历史;短信/邮件发送记录
|
||||
5. **底栏**:保存(→ 处理中)· 挂起 · 归档(硬门槛)
|
||||
|
||||
### 5.3 归档硬门槛
|
||||
|
||||
必须全部满足方可归档:
|
||||
|
||||
- 故障时间、地点、部位、等级、处置结果
|
||||
- 至少 **1** 个证据附件
|
||||
- 备注选填
|
||||
|
||||
任一缺失:阻断归档并提示缺项。
|
||||
|
||||
---
|
||||
|
||||
## 6. 工作台接入
|
||||
|
||||
数据与 `vehicle-fault-handling` **同源**(本地共享种子 / `src/common` 模块,未接真实 API)。
|
||||
|
||||
### 6.1 欢迎区预警 KPI(运维角色可见;多角色并集规则沿用工作台现规)
|
||||
|
||||
| 指标 | 口径 | 点击 |
|
||||
|------|------|------|
|
||||
| 临 7 天未归档 | 未归档且剩余天数 ≤ 7 且未逾期 | 故障处置列表 · 临期筛选 |
|
||||
| 已超 30 天未归档 | 未归档且已过截止日 | 列表 · 逾期筛选 |
|
||||
| 待处理积压 | 状态 = 待处理 | 列表 · 待处理 |
|
||||
|
||||
### 6.2 运维看板「故障登记」
|
||||
|
||||
- 总数 = 全部故障记录(含已归档)
|
||||
- 已归档 = 状态为已归档
|
||||
- 闭环率 = 已归档 / 总数
|
||||
- 可辅显:挂起数、临期数
|
||||
- 可见性:主管/兼岗全量 + 按人筛;普通运维本人/本地区(沿用现有 `OpsCockpit` 规则)
|
||||
|
||||
---
|
||||
|
||||
## 7. 数据对象(摘要)
|
||||
|
||||
`FaultRecord` 主要字段:
|
||||
|
||||
- 标识:故障号、上报时间、截止时间、来源(AI)
|
||||
- 状态与处理人
|
||||
- 原始:聊天摘要、媒体列表
|
||||
- 处置:时间、地点、部位、等级、结果、备注、车辆引用
|
||||
- 证据附件列表、挂起历史、通知历史
|
||||
|
||||
二期统计 / 证明所需的品牌、车型、部位、等级字段在一期处置主档中已采集,证明生成逻辑本期不做。
|
||||
|
||||
---
|
||||
|
||||
## 8. 组件与实现边界(实现阶段指引)
|
||||
|
||||
| 单元 | 职责 | 依赖 |
|
||||
|------|------|------|
|
||||
| `vehicle-fault-handling` 原型 | 列表、详情、状态流转、证据链、通知演示 | 共享故障种子 |
|
||||
| 共享数据模块(如 `src/common/vehicle-fault/`) | 记录类型、状态派生、时限计算、看板/KPI 聚合 | 无真实 API |
|
||||
| `oneos-web-workbench-new` | KPI 瓦片 + OpsCockpit 故障列改读共享数据 | 共享模块 |
|
||||
| 导航 | `nav-menu.json` 增加车辆运维 / 故障处置;`nav:sync` | — |
|
||||
|
||||
错误处理:归档校验失败明确列出缺项;挂起无原因不可提交。
|
||||
|
||||
---
|
||||
|
||||
## 9. 已确认决策记录
|
||||
|
||||
| 决策点 | 选择 |
|
||||
|--------|------|
|
||||
| AI 端 | 仅数据来源,不做对话 UI |
|
||||
| 落地路径 | 方案一:新原型 + 工作台同源 |
|
||||
| 菜单 | 车辆运维 → 故障处置 |
|
||||
| 中间态名称 | 处理中 |
|
||||
| 挂起与时针 | 不停表 |
|
||||
| 临 7 天含义 | 未归档且剩余天数 ≤ 7(未逾期) |
|
||||
| 一期范围 | 处置闭环 + 证据链;统计/证明占位 |
|
||||
| 归档 | 硬门槛 |
|
||||
| 工作台 | 预警 + 看板都接 |
|
||||
| 临期收件人 | 处理人,无人接手→主管 |
|
||||
| 逾期 | 固定主管;当天 1 次 + 每周 1 次 |
|
||||
| 详情布局 | 列表 + 独立详情页 |
|
||||
|
||||
---
|
||||
|
||||
## 10. 验收重点(设计层)
|
||||
|
||||
1. 种子数据入库即为待处理;保存后为处理中;挂起必填原因;归档卡硬门槛。
|
||||
2. 列表可按临期/逾期筛选;详情可看原始记录与证据链。
|
||||
3. 通知记录可演示临期与逾期模板内容。
|
||||
4. 工作台运维角色可见三类故障预警;看板故障登记闭环率与模块数据一致。
|
||||
5. 菜单路径正确;二期入口为占位说明。
|
||||
@@ -0,0 +1,178 @@
|
||||
# 车辆采购合同 + 验车入库 · UI 对齐 Linear(产品浅色)设计规格
|
||||
|
||||
**日期:** 2026-07-22
|
||||
**状态:** 规格已确认 · UI 已按本规格落地(2026-07-22)
|
||||
**范围决议:** 全链路(PC 两端 + 外勤三端)· 一波交付 · 列表壳 vm-page · 设计基底 Linear 产品浅色
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
现有 `vehicle-purchase-contract`、`vehicle-inspection` 及根下迁入的外勤三端(`vehicle-inspection-{web,miniprogram,app}`)功能已通,但视觉与交互未对齐项目标准主题与列表壳规范:硬编码 Ant Design `#10b981`、自定义 `vpc-`/`vi-` 页头与筛选条、与车辆管理 / 保险采购等业务页不一致。
|
||||
|
||||
**目标:** 在**不改业务规则**的前提下,按 Linear 产品浅色 token + vm-page 壳层,一波重做 PC 列表/表单/详情与外勤三端视觉与布局,使采购→验车→外勤→入库链路观感统一、可验收。
|
||||
|
||||
**非目标:** 不改审批阈值、VIN 校验、拒收重交、入库桥、分期付款逻辑;不上 Linear 营销深色 + 薰衣草主色;不单独进导航的外勤页仍从验车详情链出。
|
||||
|
||||
---
|
||||
|
||||
## 2. 设计事实源(优先级)
|
||||
|
||||
| 优先级 | 来源 | 用途 |
|
||||
|--------|------|------|
|
||||
| 1 | `src/themes/linear/DESIGN.md` | 品牌与组件原则事实源(标准参考主题) |
|
||||
| 2 | `src/prototypes/vehicle-management/style.css` 中 `--ln-*` / `--vm-*` | **产品浅色落地**(inverse 白底 + 主色 `#32a06e`) |
|
||||
| 3 | `src/prototypes/vm-shared/DESIGN.md` | 列表壳结构:筛选卡、工具栏、分页、禁止重复大标题等 |
|
||||
| 4 | 既有参考页 | 保险采购 / 租赁合同列表与详情分区习惯 |
|
||||
|
||||
**明确采用的 Linear 落地方式(已确认):**
|
||||
选项 1 — Linear 产品浅色,与车辆管理一致;**不**采用官网深色 `#010102` + `#5e6ad2`。
|
||||
|
||||
**ConfigProvider:** `colorPrimary: '#32a06e'`(或读 CSS 变量等价),字体栈对齐 `--vm-font`(Inter + 系统/苹方)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 信息架构与页面结构
|
||||
|
||||
### 3.1 车辆采购合同(`vehicle-purchase-contract`)
|
||||
|
||||
**列表(默认)**
|
||||
|
||||
```text
|
||||
vm-page vpc-page
|
||||
├── 筛选卡(「筛选条件」):关键词、状态、审批类型;查询 / 重置
|
||||
├── KPI 行(可选可点筛选):草稿 / 待审或审批中 / 已通过 / 已生成验车
|
||||
└── vm-table-section
|
||||
├── 工具栏右对齐:新建合同
|
||||
├── 表格 + OperationActions(查看 / 编辑 / 提交审批 / 发起工单等既有动作)
|
||||
└── TablePagination
|
||||
```
|
||||
|
||||
- 列表页**禁止**独立 h1 大标题 + 功能说明副标题(侧栏已标明模块名)。
|
||||
- 金额、数量列使用 `tabular-nums` / `ln-numeric` 既有约定。
|
||||
|
||||
**创建 / 编辑 / 查看**
|
||||
|
||||
```text
|
||||
顶栏:返回列表 + 标题(新建/编辑/查看 + 合同编号)+ 主操作(保存草稿 / 提交 / 关闭)
|
||||
主体白底分区(hairline + radius-card):
|
||||
1. 合同主体(买/卖/丙方与角色)
|
||||
2. 车型与价格(型号编码、产地、单价数量、实时总价与审批类型提示条)
|
||||
3. 分期付款计划
|
||||
4. 交付与验车约定
|
||||
5. 质保 / 关联协议 / 附件
|
||||
```
|
||||
|
||||
- ≥500 万自动「非正常审批」提示条保留,样式用 `--ln-primary-soft` / success 语义,不用另套色板。
|
||||
- 查看态只读;草稿可编辑;状态驱动操作按钮与现逻辑一致。
|
||||
|
||||
### 3.2 验车入库(`vehicle-inspection`)
|
||||
|
||||
**列表**
|
||||
|
||||
```text
|
||||
vm-page vi-page
|
||||
├── 筛选卡:关键词、任务状态;查询 / 重置
|
||||
├── KPI:待验车 / 验车中 / 已完成
|
||||
└── 表格 + 操作(进入详情 / 结案等)+ TablePagination
|
||||
```
|
||||
|
||||
**详情**
|
||||
|
||||
```text
|
||||
顶栏:返回 + 任务编号/车型摘要 + 结案、入库等主操作
|
||||
├── 任务摘要(Descriptions / 分区字段,对齐交接验收表语境)
|
||||
├── 外勤入口:Web / 小程序 / APP(点击绑定 activeInspectionId 并打开 /prototypes/.../index.html)
|
||||
└── 车辆明细表(VIN、里程、电机号、状态、拒收原因、重交操作)
|
||||
```
|
||||
|
||||
### 3.3 外勤三端(同波)
|
||||
|
||||
| 原型路径 | 壳 |
|
||||
|----------|-----|
|
||||
| `src/prototypes/vehicle-inspection-web/` | Web 外勤 |
|
||||
| `src/prototypes/vehicle-inspection-miniprogram/` | 小程序壳 |
|
||||
| `src/prototypes/vehicle-inspection-app/` | APP 壳 |
|
||||
|
||||
- 视觉:Linear 浅色语义(主色绿、白/浅灰 canvas、hairline 卡片);字号 ≥16px;触控目标 ≥44px;`cursor-pointer`;尊重 `prefers-reduced-motion`。
|
||||
- 逻辑:继续共用 `field-core.js`;《车辆交接验收表》图例 √/N/×/O、双签、双角度照片、拒收重交**行为不变**。
|
||||
- 三端仅外框/底栏差异,表单与列表结构对齐,避免三套互不相干的样式常量。
|
||||
|
||||
---
|
||||
|
||||
## 4. 视觉与组件规则(摘要)
|
||||
|
||||
| 项 | 约定 |
|
||||
|----|------|
|
||||
| 主色 | `#32a06e`(`--ln-primary`) |
|
||||
| 画布 | `--ln-canvas-parchment` / `--vm-bg` |
|
||||
| 卡片面 | `--ln-surface-card` + `--ln-hairline` + radius 8/12 |
|
||||
| 正文/次要 | `--ln-ink` / `--ln-muted` |
|
||||
| 成功/警告/错误 | `--ln-success` / `--ln-warning` / `--ln-error` |
|
||||
| 焦点 | 控件边框改主色(vm-focus-border 模式),避免装饰性外发光 |
|
||||
| 图标 | Lucide/SVG,不用 emoji 作图标 |
|
||||
| 列表操作列 | `OperationActions` + 既有 `vm-operation-actions` |
|
||||
|
||||
---
|
||||
|
||||
## 5. 业务规则(本轮冻结,仅 UI)
|
||||
|
||||
以下保持现有实现与 `.spec` 文档,**本轮不改判定**:
|
||||
|
||||
- 合同金额 ≥ 500 万 → 非正常审批,否则正常
|
||||
- 1 合同 → 1 验车任务;明细按到车追加
|
||||
- VIN 17 位;交接验收表通过条件;拒收 → 重交 → 重验
|
||||
- localStorage 桥:`oneos.vp.*`(含 `activeInspectionId`)
|
||||
|
||||
若 UI 改动导致文案/验收描述变化,**同轮**按 oneos-autoprd 与业务逻辑文档化规则更新 PRD / annotation(纯样式可跳过全量重写;分区标题、状态文案有语义变化则更新)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 文件与依赖(实现边界)
|
||||
|
||||
**预期修改**
|
||||
|
||||
- `src/prototypes/vehicle-purchase-contract/VehiclePurchaseContractApp.tsx` + `styles/index.css`(收敛到 vm-/ln- 类,去掉重复页头)
|
||||
- `src/prototypes/vehicle-inspection/VehicleInspectionApp.tsx` + `styles/index.css`
|
||||
- 外勤三端 `index.html` / 内联或共享样式(可抽公共 CSS 片段到三端复制或单文件引用,以静态可访问为准)
|
||||
- 可选:各原型补 `DESIGN.md` 一页,声明「基底 = linear 产品浅色 + vm-shared」
|
||||
|
||||
**预期不改(除非发现硬编码色破坏一致性)**
|
||||
|
||||
- `src/common/vehicle-purchase/*` 业务逻辑
|
||||
- 审批 mock、工单预填、入库桥算法
|
||||
|
||||
**依赖:** 继续 `import '../vehicle-management/style.css'`;`TablePagination`;`OperationActions`;`PrototypeAnnotationHost`。
|
||||
|
||||
---
|
||||
|
||||
## 7. 验收要点
|
||||
|
||||
1. 两列表页:无重复大标题;筛选卡 +(有)KPI + 底部分页;主色为 `#32a06e`。
|
||||
2. 合同表单/详情:分区清晰;审批提示条可见且色板正确。
|
||||
3. 验车详情:外勤三按钮可打开 `/prototypes/vehicle-inspection-*/index.html` 且绑定当前任务。
|
||||
4. 外勤三端:交接验收表可填报;与 PC 同域 localStorage 互通。
|
||||
5. 对照车辆管理列表:间距、圆角、边框、字体观感一致(允许业务字段不同)。
|
||||
6. 对比度正文 ≥ 4.5:1;可点击元素有 pointer;外勤触控区达标。
|
||||
|
||||
---
|
||||
|
||||
## 8. 决议记录
|
||||
|
||||
| 项 | 选择 |
|
||||
|----|------|
|
||||
| 优化深度 | C 全链路(含外勤) |
|
||||
| 排期 | 一波做完 |
|
||||
| PC 路线 | A 严格对齐 vm-page |
|
||||
| Linear 落地 | 1 产品浅色(`--ln-*` / `#32a06e`) |
|
||||
| 产品确认草案 | 2026-07-22 认可 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 自我检查(写规格时)
|
||||
|
||||
- [x] 无 TBD 占位关键路径
|
||||
- [x] 未混用深色薰衣草与浅色绿主色
|
||||
- [x] 业务规则与 UI 边界写清
|
||||
- [x] 外勤 URL 与同波交付写清
|
||||
- [x] 与用户确认的 C / 一波 / A / Linear-1 一致
|
||||
@@ -90,7 +90,7 @@
|
||||
| 3 | 整单待审批 / 审批中 | 转交可用;运维费用只读;**不可**部门撤回改数 |
|
||||
| 4 | 新办理人要改费用(整单未在审批中) | 若段状态为已提交 → 先走运维部 **撤回**,再编辑保存/提交 |
|
||||
| 5 | 整单在审批中要改费用 | 先 **整单撤回**,再进入费用明细编辑 |
|
||||
| 6 | 整单审批完成 | 无转交按钮 |
|
||||
| 6 | 整单审批完成 | 无转交图标 |
|
||||
|
||||
### 3.5 原因
|
||||
|
||||
@@ -103,19 +103,21 @@
|
||||
|
||||
### 4.1 入口
|
||||
|
||||
费用明细页 → **运维部**卡片标题栏右侧:
|
||||
费用明细页 → **运维组**卡片标题栏:
|
||||
|
||||
| 场景 | 可见操作(在权限内) |
|
||||
|------|----------------------|
|
||||
| 整单可编 + 运维待提交 | 保存、提交、**转交** |
|
||||
| 整单可编 + 运维已提交 | 撤回、**转交** |
|
||||
| 整单待审批 / 审批中 | 费用只读;无保存/提交/撤回;办理人/主管可见 **转交** |
|
||||
| 整单审批完成 | 无转交 |
|
||||
| 整单可编 + 运维待提交 | 保存、提交;提交人姓名后 **转交图标** |
|
||||
| 整单可编 + 运维已提交 | 撤回;提交人姓名后 **转交图标** |
|
||||
| 整单待审批 / 审批中 | 费用只读;无保存/提交/撤回;提交人姓名后 **转交图标**(办理人/主管) |
|
||||
| 整单审批完成 | 无转交图标 |
|
||||
|
||||
交互:点击转交图标打开转交弹窗。**不提供**「转交记录」入口。
|
||||
|
||||
列表页:
|
||||
|
||||
- 待审批 / 审批中:**显示「费用明细」**(不限角色),与现网「隐藏」不同,以本规格为准
|
||||
- 运维组办理人展示随 `opsHandler` 更新
|
||||
- 待审批 / 审批中:**显示「费用明细」**(不限角色)
|
||||
- 运维组办理人展示随 `opsHandler` 更新
|
||||
- **不**增加列表「转交」操作、**不**做批量
|
||||
|
||||
### 4.2 转交弹窗
|
||||
@@ -131,9 +133,7 @@
|
||||
|
||||
### 4.3 转交记录
|
||||
|
||||
每笔至少记录:时间、操作人、原办理人、新办理人、原因、当时运维段状态、当时整单审批状态。
|
||||
|
||||
费用明细运维卡片提供「转交记录」入口(时间线或抽屉即可)。
|
||||
本期**不提供**转交记录查询 UI(无抽屉/时间线)。转交原因仍必填,用于确认弹窗与后台留痕(原型可不展示)。
|
||||
|
||||
---
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
| `opsHandler` | **当前办理人**(权威)。初始可由还车人 `returnPerson` 带入;转交只改本字段,**不改**历史还车人 |
|
||||
| `submitOperation.status` | 运维段提交状态(待提交 / 已提交等既有口径) |
|
||||
| `submitOperation.name` | **最近一次提交人**;转交不覆盖;新人再次提交时再更新 |
|
||||
| `opsTransferLogs[]` | 转交记录数组(见 4.3) |
|
||||
| `opsTransferLogs[]` | 可选后台留痕;**本期无查询 UI** |
|
||||
|
||||
列表「运维组」办理人解析:读 `opsHandler`,不再直接绑死 `returnPerson`。
|
||||
|
||||
@@ -169,9 +169,9 @@
|
||||
2. 已提交单可转交;新人可撤回后编辑再提交。
|
||||
3. 主管可代转「非本人」的运维段任务。
|
||||
4. 整单待审批 / 审批中:列表可进费用明细(不限角色);运维费用只读不可编;办理人/主管仍可转交;费用与审批流不变。
|
||||
5. 审批完成后无转交按钮。
|
||||
5. 审批完成后无转交图标。
|
||||
6. 不可转给自己或非运维人员;原因为空不可提交。
|
||||
7. 转交记录可查(时间、人、原因、状态快照)。
|
||||
7. 转交入口为提交人姓名后方图标;无「转交记录」入口。
|
||||
|
||||
---
|
||||
|
||||
|
||||
168
docs/superpowers/specs/2026-07-25-autorodo-web-design.md
Normal file
168
docs/superpowers/specs/2026-07-25-autorodo-web-design.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# AutoRDO Web 工作台 · 设计规格
|
||||
|
||||
**日期**:2026-07-25
|
||||
**状态**:已确认(2026-07-25)
|
||||
**范围**:网页粘贴与确认交互 + AutoRDO Skill 对齐 + YunxiaoPMapp 多条上报提示词生成
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标
|
||||
|
||||
为产品经理提供网页工作台:直接粘贴**文本 / 图片 / 语音**,经 Cursor + AutoRDO 清洗后,在网页内对待确认项做选择题确认,答案自动并入需求描述,最后**一键复制**可喂给 Cursor + **YunxiaoPMapp** 的多条「记录需求」提示词,实现快速批量建单。
|
||||
|
||||
不替代 AutoRDO / YunxiaoPMapp Skill;网页负责编排与确认交互,清洗与写云效仍由 Cursor Agent 执行(MVP)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 已确认决策
|
||||
|
||||
| 项 | 决策 |
|
||||
|---|---|
|
||||
| 形态 | 网页 + Skill **双轨** |
|
||||
| Agent | MVP = **Cursor Agent**;预留组织自建 Agent 接口 |
|
||||
| 多模态 | 网页粘贴展示;图/语音识读由 **Cursor 多模态**完成 |
|
||||
| 清洗往返 | Cursor 洗完后,把带「待确认」的初稿 **粘回网页** 再出题 |
|
||||
| 确认结构 | 按**需求条**分页;条内**逐点**选择题;选项外可输入补充 |
|
||||
| 回填 | 每确认一点 → **自动写入**该条描述,消掉对应待确认 |
|
||||
| 云效 | **不**直连云效;一键复制上报提示词 → Cursor 调 YunxiaoPMapp |
|
||||
| 元数据 | 每条含 **优先级、标签、提交部门、提交人**(部门/人可内容预填,可改) |
|
||||
|
||||
---
|
||||
|
||||
## 3. 端到端流程
|
||||
|
||||
```text
|
||||
① 网页文本域粘贴 文/图/语音(支持多行、编号列表、表格行、空行分段)
|
||||
↓ 确认(可配置为粘贴后自动)
|
||||
② 剪贴板 = AutoRDO 清洗提示词 → 粘到 Cursor 跑 AutoRDO
|
||||
↓
|
||||
③ 将初稿(含待确认)粘回网页步骤 2
|
||||
↓
|
||||
④ 按需求 1/N 分页;条内逐点选择题 + 可选补充输入
|
||||
→ 答案实时并入描述;填写优先级/标签/提交部门/提交人
|
||||
↓ 全部确认且元数据齐全
|
||||
⑤ 一键复制「YunxiaoPMapp 多条记录需求」提示词
|
||||
↓
|
||||
⑥ 粘到 Cursor → YunxiaoPMapp 按条创建多条云效需求
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 信息架构(三步工作台)
|
||||
|
||||
### 步骤 1 · 粘贴素材
|
||||
|
||||
- 统一粘贴区:文本 + 图片/语音附件芯片预览
|
||||
- 主操作:「确认并复制清洗提示词」(可选:粘贴后自动复制)
|
||||
- 清洗提示词须明示:调用 AutoRDO、多条拆解规则、图/语音由模型识读
|
||||
|
||||
### 步骤 2 · 确认待确认
|
||||
|
||||
- 粘回区:粘贴 Cursor 返回的 `## 原始诉求(AutoRDO)` 多份稿
|
||||
- 解析为需求列表;顶部 Pill:需求 1/N
|
||||
- 左:当前标题 + 描述(确认后实时回填高亮)
|
||||
- 右:当前待确认题(单选)+「选项不含时自行补充」输入框
|
||||
- 同页元数据(每条必填):
|
||||
- 优先级:紧急 / 高 / 中 / 低
|
||||
- 标签:云效模块标签(可多选;与 YunxiaoPMapp 标签口径对齐)
|
||||
- 提交部门:输入;若原文可识别则预填
|
||||
- 提交人:输入;若原文可识别则预填
|
||||
- 缺任一元数据 → 禁止进入步骤 3 的一键复制
|
||||
|
||||
### 步骤 3 · 上报云效
|
||||
|
||||
- 展示已生成的上报提示词预览
|
||||
- 主按钮:一键复制上报提示词
|
||||
- 次按钮:复制定稿 Markdown(可选)
|
||||
- 默认 `推进至=暂不推进`
|
||||
|
||||
---
|
||||
|
||||
## 5. 提示词契约
|
||||
|
||||
### 5.1 清洗提示词(步骤 1 → Cursor)
|
||||
|
||||
要点:
|
||||
|
||||
- 点名使用 `$AutoRDO`
|
||||
- 输入含粘贴的文本摘要 + 附件说明(图/语音文件名)
|
||||
- 要求:多条独立诉求拆成多份;不确定标「待确认」;标题+描述;无结尾句号
|
||||
- 输出格式对齐 AutoRDO Skill 的 `## 原始诉求(AutoRDO)`
|
||||
|
||||
### 5.2 上报提示词(步骤 3 → Cursor)
|
||||
|
||||
```text
|
||||
YunxiaoPMapp
|
||||
请按下列条目依次记录需求;每条保持独立,不要合并。
|
||||
|
||||
记录需求:【新增|优化】{标题};描述={已确认描述};优先级={紧急|高|中|低};标签={标签};提交部门={部门};提交人={提交人};推进至=暂不推进
|
||||
|
||||
记录需求:…(下一条)
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
- 一条需求一行(或一块)口令,便于 Skill 拆条
|
||||
- 描述已无「待确认」、无结尾句号
|
||||
- 标题含 `【新增】` / `【优化】`(确认阶段或清洗结果已定)
|
||||
- 网页不写云效;由 YunxiaoPMapp 在 Cursor 侧执行建单
|
||||
|
||||
> 注:当前 YunxiaoPMapp 口令面以标题/描述/推进至为主;网页侧**先行产出**优先级/标签/提交部门/提交人字段,便于 Skill 后续消费。若 Skill 尚未落这四字段的写入逻辑,实现阶段需同步扩展 YunxiaoPMapp「记录需求」解析(另项)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 与现有 Skill 对齐
|
||||
|
||||
| 能力 | 来源 | 网页职责 |
|
||||
|---|---|---|
|
||||
| 多条拆解、标题描述、待确认 | AutoRDO | 解析初稿、出题、回填 |
|
||||
| 选择题确认 | AutoRDO `confirm-pending` | 在网页复现同等交互,替代 Cursor Plan 点选 |
|
||||
| 模块/部门词典 | AutoRDO `oneos-domain` | 生成选项与标签候选时参照(实现时可内嵌摘要或提示词约束) |
|
||||
| 建单写云效 | YunxiaoPMapp | 仅生成口令;不直连 API |
|
||||
|
||||
预留接口(组织 Agent 阶段):
|
||||
|
||||
- `POST /clean` ← 素材 → 初稿(替代步骤 ② 人工往返)
|
||||
- `POST /record` ← 已确认多条 → 建单(替代步骤 ⑥)
|
||||
|
||||
MVP 不实现上述 API,只在代码边界留 adapter 形状。
|
||||
|
||||
---
|
||||
|
||||
## 7. 交付物(实现阶段)
|
||||
|
||||
1. Axhub 原型页(建议 id:`autorodo-web` 或等价命名)
|
||||
- OneOS V2 设计规范;PC + H5
|
||||
- 三步工作台 + 粘贴往返 + 确认 + 元数据 + 复制口令
|
||||
2. AutoRDO Skill:可选补充「网页往返」口令说明(不改变清洗规则)
|
||||
3. YunxiaoPMapp:扩展记录需求解析以消费 `优先级/标签/提交部门/提交人`(若尚未支持)
|
||||
4. 本规格对应实现计划(writing-plans)
|
||||
|
||||
---
|
||||
|
||||
## 8. 非目标(MVP)
|
||||
|
||||
- 网页直连云效 API
|
||||
- 网页内嵌 OCR/ASR
|
||||
- localhost 桥接 Cursor(自动少粘贴)
|
||||
- 完整 AutoPRD 十章生成
|
||||
|
||||
---
|
||||
|
||||
## 9. 验收要点
|
||||
|
||||
1. 粘贴多行/编号/表格/空行分段素材后,能复制出可用的 AutoRDO 清洗提示词
|
||||
2. 粘回含多条「待确认」的初稿后,按需求分页、条内逐题确认,描述实时更新
|
||||
3. 选项外补充可替换本题答案并回填描述
|
||||
4. 每条可填/预填提交部门、提交人,以及优先级、标签;缺一不可复制上报词
|
||||
5. 一键复制的上报提示词可直接粘到 Cursor,驱动 YunxiaoPMapp 多条建单(在 Skill 已支持对应字段的前提下)
|
||||
6. 页面不发起云效写操作
|
||||
|
||||
---
|
||||
|
||||
## 10. 开放项(实现前可再定)
|
||||
|
||||
- 原型正式目录名 / 导航挂载位置
|
||||
- 标签候选项是写死 catalog 摘要,还是自由输入 + Skill 侧校验
|
||||
- 「粘贴后自动复制清洗提示词」默认开或关
|
||||
- YunxiaoPMapp 四字段写入是否与本原型同迭代交付
|
||||
Reference in New Issue
Block a user