Files
DashBoard/frontend/src/query-tool/utils/values.js
egg 5b358d71c1 feat(query-tool): rewrite frontend with ECharts tree, multi-select, and modular composables
Replace the monolithic useQueryToolData composable and nested Vue component tree
with a modular architecture: useLotResolve, useLotLineage, useLotDetail, and
useEquipmentQuery. Introduce ECharts TreeChart (LR orthogonal layout) for lot
lineage visualization with multi-select support, subtree expansion, zoom/pan,
and serial number normalization. Add unified LineageEngine backend with split
descendant traversal and leaf serial number queries. Archive the query-tool-rewrite
openspec change and sync delta specs to main.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 15:25:00 +08:00

94 lines
2.4 KiB
JavaScript

export function normalizeText(value) {
return String(value || '').trim();
}
export function uniqueValues(values = []) {
const seen = new Set();
const list = [];
values.forEach((value) => {
const normalized = normalizeText(value);
if (!normalized || seen.has(normalized)) {
return;
}
seen.add(normalized);
list.push(normalized);
});
return list;
}
export function parseInputValues(raw) {
return uniqueValues(String(raw || '').split(/[\n,]/));
}
export function parseArrayParam(params, key) {
const repeated = params.getAll(key).map((item) => normalizeText(item)).filter(Boolean);
if (repeated.length > 0) {
return uniqueValues(repeated);
}
const fallback = normalizeText(params.get(key));
if (!fallback) {
return [];
}
return uniqueValues(fallback.split(','));
}
export function toDateInputValue(value) {
if (!value) {
return '';
}
const date = value instanceof Date ? value : new Date(value);
if (Number.isNaN(date.getTime())) {
return '';
}
return date.toISOString().slice(0, 10);
}
export function parseDateTime(value) {
if (!value) {
return null;
}
if (value instanceof Date) {
return Number.isNaN(value.getTime()) ? null : value;
}
const date = new Date(String(value).replace(' ', 'T'));
if (Number.isNaN(date.getTime())) {
return null;
}
return date;
}
export function formatDateTime(value) {
const date = parseDateTime(value);
if (!date) {
return '-';
}
const year = date.getFullYear();
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 `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}
export function formatCellValue(value) {
if (value === null || value === undefined || value === '') {
return '-';
}
if (typeof value === 'number') {
return Number.isFinite(value) ? value.toLocaleString() : '-';
}
return String(value);
}
export function hashColor(seed) {
const text = normalizeText(seed) || 'fallback';
let hash = 0;
for (let i = 0; i < text.length; i += 1) {
hash = (hash << 5) - hash + text.charCodeAt(i);
hash |= 0;
}
const hue = Math.abs(hash) % 360;
return `hsl(${hue} 70% 52%)`;
}