密炼生产计划优化

This commit is contained in:
2026-06-17 15:47:53 +08:00
parent e28352f8ea
commit 7d7198b802
44 changed files with 2074 additions and 16 deletions

View File

@@ -0,0 +1,7 @@
<template>
<MesXslAutoSmallMaterialDemandPlanList />
</template>
<script lang="ts" setup>
import MesXslAutoSmallMaterialDemandPlanList from '../../xslmes/mesXslAutoSmallMaterialDemandPlan/MesXslAutoSmallMaterialDemandPlanList.vue';
</script>

View File

@@ -0,0 +1,7 @@
<template>
<MesXslAutoSmallMaterialPlanMaintainList />
</template>
<script lang="ts" setup>
import MesXslAutoSmallMaterialPlanMaintainList from '../../xslmes/mesXslAutoSmallMaterialPlanMaintain/MesXslAutoSmallMaterialPlanMaintainList.vue';
</script>

View File

@@ -0,0 +1,7 @@
<template>
<MesXslManualSmallMaterialDemandPlanList />
</template>
<script lang="ts" setup>
import MesXslManualSmallMaterialDemandPlanList from '../../xslmes/mesXslManualSmallMaterialDemandPlan/MesXslManualSmallMaterialDemandPlanList.vue';
</script>

View File

@@ -0,0 +1,7 @@
<template>
<MesXslManualSmallMaterialPlanMaintainList />
</template>
<script lang="ts" setup>
import MesXslManualSmallMaterialPlanMaintainList from '../../xslmes/mesXslManualSmallMaterialPlanMaintain/MesXslManualSmallMaterialPlanMaintainList.vue';
</script>

View File

@@ -17,6 +17,7 @@
const selectedRow = ref<Recordable | null>(null);
const onlySales = ref(false);
const excludeProductionFB1 = ref(false);
const [registerTable, { reload, getSelectRowKeys, getSelectRows, setSelectedRowKeys, clearSelectedRowKeys }] = useTable({
api: materialList,
@@ -35,6 +36,7 @@
...params,
enableFlag: params.enableFlag ?? 1,
onlySales: onlySales.value ? 1 : undefined,
excludeProductionFB1: excludeProductionFB1.value ? 1 : undefined,
}),
rowSelection: {
type: 'radio',
@@ -49,6 +51,7 @@
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
selectedRow.value = null;
onlySales.value = !!data?.onlySales;
excludeProductionFB1.value = !!data?.excludeProductionFB1;
clearSelectedRowKeys?.();
setModalProps({ confirmLoading: false });
const materialId = data?.materialId as string | undefined;
@@ -84,9 +87,9 @@
}
emit('select', {
materialId: row.id,
materialName: row.materialName || '',
aliasName: row.aliasName || '',
materialCode: row.materialCode || '',
materialName: row.materialName || row.material_name || '',
aliasName: row.aliasName || row.alias_name || '',
materialCode: row.materialCode || row.material_code || '',
});
closeModal();
}

View File

@@ -0,0 +1,10 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
list = '/xslmes/mesXslAutoSmallMaterialDemandPlan/list',
exportXls = '/xslmes/mesXslAutoSmallMaterialDemandPlan/exportXls',
}
export const getExportUrl = Api.exportXls;
export const list = (params) => defHttp.get({ url: Api.list, params });

View File

@@ -0,0 +1,26 @@
import { BasicColumn, FormSchema } from '/@/components/Table';
export const baseColumns: BasicColumn[] = [
{ title: '原材料名称', align: 'center', dataIndex: 'rawMaterialName', width: 260, ellipsis: true },
{ title: '需求重量(KG)', align: 'center', dataIndex: 'demandWeight', width: 180 },
];
export const machineColumns: BasicColumn[] = [{ title: '机台', align: 'center', dataIndex: 'machineName', width: 180 }, ...baseColumns];
export const searchFormSchema: FormSchema[] = [
{
label: '日期',
field: 'statDate',
component: 'DatePicker',
componentProps: { valueFormat: 'YYYY-MM-DD', placeholder: '请选择日期' },
colProps: { span: 6 },
},
{ label: '原材料名称', field: 'rawMaterialName', component: 'JInput', colProps: { span: 6 } },
];
export const superQuerySchema = {
machineName: { title: '机台', order: 0, view: 'text' },
statDate: { title: '日期', order: 1, view: 'date' },
rawMaterialName: { title: '原材料名称', order: 2, view: 'text' },
demandWeight: { title: '需求重量(KG)', order: 3, view: 'number' },
};

