| | |
| | | <!-- |
| | | * @Description: 工单管理页面 |
| | | * @Author: Ben Lin |
| | | * @version: |
| | | * @Date: 2024-05-25 00:27:00 |
| | | * @LastEditors: Ben Lin |
| | | * @LastEditTime: 2024-07-21 18:07:27 |
| | | --> |
| | | <template> |
| | | <div> |
| | | <BasicTable @register="registerTable"> |
| | | <template #toolbar> |
| | | <a-button color="primary" @click="addWo" preIcon="add_02|svg"> 新增 </a-button> |
| | | <a-button type="primary" @click="addWo" preIcon="add_02|svg"> 新增 </a-button> |
| | | <a-button ghost color="success" @click="ExcelToDb" preIcon="excel-import|svg"> |
| | | 导入 |
| | | </a-button> |
| | |
| | | @click="handleSelectItem" |
| | | preIcon="search|svg" |
| | | /> |
| | | <NormalModal @register="registerItemAdd" @success="handleItemSuccess" /> |
| | | <GeneralModal @register="registerItemAdd" @success="handleItemSuccess" /> |
| | | </template> |
| | | <template #action="{ record }"> |
| | | <TableAction |
| | |
| | | icon: 'clarity:note-edit-line', |
| | | tooltip: '修改', |
| | | onClick: handleEdit.bind(null, record), |
| | | name: undefined |
| | | }, |
| | | { |
| | | icon: 'ant-design:delete-outlined', |
| | |
| | | placement: 'left', |
| | | confirm: handleDelete.bind(null, record), |
| | | }, |
| | | name: undefined |
| | | }, |
| | | { |
| | | icon: 'config|svg', |
| | | tooltip: '配置工艺', |
| | | onClick: handleConfig.bind(null, record), |
| | | name: undefined |
| | | }, |
| | | { |
| | | icon: 'release|svg', |
| | | tooltip: '下发', |
| | | onClick: handleRelease.bind(null, record), |
| | | name: undefined |
| | | }, |
| | | { |
| | | icon: 'unrelease|svg', |
| | | tooltip: '取消下发', |
| | | onClick: handleUnRelease.bind(null, record), |
| | | }, |
| | | { |
| | | icon: 'suspend-blue|svg', |
| | | tooltip: '暂停', |
| | | onClick: handlePause.bind(null, record), |
| | | }, |
| | | // { |
| | | // icon: 'unrelease|svg', |
| | | // tooltip: '取消下发', |
| | | // onClick: handleUnRelease.bind(null, record), |
| | | // }, |
| | | // { |
| | | // icon: 'suspend-blue|svg', |
| | | // tooltip: '暂停', |
| | | // onClick: handlePause.bind(null, record), |
| | | // }, |
| | | ]" |
| | | /> |
| | | </template> |
| | |
| | | <Loading :loading="compState.loading" :tip="compState.tip" /> |
| | | <WoDrawer @register="registerDrawer" @success="handleSuccess" /> |
| | | <WoModal @register="registerWo" @success="handleSuccess" :title="title" :mtitle="mtitle" /> |
| | | <!-- 自定义模态框,可以自定义多表单 --> |
| | | <CustModal |
| | | @register="registerCust" |
| | | @success="custSuccess" |
| | | :type="cType" |
| | | :detailSlots="dtlSlots" |
| | | > |
| | | <!-- 用插槽自定义多表单 --> |
| | | <template #[item.name] v-for="item in dtlSlots" :key="item.name"> |
| | | <BasicForm @register="useFormData[item.name][0]" v-if="useFormData[item.name]"> |
| | | <!-- 用插槽自定义弹出选择框 --> |
| | | <template #[name]="{ field }" v-for="name in item.slots" :key="name"> |
| | | <a-button |
| | | class="mt-1 ml-1" |
| | | size="small" |
| | | @click="handleCustClick(field)" |
| | | :preIcon="item.preIcons[name]" |
| | | /> |
| | | <NormalModal |
| | | @register="useModalData[name][0]" |
| | | @success="(d, u) => handleEntSuccess(d, u, item.name)" |
| | | /> |
| | | </template> |
| | | </BasicForm> |
| | | <!-- 自定义内容 --> |
| | | <div style="height: 200px" id="lfContainer" v-if="isCustEl[item.name]"></div> |
| | | </template> |
| | | </CustModal> |
| | | <Suspense> |
| | | <!-- 自定义模态框,可以自定义多表单 --> |
| | | <CustModal |
| | | @register="registerCust" |
| | | @success="custSuccess" |
| | | :type="cType" |
| | | :detailSlots="dtlSlots" |
| | | :entityName="entityName" |
| | | > |
| | | <!-- 用插槽自定义多表单 --> |
| | | <template #[item.name] v-for="item in dtlSlots" :key="item.name"> |
| | | <BasicForm @register="useFormData[item.name][0]" v-if="useFormData[item.name]"> |
| | | <!-- 用插槽自定义弹出选择框 --> |
| | | <template #[name]="{ field }" v-for="name in item.slots" :key="name"> |
| | | <a-button |
| | | class="mt-1 ml-1" |
| | | size="small" |
| | | @click="handleCustClick(field)" |
| | | :preIcon="item.preIcons[name]" |
| | | /> |
| | | <GeneralModal |
| | | @register="useModalData[name][0]" |
| | | @success="(d, u) => handleEntSuccess(d, u, item.name)" |
| | | /> |
| | | </template> |
| | | </BasicForm> |
| | | <!-- 自定义内容 --> |
| | | <!-- <div style="height: 200px" id="lfContainer" v-if="isCustEl[item.name]"></div> --> |
| | | <div class="h-full" style="height: 380px" v-if="isCustEl[item.name]"> |
| | | <FlowChartView :data="routeData" @init="init" /> |
| | | </div> |
| | | </template> |
| | | </CustModal> |
| | | <!-- <template #fallback> Loading... </template> --> |
| | | </Suspense> |
| | | <RouteViewModal @register="registerRv" @success="RvItemSuccess" /> |
| | | </div> |
| | | </template> |
| | |
| | | import { BasicForm, FormSchema, FormActionType, useForm } from '/@/components/Form/index'; |
| | | import WoDrawer from './WoDrawer.vue'; |
| | | import WoModal from './WoModal.vue'; |
| | | import NormalModal from '/@/views/components/NormalModal.vue'; |
| | | import GeneralModal from '/@/views/components/GeneralModal.vue'; |
| | | import RouteViewModal from '/@/views/components/RouteViewModal.vue'; |
| | | import { FlowChartView } from '/@/components/FlowChart'; |
| | | import CustModal from '/@/views/components/CustModal.vue'; |
| | | import { useDrawer } from '/@/components/Drawer'; |
| | | import { columns, searchFormSchema } from './biz_mes_wo.data'; |
| | |
| | | import { useMessage } from '/@/hooks/web/useMessage'; |
| | | import { useI18n } from '/@/hooks/web/useI18n'; |
| | | import { useModal } from '/@/components/Modal'; |
| | | import { getListByPage } from '/@/api/tigerapi/system'; |
| | | import { SaveEntity, getListByPage } from '/@/api/tigerapi/system'; |
| | | import { GetSelectSuccess, OpenSelectItem, getFormSchema } from '/@/views/components/data'; |
| | | import LogicFlow from '@logicflow/core'; |
| | | import { getRouteData } from '/@/api/tigerapi/mes/router'; |
| | | import actionRect from '/@/components/FlowChart/src/actionRect'; |
| | | import TestNode from '/@/components/FlowChart/src/TestNode'; |
| | | import CollectNode from '/@/components/FlowChart/src/CollectNode'; |
| | | import AssemblyNode from '/@/components/FlowChart/src/AssemblyNode'; |
| | | import PackingNode from '/@/components/FlowChart/src/PackingNode'; |
| | | import RepairNode from '/@/components/FlowChart/src/RepairNode'; |
| | | import customEdge from '/@/components/FlowChart/src/customEdge'; |
| | | import { Snapshot, BpmnElement, Menu, DndPanel, SelectionSelect } from '@logicflow/extension'; |
| | | import { initRoute } from '../../../system/lowcode/data'; |
| | | import BIZ_MES_WO from '../../../system/lowcode/entityts/BIZ_MES_WO'; |
| | | import { useUserStore } from '/@/store/modules/user'; |
| | | |
| | | const { t } = useI18n(); |
| | | const ASteps = Steps; |
| | |
| | | const mtitle = ref('工单列表'); |
| | | const dtlSlots = ref([] as any[]); |
| | | const selectVals = ref({}); |
| | | const { createMessage } = useMessage(); |
| | | const { createMessage, createErrorModal } = useMessage(); |
| | | const [registerDrawer, { openDrawer }] = useDrawer(); |
| | | const compState = reactive({ |
| | | absolute: false, |
| | |
| | | tip: '加载中...', |
| | | }); |
| | | const lfInstance = ref(null) as Ref<LogicFlow | null>; |
| | | const [registerRv, { openModal: openRvModal }] = useModal(); |
| | | const [registerRv, { openModal: openRvModal, closeModal }] = useModal(); |
| | | const [registerWo, { openModal: openWoModal }] = useModal(); |
| | | const [registerItemAdd, { openModal: openItemModal }] = useModal(); |
| | | const [registerCust, { openModal: openCustModal, closeModal }] = useModal(); |
| | | const [registerCust, { openModal: openCustModal }] = useModal(); |
| | | const [registerTable, { getForm, reload }] = useTable({ |
| | | title: '工单信息', |
| | | api: getListByPage, |
| | | searchInfo: { |
| | | TABLE_NAME: 'BIZ_MES_WO', |
| | | option: { |
| | | //根据据点查询,必需带这个参数 |
| | | UserId: useUserStore().getUserInfo.userId, |
| | | ByOrg: true, |
| | | CurOrg: useUserStore().getUserInfo.orgCode, |
| | | }, |
| | | }, |
| | | columns, |
| | | formConfig: { |
| | | labelWidth: 120, |
| | |
| | | nodes: [], |
| | | edges: [], |
| | | }); |
| | | const entityName = ref('BIZ_MES_WO'); |
| | | const formSchema = ref([] as FormSchema[]); |
| | | const woSchema = ref([] as FormSchema[]); |
| | | const prodSchema = ref([] as FormSchema[]); |
| | | const rotSchema = ref([] as FormSchema[]); |
| | | const woSchema = ref<FormSchema[]>(getFormSchema('woinfo')); |
| | | const prodSchema = ref<FormSchema[]>(getFormSchema('prodinfo')); |
| | | const isCustEl = ref({ |
| | | forminfo: false, |
| | | woinfo: false, |
| | |
| | | addRot: useModal(), |
| | | setRot: useModal(), |
| | | }); |
| | | //自定义多表单实例 |
| | | const useFormData = ref({ |
| | | forminfo: useForm({ |
| | | labelWidth: 120, |
| | | schemas: formSchema, |
| | | actionColOptions: { |
| | | span: 24, |
| | | }, |
| | | showActionButtonGroup: false, |
| | | }), |
| | | woinfo: useForm({ |
| | | labelWidth: 120, |
| | | schemas: woSchema, |
| | | actionColOptions: { |
| | | span: 24, |
| | | }, |
| | | showActionButtonGroup: false, |
| | | }), |
| | | prodinfo: useForm({ |
| | | labelWidth: 120, |
| | | schemas: prodSchema, |
| | | actionColOptions: { |
| | | span: 24, |
| | | }, |
| | | showActionButtonGroup: false, |
| | | }), |
| | | // rotinfo: useForm({ |
| | | // labelWidth: 120, |
| | | // schemas: rotSchema, |
| | | // actionColOptions: { |
| | | // span: 24, |
| | | // }, |
| | | // showActionButtonGroup: false, |
| | | // }), |
| | | }); |
| | | |
| | | /* 获取多表单实例 */ |
| | | const [{ GetUseForm }] = BIZ_MES_WO(); |
| | | const useFormData = ref<any>(GetUseForm()); |
| | | |
| | | onMounted(async () => {}); |
| | | |
| | | const currlf = ref(null) as Ref<LogicFlow | null>; |
| | | /** |
| | | * @description: 工艺路线初始化 |
| | | * @param {*} lf |
| | | * @return {*} |
| | | */ |
| | | async function init(lf, rotId) { |
| | | initRoute(lf, rotId, routeData, currlf); |
| | | } |
| | | |
| | | //新增 |
| | | function addWo() { |
| | |
| | | }, |
| | | { name: 'rotinfo', slots: ['add'], preIcons: { add: 'search|svg' }, title: '工艺信息' }, |
| | | ]; |
| | | woSchema.value = getFormSchema('woinfo'); |
| | | prodSchema.value = getFormSchema('prodinfo'); |
| | | // rotSchema.value = getFormSchema('rotinfo'); |
| | | if (lfInstance.value != null) { |
| | | routeData.value = { |
| | | nodes: [], |
| | | edges: [], |
| | | }; |
| | | const lf = unref(lfInstance)!; |
| | | lf.render({}); |
| | | } |
| | | routeData.value = { |
| | | nodes: [], |
| | | edges: [], |
| | | }; |
| | | initRoute(currlf, record.ROUTE_CODE, routeData, currlf); |
| | | selectVals.value['ROUTE_CODE'] = record.ROUTE_CODE; |
| | | openCustModal(true, { |
| | | isUpdate: true, |
| | | ctype: cType, |
| | | title: '工艺配置', |
| | | width: '1000px', |
| | | width: '1200px', |
| | | formEl: useFormData.value, //如果是多个表单,增加多个插槽 |
| | | formElName: ['woinfo', 'prodinfo', 'rotinfo'], //表单插槽名称,支持多个表单 |
| | | RowKey: '', |
| | | fnName: { BIZ_MES_WO_Config: 'SaveCofig' }, //保存方法名 |
| | | initFnName: {}, //初始化方法名 |
| | | isCustEl: isCustEl.value, |
| | | ...record, |
| | | fnName: 'SaveCofig', //保存方法名 |
| | | // initFnName: { BIZ_MES_WO_Config: 'initRoute' }, //初始化方法名 |
| | | // isCustEl: isCustEl.value, |
| | | others: routeData.value, |
| | | values: record, //表单记录 |
| | | }); |
| | | } |
| | | //下发 |
| | | |
| | | /** |
| | | * @description: 下发 |
| | | * @param {*} record |
| | | * @return {*} |
| | | */ |
| | | function handleRelease(record: Recordable) { |
| | | // if (record.STATUS == 2) { |
| | | // createErrorModal({ |
| | | // title: t('警告'), |
| | | // content: t('工单已经下发,不能再下发!'), |
| | | // getContainer: () => document.body, |
| | | // }); |
| | | // return; |
| | | // } |
| | | cType.value = 'BIZ_MES_WO'; |
| | | dtlSlots.value = [ |
| | | { |
| | |
| | | title: '下发配置', |
| | | }, |
| | | ]; |
| | | formSchema.value = getFormSchema(cType.value); |
| | | // formSchema.value = getFormSchema(cType.value); |
| | | openCustModal(true, { |
| | | isUpdate: true, //是否更新操作 |
| | | ctype: cType, //是哪个页面 |
| | |
| | | formEl: useFormData.value, |
| | | formElName: ['forminfo'], //表单插槽名称 |
| | | RowKeys: { add: 'ROUTE_CODE', set: 'ROUTE_CODE' }, //插槽的弹出框选择的code |
| | | fnName: { BIZ_MES_WO: 'SaveWoBatch' }, //保存方法名 |
| | | initFnName: {}, //初始化方法名 |
| | | fnName: 'SaveWoBatch', //保存方法名 |
| | | initFnName: {}, //初始化方法名,没有就留空{} |
| | | isCustEl: isCustEl.value, |
| | | ...record, |
| | | values: record, //表单记录 |
| | | }); |
| | | } |
| | | function custSuccess(d) { |
| | | reload(); |
| | | |
| | | /** |
| | | * @description: 取消下发 |
| | | * @param {*} record |
| | | * @return {*} |
| | | */ |
| | | function handleUnRelease(record: Recordable) { |
| | | if (record.STATUS == 0) { |
| | | createErrorModal({ |
| | | title: t('警告'), |
| | | content: t('工单是初始化状态,不能取消下发!'), |
| | | getContainer: () => document.body, |
| | | }); |
| | | return; |
| | | } |
| | | record.STATUS = 0; |
| | | SaveEntity(record, true, 'BIZ_MES_WO').then((action) => { |
| | | if (action.IsSuccessed) { |
| | | createMessage.success(t('已取消下发')); |
| | | reload(); |
| | | } else { |
| | | createMessage.success(t('取消下发操作失败')); |
| | | } |
| | | }); |
| | | } |
| | | //取消下发 |
| | | function handleUnRelease(record: Recordable) {} |
| | | //暂停 |
| | | function handlePause(record: Recordable) {} |
| | | //删除 |
| | | function handlePause(record: Recordable) { |
| | | if (record.STATUS == 0) { |
| | | createErrorModal({ |
| | | title: t('警告'), |
| | | content: t('工单是初始化状态,不能暂停!'), |
| | | getContainer: () => document.body, |
| | | }); |
| | | return; |
| | | } |
| | | if (record.STATUS == 5) { |
| | | createErrorModal({ |
| | | title: t('警告'), |
| | | content: t('工单是完成状态,不能暂停!'), |
| | | getContainer: () => document.body, |
| | | }); |
| | | return; |
| | | } |
| | | record.STATUS = 4; |
| | | SaveEntity(record, true, 'BIZ_MES_WO').then((action) => { |
| | | if (action.IsSuccessed) { |
| | | createMessage.success(t('已暂停')); |
| | | reload(); |
| | | } else { |
| | | createMessage.success(t('暂停操作失败')); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * @description: 删除 |
| | | * @param {*} record |
| | | * @return {*} |
| | | */ |
| | | function handleDelete(record: Recordable) { |
| | | const apiAction = DeleteMesWo(record.ID); |
| | | apiAction.then((action) => { |
| | | DeleteMesWo(record.ID).then((action) => { |
| | | if (action.IsSuccessed) { |
| | | createMessage.success(t('已删除')); |
| | | reload(); |
| | |
| | | } |
| | | }); |
| | | } |
| | | //点击打开物料列表框 |
| | | |
| | | /** |
| | | * @description: 弹出框确定返回 |
| | | * @param {*} d |
| | | * @return {*} |
| | | */ |
| | | function custSuccess(d) { |
| | | reload(); |
| | | } |
| | | |
| | | /** |
| | | * @description: 点击打开物料列表框 |
| | | * @return {*} |
| | | */ |
| | | function handleSelectItem() { |
| | | openItemModal(true, { |
| | | title: '物料列表', |
| | |
| | | ], |
| | | tableName: 'BAS_ITEM', |
| | | rowKey: 'ITEM_CODE', |
| | | searchInfo: { TABLE_NAME: 'BAS_ITEM' }, |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * @description: 弹出选择物料框返回成功方法 |
| | | * @param {*} d |
| | | * @param {*} u |
| | | * @return {*} |
| | | */ |
| | | function handleItemSuccess(d, u) { |
| | | getForm().setFieldsValue({ |
| | | ITEM_CODE: d.values['val'], |
| | | }); |
| | | } |
| | | /* 各表单内弹出选择框选择成功后事件 */ |
| | | |
| | | /** |
| | | * @description: 各表单内弹出选择框选择成功后方法 |
| | | * @param {*} d |
| | | * @param {*} u |
| | | * @param {*} item |
| | | * @return {*} |
| | | */ |
| | | function handleEntSuccess(d, u, item) { |
| | | var values = GetSelectSuccess(d, u, cType.value); |
| | | selectVals.value = values; //保存弹出框选择的结果 |
| | | let _val = {}; |
| | | _val[d.returnFieldName] = values[d.returnFieldName]; |
| | | d.returnFieldName.map((x) => { |
| | | _val[x] = values[x]; |
| | | }); |
| | | useFormData.value[item][1].setFieldsValue(_val); |
| | | if (d.returnFieldName == 'ROUTE_CODE') { |
| | | if (d.returnFieldName == 'ROUTE_CODE' && cType.value == 'BIZ_MES_WO_Config') { |
| | | routeData.value = { |
| | | nodes: [], |
| | | edges: [], |
| | | }; |
| | | init(selectVals.value['ID']); |
| | | |
| | | init(currlf, selectVals.value['ROUTE_CODE']); |
| | | const { transformModel, width, height } = unref(currlf).graphModel; |
| | | transformModel.focusOn(300, 200, width, height); |
| | | } |
| | | } |
| | | |
| | | /* 弹出选择框 */ |
| | | /** |
| | | * @description: 弹出选择框 |
| | | * @param {*} item |
| | | * @return {*} |
| | | */ |
| | | function handleCustClick(item) { |
| | | //打开自定义模态框 |
| | | OpenSelectItem( |
| | |
| | | cType.value, |
| | | item, |
| | | [openRvModal], |
| | | selectVals.value['ID'], |
| | | selectVals.value['ROUTE_CODE'], |
| | | ); //[openRvModal], selectVals.value['ID']这是自定义参数,按实际需求 |
| | | } |
| | | function RvItemSuccess(d, u) {} |
| | | |
| | | async function init(rotId) { |
| | | LogicFlow.use(BpmnElement); |
| | | lfInstance.value = new LogicFlow({ |
| | | container: document.querySelector('#lfContainer'), |
| | | edgeGenerator: (sourceNode) => { |
| | | // console.log('a'); |
| | | // 起始节点类型 rect 时使用 自定义的边 custom-edge |
| | | if (sourceNode.properties.isReturn) return 'custom-edge'; |
| | | // if (sourceNode.type === 'rect') return 'custom-edge'; |
| | | // return 'custom-edge'; |
| | | }, |
| | | }); |
| | | const lf = unref(lfInstance)!; |
| | | // lf?.setDefaultEdgeType('line'); |
| | | lf.register(customEdge); |
| | | lf.register(actionRect); |
| | | lf.register(TestNode); |
| | | lf.register(CollectNode); |
| | | lf.register(AssemblyNode); |
| | | lf.register(PackingNode); |
| | | lf.register(RepairNode); |
| | | lf.render({}); |
| | | //通过工艺路线ID获取图形数据,并渲染 |
| | | var _data = await getRouteData(rotId); |
| | | console.log('组件已挂载', _data); |
| | | //工艺路线全信息,包括Node、Edge和Act |
| | | // routeConfig.routeData = _data.Data; |
| | | if (_data.Data != null) { |
| | | //工艺路线主信息 |
| | | var currRoute = _data.Data.route; |
| | | _data.Data.nodes.forEach((n) => { |
| | | n.node.properties = JSON.parse(n.node.properties); |
| | | routeData.value.nodes.push(n.node); |
| | | }); |
| | | console.log('111', routeData.value); |
| | | _data.Data.edges.forEach((e) => { |
| | | e.edge.properties = JSON.parse(e.edge.properties); |
| | | routeData.value.edges.push(e.edge); |
| | | }); |
| | | _data.Data.acts.forEach((act) => { |
| | | act.node.properties = JSON.parse(act.node.properties); |
| | | routeData.value.nodes.push(act.node); |
| | | }); |
| | | console.log('init', unref(lf).getGraphData(), JSON.parse(JSON.stringify(routeData.value))); |
| | | lf.render(routeData.value); |
| | | // lf.graphModel.resize(500, 400); |
| | | lf.graphModel.fitView(); |
| | | lf.graphModel.translateCenter(); |
| | | } |
| | | function RvItemSuccess(d, u) { |
| | | closeModal(); |
| | | } |
| | | </script> |