Files
zkxw/web-admin/src/utils/production-work-order-step-badge.ts
T
2026-07-06 16:59:53 +08:00

110 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { ProductionWorkOrderItem } from '@/api/production-work-order'
import type { ProductionWorkOrderTabStepCount } from '@/api/production-work-order'
import { isProductionWorkOrderTabStepBadgeZero } from '@/api/production-work-order'
export type ProductionWorkOrderStepBadgeScope = 'manage' | 'mine'
const ACTIVE_WORK_ORDER_STATUSES = new Set(['dpz', 'jxz'])
const ACTIVE_TASK_STATUSES = new Set(['dpz', 'jxz'])
function todayYmd(): string {
const d = new Date()
const y = d.getFullYear()
const m = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
return `${y}-${m}-${day}`
}
function isActiveWorkOrder(row: Pick<ProductionWorkOrderItem, 'workOrderStatus'>): boolean {
return ACTIVE_WORK_ORDER_STATUSES.has((row.workOrderStatus || '').trim())
}
function isActiveTask(task: Record<string, any>): boolean {
return ACTIVE_TASK_STATUSES.has((task.taskStatus || '').trim())
}
function isActiveStep(step: Record<string, any>): boolean {
return (step.stepStatus || '').trim() !== 'ywc'
}
function stepAssigneeUserIds(step: Record<string, any>): string[] {
const ids = step.assigneeUserIds
if (Array.isArray(ids) && ids.length) {
return ids.map((id) => String(id || '').trim()).filter(Boolean)
}
const assignees = step.assignees
if (!Array.isArray(assignees)) return []
return assignees
.map((a) => String(a?.userId || a?.id || '').trim())
.filter(Boolean)
}
function isStepFutureIncomplete(step: Record<string, any>): boolean {
const planned = (step.plannedStartTime || '').trim().slice(0, 10)
if (!planned) return false
return planned > todayYmd()
}
/** 与后端 mine-tab-step-counts 任务过滤一致 */
function isMineQualifyingTask(task: Record<string, any>, userId: string): boolean {
const uid = userId.trim()
if (!uid) return false
if (String(task.currentAssigneeUserId || '').trim() === uid) return true
const steps = Array.isArray(task.steps) ? task.steps : []
for (const step of steps) {
if (stepAssigneeUserIds(step).includes(uid)) return true
}
return false
}
/** 与后端 tab-step-counts 一致:计划开始日期已到期且步骤未完成 */
function isStepOverdueIncomplete(step: Record<string, any>): boolean {
const planned = (step.plannedStartTime || '').trim().slice(0, 10)
if (!planned) return false
return planned <= todayYmd()
}
/** 单张生产工单卡片:工艺步骤到期未完成 / 计划开始在今日之后未完成(与 Tab 角标语义一致) */
export function sumProductionWorkOrderStepBadgeCount(
workOrder: ProductionWorkOrderItem,
tasks: Record<string, any>[] | undefined,
scope: ProductionWorkOrderStepBadgeScope,
currentUserId?: string
): ProductionWorkOrderTabStepCount {
const result: ProductionWorkOrderTabStepCount = { overdueIncomplete: 0, futureIncomplete: 0 }
if (!isActiveWorkOrder(workOrder)) return result
const uid = String(currentUserId || '').trim()
for (const task of tasks || []) {
if (!isActiveTask(task)) continue
if (scope === 'mine' && uid && !isMineQualifyingTask(task, uid)) continue
for (const step of Array.isArray(task.steps) ? task.steps : []) {
if (!isActiveStep(step)) continue
if (isStepOverdueIncomplete(step)) result.overdueIncomplete += 1
if (isStepFutureIncomplete(step)) result.futureIncomplete += 1
}
}
return result
}
export function isProductionWorkOrderStepBadgeVisible(
count: ProductionWorkOrderTabStepCount
): boolean {
return !isProductionWorkOrderTabStepBadgeZero(count)
}
export function productionWorkOrderStepBadgeTitle(count: ProductionWorkOrderTabStepCount): string {
if (isProductionWorkOrderTabStepBadgeZero(count)) return ''
const overdue = count.overdueIncomplete || 0
const future = count.futureIncomplete || 0
const parts: string[] = []
if (overdue > 0) {
parts.push(`${overdue} 个工艺步骤已到期未完成`)
}
if (future > 0) {
parts.push(`${future} 个工艺步骤计划开始在今日之后`)
}
return parts.join(',')
}