View File

@@ -0,0 +1,83 @@
<template>
<div>
<BasicTable @register="registerTable">
<template #tableTitle>
<a-checkbox v-model:checked="groupByMachine" @change="onGroupByMachineChange">按机台统计</a-checkbox>
<a-button
style="margin-left: 8px"
type="primary"
v-auth="'xslmes:mes_xsl_auto_small_material_demand_plan:exportXls'"
preIcon="ant-design:export-outlined"
@click="onExportXls"
>
导出
</a-button>
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
</template>
</BasicTable>
</div>
</template>
<script lang="ts" name="xslmes-mesXslAutoSmallMaterialDemandPlan" setup>
import { onMounted, reactive, ref } from 'vue';
import { BasicTable } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import {
baseColumns,
machineColumns,
searchFormSchema,
superQuerySchema,
} from './MesXslAutoSmallMaterialDemandPlan.data';
import { list, getExportUrl } from './MesXslAutoSmallMaterialDemandPlan.api';
const queryParam = reactive<any>({ groupByMachine: 0 });
const groupByMachine = ref(false);
const { tableContext, onExportXls } = useListPage({
tableProps: {
title: '自动小料需求计划',
api: list,
columns: baseColumns,
canResize: true,
formConfig: {
schemas: searchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: true,
},
beforeFetch: (params) => {
return Object.assign(params, queryParam, {
groupByMachine: groupByMachine.value ? 1 : 0,
});
},
},
exportConfig: {
name: '自动小料需求计划',
url: getExportUrl,
params: queryParam,
},
});
const [registerTable, { reload, setColumns }] = tableContext;
const superQueryConfig = reactive(superQuerySchema);
onMounted(() => {
applyColumns();
});
function applyColumns() {
setColumns(groupByMachine.value ? machineColumns : baseColumns);
}
function onGroupByMachineChange() {
queryParam.groupByMachine = groupByMachine.value ? 1 : 0;
applyColumns();
reload();
}
function handleSuperQuery(params) {
Object.keys(params).forEach((k) => {
queryParam[k] = params[k];
});
reload();
}
</script>

View File

@@ -0,0 +1,9 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
list = '/xslmes/mesXslAutoSmallMaterialPlanMaintain/list',
saveAll = '/xslmes/mesXslAutoSmallMaterialPlanMaintain/saveAll',
}
export const list = (params) => defHttp.get({ url: Api.list, params });
export const saveAll = (params) => defHttp.post({ url: Api.saveAll, params });

View File

