Merge remote-tracking branch 'origin/master'
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import * as Cesium from 'cesium' |
| | | |
| | | import { onBeforeUnmount, onMounted, watch } from 'vue' |
| | | import { PublicCesium } from '@/utils/cesium/publicCesium' |
| | | import { loadJaAdminBoundary, removeJaAdminBoundary } from '@/utils/cesium/adminBoundary' |
| | |
| | | }) |
| | | } |
| | | |
| | | const zoomToAdminBoundary = async () => { |
| | | if (!viewer) return |
| | | const resolveSources = () => { |
| | | if (adminBoundarySources) return adminBoundarySources |
| | | const boundarySource = viewer.dataSources.getByName(ADMIN_BOUNDARY_NAMES.boundary)?.[0] ?? null |
| | | const lineSource = viewer.dataSources.getByName(ADMIN_BOUNDARY_NAMES.line)?.[0] ?? null |
| | | const labelSource = viewer.dataSources.getByName(ADMIN_BOUNDARY_NAMES.label)?.[0] ?? null |
| | | if (boundarySource || lineSource || labelSource) { |
| | | adminBoundarySources = { boundarySource, lineSource, labelSource } |
| | | } |
| | | return adminBoundarySources |
| | | } |
| | | let sources = resolveSources() |
| | | if (!sources?.boundarySource) { |
| | | sources = await loadJaAdminBoundary(viewer, { zoomTo: false }) |
| | | adminBoundarySources = sources |
| | | } |
| | | const target = sources?.boundarySource |
| | | if (!target) return |
| | | await viewer.flyTo(target, { |
| | | duration: 0, |
| | | offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-75), 0), |
| | | }) |
| | | } |
| | | |
| | | const getMap = () => ({ viewer, publicCesium: viewInstance }) |
| | | const getViewer = () => viewer |
| | | const getPublicCesium = () => viewInstance |
| | | |
| | | defineExpose({ getMap, getViewer, getPublicCesium, setAdminBoundaryVisible }) |
| | | defineExpose({ getMap, getViewer, getPublicCesium, setAdminBoundaryVisible, zoomToAdminBoundary }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | const formRef = ref(null) // 表单实例 |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = defineModel() // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const dialogMode = ref() // 弹框模式 |
| | | const submitting = ref(false) // 提交中 |
| | | const readonly = computed(() => dialogMode.value === 'view') |
| | | const route = useRoute() |
| | |
| | | :terrain="true" |
| | | :layer-mode="4" |
| | | :boundary="false" |
| | | :zoom-to-boundary="dialogMode === 'add'" |
| | | /> |
| | | </div> |
| | | <div class="right-container"> |
| | |
| | | import * as Cesium from 'cesium' |
| | | import { fwAreaDivideDetailApi, fwAreaDivideListApi } from '../partition/partitionApi' |
| | | import { buildEllipsePositions } from '@/utils/cesium/shapeTools' |
| | | import { cartesian3Convert } from '@/utils/cesium/mapUtil' |
| | | import { saveOperationLog } from '@ztzf/apis' |
| | | import { useRoute } from 'vue-router' |
| | | import { AREA_TYPE_STYLE_MAP, BUFFER_LEVEL_STYLES, DEFAULT_AREA_STYLE } from '@ztzf/constants' |
| | |
| | | const formRef = ref(null) // 表单实例 |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = defineModel() // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const dialogMode = ref() // 弹框模式 |
| | | const submitting = ref(false) // 提交中 |
| | | const readonly = computed(() => dialogMode.value === 'view') |
| | | const titleEnum = ref({ edit: '编辑', view: '查看', add: '新增' }) |
| | |
| | | return { lng: Number(lng), lat: Number(lat), height } |
| | | } |
| | | |
| | | function resolveLngLatPoint(point) { |
| | | if (!point) return null |
| | | const lng = point?.lng ?? point?.longitude |
| | | const lat = point?.lat ?? point?.latitude |
| | | if (Number.isFinite(Number(lng)) && Number.isFinite(Number(lat))) { |
| | | return { |
| | | lng: Number(lng), |
| | | lat: Number(lat), |
| | | height: Number.isFinite(Number(point?.height)) ? Number(point.height) : 0, |
| | | } |
| | | } |
| | | if (!viewer || !Number.isFinite(point?.x) || !Number.isFinite(point?.y) || !Number.isFinite(point?.z)) { |
| | | return null |
| | | } |
| | | const val = cartesian3Convert(point, viewer) |
| | | return { |
| | | lng: val.longitude, |
| | | lat: val.latitude, |
| | | height: Number.isFinite(val.height) ? val.height : 0, |
| | | } |
| | | } |
| | | |
| | | function buildShapePositions(points = []) { |
| | | const normalized = points.map(normalizeShapePoint).filter(Boolean) |
| | | return normalized.map(point => Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.height)) |
| | |
| | | |
| | | function getAreaTypeStyle(areaType) { |
| | | return AREA_TYPE_STYLE_MAP?.[String(areaType)] || DEFAULT_AREA_STYLE |
| | | } |
| | | |
| | | function resolveControlPoints(meta, drawType) { |
| | | if (!meta) return [] |
| | | if (Array.isArray(meta.controlPoints) && meta.controlPoints.length) { |
| | | return meta.controlPoints.map(resolveLngLatPoint).filter(Boolean) |
| | | } |
| | | if (drawType === 'buffer') { |
| | | return [resolveLngLatPoint(meta.center)].filter(Boolean) |
| | | } |
| | | if (drawType === 'ellipse') { |
| | | return [meta.center, meta.majorPoint, meta.minorPoint].map(resolveLngLatPoint).filter(Boolean) |
| | | } |
| | | return [] |
| | | } |
| | | |
| | | function parseGeomJson(geomJson) { |
| | |
| | | }) |
| | | } |
| | | |
| | | function pushRadiusBoundingPoints(positions, center, radius) { |
| | | if (!center || !Number.isFinite(Number(radius)) || radius <= 0) return |
| | | const resolved = resolveLngLatPoint(center) || {} |
| | | const lng = Number(resolved.lng ?? resolved.longitude) |
| | | const lat = Number(resolved.lat ?? resolved.latitude) |
| | | if (!Number.isFinite(lng) || !Number.isFinite(lat)) return |
| | | const baseLat = Cesium.Math.toRadians(lat) |
| | | const earthRadius = Cesium.Ellipsoid.WGS84.maximumRadius |
| | | const deltaLat = radius / earthRadius |
| | | const deltaLng = radius / (earthRadius * Math.max(Math.cos(baseLat), 0.000001)) |
| | | const points = [ |
| | | { lng: Cesium.Math.toDegrees(Cesium.Math.toRadians(lng) + deltaLng), lat }, |
| | | { lng: Cesium.Math.toDegrees(Cesium.Math.toRadians(lng) - deltaLng), lat }, |
| | | { lng, lat: Cesium.Math.toDegrees(baseLat + deltaLat) }, |
| | | { lng, lat: Cesium.Math.toDegrees(baseLat - deltaLat) }, |
| | | ] |
| | | points.forEach(point => { |
| | | positions.push(Cesium.Cartesian3.fromDegrees(point.lng, point.lat, resolved.height || 0)) |
| | | }) |
| | | } |
| | | |
| | | function collectSelectedAreaPositions() { |
| | | const positions = [] |
| | | if (!viewer || !selectedAreaRows.value.length) return positions |
| | | selectedAreaRows.value.forEach(area => { |
| | | const shapes = resolveAreaShapes(area) |
| | | shapes.forEach(shape => { |
| | | let points = getShapeDisplayPoints(shape) |
| | | if (!Array.isArray(points) || !points.length) { |
| | | points = resolveControlPoints(shape?.meta, shape?.drawType) |
| | | } |
| | | if (Array.isArray(points) && points.length) { |
| | | points.forEach(point => { |
| | | const resolved = resolveLngLatPoint(point) |
| | | const normalized = normalizeShapePoint(resolved) |
| | | if (!normalized) return |
| | | positions.push( |
| | | Cesium.Cartesian3.fromDegrees(normalized.lng, normalized.lat, normalized.height) |
| | | ) |
| | | }) |
| | | } |
| | | if (shape?.drawType === 'buffer' && shape?.meta?.center && Array.isArray(shape?.meta?.bufferRadii)) { |
| | | const maxRadius = Math.max(...shape.meta.bufferRadii.filter(item => Number.isFinite(item))) |
| | | pushRadiusBoundingPoints(positions, shape.meta.center, maxRadius) |
| | | } |
| | | if (shape?.drawType === 'ellipse' && shape?.meta?.center) { |
| | | const major = Number(shape?.meta?.semiMajor) |
| | | const minor = Number(shape?.meta?.semiMinor) |
| | | const radius = Number.isFinite(major) && Number.isFinite(minor) ? Math.max(major, minor) : null |
| | | pushRadiusBoundingPoints(positions, shape.meta.center, radius) |
| | | } |
| | | }) |
| | | }) |
| | | return positions |
| | | } |
| | | |
| | | function fitViewToSelectedAreas() { |
| | | if (!viewer || !selectedAreaRows.value.length) return |
| | | const positions = collectSelectedAreaPositions() |
| | | if (positions.length < 2) return |
| | | const boundingSphere = Cesium.BoundingSphere.fromPoints(positions) |
| | | const range = Math.max(boundingSphere.radius * 2.4, 200) |
| | | viewer.camera.flyToBoundingSphere(boundingSphere, { |
| | | duration: 0, |
| | | offset: new Cesium.HeadingPitchRange(viewer.camera.heading, Cesium.Math.toRadians(-90), range), |
| | | }) |
| | | } |
| | | |
| | | watch(() => selectedAreaRows.value, renderSelectedAreas) |
| | | watch( |
| | | () => visible.value, |
| | |
| | | await nextTick() |
| | | initMap() |
| | | await getAreaList() |
| | | if (dialogMode.value !== 'add') { |
| | | if (dialogMode.value === 'add') { |
| | | console.log(111) |
| | | |
| | | mapRef.value?.zoomToAdminBoundary?.() |
| | | } else { |
| | | await loadDetail() |
| | | } |
| | | await nextTick() |
| | | await syncAreaSelection() |
| | | await nextTick() |
| | | fitViewToSelectedAreas() |
| | | } |
| | | defineExpose({ |
| | | open, |
| | |
| | | :terrain="true" |
| | | :layer-mode="4" |
| | | :boundary="false" |
| | | :zoom-to-boundary="dialogMode === 'add'" |
| | | /> |
| | | </div> |
| | | <div class="right-container"> |
| | |
| | | import { useRoute } from 'vue-router' |
| | | import { fwAreaDivideDetailApi, fwAreaDivideListApi } from '../partition/partitionApi' |
| | | import { buildEllipsePositions } from '@/utils/cesium/shapeTools' |
| | | import { cartesian3Convert } from '@/utils/cesium/mapUtil' |
| | | import { AREA_TYPE_STYLE_MAP, BUFFER_LEVEL_STYLES, DEFAULT_AREA_STYLE } from '@ztzf/constants' |
| | | |
| | | // 初始化表单数据 |
| | |
| | | const formRef = ref(null) // 表单实例 |
| | | const formData = ref(initForm()) // 表单数据 |
| | | const visible = defineModel() // 弹框显隐 |
| | | const dialogMode = ref('add') // 弹框模式 |
| | | const dialogMode = ref() // 弹框模式 |
| | | const submitting = ref(false) // 提交中 |
| | | const readonly = computed(() => dialogMode.value === 'view') |
| | | const titleEnum = ref({ edit: '编辑', view: '查看', add: '新增' }) |
| | |
| | | return normalized.map(point => Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.height)) |
| | | } |
| | | |
| | | function resolveLngLatPoint(point) { |
| | | if (!point) return null |
| | | const lng = point?.lng ?? point?.longitude |
| | | const lat = point?.lat ?? point?.latitude |
| | | if (Number.isFinite(Number(lng)) && Number.isFinite(Number(lat))) { |
| | | return { |
| | | lng: Number(lng), |
| | | lat: Number(lat), |
| | | height: Number.isFinite(Number(point?.height)) ? Number(point.height) : 0, |
| | | } |
| | | } |
| | | if (!viewer || !Number.isFinite(point?.x) || !Number.isFinite(point?.y) || !Number.isFinite(point?.z)) { |
| | | return null |
| | | } |
| | | const val = cartesian3Convert(point, viewer) |
| | | return { |
| | | lng: val.longitude, |
| | | lat: val.latitude, |
| | | height: Number.isFinite(val.height) ? val.height : 0, |
| | | } |
| | | } |
| | | |
| | | function getShapeDisplayPoints(shape) { |
| | | if (Array.isArray(shape?.displayPoints) && shape.displayPoints.length) { |
| | | return shape.displayPoints |
| | |
| | | } |
| | | }) |
| | | .filter(Boolean) |
| | | } |
| | | |
| | | function pushRadiusBoundingPoints(positions, center, radius) { |
| | | if (!center || !Number.isFinite(Number(radius)) || radius <= 0) return |
| | | const resolved = resolveLngLatPoint(center) || {} |
| | | const lng = Number(resolved.lng ?? resolved.longitude) |
| | | const lat = Number(resolved.lat ?? resolved.latitude) |
| | | if (!Number.isFinite(lng) || !Number.isFinite(lat)) return |
| | | const baseLat = Cesium.Math.toRadians(lat) |
| | | const earthRadius = Cesium.Ellipsoid.WGS84.maximumRadius |
| | | const deltaLat = radius / earthRadius |
| | | const deltaLng = radius / (earthRadius * Math.max(Math.cos(baseLat), 0.000001)) |
| | | const points = [ |
| | | { lng: Cesium.Math.toDegrees(Cesium.Math.toRadians(lng) + deltaLng), lat }, |
| | | { lng: Cesium.Math.toDegrees(Cesium.Math.toRadians(lng) - deltaLng), lat }, |
| | | { lng, lat: Cesium.Math.toDegrees(baseLat + deltaLat) }, |
| | | { lng, lat: Cesium.Math.toDegrees(baseLat - deltaLat) }, |
| | | ] |
| | | points.forEach(point => { |
| | | positions.push(Cesium.Cartesian3.fromDegrees(point.lng, point.lat, resolved.height || 0)) |
| | | }) |
| | | } |
| | | |
| | | function collectSceneAreaPositions() { |
| | | const positions = [] |
| | | if (!viewer || !areaList.value.length) return positions |
| | | areaList.value.forEach(area => { |
| | | const shapes = resolveAreaShapes(area) |
| | | shapes.forEach(shape => { |
| | | const points = getShapeDisplayPoints(shape) |
| | | if (Array.isArray(points) && points.length) { |
| | | points.forEach(point => { |
| | | const resolved = resolveLngLatPoint(point) |
| | | const normalized = normalizeShapePoint(resolved) |
| | | if (!normalized) return |
| | | positions.push( |
| | | Cesium.Cartesian3.fromDegrees(normalized.lng, normalized.lat, normalized.height) |
| | | ) |
| | | }) |
| | | } |
| | | if (shape?.drawType === 'buffer' && shape?.meta?.center && Array.isArray(shape?.meta?.bufferRadii)) { |
| | | const maxRadius = Math.max(...shape.meta.bufferRadii.filter(item => Number.isFinite(item))) |
| | | pushRadiusBoundingPoints(positions, shape.meta.center, maxRadius) |
| | | } |
| | | if (shape?.drawType === 'ellipse' && shape?.meta?.center) { |
| | | const major = Number(shape?.meta?.semiMajor) |
| | | const minor = Number(shape?.meta?.semiMinor) |
| | | const radius = Number.isFinite(major) && Number.isFinite(minor) ? Math.max(major, minor) : null |
| | | pushRadiusBoundingPoints(positions, shape.meta.center, radius) |
| | | } |
| | | }) |
| | | }) |
| | | return positions |
| | | } |
| | | |
| | | function fitViewToSceneAreas() { |
| | | if (!viewer || !areaList.value.length) return |
| | | const positions = collectSceneAreaPositions() |
| | | if (positions.length < 2) return |
| | | const boundingSphere = Cesium.BoundingSphere.fromPoints(positions) |
| | | const range = Math.max(boundingSphere.radius * 2.4, 200) |
| | | viewer.camera.flyToBoundingSphere(boundingSphere, { |
| | | duration: 0, |
| | | offset: new Cesium.HeadingPitchRange(viewer.camera.heading, Cesium.Math.toRadians(-90), range), |
| | | }) |
| | | } |
| | | |
| | | function renderSceneAreas() { |
| | |
| | | await nextTick() |
| | | initMap() |
| | | await getSceneConfigList() |
| | | if (dialogMode.value !== 'add') { |
| | | if (dialogMode.value === 'add') { |
| | | mapRef.value?.zoomToAdminBoundary?.() |
| | | } else { |
| | | await loadDetail() |
| | | } |
| | | await nextTick() |
| | | setMapPoint(formData.value.longitude, formData.value.latitude) |
| | | await loadAreaList(formData.value.defenseSceneId) |
| | | fitViewToSceneAreas() |
| | | } |
| | | |
| | | onMounted(() => { |
| | |
| | | <span class="required-star">*</span> |
| | | 巡查任务类型 |
| | | </template> |
| | | <template v-slot="{ row }"> |
| | | <template v-slot="{ row, $index }"> |
| | | <el-select |
| | | class="gd-select" |
| | | popper-class="gd-select-popper" |
| | | v-model="row.patrolTaskType" |
| | | placeholder="请选择" |
| | | disabled |
| | | @change="handlePatrolTaskTypeChange($index, $event)" |
| | | > |
| | | <el-option |
| | | v-for="item in dictObj.workOrderType" |
| | |
| | | workOrderList.value = res?.data?.data?.records ?? [] |
| | | } |
| | | |
| | | // 处理巡查任务类型变化 |
| | | async function handlePatrolTaskTypeChange(index, skilledTaskType) { |
| | | // 清空该行已选择的飞手 |
| | | taskList.value[index].recommendFlyerName = '' |
| | | // 获取对应的飞手列表 |
| | | await getFlyerList(index, skilledTaskType) |
| | | } |
| | | |
| | | // 获取飞手列表 |
| | | async function getFlyerList(index, skilledTaskType) { |
| | | const res = await gdFlyerPageApi({ |
| | |
| | | </el-row> |
| | | <div class="detail-title" :style="{ marginTop: pxToRem(20) }">已选设备</div> |
| | | <el-table class="setHeight gd-dialog-table" ref="deviceTableRef" :data="deviceList" row-key="id"> |
| | | <el-table-column type="index" label="序号" /> |
| | | <el-table-column prop="nickname" label="设备名称" /> |
| | | <el-table-column prop="deviceName" label="设备型号" /> |
| | | <el-table-column prop="devicePayload" label="设备负载" /> |
| | |
| | | /> |
| | | </div> |
| | | <div class="rightBox" v-if="!dialogReadonly"> |
| | | <div class="detail-title"><span class="required-star" v-if="!dialogReadonly">*</span>推荐设备</div> |
| | | <div class="detail-title"> |
| | | <span class="required-star" v-if="!dialogReadonly">*</span> |
| | | 推荐设备 |
| | | </div> |
| | | <el-table |
| | | class="separateTable" |
| | | :empty-text="(formData.deviceLoadDemand && pointList.length) ? '暂无数据' : '请先选择设备需求并在地图上绘制工单范围'" |
| | | :empty-text=" |
| | | formData.deviceLoadDemand && pointList.length ? '暂无数据' : '请先选择设备需求并在地图上绘制工单范围' |
| | | " |
| | | ref="deviceTableRef" |
| | | :data="(formData.deviceLoadDemand && pointList.length) ? deviceList : []" |
| | | :data="formData.deviceLoadDemand && pointList.length ? deviceList : []" |
| | | row-key="id" |
| | | @selection-change="handleDeviceSelectionChange" |
| | | > |
| | |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <el-button |
| | | v-if="['11', '21', '23','31', '60'].includes(gdStatus)" |
| | | @click="viewDescription" |
| | | color="#F2F3F5" |
| | | > |
| | | {{ gdStatusObj[gdStatus].reason }} |
| | | <el-button v-if="['11', '21', '23', '31', '60'].includes(gdStatus)" @click="viewDescription" color="#F2F3F5"> |
| | | {{ gdStatusObj[gdStatus]?.reason }} |
| | | </el-button> |
| | | |
| | | <template v-if="!suddenlyEdit"> |
| | |
| | | <el-button |
| | | color="#4C34FF" |
| | | @click="requestModification" |
| | | v-if="['20'].includes(gdStatus) && permission.order_applyNegotiation" |
| | | v-if="['20'].includes(gdStatus) && permission.order_applyEdit" |
| | | > |
| | | 申请修改 |
| | | </el-button> |
| | |
| | | </template> |
| | | <template v-if="permission.order_controlCancel"> |
| | | <el-button v-if="gdStatus === '21'" @click="statusChange(6)" color="#F2F3F5">驳回</el-button> |
| | | <el-button v-if="gdStatus === '21'" @click="statusChange(5)" color="#4C34FF">同意</el-button> |
| | | <el-button v-if="gdStatus === '21'" @click="statusChange(5)" color="#4C34FF">通过</el-button> |
| | | </template> |
| | | <el-button v-if="gdStatus === '30' && permission.order_applyNegotiation" @click="addDescription" color="#4C34FF"> |
| | | 协商修改 |
| | |
| | | const hasPatrolTaskList = computed(() => ['30', '40', '50', '60'].includes(String(formData.value.workOrderStatus))) |
| | | |
| | | const gdStatusObj = { |
| | | '10': { reason: '拒单原因', operationType: '2' }, |
| | | '10': { reason: '拒单原因', operationType: '2', title: '拒绝接单' }, |
| | | '11': { reason: '拒单原因' }, |
| | | '20': { reason: '取消原因', operationType: '3' }, |
| | | '20': { reason: '原因', operationType: '3',title:'申请取消' }, |
| | | '21': { reason: '取消原因' }, |
| | | '23': { reason: '取消原因' }, |
| | | '30': { reason: '协商修改原因', operationType: '9' }, |
| | | '31': { reason: '协商修改原因' }, |
| | | '30': { reason: '修改原因', operationType: '9',title:'协商修改' }, |
| | | '31': { reason: '修改原因' }, |
| | | '40': { reason: '' }, |
| | | '50': { reason: '情况说明', operationType: '11' }, |
| | | '50': { reason: '情况说明', operationType: '11',title:'结算' }, |
| | | '60': { reason: '情况说明' }, |
| | | } |
| | | |
| | |
| | | row: formData.value, |
| | | type: gdStatusObj[gdStatus.value].operationType, |
| | | formLabel: gdStatusObj[gdStatus.value].reason, |
| | | title: gdStatusObj[gdStatus.value]?.title || '新增' |
| | | }) |
| | | }) |
| | | } |
| | |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .separateTable{ |
| | | .separateTable { |
| | | height: 0; |
| | | flex: 1; |
| | | :deep(){ |
| | | .el-scrollbar__view{ |
| | | :deep() { |
| | | .el-scrollbar__view { |
| | | height: 100%; |
| | | } |
| | | .el-table__empty-text{ |
| | | .el-table__empty-text { |
| | | line-height: normal; |
| | | } |
| | | } |
| | |
| | | <el-dialog |
| | | class="gd-dialog" |
| | | v-model="visible" |
| | | :title="titleEnum[dialogMode]" |
| | | :title="dialogTitle" |
| | | @closed="visible = false" |
| | | destroy-on-close |
| | | :close-on-click-modal="false" |
| | |
| | | } |
| | | |
| | | let formLabelStr = ref('原因') |
| | | let dialogTitle = ref('新增') |
| | | |
| | | |
| | | // 操作类型:1接单,2拒接接单,3申请取消,4申请修改, 5同意取消 6不同意取消 7.同意修改 8.不同意修改 9.协商修改 |
| | | async function open({ mode = 'add', row, formLabel, type } = {}) { |
| | | async function open({ mode = 'add', row, formLabel, type,title } = {}) { |
| | | dialogMode.value = mode |
| | | formLabelStr.value = formLabel |
| | | dialogTitle.value = dialogMode.value === 'add' ? title : '查看' |
| | | formData.value = { |
| | | workOrderId: row.id, |
| | | operationType: type, |