Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
62486410ed
@ -12,6 +12,19 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "2.3.1",
|
||||
"@univerjs/core": "^0.2.4",
|
||||
"@univerjs/design": "^0.2.4",
|
||||
"@univerjs/docs": "^0.2.4",
|
||||
"@univerjs/docs-ui": "^0.2.4",
|
||||
"@univerjs/engine-formula": "^0.2.4",
|
||||
"@univerjs/engine-numfmt": "^0.2.4",
|
||||
"@univerjs/engine-render": "^0.2.4",
|
||||
"@univerjs/facade": "^0.2.4",
|
||||
"@univerjs/rpc": "^0.2.4",
|
||||
"@univerjs/sheets": "^0.2.4",
|
||||
"@univerjs/sheets-formula": "^0.2.4",
|
||||
"@univerjs/sheets-ui": "^0.2.4",
|
||||
"@univerjs/ui": "^0.2.4",
|
||||
"@vueuse/core": "10.10.0",
|
||||
"axios": "1.7.2",
|
||||
"countup.js": "2.8.0",
|
||||
|
@ -12,6 +12,9 @@ import {
|
||||
linkType,
|
||||
} from '/@/views/backend/node/type'
|
||||
import createAxios from '/@/utils/axios'
|
||||
import { encrypt_aes } from '/@/utils/crypto'
|
||||
import { useAdminInfo } from '/@/stores/adminInfo'
|
||||
const adminInfo = useAdminInfo()
|
||||
|
||||
export const getNodeListReq = () => {
|
||||
return createAxios<never, RequestReturnType<nodeType[]>>({
|
||||
@ -98,3 +101,68 @@ export const uploadNodeReq = (data:any) => {
|
||||
data: data,
|
||||
})
|
||||
}
|
||||
|
||||
export const getMappingListReq = (data: any) => {
|
||||
return createAxios({
|
||||
url: '/api/node/link/getMappingList',
|
||||
method: 'post',
|
||||
data: data,
|
||||
})
|
||||
}
|
||||
|
||||
export const saveMappingListReq = (data: any) => {
|
||||
return createAxios<never, RequestReturnType>({
|
||||
url: '/api/node/link/saveMappingList',
|
||||
method: 'post',
|
||||
data: data,
|
||||
})
|
||||
}
|
||||
|
||||
export const bindDeviceMeasReq = (data: any) => {
|
||||
return createAxios({
|
||||
url: '/api/node/link/bindDeviceMeas',
|
||||
method: 'post',
|
||||
data: data,
|
||||
})
|
||||
}
|
||||
|
||||
export const getBindDeviceTreeReq = (data: any) => {
|
||||
return createAxios({
|
||||
url: '/api/node/link/getBindDeviceTree',
|
||||
method: 'post',
|
||||
data: data,
|
||||
})
|
||||
}
|
||||
|
||||
export const downloadMappingListReq = (data: any) => {
|
||||
return createAxios(
|
||||
{
|
||||
url: '/api/node/link/exportMappingList',
|
||||
method: 'post',
|
||||
data: data,
|
||||
responseType: 'blob',
|
||||
},
|
||||
{
|
||||
reductDataFormat: false,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export const uploadMappingListReq = (data: any, v: string) => {
|
||||
const token = encrypt_aes(adminInfo.token, v)
|
||||
return createAxios<never, RequestReturnType>(
|
||||
{
|
||||
url: '/api/node/link/importMappingList',
|
||||
method: 'post',
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
v,
|
||||
token,
|
||||
},
|
||||
},
|
||||
{
|
||||
customEncrypt: true,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -65,6 +65,11 @@ const staticRoutes: Array<RouteRecordRaw> = [
|
||||
title: pageTitle('noPower'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/univer',
|
||||
name: 'univer',
|
||||
component: () => import('/@/views/backend/node/univer.vue'),
|
||||
},
|
||||
]
|
||||
|
||||
const staticFiles: Record<string, Record<string, RouteRecordRaw>> = import.meta.glob('./static/*.ts', { eager: true })
|
||||
|
@ -622,7 +622,7 @@ const closeAttributeForm = () => {
|
||||
attributeFormRef.value?.resetFields()
|
||||
}
|
||||
const submitAttributeForm = () => {
|
||||
attributeFormRef.value?.validate((valid) => {
|
||||
attributeFormRef.value?.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
if (attributeFormTitle.value === AttributeDialogTitleStateType['add']) {
|
||||
attributeForm.value.iotModelId = curContextMenuTreeData.value!.id!
|
||||
@ -681,7 +681,7 @@ const closeServiceForm = () => {
|
||||
serviceFormRef.value?.resetFields()
|
||||
}
|
||||
const submitServiceForm = () => {
|
||||
serviceFormRef.value?.validate((valid) => {
|
||||
serviceFormRef.value?.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
if (serviceFormTitle.value === serviceDialogTitleStateType['add']) {
|
||||
serviceForm.value.iotModelId = curContextMenuTreeData.value!.id!
|
||||
|
@ -322,7 +322,7 @@ const addInstitutional = (rightClick = false) => {
|
||||
const submitAddForm = () => {
|
||||
console.log(formModel.value)
|
||||
if (!formRef.value) return
|
||||
formRef.value.validate((valid) => {
|
||||
formRef.value.validate((valid:boolean) => {
|
||||
if (valid) {
|
||||
if (dialogTitle.value === '新增机构') {
|
||||
formModel.value.parentOrgId = formModel.value.parentOrgId ?? '0'
|
||||
|
@ -98,6 +98,8 @@
|
||||
<el-table-column fixed="right" label="操作" min-width="80" align="center">
|
||||
<template #default="scope">
|
||||
<div class="tableOperate">
|
||||
<a @click="openlinkPoint(scope.row)">测点</a>
|
||||
<a>|</a>
|
||||
<a @click="editLinkList(scope.row)">编辑</a>
|
||||
<a>|</a>
|
||||
<el-popconfirm title="确定删除么?" @confirm="delLinkList(scope.row)">
|
||||
@ -175,6 +177,10 @@ import {
|
||||
import { getInstitutionalTreeListReq } from '/@/api/backend/org/request'
|
||||
import { debounce } from 'lodash-es'
|
||||
import ProtocolComponent from './protocol.vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const searchTreeInput = ref('')
|
||||
|
||||
@ -362,6 +368,7 @@ const getNodeList = () => {
|
||||
clickTreeData.value = res.data![0]
|
||||
nextTick(() => {
|
||||
nodeTreeRef.value?.setCurrentKey(res.data![0].id)
|
||||
getLinkData(res.data![0].id!)
|
||||
})
|
||||
} else {
|
||||
ElMessage.error(res.msg ?? '查询失败')
|
||||
@ -439,7 +446,7 @@ const delLinkList = (row: linkType) => {
|
||||
})
|
||||
}
|
||||
const submitLinkForm = () => {
|
||||
linkFormRef.value?.validate((valid) => {
|
||||
linkFormRef.value?.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
if (linkTitle.value === '新增链路') {
|
||||
addLinkListReq(linkForm.value)
|
||||
@ -531,9 +538,18 @@ const openParams = (data: linkType) => {
|
||||
ElMessage.warning('请先设置协议类型')
|
||||
}
|
||||
}
|
||||
getNodeList().then(() => {
|
||||
getLinkData(clickTreeData.value!.id!)
|
||||
const openlinkPoint = (data: linkType) => {
|
||||
router.push({
|
||||
name: 'univer',
|
||||
query: {
|
||||
protocol: data.protocol,
|
||||
id: data.id,
|
||||
prevPath: route.path,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
getNodeList()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
552
ui/dasadmin/src/views/backend/node/univer.vue
Normal file
552
ui/dasadmin/src/views/backend/node/univer.vue
Normal file
@ -0,0 +1,552 @@
|
||||
<template>
|
||||
<Container :has-aside="false">
|
||||
<template #mainHeader>
|
||||
<div class="header">
|
||||
<el-button @click="openCorrectionPoint">关联测点</el-button>
|
||||
<div class="rightOperate">
|
||||
<el-upload ref="uploadRef" :show-file-list="false" :limit="1" :http-request="upload" :on-exceed="handleExceed">
|
||||
<template #trigger>
|
||||
<el-button>上传</el-button>
|
||||
</template>
|
||||
</el-upload>
|
||||
<el-popconfirm @confirm="download" title="确认下载么?">
|
||||
<template #reference>
|
||||
<el-button>下载</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
<el-button @click="saveExcelData">保存</el-button>
|
||||
<el-popconfirm @confirm="resetExcel" title="确认重置么?">
|
||||
<template #reference>
|
||||
<el-button>重置</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
|
||||
<el-popconfirm @confirm="goToNodePage" title="返回通讯链路?">
|
||||
<template #reference>
|
||||
<el-icon size="22" style="cursor: pointer"><RefreshLeft /></el-icon>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #mainMain>
|
||||
<div class="main" v-loading="hasLoading">
|
||||
<div v-show="showTips" class="tips" :style="{ transform: `translate(${tipsPos.top},${tipsPos.left})` }">
|
||||
<ul>
|
||||
<li v-for="item in tipList" key="item">{{ item }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div ref="container" class="univer-container" />
|
||||
</div>
|
||||
</template>
|
||||
</Container>
|
||||
<el-dialog v-model="showCorrelationPoint" title="关联测点" @close="closecorrectionDevice">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-button @click="addCorrectionDevice" class="btnStyle">添加设备</el-button>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-popconfirm @confirm="clearCorrectionDevice" title="确认清空么?">
|
||||
<template #reference>
|
||||
<el-button class="btnStyle">清空</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<div class="treeMain">
|
||||
<el-tree
|
||||
ref="deviceTreeRef"
|
||||
:data="deviceTreeData"
|
||||
:props="repalceDeviceTreeKey"
|
||||
node-key="id"
|
||||
lazy
|
||||
:load="loadDeviceTreeData"
|
||||
show-checkbox
|
||||
></el-tree>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="treeMain">
|
||||
<el-tree :data="correctionDevice" :props="repalceDeviceTreeKey" node-key="id" draggable :allow-drop="dropJudge">
|
||||
<template #default="{ node, data }">
|
||||
<div class="correctionTreeItem">
|
||||
<span>{{ correctionDevice.findIndex((item: any) => item.id === node.key) + 1 + '、' + data.name }}</span>
|
||||
<div class="rightItem">
|
||||
<el-input v-if="data.isEdit" v-model="data.iotAddr" @keyup.enter="okEdit(data)" @blur="okEdit(data)"></el-input>
|
||||
<el-tag v-else type="info" @click="editAttr(data)">{{ data.iotAddr }}</el-tag>
|
||||
<el-popconfirm @confirm="delCorrectionDevice(node)" title="确认删除么?">
|
||||
<template #reference>
|
||||
<el-icon><Delete /></el-icon>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<template #footer>
|
||||
<el-button type="primary" @click="submitcorrectionDevice">提交</el-button>
|
||||
<el-button @click="closecorrectionDevice">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Container from '/@/components/container/index.vue'
|
||||
import { equipQuery, equipType } from '/@/api/backend'
|
||||
import { ElRow, ElCol, ElButton, ElTree, ElDialog, ElMessage, ElUpload, genFileId } from 'element-plus'
|
||||
import type { UploadRequestOptions, UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
|
||||
import type { TreeInstance } from 'element-plus'
|
||||
import { Delete, RefreshLeft } from '@element-plus/icons-vue'
|
||||
import {
|
||||
getMappingListReq,
|
||||
saveMappingListReq,
|
||||
getBindDeviceTreeReq,
|
||||
bindDeviceMeasReq,
|
||||
downloadMappingListReq,
|
||||
uploadMappingListReq,
|
||||
} from '/@/api/backend/node/request'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { onBeforeUnmount, onMounted, ref, reactive } from 'vue'
|
||||
|
||||
import '@univerjs/design/lib/index.css'
|
||||
import '@univerjs/ui/lib/index.css'
|
||||
import '@univerjs/docs-ui/lib/index.css'
|
||||
import '@univerjs/sheets-ui/lib/index.css'
|
||||
import '@univerjs/sheets-formula/lib/index.css'
|
||||
|
||||
import { Univer, UniverInstanceType, Tools, Workbook, LocaleType, IWorkbookData } from '@univerjs/core'
|
||||
import { defaultTheme } from '@univerjs/design'
|
||||
|
||||
import { UniverFormulaEnginePlugin } from '@univerjs/engine-formula'
|
||||
import { UniverRenderEnginePlugin } from '@univerjs/engine-render'
|
||||
|
||||
import { UniverUIPlugin } from '@univerjs/ui'
|
||||
|
||||
import { UniverDocsPlugin } from '@univerjs/docs'
|
||||
import { UniverDocsUIPlugin } from '@univerjs/docs-ui'
|
||||
|
||||
import { UniverSheetsPlugin } from '@univerjs/sheets'
|
||||
import { UniverSheetsFormulaPlugin } from '@univerjs/sheets-formula'
|
||||
import { UniverSheetsUIPlugin } from '@univerjs/sheets-ui'
|
||||
|
||||
import DesignZhCN from '@univerjs/design/locale/zh-CN'
|
||||
import UIZhCN from '@univerjs/ui/locale/zh-CN'
|
||||
import DocsUIZhCN from '@univerjs/docs-ui/locale/zh-CN'
|
||||
import SheetsZhCN from '@univerjs/sheets/locale/zh-CN'
|
||||
import SheetsUIZhCN from '@univerjs/sheets-ui/locale/zh-CN'
|
||||
import { FUniver } from '@univerjs/facade'
|
||||
|
||||
import { excelDefaultConfig, createWookbookData, createUpLoadExcelData, createSheetData, setExcelNameToLinkId } from './utils'
|
||||
import { encrypt_aes, generateRandomNumber } from '/@/utils/crypto'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const hasLoading = ref(true)
|
||||
|
||||
const univerRef = ref<Univer | null>(null)
|
||||
const workbook = ref<Workbook | null>(null)
|
||||
const container = ref<HTMLElement | null>(null)
|
||||
|
||||
let univerAPI: any = null
|
||||
//#region
|
||||
// const commandWhiteList = [
|
||||
// 'ui.operation.open-find-dialog',
|
||||
// 'sheet.command.set-scroll-relative',
|
||||
// 'sheet.operation.set-scroll',
|
||||
// 'ui.operation.go-to-next-match',
|
||||
// 'sheet.command.scroll-to-cell',
|
||||
// 'sheet.command.scroll-view',
|
||||
// 'formula.mutation.set-formula-calculation-notification',
|
||||
// 'formula.mutation.set-formula-data',
|
||||
// 'formula.mutation.set-other-formula',
|
||||
// 'sheet.operation.set-activate-cell-edit',
|
||||
// 'formula-ui.operation.help-function',
|
||||
// 'formula.mutation.set-formula-calculation-start',
|
||||
// 'sheet.mutation.data-validation-formula-mark-dirty',
|
||||
// 'formula-ui.operation.search-function',
|
||||
// 'formula.mutation.set-array-formula-data',
|
||||
// 'formula.mutation.set-formula-calculation-result',
|
||||
// 'doc.operation.set-selections',
|
||||
// 'ui.operation.open-replace-dialog',
|
||||
// 'sheet.operation.set-worksheet-active',
|
||||
// 'sheet.operation.set-selections',
|
||||
// ]
|
||||
//#endregion
|
||||
const init = async () => {
|
||||
const reqSheetData = await getMappingList()
|
||||
const sheetData = createSheetData(reqSheetData, 12)
|
||||
const data = createWookbookData(route.query.protocol as any, route.query.id as string, sheetData)
|
||||
initExcel(data)
|
||||
}
|
||||
|
||||
const initExcel = (data = {}) => {
|
||||
const univer = new Univer({
|
||||
theme: defaultTheme,
|
||||
locale: LocaleType.ZH_CN,
|
||||
locales: {
|
||||
[LocaleType.ZH_CN]: Tools.deepMerge(SheetsZhCN, DocsUIZhCN, SheetsUIZhCN, UIZhCN, DesignZhCN),
|
||||
},
|
||||
})
|
||||
univerRef.value = univer
|
||||
|
||||
// core plugins
|
||||
univer.registerPlugin(UniverRenderEnginePlugin)
|
||||
univer.registerPlugin(UniverFormulaEnginePlugin)
|
||||
univer.registerPlugin(UniverUIPlugin, {
|
||||
container: container.value!,
|
||||
})
|
||||
|
||||
// doc plugins
|
||||
univer.registerPlugin(UniverDocsPlugin, {
|
||||
hasScroll: false,
|
||||
})
|
||||
univer.registerPlugin(UniverDocsUIPlugin)
|
||||
|
||||
// sheet plugins
|
||||
univer.registerPlugin(UniverSheetsPlugin)
|
||||
univer.registerPlugin(UniverSheetsUIPlugin)
|
||||
univer.registerPlugin(UniverSheetsFormulaPlugin)
|
||||
|
||||
// create workbook instance
|
||||
workbook.value = univer.createUnit<IWorkbookData, Workbook>(UniverInstanceType.UNIVER_SHEET, data)
|
||||
|
||||
univerAPI = FUniver.newAPI(univer)
|
||||
|
||||
univerAPI.getSheetHooks().onCellPointerOver((cell: any) => {
|
||||
// 拿到当前鼠标指向的单元格
|
||||
if (cell?.location.row === 0 && cell?.location.col > 1) {
|
||||
const { row, col, subUnitId } = cell.location
|
||||
const typeId = subUnitId.slice(6)
|
||||
const index = `R${row}C${col}`
|
||||
tipList.value = excelDefaultConfig[route.query.protocol as any][typeId]?.[index] ?? []
|
||||
if (tipList.value.length) {
|
||||
showTips.value = true
|
||||
} else {
|
||||
showTips.value = false
|
||||
}
|
||||
tipsPos.top = cell.position.startX + 'px'
|
||||
tipsPos.left = cell.position.startY + 90 + 'px'
|
||||
} else {
|
||||
showTips.value = false
|
||||
}
|
||||
})
|
||||
hasLoading.value = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy univer instance and workbook instance
|
||||
*/
|
||||
const destroyUniver = () => {
|
||||
return new Promise((resolve) => {
|
||||
const result = univerAPI.disposeUnit('workbook-01')
|
||||
univerRef.value = null
|
||||
workbook.value = null
|
||||
resolve(result)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Get workbook data
|
||||
*/
|
||||
const getData = () => {
|
||||
if (!workbook.value) {
|
||||
throw new Error('Workbook is not initialized')
|
||||
}
|
||||
return workbook.value.save()
|
||||
}
|
||||
|
||||
const showCorrelationPoint = ref(false)
|
||||
const openCorrectionPoint = () => {
|
||||
getBindDeviceTree()
|
||||
showCorrelationPoint.value = true
|
||||
}
|
||||
const deviceTreeRef = ref<TreeInstance>()
|
||||
const deviceTreeData = ref([])
|
||||
const repalceDeviceTreeKey = {
|
||||
label: 'name',
|
||||
isLeaf: 'isLeaf',
|
||||
}
|
||||
const getTreeDataType = () => {
|
||||
equipType().then((res) => {
|
||||
deviceTreeData.value = res.data.map((item: any) => {
|
||||
return {
|
||||
name: item.equipmentTypeName,
|
||||
id: item.equipmentTypeId,
|
||||
isType: true,
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
const loadDeviceTreeData = (node: any, resolve: any) => {
|
||||
if (node.level === 0) {
|
||||
return resolve(deviceTreeData.value)
|
||||
}
|
||||
|
||||
equipQuery({ pageSize: 100, pageNum: 1, objectType: node.key }).then((res: any) => {
|
||||
const data = res.rows.map((item: any) => {
|
||||
return {
|
||||
...item,
|
||||
isLeaf: true,
|
||||
}
|
||||
})
|
||||
return resolve(data)
|
||||
})
|
||||
}
|
||||
|
||||
const correctionDevice = ref<any[]>([])
|
||||
|
||||
const addCorrectionDevice = () => {
|
||||
const nodeList = deviceTreeRef.value!.getCheckedNodes()
|
||||
|
||||
const data: any = []
|
||||
nodeList.forEach((item) => {
|
||||
if (!item.isType) {
|
||||
const exist = correctionDevice.value.find((Correction) => Correction.id == item.id)
|
||||
if (!exist) {
|
||||
data.push(item)
|
||||
}
|
||||
}
|
||||
})
|
||||
correctionDevice.value = [...correctionDevice.value, ...data]
|
||||
}
|
||||
const clearCorrectionDevice = () => {
|
||||
correctionDevice.value = []
|
||||
}
|
||||
|
||||
const delCorrectionDevice = (node: any) => {
|
||||
deviceTreeRef.value!.remove(node)
|
||||
}
|
||||
|
||||
const editAttr = (data: any) => {
|
||||
data.isEdit = true
|
||||
}
|
||||
const okEdit = (data: any) => {
|
||||
data.isEdit = false
|
||||
}
|
||||
const submitcorrectionDevice = () => {
|
||||
const bindDeviceId = correctionDevice.value.map((item: any) => {
|
||||
return {
|
||||
equipmentId: item.id,
|
||||
iotAddr: item.iotAddr,
|
||||
}
|
||||
})
|
||||
|
||||
bindDeviceMeasReq({ equipmentId: bindDeviceId, linkId: route.query.id }).then((res) => {
|
||||
ElMessage.success('关联成功!')
|
||||
closecorrectionDevice()
|
||||
})
|
||||
}
|
||||
|
||||
const closecorrectionDevice = () => {
|
||||
correctionDevice.value = []
|
||||
showCorrelationPoint.value = false
|
||||
}
|
||||
|
||||
const dropJudge = (draggingNode: any, dropNode: any, type: any) => {
|
||||
if (type === 'inner') {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const showTips = ref(false)
|
||||
const tipList = ref<string[]>([])
|
||||
const tipsPos = reactive({
|
||||
top: '0',
|
||||
left: '0',
|
||||
})
|
||||
|
||||
const saveExcelData = () => {
|
||||
const data = getData()
|
||||
const val = createUpLoadExcelData(data)
|
||||
console.log(val);
|
||||
|
||||
saveMappingList(val)
|
||||
}
|
||||
|
||||
const getBindDeviceTree = () => {
|
||||
getBindDeviceTreeReq({ linkId: route.query.id as any }).then((res) => {
|
||||
if (res.data) {
|
||||
correctionDevice.value = res.data.map((item: any) => {
|
||||
return {
|
||||
id: item.equipmentId,
|
||||
name: item.equipmentName,
|
||||
iotAddr: item.iotAddr,
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
const getMappingList = () => {
|
||||
const asyncReqList: any = []
|
||||
const type = [138, 139, 140, 146, 147]
|
||||
type.forEach((item) => {
|
||||
asyncReqList.push(
|
||||
getMappingListReq({ linkId: route.query.id as any, type: item }).then((res) => {
|
||||
return { [item]: res.data }
|
||||
})
|
||||
)
|
||||
})
|
||||
return Promise.all(asyncReqList).then((data) => {
|
||||
let result = {}
|
||||
data.forEach((item) => {
|
||||
result = { ...result, ...item }
|
||||
})
|
||||
console.log(result);
|
||||
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
const saveMappingList = (data: any[]) => {
|
||||
hasLoading.value = true
|
||||
saveMappingListReq(data).then((res) => {
|
||||
if (res.success) {
|
||||
ElMessage.success('保存成功!')
|
||||
resetExcel()
|
||||
}
|
||||
})
|
||||
}
|
||||
const uploadRef = ref<UploadInstance>()
|
||||
|
||||
const upload = (file: UploadRequestOptions) => {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file.file)
|
||||
const v = generateRandomNumber(16)
|
||||
const id = encrypt_aes(route.query.id, v)
|
||||
formData.append('id', id)
|
||||
return uploadMappingListReq(formData, v).then((res) => {
|
||||
if (res.success) {
|
||||
hasLoading.value = true
|
||||
ElMessage.success('上传成功!')
|
||||
resetExcel()
|
||||
} else {
|
||||
ElMessage.error(res.msg ?? '上传失败!')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleExceed: UploadProps['onExceed'] = (files) => {
|
||||
uploadRef.value!.clearFiles()
|
||||
const file = files[0] as UploadRawFile
|
||||
file.uid = genFileId()
|
||||
uploadRef.value!.handleStart(file)
|
||||
uploadRef.value!.submit()
|
||||
}
|
||||
|
||||
const download = () => {
|
||||
downloadMappingListReq({ linkId: route.query.id as any }).then((res: any) => {
|
||||
const title = res.headers['content-disposition'].match(/(?<=filename\=).*\.json$/)?.[0] ?? 'imptabmapping.json'
|
||||
const url = window.URL.createObjectURL(res.data)
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
a.download = title
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
window.URL.revokeObjectURL(url)
|
||||
document.body.removeChild(a)
|
||||
})
|
||||
}
|
||||
|
||||
const resetExcel = () => {
|
||||
destroyUniver().then((status) => {
|
||||
if (status) {
|
||||
init()
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
init()
|
||||
}, 1000)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const goToNodePage = () => {
|
||||
// router.push({ path: route.query.prevPath as string })
|
||||
router.go(-1)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
getTreeDataType()
|
||||
getBindDeviceTree()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
destroyUniver()
|
||||
})
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="scss">
|
||||
.main {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.univer-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.tips {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: #ccc;
|
||||
max-width: 300px;
|
||||
color: brown;
|
||||
padding: 5px 5px 5px 23px;
|
||||
border-radius: 5px;
|
||||
z-index: 9999;
|
||||
}
|
||||
}
|
||||
|
||||
/* Also hide the menubar */
|
||||
:global(.univer-menubar) {
|
||||
display: none;
|
||||
}
|
||||
.correctionTreeItem {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-right: 10px;
|
||||
.rightItem {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
min-width: 42px;
|
||||
.el-icon {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btnStyle {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.el-button {
|
||||
width: 88px;
|
||||
height: 40px;
|
||||
}
|
||||
.rightOperate {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 410px;
|
||||
.el-button {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
376
ui/dasadmin/src/views/backend/node/utils.ts
Normal file
376
ui/dasadmin/src/views/backend/node/utils.ts
Normal file
@ -0,0 +1,376 @@
|
||||
import { LocaleType, BooleanNumber, SheetTypes } from '@univerjs/core'
|
||||
|
||||
export const excelDefaultConfig: any = {
|
||||
12: {
|
||||
//遥测138 ANALOG
|
||||
138: {
|
||||
name: '模拟量',
|
||||
head: [
|
||||
{
|
||||
label: '功能码',
|
||||
code: 'col1',
|
||||
},
|
||||
{
|
||||
label: '数据类型',
|
||||
code: 'col2',
|
||||
},
|
||||
{
|
||||
label: '数据符号',
|
||||
code: 'col3',
|
||||
},
|
||||
{
|
||||
label: '寄存器地址',
|
||||
code: 'col4',
|
||||
},
|
||||
],
|
||||
R0C3: ['03', '04'],
|
||||
R0C4: [
|
||||
'0 - 32位浮点数(高位在第一个寄存器)',
|
||||
'1 - 32位浮点数(高位在第二个寄存器)',
|
||||
'2 - 16位归一化值',
|
||||
'3 - 32位归一化值(高位在第一个寄存器)',
|
||||
'4 - 32位归一化值(高位在第二个寄存器)',
|
||||
'5 - 32位浮点数(小端系统模式)',
|
||||
'6 - 32位BCD数据(*高位在第一个寄存器*)',
|
||||
'7 - 32位BCD数据(*高位在第二个寄存器*)',
|
||||
'8 - 16位BCD数据',
|
||||
], // 数据类型的提示
|
||||
R0C5: ['0 - 无符号', '1 - 有符号'], // 数据符号的提示
|
||||
},
|
||||
//遥控147 CONTROL
|
||||
147: {
|
||||
name: '遥控量',
|
||||
head: [
|
||||
{
|
||||
label: '功能码',
|
||||
code: 'col1',
|
||||
},
|
||||
{
|
||||
label: '执行前需要预置',
|
||||
code: 'col2',
|
||||
},
|
||||
{
|
||||
label: '选择合寄存器',
|
||||
code: 'col3',
|
||||
},
|
||||
{
|
||||
label: '执行合寄存器',
|
||||
code: 'col4',
|
||||
},
|
||||
{
|
||||
label: '撤销合寄存器',
|
||||
code: 'col5',
|
||||
},
|
||||
|
||||
{
|
||||
label: '合闸数值',
|
||||
code: 'col6',
|
||||
},
|
||||
{
|
||||
label: '选择分寄存器',
|
||||
code: 'col7',
|
||||
},
|
||||
{
|
||||
label: '执行分寄存器',
|
||||
code: 'col8',
|
||||
},
|
||||
{
|
||||
label: '撤销分寄存器',
|
||||
code: 'col9',
|
||||
},
|
||||
{
|
||||
label: '分闸数值',
|
||||
code: 'col10',
|
||||
},
|
||||
],
|
||||
R0C3: ['05', '15', '06', '16'],
|
||||
R0C4: ['0 - 直接执行', '1 - 预置执行'],
|
||||
},
|
||||
//遥调146 SETPOINT
|
||||
146: {
|
||||
name: '遥调量',
|
||||
head: [
|
||||
{
|
||||
label: '遥调类型',
|
||||
code: 'col1',
|
||||
},
|
||||
{
|
||||
label: '功能码',
|
||||
code: 'col2',
|
||||
},
|
||||
{
|
||||
label: '执行前需要预置',
|
||||
code: 'col3',
|
||||
},
|
||||
{
|
||||
label: '选择寄存器',
|
||||
code: 'col4',
|
||||
},
|
||||
{
|
||||
label: '执行寄存器',
|
||||
code: 'col5',
|
||||
},
|
||||
{
|
||||
label: '撤销寄存器',
|
||||
code: 'col6',
|
||||
},
|
||||
],
|
||||
R0C3: ['0 - 16位整型值', '1 - 32位值高位在第一个寄存器', '2 - 32位值高位在第二个寄存器'],
|
||||
R0C4: ['06', '16'],
|
||||
R0C5: ['0 - 直接执行', '1 - 预置执行'],
|
||||
},
|
||||
//遥脉139 ACCUMULATOR
|
||||
139: {
|
||||
name: '累计量',
|
||||
head: [
|
||||
{
|
||||
label: '功能码',
|
||||
code: 'col1',
|
||||
},
|
||||
{
|
||||
label: '数据类型',
|
||||
code: 'col2',
|
||||
},
|
||||
{
|
||||
label: '寄存器地址',
|
||||
code: 'col3',
|
||||
},
|
||||
],
|
||||
R0C3: ['03', '04'],
|
||||
R0C4: [
|
||||
'0 - 16位无符号整型值',
|
||||
'1 - 32位无符号整型值(高位在第一个寄存器)',
|
||||
'2 - 32位有符号整型值(高位在第一个寄存器)',
|
||||
'3 - 32位无符号整型值(高位在第二个寄存器)',
|
||||
'4 - 32位有符号整型值(高位在第二个寄存器)',
|
||||
'5 - 32位浮点数值(高位在第一个寄存器)',
|
||||
'6 - 32位浮点数值(高位在第二个寄存器)',
|
||||
'7 - 64位双精度值(AB CD EF GH)',
|
||||
'8 - 64位双精度值(GH EF CD AB)',
|
||||
'9 - 32位短浮点数值(小端模式)',
|
||||
'10 - 32位BCD数据(*高位在第一个寄存器*)',
|
||||
],
|
||||
},
|
||||
//遥信140 DISCRETE
|
||||
140: {
|
||||
name: '离散量',
|
||||
head: [
|
||||
{
|
||||
label: '功能码',
|
||||
code: 'col1',
|
||||
},
|
||||
{ label: '偏移量', code: 'col2' },
|
||||
{
|
||||
label: '寄存器',
|
||||
code: 'col3',
|
||||
},
|
||||
],
|
||||
R0C3: ['01', '02', '03', '04'],
|
||||
},
|
||||
},
|
||||
}
|
||||
const DEFAULT_WORKBOOK_DATA = {
|
||||
id: 'workbook-01',
|
||||
locale: LocaleType.ZH_CN,
|
||||
name: 'universheet',
|
||||
sheetOrder: ['sheet-138', 'sheet-139', 'sheet-140', 'sheet-146', 'sheet-147'],
|
||||
appVersion: '3.0.0-alpha',
|
||||
styles: {
|
||||
1: {
|
||||
vt: 2,
|
||||
ht: 2,
|
||||
},
|
||||
2: {
|
||||
vt: 2,
|
||||
ht: 2,
|
||||
bg: {
|
||||
rgb: '#eceff7',
|
||||
},
|
||||
},
|
||||
},
|
||||
sheets: {},
|
||||
}
|
||||
/**
|
||||
* 创建excel标题行
|
||||
* @param protocol
|
||||
* @returns
|
||||
*/
|
||||
const createHeaderData = (protocol: string | number) => {
|
||||
if (!protocol) return {}
|
||||
const headerData: any = {}
|
||||
//#region
|
||||
Object.keys(excelDefaultConfig[protocol!]).forEach((item) => {
|
||||
const dynamicData: any = {}
|
||||
excelDefaultConfig[protocol!][item].head.forEach((head: any, index: number) => {
|
||||
const key = index + 2
|
||||
dynamicData[key] = {
|
||||
v: head.label,
|
||||
s: '1',
|
||||
custom: head.code,
|
||||
}
|
||||
})
|
||||
const headerItemData = {
|
||||
0: {
|
||||
0: {
|
||||
v: '设备名称',
|
||||
s: '1',
|
||||
custom: 'equipmentName',
|
||||
},
|
||||
1: {
|
||||
v: '属性名称',
|
||||
s: '1',
|
||||
custom: 'name',
|
||||
},
|
||||
...dynamicData,
|
||||
},
|
||||
}
|
||||
headerData[item] = headerItemData
|
||||
})
|
||||
//#endregion
|
||||
return headerData
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置excel名称为linkId
|
||||
* @param id linkId
|
||||
*/
|
||||
export const setExcelNameToLinkId = (id: string) => {
|
||||
DEFAULT_WORKBOOK_DATA.name = id
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建excel数据
|
||||
* @param protocol 协议类型
|
||||
* @param data excel数据
|
||||
* @returns
|
||||
*/
|
||||
export const createWookbookData = (protocol: number, linkId: string, data: any = {}) => {
|
||||
const headerData = createHeaderData(protocol)
|
||||
const sheetData: any = {}
|
||||
//#region
|
||||
Object.keys(headerData).forEach((item) => {
|
||||
const rowLen = Object.keys(data[item]).length + 1
|
||||
|
||||
sheetData['sheet-' + item] = {
|
||||
type: SheetTypes.GRID,
|
||||
id: 'sheet-' + item,
|
||||
cellData: {
|
||||
...headerData[item],
|
||||
...data[item],
|
||||
},
|
||||
name: excelDefaultConfig[protocol][item].name,
|
||||
tabColor: 'green',
|
||||
hidden: BooleanNumber.FALSE,
|
||||
rowCount: rowLen,
|
||||
columnCount: Object.keys(headerData[item][0]).length,
|
||||
zoomRatio: 1,
|
||||
scrollTop: 200,
|
||||
scrollLeft: 100,
|
||||
defaultColumnWidth: 120,
|
||||
defaultRowHeight: 30,
|
||||
status: 1,
|
||||
showGridlines: 1,
|
||||
hideRow: [],
|
||||
hideColumn: [],
|
||||
columnData: {
|
||||
0: {
|
||||
w: 300,
|
||||
h: 0,
|
||||
},
|
||||
1: {
|
||||
w: 300,
|
||||
h: 0,
|
||||
},
|
||||
},
|
||||
rowHeader: {
|
||||
width: 46,
|
||||
hidden: BooleanNumber.FALSE,
|
||||
},
|
||||
columnHeader: {
|
||||
height: 20,
|
||||
hidden: BooleanNumber.FALSE,
|
||||
},
|
||||
rightToLeft: BooleanNumber.FALSE,
|
||||
}
|
||||
})
|
||||
//#endregion
|
||||
DEFAULT_WORKBOOK_DATA.sheets = sheetData
|
||||
DEFAULT_WORKBOOK_DATA.name = linkId
|
||||
|
||||
return DEFAULT_WORKBOOK_DATA
|
||||
}
|
||||
|
||||
export const createUpLoadExcelData = (workbookData: any) => {
|
||||
const sheets = workbookData.sheets
|
||||
const data: any = []
|
||||
Object.keys(sheets).forEach((item) => {
|
||||
const sheetkeyMap: any = {}
|
||||
const sheetKeys = Object.keys(sheets[item].cellData)
|
||||
sheetKeys.forEach((key) => {
|
||||
const sheetData: any = {}
|
||||
const fieldKeys = Object.keys(sheets[item].cellData[key])
|
||||
if (key === '0') {
|
||||
fieldKeys.forEach((fieldKey) => {
|
||||
const sheetKey = sheets[item].cellData[key][fieldKey].custom
|
||||
sheetkeyMap[fieldKey] = sheetKey
|
||||
})
|
||||
} else {
|
||||
let params: any = {}
|
||||
const sheetKeyMapKeys = Object.keys(sheetkeyMap)
|
||||
for (let fieldKey of sheetKeyMapKeys) {
|
||||
if (fieldKey === '0') {
|
||||
sheetData.equipmentId = sheets[item].cellData[key][fieldKey].custom.equipmentId
|
||||
sheetData.linkId = workbookData.name
|
||||
sheetData[sheetkeyMap[fieldKey]] = sheets[item].cellData[key][fieldKey]?.v ?? ''
|
||||
sheetData.type = sheets[item].cellData[key][fieldKey].custom.type
|
||||
sheetData.id = sheets[item].cellData[key][fieldKey].custom.id
|
||||
continue
|
||||
}
|
||||
if (fieldKey === '1') {
|
||||
sheetData[sheetkeyMap[fieldKey]] = sheets[item].cellData[key][fieldKey]?.v ?? ''
|
||||
continue
|
||||
}
|
||||
params[sheetkeyMap[fieldKey]] = sheets[item].cellData[key][fieldKey]?.v ?? ''
|
||||
}
|
||||
sheetData.params = JSON.stringify(params)
|
||||
data.push(sheetData)
|
||||
}
|
||||
})
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
export const createSheetData = (data: any, protocol: string | number) => {
|
||||
if (!protocol) return {}
|
||||
const excelCellDataMap: any = {}
|
||||
const headerData = createHeaderData(protocol)
|
||||
const resultData: any = {}
|
||||
Object.keys(headerData).forEach((item) => {
|
||||
excelCellDataMap[item] = {}
|
||||
Object.keys(headerData[item][0]).forEach((key) => {
|
||||
excelCellDataMap[headerData[item][0][key].custom] = key
|
||||
})
|
||||
const result: any = {}
|
||||
data[item].forEach((obj: any, index: number) => {
|
||||
const params = obj.params && obj.params !== '' ? JSON.parse(obj.params) : {}
|
||||
obj = { ...obj, ...params }
|
||||
const row = index + 1
|
||||
result[row] = {}
|
||||
Object.keys(obj).forEach((field) => {
|
||||
const col = excelCellDataMap[field]
|
||||
if (col) {
|
||||
let custom: any
|
||||
if (col === '0') {
|
||||
custom = {}
|
||||
custom.equipmentId = obj.equipmentId
|
||||
custom.type = item
|
||||
custom.id = obj.id
|
||||
}
|
||||
result[row][col] = { v: obj[field], s: '1', custom }
|
||||
}
|
||||
})
|
||||
})
|
||||
resultData[item] = result
|
||||
})
|
||||
return resultData
|
||||
}
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user