Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b678083e87 | ||
|
|
80e4d579a5 | ||
|
|
2698ca4f5c | ||
|
|
da26b1d237 | ||
|
|
d586f19bd9 | ||
|
|
be63b12db7 | ||
|
|
346346c3f9 | ||
|
|
178054426d | ||
|
|
761ad3c2f8 | ||
|
|
6d08a7673e | ||
|
|
ac0774cc74 | ||
|
|
c013158f7c | ||
|
|
f706c49e93 |
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico" type="image/svg+xml" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>南京灿能web组态编辑器</title>
|
||||
<title>南京灿能组态</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import loadSvg from '@/utils/loadSvg'
|
||||
import { loadSvg } from '@/utils/loadSvg'
|
||||
loadSvg()
|
||||
</script>
|
||||
|
||||
|
||||
@@ -24,6 +24,23 @@ export function addElement(params: any) {
|
||||
data: params
|
||||
})
|
||||
}
|
||||
// 批量导入
|
||||
export function addByZip(params: any) {
|
||||
return http.request({
|
||||
url: '/cs-system-boot/csElement/addByZip',
|
||||
method: 'post',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
// 下载
|
||||
export function downloadByZip(params: any) {
|
||||
return http.request({
|
||||
url: '/cs-system-boot/csElement/downloadByZip',
|
||||
method: 'post',
|
||||
params,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
// 删除图元
|
||||
export function deleteElement(params: any) {
|
||||
@@ -78,6 +95,13 @@ export function targetList(params: any) {
|
||||
params: params
|
||||
})
|
||||
}
|
||||
// 云平台
|
||||
export function eleEpdChooseTree_ypt() {
|
||||
return http.request({
|
||||
url: '/cs-system-boot/csDictData/eleEpdChooseTree',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
// 无锡指标列表
|
||||
export function eleEpdChooseTree_wx() {
|
||||
return http.request({
|
||||
|
||||
155
src/components/mt-edit/components/add-element/download.vue
Normal file
155
src/components/mt-edit/components/add-element/download.vue
Normal file
@@ -0,0 +1,155 @@
|
||||
<template>
|
||||
<div class="add-element">
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
v-model="open"
|
||||
title="批量导出"
|
||||
width="500px"
|
||||
destroy-on-close
|
||||
@close="closeDialog"
|
||||
>
|
||||
<el-form :model="element" ref="ruleFormRef" :rules="rules" label-width="120px">
|
||||
<el-form-item label="下载分类:" prop="name">
|
||||
<el-select v-model="element.name" placeholder="请选择下载分类" style="width: 100%">
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="mt-10px flex justify-end">
|
||||
<el-button @click="closeDialog">取消</el-button>
|
||||
<el-button @click="addNewComponent(ruleFormRef)" type="primary">导出</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getCurrentInstance, onMounted, ref, watch, reactive } from 'vue'
|
||||
import { ElInput, ElFormItem, ElForm, ElDialog, ElUpload, ElMessage, ElButton, ElSelect, ElOption } from 'element-plus'
|
||||
import type { CheckboxValueType } from 'element-plus'
|
||||
import type { UploadInstance, UploadProps, FormInstance, FormRules, UploadFile, UploadUserFile } from 'element-plus'
|
||||
import { downloadByZip, download } from '@/api/index'
|
||||
import { leftAsideStore } from '@/export'
|
||||
import { getSvg } from '@/utils/loadSvg'
|
||||
const instance = getCurrentInstance() // 获取当前组件实例
|
||||
|
||||
const open = ref(false)
|
||||
|
||||
const props = defineProps({
|
||||
show: Boolean,
|
||||
checked_keys: Array
|
||||
})
|
||||
|
||||
const element: any = ref({
|
||||
elementCode: '', //组件编码
|
||||
elementForm: '', // 图元状态
|
||||
elementMark: '', //组件标识
|
||||
elementName: '', //图元名称
|
||||
name: '', //组件子类型 图元分类
|
||||
elementType: '', //组件分类
|
||||
multipartFile: '' // 图元文件
|
||||
})
|
||||
|
||||
interface RuleForm {
|
||||
elementCode: string
|
||||
elementForm: string
|
||||
elementMark: string
|
||||
elementName: string
|
||||
name: string
|
||||
elementType: string
|
||||
}
|
||||
|
||||
const options: any = ref([])
|
||||
const isAdding = ref(false)
|
||||
const value = ref<CheckboxValueType[]>([])
|
||||
const optionName = ref('')
|
||||
const fileList = ref<UploadFile[]>([]) // 上传文件列表
|
||||
const dialogImageUrl = ref('')
|
||||
const dialogVisible = ref(false) // 上传图片预览
|
||||
|
||||
const ruleFormRef = ref<FormInstance>()
|
||||
const rules = reactive<FormRules<RuleForm>>({
|
||||
name: [{ required: true, message: '请选择需要下载的分类', trigger: 'change' }]
|
||||
})
|
||||
onMounted(() => {})
|
||||
|
||||
const setOptions = () => {
|
||||
let list = JSON.parse(JSON.stringify(props.checked_keys))
|
||||
|
||||
const uniqueArray = [...new Set(list)]
|
||||
|
||||
// 步骤2:定义需要删除的元素列表
|
||||
const removeItems = ['基础图元', '数据绑定图元']
|
||||
|
||||
// 步骤3:过滤掉需要删除的元素
|
||||
const finalArray = uniqueArray.filter(item => !removeItems.includes(item))
|
||||
options.value = finalArray.map(item => ({
|
||||
value: item,
|
||||
label: item
|
||||
}))
|
||||
}
|
||||
|
||||
const closeDialog = () => {
|
||||
open.value = false
|
||||
if (instance) {
|
||||
const emit = instance.emit
|
||||
emit('update:show', false) // 向父组件发送更新后的状态
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.show,
|
||||
val => {
|
||||
if (val === true) {
|
||||
setOptions()
|
||||
open.value = true
|
||||
element.value = {}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// 新增保存
|
||||
|
||||
const addNewComponent = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate(valid => {
|
||||
if (valid) {
|
||||
downloadByZip({
|
||||
name: element.value.name
|
||||
}).then((res: any) => {
|
||||
console.log('🚀 ~ addNewComponent ~ res:', res)
|
||||
downloadBlobFile(res, element.value.name + '.zip')
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用Blob下载工具函数(核心复用)
|
||||
* @param {Blob} blob 二进制文件流对象
|
||||
* @param {String} fileName 下载后的文件名(必须带.zip后缀)
|
||||
*/
|
||||
function downloadBlobFile(blob: any, fileName: string) {
|
||||
// 1. 创建文件下载的临时URL
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
// 2. 创建a标签(隐藏的,用于触发下载)
|
||||
const aLink = document.createElement('a')
|
||||
aLink.style.display = 'none'
|
||||
aLink.href = url
|
||||
// 3. 设置下载文件名
|
||||
aLink.download = fileName
|
||||
// 4. 把a标签插入到页面,触发点击事件
|
||||
document.body.appendChild(aLink)
|
||||
aLink.click()
|
||||
// 5. ✅ 关键优化:释放临时URL,防止内存泄漏
|
||||
window.URL.revokeObjectURL(url)
|
||||
// 6. 移除a标签,清理DOM
|
||||
document.body.removeChild(aLink)
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.option-input {
|
||||
width: 100%;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
273
src/components/mt-edit/components/add-element/importZip.vue
Normal file
273
src/components/mt-edit/components/add-element/importZip.vue
Normal file
@@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<div class="add-element">
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
v-model="open"
|
||||
title="批量导入"
|
||||
width="500px"
|
||||
destroy-on-close
|
||||
@close="closeDialog"
|
||||
>
|
||||
<el-form :model="element" ref="ruleFormRef" :rules="rules" label-width="120px">
|
||||
<el-form-item label="图元分类:" prop="elementSonType">
|
||||
<el-select v-model="element.elementSonType" placeholder="请选择图元分类" style="width: 100%">
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
||||
<template #footer>
|
||||
<el-button v-if="!isAdding" text bg size="small" type="primary" @click="onAddOption">
|
||||
新增分类
|
||||
</el-button>
|
||||
<template v-else>
|
||||
<el-input
|
||||
v-model="optionName"
|
||||
class="option-input"
|
||||
clearable
|
||||
placeholder="请输入分类名称"
|
||||
size="small"
|
||||
/>
|
||||
<el-button type="primary" size="small" @click="onConfirm">保存</el-button>
|
||||
<el-button size="small" @click="clear">取消</el-button>
|
||||
</template>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="上传zip文件:">
|
||||
<el-upload
|
||||
ref="upload"
|
||||
v-model="fileList"
|
||||
style="width: 415px"
|
||||
action="#"
|
||||
multiple
|
||||
accept=".zip"
|
||||
:http-request="UploadSvg"
|
||||
:on-remove="handleRemove"
|
||||
:before-upload="beforeAvatarUpload"
|
||||
:limit="1"
|
||||
:on-exceed="handleExceed"
|
||||
>
|
||||
<el-button type="primary">上传</el-button>
|
||||
</el-upload>
|
||||
<el-dialog :close-on-click-modal="false" v-model="dialogVisible">
|
||||
<img w-full :src="dialogImageUrl" alt="Preview Image" />
|
||||
</el-dialog>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="mt-10px flex justify-end">
|
||||
<el-button @click="closeDialog">取消</el-button>
|
||||
<el-button @click="addNewComponent(ruleFormRef)" type="primary">保存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getCurrentInstance, onMounted, ref, watch, reactive } from 'vue'
|
||||
import { ElInput, ElFormItem, ElForm, ElDialog, ElUpload, ElMessage, ElButton, ElSelect, ElOption } from 'element-plus'
|
||||
import type { CheckboxValueType } from 'element-plus'
|
||||
import type { UploadInstance, UploadProps, FormInstance, FormRules, UploadFile, UploadUserFile } from 'element-plus'
|
||||
import { addByZip, download } from '@/api/index'
|
||||
import { leftAsideStore } from '@/export'
|
||||
import { getSvg } from '@/utils/loadSvg'
|
||||
const instance = getCurrentInstance() // 获取当前组件实例
|
||||
|
||||
const open = ref(false)
|
||||
|
||||
const props = defineProps({
|
||||
show: Boolean,
|
||||
checked_keys: Array
|
||||
})
|
||||
|
||||
const element: any = ref({
|
||||
elementCode: '', //组件编码
|
||||
elementForm: '', // 图元状态
|
||||
elementMark: '', //组件标识
|
||||
elementName: '', //图元名称
|
||||
elementSonType: '', //组件子类型 图元分类
|
||||
elementType: '', //组件分类
|
||||
multipartFile: '' // 图元文件
|
||||
})
|
||||
|
||||
interface RuleForm {
|
||||
elementCode: string
|
||||
elementForm: string
|
||||
elementMark: string
|
||||
elementName: string
|
||||
elementSonType: string
|
||||
elementType: string
|
||||
}
|
||||
|
||||
const options: any = ref([])
|
||||
const isAdding = ref(false)
|
||||
const value = ref<CheckboxValueType[]>([])
|
||||
const optionName = ref('')
|
||||
const fileList = ref<UploadFile[]>([]) // 上传文件列表
|
||||
const dialogImageUrl = ref('')
|
||||
const dialogVisible = ref(false) // 上传图片预览
|
||||
|
||||
const handleRemove = (file: UploadFile) => {
|
||||
fileList.value = []
|
||||
}
|
||||
// 文件校验
|
||||
const beforeAvatarUpload: UploadProps['beforeUpload'] = rawFile => {
|
||||
if (!rawFile.name.includes('.zip')) {
|
||||
ElMessage.error('只能上传zip格式文件!')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
const handleExceed: UploadProps['onExceed'] = files => {
|
||||
return ElMessage.error('只能上传1个zip文件!')
|
||||
}
|
||||
// 上传svg
|
||||
// const UploadSvg = (params:any) => {
|
||||
// fileList.value.push(params.file);
|
||||
// };
|
||||
|
||||
const UploadSvg = (params: any) => {
|
||||
return new Promise<void>(resolve => {
|
||||
fileList.value.push(params.file)
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
const ruleFormRef = ref<FormInstance>()
|
||||
const rules = reactive<FormRules<RuleForm>>({
|
||||
elementCode: [{ required: true, message: '请输入组件编码', trigger: 'blur' }],
|
||||
elementForm: [{ required: true, message: '请选择图元状态', trigger: 'change' }],
|
||||
elementMark: [{ required: true, message: '请输入组件标识', trigger: 'blur' }],
|
||||
elementName: [{ required: true, message: '请输入图元名称', trigger: 'blur' }],
|
||||
elementSonType: [{ required: true, message: '请选择父类型', trigger: 'change' }],
|
||||
elementType: [{ required: true, message: '请选择组件分类', trigger: 'change' }]
|
||||
})
|
||||
onMounted(() => {})
|
||||
|
||||
const setOptions = () => {
|
||||
let list = JSON.parse(JSON.stringify(props.checked_keys))
|
||||
|
||||
list.push('特殊图元')
|
||||
const uniqueArray = [...new Set(list)]
|
||||
|
||||
// 步骤2:定义需要删除的元素列表
|
||||
const removeItems = ['基础图元', '数据绑定图元']
|
||||
|
||||
// 步骤3:过滤掉需要删除的元素
|
||||
const finalArray = uniqueArray.filter(item => !removeItems.includes(item))
|
||||
options.value = finalArray.map(item => ({
|
||||
value: item,
|
||||
label: item
|
||||
}))
|
||||
}
|
||||
const onAddOption = () => {
|
||||
isAdding.value = true
|
||||
}
|
||||
|
||||
const onConfirm = () => {
|
||||
if (optionName.value) {
|
||||
options.value.push({
|
||||
label: optionName.value,
|
||||
value: optionName.value
|
||||
})
|
||||
clear()
|
||||
}
|
||||
}
|
||||
|
||||
const closeDialog = () => {
|
||||
open.value = false
|
||||
if (instance) {
|
||||
const emit = instance.emit
|
||||
emit('update:show', false) // 向父组件发送更新后的状态
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.show,
|
||||
val => {
|
||||
if (val === true) {
|
||||
setOptions()
|
||||
open.value = true
|
||||
element.value = {}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const clear = () => {
|
||||
optionName.value = ''
|
||||
isAdding.value = false
|
||||
}
|
||||
// 新增保存
|
||||
|
||||
const addNewComponent = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate(valid => {
|
||||
if (valid) {
|
||||
if (fileList.value.length == 0) {
|
||||
ElMessage({
|
||||
message: '请上传zip文件!',
|
||||
type: 'warning'
|
||||
})
|
||||
return Promise.resolve() // 显式返回 Promise<void>
|
||||
}
|
||||
let form = new FormData()
|
||||
|
||||
form.append('elementCode', element.value.elementName)
|
||||
form.append('elementForm', '普通图元')
|
||||
form.append('elementMark', element.value.elementName)
|
||||
form.append('elementName', element.value.elementName)
|
||||
form.append('elementSonType', element.value.elementSonType)
|
||||
form.append('elementType', 'zip文件')
|
||||
form.append('zipFile', fileList.value[0])
|
||||
|
||||
addByZip(form).then((res: any) => {
|
||||
if (res.code == 'A0000') {
|
||||
ElMessage({
|
||||
message: '新增成功',
|
||||
type: 'success'
|
||||
})
|
||||
closeDialog()
|
||||
if (!props.checked_keys?.includes(element.value.elementSonType)) {
|
||||
leftAsideStore.registerConfig(element.value.elementSonType, [])
|
||||
}
|
||||
ElMessage.info(`加载图元中,请稍等!`)
|
||||
getSvg()
|
||||
// setTimeout(() => {
|
||||
// // 左侧列表渲染新增的图元
|
||||
// download({ filePath: res.data.path }).then((Svg: any) => {
|
||||
// // 动态添加svg
|
||||
// leftAsideStore.svgPush(res.data.elementSonType, [
|
||||
// {
|
||||
// id: res.data.id,
|
||||
// title: res.data.elementName,
|
||||
// type: 'svg',
|
||||
// thumbnail:
|
||||
// 'data:image/svg+xml;utf8,' +
|
||||
// encodeURIComponent(Svg.replace(/(\sfill=(["']))[^"']*(\2)/g, '$1#000000$3')),
|
||||
// svg: Svg.replace(/\sfill=(["'])[^"']*\1/g, ''),
|
||||
// props: {
|
||||
// fill: {
|
||||
// type: 'color',
|
||||
// val: '#FF0000',
|
||||
// title: '填充色'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ])
|
||||
// })
|
||||
// }, 100)
|
||||
} else {
|
||||
ElMessage({
|
||||
message: res.message,
|
||||
type: 'info'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
return Promise.resolve() // 确保所有分支都返回 Promise<void>
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.option-input {
|
||||
width: 100%;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
@@ -12,6 +12,22 @@
|
||||
<el-form-item label="图元分类:" prop="elementSonType">
|
||||
<el-select v-model="element.elementSonType" placeholder="请选择图元分类" style="width: 100%">
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
||||
<template #footer>
|
||||
<el-button v-if="!isAdding" text bg size="small" type="primary" @click="onAddOption">
|
||||
新增分类
|
||||
</el-button>
|
||||
<template v-else>
|
||||
<el-input
|
||||
v-model="optionName"
|
||||
class="option-input"
|
||||
clearable
|
||||
placeholder="请输入分类名称"
|
||||
size="small"
|
||||
/>
|
||||
<el-button type="primary" size="small" @click="onConfirm">保存</el-button>
|
||||
<el-button size="small" @click="clear">取消</el-button>
|
||||
</template>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="组件子类型:" prop="elementSonType">
|
||||
@@ -111,28 +127,31 @@
|
||||
<img w-full :src="dialogImageUrl" alt="Preview Image" />
|
||||
</el-dialog>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="addNewComponent(ruleFormRef)" type="primary">保存</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="mt-10px flex justify-end">
|
||||
<el-button @click="closeDialog">取消</el-button>
|
||||
<el-button @click="addNewComponent(ruleFormRef)" type="primary">保存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineProps, getCurrentInstance, onMounted, ref, watch, reactive } from 'vue'
|
||||
import { getCurrentInstance, onMounted, ref, watch, reactive } from 'vue'
|
||||
import { ElInput, ElFormItem, ElForm, ElDialog, ElUpload, ElMessage, ElButton, ElSelect, ElOption } from 'element-plus'
|
||||
import type { CheckboxValueType } from 'element-plus'
|
||||
import type { UploadInstance, UploadProps, FormInstance, FormRules, UploadFile, UploadUserFile } from 'element-plus'
|
||||
|
||||
import { addElement, download } from '@/api/index'
|
||||
import { leftAsideStore } from '@/export'
|
||||
|
||||
import { getSvg } from '@/utils/loadSvg'
|
||||
const instance = getCurrentInstance() // 获取当前组件实例
|
||||
|
||||
const open = ref(false)
|
||||
|
||||
const props = defineProps({
|
||||
show: Boolean
|
||||
show: Boolean,
|
||||
checked_keys: Array
|
||||
})
|
||||
|
||||
const element: any = ref({
|
||||
@@ -154,21 +173,10 @@ interface RuleForm {
|
||||
elementType: string
|
||||
}
|
||||
|
||||
const options = [
|
||||
{
|
||||
value: '电力基础图元',
|
||||
label: '电力基础图元'
|
||||
},
|
||||
{
|
||||
value: '自定义',
|
||||
label: '自定义'
|
||||
},
|
||||
{
|
||||
value: '特殊图元',
|
||||
label: '特殊图元'
|
||||
}
|
||||
]
|
||||
|
||||
const options: any = ref([])
|
||||
const isAdding = ref(false)
|
||||
const value = ref<CheckboxValueType[]>([])
|
||||
const optionName = ref('')
|
||||
const fileList = ref<UploadFile[]>([]) // 上传文件列表
|
||||
const dialogImageUrl = ref('')
|
||||
const dialogVisible = ref(false) // 上传图片预览
|
||||
@@ -213,6 +221,36 @@ const rules = reactive<FormRules<RuleForm>>({
|
||||
elementSonType: [{ required: true, message: '请选择父类型', trigger: 'change' }],
|
||||
elementType: [{ required: true, message: '请选择组件分类', trigger: 'change' }]
|
||||
})
|
||||
onMounted(() => {})
|
||||
const setOptions = () => {
|
||||
let list = JSON.parse(JSON.stringify(props.checked_keys))
|
||||
|
||||
list.push('特殊图元')
|
||||
const uniqueArray = [...new Set(list)]
|
||||
|
||||
// 步骤2:定义需要删除的元素列表
|
||||
const removeItems = ['基础图元', '数据绑定图元']
|
||||
|
||||
// 步骤3:过滤掉需要删除的元素
|
||||
const finalArray = uniqueArray.filter(item => !removeItems.includes(item))
|
||||
options.value = finalArray.map(item => ({
|
||||
value: item,
|
||||
label: item
|
||||
}))
|
||||
}
|
||||
const onAddOption = () => {
|
||||
isAdding.value = true
|
||||
}
|
||||
|
||||
const onConfirm = () => {
|
||||
if (optionName.value) {
|
||||
options.value.push({
|
||||
label: optionName.value,
|
||||
value: optionName.value
|
||||
})
|
||||
clear()
|
||||
}
|
||||
}
|
||||
|
||||
const closeDialog = () => {
|
||||
open.value = false
|
||||
@@ -226,12 +264,17 @@ watch(
|
||||
() => props.show,
|
||||
val => {
|
||||
if (val === true) {
|
||||
setOptions()
|
||||
open.value = true
|
||||
element.value = {}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const clear = () => {
|
||||
optionName.value = ''
|
||||
isAdding.value = false
|
||||
}
|
||||
// 新增保存
|
||||
|
||||
const addNewComponent = async (formEl: FormInstance | undefined) => {
|
||||
@@ -262,28 +305,35 @@ const addNewComponent = async (formEl: FormInstance | undefined) => {
|
||||
type: 'success'
|
||||
})
|
||||
closeDialog()
|
||||
// 左侧列表渲染新增的图元
|
||||
download({ filePath: res.data.path }).then((Svg: any) => {
|
||||
// 动态添加svg
|
||||
leftAsideStore.svgPush(res.data.elementSonType, [
|
||||
{
|
||||
id: res.data.id,
|
||||
title: res.data.elementName,
|
||||
type: 'svg',
|
||||
thumbnail:
|
||||
'data:image/svg+xml;utf8,' +
|
||||
encodeURIComponent(Svg.replace(/(\sfill=(["']))[^"']*(\2)/g, '$1#000000$3')),
|
||||
svg: Svg.replace(/\sfill=(["'])[^"']*\1/g, ''),
|
||||
props: {
|
||||
fill: {
|
||||
type: 'color',
|
||||
val: '#FF0000',
|
||||
title: '填充色'
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
})
|
||||
if (!props.checked_keys?.includes(element.value.elementSonType)) {
|
||||
leftAsideStore.registerConfig(element.value.elementSonType, [])
|
||||
}
|
||||
ElMessage.info(`加载图元中,请稍等!`)
|
||||
getSvg()
|
||||
// setTimeout(() => {
|
||||
// // 左侧列表渲染新增的图元
|
||||
// download({ filePath: res.data.path }).then((Svg: any) => {
|
||||
// // 动态添加svg
|
||||
// leftAsideStore.svgPush(res.data.elementSonType, [
|
||||
// {
|
||||
// id: res.data.id,
|
||||
// title: res.data.elementName,
|
||||
// type: 'svg',
|
||||
// thumbnail:
|
||||
// 'data:image/svg+xml;utf8,' +
|
||||
// encodeURIComponent(Svg.replace(/(\sfill=(["']))[^"']*(\2)/g, '$1#000000$3')),
|
||||
// svg: Svg.replace(/\sfill=(["'])[^"']*\1/g, ''),
|
||||
// props: {
|
||||
// fill: {
|
||||
// type: 'color',
|
||||
// val: '#FF0000',
|
||||
// title: '填充色'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ])
|
||||
// })
|
||||
// }, 100)
|
||||
} else {
|
||||
ElMessage({
|
||||
message: res.message,
|
||||
@@ -296,3 +346,9 @@ const addNewComponent = async (formEl: FormInstance | undefined) => {
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.option-input {
|
||||
width: 100%;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -55,12 +55,12 @@
|
||||
</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<el-button-group>
|
||||
<el-button text circle size="small" @click="onImportClick" :disabled="useData.keyName ==''">
|
||||
<el-button text circle size="small" @click="onImportClick" :disabled="useData.keyName == ''">
|
||||
<el-icon title="导入数据模型" :size="20">
|
||||
<svg-analysis name="import-json"></svg-analysis>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<el-button text circle size="small" @click="onExportClick" :disabled="useData.keyName ==''">
|
||||
<el-button text circle size="small" @click="onExportClick" :disabled="useData.keyName == ''">
|
||||
<el-icon title="导出数据模型" :size="20">
|
||||
<svg-analysis name="export-json"></svg-analysis>
|
||||
</el-icon>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-icon @click.stop="del(scope.$index,scope.row)" style="margin-left: 5px; cursor: pointer">
|
||||
<el-icon @click.stop="del(scope.$index, scope.row)" style="margin-left: 5px; cursor: pointer">
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
@@ -205,7 +205,7 @@ const onAddClick = () => {
|
||||
}
|
||||
|
||||
// 删除功能,传索引行数
|
||||
function del(index: number,row: any) {
|
||||
function del(index: number, row: any) {
|
||||
ElMessageBox.confirm('确定删除?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@@ -214,7 +214,7 @@ function del(index: number,row: any) {
|
||||
.then(() => {
|
||||
// splice方法,传两个参数:第几行开始,删除多少条(如果未规定此参数,则删除从 index 开始到原数组结尾的所有元素)
|
||||
dataTrees.value.splice(index, 1)
|
||||
useData.placeKid(row.kId)
|
||||
useData.placeKid(row.kId)
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功'
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div class="h-[calc(10%-1px)] flex justify-center items-center ct-border" style="padding-top: 10px">
|
||||
<el-button class="w-80/100" @click="onManageClick">管理</el-button>
|
||||
<el-button class="w-80/100" :icon="Tools" @click="onManageClick">管理</el-button>
|
||||
</div>
|
||||
<el-dialog
|
||||
:close-on-click-modal="false"
|
||||
@@ -100,8 +100,6 @@
|
||||
>
|
||||
<el-button type="primary">本地上传</el-button>
|
||||
</el-upload> -->
|
||||
<el-button type="primary" @click="checkClick()">新增图元</el-button>
|
||||
<add-element :show="openCheck" @update:show="updateOpenCheck"></add-element>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -129,7 +127,8 @@
|
||||
v-if="
|
||||
selected_node_key !== '数据绑定图元' &&
|
||||
selected_node_key !== '基础图元' &&
|
||||
show_del_local_file == item.id
|
||||
show_del_local_file == item.id &&
|
||||
hasAdmin
|
||||
"
|
||||
class="absolute w-160px h-160px left-0 top-0 opacity-80 bg-light-300 flex justify-center items-center"
|
||||
>
|
||||
@@ -141,7 +140,18 @@
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
<div style="mt10">
|
||||
<el-button type="primary" :icon="Plus" @click="checkClick()">新增图元</el-button>
|
||||
<el-button type="primary" :icon="Upload" @click="zipCheck()">批量导入</el-button>
|
||||
<el-button type="primary" :icon="Download" @click="downloadCheck()">批量导出</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 新增图元 -->
|
||||
<add-element :show="openCheck" :checked_keys="checked_keys" @update:show="updateOpenCheck"></add-element>
|
||||
<!-- 批量导入图元 -->
|
||||
<importZip :show="zipOpen" :checked_keys="checked_keys" @update:show="updateZip"></importZip>
|
||||
<!-- 下载图元 -->
|
||||
<download :show="downloadOpen" :checked_keys="checked_keys" @update:show="updateDown"></download>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
@@ -165,6 +175,7 @@ import {
|
||||
ElMessage,
|
||||
type UploadFile
|
||||
} from 'element-plus'
|
||||
import { Plus, Tools, Upload, Download } from '@element-plus/icons-vue'
|
||||
import SvgAnalysis from '@/components/mt-edit/components/svg-analysis/index.vue'
|
||||
import { useDark, useLocalStorage } from '@vueuse/core'
|
||||
import type {
|
||||
@@ -175,6 +186,8 @@ import type {
|
||||
import { globalStore } from '@/components/mt-edit/store/global'
|
||||
import { blobToBase64 } from '@/components/mt-edit/utils'
|
||||
import AddElement from '@/components/mt-edit/components/add-element/index.vue'
|
||||
import importZip from '@/components/mt-edit/components/add-element/importZip.vue'
|
||||
import download from '@/components/mt-edit/components/add-element/download.vue'
|
||||
import { deleteElement } from '@/api/index'
|
||||
import { leftAsideStore } from '@/export'
|
||||
import { useDataStore } from '@/stores/menuList'
|
||||
@@ -188,6 +201,11 @@ const leftAsideProps = withDefaults(defineProps<LeftAsideProps>(), {
|
||||
const isDark = useDark({
|
||||
selector: '#mt-edit'
|
||||
})
|
||||
const adminInfo: any = window.localStorage.getItem('adminInfo')
|
||||
const hasAdmin =
|
||||
JSON.parse(adminInfo)?.roleCode.some(item => item.includes('operation_manager') || item.includes('root')) ||
|
||||
JSON.parse(adminInfo)?.userType == 1
|
||||
|
||||
const uploadRef = ref()
|
||||
// 从本地储存中查被禁用的类别
|
||||
const disable_classify = useLocalStorage<string[]>('mt-disable-classify', [])
|
||||
@@ -282,6 +300,10 @@ const onDragStart = (config_item_key: string, item_id: string) => {
|
||||
}
|
||||
const onManageClick = () => {
|
||||
manage_dialog_visiable.value = true
|
||||
setTimeout(() => {
|
||||
treeRef.value?.setCurrentKey(classify_list.value[0])
|
||||
onNodeClick(classify_list.value[0])
|
||||
}, 100)
|
||||
}
|
||||
const handleCheckChange = (data: { label: string }, checked: boolean, indeterminate: boolean) => {
|
||||
if (checked && !checked_keys.value.includes(data.label)) {
|
||||
@@ -369,14 +391,28 @@ function onDelLocalFile(item: ILeftAsideConfigItem) {
|
||||
|
||||
// 新增图元
|
||||
const openCheck = ref(false)
|
||||
const zipOpen = ref(false)
|
||||
const downloadOpen = ref(false)
|
||||
//打开弹窗按钮
|
||||
function checkClick() {
|
||||
openCheck.value = true
|
||||
}
|
||||
function zipCheck() {
|
||||
zipOpen.value = true
|
||||
}
|
||||
function downloadCheck() {
|
||||
downloadOpen.value = true
|
||||
}
|
||||
//接收到子页面关闭弹窗的事件,改变openCheck的值,否则在刷新页面之前openCheck会一直是true,导致无法第二次打开弹窗
|
||||
const updateOpenCheck = (value: boolean) => {
|
||||
openCheck.value = value
|
||||
}
|
||||
const updateZip = (value: boolean) => {
|
||||
zipOpen.value = value
|
||||
}
|
||||
const updateDown = (value: boolean) => {
|
||||
downloadOpen.value = value
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
#mt-left-aside .el-collapse-item__header,
|
||||
|
||||
@@ -1420,11 +1420,10 @@ watch(
|
||||
|
||||
time.value = setTimeout(() => {
|
||||
console.log('🚀 ~ globalStore:', globalStore)
|
||||
if(useData.keyName==''){
|
||||
if (useData.keyName == '') {
|
||||
ElMessage.warning('请选择图纸!')
|
||||
}
|
||||
|
||||
|
||||
const { exportJson } = genExportJson(globalStore.canvasCfg, globalStore.gridCfg, globalStore.done_json)
|
||||
// const data_model: any = {
|
||||
// canvasCfg: globalStore.canvasCfg,
|
||||
|
||||
@@ -105,7 +105,7 @@ import { ElForm, ElFormItem, ElTreeSelect } from 'element-plus'
|
||||
import { computed, ref, watch, onMounted, reactive, nextTick, watchEffect } from 'vue'
|
||||
import type { IDoneJson } from '@/components/mt-edit/store/types'
|
||||
import { globalStore } from '@/components/mt-edit/store/global'
|
||||
import { lineTree, targetList, eleEpdChooseTree_wx } from '@/api/index'
|
||||
import { lineTree, targetList, eleEpdChooseTree_wx, eleEpdChooseTree_ypt } from '@/api/index'
|
||||
import { useDataStore } from '@/stores/menuList'
|
||||
import { lineTree_wx } from '@/api/index_wx'
|
||||
import { templateRef } from '@vueuse/core'
|
||||
@@ -190,11 +190,11 @@ watch(
|
||||
if (item_title.value == '绑定指标' && deptIds.value) {
|
||||
indexList()
|
||||
}
|
||||
if (useData.graphicDisplay == 'ypt') {
|
||||
if (deptIds.value) {
|
||||
indexList()
|
||||
}
|
||||
}
|
||||
// if (useData.graphicDisplay == 'ypt') {
|
||||
// if (deptIds.value) {
|
||||
// indexList()
|
||||
// }
|
||||
// }
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -267,6 +267,15 @@ const fetchData = async () => {
|
||||
try {
|
||||
const response = await lineTree({})
|
||||
treeData.value = buildLevel3Tree(response.data) // 转换数据格式并赋值给 transformedData
|
||||
if (useData.treeIndexs.length > 0) {
|
||||
treeIndexs.value = useData.treeIndexs
|
||||
return
|
||||
}
|
||||
if (useData.graphicDisplay == 'ypt') {
|
||||
const res = await eleEpdChooseTree_ypt()
|
||||
useData.settreeIndexs(res.data)
|
||||
treeIndexs.value = res.data // 转换数据格式并赋值给 transformedData
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching data:', error)
|
||||
}
|
||||
@@ -297,10 +306,10 @@ const indexList = async () => {
|
||||
}
|
||||
|
||||
{
|
||||
const response = await targetList({ lineId: lineId })
|
||||
if (response.data) {
|
||||
treeIndexs.value = response.data // 转换数据格式并赋值给 transformedData
|
||||
}
|
||||
// const response = await targetList({ lineId: lineId })
|
||||
// if (response.data) {
|
||||
// treeIndexs.value = response.data // 转换数据格式并赋值给 transformedData
|
||||
// }
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching data:', error)
|
||||
@@ -340,11 +349,11 @@ const handleDeptChange = (deptId: []) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (useData.graphicDisplay == 'ypt') {
|
||||
if (deptId) {
|
||||
indexList()
|
||||
}
|
||||
}
|
||||
// if (useData.graphicDisplay == 'ypt') {
|
||||
// if (deptId) {
|
||||
// indexList()
|
||||
// }
|
||||
// }
|
||||
})
|
||||
}
|
||||
// 给每一个元件绑定下拉框数据
|
||||
@@ -371,6 +380,11 @@ const handleSelectUID = (uid: []) => {
|
||||
} else {
|
||||
selectItemSettingProps.itemJson.UIDNames = [name.join(' / ')]
|
||||
}
|
||||
// 单个指标绑定
|
||||
if (item_title.value == '绑定指标') {
|
||||
console.log(123)
|
||||
selectItemSettingProps.itemJson.UIDType = true
|
||||
}
|
||||
}
|
||||
|
||||
// 获取选中的数据名称
|
||||
@@ -382,10 +396,13 @@ const handleSelectUID = (uid: []) => {
|
||||
.getCheckedNodes()
|
||||
.map((item: any) => item.data.unit)
|
||||
.filter((text: string) => text !== '' && text !== null && text !== undefined)
|
||||
console.log(123)
|
||||
|
||||
if (is2DArray(uid)) {
|
||||
if (selectItemSettingProps.itemJson) {
|
||||
selectItemSettingProps.itemJson.UIDNames = nameList
|
||||
selectItemSettingProps.itemJson.unit = unitList
|
||||
|
||||
indexString.value = selectItemSettingProps.itemJson.UIDNames
|
||||
}
|
||||
} else {
|
||||
@@ -393,14 +410,28 @@ const handleSelectUID = (uid: []) => {
|
||||
// 配置里面的输入框内容更新
|
||||
if (selectItemSettingProps.itemJson && selectItemSettingProps.itemJson.props) {
|
||||
if (selectItemSettingProps.itemJson?.props.text.type == 'input') {
|
||||
selectItemSettingProps.itemJson.unit = unitList
|
||||
// selectItemSettingProps.itemJson.props.text.val = name.join(' / ')
|
||||
let names = name.reverse()
|
||||
let str = ''
|
||||
let key =
|
||||
names[0] == 'max'
|
||||
? '最大值'
|
||||
: names[0] == 'min'
|
||||
? '最小值'
|
||||
: names[0] == 'avg'
|
||||
? '平均值'
|
||||
: names[0] == 'cp95'
|
||||
? 'CP95值'
|
||||
: names[0]
|
||||
if (names[1] == '无相别') {
|
||||
name[1] = ''
|
||||
str = names[2] + '-' + names[0] + ':###'
|
||||
str = names[2] + '-' + key + ':###'
|
||||
} else {
|
||||
str = names[1] + '相' + names[2] + '-' + names[0] + ':###'
|
||||
str =
|
||||
names.length == 2
|
||||
? names[1] + '-' + key + ':###'
|
||||
: names[1] + '相' + names[2] + '-' + key + ':###'
|
||||
}
|
||||
selectItemSettingProps.itemJson.props.text.val = str
|
||||
}
|
||||
|
||||
@@ -68,12 +68,18 @@
|
||||
@set-intention="val => renderCoreEmits('setIntention', val)"
|
||||
@line-mouse-up="onLineMouseUp"
|
||||
v-on="renderCoreProps.preivewMode ? eventToVOn(item, externalMethod) : {}"
|
||||
@click="() => renderCoreProps.onElementClick && item.lineId && renderCoreProps.onElementClick(item.lineId)"
|
||||
@click="
|
||||
() =>
|
||||
renderCoreProps.onElementClick &&
|
||||
item.lineId &&
|
||||
item.title != '绑定指标' &&
|
||||
renderCoreProps.onElementClick(item.lineId, item.lineName)
|
||||
"
|
||||
></render-item>
|
||||
</mt-dzr>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { nextTick, reactive, ref } from 'vue'
|
||||
import { nextTick, reactive, ref, onMounted } from 'vue'
|
||||
import MtDzr from '@/components/mt-dzr/index.vue'
|
||||
import RenderItem from '@/components/mt-edit/components/render-item/index.vue'
|
||||
import type {
|
||||
@@ -97,6 +103,8 @@ import SysButtonVue from '@/components/custom-components/sys-button-vue/index.vu
|
||||
import BindDotVue from '@/components/custom-components/bind-dot-vue/index.vue'
|
||||
import BindIndexVue from '@/components/custom-components/bind-index-vue/index.vue'
|
||||
import { ElPopover } from 'element-plus'
|
||||
import { leftAsideStore } from '@/export'
|
||||
|
||||
const instance = getCurrentInstance()
|
||||
const now_include_keys = Object.keys(instance?.appContext?.components as any)
|
||||
if (!now_include_keys.includes('text-vue')) {
|
||||
@@ -130,7 +138,7 @@ type RenderCoreProps = {
|
||||
preivewMode?: boolean
|
||||
lineAppendEnable?: boolean
|
||||
showPopover?: boolean
|
||||
onElementClick?: (elementId: string) => void
|
||||
onElementClick?: (elementId: string, lineName?: string) => void
|
||||
}
|
||||
const renderCoreProps = withDefaults(defineProps<RenderCoreProps>(), {
|
||||
doneJson: () => [],
|
||||
@@ -228,6 +236,7 @@ const onItemMove = (e: any, id: string) => {
|
||||
})
|
||||
])
|
||||
}
|
||||
|
||||
renderCoreEmits('onItemMove', item_move_params)
|
||||
})
|
||||
}
|
||||
@@ -293,4 +302,9 @@ const onLineMouseUp = () => {
|
||||
cacheStore.addHistory(globalStore.done_json)
|
||||
}, 1000)
|
||||
}
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
// console.log(123, leftAsideStore.list)
|
||||
}, 5000)
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
<template>
|
||||
<div class="w-1/1 h-1/1">
|
||||
<svg-render
|
||||
v-if="item_json.type === 'svg'"
|
||||
v-if="
|
||||
item_json.type === 'svg' &&
|
||||
leftAsideStore.list.some(k => k.symbol?.symbol_id === item_json.symbol?.symbol_id)
|
||||
"
|
||||
draggable="false"
|
||||
:symbol-id="item_json.symbol!.symbol_id"
|
||||
:symbol-str="item_json.symbol!.symbol_str"
|
||||
@@ -53,6 +56,8 @@ import GroupRender from '@/components/mt-edit/components/group-render/index.vue'
|
||||
import { prosToVBind } from '@/components/mt-edit/utils'
|
||||
import LineRender from '@/components/mt-edit/components/line-render/index.vue'
|
||||
import CustomSvgRender from '@/components/mt-edit/components/custom-svg-render/index.vue'
|
||||
import { leftAsideStore } from '@/export'
|
||||
|
||||
import { computed } from 'vue'
|
||||
type RenderItemProps = {
|
||||
itemJson: IDoneJson
|
||||
|
||||
@@ -129,7 +129,7 @@ export const useExportJsonToDoneJson = (json: IExportJson) => {
|
||||
init_configs = [...init_configs, ...iterator]
|
||||
}
|
||||
}
|
||||
const importDoneJson: IDoneJson[] = json.json.map(m => {
|
||||
const importDoneJson: IDoneJson[] = json?.json?.map(m => {
|
||||
let props: ILeftAsideConfigItemPublicProps = {}
|
||||
let symbol = undefined
|
||||
// 找到原始的props
|
||||
|
||||
@@ -320,9 +320,13 @@ const onSaveClick = () => {
|
||||
const useData = useDataStore()
|
||||
const onSaveAll = async () => {
|
||||
let data: any = await useData.dataTree.map((item, ind) => {
|
||||
let pathList = JSON.parse(item.path)
|
||||
pathList.canvasCfg.lineList = pathList.json.filter(k => k.lineId != '' && k.lineId != null).map(k => k.lineId)
|
||||
item.path = JSON.stringify(pathList)
|
||||
item.sort = ind
|
||||
return item
|
||||
})
|
||||
console.log('🚀 ~ onSaveAll ~ data:', data)
|
||||
|
||||
let form = new FormData()
|
||||
let blob = new Blob([JSON.stringify(data)], {
|
||||
|
||||
@@ -11,6 +11,7 @@ export const leftAsideStore: ILeftAside = reactive({
|
||||
['基础图元', configStore.sysComponent],
|
||||
['数据绑定图元', bingStore.sysComponent]
|
||||
]),
|
||||
list: [],
|
||||
registerConfig: (title: string, config: ILeftAsideConfigItemPublic[]) => {
|
||||
if (title == '本地文件' || title == '基础图元') {
|
||||
ElMessage.info(`title:${title}已被系统占用,请更换名称!`)
|
||||
@@ -18,7 +19,7 @@ export const leftAsideStore: ILeftAside = reactive({
|
||||
}
|
||||
|
||||
if (leftAsideStore.config.has(title)) {
|
||||
ElMessage.info(`title:${title}已存在,已经将其配置覆盖`)
|
||||
// ElMessage.info(`title:${title}已存在,已经将其配置覆盖`)
|
||||
}
|
||||
const cfg: ILeftAsideConfigItem[] = config.map(m => {
|
||||
if (m.type == 'svg') {
|
||||
@@ -49,6 +50,7 @@ export const leftAsideStore: ILeftAside = reactive({
|
||||
}
|
||||
}
|
||||
})
|
||||
leftAsideStore.list.push(...cfg)
|
||||
leftAsideStore.config.set(title, cfg)
|
||||
},
|
||||
svgPush: (title: string, config: ILeftAsideConfigItemPublic[]) => {
|
||||
|
||||
@@ -229,6 +229,7 @@ export interface IGlobalStore {
|
||||
// 左侧配置
|
||||
export interface ILeftAside {
|
||||
config: ILeftAsideConfig
|
||||
list: any
|
||||
registerConfig: (title: string, config: ILeftAsideConfigItemPublic[]) => void
|
||||
svgPush: (title: string, config: ILeftAsideConfigItemPublic[]) => void
|
||||
svgDelete: (title: string, id: string) => void
|
||||
|
||||
@@ -817,6 +817,7 @@ export const eventToVOn = (item: IDoneJson, externalMethod: (kid?: string) => vo
|
||||
code_str += event.jump_to
|
||||
}
|
||||
}
|
||||
|
||||
if (!Object.prototype.hasOwnProperty.call(event_obj, event.type)) {
|
||||
event_obj[event.type] = code_str
|
||||
} else {
|
||||
|
||||
262
src/components/mt-preview-ypt/iframeDia.vue
Normal file
262
src/components/mt-preview-ypt/iframeDia.vue
Normal file
@@ -0,0 +1,262 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<!-- 使用 v-for 遍历四个角落 -->
|
||||
<div v-for="corner in corners" v-show="corner.show" :key="corner.id" :class="['corner', corner.className]">
|
||||
<div class="content">
|
||||
<div class="title">{{ corner.title }}</div>
|
||||
<el-descriptions :column="1" size="small" label-width="70px" border>
|
||||
<el-descriptions-item label="指标数据">
|
||||
<div style="height: 200px; overflow-y: auto">
|
||||
<div
|
||||
v-for="item in props.steadyState?.filter(k => k.lineId === corner.elementId)"
|
||||
:key="item.id"
|
||||
>
|
||||
{{ item.statisticalName.replace(/\//g, '_') }}:
|
||||
{{ item.value === 3.1415926 ? '/' : item.value + item.unit }}
|
||||
</div>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
<span class="close-btn" @click="closeCorner(corner.id)">
|
||||
<Close />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import { Close } from '@element-plus/icons-vue'
|
||||
|
||||
// 定义 emits
|
||||
const emit = defineEmits(['lineListChange'])
|
||||
|
||||
// 定义接收的 props
|
||||
const props = defineProps<{
|
||||
steadyState?: any[]
|
||||
}>()
|
||||
|
||||
// 定义四个角落的数据
|
||||
const corners = ref([
|
||||
{
|
||||
id: 'topLeft',
|
||||
title: '左上',
|
||||
className: 'top-left',
|
||||
show: false,
|
||||
data: [] as { label: string; value: string }[],
|
||||
elementId: '' // 记录该角落对应的元素ID
|
||||
},
|
||||
{
|
||||
id: 'topRight',
|
||||
title: '右上',
|
||||
className: 'top-right',
|
||||
show: false,
|
||||
data: [] as { label: string; value: string }[],
|
||||
elementId: ''
|
||||
}
|
||||
])
|
||||
|
||||
const displayOrder = ref<number[]>([])
|
||||
|
||||
// 截取名称的最后一部分作为标题
|
||||
const extractTitleFromLineName = (lineName: string): string => {
|
||||
if (!lineName) return '未知监测点'
|
||||
|
||||
// 按照 "/" 分割字符串,取最后一部分
|
||||
const parts = lineName.split('/')
|
||||
return parts.length > 0 ? parts[parts.length - 1].trim() : lineName
|
||||
}
|
||||
|
||||
// 更新指定角落数据的函数
|
||||
const updateCornerData = (cornerIndex: number, elementId: string, lineName: string) => {
|
||||
// 更新标题为传入的 lineName 的最后一部分
|
||||
corners.value[cornerIndex].title = extractTitleFromLineName(lineName)
|
||||
|
||||
// 格式化数据(只保留稳态指标一项)
|
||||
corners.value[cornerIndex].data = [
|
||||
{
|
||||
label: '稳态指标',
|
||||
value: '正在加载...'
|
||||
}
|
||||
]
|
||||
|
||||
// 记录该角落对应的元素ID
|
||||
corners.value[cornerIndex].elementId = elementId
|
||||
corners.value[cornerIndex].show = true
|
||||
}
|
||||
|
||||
// 显示下一个角落的函数
|
||||
const showNextCorner = (elementId: string, lineName: string) => {
|
||||
// 检查该元素ID是否已经显示过
|
||||
const existingCornerIndex = corners.value.findIndex(corner => corner.elementId === elementId && corner.show)
|
||||
|
||||
if (existingCornerIndex !== -1) {
|
||||
// 如果该元素已经显示过,更新标题
|
||||
corners.value[existingCornerIndex].title = extractTitleFromLineName(lineName)
|
||||
return
|
||||
}
|
||||
|
||||
// 查找一个未显示的角落
|
||||
const availableCornerIndex = corners.value.findIndex(corner => !corner.show)
|
||||
|
||||
if (availableCornerIndex !== -1) {
|
||||
// 有空闲角落,显示在该角落
|
||||
updateCornerData(availableCornerIndex, elementId, lineName)
|
||||
|
||||
// 记录显示顺序
|
||||
displayOrder.value.push(availableCornerIndex)
|
||||
} else {
|
||||
// 没有空闲角落,按顺序替换角落
|
||||
// 获取需要替换的角落索引(循环替换)
|
||||
const replaceIndex = displayOrder.value.shift() || 0
|
||||
updateCornerData(replaceIndex, elementId, lineName)
|
||||
// 将替换的索引重新加入队列末尾
|
||||
displayOrder.value.push(replaceIndex)
|
||||
}
|
||||
|
||||
// updateLineList()
|
||||
}
|
||||
const timer = ref<any>(null)
|
||||
// 更新 lineList,根据 corners 的 show 状态来维护
|
||||
const updateLineList = () => {
|
||||
const newLineList = corners.value.filter(corner => corner.show && corner.elementId).map(corner => corner.elementId)
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value)
|
||||
timer.value = null
|
||||
}
|
||||
if (newLineList.length > 0) {
|
||||
emit('lineListChange', newLineList)
|
||||
timer.value = setInterval(
|
||||
() => {
|
||||
emit('lineListChange', newLineList)
|
||||
},
|
||||
3 * 60 * 1000
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭指定角落的函数
|
||||
const closeCorner = (id: string) => {
|
||||
const cornerIndex = corners.value.findIndex(c => c.id === id)
|
||||
if (cornerIndex !== -1) {
|
||||
corners.value[cornerIndex].show = false
|
||||
corners.value[cornerIndex].elementId = '' // 清空元素ID记录
|
||||
|
||||
// 从显示顺序中移除该角落索引
|
||||
const orderIndex = displayOrder.value.indexOf(cornerIndex)
|
||||
if (orderIndex !== -1) {
|
||||
displayOrder.value.splice(orderIndex, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭所有角落的函数
|
||||
const closeAllCorners = () => {
|
||||
corners.value.forEach(corner => {
|
||||
corner.show = false
|
||||
corner.elementId = ''
|
||||
})
|
||||
displayOrder.value = []
|
||||
|
||||
updateLineList()
|
||||
}
|
||||
|
||||
// 监听 corners 的变化,特别是 show 状态的变化
|
||||
watch(
|
||||
() => corners.value.map(corner => ({ id: corner.id, show: corner.show, elementId: corner.elementId })),
|
||||
(newCorners, oldCorners) => {
|
||||
// 检查是否有 show 状态的变化
|
||||
const showStateChanged = newCorners.some((corner, index) => corner.show !== oldCorners[index]?.show)
|
||||
|
||||
if (showStateChanged) {
|
||||
updateLineList()
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
// 暴露方法给父组件使用
|
||||
defineExpose({
|
||||
showNextCorner,
|
||||
closeCorner,
|
||||
closeAllCorners
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.corner {
|
||||
width: 260px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.top-left {
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.top-right {
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.bottom-left {
|
||||
top: 170px;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.bottom-right {
|
||||
top: 170px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.data-item {
|
||||
display: flex;
|
||||
margin-bottom: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: 55px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.value {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 关闭按钮样式 */
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
width: 14px;
|
||||
color: #000;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
@@ -6,10 +6,12 @@
|
||||
@mouseup="onMouseUp"
|
||||
@mouseleave="onMouseUp"
|
||||
@wheel="onMouseWheel"
|
||||
style="height: 100vh; overflow: hidden"
|
||||
>
|
||||
<div
|
||||
v-loading="useData.loading"
|
||||
:style="canvasStyle"
|
||||
style="overflow: hidden"
|
||||
:class="`canvasArea ${isDragging ? 'cursor-grabbing' : mtPreviewProps.canDrag ? 'cursor-grab' : ''} `"
|
||||
>
|
||||
<!-- <el-button type="primary" class="backBtn" @click="onBack" v-if="!useData.display">返回</el-button> -->
|
||||
@@ -42,9 +44,10 @@
|
||||
@drag-canvas-mouse-move="dragCanvasMouseMove"
|
||||
@drag-canvas-mouse-up="dragCanvasMouseUp"
|
||||
></drag-canvas>
|
||||
<!-- </el-scrollbar> -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- 弹框 -->
|
||||
<iframeDia :steadyState="dataList" ref="iframeDiaRef" @lineListChange="indicator"></iframeDia>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -59,43 +62,12 @@ import DragCanvas from '@/components/mt-edit/components/drag-canvas/index.vue'
|
||||
import { useDataStore } from '@/stores/menuList'
|
||||
import { globalStore } from '../mt-edit/store/global'
|
||||
import type { IDoneJsonEventList } from '../mt-edit/store/types'
|
||||
|
||||
import IframeDia from './iframeDia.vue'
|
||||
import MQTT from '@/utils/mqtt'
|
||||
import { log } from 'console'
|
||||
const iframeDiaRef = ref<any>(null)
|
||||
|
||||
const tableData = [
|
||||
{
|
||||
date: '2023-05-03 13:33:44:853',
|
||||
name: '1#主变分支I',
|
||||
address: '发生暂降,特征幅值:39.87%,持续时间:10.019s'
|
||||
},
|
||||
{
|
||||
date: '2023-05-02 13:31:50:155',
|
||||
name: '1#主变分支I',
|
||||
address: '发生暂降,特征幅值:39.95%,持续时间:5.02s'
|
||||
}
|
||||
// {
|
||||
// date: '2016-05-04',
|
||||
// name: '110kV杨镇变',
|
||||
// address: 'No. 189, Grove St, Los Angeles'
|
||||
// },
|
||||
// {
|
||||
// date: '2016-05-01',
|
||||
// name: '110kV加工区变',
|
||||
// address: 'No. 189, Grove St, Los Angeles'
|
||||
// },
|
||||
// {
|
||||
// date: '2016-05-01',
|
||||
// name: '110kV加工区变',
|
||||
// address: 'No. 189, Grove St, Los Angeles'
|
||||
// }
|
||||
]
|
||||
const dataList = ref([])
|
||||
|
||||
const showDetail = ref(false)
|
||||
|
||||
const showDetailClick = () => {
|
||||
showDetail.value = !showDetail.value
|
||||
}
|
||||
// 节流函数实现 (替代lodash,减少依赖)
|
||||
const throttle = (func: (...args: any[]) => void, wait: number) => {
|
||||
let lastTime = 0
|
||||
@@ -189,11 +161,6 @@ const canvasStyle = computed(() => ({
|
||||
marginLeft: (document.documentElement.clientWidth - canvas_cfg.value.width * canvas_cfg.value.scale) / 2 + 'px'
|
||||
}))
|
||||
|
||||
const onScroll = ({ scrollLeft, scrollTop }: { scrollLeft: number; scrollTop: number }) => {
|
||||
scroll_info.left = scrollLeft
|
||||
scroll_info.top = scrollTop
|
||||
}
|
||||
|
||||
// 鼠标按下事件 - 开始拖拽
|
||||
const onMouseDown = (e: MouseEvent) => {
|
||||
if (mtPreviewProps.canDrag && e.button === 0) {
|
||||
@@ -362,66 +329,37 @@ onMounted(async () => {
|
||||
if (mtPreviewProps.exportJson) {
|
||||
await setImportJson(mtPreviewProps.exportJson)
|
||||
}
|
||||
await sendTableData()
|
||||
if (useData.graphicDisplay == 'zl') {
|
||||
// // 治理项目连接mqtt
|
||||
await setMqtt()
|
||||
}
|
||||
// window.parent.postMessage({ action: useData, data: tableData }, '*') // 发送数据给父页面
|
||||
|
||||
// 连接mqtt
|
||||
await setMqtt()
|
||||
// await sendTableData()
|
||||
})
|
||||
|
||||
// 无锡大屏通过iframe传过来的数据
|
||||
// let keyList = [
|
||||
// '5f99b9ba4e563439ec8490a0c598da8d',
|
||||
// '401a696fe9918bb4cce7d9393d0d5df7',
|
||||
// '74203b186428c1684aa450ad05257b06'
|
||||
// ]
|
||||
// 无锡大屏通过iframe传过来的数据 lineId
|
||||
// mqtt推过来的 lineId
|
||||
let keyList = ref<any>([])
|
||||
|
||||
// 闪烁点 lineId
|
||||
let list = ref<any>([])
|
||||
|
||||
// 最大点闪烁点lineId
|
||||
let listMax = ref<any>([])
|
||||
|
||||
// 初始颜色
|
||||
let sendColor = ref<any>('')
|
||||
// 最大监测点颜色
|
||||
let sendMaxColor = ref<any>('')
|
||||
|
||||
// 背景色
|
||||
let backgroundPointId = ref<any>([])
|
||||
let backgroundPointColor = ref<any>('')
|
||||
|
||||
// let list = [
|
||||
// 'c53cccb8c65201c192d8c57fbdb4d993-RdNsoqHYOZ',
|
||||
// 'c53cccb8c65201c192d8c57fbdb4d993-O4jAyCBz1A',
|
||||
// // 'c53cccb8c65201c192d8c57fbdb4d993-XBd70oZ3kH',
|
||||
// 'c53cccb8c65201c192d8c57fbdb4d993-LH9I0qD86s'
|
||||
// ]
|
||||
// 实时数据表格
|
||||
const tableData = ref()
|
||||
|
||||
const sendTableData = () => {
|
||||
try {
|
||||
// 确保只传输可序列化的数据
|
||||
const cleanData = tableData.map(item => ({
|
||||
name: item.name,
|
||||
date: item.date,
|
||||
address: item.address
|
||||
}))
|
||||
|
||||
// 只发送 useData 中需要的可序列化数据
|
||||
const serializableUseData = {
|
||||
display: useData.display,
|
||||
loading: useData.loading
|
||||
// 添加其他需要的简单属性
|
||||
// 类型检查,确保 tableData.value 是数组
|
||||
if (!Array.isArray(tableData.value)) {
|
||||
console.warn('tableData is not an array, current value:', tableData.value)
|
||||
return
|
||||
}
|
||||
|
||||
// 确保只传输可序列化的数据
|
||||
const cleanData = tableData.value.map(item => ({
|
||||
name: item.name,
|
||||
date: item.timeId,
|
||||
address: item.eventDesc
|
||||
}))
|
||||
|
||||
window.parent.postMessage(
|
||||
{
|
||||
action: 'securityDetailData',
|
||||
data: cleanData
|
||||
// data1: serializableUseData
|
||||
},
|
||||
'*'
|
||||
)
|
||||
@@ -430,21 +368,10 @@ const sendTableData = () => {
|
||||
}
|
||||
}
|
||||
|
||||
let message = [
|
||||
{ id: 'c53cccb8c65201c192d8c57fbdb4d993-RdNsoqHYOZ', text: '发生时刻:2023-07-05 12:00:00' },
|
||||
{ id: 'c53cccb8c65201c192d8c57fbdb4d993-O4jAyCBz1A', text: '传输中1111......' }
|
||||
// { id: 'c53cccb8c65201c192d8c57fbdb4d993-XBd70oZ3kH', text: '发生时刻:2023-07-06 14:20:00' }
|
||||
]
|
||||
|
||||
// 传输设备相关的连接线ID列表
|
||||
let list_sys = ref<any>([])
|
||||
|
||||
let transmissionDeviceIds: string[] = []
|
||||
|
||||
let eventListAll = ref<any>([])
|
||||
|
||||
let flagValue = ref('')
|
||||
|
||||
const receiveMessage = () => {
|
||||
// 在 iframe 内的页面中
|
||||
window.addEventListener('message', function (event) {
|
||||
@@ -453,62 +380,52 @@ const receiveMessage = () => {
|
||||
|
||||
const { type, payload } = event.data
|
||||
|
||||
if (type === 'ANALYSIS_KEYS') {
|
||||
if (type === 'RESET_EVENT') {
|
||||
// 处理复位事件
|
||||
handleResetEvent()
|
||||
} else if (type === 'ANALYSIS_KEYS') {
|
||||
// 处理 ANALYSIS_KEYS 消息
|
||||
// 在处理新数据前,先清理现有的动态文字
|
||||
if (savedExportJson.value) {
|
||||
savedExportJson.value.json =
|
||||
savedExportJson.value.json?.filter(item => !item.id?.startsWith('auto-text-')) || []
|
||||
done_json.value = done_json.value.filter(item => !item.id?.startsWith('auto-text-'))
|
||||
}
|
||||
// console.log('payload1111', payload)
|
||||
// 处理接收到的 keyList 数据
|
||||
keyList.value = payload.eventList
|
||||
list.value = payload.eventList
|
||||
sendColor.value = payload.color
|
||||
// 点击行的全部数据
|
||||
if (payload.eventListAll) {
|
||||
eventListAll.value = payload.eventListAll
|
||||
// 在数据接收后重新更新文本
|
||||
setTimeout(() => {
|
||||
if (savedExportJson.value) {
|
||||
addTextNextToTransport()
|
||||
|
||||
setImportJson(savedExportJson.value)
|
||||
}
|
||||
}, 100)
|
||||
} else {
|
||||
eventListAll.value = []
|
||||
}
|
||||
if (payload.maxColor) {
|
||||
sendMaxColor.value = payload.maxColor
|
||||
} else {
|
||||
sendMaxColor.value = ''
|
||||
}
|
||||
if (payload.maxResponsibilityMonitorId) {
|
||||
listMax.value = payload.maxResponsibilityMonitorId
|
||||
} else {
|
||||
listMax.value = []
|
||||
}
|
||||
if (payload.backgroundPointId) {
|
||||
backgroundPointId.value = payload.backgroundPointId
|
||||
} else {
|
||||
backgroundPointId.value = []
|
||||
}
|
||||
if (payload.backgroundPointColor) {
|
||||
backgroundPointColor.value = payload.backgroundPointColor
|
||||
} else {
|
||||
backgroundPointColor.value = ''
|
||||
}
|
||||
if (payload.flagValue) {
|
||||
flagValue.value = payload.flagValue
|
||||
} else {
|
||||
flagValue.value = ''
|
||||
}
|
||||
init()
|
||||
}
|
||||
// 对于其他类型的消息,我们仍然调用 init()
|
||||
else if (type) {
|
||||
init()
|
||||
}
|
||||
init()
|
||||
})
|
||||
}
|
||||
|
||||
// 复位事件处理函数
|
||||
const handleResetEvent = () => {
|
||||
// 清空或重置 表格数据
|
||||
// if (tableData.value && Array.isArray(tableData.value)) {
|
||||
// tableData.value = []
|
||||
// } else {
|
||||
// // 确保 tableData 是一个空数组
|
||||
// tableData.value = []
|
||||
// }
|
||||
|
||||
// 接线图数据
|
||||
keyList.value = []
|
||||
|
||||
setTimeout(() => {
|
||||
// 表格数据
|
||||
sendTableData()
|
||||
// 接线图数据
|
||||
if (savedExportJson.value) {
|
||||
setImportJson(savedExportJson.value)
|
||||
}
|
||||
}, 100)
|
||||
|
||||
console.log('执行复位操作完成')
|
||||
}
|
||||
|
||||
//根据 lineId 查找传输设备 ID 的函数
|
||||
const findTransmissionDeviceIdsByKeyList = (array: any) => {
|
||||
if (!savedExportJson.value?.json) return []
|
||||
@@ -575,73 +492,22 @@ const setImportJson = (exportJson: IExportJson) => {
|
||||
}
|
||||
grid_cfg.value = gridCfg
|
||||
done_json.value = importDoneJson
|
||||
|
||||
console.log(11111111111)
|
||||
// 为图元添加点击事件
|
||||
addClickEventsToElements()
|
||||
|
||||
// 首页初始化的时候
|
||||
setTimeout(() => {
|
||||
console.log(22222222222222)
|
||||
|
||||
done_json.value.forEach(item => {
|
||||
//报警设备闪烁
|
||||
if (findTransmissionDeviceIdsByKeyList(list.value).includes(item.id)) {
|
||||
// item.props.fill.val = '#fcfc57'
|
||||
item.props.fill.val = sendColor.value
|
||||
if (findTransmissionDeviceIdsByKeyList(keyList.value).includes(item.id)) {
|
||||
item.props.fill.val = 'red'
|
||||
item.common_animations.val = 'flash'
|
||||
if (findTransmissionDeviceIdsByKeyList(listMax.value).includes(item.id)) {
|
||||
item.props.fill.val = sendMaxColor.value
|
||||
item.common_animations.val = 'flash'
|
||||
}
|
||||
|
||||
// 查找与该设备连接的线
|
||||
const connectedLines = searchDevicesConnect([item.id!])
|
||||
// console.log('该设备连接的线:', connectedLines)
|
||||
|
||||
// 通过连接的线找到开关,再找到开关连接的所有线
|
||||
const allRelatedLines: string[] = [...connectedLines]
|
||||
|
||||
for (const lineId of connectedLines) {
|
||||
// 通过线找到连接的开关
|
||||
const switchId = findSwitchByLineEndpoint(lineId)
|
||||
if (switchId) {
|
||||
// console.log('找到连接的开关:', switchId)
|
||||
|
||||
// 找到开关连接的所有线
|
||||
const switchLines = findLinesBySwitchId(switchId)
|
||||
// console.log('开关连接的线:', switchLines)
|
||||
|
||||
// 合并所有相关的线
|
||||
switchLines.forEach(line => {
|
||||
if (!allRelatedLines.includes(line)) {
|
||||
allRelatedLines.push(line)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//console.log('所有相关的线:', allRelatedLines)
|
||||
|
||||
// 高亮显示所有相关的线
|
||||
//只有当 flagValue 不等于 '2' 时才高亮显示所有相关的线
|
||||
if (flagValue.value !== '2') {
|
||||
highlightLines(allRelatedLines)
|
||||
}
|
||||
} else {
|
||||
item.common_animations.val = ''
|
||||
}
|
||||
|
||||
if (findTransmissionDeviceIdsByKeyList(backgroundPointId.value).includes(item.id)) {
|
||||
item.props.fill.val = backgroundPointColor.value
|
||||
item.common_animations.val = 'flash'
|
||||
}
|
||||
|
||||
// 报警设备连线电流
|
||||
// if (list_sys.value.includes(item.id)) {
|
||||
// item.props.ani_type.val = 'electricity'
|
||||
// item.props.ani_color.val = '#d0e20a'
|
||||
// }
|
||||
// if(item.id=='sys-line-vertical-v9oPMlvQL1'){
|
||||
// item.props.ani_color.val = '#8c0ae2'
|
||||
// }
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
@@ -649,9 +515,10 @@ const setImportJson = (exportJson: IExportJson) => {
|
||||
if (!useData.loading) {
|
||||
if (exportJson == null) {
|
||||
setDoneJson(useData.dataTree[0].kId)
|
||||
publish(useData.dataTree[0].id)
|
||||
} else {
|
||||
executeOperations()
|
||||
publish(useData.dataTree[0])
|
||||
singlePublish(useData.dataTree[0])
|
||||
}
|
||||
} else {
|
||||
// 如果不是true,添加监听
|
||||
@@ -662,9 +529,10 @@ const setImportJson = (exportJson: IExportJson) => {
|
||||
// 当loading变为true时执行操作
|
||||
if (exportJson == null) {
|
||||
setDoneJson(useData.dataTree[0].kId)
|
||||
publish(useData.dataTree[0].id)
|
||||
} else {
|
||||
executeOperations()
|
||||
singlePublish(useData.dataTree[0])
|
||||
publish(useData.dataTree[0])
|
||||
}
|
||||
// 执行后停止监听
|
||||
stopWatch()
|
||||
@@ -676,80 +544,6 @@ const setImportJson = (exportJson: IExportJson) => {
|
||||
return true
|
||||
}
|
||||
|
||||
// 根据线的起点或终点查找连接的开关
|
||||
const findSwitchByLineEndpoint = (lineId: string): string | null => {
|
||||
if (!savedExportJson.value?.json) return null
|
||||
|
||||
const line = savedExportJson.value.json.find(item => item.id === lineId)
|
||||
if (!line || !line.props?.bind_anchors) return null
|
||||
|
||||
const bindAnchors = line.props.bind_anchors as { start?: { id: string }; end?: { id: string } } | undefined
|
||||
if (!bindAnchors) return null
|
||||
|
||||
// 查找起点连接的开关
|
||||
const startId = bindAnchors.start?.id
|
||||
if (startId) {
|
||||
const startElement = savedExportJson.value.json.find(item => item.id === startId)
|
||||
if (startElement && startElement.title?.includes('开关')) {
|
||||
return startElement.id!
|
||||
}
|
||||
}
|
||||
|
||||
// 如果起点不是开关,查找终点连接的开关
|
||||
const endId = bindAnchors.end?.id
|
||||
if (endId) {
|
||||
const endElement = savedExportJson.value.json.find(item => item.id === endId)
|
||||
if (endElement && endElement.title?.includes('开关')) {
|
||||
return endElement.id!
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
// 根据开关ID查找所有连接的线
|
||||
const findLinesBySwitchId = (switchId: string): string[] => {
|
||||
if (!savedExportJson.value?.json) return []
|
||||
|
||||
const lineElements = savedExportJson.value.json.filter(item => item.type === 'sys-line' && item.props?.bind_anchors)
|
||||
|
||||
const connectedLines: string[] = []
|
||||
|
||||
for (const line of lineElements) {
|
||||
const bindAnchors = line.props.bind_anchors as { start?: { id: string }; end?: { id: string } } | undefined
|
||||
if (!bindAnchors) continue
|
||||
|
||||
const startId = bindAnchors.start?.id
|
||||
const endId = bindAnchors.end?.id
|
||||
|
||||
if (startId === switchId || endId === switchId) {
|
||||
connectedLines.push(line.id!)
|
||||
}
|
||||
}
|
||||
|
||||
// console.log('连接的线:', connectedLines)
|
||||
|
||||
return connectedLines
|
||||
}
|
||||
|
||||
// 高亮显示连线的函数
|
||||
const highlightLines = (lineIds: string[]) => {
|
||||
lineIds.forEach(id => {
|
||||
const line = done_json.value.find(item => item.id === id)
|
||||
if (line) {
|
||||
line.props.ani_type.val = 'electricity'
|
||||
line.props.ani_color.val = '#d0e20a'
|
||||
|
||||
// 置顶显示 - 将连线元素移到数组末尾(因为渲染顺序是按数组顺序)
|
||||
const index = done_json.value.findIndex(item => item.id === id)
|
||||
if (index !== -1) {
|
||||
const [item] = done_json.value.splice(index, 1)
|
||||
done_json.value.push(item)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 添加一个新的 ref 来存储当前点击的设备ID
|
||||
const currentClickedElementId = ref<string | null>(null)
|
||||
|
||||
@@ -759,22 +553,24 @@ let storedSelectedId = ''
|
||||
storedSelectedId = localStorage.getItem('selectedId') || ''
|
||||
|
||||
// 当前点击的元素lineId 通过mt-edit/render-core/index.vue传过来的click事件
|
||||
const handleElementClick = (elementId: string) => {
|
||||
const handleElementClick = (elementId: string, lineName: string) => {
|
||||
iframeDiaRef.value.showNextCorner(elementId, lineName)
|
||||
// 保存当前点击的设备ID
|
||||
currentClickedElementId.value = elementId
|
||||
const item = done_json.value.find(item => item.lineId === elementId)
|
||||
if (item && item.events && item.events.some(event => event.type === 'click')) {
|
||||
// 发送设备ID到父级iframe
|
||||
window.parent.postMessage(
|
||||
{
|
||||
action: 'coreClick',
|
||||
coreId: elementId.toString(), // 确保是字符串
|
||||
selectedId: storedSelectedId // 新增的字段
|
||||
// elementData: item // 可以发送整个元素数据
|
||||
},
|
||||
'*'
|
||||
)
|
||||
}
|
||||
// indicator(['00B78D0171091', '00B78D0171092'])
|
||||
// currentClickedElementId.value = elementId
|
||||
// const item = done_json.value.find(item => item.lineId === elementId)
|
||||
// if (item && item.events && item.events.some(event => event.type === 'click')) {
|
||||
// // 发送设备ID到父级iframe
|
||||
// window.parent.postMessage(
|
||||
// {
|
||||
// action: 'coreClick',
|
||||
// coreId: elementId.toString(), // 确保是字符串
|
||||
// selectedId: storedSelectedId // 新增的字段
|
||||
// // elementData: item // 可以发送整个元素数据
|
||||
// },
|
||||
// '*'
|
||||
// )
|
||||
// }
|
||||
}
|
||||
const searchDevicesConnect = (transmissionDeviceIds: string[]) => {
|
||||
// 确保 savedExportJson.value 存在
|
||||
@@ -844,95 +640,6 @@ const searchDevicesConnect = (transmissionDeviceIds: string[]) => {
|
||||
return connectedLineIds
|
||||
}
|
||||
|
||||
// 添加针对传输设备旁边添加文字的方法
|
||||
const addTextNextToTransport = () => {
|
||||
// 确保 savedExportJson.value 存在后再进行操作
|
||||
if (!savedExportJson.value) {
|
||||
console.warn('savedExportJson.value is undefined')
|
||||
return []
|
||||
}
|
||||
let transportDevices = []
|
||||
// 查找传输设备图元并添加文字图元
|
||||
transportDevices =
|
||||
savedExportJson.value.json?.filter(item =>
|
||||
findTransmissionDeviceIdsByKeyList(keyList.value).includes(item.id)
|
||||
) || []
|
||||
|
||||
// 为每个传输设备添加旁边的文字图元
|
||||
const textElementsToAdd: IExportDoneJson[] = []
|
||||
const idsToRemove: string[] = []
|
||||
|
||||
transportDevices.forEach((device, index) => {
|
||||
// 构造预期的旧文本图元 ID 模式 (基于设备 ID)
|
||||
const expectedIdPrefix = `auto-text-${device.id}-`
|
||||
|
||||
// 查找所有与当前设备关联的现有文本图元
|
||||
const existingTextElements =
|
||||
savedExportJson.value?.json?.filter(item => item.id?.startsWith(expectedIdPrefix)) || []
|
||||
|
||||
// 将这些旧图元的 ID 添加到待删除列表
|
||||
idsToRemove.push(...existingTextElements.map(item => item.id!))
|
||||
|
||||
// 获取对应的消息文本
|
||||
const deviceMessage =
|
||||
eventListAll.value[0].find((m: any) => m.monitorId === device.lineId)?.responsibilityData || 0
|
||||
|
||||
// 创建新的文本图元
|
||||
const textElement: IExportDoneJson = {
|
||||
id: `auto-text-${device.id}-${index}`, // 使用时间戳确保唯一性
|
||||
title: '动态文字',
|
||||
type: 'vue',
|
||||
tag: 'text-vue',
|
||||
props: {
|
||||
// text: deviceMessage.toFixed(1) + '%',
|
||||
text: '占比:' + Math.floor(deviceMessage * 10) / 10 + '%',
|
||||
fontFamily: '黑体',
|
||||
fontSize: 14,
|
||||
fill: 'red',
|
||||
vertical: false
|
||||
},
|
||||
common_animations: {
|
||||
val: '',
|
||||
delay: 'delay-0s',
|
||||
speed: 'slow',
|
||||
repeat: 'infinite'
|
||||
},
|
||||
binfo: {
|
||||
left: (device.binfo?.left || 0) + (device.binfo?.width / 2 || 0) + 10,
|
||||
//top: (device.binfo?.top || 0) + (device.binfo?.height || 0) / 2 - 10 + (index % 2 === 0 ? 20 : -20),
|
||||
top: (device.binfo?.top || 0) + (device.binfo?.height || 0) - 10,
|
||||
width: 200,
|
||||
height: 50,
|
||||
angle: 0
|
||||
},
|
||||
resize: true,
|
||||
rotate: true,
|
||||
lock: false,
|
||||
active: false,
|
||||
hide: false,
|
||||
UIDName: '',
|
||||
UIDNames: [],
|
||||
events: []
|
||||
}
|
||||
textElementsToAdd.push(textElement)
|
||||
})
|
||||
|
||||
// 从 savedExportJson.value.json 中移除旧的文本图元
|
||||
if (savedExportJson.value.json) {
|
||||
done_json.value = savedExportJson.value.json.filter(item => !idsToRemove.includes(item.id!))
|
||||
}
|
||||
|
||||
// 合并原始图元和新增的文字图元
|
||||
const updatedJson = [...done_json.value, ...textElementsToAdd]
|
||||
|
||||
// 更新 savedExportJson.value
|
||||
if (savedExportJson.value) {
|
||||
savedExportJson.value.json = updatedJson
|
||||
}
|
||||
|
||||
return updatedJson
|
||||
}
|
||||
|
||||
// 预览时候绑定指标等的点击事件
|
||||
const setDoneJson = async (kId: string) => {
|
||||
const filteredItems = useData.dataTree.filter(item => item.kId == kId)
|
||||
@@ -970,36 +677,16 @@ const init = async () => {
|
||||
// 调用函数获取传输设备 ID
|
||||
transmissionDeviceIds = findTransmissionDeviceIdsByKeyList(keyList.value)
|
||||
|
||||
//传入参数: transmissionDeviceIds - 一个包含传输设备ID的数组
|
||||
// 功能: 查找与这些传输设备相关的连接线(包括直接连接和间接连接的线)
|
||||
list_sys.value = searchDevicesConnect(transmissionDeviceIds)
|
||||
|
||||
// 将结果赋值给 savedExportJson.value
|
||||
// if (savedExportJson.value) {
|
||||
// // 创建一个新的对象,避免直接修改原始对象
|
||||
// savedExportJson.value = {
|
||||
// ...savedExportJson.value,
|
||||
// json: updatedDoneJson
|
||||
// }
|
||||
// } else {
|
||||
// // 如果 savedExportJson.value 不存在,创建一个新的对象
|
||||
// savedExportJson.value = {
|
||||
// canvasCfg: canvas_cfg.value,
|
||||
// gridCfg: grid_cfg.value,
|
||||
// json: updatedDoneJson
|
||||
// }
|
||||
// }
|
||||
|
||||
// 重新设置导入的JSON以触发界面更新
|
||||
setImportJson(savedExportJson.value)
|
||||
}, 100)
|
||||
}
|
||||
const timer = ref()
|
||||
|
||||
const list: any = ref([])
|
||||
// 连接mqtt
|
||||
const mqttClient = ref()
|
||||
const setMqtt = async () => {
|
||||
mqttClient.value = new MQTT('/zl/rtData/#')
|
||||
mqttClient.value = new MQTT('/zl/TemperData/#')
|
||||
|
||||
// 设置消息接收回调
|
||||
try {
|
||||
@@ -1007,43 +694,114 @@ const setMqtt = async () => {
|
||||
|
||||
// 订阅主题
|
||||
await mqttClient.value.subscribe('/zl/rtData/#')
|
||||
|
||||
await mqttClient.value.subscribe('/zl/TemperData/#') //实时数据
|
||||
await mqttClient.value.subscribe('/zl/csConfigRtData/#') //指标
|
||||
// 设置消息接收回调
|
||||
mqttClient.value.onMessage((subscribe: string, message: any) => {
|
||||
const msg: any = uint8ArrayToObject(message)
|
||||
console.log('🚀 ~ 接受消息:', msg)
|
||||
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'
|
||||
}
|
||||
})
|
||||
})
|
||||
}, 100)
|
||||
console.log('🚀 ~ setMqtt ~ msg:', msg)
|
||||
|
||||
if (subscribe.split('/')[2] === 'rtData') {
|
||||
// 指标数据
|
||||
|
||||
// await setImportJson(savedExportJson.value)
|
||||
|
||||
setTimeout(() => {
|
||||
if (done_json.value) {
|
||||
done_json.value?.forEach(item => {
|
||||
msg.forEach((msgValue: any) => {
|
||||
if (item.id == msgValue.id) {
|
||||
const unit = item?.unit && Array.isArray(item.unit) ? item.unit[0] : ''
|
||||
item.props.text.val = item.props.text.val.replace(
|
||||
/#{3}/g,
|
||||
msgValue.value == 3.1415926 ? '暂无数据' : msgValue.value + unit
|
||||
) //'B相负载电流-CP95:31'
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
if (subscribe.split('/')[2] === 'csConfigRtData') {
|
||||
// 指标数据
|
||||
dataList.value = JSON.parse(msg.message)
|
||||
//console.log('🚀 ~ setMqtt ~ dataList:', dataList.value)
|
||||
// keyList.value = JSON.parse(list.path).canvasCfg.lineList
|
||||
} else if (subscribe.split('/')[2] === 'TemperData') {
|
||||
// 表格数据
|
||||
tableData.value = []
|
||||
tableData.value = JSON.parse(msg.message)
|
||||
//console.log('🚀 ~ setMqtt ~ tableData:', tableData.value)
|
||||
// 闪烁点
|
||||
// if (Array.isArray(tableData.value) && tableData.value.length > 0) {
|
||||
// // 提取所有的 id 并去重(使用 Set 方式,性能更好)
|
||||
// const uniqueIds = [
|
||||
// ...new Set(
|
||||
// tableData.value
|
||||
// .filter(item => item.id) // 确保 id 存在
|
||||
// .map(item => item.id) // 提取 id
|
||||
// )
|
||||
// ]
|
||||
|
||||
// keyList.value = uniqueIds
|
||||
// console.log('提取的唯一ID列表:', keyList.value)
|
||||
// }
|
||||
sendTableData()
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('MQTT 初始化失败:', error)
|
||||
}
|
||||
}
|
||||
const publish = async (id: string) => {
|
||||
if (useData.graphicDisplay != 'zl') return //质量项目进入
|
||||
const singlePublish = async (id: string) => {
|
||||
if (mqttClient.value) {
|
||||
await mqttClient.value.subscribe('zl/askRtData/' + id)
|
||||
await mqttClient.value.subscribe('zl/askRtData/' + storedSelectedId)
|
||||
// 发送消息
|
||||
await mqttClient.value.publish('/zl/askRtData/' + id, '{}')
|
||||
await mqttClient.value.publish('/zl/askRtData/' + storedSelectedId, '{}')
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value)
|
||||
timer.value = null
|
||||
}
|
||||
timer.value = setInterval(
|
||||
() => {
|
||||
mqttClient.value.publish('/zl/askRtData/' + id, '{}')
|
||||
mqttClient.value.publish('/zl/askRtData/' + storedSelectedId, '{}')
|
||||
},
|
||||
3 * 60 * 1000
|
||||
)
|
||||
}
|
||||
}
|
||||
const publish = async (list: any) => {
|
||||
console.log('🚀 ~ publish ~ list:', JSON.parse(list.path).canvasCfg.lineList)
|
||||
if (mqttClient.value) {
|
||||
// 发送消息
|
||||
await mqttClient.value.publish(
|
||||
'/zl/askCSConfigWarnData/' + storedSelectedId,
|
||||
`[${JSON.parse(list.path).canvasCfg.lineList}]`
|
||||
)
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value)
|
||||
timer.value = null
|
||||
}
|
||||
timer.value = setInterval(
|
||||
() => {
|
||||
mqttClient.value.publish(
|
||||
'/zl/askCSConfigWarnData/' + storedSelectedId,
|
||||
`[${JSON.parse(list.path).canvasCfg.lineList}]`
|
||||
)
|
||||
},
|
||||
3 * 60 * 1000
|
||||
)
|
||||
}
|
||||
}
|
||||
// 绑定指标
|
||||
const indicator = async (ids: string[]) => {
|
||||
if (mqttClient.value) {
|
||||
// await mqttClient.value.subscribe('zl/askCSConfigRtData/' + useData.dataTree[0].id)
|
||||
// 发送消息
|
||||
await mqttClient.value.publish('/zl/askCSConfigRtData/' + storedSelectedId, `[${ids}]`)
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value)
|
||||
@@ -1152,4 +910,13 @@ defineExpose({
|
||||
/* background-color: #303b54; */
|
||||
background-color: #5aa1ff29;
|
||||
}
|
||||
/* .aaaa{
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0px;
|
||||
z-index: 111123;
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
background-color: #ccc;
|
||||
} */
|
||||
</style>
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
@drag-canvas-mouse-move="dragCanvasMouseMove"
|
||||
@drag-canvas-mouse-up="dragCanvasMouseUp"
|
||||
></drag-canvas>
|
||||
<!-- </el-scrollbar> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@ export const useDataStore = defineStore('data-store', {
|
||||
wxqr: '',
|
||||
loading: true,
|
||||
display: false, //无锡项目进去是true,其他项目是false 控制预览的时候返回按钮的展示
|
||||
graphicDisplay: 'zl' //无锡项目进去是true,其他项目是false 控制点击设计的时候左侧列表数据绑定图元的展示
|
||||
graphicDisplay: 'zl', //无锡项目进去是true,其他项目是false 控制点击设计的时候左侧列表数据绑定图元的展示
|
||||
treeIndexs: [] //树形结构选中的索引
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
@@ -87,6 +88,9 @@ export const useDataStore = defineStore('data-store', {
|
||||
item.path = data
|
||||
}
|
||||
})
|
||||
},
|
||||
settreeIndexs(data: any) {
|
||||
this.treeIndexs = data
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -12,4 +12,5 @@ export interface DataStoreState {
|
||||
keyName?: String
|
||||
display?: Boolean //是否展示返回按钮
|
||||
graphicDisplay?: string //是否展示数据绑定图元
|
||||
treeIndexs?: any //是否展示数据绑定图元
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { leftAsideStore } from '@/export'
|
||||
import demo from '/svgs/demo.svg?raw'
|
||||
import { find, download, queryPage } from '@/api/index'
|
||||
import { useDataStore } from '@/stores/menuList'
|
||||
import { ElMessage } from 'element-plus'
|
||||
// 定义类型接口
|
||||
interface ElementItem {
|
||||
id: string
|
||||
@@ -83,73 +84,7 @@ const loadSvg = async () => {
|
||||
})
|
||||
}
|
||||
|
||||
// // 添加页面svg
|
||||
// await find().then(async res => {
|
||||
// let result: any = {}
|
||||
// res.data.forEach((item: any) => {
|
||||
// const type = item.elementSonType
|
||||
|
||||
// // 如果该类型还没有在结果中,初始化一个空数组
|
||||
// if (!result[type]) {
|
||||
// result[type] = []
|
||||
// }
|
||||
|
||||
// // 将当前项添加到对应类型的数组中
|
||||
// result[type].push(item)
|
||||
// })
|
||||
// for (const key in result) {
|
||||
// // 创建一个存放所有Promise的数组
|
||||
// const promises = result[key].map((item: any) => {
|
||||
// return download({ filePath: item.path }).then((Svg: any) => {
|
||||
// return {
|
||||
// id: item.id,
|
||||
// title: item.elementName,
|
||||
// type: 'svg',
|
||||
// thumbnail:
|
||||
// 'data:image/svg+xml;utf8,' +
|
||||
// encodeURIComponent(Svg.replace(/(\sfill=(["']))[^"']*(\2)/g, '$1#FF0000$3')),
|
||||
// svg: Svg.replace(/\sfill=(["'])[^"']*\1/g, ''),
|
||||
// props: {
|
||||
// fill: {
|
||||
// type: 'color',
|
||||
// val: '#FF0000',
|
||||
// title: '填充色'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
|
||||
// // 等待所有下载操作完成
|
||||
// const svgList = await Promise.all(promises)
|
||||
|
||||
// // 所有异步操作完成后再执行注册
|
||||
// leftAsideStore.registerConfig(key, svgList)
|
||||
// }
|
||||
// })
|
||||
// 主逻辑
|
||||
try {
|
||||
const res = await find()
|
||||
const groupedElements: Record<string, ElementItem[]> = {}
|
||||
|
||||
// 按类型分组元素
|
||||
res.data.forEach((item: ElementItem) => {
|
||||
const { elementSonType: type } = item
|
||||
if (!groupedElements[type]) {
|
||||
groupedElements[type] = []
|
||||
}
|
||||
groupedElements[type].push(item)
|
||||
})
|
||||
|
||||
// 处理每个类型的元素并注册
|
||||
for (const [type, items] of Object.entries(groupedElements)) {
|
||||
const svgConfigs = await Promise.all(items.map(item => processSvgItem(item, type)))
|
||||
leftAsideStore.registerConfig(type, svgConfigs)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载和处理SVG元素时发生错误:', error)
|
||||
// 可以在这里添加错误恢复逻辑或用户提示
|
||||
}
|
||||
await getSvg()
|
||||
await useData.set('loading', false)
|
||||
|
||||
// const electrical_modules_files = import.meta.glob('@/assets/svgs/electrical/face/**.svg', {
|
||||
@@ -338,4 +273,31 @@ const loadSvg = async () => {
|
||||
// }
|
||||
// ])
|
||||
}
|
||||
export default loadSvg
|
||||
|
||||
const getSvg = async () => {
|
||||
// 主逻辑
|
||||
try {
|
||||
const res = await find()
|
||||
const groupedElements: Record<string, ElementItem[]> = {}
|
||||
|
||||
// 按类型分组元素
|
||||
res.data.forEach((item: ElementItem) => {
|
||||
const { elementSonType: type } = item
|
||||
if (!groupedElements[type]) {
|
||||
groupedElements[type] = []
|
||||
}
|
||||
groupedElements[type].push(item)
|
||||
})
|
||||
|
||||
// 处理每个类型的元素并注册
|
||||
for (const [type, items] of Object.entries(groupedElements)) {
|
||||
const svgConfigs = await Promise.all(items.map(item => processSvgItem(item, type)))
|
||||
leftAsideStore.registerConfig(type, svgConfigs)
|
||||
}
|
||||
ElMessage.success(`图元加载完成!`)
|
||||
} catch (error) {
|
||||
console.error('加载和处理SVG元素时发生错误:', error)
|
||||
// 可以在这里添加错误恢复逻辑或用户提示
|
||||
}
|
||||
}
|
||||
export { loadSvg, getSvg }
|
||||
|
||||
@@ -135,7 +135,7 @@ class MQTT {
|
||||
console.error('订阅失败:', error)
|
||||
reject(error)
|
||||
} else {
|
||||
console.log('订阅成功')
|
||||
console.log('订阅成功', subscribe)
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
|
||||
@@ -21,7 +21,6 @@ class HttpRequest {
|
||||
// 添加全局的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'
|
||||
// 请求头携带token
|
||||
|
||||
@@ -13,7 +13,7 @@ const MtEditRef = ref<InstanceType<typeof MtEdit>>()
|
||||
const onPreviewClick = (exportJson: IExportJson) => {
|
||||
sessionStorage.setItem('exportJson', JSON.stringify(exportJson))
|
||||
const routeUrl = router.resolve({
|
||||
name: 'preview'
|
||||
name: 'preview_YPT'
|
||||
})
|
||||
window.open(routeUrl.href, '_blank')
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ const MtEditRef = ref<InstanceType<typeof MtEdit>>()
|
||||
const onPreviewClick = (exportJson: IExportJson) => {
|
||||
sessionStorage.setItem('exportJson', JSON.stringify(exportJson))
|
||||
const routeUrl = router.resolve({
|
||||
name: 'preview'
|
||||
name: 'preview_YPT'
|
||||
})
|
||||
window.open(routeUrl.href, '_blank')
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ const useData = useDataStore()
|
||||
const onPreviewClick = (exportJson: IExportJson) => {
|
||||
sessionStorage.setItem('exportJson', JSON.stringify(exportJson))
|
||||
const routeUrl = router.resolve({
|
||||
name: 'preview'
|
||||
name: 'preview_YPT'
|
||||
})
|
||||
window.open(routeUrl.href, '_blank')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user