左帮右臂 P2 编码任务清单

左帮右臂 P2 编码任务清单

版本: V1.0

日期: 2026-06-24

对应需求: spec-p2.md

对应设计: design-p2.md

范围: P2 编码任务 T33-T45,共 13 个任务

总工时: 约 16.5 天(单人全栈)/ 约 6 天(3 条并行轨道)


1. 任务依赖关系总览

P2 任务依赖图(→ 表示依赖):

T33 ──────────────────────────────────────── (协作链可视化,独立)
T34 ──→ T35 ──→ (配额中间件集成)            (配额链路)
T34 ──→ T36 ──→ T45                         (配额管理链路)
T37 ──→ T38                                 (文章管理链路)
T39 ──────────────────────────────────────── (BOM循环可视化,独立)
T40 ──→ T41                                 (ASR降级链路)
T42 ──→ T43                                 (WebSocket网页端链路)
T42 ──→ T44                                 (WebSocket小程序链路)

并行轨道规划:

| 轨道 | 任务序列 | 预估工时 |

|------|---------|---------|

| 轨道 A(协作+可视化) | T33 → T39 | 3.5 天 |

| 轨道 B(配额+文章) | T34 → T35+T36 → T38+T45 | 6 天 |

| 轨道 C(ASR+WebSocket) | T42+T40 → T43+T44 → T41 | 6 天 |


2. 任务详细清单


T33. 协作链可视化组件 — CollaborationChainGraph.vue

  • 优先级: P2
  • 预估工时: 2 天
  • 依赖: T24(协作调度器)、T25(协作链 API)
  • 可并行: 是(与 T34/T37/T39/T40/T42 无依赖)

涉及文件

文件路径操作说明
src/components/digital-staff/CollaborationChainGraph.vue新增协作链流程图组件
src/views/DigitalStaff.vue修改集成协作链图到任务看板

编码步骤

  • [ ] T33.1 创建 src/components/digital-staff/CollaborationChainGraph.vue 组件骨架
  • 定义 Props: chain: Array<{ taskId, assignedTo, status, title, result }>, currentTaskId: string
  • 定义 Emits: node-click(nodeData)
  • 定义内部状态: hoveredNodeId: ref, autoRefreshTimer: ref
  • [ ] T33.2 实现 SVG 水平流程图布局算法 layoutChain(chain, currentTaskId)
  • 节点尺寸: 圆角矩形 180×60
  • 水平间距: 40px
  • 计算每个节点的 x/y 坐标
  • 标记 isCurrentstatusClass
  • [ ] T33.3 实现节点状态渲染与样式
  • completed → 绿色 ✅ (.node-completed)
  • running → 蓝色+脉冲动画 🔄 (.node-running)
  • pending → 灰色 ⏳ (.node-pending)
  • failed → 红色 ❌ (.node-failed)
  • 节点显示: 员工名称 + 任务状态 + 耗时
  • [ ] T33.4 实现连线渲染(带箭头的 SVG path)
  • 节点间使用贝塞尔曲线连接
  • 箭头指向下一个节点
  • 连线颜色跟随源节点状态
  • [ ] T33.5 实现交互功能
  • 点击节点 → emit('node-click', nodeData) → 显示任务详情面板
  • 鼠标悬停 → hoveredNodeId 更新 → 显示简要信息 tooltip
  • tooltip 内容: 任务描述、执行结果、耗时
  • [ ] T33.6 实现自动刷新机制
  • 当 chain 中有 running 状态节点时,每 5 秒轮询 GET /api/digital-staff/collaboration/chain/:taskId
  • 更新 chain 数据,流程图自动重渲染
  • 所有节点完成后停止轮询
  • 组件卸载时清除定时器
  • [ ] T33.7 实现异常场景处理
  • 协作链数据不完整(缺少 collaboration_chain 字段)→ 显示单节点视图 + "该任务无协作链信息"标注
  • API 超时(>5秒)→ 显示骨架屏 + 后台重试一次 + "加载失败,请重试"提示
  • [ ] T33.8 修改 src/views/DigitalStaff.vue 集成协作链图
  • 在任务看板区域添加 CollaborationChainGraph 组件
  • GET /api/digital-staff/collaboration/chain/:taskId 获取链路数据
  • 实现 showTaskDetail(nodeData) 方法展示任务详情面板
  • [ ] T33.9 前端构建与验证
  • Stop-Process -Name "node" 停止旧进程
  • npm run build 构建前端
  • 在数字员工页面触发协作链,确认流程图正确渲染
  • 确认节点状态颜色和动画正确
  • 点击节点确认显示任务详情
  • 协作链执行中确认自动刷新

验证方法

| 验证项 | 预期结果 |

|--------|---------|

| 协作链流程图渲染 | 10 节点以内渲染 <1秒 |

| 节点状态颜色 | completed=绿, running=蓝+脉冲, pending=灰, failed=红 |

| 点击节点交互 | 弹出任务详情面板 |

| 自动刷新 | 执行中每 5 秒更新,完成后停止 |

| 数据不完整 | 显示单节点+提示信息 |


T34. 租户配额后端服务 — tenant-quota-service.js

  • 优先级: P2
  • 预估工时: 1.5 天
  • 依赖: T09(租户中间件)、T15(数据库表)
  • 可并行: 是(与 T33/T37/T39/T40/T42 无依赖)

涉及文件

文件路径操作说明
server/services/tenant-quota-service.js新增租户配额后端服务
server/db-adapter.js修改新增 tenant_quotas 建表