@@ -0,0 +1,198 @@
<template>
<div class="small-plan-page">
<div class="small-plan-toolbar">
<a-button type="primary" preIcon="ant-design:save-outlined" :loading="saving" @click="handleSaveAll">保存</a-button>
</div>
<a-table :columns="columns" :data-source="rows" :pagination="false" :scroll="{ x: 1220 }" row-key="_rowKey" size="small" bordered>
<template #bodyCell="{ column, record, index }">
<template v-if="column.dataIndex === 'formulaName'">
<a-input :value="record.formulaName" @change="(e) => updateCell(index, 'formulaName', e?.target?.value)" />
</template>
<template
v-else-if="
column.dataIndex === 'morningSeqNo' ||
column.dataIndex === 'noonSeqNo' ||
column.dataIndex === 'nightSeqNo' ||
column.dataIndex === 'morningPlanCount' ||
column.dataIndex === 'noonPlanCount' ||
column.dataIndex === 'nightPlanCount'
"
>
<a-input-number
:value="record[column.dataIndex]"
:min="0"
:precision="0"
:controls="false"
style="width: 100%"
@change="(v) => updateCell(index, column.dataIndex as string, v)"
/>
</template>
<template
v-else-if="
column.dataIndex === 'morningRemark' || column.dataIndex === 'noonRemark' || column.dataIndex === 'nightRemark'
"
>
<a-input :value="record[column.dataIndex]" @change="(e) => updateCell(index, column.dataIndex as string, e?.target?.value)" />
</template>
<template v-else-if="column.key === 'action'">
<a-button type="text" size="small" class="insert-plus-btn" title="新增" @click="insertBelow(index)">+</a-button>
<a-button type="link" size="small" danger @click="removeRow(index)">删</a-button>
</template>
</template>
</a-table>
</div>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { buildUUID } from '/@/utils/uuid';
import { list, saveAll } from './MesXslAutoSmallMaterialPlanMaintain.api';
const { createMessage } = useMessage();
const saving = ref(false);
const rows = ref<Recordable[]>([]);
const columns = computed(() => [
{ title: '操作', key: 'action', width: 96, fixed: 'left', align: 'center' },
{ title: '配方名称', dataIndex: 'formulaName', width: 220, fixed: 'left', align: 'center' },
{
title: '早班',
align: 'center',
children: [
{ title: '序号', dataIndex: 'morningSeqNo', width: 90, align: 'center' },
{ title: '计划', dataIndex: 'morningPlanCount', width: 90, align: 'center' },
{ title: '备注', dataIndex: 'morningRemark', width: 160, align: 'center' },
],
},
{
title: '中班',
align: 'center',
children: [
{ title: '序号', dataIndex: 'noonSeqNo', width: 90, align: 'center' },
{ title: '计划', dataIndex: 'noonPlanCount', width: 90, align: 'center' },
{ title: '备注', dataIndex: 'noonRemark', width: 160, align: 'center' },
],
},
{
title: '夜班',
align: 'center',
children: [
{ title: '序号', dataIndex: 'nightSeqNo', width: 90, align: 'center' },
{ title: '计划', dataIndex: 'nightPlanCount', width: 90, align: 'center' },
{ title: '备注', dataIndex: 'nightRemark', width: 160, align: 'center' },
],
},
]);
function createEmptyRow(): Recordable {
return {
_rowKey: buildUUID(),
id: '',
formulaName: '',
morningSeqNo: null,
morningPlanCount: null,
morningRemark: '',
noonSeqNo: null,
noonPlanCount: null,
noonRemark: '',
nightSeqNo: null,
nightPlanCount: null,
nightRemark: '',
};
}
function createBlankRows(count = 12) {
return Array.from({ length: count }, () => createEmptyRow());
}
function updateCell(index: number, field: string, value: any) {
const row = rows.value[index];
if (!row) return;
row[field] = value;
}
function insertBelow(index: number) {
rows.value.splice(index + 1, 0, createEmptyRow());
}
function removeRow(index: number) {
rows.value.splice(index, 1);
if (!rows.value.length) {
rows.value = createBlankRows();
}
}
async function loadRows() {
const res = await list({ pageNo: 1, pageSize: 500 });
const records = (res?.records || res?.result?.records || []) as Recordable[];
rows.value = (records || []).map((item) => ({ ...createEmptyRow(), ...item, _rowKey: item.id || buildUUID() }));
if (!rows.value.length) {
rows.value = createBlankRows();
}
}
async function handleSaveAll() {
saving.value = true;
try {
const payload = rows.value.map((r) => {
const { _rowKey, ...rest } = r;
return rest;
});
await saveAll({ rows: payload });
createMessage.success('保存成功');
await loadRows();
} finally {
saving.value = false;
}
}
loadRows();
</script>
<style scoped>
.small-plan-page {
padding: 8px;
background: #fff;
}
.small-plan-toolbar {
margin-bottom: 12px;
display: flex;
gap: 8px;
}
:deep(.ant-table-thead > tr > th) {
text-align: center !important;
padding: 4px 6px !important;
font-size: 12px;
}
:deep(.ant-table-tbody > tr > td) {
padding: 2px 3px !important;
}
:deep(.ant-input),
:deep(.ant-input-number),
:deep(.ant-input-number-input) {
font-size: 12px;
}
:deep(.ant-input),
:deep(.ant-input-number) {
width: 100%;
min-width: 0;
}
.insert-plus-btn {
color: #52c41a;
font-size: 18px;
font-weight: 700;
line-height: 1;
padding: 0 4px;
}
</style>

