135 lines
4.3 KiB
TypeScript
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('、') || '—'
|
|
}
|