From f6566a3d1eddc6388b5a8cfca988a8b842d4e4e4 Mon Sep 17 00:00:00 2001
From: Ben Lin <maobin001@msn.com>
Date: 星期日, 28 四月 2024 16:38:49 +0800
Subject: [PATCH] 工艺路线更新

---
 src/api/tigerapi/model/router.ts                                      |   96 +++
 src/views/tigerprojects/mes/eng/route/route.data.ts                   |   66 ++
 src/views/tigerprojects/wms/location/location.data.ts                 |    3 
 src/hooks/setting/index.ts                                            |   10 
 src/api/tigerapi/mes/mesApi.ts                                        |    6 
 src/views/tigerprojects/mes/eng/route/components/FormItemProps.vue    |   54 +
 src/views/tigerprojects/mes/eng/route/RouteDrawer.vue                 |   74 ++
 src/utils/env.ts                                                      |   10 
 src/api/tigerapi/mes/router.ts                                        |   62 ++
 src/components/FlowChart/src/enum.ts                                  |    2 
 src/api/tigerapi/dept.ts                                              |   11 
 src/views/form-design/components/VFormDesign/components/FormProps.vue |    1 
 src/views/tigerprojects/mes/eng/route/dataTurbo.json                  |    0 
 src/api/tigerapi/model/mesModel.ts                                    |   86 +-
 src/views/tigerprojects/mes/eng/route/components/FormProps.vue        |   43 +
 src/views/tigerprojects/mes/eng/route/index.vue                       |  446 +++++++++++++++
 /dev/null                                                             |  272 ---------
 src/views/tigerprojects/mes/eng/route/styles/drag.less                |  225 +++++++
 src/components/FlowChart/src/FlowChartToolbar.vue                     |   18 
 src/api/model/baseModel.ts                                            |   37 
 src/views/tigerprojects/mes/eng/route/styles/variable.less            |   15 
 src/api/tigerapi/system.ts                                            |   66 +
 src/components/FlowChart/src/FlowChart.vue                            |   33 
 src/api/tigerapi/wms/house.ts                                         |   21 
 src/views/tigerprojects/mes/eng/route/components/PropsPanel.vue       |   80 ++
 25 files changed, 1,346 insertions(+), 391 deletions(-)

diff --git a/src/api/model/baseModel.ts b/src/api/model/baseModel.ts
index a5d599f..5878db3 100644
--- a/src/api/model/baseModel.ts
+++ b/src/api/model/baseModel.ts
@@ -12,7 +12,7 @@
   id: string;
   dataType: string;
   isAsync: boolean;
-  Options:{} | undefined;
+  Options: {} | undefined;
   timestamp: string;
   isSuccessed: boolean;
   statusCode: number;
@@ -37,15 +37,15 @@
   ByProd: boolean;
   ByWh: boolean;
 }
