混炼示方优化
This commit is contained in:
@@ -80,3 +80,23 @@ export async function loadRecordWithTrace(
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
/** 业务页签章区展示(起草取主表,校对/审核/批准取痕迹表) */
|
||||
export interface BizSignDisplay {
|
||||
draftBy: string;
|
||||
proofreadBy: string;
|
||||
auditBy: string;
|
||||
approveBy: string;
|
||||
}
|
||||
|
||||
export function buildBizSignDisplay(
|
||||
row: Recordable = {},
|
||||
resolveDraftBy: (record: Recordable) => string,
|
||||
): BizSignDisplay {
|
||||
return {
|
||||
draftBy: resolveDraftBy(row) || '',
|
||||
proofreadBy: row.traceProofreadBy || '',
|
||||
auditBy: row.traceAuditBy || '',
|
||||
approveBy: row.traceApproveBy || '',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ enum Api {
|
||||
queryById = '/xslmes/mesXslMixingSpec/queryById',
|
||||
queryIssueNumberOptions = '/xslmes/mesXslMixingSpec/queryIssueNumberOptions',
|
||||
queryPurposeOptions = '/xslmes/mesXslMixingSpec/queryPurposeOptions',
|
||||
updateSmallWeighRange = '/xslmes/mesXslMixingSpec/updateSmallWeighRange',
|
||||
}
|
||||
|
||||
export const getExportUrl = Api.exportXls;
|
||||
@@ -24,6 +25,7 @@ export const saveOrUpdate = (params, isUpdate) =>
|
||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A45】混炼示方主子表保存延长超时避免误报失败-----------
|
||||
export const queryIssueNumberOptions = (params) => defHttp.get({ url: Api.queryIssueNumberOptions, params });
|
||||
export const queryPurposeOptions = (params) => defHttp.get({ url: Api.queryPurposeOptions, params });
|
||||
export const updateSmallWeighRange = (params) => defHttp.post({ url: Api.updateSmallWeighRange, params });
|
||||
|
||||
export const deleteOne = (params, handleSuccess) =>
|
||||
defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => handleSuccess());
|
||||
|
||||
@@ -69,7 +69,15 @@ export const mainSchema: FormSchema[] = [
|
||||
{ label: '用途', field: 'purpose', component: 'Input', required: true, colProps: { span: 8 } },
|
||||
{ label: '机台', field: 'machineName', component: 'Input', colProps: { span: 8 } },
|
||||
{ label: '制作日期', field: 'makeDate', component: 'DatePicker', colProps: { span: 8 }, componentProps: { valueFormat: 'YYYY-MM-DD' } },
|
||||
{ label: '发行编号', field: 'issueNumber', component: 'Input', required: true, colProps: { span: 8 } },
|
||||
{
|
||||
label: '发行编号',
|
||||
field: 'issueNumber',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
colProps: { span: 8 },
|
||||
componentProps: { placeholder: '请点击选择密炼PS' },
|
||||
rules: [{ required: true, message: '请选择发行编号' }],
|
||||
},
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】混炼示方基本信息字段优化-----------
|
||||
{ label: '换算系数', field: 'convertFactor', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 2, style: { width: '100%' } } },
|
||||
{ label: '填充体积', field: 'fillVolume', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } },
|
||||
@@ -1387,7 +1395,7 @@ export function resolveMixingSpecFormulaStatus(record: Recordable = {}): string
|
||||
return '编制中';
|
||||
}
|
||||
|
||||
/** 混炼示方是否允许编辑/删除(与配合示方一致:仅编制状态可改) */
|
||||
/** 混炼示方是否允许删除(仅编制状态可删;编辑不受状态限制) */
|
||||
export function isMixingSpecEditable(record: Recordable = {}): boolean {
|
||||
//update-begin---author:cursor ---date:20260608 for:【XSLMES-20260608-A01】混炼示方编辑权限按状态字段判断-----------
|
||||
return !record?.status || record.status === 'compile';
|
||||
@@ -1471,3 +1479,180 @@ export function cloneMixingSpecPageForReferenceAdd(source: Recordable = {}): Rec
|
||||
};
|
||||
}
|
||||
//update-end---author:cursor ---date:20260526 for:【XSLMES-20260526-A59】规格点击选择混炼示方及参照新增-----------
|
||||
|
||||
//update-begin---author:cursor ---date:20260612 for:【XSLMES-20260612-A01】混炼示方列表查看人工/自动小料明细-----------
|
||||
/** 小料计量默认容差(KG),与旧系统施工表一致 */
|
||||
export const MIXING_SMALL_MATERIAL_WEIGH_TOLERANCE = 0.01;
|
||||
|
||||
/** 小料称重容差 */
|
||||
export interface MixingSmallWeighTolerance {
|
||||
lower: number;
|
||||
upper: number;
|
||||
}
|
||||
|
||||
/** 解析示方主表小料称重容差(未配置时默认 0.01) */
|
||||
export function resolveMixingSmallWeighTolerance(
|
||||
main: Recordable | null | undefined,
|
||||
type: MixingSmallMaterialViewType,
|
||||
): MixingSmallWeighTolerance {
|
||||
const lowerKey = type === 'manual' ? 'manualSmallWeighLowerTol' : 'autoSmallWeighLowerTol';
|
||||
const upperKey = type === 'manual' ? 'manualSmallWeighUpperTol' : 'autoSmallWeighUpperTol';
|
||||
const lower = toMixingMaterialNumber(main?.[lowerKey]);
|
||||
const upper = toMixingMaterialNumber(main?.[upperKey]);
|
||||
return {
|
||||
lower: lower != null && lower >= 0 ? lower : MIXING_SMALL_MATERIAL_WEIGH_TOLERANCE,
|
||||
upper: upper != null && upper >= 0 ? upper : MIXING_SMALL_MATERIAL_WEIGH_TOLERANCE,
|
||||
};
|
||||
}
|
||||
|
||||
/** 构建小料称重范围表单默认值 */
|
||||
export function buildMixingSmallWeighRangeForm(main: Recordable = {}): Recordable {
|
||||
const manual = resolveMixingSmallWeighTolerance(main, 'manual');
|
||||
const auto = resolveMixingSmallWeighTolerance(main, 'auto');
|
||||
return {
|
||||
id: main.id || '',
|
||||
specName: main.specName || '',
|
||||
manualSmallWeighLowerTol: manual.lower,
|
||||
manualSmallWeighUpperTol: manual.upper,
|
||||
autoSmallWeighLowerTol: auto.lower,
|
||||
autoSmallWeighUpperTol: auto.upper,
|
||||
};
|
||||
}
|
||||
|
||||
/** 小料查看类型 */
|
||||
export type MixingSmallMaterialViewType = 'manual' | 'auto';
|
||||
|
||||
export interface MixingSmallMaterialWeighRow {
|
||||
materialCode: string;
|
||||
standardWeight: number | null;
|
||||
lowerLimit: number | null;
|
||||
upperLimit: number | null;
|
||||
accumWeight: number | null;
|
||||
}
|
||||
|
||||
export interface MixingSmallMaterialAutoGroup {
|
||||
groupKey: string;
|
||||
groupLabel: string;
|
||||
rows: MixingSmallMaterialWeighRow[];
|
||||
}
|
||||
|
||||
/** 判断明细行是否属于人工小料(按种类/小类) */
|
||||
export function isMixingManualSmallMaterial(row: Recordable): boolean {
|
||||
if (!isMixingMaterialDataRow(row)) {
|
||||
return false;
|
||||
}
|
||||
const kind = String(row.materialKind || '').trim();
|
||||
const minor = String(row.materialMinor || '').trim();
|
||||
if (kind.includes('人工') || minor.includes('人工')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** 判断明细行是否属于自动小料(按种类/小类) */
|
||||
export function isMixingAutoSmallMaterial(row: Recordable): boolean {
|
||||
if (!isMixingMaterialDataRow(row)) {
|
||||
return false;
|
||||
}
|
||||
const kind = String(row.materialKind || '').trim();
|
||||
const minor = String(row.materialMinor || '').trim();
|
||||
if (kind.includes('自动') || minor.includes('自动')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** 解析自动小料分组标签:顺序未填默认 自动1-1 */
|
||||
export function resolveMixingAutoSmallGroupLabel(seqNo: unknown): string {
|
||||
const seq = toMixingMaterialNumber(seqNo);
|
||||
const suffix = seq != null && seq > 0 ? Math.round(seq) : 1;
|
||||
return `自动1-${suffix}`;
|
||||
}
|
||||
|
||||
/** 按顺序字段分组自动小料明细 */
|
||||
export function groupMixingAutoSmallMaterials(
|
||||
rows: Recordable[] = [],
|
||||
main?: Recordable,
|
||||
): MixingSmallMaterialAutoGroup[] {
|
||||
const filtered = (rows || []).filter(isMixingAutoSmallMaterial);
|
||||
if (!filtered.length) {
|
||||
return [];
|
||||
}
|
||||
const groupMap = new Map<string, Recordable[]>();
|
||||
const groupOrder: string[] = [];
|
||||
for (const row of filtered) {
|
||||
const label = resolveMixingAutoSmallGroupLabel(row.seqNo);
|
||||
if (!groupMap.has(label)) {
|
||||
groupMap.set(label, []);
|
||||
groupOrder.push(label);
|
||||
}
|
||||
groupMap.get(label)!.push(row);
|
||||
}
|
||||
groupOrder.sort((a, b) => resolveAutoGroupSortNo(a) - resolveAutoGroupSortNo(b));
|
||||
return groupOrder.map((label) => ({
|
||||
groupKey: label,
|
||||
groupLabel: label,
|
||||
rows: buildMixingSmallMaterialWeighRows(
|
||||
groupMap.get(label) || [],
|
||||
resolveMixingSmallWeighTolerance(main, 'auto'),
|
||||
),
|
||||
}));
|
||||
}
|
||||
|
||||
function resolveAutoGroupSortNo(groupLabel: string): number {
|
||||
const matched = groupLabel.match(/-(\d+)$/);
|
||||
if (!matched) {
|
||||
return 1;
|
||||
}
|
||||
const num = Number(matched[1]);
|
||||
return Number.isFinite(num) ? num : 1;
|
||||
}
|
||||
|
||||
/** 构建人工小料计量行 */
|
||||
export function buildMixingManualSmallMaterialRows(
|
||||
rows: Recordable[] = [],
|
||||
main?: Recordable,
|
||||
): MixingSmallMaterialWeighRow[] {
|
||||
return buildMixingSmallMaterialWeighRows(
|
||||
(rows || []).filter(isMixingManualSmallMaterial),
|
||||
resolveMixingSmallWeighTolerance(main, 'manual'),
|
||||
);
|
||||
}
|
||||
|
||||
/** 将明细行转为药品计量展示行(含累计标准重量) */
|
||||
export function buildMixingSmallMaterialWeighRows(
|
||||
rows: Recordable[] = [],
|
||||
tolerance: MixingSmallWeighTolerance = {
|
||||
lower: MIXING_SMALL_MATERIAL_WEIGH_TOLERANCE,
|
||||
upper: MIXING_SMALL_MATERIAL_WEIGH_TOLERANCE,
|
||||
},
|
||||
): MixingSmallMaterialWeighRow[] {
|
||||
let running = 0;
|
||||
let hasRunning = false;
|
||||
return (rows || []).map((row) => {
|
||||
const standardWeight = toMixingMaterialNumber(row.unitWeight);
|
||||
const lowerLimit =
|
||||
standardWeight != null ? roundMixingMaterialNumber(standardWeight - tolerance.lower) : null;
|
||||
const upperLimit =
|
||||
standardWeight != null ? roundMixingMaterialNumber(standardWeight + tolerance.upper) : null;
|
||||
if (standardWeight != null) {
|
||||
running += standardWeight;
|
||||
hasRunning = true;
|
||||
}
|
||||
const materialCode =
|
||||
String(row.mixerMaterialName || row.mixerMaterialDesc || row.materialKind || '').trim();
|
||||
return {
|
||||
materialCode,
|
||||
standardWeight,
|
||||
lowerLimit,
|
||||
upperLimit,
|
||||
accumWeight: standardWeight != null && hasRunning ? roundMixingMaterialNumber(running) : null,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/** 小料查看弹窗标题 */
|
||||
export function resolveMixingSmallMaterialViewTitle(viewType: MixingSmallMaterialViewType): string {
|
||||
return viewType === 'manual' ? '混炼母胶药品计量(人工)' : '混炼母胶药品计量(自动)';
|
||||
}
|
||||
//update-end---author:cursor ---date:20260612 for:【XSLMES-20260612-A01】混炼示方列表查看人工/自动小料明细-----------
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
|
||||
enum Api {
|
||||
listByMixingSpecId = '/xslmes/mesXslMixingSpecHistory/listByMixingSpecId',
|
||||
queryById = '/xslmes/mesXslMixingSpecHistory/queryById',
|
||||
}
|
||||
|
||||
export const listHistoryByMixingSpecId = (params) => defHttp.get({ url: Api.listByMixingSpecId, params });
|
||||
|
||||
export const queryHistoryById = (params) => defHttp.get({ url: Api.queryById, params });
|
||||
@@ -27,6 +27,9 @@
|
||||
</template>
|
||||
</BasicTable>
|
||||
<MesXslMixingSpecModal @register="registerModal" @success="handleSuccess" />
|
||||
<MesXslMixingSpecHistoryModal @register="registerHistoryModal" @viewDetail="handleViewHistoryDetail" />
|
||||
<MesXslMixingSmallMaterialViewModal @register="registerSmallMaterialModal" />
|
||||
<MesXslMixingSmallWeighRangeModal @register="registerWeighRangeModal" @success="handleSuccess" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -37,6 +40,9 @@
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import Icon from '/@/components/Icon';
|
||||
import MesXslMixingSpecModal from './components/MesXslMixingSpecModal.vue';
|
||||
import MesXslMixingSpecHistoryModal from './components/MesXslMixingSpecHistoryModal.vue';
|
||||
import MesXslMixingSmallMaterialViewModal from './components/MesXslMixingSmallMaterialViewModal.vue';
|
||||
import MesXslMixingSmallWeighRangeModal from './components/MesXslMixingSmallWeighRangeModal.vue';
|
||||
import { columns, searchFormSchema, isMixingSpecEditable } from './MesXslMixingSpec.data';
|
||||
import { list, deleteOne, batchDelete, getExportUrl, getImportUrl } from './MesXslMixingSpec.api';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
@@ -45,6 +51,9 @@
|
||||
|
||||
const queryParam = reactive<any>({});
|
||||
const [registerModal, { openModal }] = useModal();
|
||||
const [registerHistoryModal, { openModal: openHistoryModal }] = useModal();
|
||||
const [registerSmallMaterialModal, { openModal: openSmallMaterialModal }] = useModal();
|
||||
const [registerWeighRangeModal, { openModal: openWeighRangeModal }] = useModal();
|
||||
|
||||
const { tableContext, onExportXls, onImportXls } = useListPage({
|
||||
tableProps: {
|
||||
@@ -60,7 +69,7 @@
|
||||
actionColumn: {
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
width: 160,
|
||||
width: 260,
|
||||
fixed: 'right',
|
||||
slots: { customRender: 'action' },
|
||||
},
|
||||
@@ -84,10 +93,6 @@
|
||||
}
|
||||
|
||||
function handleEdit(record: Recordable) {
|
||||
if (!isMixingSpecEditable(record)) {
|
||||
createMessage.warning('已进入审批流程的混炼示方不允许编辑');
|
||||
return;
|
||||
}
|
||||
openModal(true, { record, isUpdate: true, showFooter: true });
|
||||
}
|
||||
|
||||
@@ -95,6 +100,32 @@
|
||||
openModal(true, { record, isUpdate: true, showFooter: false });
|
||||
}
|
||||
|
||||
function handleViewManualSmallMaterial(record: Recordable) {
|
||||
openSmallMaterialModal(true, { record, viewType: 'manual' });
|
||||
}
|
||||
|
||||
function handleViewAutoSmallMaterial(record: Recordable) {
|
||||
openSmallMaterialModal(true, { record, viewType: 'auto' });
|
||||
}
|
||||
|
||||
function handleSmallWeighRange(record: Recordable) {
|
||||
openWeighRangeModal(true, { record });
|
||||
}
|
||||
|
||||
function handleHistory(record: Recordable) {
|
||||
openHistoryModal(true, { record });
|
||||
}
|
||||
|
||||
function handleViewHistoryDetail(historyRecord: Recordable) {
|
||||
openModal(true, {
|
||||
historyId: historyRecord?.id,
|
||||
historyVersion: historyRecord?.versionNo,
|
||||
isUpdate: true,
|
||||
showFooter: false,
|
||||
isHistoryView: true,
|
||||
});
|
||||
}
|
||||
|
||||
function handleDelete(record: Recordable) {
|
||||
if (!isMixingSpecEditable(record)) {
|
||||
createMessage.warning('已进入审批流程的混炼示方不允许删除');
|
||||
@@ -116,26 +147,43 @@
|
||||
const editable = isMixingSpecEditable(record);
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
icon: 'ant-design:edit-outlined',
|
||||
tooltip: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
auth: 'xslmes:mes_xsl_mixing_spec:edit',
|
||||
ifShow: editable,
|
||||
},
|
||||
{
|
||||
label: '详情',
|
||||
icon: 'ant-design:eye-outlined',
|
||||
tooltip: '详情',
|
||||
onClick: handleDetail.bind(null, record),
|
||||
ifShow: !editable,
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
icon: 'ant-design:delete-outlined',
|
||||
tooltip: '删除',
|
||||
auth: 'xslmes:mes_xsl_mixing_spec:delete',
|
||||
ifShow: editable,
|
||||
popConfirm: { title: '是否确认删除', confirm: handleDelete.bind(null, record) },
|
||||
},
|
||||
{
|
||||
label: '详情',
|
||||
onClick: handleDetail.bind(null, record),
|
||||
ifShow: editable,
|
||||
icon: 'ant-design:user-outlined',
|
||||
tooltip: '查看人工小料',
|
||||
onClick: handleViewManualSmallMaterial.bind(null, record),
|
||||
},
|
||||
{
|
||||
icon: 'ant-design:robot-outlined',
|
||||
tooltip: '查看自动小料',
|
||||
onClick: handleViewAutoSmallMaterial.bind(null, record),
|
||||
},
|
||||
{
|
||||
icon: 'ant-design:column-width-outlined',
|
||||
tooltip: '小料称重范围',
|
||||
onClick: handleSmallWeighRange.bind(null, record),
|
||||
auth: 'xslmes:mes_xsl_mixing_spec:edit',
|
||||
},
|
||||
{
|
||||
icon: 'ant-design:history-outlined',
|
||||
tooltip: '历史记录',
|
||||
onClick: handleHistory.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,408 @@
|
||||
<template>
|
||||
<BasicModal
|
||||
v-bind="$attrs"
|
||||
destroyOnClose
|
||||
:width="'88%'"
|
||||
:title="modalTitle"
|
||||
:showOkBtn="false"
|
||||
cancelText="关闭"
|
||||
wrapClassName="mixing-small-material-view-modal"
|
||||
@register="registerModal"
|
||||
>
|
||||
<a-spin :spinning="loading">
|
||||
<div class="mixing-small-sheet">
|
||||
<table class="mixing-small-form-table">
|
||||
<colgroup>
|
||||
<col style="width: 22%" />
|
||||
<col style="width: 42%" />
|
||||
<col style="width: 9%" />
|
||||
<col style="width: 9%" />
|
||||
<col style="width: 9%" />
|
||||
<col style="width: 9%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="formTitle sheet-title-cell">{{ sheetTitle }}</th>
|
||||
<td class="formValue info-cell"></td>
|
||||
<th class="formTitle">起草</th>
|
||||
<th class="formTitle">校对</th>
|
||||
<th class="formTitle">审核</th>
|
||||
<th class="formTitle">批准</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="formTitle sheet-subtitle-cell">施工表</th>
|
||||
<td class="formValue info-cell">发行处:{{ displayText(mainForm.issueDept) }}</td>
|
||||
<td class="formValue sign-cell">{{ displaySign(signDisplay.draftBy) }}</td>
|
||||
<td class="formValue sign-cell">{{ displaySign(signDisplay.proofreadBy) }}</td>
|
||||
<td class="formValue sign-cell">{{ displaySign(signDisplay.auditBy) }}</td>
|
||||
<td class="formValue sign-cell">{{ displaySign(signDisplay.approveBy) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="formValue blank-cell"></td>
|
||||
<td class="formValue info-cell">发行编号:{{ displayText(mainForm.issueNumber) }}</td>
|
||||
<td class="formValue sign-cell"></td>
|
||||
<td class="formValue sign-cell"></td>
|
||||
<td class="formValue sign-cell"></td>
|
||||
<td class="formValue sign-cell"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="formValue blank-cell"></td>
|
||||
<td class="formValue info-cell">作成日:{{ displayText(mainForm.makeDate) }}</td>
|
||||
<td class="formValue sign-cell"></td>
|
||||
<td class="formValue sign-cell"></td>
|
||||
<td class="formValue sign-cell"></td>
|
||||
<td class="formValue sign-cell"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="formValue blank-cell"></td>
|
||||
<td class="formValue info-cell">适用工厂:{{ displayText(mainForm.applyFactory) }}</td>
|
||||
<td class="formValue sign-cell"></td>
|
||||
<td class="formValue sign-cell"></td>
|
||||
<td class="formValue sign-cell"></td>
|
||||
<td class="formValue sign-cell"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="formTitle key-label-cell">规 格</th>
|
||||
<td class="formValue key-value-cell" colspan="5">{{ displayText(mainForm.specName) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="formTitle key-label-cell">机 台</th>
|
||||
<td class="formValue key-value-cell" colspan="5">{{ displayText(mainForm.machineName) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="unit-label">单位:KG</div>
|
||||
|
||||
<template v-if="viewType === 'manual'">
|
||||
<table class="mixing-small-data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>药品CODE</th>
|
||||
<th>标准重量</th>
|
||||
<th>计量下限</th>
|
||||
<th>计量上限</th>
|
||||
<th>累计标准重量</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(row, index) in manualRows" :key="`manual-${index}`">
|
||||
<td>{{ row.materialCode }}</td>
|
||||
<td>{{ formatWeight(row.standardWeight) }}</td>
|
||||
<td>{{ formatWeight(row.lowerLimit) }}</td>
|
||||
<td>{{ formatWeight(row.upperLimit) }}</td>
|
||||
<td>{{ formatWeight(row.accumWeight) }}</td>
|
||||
</tr>
|
||||
<tr v-if="!manualRows.length">
|
||||
<td colspan="5" class="empty-cell">暂无人工小料明细</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<div v-for="group in autoGroups" :key="group.groupKey" class="auto-group-block">
|
||||
<div class="auto-group-title">{{ group.groupLabel }}</div>
|
||||
<table class="mixing-small-data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>药品CODE</th>
|
||||
<th>标准重量</th>
|
||||
<th>计量下限</th>
|
||||
<th>计量上限</th>
|
||||
<th>累计标准重量</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(row, index) in group.rows" :key="`${group.groupKey}-${index}`">
|
||||
<td>{{ row.materialCode }}</td>
|
||||
<td>{{ formatWeight(row.standardWeight) }}</td>
|
||||
<td>{{ formatWeight(row.lowerLimit) }}</td>
|
||||
<td>{{ formatWeight(row.upperLimit) }}</td>
|
||||
<td>{{ formatWeight(row.accumWeight) }}</td>
|
||||
</tr>
|
||||
<tr v-if="!group.rows.length">
|
||||
<td colspan="5" class="empty-cell">暂无数据</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div v-if="!autoGroups.length" class="empty-block">暂无自动小料明细</div>
|
||||
</template>
|
||||
|
||||
<table class="mixing-small-remark-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="formTitle">备注</th>
|
||||
<td class="formValue remark-cell"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</a-spin>
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { queryById } from '../MesXslMixingSpec.api';
|
||||
import {
|
||||
MixingSmallMaterialAutoGroup,
|
||||
MixingSmallMaterialViewType,
|
||||
MixingSmallMaterialWeighRow,
|
||||
buildMixingManualSmallMaterialRows,
|
||||
groupMixingAutoSmallMaterials,
|
||||
resolveMixingSmallMaterialViewTitle,
|
||||
} from '../MesXslMixingSpec.data';
|
||||
import { resolveFormulaSpecUserDisplayName } from '/@/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data';
|
||||
import {
|
||||
MIXING_SPEC_BIZ_TABLE,
|
||||
buildBizSignDisplay,
|
||||
loadRecordWithTrace,
|
||||
} from '/@/views/xslmes/approval/integration/traceRecordHelper';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
const userStore = useUserStore();
|
||||
|
||||
const loading = ref(false);
|
||||
const viewType = ref<MixingSmallMaterialViewType>('manual');
|
||||
const mainForm = ref<Recordable>({});
|
||||
const manualRows = ref<MixingSmallMaterialWeighRow[]>([]);
|
||||
const autoGroups = ref<MixingSmallMaterialAutoGroup[]>([]);
|
||||
const signDisplay = reactive({
|
||||
draftBy: '',
|
||||
proofreadBy: '',
|
||||
auditBy: '',
|
||||
approveBy: '',
|
||||
});
|
||||
|
||||
const sheetTitle = computed(() => resolveMixingSmallMaterialViewTitle(viewType.value));
|
||||
const modalTitle = computed(() => sheetTitle.value);
|
||||
|
||||
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
|
||||
viewType.value = data?.viewType === 'auto' ? 'auto' : 'manual';
|
||||
mainForm.value = {};
|
||||
manualRows.value = [];
|
||||
autoGroups.value = [];
|
||||
signDisplay.draftBy = '';
|
||||
signDisplay.proofreadBy = '';
|
||||
signDisplay.auditBy = '';
|
||||
signDisplay.approveBy = '';
|
||||
setModalProps({ loading: true });
|
||||
loading.value = true;
|
||||
try {
|
||||
const record = data?.record || {};
|
||||
if (!record?.id) {
|
||||
createMessage.warning('未找到混炼示方记录');
|
||||
return;
|
||||
}
|
||||
const detail = await loadRecordWithTrace(record.id, MIXING_SPEC_BIZ_TABLE, queryById, record);
|
||||
mainForm.value = {
|
||||
...detail,
|
||||
issueDept: detail?.issueDept || detail?.applyFactory || '',
|
||||
};
|
||||
const sign = buildBizSignDisplay(detail, (row) =>
|
||||
resolveFormulaSpecUserDisplayName(
|
||||
row.draftBy || row.createBy,
|
||||
row.draftBy_dictText || row.createBy_dictText,
|
||||
userStore.getUserInfo || {},
|
||||
),
|
||||
);
|
||||
signDisplay.draftBy = sign.draftBy;
|
||||
signDisplay.proofreadBy = sign.proofreadBy;
|
||||
signDisplay.auditBy = sign.auditBy;
|
||||
signDisplay.approveBy = sign.approveBy;
|
||||
const materialList = detail?.materialList || [];
|
||||
if (viewType.value === 'manual') {
|
||||
manualRows.value = buildMixingManualSmallMaterialRows(materialList, detail);
|
||||
} else {
|
||||
autoGroups.value = groupMixingAutoSmallMaterials(materialList, detail);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
createMessage.error('加载小料明细失败');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
setModalProps({ loading: false });
|
||||
}
|
||||
});
|
||||
|
||||
function displayText(value: unknown) {
|
||||
if (value == null || value === '') {
|
||||
return '';
|
||||
}
|
||||
return String(value);
|
||||
}
|
||||
|
||||
function displaySign(value: unknown) {
|
||||
const text = displayText(value);
|
||||
return text || '—';
|
||||
}
|
||||
|
||||
function formatWeight(value: number | null | undefined) {
|
||||
if (value == null) {
|
||||
return '';
|
||||
}
|
||||
const text = String(value);
|
||||
if (text.includes('.')) {
|
||||
return text.replace(/0+$/, '').replace(/\.$/, '');
|
||||
}
|
||||
return text;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@form-border: #ccc;
|
||||
@form-label-bg: #f5f5f5;
|
||||
|
||||
.mixing-small-sheet {
|
||||
border: 1px solid @form-border;
|
||||
background: #fcfdfd;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.mixing-small-form-table,
|
||||
.mixing-small-data-table,
|
||||
.mixing-small-remark-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.mixing-small-form-table {
|
||||
th.formTitle,
|
||||
td.formValue {
|
||||
border: 1px solid @form-border;
|
||||
height: 30px;
|
||||
padding: 0 8px;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
th.formTitle {
|
||||
background: @form-label-bg;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
td.formValue {
|
||||
background: #fff;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
th.sheet-title-cell {
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
th.sheet-subtitle-cell {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 6px;
|
||||
}
|
||||
|
||||
td.info-cell {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
td.blank-cell {
|
||||
background: @form-label-bg;
|
||||
}
|
||||
|
||||
th.key-label-cell {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
td.key-value-cell {
|
||||
height: 34px;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.unit-label {
|
||||
padding: 6px 8px 0;
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.mixing-small-data-table {
|
||||
margin-top: 4px;
|
||||
|
||||
th,
|
||||
td {
|
||||
border: 1px solid @form-border;
|
||||
height: 30px;
|
||||
padding: 0 6px;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
th {
|
||||
background: @form-label-bg;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
td {
|
||||
background: #fff;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.empty-cell {
|
||||
color: #999;
|
||||
height: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.auto-group-block {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.auto-group-title {
|
||||
padding: 5px 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
background: #e8e8e8;
|
||||
border: 1px solid @form-border;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.empty-block {
|
||||
margin: 16px 0;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.mixing-small-remark-table {
|
||||
margin-top: 10px;
|
||||
|
||||
th.formTitle {
|
||||
width: 80px;
|
||||
border: 1px solid @form-border;
|
||||
background: @form-label-bg;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
td.remark-cell {
|
||||
border: 1px solid @form-border;
|
||||
height: 72px;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<BasicModal
|
||||
v-bind="$attrs"
|
||||
destroyOnClose
|
||||
title="小料称重范围"
|
||||
:width="560"
|
||||
@register="registerModal"
|
||||
@ok="handleSubmit"
|
||||
>
|
||||
<a-spin :spinning="loading">
|
||||
<div class="weigh-range-tip">
|
||||
计量下限 = 标准重量 − 下限容差;计量上限 = 标准重量 + 上限容差。单位:KG,默认容差 0.01。
|
||||
</div>
|
||||
<div v-if="formState.specName" class="weigh-range-spec">规格:{{ formState.specName }}</div>
|
||||
|
||||
<a-divider orientation="left">人工小料</a-divider>
|
||||
<a-form layout="vertical">
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="下限容差" required>
|
||||
<a-input-number
|
||||
v-model:value="formState.manualSmallWeighLowerTol"
|
||||
:min="0"
|
||||
:precision="6"
|
||||
style="width: 100%"
|
||||
placeholder="默认 0.01"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="上限容差" required>
|
||||
<a-input-number
|
||||
v-model:value="formState.manualSmallWeighUpperTol"
|
||||
:min="0"
|
||||
:precision="6"
|
||||
style="width: 100%"
|
||||
placeholder="默认 0.01"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
|
||||
<a-divider orientation="left">自动小料</a-divider>
|
||||
<a-form layout="vertical">
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="下限容差" required>
|
||||
<a-input-number
|
||||
v-model:value="formState.autoSmallWeighLowerTol"
|
||||
:min="0"
|
||||
:precision="6"
|
||||
style="width: 100%"
|
||||
placeholder="默认 0.01"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="上限容差" required>
|
||||
<a-input-number
|
||||
v-model:value="formState.autoSmallWeighUpperTol"
|
||||
:min="0"
|
||||
:precision="6"
|
||||
style="width: 100%"
|
||||
placeholder="默认 0.01"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { queryById, updateSmallWeighRange } from '../MesXslMixingSpec.api';
|
||||
import { MIXING_SMALL_MATERIAL_WEIGH_TOLERANCE, buildMixingSmallWeighRangeForm } from '../MesXslMixingSpec.data';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
const loading = ref(false);
|
||||
const formState = reactive({
|
||||
id: '',
|
||||
specName: '',
|
||||
manualSmallWeighLowerTol: MIXING_SMALL_MATERIAL_WEIGH_TOLERANCE,
|
||||
manualSmallWeighUpperTol: MIXING_SMALL_MATERIAL_WEIGH_TOLERANCE,
|
||||
autoSmallWeighLowerTol: MIXING_SMALL_MATERIAL_WEIGH_TOLERANCE,
|
||||
autoSmallWeighUpperTol: MIXING_SMALL_MATERIAL_WEIGH_TOLERANCE,
|
||||
});
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
Object.assign(formState, buildMixingSmallWeighRangeForm({}));
|
||||
const record = data?.record || {};
|
||||
if (!record?.id) {
|
||||
createMessage.warning('未找到混炼示方记录');
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
setModalProps({ confirmLoading: false });
|
||||
try {
|
||||
const detail = await queryById({ id: record.id });
|
||||
Object.assign(formState, buildMixingSmallWeighRangeForm(detail || record));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
Object.assign(formState, buildMixingSmallWeighRangeForm(record));
|
||||
createMessage.error('加载小料称重范围失败');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
function normalizeTol(value: unknown) {
|
||||
const num = Number(value);
|
||||
if (Number.isNaN(num) || num < 0) {
|
||||
return null;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
if (!formState.id) {
|
||||
createMessage.warning('未找到混炼示方记录');
|
||||
return;
|
||||
}
|
||||
const payload = {
|
||||
id: formState.id,
|
||||
manualSmallWeighLowerTol: normalizeTol(formState.manualSmallWeighLowerTol),
|
||||
manualSmallWeighUpperTol: normalizeTol(formState.manualSmallWeighUpperTol),
|
||||
autoSmallWeighLowerTol: normalizeTol(formState.autoSmallWeighLowerTol),
|
||||
autoSmallWeighUpperTol: normalizeTol(formState.autoSmallWeighUpperTol),
|
||||
};
|
||||
if (
|
||||
payload.manualSmallWeighLowerTol == null ||
|
||||
payload.manualSmallWeighUpperTol == null ||
|
||||
payload.autoSmallWeighLowerTol == null ||
|
||||
payload.autoSmallWeighUpperTol == null
|
||||
) {
|
||||
createMessage.warning('请填写有效的小料称重容差(不能为负数)');
|
||||
return;
|
||||
}
|
||||
setModalProps({ confirmLoading: true });
|
||||
try {
|
||||
await updateSmallWeighRange(payload);
|
||||
createMessage.success('保存成功');
|
||||
closeModal();
|
||||
emit('success');
|
||||
} finally {
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.weigh-range-tip {
|
||||
margin-bottom: 8px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.weigh-range-spec {
|
||||
margin-bottom: 4px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<BasicModal
|
||||
v-bind="$attrs"
|
||||
@register="registerModal"
|
||||
title="混炼示方历史记录"
|
||||
:width="960"
|
||||
destroyOnClose
|
||||
:showOkBtn="false"
|
||||
cancelText="关闭"
|
||||
>
|
||||
<a-spin :spinning="loading">
|
||||
<a-descriptions bordered :column="3" size="small" class="mb-3">
|
||||
<a-descriptions-item label="规格名">{{ specTitle || '-' }}</a-descriptions-item>
|
||||
<a-descriptions-item label="发行编号">{{ issueNumber || '-' }}</a-descriptions-item>
|
||||
<a-descriptions-item label="历史条数">{{ historyList.length }}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
<BasicTable
|
||||
:columns="historyColumns"
|
||||
:dataSource="historyList"
|
||||
:pagination="false"
|
||||
:canResize="false"
|
||||
size="small"
|
||||
bordered
|
||||
rowKey="id"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'action'">
|
||||
<a-button type="link" size="small" @click="handleViewDetail(record)">查看详情</a-button>
|
||||
</template>
|
||||
</template>
|
||||
</BasicTable>
|
||||
<a-empty v-if="!loading && historyList.length === 0" description="暂无历史记录" />
|
||||
</a-spin>
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicTable, BasicColumn } from '/@/components/Table';
|
||||
import { listHistoryByMixingSpecId } from '../MesXslMixingSpecHistory.api';
|
||||
|
||||
const emit = defineEmits(['register', 'viewDetail']);
|
||||
|
||||
const loading = ref(false);
|
||||
const specTitle = ref('');
|
||||
const issueNumber = ref('');
|
||||
const historyList = ref<Recordable[]>([]);
|
||||
|
||||
const historyColumns: BasicColumn[] = [
|
||||
{ title: '版本号', dataIndex: 'versionNo', width: 90 },
|
||||
{ title: '操作类型', dataIndex: 'actionType_dictText', width: 90 },
|
||||
{ title: '操作人', dataIndex: 'operateByName', width: 120 },
|
||||
{ title: '操作时间', dataIndex: 'operateTime', width: 170 },
|
||||
{ title: '操作', dataIndex: 'action', width: 100, fixed: 'right' },
|
||||
];
|
||||
|
||||
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
|
||||
historyList.value = [];
|
||||
specTitle.value = data?.record?.specName || '';
|
||||
issueNumber.value = data?.record?.issueNumber || '';
|
||||
setModalProps({ confirmLoading: false });
|
||||
const mixingSpecId = data?.record?.id;
|
||||
if (!mixingSpecId) {
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
try {
|
||||
historyList.value = (await listHistoryByMixingSpecId({ mixingSpecId })) || [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
function handleViewDetail(record: Recordable) {
|
||||
emit('viewDetail', record);
|
||||
}
|
||||
</script>
|
||||
@@ -536,6 +536,7 @@ import {
|
||||
MIXING_STEP_MIN_COLUMN_WIDTH,
|
||||
} from '../MesXslMixingSpec.data';
|
||||
import { saveOrUpdate, queryById } from '../MesXslMixingSpec.api';
|
||||
import { queryHistoryById } from '../MesXslMixingSpecHistory.api';
|
||||
import { resolveFormulaSpecUserDisplayName } from '/@/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.data';
|
||||
import { MIXING_SPEC_BIZ_TABLE, loadRecordWithTrace } from '/@/views/xslmes/approval/integration/traceRecordHelper';
|
||||
import MesXslMixingMaterialColumnSetting from './MesXslMixingMaterialColumnSetting.vue';
|
||||
@@ -556,6 +557,8 @@ const userStore = useUserStore();
|
||||
|
||||
const isUpdate = ref(false);
|
||||
const showFooter = ref(true);
|
||||
const isHistoryView = ref(false);
|
||||
const historyVersion = ref('');
|
||||
const mixerPsCompilePickerId = ref('');
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A34】混合步骤动作/组合下拉选项-----------
|
||||
const mixerActionOptions = ref<{ title: string; value: string }[]>([]);
|
||||
@@ -1245,11 +1248,21 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data
|
||||
downStepData.value = [];
|
||||
tcuData.value = ensureTcuDefaultRows([]);
|
||||
await loadMixerStepOptions('');
|
||||
isHistoryView.value = !!data?.isHistoryView;
|
||||
historyVersion.value = data?.historyVersion || '';
|
||||
isUpdate.value = !!data?.isUpdate;
|
||||
showFooter.value = !!data?.showFooter;
|
||||
showFooter.value = !!data?.showFooter && !isHistoryView.value;
|
||||
await setProps({ disabled: !showFooter.value });
|
||||
setModalProps({ showOkBtn: showFooter.value, showCancelBtn: showFooter.value, confirmLoading: false });
|
||||
if (isUpdate.value && data?.record?.id) {
|
||||
if (isHistoryView.value && data?.historyId) {
|
||||
const row = await queryHistoryById({ id: data.historyId });
|
||||
if (!row?.id) {
|
||||
createMessage.warning('未找到历史记录数据');
|
||||
return;
|
||||
}
|
||||
historyVersion.value = historyVersion.value || data?.historyVersion || '';
|
||||
await applyMixingSpecPageData(row, 'edit');
|
||||
} else if (isUpdate.value && data?.record?.id) {
|
||||
const row = await loadRecordWithTrace(data.record.id, MIXING_SPEC_BIZ_TABLE, queryById, data.record);
|
||||
await applyMixingSpecPageData(row, 'edit');
|
||||
} else {
|
||||
@@ -1271,11 +1284,46 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data
|
||||
}
|
||||
});
|
||||
|
||||
const title = computed(() => (!showFooter.value && unref(isUpdate) ? '混炼示方详情' : !unref(isUpdate) ? '新增混炼示方' : '编辑混炼示方'));
|
||||
const title = computed(() => {
|
||||
if (unref(isHistoryView)) {
|
||||
const version = unref(historyVersion);
|
||||
return version ? `混炼示方历史详情(${version})` : '混炼示方历史详情';
|
||||
}
|
||||
return !showFooter.value && unref(isUpdate) ? '混炼示方详情' : !unref(isUpdate) ? '新增混炼示方' : '编辑混炼示方';
|
||||
});
|
||||
|
||||
function resolveValidateErrorMessage(error: unknown) {
|
||||
const err = error as { errorFields?: { name?: string[]; errors?: string[] }[] };
|
||||
const messages = (err?.errorFields || [])
|
||||
.flatMap((item) => item?.errors || [])
|
||||
.filter((msg) => !!msg);
|
||||
if (messages.length) {
|
||||
return messages.join(';');
|
||||
}
|
||||
const fieldLabelMap: Recordable<string> = {
|
||||
specName: '规格',
|
||||
purpose: '用途',
|
||||
issueNumber: '发行编号',
|
||||
};
|
||||
const fields = (err?.errorFields || [])
|
||||
.map((item) => item?.name?.[0])
|
||||
.filter(Boolean)
|
||||
.map((name) => fieldLabelMap[name as string] || name);
|
||||
if (fields.length) {
|
||||
return `请完善必填项:${fields.join('、')}`;
|
||||
}
|
||||
return '请完善表单必填项';
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
await syncSheetToForm();
|
||||
const formValues = await validate();
|
||||
let formValues: Recordable;
|
||||
try {
|
||||
formValues = await validate();
|
||||
} catch (error) {
|
||||
createMessage.warning(resolveValidateErrorMessage(error));
|
||||
return;
|
||||
}
|
||||
const materialList = resolveMaterialTableRawRows();
|
||||
applyMaterialAccumWeight(materialList);
|
||||
const stepList = stepRef.value?.getTableData?.() || stepData.value;
|
||||
|
||||
Reference in New Issue
Block a user