View File

@@ -0,0 +1,10 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
list = '/xslmes/mesXslManualSmallMaterialDemandPlan/list',
exportXls = '/xslmes/mesXslManualSmallMaterialDemandPlan/exportXls',
}
export const getExportUrl = Api.exportXls;
export const list = (params) => defHttp.get({ url: Api.list, params });

View File

@@ -0,0 +1,26 @@
import { BasicColumn, FormSchema } from '/@/components/Table';
export const baseColumns: BasicColumn[] = [
{ title: '原材料名称', align: 'center', dataIndex: 'rawMaterialName', width: 260, ellipsis: true },
{ title: '需求重量(KG)', align: 'center', dataIndex: 'demandWeight', width: 180 },
];
export const machineColumns: BasicColumn[] = [{ title: '机台', align: 'center', dataIndex: 'machineName', width: 180 }, ...baseColumns];
export const searchFormSchema: FormSchema[] = [
{
label: '日期',
field: 'statDate',
component: 'DatePicker',
componentProps: { valueFormat: 'YYYY-MM-DD', placeholder: '请选择日期' },
colProps: { span: 6 },
},
{ label: '原材料名称', field: 'rawMaterialName', component: 'JInput', colProps: { span: 6 } },
];
export const superQuerySchema = {
machineName: { title: '机台', order: 0, view: 'text' },
statDate: { title: '日期', order: 1, view: 'date' },
rawMaterialName: { title: '原材料名称', order: 2, view: 'text' },
demandWeight: { title: '需求重量(KG)', order: 3, view: 'number' },
};

View File

@@ -0,0 +1,83 @@
<template>
<div>
<BasicTable @register="registerTable">
<template #tableTitle>
<a-checkbox v-model:checked="groupByMachine" @change="onGroupByMachineChange">按机台统计</a-checkbox>
<a-button
style="margin-left: 8px"
type="primary"
v-auth="'xslmes:mes_xsl_manual_small_material_demand_plan:exportXls'"
preIcon="ant-design:export-outlined"
@click="onExportXls"
>
导出
</a-button>
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
</template>
</BasicTable>
</div>
</template>
<script lang="ts" name="xslmes-mesXslManualSmallMaterialDemandPlan" setup>
import { onMounted, reactive, ref } from 'vue';
import { BasicTable } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import {
baseColumns,
machineColumns,
searchFormSchema,
superQuerySchema,
} from './MesXslManualSmallMaterialDemandPlan.data';
import { list, getExportUrl } from './MesXslManualSmallMaterialDemandPlan.api';
const queryParam = reactive<any>({ groupByMachine: 0 });
const groupByMachine = ref(false);
const { tableContext, onExportXls } = useListPage({
tableProps: {
title: '人工小料需求计划',
api: list,
columns: baseColumns,
canResize: true,
formConfig: {
schemas: searchFormSchema,
autoSubmitOnEnter: true,
showAdvancedButton: true,
},
beforeFetch: (params) => {
return Object.assign(params, queryParam, {
groupByMachine: groupByMachine.value ? 1 : 0,
});
},
},
exportConfig: {
name: '人工小料需求计划',
url: getExportUrl,
params: queryParam,
},
});
const [registerTable, { reload, setColumns }] = tableContext;
const superQueryConfig = reactive(superQuerySchema);
onMounted(() => {
applyColumns();
});
function applyColumns() {
setColumns(groupByMachine.value ? machineColumns : baseColumns);
}
function onGroupByMachineChange() {
queryParam.groupByMachine = groupByMachine.value ? 1 : 0;
applyColumns();
reload();
}
function handleSuperQuery(params) {
Object.keys(params).forEach((k) => {
queryParam[k] = params[k];
});
reload();
}
</script>