-export interface localeMsg{
-  Key:string;
-  Args:[];
+export interface localeMsg {
+  Key: string;
+  Args: [];
 }
 
 export interface ApiAction<T> {
   ID: string;
-  DataAssembly:string;
-  Options:{} | undefined;
+  DataAssembly: string;
+  Options: {} | undefined;
   DataType: string;
   IsAsync: boolean;
   Timestamp: string;
@@ -53,30 +53,29 @@
   StatusCode: number;
   Message: string;
   Data: T;
-  LocaleMsg:localeMsg | undefined;
+  LocaleMsg: localeMsg | undefined;
 }
 export interface ApiActionJob<T> {
   ID: string;
-  DataAssembly:string;
-  Option:{};
+  DataAssembly: string;
+  Option: {};
   DataType: string;
   IsAsync: boolean;
   Timestamp: string;
   IsSuccessed: boolean;
   StatusCode: number;
   Message: string;
-  Data:
-  {
-    jobName:string;
-    period:number;
-    remark:string;
+  Data: {
+    jobName: string;
+    period: number;
+    remark: string;
   };
 }
 
 export interface QueryAble {
-    QueryAble_T: string,
-    page: object,
-    where: string,
-    order: string,
-    Items: []
+  QueryAble_T: string;
+  page: object;
+  where: string;
+  order: string;
+  Items: [];
 }
diff --git a/src/api/tigerapi/dept.ts b/src/api/tigerapi/dept.ts
index 86f302e..ac58304 100644
--- a/src/api/tigerapi/dept.ts
+++ b/src/api/tigerapi/dept.ts
@@ -108,8 +108,12 @@
 // 鎹偣涓嬫媺鏍�
 export const optionsListApi = async (params: Recordable) => {
   // const usParams = genAction('V_USER_ORG', `USER_ID='${userid}'`);
-  const usParams = genAction('V_USER_ORG', { QueryAble_T:"", where: "USER_ID = '" + params + "'", order:''});
-  var data = await defHttp.post(
+  const usParams = genAction('V_USER_ORG', {
+    QueryAble_T: '',
+    where: "USER_ID = '" + params + "'",
+    order: '',
+  });
+  const data = await defHttp.post(
     { url: Api.QueryUrl, params: usParams },
     {
       errorMessageMode: 'none',
@@ -117,6 +121,5 @@
       // apiUrl: globSetting.taskApiUrl
     },
   );
-  return data
+  return data;
 };
-
diff --git a/src/api/tigerapi/mes/mesApi.ts b/src/api/tigerapi/mes/mesApi.ts
new file mode 100644
index 0000000..1d9b25e
--- /dev/null
+++ b/src/api/tigerapi/mes/mesApi.ts
@@ -0,0 +1,6 @@
+export enum mesApi {
+  GetRoute = '/MES/GetRoute',
+  GetRouteData = '/MES/GetRouteData',
+  SaveRouteData = '/MES/SaveRouteData',
+  SaveRoute = '/MES/SaveRoute',
+}
diff --git a/src/api/tigerapi/mes/router.ts b/src/api/tigerapi/mes/router.ts
new file mode 100644
index 0000000..8b14995
--- /dev/null
+++ b/src/api/tigerapi/mes/router.ts
@@ -0,0 +1,62 @@
+import { ApiAction } from '../../model/baseModel';
+import { genAction } from '../system';
+import { defHttp } from '/@/utils/http/axios';
+import { MES_ROUTE, RouteData } from '../model/router';
+import { mesApi } from './mesApi';
+import { useUserStore } from '/@/store/modules/user';
+
+/*
+ * 鑾峰彇宸ヨ壓璺嚎鍒楄〃
+ */
+export function getRouteData(route_code: string) {
+  const params = genAction('', route_code);
+  return getApi(params);
+}
+async function getApi(params: ApiAction<string>) {
+  const data = await defHttp.post<ApiAction<RouteData>>(
+    {
+      url: mesApi.GetRouteData,
+      params,
+    },
+    {
+      errorMessageMode: 'modal',
+      isTransformResponse: false,
+    },
+  );
+  return data;
+}
+
+//淇濆瓨
+export const SaveRouteData = async (params: RouteData) => {
+  const data = await defHttp.post(
+    { url: mesApi.SaveRouteData, params: genAction('', params) },
+    {
+      errorMessageMode: 'none',
+      isTransformResponse: false,
+    },
+  );
+  return data;
+};
+export const SaveRoute = async (params: MES_ROUTE) => {
+  params.CREATE_USER = useUserStore().getUserInfo.userId as string;
+  params.UPDATE_USER = useUserStore().getUserInfo.userId as string;
+  const data = await defHttp.post(
+    { url: mesApi.SaveRoute, params: genAction('MES_ROUTE', params) },
+    {
+      errorMessageMode: 'none',
+      isTransformResponse: false,
+    },
+  );
+  return data;
+};
+//鍒犻櫎
+// export const DeleteOper = async (params: Recordable) => {
+//   const usParams = genAction('MES_OPERATION', [params]);
+//   return await defHttp.post(
+//     { url: Api.DeleteList, params: usParams },
+//     {
+//       errorMessageMode: 'none',
+//       isTransformResponse: false,
+//     },
+//   );
+// };
diff --git a/src/api/tigerapi/model/mesModel.ts b/src/api/tigerapi/model/mesModel.ts
index 3536441..e0b0aa8 100644
--- a/src/api/tigerapi/model/mesModel.ts
+++ b/src/api/tigerapi/model/mesModel.ts
@@ -27,55 +27,55 @@
 };
 export type CheckRulePageParams = BasicPageParams & CheckRuleParams;
 export interface CheckRuleListItem {
-	ID: string;
-	CREATE_TIME: Date;
-	CREATE_USER: string;
-	UPDATE_TIME: Date;
-	UPDATE_USER: string;
-	// GHOST_ROW: boolean;
-	// AUTH_ORG: string;
-	// AUTH_PROD: string;
-	// AUTH_WH: string;
-	RULE_CODE: string;
-	RULE_NAME: string;
-	RULE_DESC: string;
-	RULE_TYPE: number;
-	PRIORITY: number;
-	CODE_LENGTH: number;
-	CHECK_TYPE: number;
-	CHECK_REGEX: string;
-	REMARK: string;
+  ID: string;
+  CREATE_TIME: Date;
+  CREATE_USER: string;
+  UPDATE_TIME: Date;
+  UPDATE_USER: string;
+  // GHOST_ROW: boolean;
+  // AUTH_ORG: string;
+  // AUTH_PROD: string;
+  // AUTH_WH: string;
+  RULE_CODE: string;
+  RULE_NAME: string;
+  RULE_DESC: string;
+  RULE_TYPE: number;
+  PRIORITY: number;
+  CODE_LENGTH: number;
+  CHECK_TYPE: number;
+  CHECK_REGEX: string;
+  REMARK: string;
 }
 
 export type CheckRuleDtlParams = {
   RULE_ID: string;
 };
 export interface iBAS_CODE_DTL {
-	ID: string;
-	CREATE_TIME: Date;
-	CREATE_USER: string;
-	UPDATE_TIME: Date;
-	UPDATE_USER: string;
-	GHOST_ROW: boolean;
-	AUTH_ORG: string;
-	AUTH_PROD: string;
-	AUTH_WH: string;
-	RULE_ID: string;
-	RULE_SEQ: number;
-	DESCRIPTION: string;
-	DATA_TYPE: number;
-	DATA_CASE: string;
-	DATA_VALUE: string;
-	SERIAL_MIN: number;
-	SERIAL_MAX: number;
-	SERIAL_RESET: number;
-	CHECK_TABLE: string;
-	CHECK_FIELD: string;
-	CHECK_LENGTH: number;
-	REPEAT_TIMES: number;
-	START_DIGIT: string;
-	DATA_REGEX: string;
-	REMARK: string;
+  ID: string;
+  CREATE_TIME: Date;
+  CREATE_USER: string;
+  UPDATE_TIME: Date;
+  UPDATE_USER: string;
+  GHOST_ROW: boolean;
+  AUTH_ORG: string;
+  AUTH_PROD: string;
+  AUTH_WH: string;
+  RULE_ID: string;
+  RULE_SEQ: number;
+  DESCRIPTION: string;
+  DATA_TYPE: number;
+  DATA_CASE: string;
+  DATA_VALUE: string;
+  SERIAL_MIN: number;
+  SERIAL_MAX: number;
+  SERIAL_RESET: number;
+  CHECK_TABLE: string;
+  CHECK_FIELD: string;
+  CHECK_LENGTH: number;
+  REPEAT_TIMES: number;
+  START_DIGIT: string;
+  DATA_REGEX: string;
+  REMARK: string;
 }
 
 export type MeslineParams = {
diff --git a/src/api/tigerapi/model/router.ts b/src/api/tigerapi/model/router.ts
new file mode 100644
index 0000000..ac92a6e
--- /dev/null
+++ b/src/api/tigerapi/model/router.ts
@@ -0,0 +1,96 @@
+export interface MES_ROUTE {
+  ID: string;
+  CREATE_TIME: Date;
+  CREATE_USER: string;
+  UPDATE_TIME: Date;
+  UPDATE_USER: string;
+  GHOST_ROW: boolean;
+  ROT_CODE: string;
+  ROT_NAME: string;
+  ROT_TYPE: string;
+  ROT_VER: string;
+  IS_ACTIVE: string;
+  REMARK: string;
+}
+
+export interface MES_ROUTE_NODE {
+  ID: string;
+  CREATE_TIME: Date;
+  CREATE_USER: string;
+  UPDATE_TIME: Date;
+  UPDATE_USER: string;
+  GHOST_ROW: boolean;
+  NODE_CODE: string;
+  NODE_NAME: string;
+  ROT_CODE: string;
+  SEGMENT: string;
+  OPER_CODE: string;
+  GPH_TYPE: string;
+  GPH_X: number;
+  GPH_Y: number;
+  GPH_PROP: string;
+  GPH_TEXT: string;
+  IS_ACTIVE: string;
+  IS_CALC_FPY: string;
+  CAN_SKIP: string;
+  REMARK: string;
+}
+
+export interface MES_ROUTE_EDGE {
+  ID: string;
+  CREATE_TIME: Date;
+  CREATE_USER: string;
+  UPDATE_TIME: Date;
+  UPDATE_USER: string;
+  GHOST_ROW: boolean;
+  EDGE_CODE: string;
+  EDGE_NAME: string;
+  ROT_CODE: string;
+  SRC_NODE: string;
+  TGT_NODE: string;
+  GPH_TYPE: string;
+  GPH_SRC_X: number;
+  GPH_SRC_Y: number;
+  GPH_TGT_X: number;
+  GPH_TGT_Y: number;
+  GPH_PROP: string;
+  GPH_POTS: string;
+  REMARK: string;
+}
+
+export interface node {
+  id: string;
+  type: string;
+  x: number;
+  y: number;
+  properties: {};
+  text: nodeText;
+}
+
+export interface edge {
+  id: string;
+  type: string;
+  sourceNodeId: string;
+  targetNodeId: string;
+  startPoint: point;
+  endPoint: point;
+  properties: {};
+  pointsList: point[];
+}
+
+export interface point {
+  x: number;
+  y: number;
+}
+
+export interface nodeText {
+  x: number;
+  y: number;
+  value: string;
+}
+
+export interface RouteData {
+  route: MES_ROUTE;
+  nodes: MES_ROUTE_NODE[];
+  edges: MES_ROUTE_EDGE[];
+}
diff --git a/src/api/tigerapi/system.ts b/src/api/tigerapi/system.ts
index 579e8b0..e52da83 100644
--- a/src/api/tigerapi/system.ts
+++ b/src/api/tigerapi/system.ts
@@ -1,7 +1,7 @@
 import { UserConfigFn } from 'vite';
 import { buildUUID } from '../../utils/uuid';
 import { DateFormat } from '../../utils/dataformat';
-import { ApiAction,ApiActionJob, ApiActionPage } from '../model/baseModel';
+import { ApiAction, ApiActionJob, ApiActionPage } from '../model/baseModel';
 import {
   MenuParams,
   RoleParams,
@@ -27,7 +27,6 @@
   iSYS_ROLE_WH,
 } from './model/systemModel';
 import { defHttp } from '/@/utils/http/axios';
-import { isUnDef } from '/@/utils/is';
 
 export enum Api {
   QueryUrl = '/Base/Query',
@@ -49,7 +48,7 @@
   GetOrgTreeList = '/SYS/getOrgTreeList',
   GetHouseTreeList = '/WMS/GetHouseModel',
   GetHouseOrgTreeList = '/WMS/GetHouseModelOrg',
-  GetCreateBillCode = '/WMS/CreateBillCode', 
+  GetCreateBillCode = '/WMS/CreateBillCode',
   GetCreateTFBillCode = '/WMS/CreateTFBillCode',
   GetAllRoleList = '/system/getAllRoleList',
   urlSetSysUserToGroup = '/SYS/SetSysUserToGroup',
@@ -57,22 +56,22 @@
   StartJob = '/Tsk/StartJob',
   StopJob = '/Tsk/PauseJob',
   AddJob = '/Tsk/AddJob',
-  UpdateJob= '/Tsk/UpdateJob',
-  urlQueryEnum= '/Base/QueryEnum',
-  DeleteWareHouse='/WMS/DelWareHouseModel',
-  AddLocation='/WMS/AddLoctionModel',
-  CheckLocation='/WMS/CheckLocation',
-  SummaryCount='/WMS/SummaryCount',
-  GenerateCount='/WMS/GenerateCount',
-  GetUpdateOrg='/WMS/GetUpdateOrg',
-  GetQrCode='/WMS/Item/GetQRCode',
-  UpdateReq='/WMS/UpdateReq',
-  MaterialResale='/WMS/MaterialResale',
-  GetProdctResult='/WMS/ProductInput/GetProdctResult',
+  UpdateJob = '/Tsk/UpdateJob',
+  urlQueryEnum = '/Base/QueryEnum',
+  DeleteWareHouse = '/WMS/DelWareHouseModel',
+  AddLocation = '/WMS/AddLoctionModel',
+  CheckLocation = '/WMS/CheckLocation',
+  SummaryCount = '/WMS/SummaryCount',
+  GenerateCount = '/WMS/GenerateCount',
+  GetUpdateOrg = '/WMS/GetUpdateOrg',
+  GetQrCode = '/WMS/Item/GetQRCode',
+  UpdateReq = '/WMS/UpdateReq',
+  MaterialResale = '/WMS/MaterialResale',
+  GetProdctResult = '/WMS/ProductInput/GetProdctResult',
   // 瀹屽伐鍏ュ簱鐘舵�佽繕鍘�
   GetStatusRestored = '/WMS/ProductInput/StatusRestored',
   // 鎵归噺鏇存柊鍐呭
-  GetUpdateTime = '/MaterialInfo/UpdateTime'
+  GetUpdateTime = '/MaterialInfo/UpdateTime',
 }
 
 /**
@@ -83,12 +82,18 @@
  * @param pageSize
  * @returns
  */
-export function genActionPage(datatype: string, sqlcmd: string, page: number, pageSize: number,option?:object) {
+export function genActionPage(
+  datatype: string,
+  sqlcmd: string,
+  page: number,
+  pageSize: number,
+  option?: object,
+) {
   const time = new Date();
   const params: ApiActionPage = {
     id: buildUUID(),
     dataType: datatype,
-    Options:option,
+    Options: option,
     isAsync: true,
     timestamp: time.toDateString(),
     isSuccessed: true,
@@ -113,12 +118,12 @@
 /*
  * 鐢熸垚Action
  */
-export function genAction<T>(datatype: string, data: T,option?:object) {
+export function genAction<T>(datatype: string, data: T, option?: object) {
   const time = new Date();
   const params: ApiAction<T> = {
     ID: buildUUID(),
-    DataAssembly:'',
-    Options:option,
+    DataAssembly: '',
+    Options: option,
     DataType: datatype,
     IsAsync: true,
     Timestamp: time.toDateString(),
@@ -126,14 +131,21 @@
     Message: '',
     StatusCode: 0,
     Data: data,
+    LocaleMsg: undefined,
   };
   return params;
 }
-export function genActionjob<sting>(datatype: string, assembly: string, data: string,timeone:number,remark:string) {
+export function genActionjob<sting>(
+  datatype: string,
+  assembly: string,
+  data: string,
+  timeone: number,
+  remark: string,
+) {
   const time = new Date();
   const params: ApiActionJob<string> = {
     ID: buildUUID(),
-    DataAssembly:assembly,
+    DataAssembly: assembly,
     DataType: datatype,
     IsAsync: true,
     Timestamp: time.toDateString(),
@@ -141,9 +153,9 @@
     Message: '',
     StatusCode: 0,
     Data: {
-      jobName:data,
-      period:timeone,
-      remark: remark
+      jobName: data,
+      period: timeone,
+      remark: remark,
     },
   };
   return params;
@@ -491,7 +503,7 @@
     },
   );
 
-  export const setBasStatus = (params: any) =>
+export const setBasStatus = (params: any) =>
   defHttp.post(
     { url: Api.UpdateEntity, params: genAction('BAS_ITEM', params) },
     {
diff --git a/src/api/tigerapi/wms/house.ts b/src/api/tigerapi/wms/house.ts
index eb104db..e452191 100644
--- a/src/api/tigerapi/wms/house.ts
+++ b/src/api/tigerapi/wms/house.ts
@@ -1,5 +1,5 @@
 import { buildUUID } from '../../../utils/uuid';
-import { ApiAction, ApiActionPage } from '../../model/baseModel';
+import { ApiAction } from '../../model/baseModel';
 import {
   WhPageListGetResultModel,
   HouseListItem,
@@ -7,9 +7,8 @@
   RegionListItem,
   ShelfListItem,
   LocationListItem,
-  LocationGuiZeListItem,
 } from '../model/warehoueseModel';
-import { genAction, Api, genActionPage, isExist } from '../system';
+import { genAction, Api, isExist } from '../system';
 import { useUserStore } from '/@/store/modules/user';
 import { formatToDateTime } from '/@/utils/dateUtil';
 import { defHttp } from '/@/utils/http/axios';
@@ -23,7 +22,7 @@
   );
 //閫氳繃浠撳簱code鏌ヨ淇敼鐨勬暟鎹�
 export function getWHList(params: string) {
-  var rmParams = genAction('', '');
+  let rmParams = genAction('', '');
   if (params.slice(0, 1) == 'W') {
     rmParams = genAction('WMS_WAREHOUSE', " ID = '" + params.slice(1) + "'");
   }
@@ -37,7 +36,7 @@
   return getWareHouse(rmParams);
 }
 async function getWareHouse(params: ApiAction<string>) {
-  var data;
+  let data;
   if (params.DataType == 'WMS_WAREHOUSE') {
     data = await defHttp.post<ApiAction<WhListItem>>(
       {
@@ -116,7 +115,7 @@
     );
   } else {
     const usParams = genAction('WMS_WAREHOUSE', "WH_CODE='" + params.WH_CODE + "'");
-    var check = await isExist(usParams);
+    const check = await isExist(usParams);
     console.log('check', check);
     if (!check.Data) {
       const time = new Date();
@@ -175,8 +174,8 @@
       'WMS_REGION',
       "REGION_CODE='" + params.REGION_CODE + "'AND AUTH_ORG='" + regionitem.ORG_CODE + "'",
     );
-    var check = await isExist(usParams);
-    console.log('check',check)
+    const check = await isExist(usParams);
+    console.log('check', check);
     if (!check.Data) {
       regionitem.ID = buildUUID(); //鐢熸垚GUID
       regionitem.UPDATE_TIME = formatToDateTime(new Date());
@@ -244,7 +243,7 @@
       'WMS_SHELF',
       "SHELF_CODE='" + params.SHELF_CODE + "'AND AUTH_ORG='" + Shelfitem.ORG_CODE + "'",
     );
-    var check = await isExist(usParams);
+    const check = await isExist(usParams);
     if (!check.Data) {
       //Shelfitem.AUTH_ORG = useUserStore().getUserInfo.orgCode as string;
       data = await defHttp.post(
@@ -255,7 +254,7 @@
         },
       );
     } else {
-      data=false;
+      data = false;
     }
   }
   return data;
@@ -305,7 +304,7 @@
 export const SaveLocation = async (params: Recordable, isUpdate: boolean) => {
   let data;
   {
-    var locations = [];
+    const locations = [];
     params.forEach((items) => {
       items.forEach((item) => {
         item.CREATE_USER = useUserStore().getUserInfo.userId as string;
diff --git a/src/components/FlowChart/src/FlowChart.vue b/src/components/FlowChart/src/FlowChart.vue
index 318cc49..9877602 100644
--- a/src/components/FlowChart/src/FlowChart.vue
+++ b/src/components/FlowChart/src/FlowChart.vue
@@ -6,6 +6,7 @@
       @view-data="handlePreview"
       @save-data="handleSave"
       @add-data="handleAdd"
+      @addlf="handleAddlf"
     />
     <div ref="lfElRef" class="h-full"></div>
     <BasicModal @register="register" title="娴佺▼鏁版嵁" width="50%">
@@ -59,7 +60,8 @@
         type: Array,
       },
     },
-    setup(props) {
+    emits: ['view-data', 'save-data', 'add-lf'],
+    setup(props, { emit }) {
       const globSetting = useGlobSetting();
       const lfElRef = ref(null);
       const graphData = ref({});
@@ -161,6 +163,7 @@
           lf.on('anchor:drop', (data) => {
             const nodeData = data.nodeModel.getData();
             if (nodeData.properties.isReturn === true) {
+              console.log(11, nodeData.properties.isReturn);
               data.nodeModel.graphModel.edges.forEach((element) => {
                 if (element.sourceNodeId === data.nodeModel.id) {
                   lf.changeEdgeType(element.id, 'custom-edge');
@@ -170,12 +173,16 @@
           });
         }
         lf.on('node:click,edge:click', (data) => {
-          console.log(data.data.text.value, data.isSelected);
-          notification.success({
-            message: t('鐐瑰嚮浜嗚妭鐐�'),
-            description: `${data.data.text.value}: ${data.isSelected}`,
-            duration: 3,
-          });
+          if (data.isSelected) {
+            console.log(data.data.text.value, data.isSelected);
+            notification.success({
+              message: t('鐐瑰嚮浜嗚妭鐐�'),
+              description: `${data.data.text.value}: ${data.isSelected}`,
+              duration: 3,
+            });
+          } else {
+            console.log(data.data.type);
+          }
         });
       }
 
@@ -189,11 +196,12 @@
       }
 
       function handleSave() {
-        console.log('handleSave');
+        // console.log('handleSave');
         const lf = unref(lfInstance);
         if (!lf) {
           return;
         }
+        emit('save-data', lf);
       }
 
       function handleAdd() {
@@ -206,6 +214,14 @@
         lf.render({});
       }
 
+      function handleAddlf() {
+        const lf = unref(lfInstance);
+        if (!lf) {
+          return;
+        }
+        emit('add-lf', lf);
+      }
+
       onMounted(init);
 
       return {
@@ -216,6 +232,7 @@
         graphData,
         handleSave,
         handleAdd,
+        handleAddlf,
       };
     },
   });
diff --git a/src/components/FlowChart/src/FlowChartToolbar.vue b/src/components/FlowChart/src/FlowChartToolbar.vue
index e2d05c4..4b14750 100644
--- a/src/components/FlowChart/src/FlowChartToolbar.vue
+++ b/src/components/FlowChart/src/FlowChartToolbar.vue
@@ -30,9 +30,14 @@
     props: {
       prefixCls: String,
     },
-    emits: ['view-data'],
+    emits: ['view-data', 'save-data', 'addlf'],
     setup(_, { emit }) {
       const toolbarItemList = ref<ToolbarConfig[]>([
+        {
+          type: ToolbarTypeEnum.ADD,
+          icon: 'ion:add-outline',
+          tooltip: '鏂板娴佺▼',
+        },
         {
           type: ToolbarTypeEnum.ZOOM_IN,
           icon: 'codicon:zoom-out',
@@ -68,6 +73,11 @@
           tooltip: '涓嬭浇',
         },
         {
+          type: ToolbarTypeEnum.SAVE_DATA,
+          icon: 'ion:save-outline',
+          tooltip: '淇濆瓨',
+        },
+        {
           type: ToolbarTypeEnum.VIEW_DATA,
           icon: 'carbon:document-view',
           tooltip: '鏌ョ湅鏁版嵁',
@@ -94,6 +104,9 @@
           return;
         }
         switch (item.type) {
+          case ToolbarTypeEnum.ADD:
+            emit('addlf');
+            break;
           case ToolbarTypeEnum.ZOOM_IN:
             lf.zoom();
             break;
@@ -115,6 +128,9 @@
           case ToolbarTypeEnum.VIEW_DATA:
             emit('view-data');
             break;
+          case ToolbarTypeEnum.SAVE_DATA:
+            emit('save-data');
+            break;
         }
       };
 
diff --git a/src/components/FlowChart/src/enum.ts b/src/components/FlowChart/src/enum.ts
index 8ea134c..c979ff6 100644
--- a/src/components/FlowChart/src/enum.ts
+++ b/src/components/FlowChart/src/enum.ts
@@ -1,4 +1,5 @@
 export enum ToolbarTypeEnum {
+  ADD = 'add',
   ZOOM_IN = 'zoomIn',
   ZOOM_OUT = 'zoomOut',
   RESET_ZOOM = 'resetZoom',
@@ -8,4 +9,5 @@
 
   SNAPSHOT = 'snapshot',
   VIEW_DATA = 'viewData',
+  SAVE_DATA = 'saveData',
 }
diff --git a/src/hooks/setting/index.ts b/src/hooks/setting/index.ts
index 10d9dbf..f46379f 100644
--- a/src/hooks/setting/index.ts
+++ b/src/hooks/setting/index.ts
@@ -3,8 +3,14 @@
 import { getAppEnvConfig } from '/@/utils/env';
 
 export const useGlobSetting = (): Readonly<GlobConfig> => {
-  const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_UPLOAD_URL, VITE_GLOB_MAP_KEY, VITE_GLOB_TSK_API_URL } =
-    getAppEnvConfig();
+  const {
+    VITE_GLOB_APP_TITLE,
+    VITE_GLOB_API_URL,
+    VITE_GLOB_API_URL_PREFIX,
+    VITE_GLOB_UPLOAD_URL,
+    VITE_GLOB_MAP_KEY,
+    VITE_GLOB_TSK_API_URL,
+  } = getAppEnvConfig();
 
   // Take global configuration
   const glob: Readonly<GlobConfig> = {
diff --git a/src/utils/env.ts b/src/utils/env.ts
index 9600ffc..0c81914 100644
--- a/src/utils/env.ts
+++ b/src/utils/env.ts
@@ -25,8 +25,14 @@
       (import.meta.env as unknown as GlobEnvConfig)
     : window[ENV_NAME as any]) as unknown as GlobEnvConfig;
 
-  const { VITE_GLOB_APP_TITLE, VITE_GLOB_API_URL, VITE_GLOB_API_URL_PREFIX, VITE_GLOB_UPLOAD_URL, VITE_GLOB_MAP_KEY,VITE_GLOB_TSK_API_URL } =
-    ENV;
+  const {
+    VITE_GLOB_APP_TITLE,
+    VITE_GLOB_API_URL,
+    VITE_GLOB_API_URL_PREFIX,
+    VITE_GLOB_UPLOAD_URL,
+    VITE_GLOB_MAP_KEY,
+    VITE_GLOB_TSK_API_URL,
+  } = ENV;
 
   return {
     VITE_GLOB_APP_TITLE,
diff --git a/src/views/form-design/components/VFormDesign/components/FormProps.vue b/src/views/form-design/components/VFormDesign/components/FormProps.vue
index f170781..d059c46 100644
--- a/src/views/form-design/components/VFormDesign/components/FormProps.vue
+++ b/src/views/form-design/components/VFormDesign/components/FormProps.vue
@@ -81,6 +81,7 @@
   import { InputNumber, Slider, Checkbox, Col, RadioChangeEvent } from 'ant-design-vue';
   // import RadioButtonGroup from '/@/components/RadioButtonGroup.vue';
   import { Form, FormItem, Radio } from 'ant-design-vue';
+
   export default defineComponent({
     name: 'FormProps',
     components: {
diff --git a/src/views/tigerprojects/mes/eng/route/RouteDrawer.vue b/src/views/tigerprojects/mes/eng/route/RouteDrawer.vue
new file mode 100644
index 0000000..0e27c6c
--- /dev/null
+++ b/src/views/tigerprojects/mes/eng/route/RouteDrawer.vue
@@ -0,0 +1,74 @@
+<template>
+  <BasicDrawer
+    v-bind="$attrs"
+    @register="registerDrawer"
+    showFooter
+    :title="getTitle"
+    width="800px"
+    @ok="handleSubmit"
+  >
+    <BasicForm @register="registerForm" />
+  </BasicDrawer>
+</template>
+<script lang="ts">
+  import { defineComponent, ref, computed, unref, Ref } from 'vue';
+  import { BasicForm, useForm } from '/@/components/Form/index';
+  import { formSchema } from './route.data';
+  import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
+  import { SaveRoute } from '/@/api/tigerapi/mes/router';
+  import LogicFlow from '@logicflow/core';
+
+  export default defineComponent({
+    name: 'LocationDrawer',
+    components: { BasicDrawer, BasicForm },
+    emits: ['success', 'register'],
+    setup(_, { emit }) {
+      const isUpdate = ref(true);
+      const lfInstance = ref(null) as Ref<LogicFlow | null>;
+      const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
+        labelWidth: 120,
+        schemas: formSchema,
+        actionColOptions: {
+          span: 24,
+        },
+        showActionButtonGroup: false,
+      });
+
+      const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
+        resetFields();
+        setDrawerProps({ confirmLoading: false });
+        isUpdate.value = !!data?.isUpdate;
+        lfInstance.value = data?.lf;
+        if (unref(isUpdate)) {
+          setFieldsValue({
+            ...data.record,
+          });
+        }
+      });
+
+      const getTitle = computed(() => (!unref(isUpdate) ? '鏂板宸ヨ壓璺嚎' : '缂栬緫宸ヨ壓璺嚎'));
+
+      async function handleSubmit() {
+        try {
+          const values = await validate();
+          setDrawerProps({ confirmLoading: true });
+          //淇濆瓨宸ヨ壓璺嚎
+          const apiAction = await SaveRoute(values);
+          if (apiAction.IsSuccessed) {
+            closeDrawer();
+            emit('success', lfInstance);
+          }
+        } finally {
+          setDrawerProps({ confirmLoading: false });
+        }
+      }
+
+      return {
+        registerDrawer,
+        registerForm,
+        getTitle,
+        handleSubmit,
+      };
+    },
+  });
+</script>
diff --git a/src/views/tigerprojects/mes/eng/route/components/FormItemProps.vue b/src/views/tigerprojects/mes/eng/route/components/FormItemProps.vue
new file mode 100644
index 0000000..49196d7
--- /dev/null
+++ b/src/views/tigerprojects/mes/eng/route/components/FormItemProps.vue
@@ -0,0 +1,54 @@
+<!--
+ * @Description: 琛ㄥ崟椤瑰睘鎬э紝鎺т欢灞炴�ч潰鏉�
+-->
+<template>
+  <div class="properties-content">
+    <div class="properties-body" v-if="itemProps">
+      <Empty class="hint-box" v-if="!itemProps" description="鏈�夋嫨鎺т欢" />
+      <Form v-else label-align="left" layout="vertical">
+        <div v-for="item of baseFormItemProps" :key="item.name">
+          <FormItem :label="item.label" v-if="showProps(item.exclude)">
+            <component
+              class="component-props"
+              v-bind="item.componentProps"
+              :is="item.component"
+              v-model:value="formConfig.currentItem[item.name]"
+            />
+          </FormItem>
+        </div>
+      </Form>
+    </div>
+  </div>
+</template>
+<script lang="ts" setup>
+  import { computed, ref, watch } from 'vue';
+  import { Empty, Input, Form, FormItem, Switch, Checkbox, Col } from 'ant-design-vue';
+
+  const itemProps = ref(true);
+  const baseFormItemProps = ref([]);
+  // watch(
+  //   () => formConfig.value,
+  //   () => {
+  //     if (formConfig.value.currentItem) {
+  //       formConfig.value.currentItem.itemProps = formConfig.value.currentItem.itemProps || {};
+  //       formConfig.value.currentItem.itemProps.labelCol =
+  //         formConfig.value.currentItem.itemProps.labelCol || {};
+  //       formConfig.value.currentItem.itemProps.wrapperCol =
+  //         formConfig.value.currentItem.itemProps.wrapperCol || {};
+  //     }
+  //   },
+  //   { deep: true, immediate: true },
+  // );
+  // const showProps = (exclude: string[] | undefined) => {
+  //   if (!exclude) {
+  //     return true;
+  //   }
+  //   return isArray(exclude) ? !exclude.includes(formConfig.value.currentItem!.component) : true;
+  // };
+
+  // const controlPropsList = computed(() => {
+  //   return baseFormItemControlAttrs.filter((item) => {
+  //     return showProps(item.exclude);
+  //   });
+  // });
+</script>
diff --git a/src/views/tigerprojects/mes/eng/route/components/FormProps.vue b/src/views/tigerprojects/mes/eng/route/components/FormProps.vue
new file mode 100644
index 0000000..f10bda1
--- /dev/null
+++ b/src/views/tigerprojects/mes/eng/route/components/FormProps.vue
@@ -0,0 +1,43 @@
+<!--
+ * @Description: 鍙充晶灞炴�ч潰鏉挎帶浠� 琛ㄥ崟灞炴�ч潰鏉�
+-->
+<template>
+  <div class="properties-content">
+    <Form class="properties-body" label-align="left" layout="vertical">
+      <!--      <e-upload v-model="fileList"></e-upload>-->
+
+      <FormItem label="琛ㄥ崟甯冨眬">
+        <RadioGroup button-style="solid" v-model:value="formConfig.layout">
+          <RadioButton value="horizontal">姘村钩</RadioButton>
+          <RadioButton value="vertical" :disabled="formConfig.labelLayout === 'Grid'">
+            鍨傜洿
+          </RadioButton>
+          <RadioButton value="inline" :disabled="formConfig.labelLayout === 'Grid'">
+            琛屽唴
+          </RadioButton>
+        </RadioGroup>
+      </FormItem>
+
+      <!-- <Row> -->
+    </Form>
+  </div>
+</template>
+<script lang="ts" setup>
+  import { Radio, Form, FormItem } from 'ant-design-vue';
+  import { ref } from 'vue';
+
+  const RadioGroup = Radio.Group;
+  const RadioButton = Radio.Button;
+
+  const formConfig = ref({
+    colon: true,
+    disabled: false,
+    hideRequiredMark: true,
+    layout: 'horizontal',
+    size: 120,
+    labelLayout: 'Grid',
+    labelWidth: '120',
+    labelCol: 24,
+    labelAlign: 'Left',
+  });
+</script>
diff --git a/src/views/tigerprojects/mes/eng/route/components/PropsPanel.vue b/src/views/tigerprojects/mes/eng/route/components/PropsPanel.vue
new file mode 100644
index 0000000..3647890
--- /dev/null
+++ b/src/views/tigerprojects/mes/eng/route/components/PropsPanel.vue
@@ -0,0 +1,80 @@
+<!--
+ * @Description: 鍙充晶灞炴�ч厤缃潰鏉�
+-->
+<template>
+  <div>
+    <Tabs v-model:activeKey="activeKey" :tabBarStyle="{ margin: 0 }">
+      <TabPane :key="1" tab="宸ヨ壓璺嚎">
+        <FormProps />
+      </TabPane>
+      <TabPane :key="2" tab="宸ュ簭">
+        <FormItemProps />
+      </TabPane>
+      <!-- <TabPane :key="3" tab="鏍呮牸">
+        <ComponentColumnProps />
+      </TabPane>
+      <TabPane :key="4" tab="缁勪欢">
+        <slot v-if="slotProps" :name="slotProps.component + 'Props'"></slot>
+        <ComponentProps v-else />
+      </TabPane> -->
+    </Tabs>
+  </div>
+</template>
+<script lang="ts" setup>
+  import { ref } from 'vue';
+  import FormProps from './FormProps.vue';
+  import FormItemProps from './FormItemProps.vue';
+  // import ComponentProps from '../components/ComponentProps.vue';
+  // import ComponentColumnProps from '../components/FormItemColumnProps.vue';
+  // import { useFormDesignState } from '../../../hooks/useFormDesignState';
+  // import { customComponents } from '../../../core/formItemConfig';
+  import { TabPane, Tabs } from 'ant-design-vue';
+
+  type ChangeTabKey = 1 | 2;
+  export interface IPropsPanel {
+    changeTab: (key: ChangeTabKey) => void;
+  }
+  const activeKey = ref(1);
+</script>
+
+<style lang="less" scoped>
+  @import url('../styles/variable.less');
+
+  :deep(.ant-tabs) {
+    box-sizing: border-box;
+
+    form {
+      position: absolute;
+      width: 100%;
+      height: calc(100% - 50px);
+      margin-right: 10px;
+      overflow-x: hidden;
+      overflow-y: auto;
+    }
+
+    .hint-box {
+      margin-top: 200px;
+    }
+
+    .ant-form-item,
+    .ant-slider-with-marks {
+      margin-right: 20px;
+      margin-bottom: 0;
+      margin-left: 10px;
+    }
+
+    .ant-form-item {
+      // width: 100%;
+      margin-bottom: 0;
+
+      .ant-form-item-label {
+        line-height: 2;
+        vertical-align: text-top;
+      }
+    }
+
+    .ant-input-number {
+      width: 100%;
+    }
+  }
+</style>
diff --git a/src/views/tigerprojects/mes/eng/router/dataTurbo.json b/src/views/tigerprojects/mes/eng/route/dataTurbo.json
similarity index 100%
rename from src/views/tigerprojects/mes/eng/router/dataTurbo.json
rename to src/views/tigerprojects/mes/eng/route/dataTurbo.json
diff --git a/src/views/tigerprojects/mes/eng/route/index.vue b/src/views/tigerprojects/mes/eng/route/index.vue
new file mode 100644
index 0000000..65e8a47
--- /dev/null
+++ b/src/views/tigerprojects/mes/eng/route/index.vue
@@ -0,0 +1,446 @@
+<template>
+  <PageWrapper title="宸ヨ壓娴佺▼鍥�" content="鏍规嵁鐢熶骇宸ヨ壓璁捐宸ヨ壓娴佺▼" contentFullHeight fixedHeight>
+    <Layout class="h-full">
+      <LayoutContent>
+        <FlowChart :data="demoData" @save-data="handleSave" @add-lf="handleAddlf" />
+      </LayoutContent>
+      <LayoutSider
+        :class="`right`"
+        collapsible
+        :reverseArrow="true"
+        collapsedWidth="0"
+        width="450"
+        style="background: #fafafa; border-left: 1px solid #d9d9d9; padding: 10px"
+        :zeroWidthTriggerStyle="{ 'margin-top': '-70px', 'background-color': 'gray' }"
+      >
+        <PropsPanel ref="propsPanel" :activeKey="activeKey">
+          <template v-for="item of schemas" #[`${item.component}Props`]="data">
+            <slot
+              :name="`${item.component}Props`"
+              v-bind="{ formItem: data, props: data.componentProps }"
+            ></slot>
+          </template>
+        </PropsPanel>
+        <!-- <BasicForm
+          autoFocusFirstItem
+          :labelWidth="120"
+          :schemas="schemas"
+          :actionColOptions="{ span: 24 }"
+          :submitButtonOptions="{ text: '纭畾' }"
+          @submit="handleSubmit"
+          @reset="handleReset"
+      /> -->
+      </LayoutSider>
+    </Layout>
+    <RouteDrawer @register="registerDrawer" @success="handleSuccess" />
+  </PageWrapper>
+</template>
+
+<script lang="ts" setup>
+  import { FlowChart } from '/@/components/FlowChart';
+  import { PageWrapper } from '/@/components/Page';
+  import { BasicForm, FormSchema } from '/@/components/Form/index';
+  import { getOperAllList } from '/@/api/tigerapi/mes/oper';
+  import { SaveRouteData } from '/@/api/tigerapi/mes/router';
+  import { ref, unref } from 'vue';
+  import { Layout, LayoutContent, LayoutSider } from 'ant-design-vue';
+  import {
+    RouteData,
+    node,
+    edge,
+    MES_ROUTE_NODE,
+    MES_ROUTE_EDGE,
+  } from '/@/api/tigerapi/model/router';
+  import { useUserStore } from '/@/store/modules/user';
+  import { buildUUID } from '/@/utils/uuid';
+  import RouteDrawer from './RouteDrawer.vue';
+  import { useDrawer } from '/@/components/Drawer';
+  import PropsPanel from './components/PropsPanel.vue';
+
+  const [registerDrawer, { openDrawer }] = useDrawer();
+  const isRute = (type: string) => type === '0';
+  const isOper = (type: string) => type === '1';
+  const activeKey = ref(1);
+  const schemas: FormSchema[] = [
+    {
+      field: 'func_type',
+      label: '灞炴�ч〉',
+      component: 'RadioButtonGroup',
+      defaultValue: '0',
+      componentProps: {
+        options: [
+          { label: '宸ヨ壓娴佺▼', value: '0' },
+          { label: '宸ュ簭', value: '1' },
+        ],
+      },
+      colProps: { lg: 24, md: 24 },
+    },
+    {
+      field: 'OPER_CODE',
+      component: 'ApiSelect',
+      label: '閫夋嫨宸ュ簭',
+      componentProps: {
+        api: getOperAllList,
+        // params: {
+        //   id: 1,
+        // },
+        resultField: 'items',
+        labelField: 'OPER_NAME',
+        valueField: 'OPER_CODE',
+        // not request untill to select
+        immediate: false,
+        onChange: (e) => {
+          console.log('selected:', e);
+        },
+        // atfer request callback
+        onOptionsChange: (options) => {
+          console.log('get options', options.length, options);
+        },
+      },
+      ifShow: ({ values }) => isOper(values.func_type),
+    },
+    {
+      field: 'field2',
+      component: 'Input',
+      label: '宸ュ簭绫诲瀷',
+      // componentProps:{},
+      // can func
+      componentProps: ({ schema, formModel }) => {
+        console.log('form:', schema);
+        console.log('formModel:', formModel);
+        return {
+          placeholder: '娴嬭瘯',
+          onChange: (e: any) => {
+            console.log(e);
+          },
+        };
+      },
+      renderComponentContent: () => {
+        return {
+          prefix: () => '宸ュ簭',
+          suffix: () => '绫诲瀷',
+        };
+      },
+      ifShow: ({ values }) => isOper(values.func_type),
+    },
+    {
+      field: 'field3',
+      component: 'Select',
+      label: '宸ュ簭琛屼负',
+      componentProps: {
+        options: [
+          {
+            label: '瀛樺偍杩囩▼',
+            value: '1',
+            key: '1',
+          },
+          {
+            label: '鏉$爜瑙勫垯',
+            value: '2',
+            key: '2',
+          },
+          {
+            label: '琛屼负涓�',
+            value: '3',
+            key: '3',
+          },
+          {
+            label: '琛屼负浜�',
+            value: '4',
+            key: '4',
+          },
+          {
+            label: '琛屼负涓�',
+            value: '5',
+            key: '5',
+          },
+        ],
+      },
+      ifShow: ({ values }) => isOper(values.func_type),
+    },
+    {
+      field: 'field4',
+      component: 'Switch',
+      label: '鏄惁璁$畻鐩撮�氱巼',
+      colProps: {
+        span: 16,
+      },
+      labelWidth: 200,
+      ifShow: ({ values }) => isOper(values.func_type),
+    },
+    {
+      field: 'field5',
+      component: 'Switch',
+      label: '鏄惁鍙烦绔�',
+      colProps: {
+        span: 16,
+      },
+      labelWidth: 200,
+      ifShow: ({ values }) => isOper(values.func_type),
+    },
+    {
+      field: 'ROT_CODE',
+      label: '宸ヨ壓璺嚎缂栫爜',
+      required: true,
+      component: 'Input',
+      colProps: { span: 16 },
+      ifShow: ({ values }) => isRute(values.func_type),
+    },
+    {
+      field: 'ROT_NAME',
+      label: '宸ヨ壓璺嚎鍚嶇О',
+      required: true,
+      component: 'Input',
+      colProps: { span: 16 },
+      ifShow: ({ values }) => isRute(values.func_type),
+    },
+    {
+      field: 'ROT_TYPE',
+      label: '宸ヨ壓璺嚎绫诲瀷',
+      required: true,
+      component: 'Input',
+      colProps: { span: 16 },
+      ifShow: ({ values }) => isRute(values.func_type),
+    },
+    {
+      field: 'ROT_VER',
+      label: '宸ヨ壓璺嚎鐗堟湰',
+      required: true,
+      component: 'Input',
+      colProps: { span: 16 },
+      ifShow: ({ values }) => isRute(values.func_type),
+    },
+    {
+      field: 'IS_ACTIVE',
+      label: '鏄惁鍚敤',
+      required: true,
+      component: 'Select',
+      colProps: { span: 16 },
+      componentProps: {
+        options: [
+          {
+            label: '鏄�',
+            value: 'Y',
+            key: 'Y',
+          },
+          {
+            label: '鍚�',
+            value: 'N',
+            key: 'N',
+          },
+        ],
+      },
+      ifShow: ({ values }) => isRute(values.func_type),
+    },
+  ];
+  const demoData = ref({});
+  // const demoData1 = ref({
+  //   nodes: [
+  //     {
+  //       id: '5d82e943-477f-4313-aaff-a736d8caba74',
+  //       type: 'rect',
+  //       x: 340,
+  //       y: 120,
+  //       properties: {},
+  //       text: {
+  //         x: 340,
+  //         y: 120,
+  //         value: '娴嬭瘯宸ュ簭',
+  //       },
+  //     },
+  //     {
+  //       id: '6e0c6714-69a7-4160-8bda-61f4e6d285dd',
+  //       type: 'rect',
+  //       x: 560,
+  //       y: 120,
+  //       properties: {},
+  //       text: {
+  //         x: 560,
+  //         y: 120,
+  //         value: '涓婃枡宸ュ簭',
+  //       },
+  //     },
+  //     {
+  //       id: '80b2ee17-5a0e-4586-ba28-6ba59fcc0f59',
+  //       type: 'rect',
+  //       x: 340,
+  //       y: 280,
+  //       properties: {
+  //         isReturn: true,
+  //       },
+  //       text: {
+  //         x: 340,
+  //         y: 280,
+  //         value: '缁翠慨宸ュ簭',
+  //       },
+  //     },
+  //   ],
+  //   edges: [
+  //     {
+  //       id: 'Flow_0p4u47c',
+  //       type: 'bpmn:sequenceFlow',
+  //       sourceNodeId: '5d82e943-477f-4313-aaff-a736d8caba74',
+  //       targetNodeId: '6e0c6714-69a7-4160-8bda-61f4e6d285dd',
+  //       startPoint: {
+  //         x: 390,
+  //         y: 120,
+  //       },
+  //       endPoint: {
+  //         x: 510,
+  //         y: 120,
+  //       },
+  //       properties: {},
+  //       pointsList: [
+  //         {
+  //           x: 390,
+  //           y: 120,
+  //         },
+  //         {
+  //           x: 510,
+  //           y: 120,
+  //         },
+  //       ],
+  //     },
+  //     {
+  //       id: 'Flow_09tu4cm',
+  //       type: 'bpmn:sequenceFlow',
+  //       sourceNodeId: '5d82e943-477f-4313-aaff-a736d8caba74',
+  //       targetNodeId: '80b2ee17-5a0e-4586-ba28-6ba59fcc0f59',
+  //       startPoint: {
+  //         x: 340,
+  //         y: 160,
+  //       },
+  //       endPoint: {
+  //         x: 340,
+  //         y: 240,
+  //       },
+  //       properties: {},
+  //       pointsList: [
+  //         {
+  //           x: 340,
+  //           y: 160,
+  //         },
+  //         {
+  //           x: 340,
+  //           y: 240,
+  //         },
+  //       ],
+  //     },
+  //     {
+  //       id: '22226ec4-9960-497d-93cb-6226a3f29b3d',
+  //       type: 'custom-edge',
+  //       sourceNodeId: '80b2ee17-5a0e-4586-ba28-6ba59fcc0f59',
+  //       targetNodeId: '5d82e943-477f-4313-aaff-a736d8caba74',
+  //       startPoint: {
+  //         x: 351,
+  //         y: 240,
+  //       },
+  //       endPoint: {
+  //         x: 351,
+  //         y: 160,
+  //       },
+  //       properties: {},
+  //       pointsList: [
+  //         {
+  //           x: 351,
+  //           y: 240,
+  //         },
+  //         {
+  //           x: 351,
+  //           y: 160,
+  //         },
+  //       ],
+  //     },
+  //   ],
+  // });
+  function handleReset() {}
+  function handleSubmit(_values: any) {
+    try {
+    } catch {}
+  }
+
+  async function handleSave(lf) {
+    console.log('handleSave', unref(lf).getGraphData().nodes[0]);
+    var _routeData: RouteData = {
+      route: {
+        ID: buildUUID(),
+        CREATE_TIME: new Date(),
+        CREATE_USER: useUserStore().getUserInfo.userId as string,
+        UPDATE_TIME: new Date(),
+        UPDATE_USER: useUserStore().getUserInfo.userId as string,
+        GHOST_ROW: false,
+        ROT_CODE: 'R001',
+        ROT_NAME: 'R001',
+        ROT_TYPE: '',
+        ROT_VER: '01',
+        IS_ACTIVE: 'Y',
+        REMARK: 'R001',
+      },
+      nodes: [],
+      edges: [],
+    };
+    var _nodes = unref(lf).getGraphData().nodes as node[];
+    var _edges = unref(lf).getGraphData().edges as edge[];
+    _nodes.forEach((n) => {
+      var node: MES_ROUTE_NODE = {
+        ID: '',
+        CREATE_TIME: _routeData.route.CREATE_TIME,
+        CREATE_USER: useUserStore().getUserInfo.userId as string,
+        UPDATE_TIME: _routeData.route.UPDATE_TIME,
+        UPDATE_USER: useUserStore().getUserInfo.userId as string,
+        GHOST_ROW: false,
+        NODE_CODE: 'N001',
+        NODE_NAME: 'N001',
+        ROT_CODE: _routeData.route.ROT_CODE,
+        SEGMENT: '',
+        OPER_CODE: '',
+        GPH_TYPE: n.type,
+        GPH_X: n.x,
+        GPH_Y: n.y,
+        GPH_PROP: '',
+        GPH_TEXT: n.text.value,
+        IS_ACTIVE: 'Y',
+        IS_CALC_FPY: 'N',
+        CAN_SKIP: 'N',
+        REMARK: '',
+      };
+      _routeData.nodes.push(node);
+    });
+    _edges.forEach((e) => {
+      var edge: MES_ROUTE_EDGE = {
+        ID: '',
+        CREATE_TIME: _routeData.route.CREATE_TIME,
+        CREATE_USER: useUserStore().getUserInfo.userId as string,
+        UPDATE_TIME: _routeData.route.UPDATE_TIME,
+        UPDATE_USER: useUserStore().getUserInfo.userId as string,
+        GHOST_ROW: false,
+        EDGE_CODE: 'E001',
+        EDGE_NAME: 'E001',
+        ROT_CODE: _routeData.route.ROT_CODE,
+        SRC_NODE: e.sourceNodeId,
+        TGT_NODE: e.targetNodeId,
+        GPH_TYPE: e.type,
+        GPH_SRC_X: e.startPoint.x,
+        GPH_SRC_Y: e.startPoint.y,
+        GPH_TGT_X: e.endPoint.x,
+        GPH_TGT_Y: e.endPoint.y,
+        GPH_PROP: '',
+        GPH_POTS: JSON.stringify(e.pointsList),
+        REMARK: '',
+      };
+      _routeData.edges.push(edge);
+    });
+    await SaveRouteData(_routeData);
+  }
+
+  async function handleAddlf(lf) {
+    openDrawer(true, {
+      isUpdate: false,
+      lf: lf,
+    });
+  }
+
+  function handleSuccess(lfInstance) {
+    unref(lfInstance).render({});
+  }
+</script>
diff --git a/src/views/tigerprojects/mes/eng/route/route.data.ts b/src/views/tigerprojects/mes/eng/route/route.data.ts
new file mode 100644
index 0000000..d4fd487
--- /dev/null
+++ b/src/views/tigerprojects/mes/eng/route/route.data.ts
@@ -0,0 +1,66 @@
+import { FormSchema } from '/@/components/Table';
+
+export const formSchema: FormSchema[] = [
+  {
+    field: 'ROT_CODE',
+    label: '宸ヨ壓璺嚎缂栫爜',
+    required: true,
+    component: 'Input',
+    colProps: { span: 8 },
+  },
+  {
+    field: 'ID',
+    label: 'ID',
+    component: 'Input',
+    show: false,
+  },
+  {
+    field: 'ROT_NAME',
+    label: '宸ヨ壓璺嚎鍚嶇О',
+    required: true,
+    component: 'Input',
+    colProps: { span: 8 },
+  },
+  {
+    field: 'ROT_TYPE',
+    label: '宸ヨ壓璺嚎绫诲瀷',
+    required: true,
+    component: 'Input',
+    colProps: { span: 8 },
+  },
+  {
+    field: 'ROT_VER',
+    label: '宸ヨ壓璺嚎鐗堟湰',
+    // required: true,
+    component: 'Input',
+    colProps: { span: 8 },
+  },
+  {
+    field: 'IS_ACTIVE',
+    label: '鏄惁鍚敤(Y/N)',
+    required: true,
+    component: 'Select',
+    colProps: { span: 8 },
+    componentProps: {
+      options: [
+        {
+          label: '鏄�',
+          value: 'Y',
+          key: 'Y',
+        },
+        {
+          label: '鍚�',
+          value: 'N',
+          key: 'N',
+        },
+      ],
+    },
+  },
+  {
+    field: 'REMARK',
+    label: '澶囨敞',
+    // required: true,
+    component: 'Input',
+    colProps: { span: 24 },
+  },
+];
diff --git a/src/views/tigerprojects/mes/eng/route/styles/drag.less b/src/views/tigerprojects/mes/eng/route/styles/drag.less
new file mode 100644
index 0000000..3192f35
--- /dev/null
+++ b/src/views/tigerprojects/mes/eng/route/styles/drag.less
@@ -0,0 +1,225 @@
+.draggable-box {
+  height: 100%;
+  overflow: auto;
+
+  :deep(.list-main) {
+    overflow: hidden;
+    padding: 5px;
+    position: relative;
+
+    .moving {
+      // 鎷栨斁绉诲姩涓�;
+      min-height: 35px;
+      box-sizing: border-box;
+      overflow: hidden;
+      padding: 0 !important;
+      position: relative;
+
+      &::before {
+        content: '';
+        height: 5px;
+        width: 100%;
+        background-color: @primary-color;
+        position: absolute;
+        top: 0;
+        right: 0;
+      }
+    }
+
+    .drag-move-box {
+      position: relative;
+      box-sizing: border-box;
+      padding: 8px;
+      overflow: hidden;
+      transition: all 0.3s;
+      min-height: 60px;
+
+      &:hover {
+        background-color: @primary-hover-bg-color;
+      }
+
+      // 閫夋嫨鏃� start
+      &::before {
+        content: '';
+        height: 5px;
+        width: 100%;
+        background-color: @primary-color;
+        position: absolute;
+        top: 0;
+        right: -100%;
+        transition: all 0.3s;
+      }
+
+      &.active {
+        background-color: @primary-hover-bg-color;
+        outline-offset: 0;
+
+        &::before {
+          right: 0;
+        }
+      }
+
+      // 閫夋嫨鏃� end
+      .form-item-box {
+        position: relative;
+        box-sizing: border-box;
+        word-wrap: break-word;
+
+        &::before {
+          content: '';
+          position: absolute;
+          width: 100%;
+          height: 100%;
+          top: 0;
+          left: 0;
+        }
+
+        .ant-form-item {
+          // 淇敼ant form-item鐨刴argin涓簆adding
+          margin: 0;
+          padding-bottom: 6px;
+        }
+      }
+
+      .show-key-box {
+        // 鏄剧ずkey
+        position: absolute;
+        bottom: 2px;
+        right: 5px;
+        font-size: 14px;
+        // z-index: 999;
+        color: @primary-color;
+      }
+
+      .copy,
+      .delete {
+        position: absolute;
+        top: 0;
+        width: 30px;
+        height: 30px;
+        line-height: 30px;
+        text-align: center;
+        color: #fff;
+        // z-index: 989;
+        transition: all 0.3s;
+
+        &.unactivated {
+          opacity: 0 !important;
+          pointer-events: none;
+        }
+
+        &.active {
+          opacity: 1 !important;
+        }
+      }
+
+      .copy {
+        border-radius: 0 0 0 8px;
+        right: 30px;
+        background-color: @primary-color;
+      }
+
+      .delete {
+        right: 0;
+        background-color: @primary-color;
+      }
+    }
+
+    .grid-box {
+      position: relative;
+      box-sizing: border-box;
+      padding: 5px;
+      background-color: @layout-background-color;
+      width: 100%;
+      transition: all 0.3s;
+      overflow: hidden;
+
+      .form-item-box {
+        position: relative;
+        box-sizing: border-box;
+
+        .ant-form-item {
+          // 淇敼ant form-item鐨刴argin涓簆adding
+          margin: 0;
+          padding-bottom: 15px;
+        }
+      }
+
+      .grid-row {
+        background-color: @layout-background-color;
+
+        .grid-col {
+          .draggable-box {
+            min-height: 80px;
+            min-width: 50px;
+            border: 1px #ccc dashed;
+            // background: #fff;
+
+            .list-main {
+              min-height: 83px;
+              position: relative;
+              border: 1px #ccc dashed;
+            }
+          }
+        }
+      }
+
+      // 閫夋嫨鏃� start
+      &::before {
+        content: '';
+        height: 5px;
+        width: 100%;
+        background: transparent;
+        position: absolute;
+        top: 0;
+        right: -100%;
+        transition: all 0.3s;
+      }
+
+      &.active {
+        background-color: @layout-hover-bg-color;
+        outline-offset: 0;
+
+        &::before {
+          background-color: @layout-color;
+          right: 0;
+        }
+      }
+      // 閫夋嫨鏃� end
+      > .copy-delete-box {
+        > .copy,
+        > .delete {
+          position: absolute;
+          top: 0;
+          width: 30px;
+          height: 30px;
+          line-height: 30px;
+          text-align: center;
+          color: #fff;
+          // z-index: 989;
+          transition: all 0.3s;
+
+          &.unactivated {
+            opacity: 0 !important;
+            pointer-events: none;
+          }
+
+          &.active {
+            opacity: 1 !important;
+          }
+        }
+
+        > .copy {
+          border-radius: 0 0 0 8px;
+          right: 30px;
+          background-color: @layout-color;
+        }
+
+        > .delete {
+          right: 0;
+          background-color: @layout-color;
+        }
+      }
+    }
+  }
+}
diff --git a/src/views/tigerprojects/mes/eng/route/styles/variable.less b/src/views/tigerprojects/mes/eng/route/styles/variable.less
new file mode 100644
index 0000000..8749dce
--- /dev/null
+++ b/src/views/tigerprojects/mes/eng/route/styles/variable.less
@@ -0,0 +1,15 @@
+// 琛ㄥ崟璁捐鍣ㄦ牱寮�
+@primary-color: #13c2c2;
+@layout-color: #9867f7;
+
+@primary-background-color: fade(@primary-color, 6%);
+@primary-hover-bg-color: fade(@primary-color, 20%);
+@layout-background-color: fade(@layout-color, 12%);
+@layout-hover-bg-color: fade(@layout-color, 24%);
+
+@title-text-color: #fff;
+@border-color: #ccc;
+
+@left-right-width: 280px;
+@header-height: 56px;
+@operating-area-height: 45px;
diff --git a/src/views/tigerprojects/mes/eng/router/index.vue b/src/views/tigerprojects/mes/eng/router/index.vue
deleted file mode 100644
index 8d0e5a3..0000000
--- a/src/views/tigerprojects/mes/eng/router/index.vue
+++ /dev/null
@@ -1,272 +0,0 @@
-<template>
-  <PageWrapper title="宸ヨ壓娴佺▼鍥�" content="鏍规嵁鐢熶骇宸ヨ壓璁捐宸ヨ壓娴佺▼" contentFullHeight fixedHeight>
-    <a-layout style="min-height: 100vh">
-      <a-layout-content>
-        <FlowChart :data="demoData" />
-      </a-layout-content>
-      <a-layout-sider
-        width="450"
-        style="background: #fafafa; border-left: 1px solid #d9d9d9; padding: 20px"
-        ><BasicForm
-          autoFocusFirstItem
-          :labelWidth="80"
-          :schemas="schemas"
-          :actionColOptions="{ span: 24 }"
-          :submitButtonOptions="{ text: '纭畾' }"
-          @submit="handleSubmit"
-          @reset="handleReset"
-      /></a-layout-sider>
-    </a-layout>
-  </PageWrapper>
-</template>
-
-<script lang="ts" setup>
-  import { FlowChart } from '/@/components/FlowChart';
-  import { PageWrapper } from '/@/components/Page';
-  import { BasicForm, FormSchema } from '/@/components/Form/index';
-  import { getOperAllList } from '/@/api/tigerapi/mes/oper';
-  import { ref } from 'vue';
-
-  const isRuter = (type: string) => type === '0';
-  const isOper = (type: string) => type === '1';
-  const schemas: FormSchema[] = [
-    // {
-    //   field: 'divider-basic',
-    //   component: 'Divider',
-    //   label: '灞炴�ч〉',
-    // },
-    {
-      field: 'func_type',
-      label: '灞炴�ч〉',
-      component: 'RadioButtonGroup',
-      defaultValue: '0',
-      componentProps: {
-        options: [
-          { label: '宸ヨ壓娴佺▼', value: '0' },
-          { label: '宸ュ簭', value: '1' },
-        ],
-      },
-      colProps: { lg: 24, md: 24 },
-    },
-    {
-      field: 'OPER_CODE',
-      component: 'ApiSelect',
-      label: '閫夋嫨宸ュ簭',
-      componentProps: {
-        api: getOperAllList,
-        // params: {
-        //   id: 1,
-        // },
-        resultField: 'items',
-        labelField: 'OPER_NAME',
-        valueField: 'OPER_CODE',
-        // not request untill to select
-        immediate: false,
-        onChange: (e) => {
-          console.log('selected:', e);
-        },
-        // atfer request callback
-        onOptionsChange: (options) => {
-          console.log('get options', options.length, options);
-        },
-      },
-      ifShow: ({ values }) => isOper(values.func_type),
-    },
-    {
-      field: 'field2',
-      component: 'Input',
-      label: '宸ュ簭绫诲瀷',
-      // componentProps:{},
-      // can func
-      componentProps: ({ schema, formModel }) => {
-        console.log('form:', schema);
-        console.log('formModel:', formModel);
-        return {
-          placeholder: '娴嬭瘯',
-          onChange: (e: any) => {
-            console.log(e);
-          },
-        };
-      },
-      renderComponentContent: () => {
-        return {
-          prefix: () => '宸ュ簭',
-          suffix: () => '绫诲瀷',
-        };
-      },
-    },
-    {
-      field: 'field3',
-      component: 'Select',
-      label: '宸ュ簭琛屼负',
-      componentProps: {
-        options: [
-          {
-            label: '瀛樺偍杩囩▼',
-            value: '1',
-            key: '1',
-          },
-          {
-            label: '鏉$爜瑙勫垯',
-            value: '2',
-            key: '2',
-          },
-          {
-            label: '琛屼负涓�',
-            value: '3',
-            key: '3',
-          },
-          {
-            label: '琛屼负浜�',
-            value: '4',
-            key: '4',
-          },
-          {
-            label: '琛屼负涓�',
-            value: '5',
-            key: '5',
-          },
-        ],
-      },
-    },
-    {
-      field: 'field4',
-      component: 'Switch',
-      label: '鏄惁璁$畻鐩撮�氱巼',
-      colProps: {
-        span: 16,
-      },
-      labelWidth: 200,
-    },
-    {
-      field: 'field5',
-      component: 'Switch',
-      label: '鏄惁鍙烦绔�',
-      colProps: {
-        span: 16,
-      },
-      labelWidth: 200,
-    },
-  ];
-  const demoData = ref({
-    nodes: [
-      {
-        id: '5d82e943-477f-4313-aaff-a736d8caba74',
-        type: 'rect',
-        x: 340,
-        y: 120,
-        properties: {},
-        text: {
-          x: 340,
-          y: 120,
-          value: '娴嬭瘯宸ュ簭',
-        },
-      },
-      {
-        id: '6e0c6714-69a7-4160-8bda-61f4e6d285dd',
-        type: 'rect',
-        x: 560,
-        y: 120,
-        properties: {},
-        text: {
-          x: 560,
-          y: 120,
-          value: '涓婃枡宸ュ簭',
-        },
-      },
-      {
-        id: '80b2ee17-5a0e-4586-ba28-6ba59fcc0f59',
-        type: 'rect',
-        x: 340,
-        y: 280,
-        properties: {
-          isReturn: true,
-        },
-        text: {
-          x: 340,
-          y: 280,
-          value: '缁翠慨宸ュ簭',
-        },
-      },
-    ],
-    edges: [
-      {
-        id: 'Flow_0p4u47c',
-        type: 'bpmn:sequenceFlow',
-        sourceNodeId: '5d82e943-477f-4313-aaff-a736d8caba74',
-        targetNodeId: '6e0c6714-69a7-4160-8bda-61f4e6d285dd',
-        startPoint: {
-          x: 390,
-          y: 120,
-        },
-        endPoint: {
-          x: 510,
-          y: 120,
-        },
-        properties: {},
-        pointsList: [
-          {
-            x: 390,
-            y: 120,
-          },
-          {
-            x: 510,
-            y: 120,
-          },
-        ],
-      },
-      {
-        id: 'Flow_09tu4cm',
-        type: 'bpmn:sequenceFlow',
-        sourceNodeId: '5d82e943-477f-4313-aaff-a736d8caba74',
-        targetNodeId: '80b2ee17-5a0e-4586-ba28-6ba59fcc0f59',
-        startPoint: {
-          x: 340,
-          y: 160,
-        },
-        endPoint: {
-          x: 340,
-          y: 240,
-        },
-        properties: {},
-        pointsList: [
-          {
-            x: 340,
-            y: 160,
-          },
-          {
-            x: 340,
-            y: 240,
-          },
-        ],
-      },
-      {
-        id: '22226ec4-9960-497d-93cb-6226a3f29b3d',
-        type: 'custom-edge',
-        sourceNodeId: '80b2ee17-5a0e-4586-ba28-6ba59fcc0f59',
-        targetNodeId: '5d82e943-477f-4313-aaff-a736d8caba74',
-        startPoint: {
-          x: 351,
-          y: 240,
-        },
-        endPoint: {
-          x: 351,
-          y: 160,
-        },
-        properties: {},
-        pointsList: [
-          {
-            x: 351,
-            y: 240,
-          },
-          {
-            x: 351,
-            y: 160,
-          },
-        ],
-      },
-    ],
-  });
-  function handleReset() {}
-  function handleSubmit(_values: any) {}
-</script>
diff --git a/src/views/tigerprojects/wms/location/location.data.ts b/src/views/tigerprojects/wms/location/location.data.ts
index 0b17d41..9125571 100644
--- a/src/views/tigerprojects/wms/location/location.data.ts
+++ b/src/views/tigerprojects/wms/location/location.data.ts
@@ -1,5 +1,4 @@
-import { BasicColumn } from '/@/components/Table';
-import { FormSchema } from '/@/components/Table';
+import { BasicColumn, FormSchema } from '/@/components/Table';
 import { h } from 'vue';
 import { Tag } from 'ant-design-vue';
 

--
Gitblit v1.9.3