This commit is contained in:
zlwu committed 2026-06-15 11:43:16 +08:00
1 parent 427bcb1551
commit 31b04575e2
247 files changed
+39284 -20367

No files matched your search

@@ -0,0 +1,238 @@
import type { ProductionWorkOrderItem } from '@/api/production-work-order'
import { fetchProductionWorkOrderDetail } from '@/api/production-work-order'
import { fetchMyProductionTasks } from '@/api/production-task'
export type ProductionWorkOrderTypeTab = 'inbound' | 'temporary' | 'outbound'
export type ProductionTaskMineFilters = {
keyword?: string
taskStatus?: string
workOrderType?: ProductionWorkOrderTypeTab
}
export type MineWorkOrderSearchFilters = {
keyword?: string
workOrderStatus?: string
bizType?: string
createTimeStart?: string
createTimeEnd?: string
infusionTimeStart?: string
infusionTimeEnd?: string
activeTypeTab: ProductionWorkOrderTypeTab
}
export type ProductionTaskRow = Record<string, any>
export type MineWorkOrderEntry = {
workOrderId: string
workOrder: ProductionWorkOrderItem
activeTypeTab: ProductionWorkOrderTypeTab
tasks: ProductionTaskRow[]
}
const MINE_TASK_FETCH_PAGE_SIZE = 100
function dateInRange(value: string | undefined, start?: string, end?: string): boolean {
const v = (value || '').trim().slice(0, 10)
if (!v) return !start && !end
if (start && v < start) return false
if (end && v > end) return false
return true
}
function keywordMatchesWorkOrder(
row: ProductionWorkOrderItem,
keyword: string,
tab: ProductionWorkOrderTypeTab
): boolean {
const kw = keyword.trim().toLowerCase()
if (!kw) return true
const fields =
tab === 'temporary'
? [row.workOrderNo]
: tab === 'outbound'
? [row.workOrderNo, row.applicationNo, row.applicationName]
: [row.workOrderNo, row.sampleCode, row.labStorageCode]
return fields.some((f) => (f || '').toLowerCase().includes(kw))
}
export function resolveWorkOrderTypeTab(task: ProductionTaskRow): ProductionWorkOrderTypeTab {
const t = String(task.workOrderType || task.orderSource || 'inbound').trim()
if (t === 'outbound' || t === 'temporary' || t === 'inbound') return t
return 'inbound'
}
export function buildWorkOrderFromTasks(tasks: ProductionTaskRow[]): ProductionWorkOrderItem {
const t = tasks[0]
const woType = resolveWorkOrderTypeTab(t)
return {
id: t.workOrderId,
workOrderNo: t.workOrderNo || '—',
workOrderType: woType,
workOrderStatus: t.workOrderStatus || '',
protocolNo: t.protocolNo || '',
sampleCode: t.sampleCode || '',
receptionSource: t.receptionSource,
receptionSourceLabel: t.receptionSourceLabel,
protocolStatus: t.protocolStatus,
bizType: woType === 'outbound' ? t.bizType : undefined,
bizTypeLabel: woType === 'outbound' ? t.bizTypeLabel : undefined,
applicationNo: t.applicationNo,
applicationName: t.applicationName,
channelName: t.channelName,
patientName: t.patientName,
sortNo: t.sortNo,
totalCourseCount: t.totalCourseCount,
infusionTime: t.infusionTime,
sampleTypeName: t.sampleTypeName,
handlerName: t.handlerName,
receptionTime: t.receptionTime,
labStorageCode: t.labStorageCode,
remark: t.workOrderRemark || t.remark,
createTime: t.workOrderCreateTime || t.createTime || ''
}
}
export function groupMineTasksByWorkOrder(tasks: ProductionTaskRow[]): MineWorkOrderEntry[] {
const map = new Map<string, ProductionTaskRow[]>()
const order: string[] = []
for (const row of tasks) {
const key = row.workOrderId || row.workOrderNo || row.id
if (!map.has(key)) {
map.set(key, [])
order.push(key)
}
map.get(key)!.push(row)
}
return order.map((workOrderId) => {
const groupTasks = map.get(workOrderId)!
return {
workOrderId,
workOrder: buildWorkOrderFromTasks(groupTasks),
activeTypeTab: resolveWorkOrderTypeTab(groupTasks[0]),
tasks: groupTasks
}
})
}
export function buildPresetTasksMap(entries: MineWorkOrderEntry[]): Record<string, ProductionTaskRow[]> {
const map: Record<string, ProductionTaskRow[]> = {}
for (const entry of entries) {
map[entry.workOrder.id] = entry.tasks
}
return map
}
async function fetchMineTasksByScope(
scope: 'current' | 'history',
filters: ProductionTaskMineFilters
): Promise<ProductionTaskRow[]> {
const pageSize = MINE_TASK_FETCH_PAGE_SIZE
let page = 1
const all: ProductionTaskRow[] = []
let total = 0
while (true) {
const res = await fetchMyProductionTasks({
scope,
page,
pageSize,
keyword: filters.keyword || undefined,
taskStatus: filters.taskStatus || undefined,
workOrderType: filters.workOrderType || undefined
})
const list = res.list || []
all.push(...list)
total = res.total || 0
if (!list.length || all.length >= total) break
page += 1
}
return all
}
/** 合并当前负责人任务与曾转发任务(方案 C:单列表) */
export async function fetchAllMineProductionTasks(
filters: ProductionTaskMineFilters
): Promise<ProductionTaskRow[]> {
const [current, history] = await Promise.all([
fetchMineTasksByScope('current', filters),
fetchMineTasksByScope('history', filters)
])
const map = new Map<string, ProductionTaskRow>()
for (const row of [...current, ...history]) {
if (row.id) map.set(row.id, row)
}
return [...map.values()]
}
export async function enrichMineEntriesWithWorkOrders(
entries: MineWorkOrderEntry[]
): Promise<MineWorkOrderEntry[]> {
const cache = new Map<string, ProductionWorkOrderItem>()
const uniqueIds = [...new Set(entries.map((entry) => entry.workOrderId))]
await Promise.all(
uniqueIds.map(async (id) => {
try {
const detail = await fetchProductionWorkOrderDetail(id)
cache.set(id, detail)
} catch {
// 保留任务聚合的工单摘要
}
})
)
return entries.map((entry) => {
const detail = cache.get(entry.workOrderId)
if (!detail) return entry
return {
...entry,
workOrder: {
...entry.workOrder,
...detail,
paymentSummary: detail.paymentSummary ?? entry.workOrder.paymentSummary,
feeSummary: detail.feeSummary ?? entry.workOrder.feeSummary
}
}
})
}
export function filterMineEntriesByWorkOrderSearch(
entries: MineWorkOrderEntry[],
filters: MineWorkOrderSearchFilters
): MineWorkOrderEntry[] {
const tab = filters.activeTypeTab
return entries.filter((entry) => {
const row = entry.workOrder
if (row.workOrderType && row.workOrderType !== tab) return false
if (entry.activeTypeTab !== tab) return false
if (filters.workOrderStatus && row.workOrderStatus !== filters.workOrderStatus) return false
if (tab === 'outbound' && filters.bizType && row.bizType !== filters.bizType) return false
if (!keywordMatchesWorkOrder(row, filters.keyword || '', tab)) return false
if (tab === 'outbound') {
if (!dateInRange(row.infusionTime, filters.infusionTimeStart, filters.infusionTimeEnd)) {
return false
}
} else if (!dateInRange(row.createTime, filters.createTimeStart, filters.createTimeEnd)) {
return false
}
return true
})
}
export function paginateMineEntries<T>(items: T[], page: number, pageSize: number) {
const safePage = Math.max(1, page)
const safeSize = Math.max(1, pageSize)
const start = (safePage - 1) * safeSize
return {
total: items.length,
items: items.slice(start, start + safeSize)
}
}
export function buildMineTableRows(pageEntries: MineWorkOrderEntry[]): {
rows: ProductionWorkOrderItem[]
presetTasksByWorkOrderId: Record<string, ProductionTaskRow[]>
} {
return {
rows: pageEntries.map((e) => e.workOrder),
presetTasksByWorkOrderId: buildPresetTasksMap(pageEntries)
}
}