import { PLAN_COLOR_PALETTE } from './project-gantt.constants'; export function createSearchQuery() { return { routingName: '', productName: '', planCode: '' }; } export function createHoverTooltipState() { return { visible: false, content: '', style: { left: '0px', top: '0px' } }; } export function parseDate(value) { if (!value) { return null; } const date = value instanceof Date ? new Date(value) : new Date(String(value).replace(/-/g, '/')); if (Number.isNaN(date.getTime())) { return null; } return date; } export function startOfDay(date) { const target = new Date(date); target.setHours(0, 0, 0, 0); return target; } export function startOfMonth(date) { return new Date(date.getFullYear(), date.getMonth(), 1); } export function endOfMonth(date) { return new Date(date.getFullYear(), date.getMonth() + 1, 0); } export function formatDateKey(date) { const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${date.getFullYear()}-${month}-${day}`; } export function escapeHtml(value) { return String(value == null ? '' : value) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } export function formatDateTime(value) { if (!value) { return ''; } if (typeof value === 'string') { return value; } const date = parseDate(value); if (!date) { return ''; } const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hour = String(date.getHours()).padStart(2, '0'); const minute = String(date.getMinutes()).padStart(2, '0'); const second = String(date.getSeconds()).padStart(2, '0'); return `${date.getFullYear()}-${month}-${day} ${hour}:${minute}:${second}`; } export function buildCalendarTooltipHtml(entries) { const list = Array.isArray(entries) ? entries : [entries]; const blocks = list .map((entry, index) => { const rows = [ { label: '产品名称', value: entry.productName || '' }, { label: '工艺路线', value: entry.routingName || '' }, { label: entry.productionOrderNumber ? '生产订单号' : '计划编码', value: entry.productionOrderNumber || entry.planCode || '' }, { label: '产品编码', value: entry.productCode || '' }, { label: '数量', value: entry.qty }, { label: '规格', value: entry.specification || '' }, { label: '型号', value: entry.modeType || '' }, { label: '工位', value: entry.resourceName || '' }, { label: '编码', value: entry.resourceCode || '' } ].filter( (item) => item.value !== '' && item.value !== null && item.value !== undefined ); return `
${ list.length > 1 ? `
数据${ index + 1 }
` : '' } ${rows .map( (item) => `
${escapeHtml( item.label )}: ${escapeHtml( item.value )}
` ) .join('')}
`; }) .join(''); return `
工作日历详情${list.length > 1 ? `(${list.length}条)` : ''}
${blocks}
`; } export function buildTooltipHtml( task, planMetaByCode = {}, activeTab = '', resourceLabelMode = 'plan' ) { const planMeta = planMetaByCode[task.code] || {}; const quantityText = [ task.qty ?? task.productNum ?? planMeta.productNum, task.measuringUnit || task.unit || planMeta.measuringUnit || planMeta.unit ] .filter((item) => item !== '' && item !== null && item !== undefined) .join(''); const isOrderSchedulingTooltip = resourceLabelMode === 'order'; const orderTitleValue = task.productionOrderNumber || task.apsWorkOrderCode || task.workOrderCode || task.productionOrderCode || planMeta.productionOrderNumber || planMeta.apsWorkOrderCode || planMeta.workOrderCode || task.planCode || planMeta.planCode || planMeta.code || task.code || planMeta.productName || task.productName || ''; const title = isOrderSchedulingTooltip ? ['订单', orderTitleValue].filter(Boolean).join(':') || '订单信息' : [task.title, task.name || task.text || planMeta.productName] .filter(Boolean) .join(':') || task.code || '任务信息'; const resourceRows = activeTab === 'team' ? [ { label: '工位', value: task.resourceName || '' }, { label: '编码', value: task.resourceCode || '' } ] : []; const rows = [ { label: '计划编号', value: planMeta.code || planMeta.planCode || task.code || '' }, { label: '开始时间', value: formatDateTime( task.rawStartDate || task.start_date || planMeta.startTime ) }, { label: '结束时间', value: formatDateTime( task.rawEndDate || task.end_date || planMeta.endTime ) }, { label: '产品名称', value: isOrderSchedulingTooltip ? planMeta.productName || task.productName || '' : planMeta.productName || task.text || task.name || '' }, { label: '数量', value: quantityText }, { label: '工艺路线', value: task.routingName || planMeta.routingName || planMeta.produceRoutingName || '' }, { label: '规格', value: planMeta.specification || planMeta.spec || '' }, { label: '型号', value: task.modeType || planMeta.modeType || planMeta.model || '' }, { label: '批次号', value: task.batchNo || task.batchNumber || task.batchCode || planMeta.batchNo || planMeta.batchNumber || planMeta.batchCode || '' }, ...resourceRows, ...(resourceLabelMode === 'order' ? [] : [ { label: activeTab === 'factory' ? '工厂' : '班组', value: task.teamName || planMeta.teamName || planMeta.executionTeamName || '' } ]) ].filter((item) => item.value); return `
${escapeHtml(title)}
${rows .map( (item) => `
${escapeHtml( item.label )}: ${escapeHtml( item.value )}
` ) .join('')}
`; } export function resolveTaskColor(type) { if (type == 1) return '#02a7f0'; if (type == 2) return '#fec0dc'; if (type == 3) return '#62ddd4'; if (type == 4) return '#d1a6ff'; if (type == 5) return '#0e85fa'; return '#8fb7ff'; } export function hashString(value) { const text = String(value || ''); let hash = 0; for (let i = 0; i < text.length; i++) { hash = (hash << 5) - hash + text.charCodeAt(i); hash |= 0; } return Math.abs(hash); } export function resolvePlanColor(planKey) { if (!planKey) { return PLAN_COLOR_PALETTE[0]; } return PLAN_COLOR_PALETTE[hashString(planKey) % PLAN_COLOR_PALETTE.length]; }