编码步骤

  • [ ] T34.1 创建 server/services/tenant-quota-service.js 服务骨架
  • 定义 TenantQuotaService 类,单例模式
  • module.exports = new TenantQuotaService() 直接导出实例
  • 依赖: db-adapter(SQLite/MySQL 双后端)
  • 定义默认配额常量:
    const DEFAULT_QUOTAS = {
      maxParts: 10000,
      maxBoms: 1000,
      maxUsers: 50,
      maxStaffTasks: 5000
    }
    
  • [ ] T34.2 实现 ensureTable() — 建表
  • CREATE TABLE IF NOT EXISTS tenant_quotas(字段见 design-p2.md 3.2.1)
  • 创建索引 idx_tenant_quotas_enterprise
  • 在服务初始化时调用
  • [ ] T34.3 实现 checkQuota(enterpriseId, resourceType) — 配额检查
  • 查询 tenant_quotas 获取配额上限和当前数量
  • 无记录 → 使用 DEFAULT_QUOTAS 默认值
  • 计算使用率 usagePercent = current / max * 100
  • 返回 { allowed: boolean, current: number, max: number, warning: string|null, usagePercent: number }
  • allowed 判定: current < max
  • warning 判定: usagePercent >= 80"${resourceType}数量已达配额80%,请关注"
  • [ ] T34.4 实现 incrementUsage(enterpriseId, resourceType, delta = 1) — 使用量递增
  • UPDATE tenant_quotas SET current_{resourceType} = current_{resourceType} + delta WHERE enterprise_id = ?
  • 若行不存在 → INSERT 默认配额行 + increment
  • 使用 camelCase 命名: incrementUsage
  • [ ] T34.5 实现 syncQuotaUsage(enterpriseId) — 单租户同步
  • 统计实际 Part/BOM/User/StaffTask 数量(查询各业务表)
  • UPDATE tenant_quotas SET currentParts=..., currentBoms=..., currentUsers=..., currentStaffTasks=...
  • 若行不存在 → INSERT 默认配额行 + 实际数量
  • 日志: [Quota] 租户 ${enterpriseId} 配额同步完成: Parts=${n}, BOMs=${n}, Users=${n}, Tasks=${n}
  • [ ] T34.6 实现 syncAllQuotas() — 全量同步
  • 查询所有租户列表
  • 遍历执行 syncQuotaUsage
  • 启动时调用一次
  • 每日凌晨定时调用(使用 setInterval 模拟 cron)
  • [ ] T34.7 实现 getQuota(enterpriseId) — 获取配额信息
  • 查询 tenant_quotas 返回完整配额信息
  • 无记录 → 返回默认配额 + 当前使用量全为 0
  • [ ] T34.8 实现 updateQuota(enterpriseId, fields) — 修改配额上限
  • 验证 fields 中的值 > 0
  • UPDATE tenant_quotas SET maxParts=..., maxBoms=..., ... WHERE enterprise_id = ?
  • 若行不存在 → INSERT 新行
  • 记录审计日志: { action: 'quota_updated', enterprise_id, changes: fields }
  • [ ] T34.9 实现 getAllQuotas() — 管理员查看所有租户配额
  • SELECT * FROM tenant_quotas ORDER BY enterprise_id
  • 返回配额列表
  • [ ] T34.10 修改 server/db-adapter.js 新增建表语句
  • createDatabase() 中新增 tenant_quotas 建表 SQL
  • createDatabase() 中新增索引创建 SQL

验证方法

| 验证项 | 预期结果 |

|--------|---------|

| checkQuota 正常 | 返回 { allowed: true, current: N, max: N, warning: null } |

| checkQuota 超限 | 返回 { allowed: false, current: 10000, max: 10000, warning: "..." } |

| checkQuota 80%警告 | 返回 { allowed: true, warning: "Part数量已达配额80%..." } |

| incrementUsage | 调用后 current 值 +1 |

| syncQuotaUsage | 与实际数据一致 |

| 无配额记录 | 使用默认配额,不阻断 |


T35. 租户配额检查中间件集成

  • 优先级: P2
  • 预估工时: 1 天
  • 依赖: T34(配额服务需先就绪)
  • 可并行: 否(依赖 T34),但可与 T36 并行

涉及文件

文件路径操作说明
server/middleware/tenant-middleware.js修改新增 quotaGuard(resourceType)
server.js修改在创建类路由中增加配额检查

编码步骤

  • [ ] T35.1server/middleware/tenant-middleware.js 中新增 quotaGuard(resourceType) 方法
  • req.tenantContext.enterpriseId 获取租户 ID
  • req.tenantContext.role 获取用户角色
  • 调用 tenantQuotaService.checkQuota(enterpriseId, resourceType)
  • allowed === false 且非管理员 → 403 + 配额超限提示
    res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' })
    res.end(JSON.stringify({ success: false, error: `已达到${resourceType}配额上限(${result.max}),请联系管理员升级` }))
    
  • warning !== null → 在响应头中附加 X-Quota-Warning
  • 管理员角色跳过阻断(仅附加 X-Quota-Exceeded: true 警告头)
  • 注入 req.quotaResult = result
  • 调用 next() 继续处理
  • [ ] T35.2tenant-middleware.js 中导出 quotaGuard
  • 确保 module.exports 包含 quotaGuard
  • [ ] T35.3 修改 server.js — Part 创建路由增加配额检查
  • 在 Part 创建处理前调用 quotaGuard('parts')(req, res, () => { / 原有创建逻辑 / })
  • 在 Part 创建成功后调用 tenantQuotaService.incrementUsage(enterpriseId, 'parts')
  • [ ] T35.4 修改 server.js — BOM 创建路由增加配额检查
  • quotaGuard('boms') + incrementUsage('boms')
  • [ ] T35.5 修改 server.js — 用户创建路由增加配额检查
  • quotaGuard('users') + incrementUsage('users')
  • [ ] T35.6 修改 server.js — 数字员工任务创建路由增加配额检查
  • quotaGuard('staffTasks') + incrementUsage('staffTasks')
  • [ ] T35.7 实现配额超限审计日志
  • quotaGuard 中,当 allowed === false 时调用审计日志服务
  • logAudit({ action: 'quota_exceeded', enterprise_id: enterpriseId, resource_type: resourceType, current: result.current, max: result.max })
  • [ ] T35.8server.js 中引入配额服务
  • const tenantQuotaService = require('./server/services/tenant-quota-service')
  • const { quotaGuard } = require('./server/middleware/tenant-middleware')

验证方法

| 验证项 | 预期结果 |

|--------|---------|

| 配额超限阻断 | 租户达到上限后创建返回 403 |

| 80%警告 | 达到 80% 后响应头包含 X-Quota-Warning |

| 管理员跳过 | 管理员超限后创建成功,响应头含 X-Quota-Exceeded |

| 审计日志 | 配额超限事件记录到审计日志 |

| 创建后计数 | 创建成功后 current 值 +1 |


T36. 租户配额管理 API

  • 优先级: P2
  • 预估工时: 0.5 天
  • 依赖: T34(配额服务需先就绪)
  • 可并行: 可与 T35 并行

涉及文件

文件路径操作说明
server/routes/admin-quota.js新增配额管理 API 路由
server.js修改注册路由