View File

@@ -0,0 +1,9 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
list = '/xslmes/mesXslManualSmallMaterialPlanMaintain/list',
saveAll = '/xslmes/mesXslManualSmallMaterialPlanMaintain/saveAll',
}
export const list = (params) => defHttp.get({ url: Api.list, params });
export const saveAll = (params) => defHttp.post({ url: Api.saveAll, params });

View File

@@ -0,0 +1,198 @@
<template>
<div class="small-plan-page">
<div class="small-plan-toolbar">
<a-button type="primary" preIcon="ant-design:save-outlined" :loading="saving" @click="handleSaveAll">保存</a-button>
</div>
<a-table :columns="columns" :data-source="rows" :pagination="false" :scroll="{ x: 1220 }" row-key="_rowKey" size="small" bordered>
<template #bodyCell="{ column, record, index }">
<template v-if="column.dataIndex === 'formulaName'">
<a-input :value="record.formulaName" @change="(e) => updateCell(index, 'formulaName', e?.target?.value)" />
</template>
<template
v-else-if="
column.dataIndex === 'morningSeqNo' ||
column.dataIndex === 'noonSeqNo' ||
column.dataIndex === 'nightSeqNo' ||
column.dataIndex === 'morningPlanCount' ||
column.dataIndex === 'noonPlanCount' ||
column.dataIndex === 'nightPlanCount'
"
>
<a-input-number
:value="record[column.dataIndex]"
:min="0"
:precision="0"
:controls="false"
style="width: 100%"
@change="(v) => updateCell(index, column.dataIndex as string, v)"
/>
</template>
<template
v-else-if="
column.dataIndex === 'morningRemark' || column.dataIndex === 'noonRemark' || column.dataIndex === 'nightRemark'
"
>
<a-input :value="record[column.dataIndex]" @change="(e) => updateCell(index, column.dataIndex as string, e?.target?.value)" />
</template>
<template v-else-if="column.key === 'action'">
<a-button type="text" size="small" class="insert-plus-btn" title="新增" @click="insertBelow(index)">+</a-button>
<a-button type="link" size="small" danger @click="removeRow(index)">删</a-button>
</template>
</template>
</a-table>
</div>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { buildUUID } from '/@/utils/uuid';
import { list, saveAll } from './MesXslManualSmallMaterialPlanMaintain.api';
const { createMessage } = useMessage();
const saving = ref(false);
const rows = ref<Recordable[]>([]);
const columns = computed(() => [
{ title: '操作', key: 'action', width: 96, fixed: 'left', align: 'center' },
{ title: '配方名称', dataIndex: 'formulaName', width: 220, fixed: 'left', align: 'center' },
{
title: '早班',
align: 'center',
children: [
{ title: '序号', dataIndex: 'morningSeqNo', width: 90, align: 'center' },
{ title: '计划', dataIndex: 'morningPlanCount', width: 90, align: 'center' },
{ title: '备注', dataIndex: 'morningRemark', width: 160, align: 'center' },
],
},
{
title: '中班',
align: 'center',
children: [
{ title: '序号', dataIndex: 'noonSeqNo', width: 90, align: 'center' },
{ title: '计划', dataIndex: 'noonPlanCount', width: 90, align: 'center' },
{ title: '备注', dataIndex: 'noonRemark', width: 160, align: 'center' },
],
},
{
title: '夜班',
align: 'center',
children: [
{ title: '序号', dataIndex: 'nightSeqNo', width: 90, align: 'center' },
{ title: '计划', dataIndex: 'nightPlanCount', width: 90, align: 'center' },
{ title: '备注', dataIndex: 'nightRemark', width: 160, align: 'center' },
],
},
]);
function createEmptyRow(): Recordable {
return {
_rowKey: buildUUID(),
id: '',
formulaName: '',
morningSeqNo: null,
morningPlanCount: null,
morningRemark: '',
noonSeqNo: null,
noonPlanCount: null,
noonRemark: '',
nightSeqNo: null,
nightPlanCount: null,
nightRemark: '',
};
}
function createBlankRows(count = 12) {
return Array.from({ length: count }, () => createEmptyRow());
}
function updateCell(index: number, field: string, value: any) {
const row = rows.value[index];
if (!row) return;
row[field] = value;
}
function insertBelow(index: number) {
rows.value.splice(index + 1, 0, createEmptyRow());
}
function removeRow(index: number) {
rows.value.splice(index, 1);
if (!rows.value.length) {
rows.value = createBlankRows();
}
}
async function loadRows() {
const res = await list({ pageNo: 1, pageSize: 500 });
const records = (res?.records || res?.result?.records || []) as Recordable[];
rows.value = (records || []).map((item) => ({ ...createEmptyRow(), ...item, _rowKey: item.id || buildUUID() }));
if (!rows.value.length) {
rows.value = createBlankRows();
}
}
async function handleSaveAll() {
saving.value = true;
try {
const payload = rows.value.map((r) => {
const { _rowKey, ...rest } = r;
return rest;
});
await saveAll({ rows: payload });
createMessage.success('保存成功');
await loadRows();
} finally {
saving.value = false;
}
}
loadRows();
</script>
<style scoped>
.small-plan-page {
padding: 8px;
background: #fff;
}
.small-plan-toolbar {
margin-bottom: 12px;
display: flex;
gap: 8px;
}
:deep(.ant-table-thead > tr > th) {
text-align: center !important;
padding: 4px 6px !important;
font-size: 12px;
}
:deep(.ant-table-tbody > tr > td) {
padding: 2px 3px !important;
}
:deep(.ant-input),
:deep(.ant-input-number),
:deep(.ant-input-number-input) {
font-size: 12px;
}
:deep(.ant-input),
:deep(.ant-input-number) {
width: 100%;
min-width: 0;
}
.insert-plus-btn {
color: #52c41a;
font-size: 18px;
font-weight: 700;
line-height: 1;
padding: 0 4px;
}
</style>

