diff --git a/src/components/mt-edit/components/add-element/index.vue b/src/components/mt-edit/components/add-element/index.vue index 4234dc9..6179c62 100644 --- a/src/components/mt-edit/components/add-element/index.vue +++ b/src/components/mt-edit/components/add-element/index.vue @@ -79,7 +79,14 @@ /> --> - + + + 默认上传按钮(隐藏) + + { ) return selected_items.length > 1 }) +const uploadRef = ref() const import_visible = ref(false) const export_visible = ref(false) const done_json_tree_visiable = ref(false) @@ -169,12 +185,65 @@ const onDeleteClick = () => { cacheStore.addHistory(globalStore.done_json) } const onImportClick = () => { - import_visible.value = true - mainPanelRef.value?.stopListenerKeyDown() + uploadRef.value?.$el.querySelector('input[type="file"]')?.click() + // import_visible.value = true + // mainPanelRef.value?.stopListenerKeyDown() } +const handleExceed: UploadProps['onExceed'] = files => { + uploadRef.value!.clearFiles() + const file = files[0] as UploadRawFile + file.uid = genFileId() + uploadRef.value!.handleStart(file) +} +// 上传json文件 +const handleOnchange = (uploadFile: UploadFile) => { + let file: any = uploadFile.raw // 获取文件信息 + + const fileName = file.name + const isJsonSuffix = fileName.endsWith('.json') + + // 方式2:通过文件 MIME 类型校验(辅助验证,部分浏览器可能不准确) + const isJsonType = file.type === 'application/json' || file.type === '' + + if (!isJsonSuffix || !isJsonType) { + ElMessage.error('请上传后缀为 .json 的合法 JSON 文件!') + uploadRef.value.clearFiles() + return // 校验失败,终止后续操作 + } + + const fileReader = new FileReader() + fileReader.readAsText(file!) // 开始读取文件的内容为二进制 + + fileReader.onload = ev => { + // 读取完成,对数据进行自己的操作 + const data = ev.target?.result //获取内容 + console.log('🚀 ~ handleOnchange ~ data:', data) + onImportYes(data) + // console.log(JSON.parse(data as string)) + } +} + const onExportClick = () => { - export_visible.value = true - mainPanelRef.value?.stopListenerKeyDown() + // export_visible.value = true + // mainPanelRef.value?.stopListenerKeyDown() + // :done-json="objectDeepClone(globalStore.done_json)" + // :canvas-cfg="globalStore.canvasCfg" + // :grid-cfg="globalStore.gridCfg" + + const { exportJson } = genExportJson( + globalStore.canvasCfg, + globalStore.gridCfg, + objectDeepClone(globalStore.done_json) + ) + let data = JSON.stringify(exportJson, null, 2) + let blob = new Blob([data], { type: 'text/plain' }) + let url = URL.createObjectURL(blob) + let a = document.createElement('a') + a.href = url + a.download = useData.keyName + '.json' + a.click() + + ElMessage.success('JSON 导出成功') } const onTreeUpdateSelectedItemsId = (id: string) => { globalStore.setSingleSelect(id) @@ -207,15 +276,35 @@ const onRedoClick = () => { const onUndoClick = () => { mainPanelRef.value?.onUndo() } -const onImportYes = async () => { - const res = await importJsonRef.value?.onImport() +const onImportYes = async (row: any) => { + const res = await onImport(row) + // const res = await importJsonRef.value?.onImport() if (res) { import_visible.value = false + uploadRef.value.clearFiles() cacheStore.addHistory(globalStore.done_json) + ElMessage.success('JSON 导入成功') } else { + uploadRef.value.clearFiles() ElMessage.error('导入失败,请检查数据格式') } } + +const onImport = (res: any) => { + return new Promise((resolve, reject) => { + try { + const json: IExportJson = JSON.parse(res) + const { canvasCfg, gridCfg, importDoneJson } = useExportJsonToDoneJson(json) + globalStore.canvasCfg = canvasCfg + globalStore.gridCfg = gridCfg + globalStore.setGlobalStoreDoneJson(importDoneJson) + resolve(true) + } catch (error) { + resolve(false) + } + }) +} + const onPreviewClick = () => { // 获取导出json const { exportJson } = genExportJson(globalStore.canvasCfg, globalStore.gridCfg, globalStore.done_json) diff --git a/src/components/mt-preview-ypt/index.vue b/src/components/mt-preview-ypt/index.vue index af983ef..370188d 100644 --- a/src/components/mt-preview-ypt/index.vue +++ b/src/components/mt-preview-ypt/index.vue @@ -296,7 +296,7 @@ const onMouseWheel = (e: WheelEvent) => { // 如果缩放中心是鼠标位置,计算新的平移值以保持视觉中心 if (canvasAreaRef.value) { - const rect = canvasAreaRef.value.getBoundingClientRect() + const rect = canvasAreaRef.value?.getBoundingClientRect() const mouseX = e.clientX - rect.left const mouseY = e.clientY - rect.top diff --git a/src/components/mt-preview-zl/index.ts b/src/components/mt-preview-zl/index.ts new file mode 100644 index 0000000..d66ddb0 --- /dev/null +++ b/src/components/mt-preview-zl/index.ts @@ -0,0 +1,3 @@ +import MtPreview from './index.vue' + +export default MtPreview diff --git a/src/components/mt-preview-zl/index.vue b/src/components/mt-preview-zl/index.vue new file mode 100644 index 0000000..e70b97e --- /dev/null +++ b/src/components/mt-preview-zl/index.vue @@ -0,0 +1,1174 @@ + + + + + diff --git a/src/components/mt-preview/index.vue b/src/components/mt-preview/index.vue index 1930000..98ec1bc 100644 --- a/src/components/mt-preview/index.vue +++ b/src/components/mt-preview/index.vue @@ -588,6 +588,7 @@ const setImportJson = (exportJson: IExportJson) => { //报警设备闪烁 if (findTransmissionDeviceIdsByKeyList(list.value).includes(item.id)) { // item.props.fill.val = '#fcfc57' + item.props.fill.val = sendColor.value item.common_animations.val = 'flash' if (findTransmissionDeviceIdsByKeyList(listMax.value).includes(item.id)) { @@ -1027,16 +1028,26 @@ const setMqtt = async () => { await mqttClient.value.subscribe('/zl/rtData/#') // 设置消息接收回调 - mqttClient.value.onMessage((subscribe: string, message: any) => { + mqttClient.value.onMessage(async (subscribe: string, message: any) => { const msg: any = uint8ArrayToObject(message) console.log('🚀 ~ 接受消息:', msg) - setTimeout(() => { + list.value = [...new Set(msg.filter((item: any) => item.devStatus === 1).map((item: any) => item.lineId))] + sendColor.value = '#ff0000' + // await setImportJson(savedExportJson.value) + + await setTimeout(() => { done_json.value.forEach(item => { msg.forEach((msgValue: any) => { if (item.id == msgValue.id) { item.props.text.val = item.props.text.val.replace(/#{3}/g, msgValue.value) //'B相负载电流-CP95:31' } }) + list.value.forEach((listValue: any) => { + if (listValue == item.lineId && item.type == 'svg') { + item.props.fill.val = '#ff0000' + // item.common_animations.val = 'flash' + } + }) }) }, 100) }) diff --git a/src/export.ts b/src/export.ts index 3ed3e7b..f26345d 100644 --- a/src/export.ts +++ b/src/export.ts @@ -8,5 +8,6 @@ import MtDzr from '@/components/mt-dzr' import MtEdit from '@/components/mt-edit' import MtPreview from '@/components/mt-preview' import MtPreviewYpt from '@/components/mt-preview-ypt' +import MtPreviewZl from '@/components/mt-preview-zl' import { leftAsideStore } from '@/components/mt-edit/store/left-aside' -export { MtDzr, MtEdit, MtPreview, leftAsideStore, MtPreviewYpt } +export { MtDzr, MtEdit, MtPreview, leftAsideStore, MtPreviewYpt, MtPreviewZl } diff --git a/src/router/index.ts b/src/router/index.ts index 6a15174..eba6dcb 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -25,6 +25,12 @@ export const constantRoutes = [ path: '/preview_YPT', component: () => import('../views/preview/index_YPT.vue') }, + { + // 云平台预览页面 + name: 'preview_ZL', + path: '/preview_ZL', + component: () => import('../views/preview/index_ZL.vue') + }, { name: 'edit-load', path: '/edit-load', diff --git a/src/stores/menuList/index.ts b/src/stores/menuList/index.ts index e2645c4..e9666b6 100644 --- a/src/stores/menuList/index.ts +++ b/src/stores/menuList/index.ts @@ -11,6 +11,7 @@ export const useDataStore = defineStore('data-store', { identifying: '0', mqttID: '', preview: '', + keyName: '', //选中的name wxqr: '', loading: true, display: false, //无锡项目进去是true,其他项目是false 控制预览的时候返回按钮的展示 @@ -67,13 +68,18 @@ export const useDataStore = defineStore('data-store', { modify(kId: number, val: string) { this.dataTree.forEach((item: any) => { if (item.kId == kId) { - item.name = val } }) }, // 放置kid placeKid(id: String) { this.identifying = id + this.keyName = '' + this.dataTree.forEach((item: any) => { + if (item.kId == id) { + this.keyName = item.name + } + }) }, setUpPath(data: String) { this.dataTree.forEach((item: any) => { diff --git a/src/stores/menuList/types.ts b/src/stores/menuList/types.ts index d96f928..8b7fcac 100644 --- a/src/stores/menuList/types.ts +++ b/src/stores/menuList/types.ts @@ -9,6 +9,7 @@ export interface DataStoreState { preview?: String wxqr?: String loading?: boolean + keyName?: String display?: Boolean //是否展示返回按钮 graphicDisplay?: string //是否展示数据绑定图元 } diff --git a/src/utils/loadSvg.ts b/src/utils/loadSvg.ts index 77f068b..acd5c55 100644 --- a/src/utils/loadSvg.ts +++ b/src/utils/loadSvg.ts @@ -25,14 +25,15 @@ interface SvgConfig { } } // 处理单个SVG元素的函数 -const processSvgItem = async (item: ElementItem): Promise => { +const processSvgItem = async (item: ElementItem, type: string): Promise => { try { const svgContent = await download({ filePath: item.path }) // 替换填充色用于缩略图 - const filledSvg = svgContent.replace(/(\sfill=(["']))[^"']*(\2)/g, '$1#000000$3') + const filledSvg = + type == '特殊图元' ? svgContent : svgContent.replace(/(\sfill=(["']))[^"']*(\2)/g, '$1#000000$3') // 移除原始填充色 - const cleanSvg = svgContent.replace(/\sfill=(["'])[^"']*\1/g, '') + const cleanSvg = type == '特殊图元' ? svgContent : svgContent.replace(/\sfill=(["'])[^"']*\1/g, '') return { id: item.id, @@ -142,7 +143,7 @@ const loadSvg = async () => { // 处理每个类型的元素并注册 for (const [type, items] of Object.entries(groupedElements)) { - const svgConfigs = await Promise.all(items.map(item => processSvgItem(item))) + const svgConfigs = await Promise.all(items.map(item => processSvgItem(item, type))) leftAsideStore.registerConfig(type, svgConfigs) } } catch (error) { diff --git a/src/utils/mqtt.ts b/src/utils/mqtt.ts index 1d5948c..9cd89b6 100644 --- a/src/utils/mqtt.ts +++ b/src/utils/mqtt.ts @@ -55,7 +55,7 @@ class MQTT { // const mqttUrl = 'ws://192.168.1.103:8083/mqtt' const mqttUrl = localStorage.getItem('MQTTZUTAI') == 'null' - ? 'ws://192.168.1.24:8085/mqtt' + ? 'ws://192.168.1.103:8083/mqtt' : localStorage.getItem('MQTTZUTAI') console.log('🚀 ~ MQTT ~ init ~ mqttUrl:', mqttUrl) this.client = mqtt.connect(mqttUrl, this.defaultOptions as IClientOptions) diff --git a/src/utils/request.ts b/src/utils/request.ts index 4016a6b..3c871c2 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -19,11 +19,11 @@ class HttpRequest { instance.interceptors.request.use( config => { // 添加全局的loading.. - // config.headers['Authorization'] = - // 'bearer ' + JSON.parse(window.localStorage.getItem('adminInfo') || '{}').access_token // 请求头带上token token要在登录的时候保存在localStorage中 - config.headers['Authorization'] = - 'bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5kZXgiOiJmYTM3YjkzY2M5MGQ0YzE3ODRjYThmNmRlYmRkZWUxYSIsInVzZXJfbmFtZSI6InJvb3QiLCJzY29wZSI6WyJhbGwiXSwibmlja25hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJ1c2VyVHlwZSI6MCwiZGVwdEluZGV4IjoiNTY5OWU1OTE2YTE4YTYzODFlMWFjOTJkYTViZDI2MjgiLCJleHAiOjE4MjE4MTc2MTksImF1dGhvcml0aWVzIjpbInJvb3QiXSwianRpIjoiMmJiM2Q5ZTYtNmY3Yy00Yjg1LThiM2EtZDI2ODdmMTUzMDg5IiwiY2xpZW50X2lkIjoibmpjbnRlc3QiLCJoZWFkU2N1bHB0dXJlIjoicmVzb3VyY2VEYXRhLzMxNzRDRUFFOUQ0MjRGMjJCQjkxQTU4OURENjdCMDUxLmpwZyJ9.WjeYl1lvvJdDE1FUGIhS99rE5qKaBXOypWxmxK0svWweGqEbu1XCLjKm_YkiTwjZJ_oIcn5JOO9rvHFkkea76BUsYo5wlzuBBiy7sKqM1fFzOFQq6hdFevNTJAbYH9FiBxYxI-e9DZ5mvLGE6umOjUfn_FAsku2w6Uj5DtvpOKBWYzLEPTEifOqNI9he4zJAmVZniUUMf26SDoEdfu0TyrIS1j_qKaEb-cqR1XDhivdthEBK5m9vxJyXFZ5kofNxwQQkit_oiqJRkCZIt9TWAjCh-frzMHCvA30hkAr-VCD2JfCmmEr3hW_lmwfINaPtFVbHCdCKqdrl6VmF1HObaQ' + 'bearer ' + JSON.parse(window.localStorage.getItem('adminInfo') || '{}').access_token // 请求头带上token token要在登录的时候保存在localStorage中 + + // config.headers['Authorization'] = + // 'bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5kZXgiOiJmYTM3YjkzY2M5MGQ0YzE3ODRjYThmNmRlYmRkZWUxYSIsInVzZXJfbmFtZSI6InJvb3QiLCJzY29wZSI6WyJhbGwiXSwibmlja25hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJ1c2VyVHlwZSI6MCwiZGVwdEluZGV4IjoiNTY5OWU1OTE2YTE4YTYzODFlMWFjOTJkYTViZDI2MjgiLCJleHAiOjE4MjE4MTc2MTksImF1dGhvcml0aWVzIjpbInJvb3QiXSwianRpIjoiMmJiM2Q5ZTYtNmY3Yy00Yjg1LThiM2EtZDI2ODdmMTUzMDg5IiwiY2xpZW50X2lkIjoibmpjbnRlc3QiLCJoZWFkU2N1bHB0dXJlIjoicmVzb3VyY2VEYXRhLzMxNzRDRUFFOUQ0MjRGMjJCQjkxQTU4OURENjdCMDUxLmpwZyJ9.WjeYl1lvvJdDE1FUGIhS99rE5qKaBXOypWxmxK0svWweGqEbu1XCLjKm_YkiTwjZJ_oIcn5JOO9rvHFkkea76BUsYo5wlzuBBiy7sKqM1fFzOFQq6hdFevNTJAbYH9FiBxYxI-e9DZ5mvLGE6umOjUfn_FAsku2w6Uj5DtvpOKBWYzLEPTEifOqNI9he4zJAmVZniUUMf26SDoEdfu0TyrIS1j_qKaEb-cqR1XDhivdthEBK5m9vxJyXFZ5kofNxwQQkit_oiqJRkCZIt9TWAjCh-frzMHCvA30hkAr-VCD2JfCmmEr3hW_lmwfINaPtFVbHCdCKqdrl6VmF1HObaQ' // 请求头携带token return config }, diff --git a/src/views/preview/index_ZL.vue b/src/views/preview/index_ZL.vue new file mode 100644 index 0000000..97e71b0 --- /dev/null +++ b/src/views/preview/index_ZL.vue @@ -0,0 +1,19 @@ + +