编码步骤

  • [ ] T36.1 创建 server/routes/admin-quota.js 路由文件
  • 导出 handleAdminQuotaRoute(req, res, pathname, query, bodyStr)
  • module.exports = { handleAdminQuotaRoute }
  • [ ] T36.2 实现 GET /api/admin/quotas — 所有租户配额列表
  • 验证管理员角色: req.userRole === 'admin',否则返回 403
  • 调用 tenantQuotaService.getAllQuotas()
  • 返回 { success: true, data: { quotas: [...] } }
  • [ ] T36.3 实现 GET /api/admin/quotas/:enterpriseId — 指定租户配额
  • 验证管理员角色
  • 从 pathname 解析 enterpriseId
  • 调用 tenantQuotaService.getQuota(enterpriseId)
  • 返回 { success: true, data: { enterpriseId, maxParts, currentParts, ... } }
  • [ ] T36.4 实现 PUT /api/admin/quotas/:enterpriseId — 修改配额上限
  • 验证管理员角色
  • 使用 collectBody(req) 读取请求体
  • 解析 body: { maxParts?, maxBoms?, maxUsers?, maxStaffTasks? }
  • 调用 tenantQuotaService.updateQuota(enterpriseId, fields)
  • 记录审计日志
  • 返回 { success: true }
  • [ ] T36.5 实现 POST /api/admin/quotas/init — 批量初始化默认配额
  • 验证管理员角色
  • 使用 collectBody(req) 读取请求体
  • 调用 tenantQuotaService.initDefaultQuotas()
  • 返回 { success: true, data: { initialized: N } }
  • [ ] T36.6 实现 POST /api/admin/quotas/:enterpriseId/sync — 手动同步配额
  • 验证管理员角色
  • 使用 collectBody(req) 读取请求体
  • 调用 tenantQuotaService.syncQuotaUsage(enterpriseId)
  • 返回 { success: true, data: { synced: true } }
  • [ ] T36.7 修改 server.js 注册路由
  • const adminQuotaRoutes = require('./server/routes/admin-quota')
  • handleRequest 中:
    if (pathname.startsWith('/api/admin/quotas')) {
      return adminQuotaRoutes.handleAdminQuotaRoute(req, res, pathname, query, bodyStr)
    }
    

验证方法

| 验证项 | 预期结果 |

|--------|---------|

| 获取配额列表 | GET /api/admin/quotas 返回所有租户配额 |

| 修改配额上限 | PUT /api/admin/quotas/:id 修改后立即生效 |

| 非管理员访问 | 返回 403 Forbidden |

| 批量初始化 | 为无配额记录的租户创建默认配额 |

| 手动同步 | 同步后 current 值与实际数据一致 |


T37. 已发布文章后端 — published-articles 服务与 API

  • 优先级: P2
  • 预估工时: 1.5 天
  • 依赖: T11(微信环境变量统一)、T31(发布重试)
  • 可并行: 是(与 T33/T34/T39/T40/T42 无依赖)

涉及文件

文件路径操作说明
server/services/published-article-service.js新增已发布文章服务
server/services/wechat-publish.js修改发布成功后写入记录
server/routes/content-api.js修改新增已发布文章 API
server/db-adapter.js修改新增 published_articles 建表

编码步骤

  • [ ] T37.1 创建 server/services/published-article-service.js 服务骨架
  • 定义 PublishedArticleService 类,单例模式
  • module.exports = new PublishedArticleService() 直接导出实例
  • 依赖: db-adapter
  • [ ] T37.2 实现 ensureTable() — 建表
  • CREATE TABLE IF NOT EXISTS published_articles(字段见 design-p2.md 3.2.2)
  • 创建索引 idx_published_articles_enterpriseidx_published_articles_status
  • [ ] T37.3 实现 recordPublish(data) — 发布成功后记录
  • 参数: { articleId, publishId, mediaId, title, publishTime, publishUrl, status, enterpriseId }
  • INSERT INTO published_articles (article_id, publish_id, media_id, title, publish_time, publish_url, status, enterprise_id) VALUES (...)
  • 日志: [PublishedArticle] 记录发布: ${title}, publishId=${publishId}
  • [ ] T37.4 实现 getPublishedArticles(filters) — 分页查询
  • 参数: { page, pageSize, enterpriseId, status }
  • SELECT * FROM published_articles WHERE enterprise_id = ? AND status = ? LIMIT ? OFFSET ?
  • 返回 { items: [...], total, page, pageSize }
  • [ ] T37.5 实现 getPublishedArticle(id) — 单条记录
  • SELECT * FROM published_articles WHERE id = ?
  • 返回完整发布记录
  • [ ] T37.6 实现 updatePublishStatus(id, status, extra) — 更新发布状态
  • UPDATE published_articles SET status = ?, retry_count = retry_count + 1, updated_at = ? WHERE id = ?
  • extra 可包含 error 信息等
  • 日志: [PublishedArticle] 状态更新: id=${id}, status=${status}
  • [ ] T37.7 修改 server/services/wechat-publish.js — 发布成功后写入记录
  • publishArticle() 函数末尾,发布成功后:
    try {
      const publishedArticleService = require('./published-article-service')
      await publishedArticleService.recordPublish({
        articleId: options.articleId || '',
        publishId: publishResult.publishId,
        mediaId: draft.mediaId,
        title,
        publishTime: new Date().toISOString(),
        publishUrl: '',
        status: 'published',
        enterpriseId: options.enterpriseId || 'default'
      })
    } catch (e) {
      console.error('[WeChat] 发布记录保存失败:', e.message)
    }
    
  • 发布失败后:
    try {
      const publishedArticleService = require('./published-article-service')
      await publishedArticleService.updatePublishStatus(options.articleId, 'failed', { error: publishResult.error })
    } catch (e) {}
    
  • [ ] T37.8 修改 server/routes/content-api.js — 新增已发布文章 API
  • GET /api/content/published-articles — 已发布文章列表
  • 解析 query 参数: page, pageSize, enterpriseId, status
  • 调用 publishedArticleService.getPublishedArticles(filters)
  • GET /api/content/published-articles/:id — 单条发布记录
  • 从 pathname 解析 id
  • 调用 publishedArticleService.getPublishedArticle(id)
  • [ ] T37.9 修改 server/db-adapter.js 新增建表语句
  • createDatabase() 中新增 published_articles 建表 SQL
  • createDatabase() 中新增索引创建 SQL

验证方法

| 验证项 | 预期结果 |

|--------|---------|

| 发布成功记录 | published_articles 表有新记录 |

| 发布失败记录 | 状态标记为 failed |

| 文章列表查询 | GET /api/content/published-articles 返回分页列表 |

| 单条记录查询 | GET /api/content/published-articles/:id 返回详情 |

| 记录保存失败 | 文章已发布但记录缺失,日志记录错误 |


T38. 已发布文章前端管理界面

  • 优先级: P2
  • 预估工时: 1 天
  • 依赖: T37(已发布文章 API 需先就绪)
  • 可并行: 否(依赖 T37)

涉及文件

文件路径操作说明
src/views/ContentManager.vue修改增加"已发布"标签页
src/services/api.js修改新增已发布文章 API 调用

