| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- <script setup lang="ts">
- import {
- WebtopoProjectApi,
- type WebtopoProjectDetailVO,
- type WebtopoProjectUpdateReqVO
- } from '@/api/pms/maotu'
- import type { IExportJson } from '@/components/mt-edit/components/types'
- import { useGenThumbnail } from '@/components/mt-edit/composables/thumbnail'
- import { MtEdit } from '@/export'
- import { Canvg } from 'canvg'
- import html2canvas from 'html2canvas'
- import { ElMessage } from 'element-plus'
- import { nextTick, onMounted, ref } from 'vue'
- import { useRoute, useRouter } from 'vue-router'
- import DeviceBindPanel from './components/DeviceBindPanel.vue'
- const route = useRoute()
- const router = useRouter()
- const MtEditRef = ref<InstanceType<typeof MtEdit>>()
- const projectDetail = ref<WebtopoProjectDetailVO>()
- const saveLoading = ref(false)
- const getProjectId = () => {
- const id = Number(route.params.id)
- return Number.isFinite(id) && id > 0 ? id : undefined
- }
- const getLinkedDeviceIds = (detail: WebtopoProjectDetailVO) => {
- return detail.linkedDeviceIds || detail.linkedDevices?.map((item) => item.id) || []
- }
- const loadProject = async () => {
- const id = getProjectId()
- if (!id) {
- return
- }
- try {
- const data = await WebtopoProjectApi.getWebtopoProject(id)
- projectDetail.value = data
- if (data?.dataModel) {
- await nextTick()
- MtEditRef.value?.setImportJson(data.dataModel as IExportJson)
- }
- } catch {
- ElMessage.error('拓扑数据加载失败')
- }
- }
- const genThumbnailDataUrl = async (canvasId = 'mtCanvasArea') => {
- const el = document.querySelector<HTMLElement>(`#${canvasId}`)
- if (!el) {
- ElMessage.error('没有找到canvas元素,请检查!')
- return projectDetail.value?.thumbnail
- }
- const shouldRemoveSvgNodes: HTMLCanvasElement[] = []
- const svgElements = document.body.querySelectorAll<HTMLElement>(`#${canvasId} .mt-line-render`)
- for (const item of svgElements) {
- const svg = item.outerHTML.trim()
- const canvas = document.createElement('canvas')
- canvas.width = item.getBoundingClientRect().width
- canvas.height = item.getBoundingClientRect().height
- const ctx = canvas.getContext('2d')
- const v = Canvg.fromString(ctx!, svg)
- await v.render()
- if (item.style.position) {
- canvas.style.position += item.style.position
- canvas.style.left += item.style.left
- canvas.style.top += item.style.top
- }
- item.parentNode!.appendChild(canvas)
- shouldRemoveSvgNodes.push(canvas)
- }
- try {
- const width = el.offsetWidth
- const height = el.offsetHeight
- const canvas = await html2canvas(el, {
- useCORS: true,
- scale: 2,
- width,
- height,
- allowTaint: true,
- windowHeight: height,
- logging: false,
- ignoreElements: (element) => element.classList.contains('mt-line-render')
- })
- return canvas.toDataURL('image/png')
- } finally {
- shouldRemoveSvgNodes.forEach((item) => item.remove())
- }
- }
- const onPreviewClick = (exportJson: IExportJson) => {
- sessionStorage.setItem('exportJson', JSON.stringify(exportJson))
- const routeUrl = router.resolve({
- name: 'MaotuPreview'
- })
- window.open(routeUrl.href, '_blank')
- }
- const onSaveClick = async (dataModel: IExportJson) => {
- const detail = projectDetail.value
- if (!detail?.id) {
- ElMessage.error('项目信息不存在,无法保存')
- return
- }
- try {
- saveLoading.value = true
- const thumbnail = await genThumbnailDataUrl()
- const data: WebtopoProjectUpdateReqVO = {
- id: detail.id,
- projectName: detail.projectName,
- linkedDeviceIds: getLinkedDeviceIds(detail),
- remark: detail.remark,
- thumbnail,
- dataModel: JSON.stringify(dataModel)
- }
- await WebtopoProjectApi.updateWebtopoProject(data)
- projectDetail.value = {
- ...detail,
- thumbnail,
- dataModel: JSON.stringify(dataModel)
- }
- ElMessage.success('更新成功')
- } finally {
- saveLoading.value = false
- }
- }
- const onReturnClick = () => {
- router.go(-1)
- }
- const onThumbnailClick = () => {
- useGenThumbnail()
- }
- onMounted(() => {
- loadProject()
- })
- </script>
- <template>
- <div v-loading="saveLoading" class="w-1/1 h-100vh">
- <mt-edit
- ref="MtEditRef"
- :use-thumbnail="true"
- @on-preview-click="onPreviewClick"
- @on-return-click="onReturnClick"
- @on-save-click="onSaveClick"
- @on-thumbnail-click="onThumbnailClick">
- <template #deviceBind="{ item }">
- <DeviceBindPanel :item="item" :devices="projectDetail?.linkedDevices || []" />
- </template>
- </mt-edit>
- </div>
- </template>
- <style scoped></style>
|