View File

@@ -1,7 +1,17 @@
<template>
<div class="mixing-plan-page">
<div class="mixing-plan-toolbar">
<a-date-picker
v-model:value="queryPlanDate"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
placeholder="选择计划日期"
style="width: 160px"
:disabled="saving || refreshing"
/>
<a-button preIcon="ant-design:search-outlined" :loading="querying" :disabled="saving" @click="handleQuery">查询</a-button>
<a-button type="primary" preIcon="ant-design:save-outlined" :loading="saving" @click="handleSaveAll">保存</a-button>
<a-button preIcon="ant-design:reload-outlined" :loading="refreshing" :disabled="saving" @click="handleRefresh">刷新</a-button>
</div>
<a-table
@@ -100,6 +110,9 @@
const { createMessage } = useMessage();
const saving = ref(false);
const refreshing = ref(false);
const querying = ref(false);
const queryPlanDate = ref<string>('');
const rows = ref<Recordable[]>([]);
const pickerContext = ref<{ rowIndex: number; shift?: 'morning' | 'noon' | 'night' } | null>(null);
@@ -228,8 +241,12 @@
}
function openOrderPicker(rowIndex: number, shift: 'morning' | 'noon' | 'night') {
pickerContext.value = { rowIndex, shift };
const row = rows.value[rowIndex];
if (!row?.machineId && !row?.machineName) {
createMessage.warning('请先选择机台信息');
return;
}
pickerContext.value = { rowIndex, shift };
openOrderModal(true, {
planId: row?.[`${shift}PlanId`] || '',
machineId: row?.machineId || '',
@@ -252,11 +269,26 @@
row[`${shift}PlannedCarCount`] = payload?.plannedCarCount ?? null;
row[`${shift}ScheduledCarCount`] = payload?.scheduledCarCount ?? null;
row[`${shift}FinishedCarCount`] = payload?.finishedCarCount ?? null;
row[`${shift}PlanCount`] = calcPlanCount(payload?.plannedCarCount, payload?.finishedCarCount);
pickerContext.value = null;
}
function calcPlanCount(plannedCarCount?: number | null, finishedCarCount?: number | null) {
const planned = Number(plannedCarCount ?? 0);
const finished = Number(finishedCarCount ?? 0);
const remain = planned - finished;
if (!Number.isFinite(remain)) {
return null;
}
return Math.max(0, remain);
}
async function loadRows() {
const res = await list({ pageNo: 1, pageSize: 500 });
const res = await list({
pageNo: 1,
pageSize: 500,
planDate: queryPlanDate.value || undefined,
});
const records = (res?.records || res?.result?.records || []) as Recordable[];
rows.value = (records || []).map((item) => ({ ...createEmptyRow(), ...item, _rowKey: item.id || buildUUID() }));
if (!rows.value.length) {
@@ -279,6 +311,25 @@
}
}
async function handleRefresh() {
refreshing.value = true;
try {
await loadRows();
createMessage.success('已刷新最新数据');
} finally {
refreshing.value = false;
}
}
async function handleQuery() {
querying.value = true;
try {
await loadRows();
} finally {
querying.value = false;
}
}
loadRows();
</script>

View File

@@ -51,7 +51,12 @@ export const formSchema: FormSchema[] = [
},
{ label: '生产车间', field: 'productionWorkshop', component: 'Input' },
{ label: '加工段数', field: 'processSegmentCount', component: 'InputNumber', componentProps: { min: 0, precision: 0 } },
{ label: '物料编号', field: 'materialCode', component: 'Input' },
{
label: '物料编号',
field: 'materialCode',
component: 'Input',
slot: 'materialCodeSlot',
},
{ label: 'MES胶料名称', field: 'mesMaterialName', component: 'Input' },
{ label: '金蝶物料名称', field: 'kingdeeMaterialName', component: 'Input' },
{ label: '金蝶物料规格', field: 'kingdeeMaterialSpec', component: 'Input' },

View File

@@ -1,19 +1,32 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="title" width="860px" @ok="handleSubmit">
<BasicForm @register="registerForm" />
<BasicForm @register="registerForm">
<template #materialCodeSlot="{ model }">
<a-input
:value="model.materialCode"
readonly
placeholder="点击选择胶料"
@click="openMaterialPicker"
/>
</template>
</BasicForm>
</BasicModal>
<MesMaterialSelectModal @register="registerMaterialModal" @select="onMaterialSelected" />
</template>
<script lang="ts" setup>
import { computed, ref, unref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { useModal } from '/@/components/Modal';
import { formSchema } from '../MesXslProductionOrder.data';
import { saveOrUpdate } from '../MesXslProductionOrder.api';
import MesMaterialSelectModal from '/@/views/mes/material/modules/MesMaterialSelectModal.vue';
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
const isDetail = ref(false);
const [registerMaterialModal, { openModal: openMaterialModal }] = useModal();
const [registerForm, { resetFields, setFieldsValue, validate, setProps }] = useForm({
labelWidth: 110,
@@ -50,4 +63,22 @@
setModalProps({ confirmLoading: false });
}
}
function openMaterialPicker() {
if (isDetail.value) {
return;
}
openMaterialModal(true, {
materialId: '',
excludeProductionFB1: true,
});
}
async function onMaterialSelected(payload: Recordable) {
const materialName = payload?.materialName || payload?.material_name || '';
await setFieldsValue({
materialCode: materialName,
mesMaterialName: materialName,
});
}
</script>