编码步骤

  • [ ] T38.1 修改 src/views/ContentManager.vue — 增加"已发布"标签页
  • 在现有标签页(生成 | 草稿 | 设置)后新增"已发布"标签页
  • 使用 Vue 3 Composition API 风格
  • [ ] T38.2 实现已发布文章列表 UI
  • 表格列: 标题、发布时间、发布状态、操作
  • 状态标记: 🟢已发布(published) / 🟡发布中(publishing) / 🔴发布失败(failed)
  • 空状态提示: "暂无已发布文章"
  • [ ] T38.3 实现操作按钮
  • "查看链接" → window.open(publishUrl, '_blank') 新窗口打开微信文章
  • "重新发布" → 仅对 failed 状态显示,调用发布 API
  • [ ] T38.4 实现分页和搜索功能
  • 分页组件: 上一页/下一页/页码跳转
  • 搜索: 按标题关键词搜索
  • 筛选: 按发布状态筛选
  • [ ] T38.5 修改 src/services/api.js — 新增已发布文章 API 调用
  • getPublishedArticles(params)GET /api/content/published-articles
  • getPublishedArticle(id)GET /api/content/published-articles/:id
  • [ ] T38.6 添加浏览器 console 详细日志
  • 列表加载: console.log('[ContentManager] 已发布文章加载:', data)
  • 操作日志: console.log('[ContentManager] 查看链接:', publishUrl)
  • [ ] T38.7 前端构建与验证
  • Stop-Process -Name "node" 停止旧进程
  • npm run build 构建前端
  • 打开内容管理页面,切换到"已发布"标签页
  • 确认文章列表正确显示
  • 点击"查看链接"确认新窗口打开
  • 发布失败的文章确认显示"重新发布"按钮

验证方法

验证项预期结果
已发布标签页切换后显示文章列表
状态标记published=🟢, publishing=🟡, failed=🔴
查看链接新窗口打开微信文章
重新发布仅 failed 状态显示按钮
分页搜索功能正常

T39. BOM 循环依赖可视化增强

  • 优先级: P2
  • 预估工时: 1.5 天
  • 依赖: T22(BomTreeGraph)、T07(BOM 导入)
  • 可并行: 是(与 T33/T34/T37/T40/T42 无依赖)

涉及文件

文件路径操作说明
src/components/bom/BomTreeGraph.vue修改增加循环依赖高亮
server/services/bom-import-service.js修改返回循环路径数据
src/views/BomAssistant.vue修改传递 cyclePaths 到 BomTreeGraph

