现场问题先关闭还是先验收,建筑任务怎样处理依赖

建筑项目指挥台里,"裙楼机电 3 个冲突点"和"地下车库今日验收"同时出现。若验收任务只看自己的状态,用户可以把它标为完成;但关联的机电冲突还没处理,进度看板就提前把这部分工程算进了已完成。

我没有把依赖关系写在说明文字里,而是让每个任务明确列出它依赖哪些问题或前置任务。任务状态变化前,控制器先判断阻塞条件。

问题和任务各自有稳定编号

ts 复制代码
export type WorkState = 'todo' | 'working' | 'waitingReview' | 'done' | 'blocked'

export interface SiteIssue {
  id: string
  title: string
  severity: 'minor' | 'major' | 'critical'
  state: 'open' | 'resolved' | 'verified'
  updatedAt: number
}

export interface SiteTask {
  id: string
  title: string
  state: WorkState
  dependsOnTaskIds: string[]
  blocksOnIssueIds: string[]
  progress: number
}

"结构完成""协调中""今日验收"是展示标签,真正的判断使用状态字段和 ID。页面过滤楼层或切换平板布局时,任务引用不会因为数组排序而断开。

完成前先收集阻塞项

ts 复制代码
export interface BlockReason {
  type: 'task' | 'issue'
  id: string
  title: string
}

export function blockersOf(
  task: SiteTask,
  tasks: SiteTask[],
  issues: SiteIssue[]
): BlockReason[] {
  const reasons: BlockReason[] = []
  task.dependsOnTaskIds.forEach((id: string) => {
    const dependency = tasks.find((item: SiteTask) => item.id === id)
    if (dependency && dependency.state !== 'done') {
      reasons.push({ type: 'task', id, title: dependency.title })
    }
  })
  task.blocksOnIssueIds.forEach((id: string) => {
    const issue = issues.find((item: SiteIssue) => item.id === id)
    if (issue && issue.state !== 'verified') {
      reasons.push({ type: 'issue', id, title: issue.title })
    }
  })
  return reasons
}

问题标记"已解决"后还不能立即放行验收,必须经过"已验证"。这能区分现场负责人声称修复和验收人员实际确认两个阶段。

状态迁移有明确入口

ts 复制代码
export function requestDone(
  task: SiteTask,
  tasks: SiteTask[],
  issues: SiteIssue[]
): SiteTask {
  const blockers = blockersOf(task, tasks, issues)
  if (blockers.length > 0) {
    return { ...task, state: 'blocked' }
  }
  if (task.state !== 'working' && task.state !== 'waitingReview') {
    return task
  }
  return { ...task, state: 'done', progress: 100 }
}

任务卡片点击"完成"时,如果返回 blocked,右侧详情展开阻塞项,而不是简单提示"操作失败"。现场人员能直接看到是"裙楼机电"还是某一项验收问题未闭环。

总体进度使用可验收权重

第一版通常把所有任务的百分比直接平均,尚未验收的大任务也会抬高总进度。我给任务增加权重,且只有状态到 done 才贡献完整权重。

ts 复制代码
export interface WeightedTask extends SiteTask {
  weight: number
}

export function projectProgress(tasks: WeightedTask[]): number {
  const weight = tasks.reduce((sum: number, item: WeightedTask) => sum + item.weight, 0)
  if (weight === 0) return 0
  const completed = tasks.reduce((sum: number, item: WeightedTask) => {
    const ratio = item.state === 'done' ? 1 : Math.min(0.95, item.progress / 100)
    return sum + item.weight * ratio
  }, 0)
  return Math.round(completed / weight * 100)
}

未验收任务最多贡献 95%,避免"99%"长期停留却掩盖关键阻塞。这个规则并非施工进度的通用算法,真实项目应由项目管理系统提供权重和验收口径。

实时数据与人工修改并存

页面里的"实时运行"按钮只控制本地演示变化。未来接入现场系统时,每条同步消息携带更新时间,人工刚写入的验收结果不能被更早的远端消息覆盖。

ts 复制代码
export function acceptRemoteTask(current: SiteTask, remote: SiteTask & { updatedAt: number }, localUpdatedAt: number): SiteTask {
  return remote.updatedAt >= localUpdatedAt ? remote : current
}

任务、问题和验收三类状态分别保存后,建筑项目指挥台才能把 72% 总体进度、14 个待处理问题和楼层卡片放在同一套逻辑里。现场问题没有验证完成,依赖它的验收不会被提前关闭。

相关推荐
ss2734 小时前
PostgreSQL常见索引问题与解决方案
数据库·postgresql
小徐不徐说4 小时前
序列化与反序列化:把 C++ 对象可靠地保存下来
开发语言·数据库·c++·php
花开盛夏^.^5 小时前
电脑打开多个浏览器Web窗口占用较大的运行内存的原因
前端·浏览器
Dxy12393102165 小时前
JS DES 加密详解
开发语言·javascript·arcgis
充值内卷5 小时前
我给桌面加了个鱼缸:C++ 写后端,WebView2 里养一座 Three.js 小岛
开发语言·javascript·c++
瀚高PG实验室5 小时前
发布端逻辑复制槽消失
数据库·postgresql·瀚高数据库
ss2736 小时前
PostgreSQL慢查询定位与优化
数据库·postgresql
馒头不想说话6 小时前
实体店老板的24小时AI运营员工,写、剪、发全自动,省下一整个团队工资
前端
香蕉大香蕉(06敬畏市场)6 小时前
MySQL 单点详解(07)
java·数据库·mysql·ai·博客·八股
smilejingwei7 小时前
TRAE 插件上新 | SQLazy:让 AI 写出可信复杂 SQL
数据库·人工智能·sql