Files
zkxw/web-admin/src/utils/qc-company-task-group.ts
T
2026-09-03 17:12:38 +08:00

135 lines
4.3 KiB
TypeScript

import type { QcTask } from '../api/qc-task'
export type QcTaskListLabItem = { kind: 'lab'; task: QcTask }
/** 批次内全部第三方任务合一卡 */
export type QcTaskListAllThirdItem = { kind: 'all-third'; tasks: QcTask[] }
export type QcTaskListDisplayItem = QcTaskListLabItem | QcTaskListAllThirdItem
export const UNASSIGNED_THIRD_PARTY_COMPANY_LABEL = '未归属公司'
export const ALL_THIRD_PARTY_CARD_TITLE = '第三方质检项目'
function trimId(v?: string) {
return (v || '').trim()
}
export function thirdPartyCompanyDisplayName(task: Pick<QcTask, 'companyId' | 'companyName'>): string {
if (!trimId(task.companyId)) return UNASSIGNED_THIRD_PARTY_COMPANY_LABEL
return (task.companyName || '').trim() || UNASSIGNED_THIRD_PARTY_COMPANY_LABEL
}
/** 有非空 companyId 的去重公司数(不含未归属) */
export function countDistinctThirdPartyCompanies(tasks: QcTask[]): number {
const ids = new Set<string>()
for (const t of tasks || []) {
const cid = trimId(t.companyId)
if (cid) ids.add(cid)
}
return ids.size
}
export function allThirdPartyCardSubtitle(tasks: QcTask[]): string {
const list = tasks || []
const n = list.length
const m = countDistinctThirdPartyCompanies(list)
if (m > 0) return `第三方 · ${n} 个检测项目 · ${m} 家公司`
return `第三方 · ${n} 个检测项目`
}
/**
* 先按公司首次出现顺序分组,组内保持原序;无 companyId 的「未归属公司」组放最后。
*/
export function sortThirdPartyTasksByCompany(tasks: QcTask[]): QcTask[] {
const list = [...(tasks || [])]
const companyOrder: string[] = []
const byCompany = new Map<string, QcTask[]>()
const orphans: QcTask[] = []
for (const t of list) {
const cid = trimId(t.companyId)
if (!cid) {
orphans.push(t)
continue
}
if (!byCompany.has(cid)) {
byCompany.set(cid, [])
companyOrder.push(cid)
}
byCompany.get(cid)!.push(t)
}
const sorted: QcTask[] = []
for (const cid of companyOrder) {
sorted.push(...(byCompany.get(cid) || []))
}
sorted.push(...orphans)
return sorted
}
/** 自检卡在前(原序);全部第三方(含无 companyId)合成一张 all-third 卡 */
export function buildTaskListDisplayItems(tasks: QcTask[]): QcTaskListDisplayItem[] {
const lab: QcTaskListDisplayItem[] = []
const third: QcTask[] = []
for (const t of tasks || []) {
if ((t.taskType || '').trim() === 'dsfjc') {
third.push(t)
continue
}
// sysz 及其他非第三方:按自检单卡展示(与旧逻辑一致)
lab.push({ kind: 'lab', task: t })
}
if (!third.length) return lab
return [...lab, { kind: 'all-third', tasks: third }]
}
export function companyGroupProgress(tasks: QcTask[]) {
const list = tasks || []
const completed = list.filter((t) => (t.taskStatus || '').trim() === 'ywc').length
return { completed, total: list.length }
}
function timeMs(v?: string) {
if (!v) return 0
const n = Date.parse(String(v).replace(/-/g, '/'))
return Number.isFinite(n) ? n : 0
}
export function pickSharedRemarkAndAttachments(tasks: QcTask[]): {
remark: string
thirdPartyAttachments: string
attachmentFiles: NonNullable<QcTask['attachmentFiles']>
} {
const list = [...(tasks || [])].sort((a, b) => timeMs(b.updateTime) - timeMs(a.updateTime))
let remark = ''
let thirdPartyAttachments = ''
let attachmentFiles: NonNullable<QcTask['attachmentFiles']> = []
for (const t of list) {
if (!remark && (t.remark || '').trim()) remark = (t.remark || '').trim()
const urls = (t.thirdPartyAttachments || '').trim()
const files = t.attachmentFiles || []
if (!thirdPartyAttachments && (urls || files.length)) {
thirdPartyAttachments = urls
attachmentFiles = files.length ? [...files] : []
}
if (remark && (thirdPartyAttachments || attachmentFiles.length)) break
}
return { remark, thirdPartyAttachments, attachmentFiles }
}
export function uniqueAssigneeNames(tasks: QcTask[]): string {
const names: string[] = []
const seen = new Set<string>()
for (const t of tasks || []) {
const raw = (t.assigneeUserNames || '').trim()
if (!raw) continue
for (const part of raw.split(/[,,、]/)) {
const n = part.trim()
if (!n || seen.has(n)) continue
seen.add(n)
names.push(n)
}
}
return names.join('、') || '—'
}