编码步骤

  • [ ] T39.1 修改 BomTreeGraph.vue — 新增 Props
  • 新增 prop cyclePaths: Array> — 循环路径数组 [[nodeId1, nodeId2, ...], ...]
  • 默认值: []
  • [ ] T39.2 修改 BomTreeGraph.vue — 新增 Computed
  • cycleNodeIds: computed(() => new Set(cyclePaths.value.flat())) — 从 cyclePaths 提取所有循环节点 ID
  • cycleEdgeIds: computed(() => { / 从 cyclePaths 提取循环路径的边 ID 集合 / }) — 循环边集合
  • [ ] T39.3 修改 BomTreeGraph.vue — 修改 flattenTree() 方法
  • 节点增加 status: 'cycle' 标记(当 id in cycleNodeIds
  • 循环节点使用特殊 CSS 类 .node-cycle
  • [ ] T39.4 修改 BomTreeGraph.vue — 修改边渲染
  • 循环路径的边增加 class: 'edge-cycle'(红色加粗)
  • 多循环场景颜色区分:
    const CYCLE_COLORS = ['#f44336', '#ff9800', '#9c27b0']  // 红/橙/紫
    function getCycleColor(cycleIndex) {
      return CYCLE_COLORS[cycleIndex % CYCLE_COLORS.length]
    }
    
  • [ ] T39.5 新增 CSS 样式
  • .node-cycle .node-rect: 红色填充 + 红色边框 + 脉冲动画
  • .edge-cycle: 红色加粗线条
  • @keyframes pulse: 透明度脉冲动画
  • 循环节点旁显示 "⚠️ 循环依赖" 标签
  • [ ] T39.6 新增循环节点点击交互
  • 点击循环节点 → 弹出提示 "检测到循环依赖:A → B → C → A"
  • 提供"查看完整路径"和"忽略"选项
  • 循环路径过长(>10节点)→ 截断显示 + "...等 N 个节点形成循环"
  • [ ] T39.7 修改 server/services/bom-import-service.js — 返回循环路径数据
  • 修改 _detectCycle_detectCycleWithPaths,返回循环路径数组而非布尔值
  • DFS 算法检测循环并记录完整路径(见 design-p2.md 4.4)
  • 修改 buildBomTree() 返回值: 增加 cyclePaths 字段
    if (cyclePaths.length > 0) {
      return { error: '检测到循环依赖', items: [], cyclePaths }
    }
    
  • [ ] T39.8 修改 src/views/BomAssistant.vue — 传递 cyclePaths
  • 从 BOM 导入结果中提取 cyclePaths
  • 导入含循环依赖的 BOM 时,BomTreeGraph 预览中高亮循环路径
  • 提示 "请修正循环依赖后重新导入"
  • [ ] T39.9 前端构建与验证
  • Stop-Process -Name "node" 停止旧进程
  • npm run build 构建前端
  • 导入包含循环依赖的 BOM,确认循环节点标红
  • 确认循环路径的边使用红色加粗线条
  • 点击循环节点确认显示完整循环路径
  • 多个独立循环确认使用不同颜色区分

验证方法

| 验证项 | 预期结果 |

|--------|---------|

| 循环节点高亮 | 节点标红 + 脉冲动画 + ⚠️标签 |

| 循环边高亮 | 红色加粗线条 |

| 点击循环节点 | 弹出循环路径信息 |

| 多循环颜色区分 | 红/橙/紫三种颜色 |

| 导入阻断 | 含循环依赖的 BOM 拒绝导入 |

| 长路径截断 | >10 节点截断显示 |


T40. 阿里云 ASR 后端实现

  • 优先级: P2
  • 预估工时: 1.5 天
  • 依赖: T01(VoiceInput 需先就绪)
  • 可并行: 是(与 T33/T34/T37/T39/T42 无依赖)

涉及文件

文件路径操作说明
server/services/asr-service.js修改增加阿里云后端 + 降级链 + 健康检查
config.yaml修改新增 asr.providers + asr.aliyun 配置节

编码步骤

  • [ ] T40.1 修改 config.yaml — 新增 ASR 配置节
  • asr 节点下新增 providers 数组和 aliyun 配置:
    asr:
      provider: iflytek
      timeout: 15000
      providers:
        - name: iflytek
          priority: 1
          enabled: true
        - name: aliyun
          priority: 2
          enabled: true
        - name: echo
          priority: 3
          enabled: true
      aliyun:
        access_key_id: ""
        access_key_secret: ""
        app_key: ""
    
  • [ ] T40.2asr-service.js 中新增 recognizeAliyun(audioBuffer, format, sampleRate) 方法
  • 阿里云智能语音 REST API 调用
  • API: https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/asr
  • 认证: AccessKeyId + AccessKeySecret 签名
  • 参数: appKey, format(pcm/wav), sampleRate(16000)
  • 环境变量覆盖: ALIYUN_ASR_ACCESS_KEY_ID / ALIYUN_ASR_ACCESS_KEY_SECRET / ALIYUN_ASR_APP_KEY
  • 返回识别文本
  • 日志: [ASR] 阿里云识别结果: ${text}
  • [ ] T40.3 修改 asr-service.jsrecognize() 方法 — 实现降级链
  • 从 config.yaml 读取 asr.providers 配置
  • priority 排序,过滤 enabled !== false
  • 遍历 providers,按顺序尝试:
  • iflytekrecognizeIflytek()
  • aliyunrecognizeAliyun()
  • echorecognizeEcho()
  • 成功 → 返回 { text, provider }
  • 失败 → 记录日志 + 尝试下一个
  • 全部失败 → 抛出错误 "语音识别服务暂时不可用,请稍后重试"
  • 保持 /api/asr/recognize 接口格式不变,响应增加 provider 字段
  • [ ] T40.4 新增 checkProviderHealth(providerName) 方法 — 健康检查
  • 缓存健康状态: healthCache = new Map(),5 分钟有效期
  • iflytek: 验证配置完整性 (app_id, api_key, api_secret)
  • aliyun: 验证配置完整性 (access_key_id, access_key_secret, app_key)
  • echo: 永远可用
  • 请求时优先使用最近一次健康检查通过的后端
  • [ ] T40.5 新增降级统计 degradeStats
  • degradeStats = { iflytek: { success: 0, fail: 0 }, aliyun: { success: 0, fail: 0 }, echo: { count: 0 } }
  • 每次识别成功/失败时更新统计
  • [ ] T40.6 处理阿里云 ASR 配置缺失场景
  • config.yaml 中未配置 aliyun.access_key_id 等时
  • 跳过阿里云后端,直接降级到 Echo 模式
  • 日志: [ASR] 阿里云配置缺失,跳过
  • [ ] T40.7 添加浏览器 console 详细日志(PREFERENCE_2)
  • 降级切换日志: [ASR] ${provider.name} 识别失败,切换到下一个: ${error.message}
  • 识别成功日志: [ASR] 识别成功, provider=${provider.name}, text=${text.substring(0, 50)}

验证方法

| 验证项 | 预期结果 |

|--------|---------|

| 讯飞可用 | 正常识别,provider='iflytek' |

| 讯飞不可用 | 自动切换阿里云,provider='aliyun' |

| 阿里云不可用 | 降级到 Echo,provider='echo' |

| 配置缺失 | 跳过阿里云,直接 Echo |

| 全部不可用 | 返回错误提示 |

| 健康检查 | 5 分钟缓存,优先使用健康后端 |

| 接口兼容 | /api/asr/recognize 格式不变,增加 provider 字段 |


T41. ASR 降级链路测试与监控

  • 优先级: P2
  • 预估工时: 0.5 天
  • 依赖: T40(阿里云 ASR 后端需先就绪)
  • 可并行: 否(依赖 T40)

涉及文件

文件路径操作说明
server/services/asr-service.js修改增加降级统计 API + 日志汇总
server.js修改注册 ASR 统计 API

编码步骤

  • [ ] T41.1asr-service.js 中新增 getStats() 方法
  • 返回降级统计数据:
    {
      iflytek: { success: N, fail: N },
      aliyun: { success: N, fail: N },
      echo: { count: N }
    }
    
  • [ ] T41.2 新增 GET /api/asr/stats API
  • 调用 asrService.getStats()
  • 返回 { success: true, data: { ...stats } }
  • server.js 中注册路由
  • [ ] T41.3 新增统计汇总日志
  • 每 100 次识别输出一次统计摘要:
    console.log(`[ASR] 统计汇总: iflytek(${stats.iflytek.success}/${stats.iflytek.fail}), aliyun(${stats.aliyun.success}/${stats.aliyun.fail}), echo(${stats.echo.count})`)
    
  • [ ] T41.4 添加浏览器 console 详细日志
  • 每次降级切换时输出详细日志
  • 健康检查结果日志

验证方法

| 验证项 | 预期结果 |

|--------|---------|

| 降级统计正确 | 调用 ASR 接口后统计数据更新 |

| 统计 API | GET /api/asr/stats 返回正确数据 |

| 汇总日志 | 每 100 次输出统计摘要 |

| 浏览器日志 | console 显示 ASR 降级详细日志 |


T42. WebSocket 服务端实现

  • 优先级: P2
  • 预估工时: 2 天
  • 依赖: T17(通知同步服务需先就绪)
  • 可并行: 是(与 T33/T34/T37/T39/T40 无依赖)

涉及文件

文件路径操作说明
server/services/websocket-service.js新增WebSocket 服务端
server.js修改集成 WebSocket 升级 + 通知推送

编码步骤

  • [ ] T42.1 安装 ws 依赖
  • npm install ws
  • 如 jsonwebtoken 未安装: npm install jsonwebtoken
  • [ ] T42.2 创建 server/services/websocket-service.js 服务骨架
  • 定义 WebSocketService 类,单例模式
  • module.exports = new WebSocketService() 直接导出实例
  • 依赖: ws, jsonwebtoken
  • 核心数据结构:
  • connections: Map> — 用户连接映射
  • tenantConnections: Map> — 租户连接映射
  • messageBuffer: Map> — 离线消息缓冲
  • [ ] T42.3 实现 init(httpServer) — 初始化 WebSocket 服务
  • 创建 WebSocket.Server({ noServer: true })
  • 监听 httpServerupgrade 事件
  • 匹配 /ws 路径
  • 验证 JWT(从 req.url 的 query 参数获取 token)
  • JWT 无效 → 拒绝升级,返回 4001 错误码
  • JWT 有效 → wss.handleUpgrade(req, socket, head, ws)
  • [ ] T42.4 实现 handleConnection(ws, req) — 连接管理
  • 从 JWT 解析 userIdenterpriseId
  • 检查连接数限制: 全局 <1000, 单用户 <5
  • 超限 → 关闭连接,返回 503 "服务繁忙"
  • 添加到 connectionstenantConnections 映射
  • 监听 ws.on('message') → 处理 pong 等客户端消息
  • 监听 ws.on('close') → 调用 handleDisconnect(ws)
  • 日志: [WS] 用户 ${userId} 连接, 当前在线: ${totalConnections}
  • [ ] T42.5 实现 broadcastToUser(userId, message) — 用户级推送
  • 查找 connections.get(userId) 的所有 WebSocket
  • 逐个 ws.send(JSON.stringify(message))
  • 消息格式: { type, data, timestamp, messageId }
  • 发送失败 → 从连接映射移除该 ws
  • [ ] T42.6 实现 broadcastToTenant(enterpriseId, message) — 租户级推送
  • 查找 tenantConnections.get(enterpriseId) 的所有用户
  • 逐用户调用 broadcastToUser
  • 日志: [WS] 租户 ${enterpriseId} 广播, 在线用户: ${userCount}
  • [ ] T42.7 实现 handleDisconnect(ws) — 断连处理
  • connectionstenantConnections 映射中移除
  • 将未送达消息暂存到 messageBuffer
  • 日志: [WS] 用户 ${userId} 断开连接
  • [ ] T42.8 实现消息补发机制
  • 客户端重连时发送 lastMessageId 参数
  • 服务端从 notifications 表查询该 ID 之后的消息
  • 逐条补发
  • 日志: [WS] 用户 ${userId} 补发 ${count} 条消息
  • [ ] T42.9 实现心跳保活
  • 服务端每 30 秒发送 ping 消息
  • 客户端 10 秒内未响应 pong → 关闭连接
  • 使用 ws.ping() + ws.pong() 原生机制
  • [ ] T42.10 实现 getStats() — 连接统计
  • 返回: { totalConnections, uniqueUsers, tenantStats: { enterpriseId: userCount } }
  • [ ] T42.11 修改 server.js — 集成 WebSocket 服务
  • 在 HTTP 服务器创建后:
    const websocketService = require('./server/services/websocket-service')
    websocketService.init(server)
    
  • 在通知推送逻辑中增加:
    websocketService.broadcastToUser(userId, {
      type: 'notification',
      data: message,
      timestamp: Date.now(),
      messageId: generateMessageId()
    })
    

验证方法

| 验证项 | 预期结果 |

|--------|---------|

| WebSocket 连接 | ws://host/ws?token=xxx 连接成功 |

| JWT 验证 | 无效 token 返回 4001 关闭连接 |

| 消息推送 | 通知发送后 WebSocket 客户端收到消息 |

| 消息补发 | 重连后收到断连期间的消息 |

| 心跳保活 | 30 秒 ping,10 秒无 pong 关闭 |

| 连接数限制 | 全局 >1000 返回 503,单用户 >5 拒绝 |

| 推送延迟 | <200ms |


T43. WebSocket 前端集成

  • 优先级: P2
  • 预估工时: 1.5 天
  • 依赖: T42(WebSocket 服务端需先就绪)
  • 可并行: 否(依赖 T42),但可与 T44 并行

涉及文件

文件路径操作说明
src/composables/useWebSocket.js新增WebSocket 前端 composable
src/stores/app.js修改使用 WebSocket 接收通知
src/App.vue修改初始化 WebSocket 连接

编码步骤

  • [ ] T43.1 创建 src/composables/useWebSocket.js composable
  • 使用 Vue 3 Composition API 风格
  • 状态:
  • ws: ref
  • connected: ref(false)
  • usePolling: ref(false)
  • retryCount: ref(0)
  • messageHandlers: Array([])
  • lastMessageId: ref('')
  • [ ] T43.2 实现 connect(token) 方法
  • 获取 WebSocket URL: ws://${window.location.host}/ws?token=${token}
  • ws = new WebSocket(url)
  • ws.onopenconnected = true, usePolling = false, retryCount = 0
  • ws.onmessage → 解析 JSON → 调用 messageHandlers
  • ws.oncloseconnected = false → 2 秒后重连(最多 5 次,指数退避)
  • ws.onerror → 标记 usePolling = true
  • console.log 详细日志: [WS] 连接成功 / [WS] 连接失败 / [WS] 重连中(${retryCount}/5)
  • [ ] T43.3 实现 disconnect() 方法
  • ws.close()
  • 清除重连定时器
  • connected = false
  • [ ] T43.4 实现 onMessage(handler) 方法
  • messageHandlers.push(handler)
  • 返回取消注册函数: () => { messageHandlers.splice(index, 1) }
  • [ ] T43.5 实现 send(data) 方法
  • ws.send(JSON.stringify(data))
  • 连接未建立时缓存消息
  • [ ] T43.6 实现自动重连逻辑
  • 断连后等待 2 秒重试
  • 最多重试 5 次
  • 指数退避: 2s → 4s → 8s → 16s → 32s
  • 重连时携带 lastMessageId 参数
  • 重连成功后补发缓存消息
  • [ ] T43.7 实现轮询降级逻辑
  • usePolling = true 时,每 5 秒调用 GET /api/notifications 轮询
  • 轮询结果通过 messageHandlers 分发
  • WebSocket 重连成功后切换回实时模式: usePolling = false
  • console.log: [WS] 降级为轮询模式 / [WS] 恢复实时模式
  • [ ] T43.8 修改 src/stores/app.js — 集成 WebSocket
  • 在 store 初始化时调用 useWebSocket.connect(token)
  • WebSocket 消息到达时更新 store 状态
  • 新通知到达时更新通知列表
  • [ ] T43.9 修改 src/App.vue — 初始化 WebSocket 连接
  • onMounted 中:
    const { connect, disconnect, onMessage } = useWebSocket()
    const token = localStorage.getItem('token')
    if (token) connect(token)
    
  • onUnmounted 中: disconnect()
  • 注册消息处理器: onMessage(handleWsMessage)
  • [ ] T43.10 添加浏览器 console 详细日志(PREFERENCE_2)
  • 连接状态变化: [WS] 连接成功 / [WS] 断开连接 / [WS] 重连成功
  • 消息接收: [WS] 收到消息: type=${msg.type}
  • 降级切换: [WS] 降级为轮询模式 / [WS] 恢复实时模式
  • [ ] T43.11 前端构建与验证
  • Stop-Process -Name "node" 停止旧进程
  • npm run build 构建前端
  • 登录后确认 WebSocket 连接建立
  • 收到通知后确认 store 状态实时更新
  • 断网后确认自动重连
  • WebSocket 不可用时确认降级为轮询
  • 浏览器 console 显示 WebSocket 详细日志

验证方法

| 验证项 | 预期结果 |

|--------|---------|

| 连接建立 | 登录后 WebSocket 连接成功 |

| 实时通知 | 收到通知后 store 状态即时更新 |

| 自动重连 | 断网后 2 秒重连,最多 5 次 |

| 轮询降级 | WebSocket 不可用时 5 秒轮询 |

| 恢复实时 | 重连成功后切换回 WebSocket |

| Console 日志 | 显示连接/断连/重连/消息日志 |


T44. 小程序 WebSocket 集成

  • 优先级: P2
  • 预估工时: 1 天
  • 依赖: T42(WebSocket 服务端需先就绪)、T04(小程序登录)
  • 可并行: 可与 T43 并行

涉及文件

文件路径操作说明
bossagents-miniapp/src/utils/websocket.js新增小程序 WebSocket 工具
bossagents-miniapp/src/store/index.js修改集成 WebSocket

编码步骤

  • [ ] T44.1 创建 bossagents-miniapp/src/utils/websocket.js
  • 使用 uni.connectSocket() 建立连接
  • 状态: connected: false, retryCount: 0, usePolling: false
  • [ ] T44.2 实现 connect(token) 方法
  • uni.connectSocket({ url: 'ws://${host}/ws?token=${token}' })
  • uni.onSocketOpenconnected = true, usePolling = false
  • uni.onSocketMessage → 解析 JSON → 调用回调
  • uni.onSocketError → 触发重连
  • uni.onSocketClose → 触发重连
  • [ ] T44.3 实现自动重连
  • 2 秒后重试,最多 5 次
  • 指数退避: 2s → 4s → 8s → 16s → 32s
  • [ ] T44.4 实现降级逻辑
  • WebSocket 连接失败时切换到 5 秒轮询
  • 轮询调用 GET /api/notifications
  • 重连成功后切换回 WebSocket
  • [ ] T44.5 实现 onMessage(callback) 方法
  • 注册消息处理回调
  • [ ] T44.6 修改 bossagents-miniapp/src/store/index.js — 集成 WebSocket
  • useNotificationStore 中集成 WebSocket
  • WebSocket 消息到达时更新通知列表
  • 新通知到达时显示 uni.showToast 提示

验证方法

验证项预期结果
小程序连接登录后 WebSocket 连接成功
实时通知通知列表即时更新
自动重连断网后自动重连
轮询降级WebSocket 不可用时 5 秒轮询
Toast 提示新通知到达时显示提示

T45. 租户配额管理前端界面

  • 优先级: P2
  • 预估工时: 1.5 天
  • 依赖: T36(配额管理 API 需先就绪)
  • 可并行: 否(依赖 T36)

涉及文件

文件路径操作说明
src/views/AdminQuotaManager.vue新增配额管理前端界面
src/router/index.js修改新增配额管理路由
src/services/api.js修改新增配额管理 API 调用

编码步骤

  • [ ] T45.1 创建 src/views/AdminQuotaManager.vue 页面骨架
  • 使用 Vue 3 Composition API 风格
  • 顶部: 租户选择下拉框 + "批量初始化"按钮
  • 主体: 配额使用情况表格
  • [ ] T45.2 实现配额使用情况表格
  • 列: 租户名称 | Part(当前/上限/占比) | BOM(当前/上限/占比) | 用户(当前/上限/占比) | 月任务(当前/上限/占比) | 操作
  • 占比计算: current / max * 100
  • 占比 >80% → 单元格标黄 (background: #fff3e0)
  • 占比 >100% → 单元格标红 (background: #fce4ec)
  • 进度条可视化: 每个资源类型显示进度条
  • [ ] T45.3 实现编辑配额弹窗
  • 表单字段: maxParts、maxBoms、maxUsers、maxStaffTasks
  • 输入验证: 值必须 >0
  • 保存时调用 PUT /api/admin/quotas/:enterpriseId
  • 新配额 < 当前使用量 → 弹出警告 "当前使用量(N)已超过新配额(N),已有数据不受影响但无法新增"
  • 保存成功后刷新表格
  • [ ] T45.4 实现批量初始化功能
  • 点击"批量初始化" → 确认弹窗 "将为所有无配额记录的租户创建默认配额"
  • 调用 POST /api/admin/quotas/init
  • 显示初始化结果: "已为 N 个租户初始化默认配额"
  • [ ] T45.5 实现手动同步功能
  • 每行操作列增加"同步"按钮
  • 调用 POST /api/admin/quotas/:enterpriseId/sync
  • 同步成功后刷新该行数据
  • [ ] T45.6 修改 src/services/api.js — 新增配额管理 API 调用
  • getQuotas()GET /api/admin/quotas
  • getQuota(enterpriseId)GET /api/admin/quotas/:enterpriseId
  • updateQuota(enterpriseId, data)PUT /api/admin/quotas/:enterpriseId
  • initQuotas()POST /api/admin/quotas/init
  • syncQuota(enterpriseId)POST /api/admin/quotas/:enterpriseId/sync
  • [ ] T45.7 修改 src/router/index.js — 新增配额管理路由
  • 新增 /admin/quotas 路由
  • 需 admin 角色守卫: 非管理员访问返回 403
  • 页面标题: "配额管理"
  • [ ] T45.8 实现非管理员访问拦截
  • 路由守卫检查用户角色
  • 非管理员 → 重定向到首页 + 提示 "无权访问"
  • [ ] T45.9 添加浏览器 console 详细日志
  • 配额加载: console.log('[AdminQuota] 配额列表加载:', data)
  • 操作日志: console.log('[AdminQuota] 修改配额:', enterpriseId, data)
  • [ ] T45.10 前端构建与验证
  • Stop-Process -Name "node" 停止旧进程
  • npm run build 构建前端
  • 管理员打开配额管理页面,确认显示所有租户配额
  • 修改配额上限后确认保存成功
  • 占比超过 80% 的指标确认标黄
  • 非管理员访问确认返回 403
  • 批量初始化和手动同步功能正常

验证方法

验证项预期结果
配额列表展示显示所有租户配额及使用情况
占比标色>80%标黄, >100%标红
编辑配额修改后立即生效
新配额低于使用量弹出警告
批量初始化为无配额租户创建默认配额
手动同步同步后数据一致
非管理员拦截返回 403

3. 推荐执行顺序

3.1 三轨并行执行计划

第一周(P2 核心,3 条并行轨道)

天数轨道 A(协作+可视化)轨道 B(配额+文章)轨道 C(ASR+WebSocket)
D1-D2T33 协作链可视化T34 租户配额后端T42 WebSocket 服务端
D2-D3T39 BOM 循环依赖可视化T37 已发布文章后端T40 阿里云 ASR 后端
D3-D4T35 配额检查中间件 + T36 配额 APIT43 WebSocket 前端 + T44 小程序
D4-D5T38 文章前端 + T45 配额前端T41 ASR 降级监控

关键里程碑

里程碑完成标志预计时间
M9: 协作可视化可用T33 完成,协作链流程图可渲染P2 D2
M10: 配额管控上线T34-T36+T45 完成,配额检查+管理界面可用P2 D5
M11: 文章管理闭环T37-T38 完成,已发布文章可查询管理P2 D4
M12: BOM 诊断增强T39 完成,循环依赖可视化高亮P2 D3
M13: ASR 三后端就绪T40-T41 完成,讯飞→阿里云→Echo 降级链P2 D5
M14: 实时推送上线T42-T44 完成,三端 WebSocket 实时同步P2 D4

3.2 任务依赖与并行矩阵

可并行任务组:

组1 (D1-D2, 无依赖):
  T33 + T34 + T42

组2 (D2-D3, 依赖组1):
  T39 + T37 + T40

组3 (D3-D4, 依赖组2):
  T35+T36 + T43+T44

组4 (D4-D5, 依赖组3):
  T38+T45 + T41

4. 全局约束与注意事项

4.1 编码约束

| 约束项 | 说明 |

|--------|------|

| 包管理 | 只用 npm install,不用 pnpm |

| POST 路由 | server.js 中 POST 路由需要 collectBody(req) |

| 模块导出 | module.exports = ClassName 直接导出(服务类用单例: module.exports = new ClassName()) |

| 前端构建 | 修改前端代码后需要 npm run build |

| 构建前停止 | 构建前必须先 Stop-Process -Name "node" |

| 命名规范 | JavaScript 变量和函数使用 camelCase |

| 配置驱动 | 使用 JSON 定义对象模型、YAML 定义规则,声明式配置风格 |

| 三端统一 | 网页端+飞书端+小程序端底层统一实现 |

4.2 server.js 修改汇总

// 1. 新增 require (T35/T36/T42)
const tenantQuotaService = require('./server/services/tenant-quota-service')
const { quotaGuard } = require('./server/middleware/tenant-middleware')
const adminQuotaRoutes = require('./server/routes/admin-quota')
const websocketService = require('./server/services/websocket-service')

// 2. WebSocket 初始化 (T42) — 在 server 创建后
websocketService.init(server)

// 3. 配额检查中间件集成 (T35) — 在创建类路由中
// Part 创建: quotaGuard('parts')(req, res, () => { /* 原有逻辑 */ })
// BOM 创建: quotaGuard('boms')
// 用户创建: quotaGuard('users')
// 数字员工任务创建: quotaGuard('staffTasks')

// 4. 配额管理路由注册 (T36)
if (pathname.startsWith('/api/admin/quotas')) {
  return adminQuotaRoutes.handleAdminQuotaRoute(req, res, pathname, query, bodyStr)
}

// 5. ASR 统计路由注册 (T41)
if (pathname === '/api/asr/stats' && req.method === 'GET') {
  // 返回降级统计
}

// 6. 通知推送集成 WebSocket (T42)
websocketService.broadcastToUser(userId, { type: 'notification', data: message, timestamp: Date.now() })

4.3 db-adapter.js 修改汇总

// 在 createDatabase() 中新增:

// tenant_quotas (T34)
db.exec(`CREATE TABLE IF NOT EXISTS tenant_quotas (...)`)
db.exec(`CREATE INDEX IF NOT EXISTS idx_tenant_quotas_enterprise ON tenant_quotas(enterprise_id)`)

// published_articles (T37)
db.exec(`CREATE TABLE IF NOT EXISTS published_articles (...)`)
db.exec(`CREATE INDEX IF NOT EXISTS idx_published_articles_enterprise ON published_articles(enterprise_id)`)
db.exec(`CREATE INDEX IF NOT EXISTS idx_published_articles_status ON published_articles(status)`)

4.4 依赖安装汇总

# T42: WebSocket 服务端
npm install ws

# T42: JWT 验证(如未安装)
npm install jsonwebtoken

5. 新增文件清单

| 文件路径 | 任务 | 说明 |

|---------|------|------|

| src/components/digital-staff/CollaborationChainGraph.vue | T33 | 协作链流程图组件 |

| server/services/tenant-quota-service.js | T34 | 租户配额后端服务 |

| server/routes/admin-quota.js | T36 | 配额管理 API 路由 |

| server/services/published-article-service.js | T37 | 已发布文章服务 |

| src/views/AdminQuotaManager.vue | T45 | 配额管理前端界面 |

| server/services/websocket-service.js | T42 | WebSocket 服务端 |

| src/composables/useWebSocket.js | T43 | WebSocket 前端 composable |

| bossagents-miniapp/src/utils/websocket.js | T44 | 小程序 WebSocket 工具 |

修改文件清单

文件路径任务修改内容
server/middleware/tenant-middleware.jsT35新增 quotaGuard(resourceType)
server.jsT35/T36/T41/T42配额检查路由集成 + WebSocket 初始化 + ASR 统计路由
server/db-adapter.jsT34/T37新增 tenant_quotas + published_articles 建表
server/services/wechat-publish.jsT37发布成功后调用 recordPublish()
server/routes/content-api.jsT37新增已发布文章 API
src/views/ContentManager.vueT38增加"已发布"标签页
src/services/api.jsT38/T45新增已发布文章 + 配额管理 API 调用
src/components/bom/BomTreeGraph.vueT39新增 cyclePaths prop + 循环高亮 CSS
server/services/bom-import-service.jsT39_detectCycle 返回循环路径
src/views/BomAssistant.vueT39传递 cyclePaths 到 BomTreeGraph
server/services/asr-service.jsT40/T41增加阿里云后端 + 降级链 + 健康检查 + 统计
config.yamlT40新增 asr.providers + asr.aliyun 配置节
src/views/DigitalStaff.vueT33集成 CollaborationChainGraph
src/router/index.jsT45新增 /admin/quotas 路由
src/stores/app.jsT43使用 WebSocket 接收通知
src/App.vueT43初始化 WebSocket 连接
bossagents-miniapp/src/store/index.jsT44集成 WebSocket

6. 任务统计

| 编号 | 任务名称 | 优先级 | 预估工时 | 依赖 | 可并行 |

|------|---------|--------|---------|------|--------|

| T33 | 协作链可视化组件 | P2 | 2天 | T24+T25 | 是 |

| T34 | 租户配额后端服务 | P2 | 1.5天 | T09+T15 | 是 |

| T35 | 租户配额检查中间件集成 | P2 | 1天 | T34 | 与T36并行 |

| T36 | 租户配额管理 API | P2 | 0.5天 | T34 | 与T35并行 |

| T37 | 已发布文章后端 | P2 | 1.5天 | T11+T31 | 是 |

| T38 | 已发布文章前端界面 | P2 | 1天 | T37 | 否 |

| T39 | BOM 循环依赖可视化 | P2 | 1.5天 | T22+T07 | 是 |

| T40 | 阿里云 ASR 后端实现 | P2 | 1.5天 | T01 | 是 |

| T41 | ASR 降级链路测试与监控 | P2 | 0.5天 | T40 | 否 |

| T42 | WebSocket 服务端实现 | P2 | 2天 | T17 | 是 |

| T43 | WebSocket 前端集成 | P2 | 1.5天 | T42 | 与T44并行 |

| T44 | 小程序 WebSocket 集成 | P2 | 1天 | T42+T04 | 与T43并行 |

| T45 | 租户配额管理前端界面 | P2 | 1.5天 | T36 | 否 |

P2 总工时: 约 16.5 天(单人全栈)

并行执行: 约 5 天(3 条并行轨道)


文档状态: 已完成

文件路径: C:\bossagents\docs\tasks-p2.md

← 返回案例列表
分享:
🤖 Try Now →
🤖
🎁