feat(mes):review 工序定义(pro_process)、工艺路线(pro_route)
parent
01a1d3e001
commit
80a25ca767
|
|
@ -39,6 +39,7 @@ const selectValue = computed({
|
|||
},
|
||||
});
|
||||
|
||||
// TODO @AI:是不是要写注释;
|
||||
function handleFilter(input: string, option: any) {
|
||||
const keyword = input.toLowerCase();
|
||||
const item = option?.item as MesProProcessApi.Process | undefined;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ export function useFormSchema(formApi?: VbenFormApi): VbenFormSchema[] {
|
|||
{
|
||||
type: 'default',
|
||||
onClick: async () => {
|
||||
// TODO @AI:需要 try catch 么?感觉直接去掉也可以?
|
||||
try {
|
||||
const code = await generateAutoCode(
|
||||
MesAutoCodeRuleCode.PRO_PROCESS_CODE,
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ async function getList() {
|
|||
|
||||
/** 新增工序步骤 */
|
||||
function handleCreate() {
|
||||
// TODO @AI:是不是可以直接 max 然后 || 0;
|
||||
const maxSort =
|
||||
list.value.length > 0
|
||||
? Math.max(...list.value.map((item) => item.sort || 0))
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ import { Button } from 'ant-design-vue';
|
|||
|
||||
import { z } from '#/adapter/form';
|
||||
import { generateAutoCode } from '#/api/mes/md/autocode/record';
|
||||
import {
|
||||
MdItemSelect,
|
||||
MdProductBomSelect,
|
||||
} from '#/views/mes/md/item/components';
|
||||
import { MesAutoCodeRuleCode } from '#/views/mes/utils/constants';
|
||||
|
||||
/** 工艺路线表单 */
|
||||
|
|
@ -333,3 +337,119 @@ export function useRouteProductBomGridColumns(): VxeTableGridOptions<MesProRoute
|
|||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/** 工艺路线产品表单 */
|
||||
export function useRouteProductFormSchema(
|
||||
onItemChange?: (item: any) => void,
|
||||
): VbenFormSchema[] {
|
||||
return [
|
||||
{
|
||||
fieldName: 'id',
|
||||
component: 'Input',
|
||||
dependencies: { triggerFields: [''], show: () => false },
|
||||
},
|
||||
{
|
||||
fieldName: 'routeId',
|
||||
component: 'Input',
|
||||
dependencies: { triggerFields: [''], show: () => false },
|
||||
},
|
||||
// 产品物料:使用业务自定义选择器,change 回填编码/名称/规格/单位
|
||||
{
|
||||
fieldName: 'itemId',
|
||||
label: '产品',
|
||||
component: MdItemSelect as any,
|
||||
componentProps: {
|
||||
onChange: onItemChange,
|
||||
},
|
||||
formItemClass: 'col-span-2',
|
||||
rules: 'selectRequired',
|
||||
},
|
||||
{
|
||||
fieldName: 'quantity',
|
||||
label: '生产数量',
|
||||
component: 'InputNumber',
|
||||
componentProps: { class: '!w-full', min: 1, precision: 0 },
|
||||
rules: z.number().default(1),
|
||||
},
|
||||
{
|
||||
fieldName: 'productionTime',
|
||||
label: '生产用时',
|
||||
component: 'InputNumber',
|
||||
componentProps: { class: '!w-full', min: 0, precision: 2 },
|
||||
rules: z.number().default(1),
|
||||
},
|
||||
{
|
||||
fieldName: 'timeUnitType',
|
||||
label: '时间单位',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
options: getDictOptions(DICT_TYPE.MES_TIME_UNIT_TYPE),
|
||||
placeholder: '请选择',
|
||||
},
|
||||
rules: z.string().default('MINUTE'),
|
||||
},
|
||||
{
|
||||
fieldName: 'remark',
|
||||
label: '备注',
|
||||
component: 'Textarea',
|
||||
formItemClass: 'col-span-2',
|
||||
componentProps: { maxLength: 250, placeholder: '请输入备注', rows: 2 },
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/** 工艺路线产品 BOM 表单 */
|
||||
export function useRouteProductBomFormSchema(
|
||||
itemId: () => number,
|
||||
onBomChange?: (bom: any) => void,
|
||||
): VbenFormSchema[] {
|
||||
return [
|
||||
{
|
||||
fieldName: 'id',
|
||||
component: 'Input',
|
||||
dependencies: { triggerFields: [''], show: () => false },
|
||||
},
|
||||
{
|
||||
fieldName: 'routeId',
|
||||
component: 'Input',
|
||||
dependencies: { triggerFields: [''], show: () => false },
|
||||
},
|
||||
{
|
||||
fieldName: 'processId',
|
||||
component: 'Input',
|
||||
dependencies: { triggerFields: [''], show: () => false },
|
||||
},
|
||||
{
|
||||
fieldName: 'productId',
|
||||
component: 'Input',
|
||||
dependencies: { triggerFields: [''], show: () => false },
|
||||
},
|
||||
// BOM 物料:依赖产品物料,使用业务自定义选择器
|
||||
{
|
||||
fieldName: 'itemId',
|
||||
label: 'BOM 物料',
|
||||
component: MdProductBomSelect as any,
|
||||
componentProps: () => ({
|
||||
itemId: itemId(),
|
||||
onChange: onBomChange,
|
||||
placeholder: '请选择 BOM 物料',
|
||||
}),
|
||||
rules: 'selectRequired',
|
||||
},
|
||||
{
|
||||
fieldName: 'quantity',
|
||||
label: '用料比例',
|
||||
component: 'InputNumber',
|
||||
componentProps: { class: '!w-full', min: 0, precision: 2 },
|
||||
rules: z.number().default(1),
|
||||
},
|
||||
{
|
||||
fieldName: 'remark',
|
||||
label: '备注',
|
||||
component: 'Textarea',
|
||||
componentProps: { maxLength: 250, placeholder: '请输入备注', rows: 2 },
|
||||
},
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
<script lang="ts" setup>
|
||||
import type { MesProRouteProductBomApi } from '#/api/mes/pro/route/productbom';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import {
|
||||
createRouteProductBom,
|
||||
updateRouteProductBom,
|
||||
} from '#/api/mes/pro/route/productbom';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
import { useRouteProductBomFormSchema } from '../data';
|
||||
|
||||
const emit = defineEmits(['success']);
|
||||
const formData = ref<MesProRouteProductBomApi.RouteProductBom>(); // 当前编辑的 BOM 数据
|
||||
const productId = ref<number>(0); // 当前产品物料编号,供 BOM 选择器筛选可用 BOM
|
||||
const getTitle = computed(() =>
|
||||
formData.value?.id
|
||||
? $t('ui.actionTitle.edit', ['BOM 物料'])
|
||||
: $t('ui.actionTitle.create', ['BOM 物料']),
|
||||
);
|
||||
|
||||
/** MdProductBomSelect change 回调:把 BOM 物料编码/名称/规格/单位/默认用量回填到 form */
|
||||
async function handleBomChange(bom?: any) {
|
||||
if (!bom) {
|
||||
return;
|
||||
}
|
||||
await formApi.setValues({
|
||||
itemCode: bom.bomItemCode,
|
||||
itemName: bom.bomItemName,
|
||||
quantity: bom.quantity ?? 1,
|
||||
specification: bom.specification,
|
||||
unitName: bom.unitName,
|
||||
});
|
||||
}
|
||||
|
||||
const [Form, formApi] = useVbenForm({
|
||||
commonConfig: {
|
||||
componentProps: { class: 'w-full' },
|
||||
formItemClass: 'col-span-1',
|
||||
labelWidth: 110,
|
||||
},
|
||||
layout: 'horizontal',
|
||||
schema: useRouteProductBomFormSchema(() => productId.value, handleBomChange),
|
||||
showDefaultActions: false,
|
||||
});
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
async onConfirm() {
|
||||
const { valid } = await formApi.validate();
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
modalApi.lock();
|
||||
// 提交表单
|
||||
const data =
|
||||
(await formApi.getValues()) as MesProRouteProductBomApi.RouteProductBom;
|
||||
try {
|
||||
await (formData.value?.id
|
||||
? updateRouteProductBom(data)
|
||||
: createRouteProductBom(data));
|
||||
// 关闭并提示
|
||||
await modalApi.close();
|
||||
emit('success');
|
||||
message.success($t('ui.actionMessage.operationSuccess'));
|
||||
} finally {
|
||||
modalApi.unlock();
|
||||
}
|
||||
},
|
||||
async onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
formData.value = undefined;
|
||||
return;
|
||||
}
|
||||
await formApi.resetForm();
|
||||
// 加载数据
|
||||
const data = modalApi.getData<{
|
||||
processId: number;
|
||||
productId: number;
|
||||
routeId: number;
|
||||
row?: MesProRouteProductBomApi.RouteProductBom;
|
||||
}>();
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
productId.value = data.productId;
|
||||
if (data.row) {
|
||||
formData.value = data.row;
|
||||
// 设置到 values
|
||||
await formApi.setValues(data.row);
|
||||
return;
|
||||
}
|
||||
await formApi.setValues({
|
||||
processId: data.processId,
|
||||
productId: data.productId,
|
||||
quantity: 1,
|
||||
routeId: data.routeId,
|
||||
});
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :title="getTitle" class="w-1/3">
|
||||
<Form class="mx-4" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
@ -48,8 +48,10 @@ const [Form, formApi] = useVbenForm({
|
|||
wrapperClass: 'grid-cols-2',
|
||||
});
|
||||
|
||||
// TODO @AI:注释风格,是不是和别的没对齐
|
||||
formApi.setState({ schema: useFormSchema(formApi) });
|
||||
|
||||
// TODO @AI:注释风格,是不是和别的没对齐
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
async onConfirm() {
|
||||
if (isDetail.value) {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ async function loadSchema(): Promise<VbenFormSchema[]> {
|
|||
return useRouteProcessFormSchema(options);
|
||||
}
|
||||
|
||||
// TODO @AI:注释风格,是不是和别的没对齐
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
async onConfirm() {
|
||||
const { valid } = await formApi.validate();
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||
} as VxeTableGridOptions<MesProRouteProcessApi.RouteProcess>,
|
||||
});
|
||||
|
||||
// TODO @AI:注释风格,是不是和别的没对齐
|
||||
async function getList() {
|
||||
gridApi.setLoading(true);
|
||||
try {
|
||||
|
|
@ -55,6 +56,7 @@ async function getList() {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO @AI:注释风格,是不是和别的没对齐
|
||||
function handleCreate() {
|
||||
const maxSort =
|
||||
list.value.length > 0
|
||||
|
|
@ -63,10 +65,12 @@ function handleCreate() {
|
|||
processFormModalApi.setData({ maxSort, routeId: props.routeId }).open();
|
||||
}
|
||||
|
||||
// TODO @AI:注释风格,是不是和别的没对齐
|
||||
function handleEdit(row: MesProRouteProcessApi.RouteProcess) {
|
||||
processFormModalApi.setData({ id: row.id, routeId: props.routeId, row }).open();
|
||||
}
|
||||
|
||||
// TODO @AI:注释风格,是不是和别的没对齐
|
||||
async function handleDelete(row: MesProRouteProcessApi.RouteProcess) {
|
||||
await deleteRouteProcess(row.id!);
|
||||
message.success($t('ui.actionMessage.deleteSuccess', ['工艺路线工序']));
|
||||
|
|
|
|||
|
|
@ -1,34 +1,23 @@
|
|||
<script lang="ts" setup>
|
||||
import type { FormInstance } from 'ant-design-vue';
|
||||
|
||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
import type { MesProRouteProductBomApi } from '#/api/mes/pro/route/productbom';
|
||||
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
import {
|
||||
Form as AForm,
|
||||
FormItem,
|
||||
InputNumber,
|
||||
message,
|
||||
Modal,
|
||||
TabPane,
|
||||
Tabs,
|
||||
Textarea,
|
||||
} from 'ant-design-vue';
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { message, TabPane, Tabs } from 'ant-design-vue';
|
||||
|
||||
import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { getRouteProcessListByRoute } from '#/api/mes/pro/route/process';
|
||||
import {
|
||||
createRouteProductBom,
|
||||
deleteRouteProductBom,
|
||||
getRouteProductBomList,
|
||||
updateRouteProductBom,
|
||||
} from '#/api/mes/pro/route/productbom';
|
||||
import { $t } from '#/locales';
|
||||
import { MdProductBomSelect } from '#/views/mes/md/item/components';
|
||||
|
||||
import { useRouteProductBomGridColumns } from '../data';
|
||||
import BomForm from './bom-form.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
productId: number;
|
||||
|
|
@ -36,27 +25,17 @@ const props = defineProps<{
|
|||
routeId: number;
|
||||
}>();
|
||||
|
||||
// TODO @AI:const 的尾注释?别的 vue 文件也看看,遵守 agents md 里说的。
|
||||
const processOptions = ref<
|
||||
Array<{ processId: number; processName?: string }>
|
||||
>([]);
|
||||
const activeProcessId = ref<string>('');
|
||||
>([]); // TODO @AI:是不是不用转换,vue 那直接处理就好了;
|
||||
const activeProcessId = ref<string>(''); // TODO @AI:这个好像是 number?看看 vue3 + ep 里的代码。
|
||||
const list = ref<MesProRouteProductBomApi.RouteProductBom[]>([]);
|
||||
|
||||
const formVisible = ref(false);
|
||||
const formRef = ref<FormInstance>();
|
||||
const isUpdate = ref(false);
|
||||
const formData = reactive<MesProRouteProductBomApi.RouteProductBom>({
|
||||
quantity: 1,
|
||||
const [BomFormModal, bomFormModalApi] = useVbenModal({
|
||||
connectedComponent: BomForm,
|
||||
destroyOnClose: true,
|
||||
});
|
||||
const formRules = {
|
||||
itemId: [{ message: 'BOM 物料不能为空', required: true }],
|
||||
quantity: [{ message: '用料比例不能为空', required: true }],
|
||||
};
|
||||
const formTitle = computed(() =>
|
||||
isUpdate.value
|
||||
? $t('ui.actionTitle.edit', ['BOM 物料'])
|
||||
: $t('ui.actionTitle.create', ['BOM 物料']),
|
||||
);
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
gridOptions: {
|
||||
|
|
@ -72,6 +51,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||
} as VxeTableGridOptions<MesProRouteProductBomApi.RouteProductBom>,
|
||||
});
|
||||
|
||||
/** 加载路线下的工序列表,用于工序 Tab */
|
||||
async function loadProcessList() {
|
||||
const data = await getRouteProcessListByRoute(props.routeId);
|
||||
processOptions.value = (data || []).map((item) => ({
|
||||
|
|
@ -88,6 +68,7 @@ async function loadProcessList() {
|
|||
}
|
||||
}
|
||||
|
||||
/** 加载当前工序下的 BOM 列表 */
|
||||
async function getList() {
|
||||
if (!activeProcessId.value) {
|
||||
return;
|
||||
|
|
@ -105,70 +86,40 @@ async function getList() {
|
|||
}
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
Object.assign(formData, {
|
||||
id: undefined,
|
||||
itemCode: undefined,
|
||||
itemId: undefined,
|
||||
itemName: undefined,
|
||||
processId: Number(activeProcessId.value),
|
||||
productId: props.productId,
|
||||
quantity: 1,
|
||||
remark: undefined,
|
||||
routeId: props.routeId,
|
||||
specification: undefined,
|
||||
unitName: undefined,
|
||||
});
|
||||
formRef.value?.clearValidate();
|
||||
}
|
||||
|
||||
/** 新增 BOM */
|
||||
function handleCreate() {
|
||||
if (!activeProcessId.value) {
|
||||
message.warning('请先选择工序');
|
||||
return;
|
||||
}
|
||||
resetForm();
|
||||
isUpdate.value = false;
|
||||
formVisible.value = true;
|
||||
bomFormModalApi
|
||||
.setData({
|
||||
processId: Number(activeProcessId.value),
|
||||
productId: props.productId,
|
||||
routeId: props.routeId,
|
||||
})
|
||||
.open();
|
||||
}
|
||||
|
||||
/** 编辑 BOM */
|
||||
function handleEdit(row: MesProRouteProductBomApi.RouteProductBom) {
|
||||
Object.assign(formData, row);
|
||||
isUpdate.value = true;
|
||||
formVisible.value = true;
|
||||
bomFormModalApi
|
||||
.setData({
|
||||
processId: Number(activeProcessId.value),
|
||||
productId: props.productId,
|
||||
routeId: props.routeId,
|
||||
row,
|
||||
})
|
||||
.open();
|
||||
}
|
||||
|
||||
/** 删除 BOM */
|
||||
async function handleDelete(row: MesProRouteProductBomApi.RouteProductBom) {
|
||||
await deleteRouteProductBom(row.id!);
|
||||
message.success($t('ui.actionMessage.deleteSuccess', ['BOM 物料']));
|
||||
await getList();
|
||||
}
|
||||
|
||||
async function submitForm() {
|
||||
try {
|
||||
await formRef.value?.validate();
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
await (isUpdate.value
|
||||
? updateRouteProductBom(formData)
|
||||
: createRouteProductBom(formData));
|
||||
message.success($t('ui.actionMessage.operationSuccess'));
|
||||
formVisible.value = false;
|
||||
await getList();
|
||||
}
|
||||
|
||||
/** BOM 选中后回填用量比例 */
|
||||
function handleBomChange(bom?: any) {
|
||||
if (bom) {
|
||||
formData.quantity = bom.quantity ?? 1;
|
||||
formData.itemCode = bom.bomItemCode;
|
||||
formData.itemName = bom.bomItemName;
|
||||
formData.specification = bom.specification;
|
||||
formData.unitName = bom.unitName;
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [props.routeId, props.productId],
|
||||
() => {
|
||||
|
|
@ -181,6 +132,7 @@ watch(
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<BomFormModal @success="getList" />
|
||||
<Tabs v-model:active-key="activeProcessId" @change="getList">
|
||||
<TabPane
|
||||
v-for="item in processOptions"
|
||||
|
|
@ -222,44 +174,4 @@ watch(
|
|||
/>
|
||||
</template>
|
||||
</Grid>
|
||||
|
||||
<Modal
|
||||
v-model:open="formVisible"
|
||||
:title="formTitle"
|
||||
width="500px"
|
||||
@ok="submitForm"
|
||||
>
|
||||
<AForm
|
||||
ref="formRef"
|
||||
:label-col="{ span: 6 }"
|
||||
:wrapper-col="{ span: 16 }"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
>
|
||||
<FormItem label="BOM 物料" name="itemId">
|
||||
<MdProductBomSelect
|
||||
v-model="formData.itemId"
|
||||
:item-id="productId"
|
||||
placeholder="请选择 BOM 物料"
|
||||
@change="handleBomChange"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="用料比例" name="quantity">
|
||||
<InputNumber
|
||||
v-model:value="formData.quantity"
|
||||
class="!w-full"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="备注" name="remark">
|
||||
<Textarea
|
||||
v-model:value="formData.remark"
|
||||
:max-length="250"
|
||||
placeholder="请输入备注"
|
||||
:rows="2"
|
||||
/>
|
||||
</FormItem>
|
||||
</AForm>
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,90 +1,73 @@
|
|||
<script lang="ts" setup>
|
||||
import type { FormInstance } from 'ant-design-vue';
|
||||
|
||||
import type { MesProRouteProductApi } from '#/api/mes/pro/route/product';
|
||||
|
||||
import { computed, reactive, ref } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { DICT_TYPE } from '@vben/constants';
|
||||
import { getDictOptions } from '@vben/hooks';
|
||||
|
||||
import {
|
||||
Form as AForm,
|
||||
Divider,
|
||||
FormItem,
|
||||
InputNumber,
|
||||
message,
|
||||
Select,
|
||||
Textarea,
|
||||
} from 'ant-design-vue';
|
||||
import { Divider, message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import {
|
||||
createRouteProduct,
|
||||
updateRouteProduct,
|
||||
} from '#/api/mes/pro/route/product';
|
||||
import { $t } from '#/locales';
|
||||
import { MdItemSelect } from '#/views/mes/md/item/components';
|
||||
|
||||
import { useRouteProductFormSchema } from '../data';
|
||||
import ProductBomList from './product-bom-list.vue';
|
||||
|
||||
const emit = defineEmits(['success']);
|
||||
const isUpdate = ref(false);
|
||||
const formRef = ref<FormInstance>();
|
||||
const formData = reactive<MesProRouteProductApi.RouteProduct>({
|
||||
productionTime: 1,
|
||||
quantity: 1,
|
||||
timeUnitType: 'MINUTE',
|
||||
});
|
||||
const formRules = {
|
||||
itemId: [{ message: '产品不能为空', required: true }],
|
||||
quantity: [{ message: '生产数量不能为空', required: true }],
|
||||
};
|
||||
const timeUnitOptions = computed(() =>
|
||||
getDictOptions(DICT_TYPE.MES_TIME_UNIT_TYPE).map((item) => ({
|
||||
label: item.label,
|
||||
value: item.value as string,
|
||||
})),
|
||||
);
|
||||
const formData = ref<MesProRouteProductApi.RouteProduct>(); // 当前编辑/查看的产品数据
|
||||
const getTitle = computed(() =>
|
||||
isUpdate.value
|
||||
formData.value?.id
|
||||
? $t('ui.actionTitle.edit', ['工艺路线产品'])
|
||||
: $t('ui.actionTitle.create', ['工艺路线产品']),
|
||||
);
|
||||
|
||||
/** 重置表单数据 */
|
||||
function resetForm(routeId?: number) {
|
||||
Object.assign(formData, {
|
||||
id: undefined,
|
||||
itemCode: undefined,
|
||||
itemId: undefined,
|
||||
itemName: undefined,
|
||||
productionTime: 1,
|
||||
quantity: 1,
|
||||
remark: undefined,
|
||||
routeId: routeId ?? formData.routeId,
|
||||
specification: undefined,
|
||||
timeUnitType: 'MINUTE',
|
||||
unitName: undefined,
|
||||
/** MdItemSelect change 回调:把物料编码/名称/规格/单位回填到 form */
|
||||
async function handleItemChange(item?: any) {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
await formApi.setValues({
|
||||
itemCode: item.code,
|
||||
itemName: item.name,
|
||||
specification: item.specification,
|
||||
unitName: item.unitMeasureName,
|
||||
});
|
||||
formRef.value?.clearValidate();
|
||||
}
|
||||
|
||||
const [Form, formApi] = useVbenForm({
|
||||
commonConfig: {
|
||||
componentProps: { class: 'w-full' },
|
||||
formItemClass: 'col-span-1',
|
||||
labelWidth: 100,
|
||||
},
|
||||
layout: 'horizontal',
|
||||
schema: useRouteProductFormSchema(handleItemChange),
|
||||
showDefaultActions: false,
|
||||
wrapperClass: 'grid-cols-2',
|
||||
});
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
// TODO @AI:注释风格,是不是和别的没对齐
|
||||
async onConfirm() {
|
||||
try {
|
||||
await formRef.value?.validate();
|
||||
} catch {
|
||||
const { valid } = await formApi.validate();
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
modalApi.lock();
|
||||
// 提交表单
|
||||
const data =
|
||||
(await formApi.getValues()) as MesProRouteProductApi.RouteProduct;
|
||||
try {
|
||||
if (isUpdate.value) {
|
||||
await updateRouteProduct(formData);
|
||||
if (formData.value?.id) {
|
||||
await updateRouteProduct(data);
|
||||
} else {
|
||||
const id = await createRouteProduct(formData);
|
||||
formData.id = id;
|
||||
isUpdate.value = true;
|
||||
const id = await createRouteProduct(data);
|
||||
formData.value = { ...data, id };
|
||||
await formApi.setFieldValue('id', id);
|
||||
}
|
||||
emit('success');
|
||||
message.success($t('ui.actionMessage.operationSuccess'));
|
||||
|
|
@ -92,12 +75,13 @@ const [Modal, modalApi] = useVbenModal({
|
|||
modalApi.unlock();
|
||||
}
|
||||
},
|
||||
onOpenChange(isOpen: boolean) {
|
||||
async onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
resetForm();
|
||||
isUpdate.value = false;
|
||||
formData.value = undefined;
|
||||
return;
|
||||
}
|
||||
await formApi.resetForm();
|
||||
// 加载数据
|
||||
const data = modalApi.getData<{
|
||||
id?: number;
|
||||
routeId: number;
|
||||
|
|
@ -107,79 +91,21 @@ const [Modal, modalApi] = useVbenModal({
|
|||
return;
|
||||
}
|
||||
if (data.row) {
|
||||
Object.assign(formData, data.row);
|
||||
isUpdate.value = true;
|
||||
} else {
|
||||
resetForm(data.routeId);
|
||||
isUpdate.value = false;
|
||||
formData.value = data.row;
|
||||
// 设置到 values
|
||||
await formApi.setValues(data.row);
|
||||
return;
|
||||
}
|
||||
await formApi.setValues({ routeId: data.routeId });
|
||||
},
|
||||
});
|
||||
|
||||
/** 物料编号变化时回填名称等 */
|
||||
function handleItemChange(item?: any) {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
formData.itemCode = item.code;
|
||||
formData.itemName = item.name;
|
||||
formData.specification = item.specification;
|
||||
formData.unitName = item.unitName;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :title="getTitle" class="w-3/5">
|
||||
<AForm
|
||||
ref="formRef"
|
||||
class="mx-4"
|
||||
:label-col="{ flex: '0 0 110px' }"
|
||||
:wrapper-col="{ flex: 'auto' }"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
>
|
||||
<div class="grid grid-cols-2 gap-x-4">
|
||||
<FormItem class="col-span-2" label="产品" name="itemId">
|
||||
<MdItemSelect
|
||||
v-model="formData.itemId"
|
||||
@change="handleItemChange"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="生产数量" name="quantity">
|
||||
<InputNumber
|
||||
v-model:value="formData.quantity"
|
||||
class="!w-full"
|
||||
:min="1"
|
||||
:precision="0"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="生产用时" name="productionTime">
|
||||
<InputNumber
|
||||
v-model:value="formData.productionTime"
|
||||
class="!w-full"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="时间单位" name="timeUnitType">
|
||||
<Select
|
||||
v-model:value="formData.timeUnitType"
|
||||
allow-clear
|
||||
:options="timeUnitOptions"
|
||||
placeholder="请选择"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem class="col-span-2" label="备注" name="remark">
|
||||
<Textarea
|
||||
v-model:value="formData.remark"
|
||||
:max-length="250"
|
||||
placeholder="请输入备注"
|
||||
:rows="2"
|
||||
/>
|
||||
</FormItem>
|
||||
</div>
|
||||
</AForm>
|
||||
<template v-if="isUpdate && formData.id && formData.itemId">
|
||||
<Form class="mx-4" />
|
||||
<!-- 编辑/详情模式下展示产品 BOM 子表,新增模式下隐藏 -->
|
||||
<template v-if="formData?.id && formData?.itemId">
|
||||
<Divider class="!my-3" orientation="left">产品 BOM 配置</Divider>
|
||||
<div class="mx-4">
|
||||
<ProductBomList
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ const [ProductFormModal, productFormModalApi] = useVbenModal({
|
|||
destroyOnClose: true,
|
||||
});
|
||||
|
||||
// TODO @AI:代码的排版风格?ps:和别的模块,看看是不是一致;
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
gridOptions: {
|
||||
autoResize: true,
|
||||
|
|
@ -47,6 +48,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||
} as VxeTableGridOptions<MesProRouteProductApi.RouteProduct>,
|
||||
});
|
||||
|
||||
// TODO @AI:注释风格,是不是和别的没对齐
|
||||
async function getList() {
|
||||
gridApi.setLoading(true);
|
||||
try {
|
||||
|
|
@ -57,14 +59,17 @@ async function getList() {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO @AI:注释风格,是不是和别的没对齐
|
||||
function handleCreate() {
|
||||
productFormModalApi.setData({ routeId: props.routeId }).open();
|
||||
}
|
||||
|
||||
// TODO @AI:注释风格,是不是和别的没对齐
|
||||
function handleEdit(row: MesProRouteProductApi.RouteProduct) {
|
||||
productFormModalApi.setData({ id: row.id, routeId: props.routeId, row }).open();
|
||||
}
|
||||
|
||||
// TODO @AI:注释风格,是不是和别的没对齐
|
||||
async function handleDelete(row: MesProRouteProductApi.RouteProduct) {
|
||||
await deleteRouteProduct(row.id!);
|
||||
message.success($t('ui.actionMessage.deleteSuccess', ['工艺路线产品']));
|
||||
|
|
|
|||
Loading…
Reference in New Issue