胶料快检添加离线模式
This commit is contained in:
@@ -223,10 +223,10 @@ export const rawLineJVxeColumns: JVxeColumn[] = [
|
||||
componentProps: numProps,
|
||||
},
|
||||
{
|
||||
title: '行检验结果',
|
||||
title: '单次检验结果',
|
||||
key: 'rowInspectResult',
|
||||
type: JVxeTypes.select,
|
||||
width: 110,
|
||||
width: 130,
|
||||
disabled: true,
|
||||
dictCode: 'xslmes_rubber_quick_test_record_result',
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
width="1200px"
|
||||
@register="registerModal"
|
||||
@ok="handleSubmit"
|
||||
@visible-change="onModalVisibleChange"
|
||||
>
|
||||
<BasicForm @register="registerForm">
|
||||
<template #prodEquipmentPicker="{ model, field }">
|
||||
@@ -25,64 +26,108 @@
|
||||
</BasicForm>
|
||||
|
||||
<template v-if="useNewDetail">
|
||||
<a-divider orientation="left">数据标准明细</a-divider>
|
||||
<JVxeTable
|
||||
v-if="tableReady"
|
||||
row-number
|
||||
keep-source
|
||||
:toolbar="false"
|
||||
:insert-row="false"
|
||||
:remove-btn="false"
|
||||
:max-height="260"
|
||||
:loading="detailLoading"
|
||||
:columns="stdLineJVxeColumns"
|
||||
:dataSource="stdLineDataSource"
|
||||
disabled
|
||||
/>
|
||||
<div class="detail-section">
|
||||
<div class="detail-section__header">
|
||||
<span class="detail-section__accent" />
|
||||
<div class="detail-section__titles">
|
||||
<span class="detail-section__title">数据标准明细</span>
|
||||
<span class="detail-section__desc">实验标准数据点及上下限快照</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-section__body">
|
||||
<JVxeTable
|
||||
v-if="tableReady"
|
||||
row-number
|
||||
keep-source
|
||||
:toolbar="false"
|
||||
:insert-row="false"
|
||||
:remove-btn="false"
|
||||
:max-height="260"
|
||||
:loading="detailLoading"
|
||||
:columns="stdLineJVxeColumns"
|
||||
:dataSource="stdLineDataSource"
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a-divider orientation="left">试验结果明细</a-divider>
|
||||
<JVxeTable
|
||||
v-if="tableReady"
|
||||
row-number
|
||||
keep-source
|
||||
:toolbar="false"
|
||||
:insert-row="false"
|
||||
:remove-btn="false"
|
||||
:max-height="320"
|
||||
:loading="detailLoading"
|
||||
:columns="rawLineJVxeColumns"
|
||||
:dataSource="rawLineDataSource"
|
||||
:disabled="isDetail"
|
||||
/>
|
||||
<div class="detail-section">
|
||||
<div class="detail-section__header">
|
||||
<span class="detail-section__accent detail-section__accent--green" />
|
||||
<div class="detail-section__titles">
|
||||
<span class="detail-section__title">试验结果明细</span>
|
||||
<span class="detail-section__desc">各次试验检测值与单次检验结果</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-section__body">
|
||||
<JVxeTable
|
||||
v-if="tableReady"
|
||||
row-number
|
||||
keep-source
|
||||
:toolbar="false"
|
||||
:insert-row="false"
|
||||
:remove-btn="false"
|
||||
:max-height="320"
|
||||
:loading="detailLoading"
|
||||
:columns="rawLineJVxeColumns"
|
||||
:dataSource="rawLineDataSource"
|
||||
:disabled="isDetail"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a-divider orientation="left">曲线图</a-divider>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<div class="chart-title">温度曲线(上模/下模)</div>
|
||||
<div ref="tempChartRef" class="chart-box"></div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<div class="chart-title">S'(dNm) 曲线</div>
|
||||
<div ref="torqueChartRef" class="chart-box"></div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<div class="detail-section detail-section--chart">
|
||||
<div class="detail-section__header">
|
||||
<span class="detail-section__accent detail-section__accent--orange" />
|
||||
<div class="detail-section__titles">
|
||||
<span class="detail-section__title">曲线图明细</span>
|
||||
<span class="detail-section__desc">密炼过程温度与扭矩曲线</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-section__body detail-section__body--chart">
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<div class="chart-card">
|
||||
<div class="chart-card__title">温度曲线(上模 / 下模)</div>
|
||||
<div ref="tempChartRef" class="chart-box"></div>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<div class="chart-card">
|
||||
<div class="chart-card__title">S'(dNm) 曲线</div>
|
||||
<div ref="torqueChartRef" class="chart-box"></div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<a-divider orientation="left">检验明细(历史数据)</a-divider>
|
||||
<JVxeTable
|
||||
v-if="tableReady"
|
||||
row-number
|
||||
keep-source
|
||||
:toolbar="false"
|
||||
:insert-row="false"
|
||||
:remove-btn="false"
|
||||
:max-height="380"
|
||||
:loading="detailLoading"
|
||||
:columns="lineJVxeColumns"
|
||||
:dataSource="lineDataSource"
|
||||
:disabled="isDetail"
|
||||
/>
|
||||
<div class="detail-section">
|
||||
<div class="detail-section__header">
|
||||
<span class="detail-section__accent detail-section__accent--gray" />
|
||||
<div class="detail-section__titles">
|
||||
<span class="detail-section__title">检验明细(历史数据)</span>
|
||||
<span class="detail-section__desc">旧版汇总检验数据</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-section__body">
|
||||
<JVxeTable
|
||||
v-if="tableReady"
|
||||
row-number
|
||||
keep-source
|
||||
:toolbar="false"
|
||||
:insert-row="false"
|
||||
:remove-btn="false"
|
||||
:max-height="380"
|
||||
:loading="detailLoading"
|
||||
:columns="lineJVxeColumns"
|
||||
:dataSource="lineDataSource"
|
||||
:disabled="isDetail"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<MesXslEquipmentLedgerSelectModal @register="registerLedgerModal" @select="onLedgerSelect" />
|
||||
@@ -102,7 +147,13 @@
|
||||
stdLineJVxeColumns,
|
||||
rawLineJVxeColumns,
|
||||
} from '../MesXslRubberQuickTestRecord.data';
|
||||
import { saveOrUpdate, queryById, queryChartPointListByRecordId } from '../MesXslRubberQuickTestRecord.api';
|
||||
import {
|
||||
saveOrUpdate,
|
||||
queryById,
|
||||
queryChartPointListByRecordId,
|
||||
queryStdLineListByRecordId,
|
||||
queryRawLineListByRecordId,
|
||||
} from '../MesXslRubberQuickTestRecord.api';
|
||||
import MesXslEquipmentLedgerSelectModal from '/@/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipmentLedgerSelectModal.vue';
|
||||
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
@@ -135,6 +186,35 @@
|
||||
|
||||
const [registerLedgerModal, { openModal: openLedgerModal }] = useModal();
|
||||
|
||||
function unwrapApiList(payload: unknown): Recordable[] {
|
||||
if (Array.isArray(payload)) return payload;
|
||||
if (payload && typeof payload === 'object') {
|
||||
const result = (payload as Recordable).result;
|
||||
if (Array.isArray(result)) return result;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function unwrapApiRecord(payload: unknown): Recordable {
|
||||
if (payload && typeof payload === 'object' && (payload as Recordable).id != null) {
|
||||
return payload as Recordable;
|
||||
}
|
||||
if (payload && typeof payload === 'object' && (payload as Recordable).result) {
|
||||
return ((payload as Recordable).result ?? {}) as Recordable;
|
||||
}
|
||||
return (payload ?? {}) as Recordable;
|
||||
}
|
||||
|
||||
function normalizeChartPoint(point: Recordable): Recordable {
|
||||
return {
|
||||
sortNo: point.sortNo ?? point.sort_no ?? 0,
|
||||
timeMin: point.timeMin ?? point.time_min,
|
||||
upperTemp: point.upperTemp ?? point.upper_temp,
|
||||
lowerTemp: point.lowerTemp ?? point.lower_temp,
|
||||
torqueS: point.torqueS ?? point.torque_s,
|
||||
};
|
||||
}
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
tableReady.value = false;
|
||||
stdLineDataSource.value = [];
|
||||
@@ -149,9 +229,9 @@
|
||||
|
||||
if (data?.record?.id) {
|
||||
detailLoading.value = true;
|
||||
const recordId = data.record.id as string;
|
||||
try {
|
||||
const mainRaw = await queryById({ id: data.record.id });
|
||||
const m = (mainRaw as any)?.id != null ? mainRaw : (mainRaw as any)?.result ?? mainRaw;
|
||||
const m = unwrapApiRecord(await queryById({ id: recordId }));
|
||||
const patch: Recordable = { ...m };
|
||||
if (data?.showFooter && !patch.inspectorRealname && !patch.inspectorUserId) {
|
||||
const user = userStore.getUserInfo || {};
|
||||
@@ -161,22 +241,35 @@
|
||||
}
|
||||
await setFieldsValue(patch);
|
||||
|
||||
const stdLines = m?.stdLineList ?? [];
|
||||
const rawLines = m?.rawLineList ?? [];
|
||||
let chartPoints = m?.chartPointList ?? [];
|
||||
const legacyLines = m?.lineList ?? [];
|
||||
let stdLines = unwrapApiList(m?.stdLineList);
|
||||
let rawLines = unwrapApiList(m?.rawLineList);
|
||||
const legacyLines = unwrapApiList(m?.lineList);
|
||||
|
||||
if (stdLines.length > 0 || rawLines.length > 0 || chartPoints.length > 0) {
|
||||
if (!stdLines.length) {
|
||||
try {
|
||||
stdLines = unwrapApiList(await queryStdLineListByRecordId({ id: recordId }));
|
||||
} catch (_) {
|
||||
stdLines = [];
|
||||
}
|
||||
}
|
||||
if (!rawLines.length) {
|
||||
try {
|
||||
rawLines = unwrapApiList(await queryRawLineListByRecordId({ id: recordId }));
|
||||
} catch (_) {
|
||||
rawLines = [];
|
||||
}
|
||||
}
|
||||
|
||||
if (stdLines.length > 0 || rawLines.length > 0) {
|
||||
useNewDetail.value = true;
|
||||
stdLineDataSource.value = stdLines;
|
||||
rawLineDataSource.value = rawLines;
|
||||
if (!chartPoints.length && data?.record?.id) {
|
||||
try {
|
||||
const chartRes = await queryChartPointListByRecordId({ id: data.record.id });
|
||||
chartPoints = Array.isArray(chartRes) ? chartRes : (chartRes as any)?.result ?? [];
|
||||
} catch (_) {
|
||||
chartPoints = [];
|
||||
}
|
||||
|
||||
let chartPoints: Recordable[] = [];
|
||||
try {
|
||||
chartPoints = unwrapApiList(await queryChartPointListByRecordId({ id: recordId })).map(normalizeChartPoint);
|
||||
} catch (_) {
|
||||
chartPoints = unwrapApiList(m?.chartPointList).map(normalizeChartPoint);
|
||||
}
|
||||
chartPointDataSource.value = chartPoints;
|
||||
} else {
|
||||
@@ -195,19 +288,48 @@
|
||||
async function scheduleRenderCharts(points: Recordable[]) {
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
window.setTimeout(() => {
|
||||
renderCharts(points);
|
||||
resizeTempChart();
|
||||
resizeTorqueChart();
|
||||
}, 120);
|
||||
await new Promise<void>((resolve) => {
|
||||
window.setTimeout(() => {
|
||||
renderCharts(points);
|
||||
resizeTempChart();
|
||||
resizeTorqueChart();
|
||||
resolve();
|
||||
}, 280);
|
||||
});
|
||||
}
|
||||
|
||||
function onModalVisibleChange(visible: boolean) {
|
||||
if (visible && useNewDetail.value) {
|
||||
scheduleRenderCharts(chartPointDataSource.value);
|
||||
}
|
||||
}
|
||||
|
||||
watch(useNewDetail, async (visible) => {
|
||||
if (visible && chartPointDataSource.value.length) {
|
||||
if (visible) {
|
||||
await scheduleRenderCharts(chartPointDataSource.value);
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => [useNewDetail.value, tempChartRef.value, torqueChartRef.value] as const,
|
||||
([visible, tempEl, torqueEl]) => {
|
||||
if (visible && tempEl && torqueEl) {
|
||||
scheduleRenderCharts(chartPointDataSource.value);
|
||||
}
|
||||
},
|
||||
{ flush: 'post' },
|
||||
);
|
||||
|
||||
watch(
|
||||
chartPointDataSource,
|
||||
async (points) => {
|
||||
if (useNewDetail.value && points?.length) {
|
||||
await scheduleRenderCharts(points);
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
const title = computed(() => (unref(isDetail) ? '快检记录详情' : '编辑胶料快检记录'));
|
||||
|
||||
function toChartNumber(value: unknown) {
|
||||
@@ -217,24 +339,27 @@
|
||||
}
|
||||
|
||||
function renderCharts(points: Recordable[]) {
|
||||
if (!points?.length) {
|
||||
const normalized = (points ?? []).map((p) => normalizeChartPoint(p));
|
||||
if (!normalized.length) {
|
||||
setTempChartOptions({ title: { text: '暂无曲线数据', left: 'center', top: 'center', textStyle: { fontSize: 14 } } });
|
||||
setTorqueChartOptions({ title: { text: '暂无曲线数据', left: 'center', top: 'center', textStyle: { fontSize: 14 } } });
|
||||
return;
|
||||
}
|
||||
const sorted = [...points].sort((a, b) => (a.sortNo ?? 0) - (b.sortNo ?? 0));
|
||||
const times = sorted.map((p) => toChartNumber(p.timeMin) ?? 0);
|
||||
const sorted = [...normalized].sort((a, b) => (Number(a.sortNo) || 0) - (Number(b.sortNo) || 0));
|
||||
const tempUpper = sorted.map((p) => [toChartNumber(p.timeMin) ?? 0, toChartNumber(p.upperTemp)]);
|
||||
const tempLower = sorted.map((p) => [toChartNumber(p.timeMin) ?? 0, toChartNumber(p.lowerTemp)]);
|
||||
const torque = sorted.map((p) => [toChartNumber(p.timeMin) ?? 0, toChartNumber(p.torqueS)]);
|
||||
|
||||
setTempChartOptions({
|
||||
title: undefined,
|
||||
tooltip: { trigger: 'axis' },
|
||||
legend: { data: ['上模温度', '下模温度'] },
|
||||
grid: { left: 48, right: 24, top: 40, bottom: 32 },
|
||||
xAxis: { type: 'category', name: '时间(min)', data: times },
|
||||
yAxis: { type: 'value', name: '温度(℃)', min: 189, max: 201, interval: 3 },
|
||||
xAxis: { type: 'value', name: '时间(min)', min: 0, max: 2, interval: 0.5 },
|
||||
yAxis: { type: 'value', name: '温度(℃)', scale: true },
|
||||
series: [
|
||||
{ name: '上模温度', type: 'line', smooth: true, data: sorted.map((p) => toChartNumber(p.upperTemp)) },
|
||||
{ name: '下模温度', type: 'line', smooth: true, data: sorted.map((p) => toChartNumber(p.lowerTemp)) },
|
||||
{ name: '上模温度', type: 'line', smooth: true, showSymbol: true, data: tempUpper },
|
||||
{ name: '下模温度', type: 'line', smooth: true, showSymbol: true, data: tempLower },
|
||||
],
|
||||
});
|
||||
|
||||
@@ -243,9 +368,9 @@
|
||||
tooltip: { trigger: 'axis' },
|
||||
legend: { data: ["S'(dNm)"] },
|
||||
grid: { left: 48, right: 24, top: 40, bottom: 32 },
|
||||
xAxis: { type: 'category', name: '时间(min)', data: times },
|
||||
yAxis: { type: 'value', name: "S'(dNm)", min: 0, max: 14.8 },
|
||||
series: [{ name: "S'(dNm)", type: 'line', smooth: true, data: sorted.map((p) => toChartNumber(p.torqueS)) }],
|
||||
xAxis: { type: 'value', name: '时间(min)', min: 0, max: 2, interval: 0.5 },
|
||||
yAxis: { type: 'value', name: "S'(dNm)", scale: true },
|
||||
series: [{ name: "S'(dNm)", type: 'line', smooth: true, showSymbol: true, data: torque }],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -331,13 +456,96 @@
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chart-title {
|
||||
font-size: 13px;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
margin-bottom: 8px;
|
||||
.detail-section {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.detail-section:first-of-type {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.detail-section__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 14px;
|
||||
background: linear-gradient(90deg, #f7f9fc 0%, #fafbfc 100%);
|
||||
border: 1px solid #eef1f5;
|
||||
border-bottom: none;
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
.detail-section__accent {
|
||||
flex-shrink: 0;
|
||||
width: 4px;
|
||||
height: 18px;
|
||||
border-radius: 2px;
|
||||
background: var(--j-global-primary-color, #1677ff);
|
||||
}
|
||||
|
||||
.detail-section__accent--green {
|
||||
background: #52c41a;
|
||||
}
|
||||
|
||||
.detail-section__accent--orange {
|
||||
background: #fa8c16;
|
||||
}
|
||||
|
||||
.detail-section__accent--gray {
|
||||
background: #8c8c8c;
|
||||
}
|
||||
|
||||
.detail-section__titles {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.detail-section__title {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 1.35;
|
||||
color: rgba(0, 0, 0, 0.88);
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.detail-section__desc {
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
.detail-section__body {
|
||||
padding: 12px;
|
||||
background: #fff;
|
||||
border: 1px solid #eef1f5;
|
||||
border-radius: 0 0 8px 8px;
|
||||
}
|
||||
|
||||
.detail-section__body--chart {
|
||||
padding: 12px 12px 4px;
|
||||
}
|
||||
|
||||
.chart-card {
|
||||
padding: 10px 12px 8px;
|
||||
background: #fafbfc;
|
||||
border: 1px solid #f0f2f5;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.chart-card__title {
|
||||
margin-bottom: 8px;
|
||||
padding-left: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: rgba(0, 0, 0, 0.72);
|
||||
border-left: 2px solid rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.chart-box {
|
||||
width: 100%;
|
||||
height: 220px;
|
||||
min-height: 220px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user