Zimo 1 semana atrás
pai
commit
7706b6ba10

+ 32 - 0
src/App.vue

@@ -17,6 +17,24 @@ const electrical_stroke_modules_files = import.meta.glob('./assets/svgs/electric
   eager: true,
   as: 'raw'
 })
+const process_demo_image_files = import.meta.glob('./assets/images/process-demo/**.jpg', {
+  eager: true,
+  query: '?url',
+  import: 'default'
+})
+const process_demo_image_titles: Record<string, string> = {
+  'process-tank': '储罐',
+  'process-pump': '输送泵',
+  'process-valve': '控制阀',
+  'process-flowmeter': '流量计',
+  'process-heat-exchanger': '换热器',
+  'process-boiler': '加热炉',
+  'process-mixer': '搅拌反应器',
+  'process-treatment': '处理设备',
+  'process-blower': '鼓风机',
+  'process-pipe-branch': '支路管道',
+  'process-callout': '标注引线'
+}
 const electrical_register_config: any = []
 for (const key in electrical_modules_files) {
   //根据路径获取svg文件名
@@ -57,6 +75,20 @@ for (const key in electrical_stroke_modules_files) {
 }
 leftAsideStore.registerConfig('电气符号', electrical_register_config)
 
+const process_demo_register_config = Object.entries(process_demo_image_files).map(
+  ([key, url]) => {
+    const name = key.split('/').pop()!.split('.')[0]
+    return {
+      id: name,
+      title: process_demo_image_titles[name] || name,
+      type: 'img',
+      thumbnail: url,
+      props: {}
+    }
+  }
+)
+leftAsideStore.registerConfig('工艺流程图', process_demo_register_config)
+
 const route = useRoute()
 const { addListeners, removeListeners } = useAutoLogout()
 

+ 26 - 5
src/api/pms/maotu/index.ts

@@ -29,6 +29,7 @@ export type WebtopoProjectLinkedDevicePointParamVO = {
 
 export type WebtopoProjectDetailVO = WebtopoProjectVO & {
   dataModel?: unknown
+  dataModelParseError?: string
 }
 
 export type WebtopoProjectPageReqVO = {
@@ -63,17 +64,34 @@ const unwrapData = <T>(res: T | ApiResult<T>) => {
   return res as T
 }
 
-export const parseWebtopoDataModel = (dataModel: unknown) => {
+const parseWebtopoDataModelResult = (dataModel: unknown) => {
   if (typeof dataModel !== 'string') {
-    return dataModel
+    return {
+      dataModel
+    }
   }
 
   const trimmedDataModel = dataModel.trim()
   if (!trimmedDataModel) {
-    return undefined
+    return {
+      dataModel: undefined
+    }
+  }
+
+  try {
+    return {
+      dataModel: JSON.parse(trimmedDataModel)
+    }
+  } catch {
+    return {
+      dataModel: undefined,
+      dataModelParseError: '拓扑数据格式错误,无法解析 JSON'
+    }
   }
+}
 
-  return JSON.parse(trimmedDataModel)
+export const parseWebtopoDataModel = (dataModel: unknown) => {
+  return parseWebtopoDataModelResult(dataModel).dataModel
 }
 
 export const WebtopoProjectApi = {
@@ -105,9 +123,12 @@ export const WebtopoProjectApi = {
       return data
     }
 
+    const { dataModel, dataModelParseError } = parseWebtopoDataModelResult(data?.dataModel)
+
     return {
       ...data,
-      dataModel: parseWebtopoDataModel(data?.dataModel)
+      dataModel,
+      dataModelParseError
     }
   }
 }

BIN
src/assets/images/process-demo/process-blower.jpg


BIN
src/assets/images/process-demo/process-boiler.jpg


BIN
src/assets/images/process-demo/process-callout.jpg


BIN
src/assets/images/process-demo/process-flowmeter.jpg


BIN
src/assets/images/process-demo/process-heat-exchanger.jpg


BIN
src/assets/images/process-demo/process-mixer.jpg


BIN
src/assets/images/process-demo/process-pipe-branch.jpg


BIN
src/assets/images/process-demo/process-pump.jpg


BIN
src/assets/images/process-demo/process-tank.jpg


BIN
src/assets/images/process-demo/process-treatment.jpg


BIN
src/assets/images/process-demo/process-valve.jpg


+ 26 - 6
src/components/mt-edit/composables/index.ts

@@ -5,10 +5,24 @@ import type {
   IGlobalStoreCanvasCfg,
   IGlobalStoreGridCfg,
   ILeftAsideConfigItem,
-  ILeftAsideConfigItemPublicProps
+  ILeftAsideConfigItemPublicProps,
+  ILeftAsideConfigItemPublicPropsType
 } from '../store/types'
 import { objectDeepClone } from '../utils'
 
+const getImportedPropType = (val: unknown): ILeftAsideConfigItemPublicPropsType => {
+  if (typeof val === 'boolean') {
+    return 'switch'
+  }
+  if (typeof val === 'number') {
+    return 'number'
+  }
+  if (typeof val === 'object') {
+    return 'jsonEdit'
+  }
+  return 'input'
+}
+
 export const genExportJson = (
   canvasCfg: IGlobalStoreCanvasCfg,
   gridCfg: IGlobalStoreGridCfg,
@@ -54,11 +68,17 @@ export const useExportJsonToDoneJson = (json: IExportJson) => {
       props = { ...props, ...objectDeepClone(find_props) }
     }
 
-    for (const key in m.props) {
-      console.log('key', key)
-      console.log('props[key]', props[key])
-      console.log('m.props[key]', m.props[key])
-      props[key].val = m.props[key]
+    for (const key in m.props || {}) {
+      if (props[key]) {
+        props[key].val = m.props[key]
+      } else {
+        props[key] = {
+          title: key,
+          type: getImportedPropType(m.props[key]),
+          val: m.props[key],
+          disabled: true
+        }
+      }
     }
 
     if (find_item?.symbol) {

+ 14 - 3
src/config/axios/index.ts

@@ -4,16 +4,27 @@ import { config } from './config'
 
 const { default_headers } = config
 
+const DEFAULT_LANG = 'zh-CN'
+
+const getRequestLang = () => {
+  try {
+    const langStore = JSON.parse(localStorage.getItem('lang') || '{}')
+    const lang = typeof langStore === 'string' ? langStore : langStore?.v
+
+    return typeof lang === 'string' && lang ? lang.replace(/"/g, '') : DEFAULT_LANG
+  } catch {
+    return DEFAULT_LANG
+  }
+}
+
 const request = (option: any) => {
   const { headersType, headers, ...otherOption } = option
 
-  const langStore = JSON.parse(localStorage.getItem('lang') || '{}')
-
   return service({
     ...otherOption,
     headers: {
       'Content-Type': headersType || default_headers,
-      Lang: langStore.v.replace(/"/g, ''),
+      Lang: getRequestLang(),
       ...headers
     }
   })

+ 11 - 0
src/views/maotu/edit.vue

@@ -18,6 +18,7 @@ const router = useRouter()
 const MtEditRef = ref<InstanceType<typeof MtEdit>>()
 const projectDetail = ref<WebtopoProjectDetailVO>()
 const saveLoading = ref(false)
+const dataModelParseError = ref('')
 
 const getProjectId = () => {
   const id = Number(route.params.id)
@@ -37,6 +38,12 @@ const loadProject = async () => {
   try {
     const data = await WebtopoProjectApi.getWebtopoProject(id)
     projectDetail.value = data
+    dataModelParseError.value = data?.dataModelParseError || ''
+
+    if (dataModelParseError.value) {
+      ElMessage.error(dataModelParseError.value)
+      return
+    }
 
     if (data?.dataModel) {
       await nextTick()
@@ -109,6 +116,10 @@ const onSaveClick = async (dataModel: IExportJson) => {
     ElMessage.error('项目信息不存在,无法保存')
     return
   }
+  if (dataModelParseError.value) {
+    ElMessage.error('拓扑数据格式错误,修复后才能保存')
+    return
+  }
 
   try {
     saveLoading.value = true

+ 4 - 0
src/views/maotu/preview.vue

@@ -118,6 +118,10 @@ const loadProject = async () => {
 
   try {
     const data = await WebtopoProjectApi.getWebtopoProject(id)
+    if (data?.dataModelParseError) {
+      ElMessage.error(data.dataModelParseError)
+      return
+    }
     await setPreviewData(data?.dataModel)
     startDeviceBindPolling()
   } catch {