Merge branch 'refs/heads/feature/v6.0/6.0.3' into feature/v6.0/6.0.4
33 files modified
1 files added
| | |
| | | # 算法仓库图片地址 |
| | | VITE_APP_PICTURE_URL = https://wrj.shuixiongit.com/aiskyminio/cloud-bucket |
| | | |
| | | # 行政区划存放地址 |
| | | VITE_APP_REGION_URL = https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_region |
| | | # 是否在打包时开启压缩,支持 gzip 和 brotli |
| | | VITE_BUILD_COMPRESS = gzip |
| | | |
| | |
| | | } |
| | | |
| | | // 注销 |
| | | export const deviceOffline = (dockSn) => { |
| | | export const deviceOffline = (dockSn, deleteFlag) => { |
| | | return request({ |
| | | url: `/drone-device-core/manage/api/v1/devices/deviceOffline?dockSn=${dockSn}`, |
| | | url: `/drone-device-core/manage/api/v1/devices/deviceOffline?dockSn=${dockSn}&deleteFlag=${deleteFlag}`, |
| | | method: 'get', |
| | | }) |
| | | } |
| | |
| | | method: 'post', |
| | | data: param |
| | | }) |
| | | } |
| | | |
| | | export const devicesUpAndDown = (param) => { |
| | | return request({ |
| | | url: `/drone-device-core/manage/api/v1/devices/upAndDown`, |
| | | method: 'post', |
| | | data: param |
| | | }) |
| | | } |
| | |
| | | }) |
| | | } |
| | | |
| | | export const getDeviceRegion = params => { |
| | | export const getDeviceRegion = data => { |
| | | return request({ |
| | | url: '/drone-device-core/manage/api/v1/devices/getDeviceRegion', |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | export const getDeviceRegionByPost = data => { |
| | | return request({ |
| | | url: '/drone-device-core/manage/api/v1/devices/getDeviceRegion', |
| | | method: 'post', |
| | | data, |
| | | method: 'post', |
| | | data:{ hidden_flag:0, ...data }, |
| | | }) |
| | | } |
| | | |
| | |
| | | }) |
| | | } |
| | | |
| | | export const getDeviceRegion = params => { |
| | | export const getDeviceRegion = data => { |
| | | return request({ |
| | | url: '/drone-device-core/manage/api/v1/devices/getDeviceRegion', |
| | | method: 'get', |
| | | params, |
| | | method: 'post', |
| | | data:{ hidden_flag:0, ...data }, |
| | | }) |
| | | } |
| | | |
| | |
| | | method: 'post', |
| | | data: data, |
| | | }) |
| | | } |
| | | } |
| New file |
| | |
| | | <template> |
| | | <el-dialog class="ztzf-dialog-mange" append-to-body v-model="props.isShowView" :title="props.title" |
| | | :width="props.width" :close-on-click-modal="false" :destroy-on-close="true" @close="cancel"> |
| | | <slot name="default" /> |
| | | <template #footer v-if="props.addEditView !== 'view'"> |
| | | <div class="dialog-footer"> |
| | | <el-button v-if="props.addEditView === 'add'" type="primary" @click="submit" :icon="CirclePlus">保存</el-button> |
| | | <el-button v-else type="primary" @click="submit" :icon="CircleCheck">确认</el-button> |
| | | <el-button @click="cancel" :icon="CircleClose">取消</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | <script setup> |
| | | import { ElMessage } from 'element-plus' |
| | | import { Delete, Search, CircleCheck, CircleClose, CirclePlus } from '@element-plus/icons-vue' |
| | | import { defineEmits } from 'vue'; |
| | | |
| | | const emit = defineEmits(['cancel', 'confirm']); |
| | | |
| | | const props = defineProps({ |
| | | width: { |
| | | type: String, |
| | | default: '800' |
| | | }, |
| | | isShowView: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | addEditView: { |
| | | type: String, |
| | | default: 'add' |
| | | }, |
| | | title:{ |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }) |
| | | |
| | | function submit() { |
| | | emit('submit') |
| | | } |
| | | function cancel() { |
| | | emit('cancel') |
| | | } |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | </style> |
| | |
| | | index: true, |
| | | selection: true, |
| | | viewBtn: true, |
| | | menuWidth: 250, |
| | | menuWidth: 280, |
| | | dialogWidth: 880, |
| | | dialogClickModal: false, |
| | | |
| | |
| | | index: true, |
| | | selection: true, |
| | | viewBtn: true, |
| | | menuWidth: 250, |
| | | menuWidth: 280, |
| | | dialogWidth: 880, |
| | | dialogClickModal: false, |
| | | |
| | |
| | | <el-dropdown class="avue-tags__menu"> |
| | | <el-button type="primary" style="background: #409eff;border-color: #409eff"> |
| | | {{ $t('tagsView.menu') }} |
| | | <i class="el-icon-arrow-down el-icon--right"></i> |
| | | <!-- <i class="el-icon-arrow-down el-icon--right"></i> --> |
| | | </el-button> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | |
| | | @import './variables.scss'; |
| | | @import './base.scss'; |
| | | @import './tool.scss'; |
| | | @import './element-ui.scss'; |
| | | a { |
| | | text-decoration: none; |
| | | color: #333; |
| | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | //======以下针对表格功能 增删查改样式和弹窗========= |
| | | .ztzf-dialog-mange { |
| | | .el-dialog__body { |
| | | padding: 2rem 2rem 4rem; |
| | | flex: 1; |
| | | overflow: scroll; |
| | | border-top: 0.1rem solid #f0f0f0; |
| | | } |
| | | .el-dialog__footer { |
| | | z-index: 2; |
| | | display: block; |
| | | padding: 1rem 1.6rem; |
| | | box-sizing: border-box; |
| | | border-top: 0.1rem solid #f0f0f0; |
| | | width: 100%; |
| | | position: absolute; |
| | | left: 0; |
| | | bottom: 0; |
| | | background-color: #fff; |
| | | text-align: right; |
| | | } |
| | | } |
| | | .ztzf-search-mange { |
| | | height: 40px; |
| | | .search-contain { |
| | | display: flex;justify-content: space-between; |
| | | } |
| | | } |
| | | .ztzf-form-mange { |
| | | .el-form-item { |
| | | width: 300px; |
| | | :deep(.el-form-item__label) { |
| | | width: 120px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .ztzf-table-mange { |
| | | th.el-table__cell { |
| | | color: rgba(0, 0, 0, .85); |
| | | background-color: #fafafa; |
| | | } |
| | | } |
| | | |
| | | .table-view-mange { |
| | | width: 100%; |
| | | border-top: 0.1rem solid #ebeef5; |
| | | border-left: 0.1rem solid #ebeef5; |
| | | margin-left: 0; |
| | | margin-right: 0; |
| | | .el-col { |
| | | padding-left: 0; |
| | | padding-right: 0; |
| | | margin-bottom: 0; |
| | | height: 32px; |
| | | line-height: 32px; |
| | | border-right: 0.1rem solid #ebeef5; |
| | | text-align: center; |
| | | align-items: center; |
| | | .el-input__wrapper { |
| | | box-shadow: none !important; |
| | | border-bottom: 0.1rem solid #ebeef5; |
| | | } |
| | | } |
| | | .label { |
| | | color: #909399; |
| | | box-sizing: border-box; |
| | | background: #fafafa; |
| | | } |
| | | } |
| | |
| | | speed: 5 |
| | | }) |
| | | |
| | | let arrowLineMaterialPropertyOrange = new ArrowLineMaterialProperty({ |
| | | color: new Cesium.Color(255 / 255, 185 / 255, 58 / 255, 1), |
| | | directionColor: new Cesium.Color(1, 1, 1, 1), |
| | | outlineColor: new Cesium.Color(1, 1, 1, 1), |
| | | outlineWidth: 0, |
| | | speed: 5, |
| | | }) |
| | | |
| | | let arrowLineMaterialPropertyGreen = new ArrowLineMaterialProperty({ |
| | | color: new Cesium.Color(6 / 255, 217 / 255, 87 / 255, 1), |
| | | directionColor: new Cesium.Color(1, 1, 1, 1), |
| | | outlineColor: new Cesium.Color(1, 1, 1, 1), |
| | | outlineWidth: 0, |
| | | speed: 5, |
| | | }) |
| | | |
| | | // 记录index |
| | | let indexLog = 0 |
| | | // 颜色 |
| | | function getLineColor(lineNumber) { |
| | | // 颜色顺序: 蓝(0), 黄(1), 绿(2) |
| | | const colors = [arrowLineMaterialProperty, arrowLineMaterialPropertyOrange, arrowLineMaterialPropertyGreen] |
| | | // 计算颜色索引 (从0开始) |
| | | const colorIndex = (lineNumber - 1) % 3 |
| | | // 返回对应颜色 |
| | | return colors[colorIndex] |
| | | } |
| | | |
| | | let runningLineMaterial = new LineTrailMaterial({ |
| | | color: Cesium.Color.fromCssColorString('#1FFF69'), |
| | | opacity: 1, |
| | |
| | | * @param {*} viewer |
| | | */ |
| | | initCreateRoute (viewer) { |
| | | indexLog = 0 |
| | | this.viewer = viewer |
| | | } |
| | | |
| | |
| | | */ |
| | | async drawPointRoute (lineObj, missionConfig, dronePosition, data, startPoint, isShowDock, isShowPointBillboard, wayline_type) { |
| | | const { positionArray, filePositions } = this.disposeData(lineObj, missionConfig, dronePosition, data, startPoint, wayline_type) |
| | | |
| | | |
| | | const droneTransformPosition = Cesium.Cartesian3.fromDegrees( |
| | | Number(dronePosition.longitude), |
| | | Number(dronePosition.latitude), |
| | |
| | | |
| | | // 路径线 |
| | | let polyline |
| | | |
| | | |
| | | if (this.type === 'clusterScheduling') { |
| | | filePositions.forEach((item, index) => { |
| | |
| | | polyline: { |
| | | width: 4, |
| | | positions: positionArray, |
| | | material: arrowLineMaterialProperty, |
| | | material: getLineColor(indexLog), |
| | | clampToGround: false, |
| | | }, |
| | | |
| | |
| | | * @returns {} {positionArray: 带拼接点位置, filePositions:光航线点位置} |
| | | */ |
| | | disposeData (lineObj, missionConfig, dronePosition, data, startPoint, wayline_type) { |
| | | indexLog = indexLog + 1 |
| | | const { device_sn } = data |
| | | |
| | | const executeHeightMode = lineObj.executeHeightMode === "WGS84" |
| | |
| | | <template> |
| | | <div class="algorithmMange"> |
| | | <div class="search-box"> |
| | | <div class="ztzf-search-mange"> |
| | | <el-form :model="params" inline> |
| | | <div style="display: flex;justify-content: space-between;"> |
| | | <div class="search-contain"> |
| | | <div> |
| | | <el-form-item label="算法名称:"> |
| | | <el-input v-model="params.algName" placeholder="请输入算法名称" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="算法类型:"> |
| | | <el-select class="ztzf-select" :teleported="false" v-model="params.algTypeCode" placeholder="请选择算法类型" clearable> |
| | | <el-option v-for="item in sfTypes" :key="item.id" :label="item.dictValue" :value="item.dictKey" ></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </div> |
| | | <div> |
| | | <el-form-item class="btns"> |
| | | <el-button type="primary" @click="getList">搜索</el-button> |
| | | <el-button @click="cancelSearch">清空</el-button> |
| | | <el-input v-model="params.algName" placeholder="请输入算法名称" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="算法类型:"> |
| | | <el-select class="ztzf-select" :teleported="false" v-model="params.algTypeCode" placeholder="请选择算法类型" clearable> |
| | | <el-option v-for="item in sfTypes" :key="item.id" :label="item.dictValue" :value="item.dictKey" ></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </div> |
| | | <div class="btns"> |
| | | <el-button type="primary" @click="getList" :icon="Search">搜索</el-button> |
| | | <el-button @click="cancelSearch" :icon="Delete">清空</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | </el-form> |
| | | </div> |
| | | <div class="mange-table"> |
| | | <el-table border :data="tableList" class="custom-header"> |
| | | <el-table border :data="tableList" class="ztzf-table-mange"> |
| | | <el-table-column label="序号" type="index" width="60"></el-table-column> |
| | | <el-table-column prop="model_name" label="算法名称" align="center" show-overflow-tooltip></el-table-column> |
| | | <el-table-column prop="alg_type" label="算法类型" align="center"></el-table-column> |
| | |
| | | </div> |
| | | <div class="pagination"> |
| | | <el-pagination class="ztzf-pagination" popper-class="custom-pagination-dropdown" background |
| | | :page-sizes="[10, 20, 30, 40, 50, 100]" :size="size" v-model:current-page="params.current" |
| | | :page-sizes="[10, 20, 30, 40, 50, 100]" :size="params.size" v-model:current-page="params.current" |
| | | v-model:page-size="params.size" layout="total, sizes, prev, pager, next, jumper" :total="total" |
| | | @size-change="handleSizeChange" @current-change="handleCurrentChange" /> |
| | | </div> |
| | | </div> |
| | | <el-dialog class="ztzf-dialog" append-to-body v-model="isShowView" title="查看" |
| | | :width="pxToRem(600)" :close-on-click-modal="false" :destroy-on-close="true"> |
| | | <div class="content"> |
| | | <table class="view-table" border> |
| | | <tr> |
| | | <td class="label">算法名称</td> |
| | | <td class="value">{{ rowView.model_name }}</td> |
| | | <td class="label">算法类型</td> |
| | | <td class="value">{{ rowView.alg_type }}</td> |
| | | </tr> |
| | | <tr> |
| | | <td class="label">最低准确率</td> |
| | | <td class="value">{{ rowView.qua_rate }}</td> |
| | | <td class="label">最高准确率</td> |
| | | <td class="value">{{ rowView.pass_rate }}</td> |
| | | </tr> |
| | | <tr> |
| | | <td class="label">事件生成类型</td> |
| | | <td class="value">{{ rowView.event_type == 0 ? '常规类' : '紧急类' }}</td> |
| | | <td class="label">算法描述</td> |
| | | <td class="value">{{ rowView.remark }}</td> |
| | | </tr> |
| | | </table> |
| | | </div> |
| | | </el-dialog> |
| | | <el-dialog class="ztzf-dialog" append-to-body v-model="isShowEditView" title="编辑" |
| | | :width="pxToRem(800)" :close-on-click-modal="false" :destroy-on-close="true"> |
| | | <div class="content-edit"> |
| | | <el-form ref="ruleFormRef" :model="editParams" :rules="rules" inline> |
| | | <commonDialog :isShowView="isShowViewTest" width="1000" title="查看" addEditView="view" @cancel="isShowViewTest = false"> |
| | | <template #default> |
| | | <el-row :gutter="0" class="table-view-mange"> |
| | | <el-col :span="6" class="label">算法名称</el-col> |
| | | <el-col :span="6">{{ rowView.model_name }}</el-col> |
| | | <el-col :span="6" class="label">算法类型</el-col> |
| | | <el-col :span="6">{{ rowView.alg_type }}</el-col> |
| | | </el-row> |
| | | <el-row :gutter="0" class="table-view-mange"> |
| | | <el-col :span="6" class="label">最低准确率</el-col> |
| | | <el-col :span="6">{{ rowView.qua_rate }}</el-col> |
| | | <el-col :span="6" class="label">最高准确率</el-col> |
| | | <el-col :span="6">{{ rowView.pass_rate }}</el-col> |
| | | </el-row> |
| | | <el-row :gutter="0" class="table-view-mange"> |
| | | <el-col :span="6" class="label">事件生成类型</el-col> |
| | | <el-col :span="6">{{ rowView.event_type == 0 ? '常规类' : '紧急类' }}</el-col> |
| | | <el-col :span="6" class="label"></el-col> |
| | | <el-col :span="6"></el-col> |
| | | </el-row> |
| | | <el-row :gutter="0" class="table-view-mange"> |
| | | <el-col :span="6" class="label">算法描述</el-col> |
| | | <el-col :span="18"> |
| | | <el-input v-model="rowView.remark"></el-input> |
| | | </el-col> |
| | | </el-row> |
| | | </template> |
| | | </commonDialog> |
| | | <commonDialog :isShowView="isShowEditView" title="编辑" addEditView="edit" @submit="submit(ruleFormRef)" @cancel="isShowEditView = false"> |
| | | <template #default> |
| | | <el-form class="ztzf-form-mange" ref="ruleFormRef" :model="editParams" :rules="rules" inline> |
| | | <el-form-item label="算法名称"> |
| | | <el-input v-model="editParams.model_name" disabled /> |
| | | </el-form-item> |
| | |
| | | <el-form-item label="算法描述"> |
| | | <el-input v-model="editParams.remark" placeholder="请输入算法描述" clearable /> |
| | | </el-form-item> |
| | | <div class="btns"> |
| | | <el-button type="primary" @click="submit(ruleFormRef)">确认</el-button> |
| | | <el-button @click="isShowEditView = false">取消</el-button> |
| | | </div> |
| | | </el-form> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | </commonDialog> |
| | | </template> |
| | | <script setup> |
| | | import { getAlgorithmManageList, algorithmManageEdit } from '@/api/algorithmMange/algorithmMange'; |
| | | import { getDictionaryByCode } from '@/api/system/dictbiz'; |
| | | import commonDialog from '@/components/commonDialog.vue' |
| | | import { ElMessage } from 'element-plus'; |
| | | import { Delete, Search } from '@element-plus/icons-vue' |
| | | |
| | | const total = ref(0) |
| | | const params = ref({ |
| | |
| | | |
| | | let tableList = ref([]) |
| | | |
| | | let isShowView = ref(false) |
| | | let isShowViewTest = ref(false) |
| | | |
| | | let rowView = ref({}) |
| | | |
| | |
| | | }); |
| | | } |
| | | function handleDetail(row) { |
| | | isShowView.value = true |
| | | isShowViewTest.value = true |
| | | rowView.value = row |
| | | } |
| | | function handleEdit(row) { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | .content { |
| | | padding: 20px; |
| | | |
| | | .view-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | border: 1px solid #EBEEF5; |
| | | |
| | | tr { |
| | | &:not(:last-child) { |
| | | border-bottom: 1px solid #EBEEF5; |
| | | } |
| | | |
| | | td { |
| | | padding: 12px 10px; |
| | | |
| | | &.label { |
| | | width: 140px; |
| | | text-align: right; |
| | | // color: #909399; |
| | | // background-color: #F5F7FA; |
| | | border-right: 1px solid #EBEEF5; |
| | | } |
| | | |
| | | &.value { |
| | | width: 180px; |
| | | // color: #303133; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .content-edit { |
| | | .el-form { |
| | | .el-form-item { |
| | | width: 300px; |
| | | :deep(.el-form-item__label) { |
| | | width: 120px; |
| | | } |
| | | |
| | | } |
| | | .btns { |
| | | display: flex; |
| | | justify-content: center |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <el-dialog modal-class="mapDialog" v-model="isShow" width="80%"> |
| | | <el-dialog modal-class="mapDialog" v-model="isShow" width="80%" class="ztzf-dialog-mange"> |
| | | <template #header="{ titleId, titleClass }"> |
| | | <div class="my-header"> |
| | | <h4 :id="titleId" :class="titleClass">定位</h4> |
| | |
| | | |
| | | <style scoped lang="scss"> |
| | | .mapBox { |
| | | margin-top: 10px; |
| | | z-index: 2; |
| | | height: 650px; |
| | | width: 98%; |
| | |
| | | <!-- 查看弹框 --> |
| | | <el-dialog |
| | | v-model="dialogVisible" |
| | | class="ztzf-dialog-mange" |
| | | width="60%" |
| | | append-to-body |
| | | @close="dialogClose" |
| | |
| | | <!-- 视频预览 --> |
| | | <el-dialog |
| | | :title="currentVideoTitle" |
| | | class="ztzf-dialog-mange" |
| | | modal-class="videoDialog" |
| | | append-to-body |
| | | width="54%" |
| | |
| | | @click.stop="copyInfo(scope.row, scope.index)" v-if="userInfo.role_name.includes('admin')">复制 |
| | | </el-button> |
| | | </template> |
| | | </avue-crud> |
| | | </avue-crud>F |
| | | </basic-container> |
| | | </template> |
| | | |
| | |
| | | label: '设备类型', |
| | | editDisplay: false, |
| | | prop: 'type', |
| | | type: 'radio', |
| | | labelWidth: 130, |
| | | value: 0, |
| | | type: 'select', |
| | | dicData: [ |
| | | { |
| | | label: '机场', |
| | | label: '机巢', |
| | | value: 0 |
| | | }, |
| | | { |
| | | label: '遥控器', |
| | | label: '控制器', |
| | | value: 1 |
| | | } |
| | | ], |
| | |
| | | }, |
| | | }, |
| | | { |
| | | label: '设备描述', // '工作空间描述', |
| | | prop: 'workspace_desc', |
| | | labelWidth: 130, |
| | | searchSpan: 4, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: '请输入设备描述', |
| | | trigger: 'blur', |
| | | }, |
| | | { |
| | | max: 30, |
| | | message: '设备描述不能超过30个字', |
| | | trigger: 'blur', |
| | | }, |
| | | // 如果需要更严格的校验(如中文字符计算),可以使用 validator |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (value && value.length > 30) { |
| | | callback(new Error('设备描述不能超过30个字')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: 'blur', |
| | | }, |
| | | ], |
| | | }, |
| | | |
| | | { |
| | | label: '创建时间', |
| | | prop: 'create_time', |
| | | addDisplay: false, |
| | |
| | | format: 'YYYY-MM-DD HH:mm:ss', |
| | | |
| | | }, |
| | | { |
| | | label: '设备描述', // '工作空间描述', |
| | | prop: 'workspace_desc', |
| | | type: 'textarea', |
| | | labelWidth: 130, |
| | | searchSpan: 4, |
| | | overHidden: true, |
| | | minRows: 3, |
| | | maxRows: 5, |
| | | maxlength: 250, |
| | | span: 24, |
| | | showWordLimit: true, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: '请输入设备描述不能超过250个字', |
| | | trigger: 'blur', |
| | | }, |
| | | { |
| | | max: 250, |
| | | message: '设备描述不能超过250个字', |
| | | trigger: 'blur', |
| | | }, |
| | | // 如果需要更严格的校验(如中文字符计算),可以使用 validator |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (value && value.length > 250) { |
| | | callback(new Error('设备描述不能超过250个字')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: 'blur', |
| | | }, |
| | | ], |
| | | }, |
| | | |
| | | |
| | | |
| | | |
| | | ], |
| | |
| | | </template> |
| | | <template #menu="scope"> |
| | | <el-dropdown> |
| | | <el-button type="primary" text v-if="permission.oss_set"><el-icon><MoreFilled /></el-icon>更多</el-button> |
| | | <el-button type="primary" text v-if="permission.oss_set"><el-icon><MoreFilled /></el-icon>更多</el-button> |
| | | <template #dropdown v-if="scope.row.domain == 3"> |
| | | <el-dropdown-menu teleported> |
| | | <el-dropdown-item command="a"> |
| | |
| | | <el-dropdown-item command="d"><el-button type="primary" text icon="el-icon-collection" v-if="permission.fly_device_offline" |
| | | @click.stop="rollFirmware(scope.row)">固件版本管理</el-button> |
| | | </el-dropdown-item> |
| | | <el-dropdown-item command="d"> |
| | | <el-button type="primary" text icon="el-icon-collection" v-if="!scope.row.status" @click.stop="dockNotLine(scope.row)"> |
| | | {{ scope.row.hidden_flag == 1 ? '设备上线' : '设备下线'}} |
| | | <el-dropdown-item command="d" v-if="!scope.row.status"> |
| | | <el-button type="primary" text icon="el-icon-collection" @click.stop="dockNotLine(scope.row)"> |
| | | {{ scope.row.hidden_flag === 1 ? '设备上线' : '设备下线'}} |
| | | </el-button> |
| | | </el-dropdown-item> |
| | | <el-dropdown-item command="e"><el-button type="primary" text icon="el-icon-document-delete" v-if="permission.fly_device_offline" |
| | |
| | | </template> |
| | | <template #dropdown v-else> |
| | | <el-dropdown-menu teleported> |
| | | <el-dropdown-item command="a"> |
| | | <!-- <el-dropdown-item command="a"> |
| | | <el-button type="primary" text icon="el-icon-circle-close" @click.stop="rowDel(scope.row, scope.index)">删除</el-button> |
| | | </el-dropdown-item> |
| | | <el-dropdown-item command="a"> |
| | | </el-dropdown-item> --> |
| | | <!-- <el-dropdown-item command="a"> |
| | | <el-button type="primary" text icon="el-icon-key" v-if="permission.operate_password_set" @click.stop="handleOperatePassword(scope.row, scope.index)">操控密码设置</el-button> |
| | | </el-dropdown-item> --> |
| | | <el-dropdown-item command="d"><el-button type="primary" text icon="el-icon-collection" @click.stop="rollFirmware(scope.row)">固件版本管理</el-button> |
| | | </el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </template> |
| | | </el-dropdown> |
| | | </template> |
| | | |
| | | |
| | | <!-- 添加行政区划显示模板 --> |
| | | <template #area_code="{ row }"> |
| | | <span>{{ row.area_name }}</span> |
| | |
| | | |
| | | <el-dialog title="操控密码查看" append-to-body v-model="operatePasswordViewBox" width="455px"> |
| | | <el-input v-model="operate_password" disabled></el-input> |
| | | </el-dialog> |
| | | |
| | | <el-dialog title="注销" class="zx-cancel" append-to-body v-model="cancenOperate" width="460px"> |
| | | <div style="display: flex;justify-content: center;margin-bottom: 10px;">注销 |
| | | <span style="color:cornflowerblue;font-weight: bolder;margin: 0px 4px;"> |
| | | {{ cancelSNName }} |
| | | </span> 设备可能会影响相关数据,确认注销吗?</div> |
| | | <div style="display: flex;justify-content: center;color:red;font-size: 12px;">*删除相关图片、视频、事件</div> |
| | | <template #footer> |
| | | <span class="dialog-footer" style="display: flex;justify-content: center;"> |
| | | <el-button @click="cancenOperate = false">取 消</el-button> |
| | | <el-button type="primary" @click="cancenOperateDo">确 定</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <el-dialog title="固件升级" append-to-body v-model="firmwareBox" width="455px"> |
| | |
| | | getDeviceFirmwareList, |
| | | getDevices, |
| | | deviceOffline, |
| | | devicesUpdate |
| | | devicesUpdate, |
| | | devicesUpAndDown |
| | | } from '@/api/device/device' |
| | | import { deleteByOssId, addOrUpdate as addOrUpdateOssBind } from '@/api/device/ossBind' |
| | | import { getListPage as getOssList } from '@/api/resource/oss' |
| | |
| | | } |
| | | } |
| | | return { |
| | | treeResolveMap: new Map(), |
| | | rules: { |
| | | password: [{ required: true, validator: validatePass, trigger: 'blur' }], |
| | | password2: [{ required: true, validator: validatePass2, trigger: 'blur' }], |
| | | }, |
| | | cancelSNName: '', |
| | | cancenOperate: false, |
| | | cancenOperateRow: {}, |
| | | deleteFlag: false, |
| | | passwordForm: { |
| | | id: '', |
| | | password: '', |
| | |
| | | searchSpan: 4, |
| | | labelWidth: 145, |
| | | width: 120, |
| | | // rules: [ |
| | | // { |
| | | // required: true, |
| | | // message: '请输入设备型号', |
| | | // trigger: 'blur', |
| | | // }, |
| | | // ], |
| | | }, |
| | | { |
| | | label: '设备SN', |
| | |
| | | searchSpan: 4, |
| | | // editDisabled: true, |
| | | editDisplay: false, //编辑显示 |
| | | // rules: [ |
| | | // { |
| | | // required: true, |
| | | // message: '请输入设备SN', |
| | | // trigger: 'blur', |
| | | // }, |
| | | // ], |
| | | }, |
| | | // { |
| | | // label: '机巢编号', |
| | | // prop: 'machine_nest_sn', |
| | | // labelWidth: 145, |
| | | // editDisabled: true, |
| | | // rules: [ |
| | | // { |
| | | // required: false, |
| | | // message: '请输入机巢编号', |
| | | // trigger: 'blur', |
| | | // }, |
| | | // ], |
| | | // }, |
| | | |
| | | { |
| | | label: '设备位置',// '行政区划', |
| | | prop: 'area_name', |
| | |
| | | }, |
| | | ], |
| | | }, |
| | | |
| | | // { |
| | | // label: '设备位置', |
| | | // prop: 'address', |
| | | // labelWidth: 145, |
| | | // width: 100, |
| | | // overHidden: true, |
| | | // rules: [ |
| | | // { |
| | | // required: true, |
| | | // message: '请输入设备位置', |
| | | // trigger: 'blur', |
| | | // }, |
| | | // ], |
| | | // }, |
| | | { |
| | | label: '是否激活', |
| | | prop: 'esim_activate_state', |
| | | labelWidth: 145, |
| | | width: 160, |
| | | overHidden: true, |
| | | editDisplay: false, //编辑显示 |
| | | viewDisplay: false, |
| | | align: 'center', |
| | | formatter: (row, column, cellValue) => { |
| | | const statusMap = { |
| | | 0: '未知', |
| | | 1: '未激活', |
| | | 2: '已激活' |
| | | }; |
| | | return statusMap[cellValue] || '/'; |
| | | } |
| | | }, |
| | | |
| | | { |
| | | label: '负载设备', |
| | |
| | | width: 160, |
| | | overHidden: true, |
| | | editDisplay: false, //编辑显示 |
| | | // editDisabled: true, |
| | | // rules: [ |
| | | // { |
| | | // required: true, |
| | | // message: '请输入负载设备', |
| | | // trigger: 'blur', |
| | | // }, |
| | | // ], |
| | | |
| | | }, |
| | | { |
| | | // hide: true, |
| | |
| | | width: 200, |
| | | type: 'daterange', |
| | | format: 'YYYY-MM-DD', |
| | | valueFormat: 'YYYY-MM-DD HH:mm:ss', |
| | | valueFormat: 'YYYY-MM-DD', |
| | | startPlaceholder: '保险开始日期', |
| | | endPlaceholder: '保险结束日期', |
| | | align: 'center', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | required: false, |
| | | message: '请选择保险有效期', |
| | | trigger: 'blur', |
| | | }, |
| | | ], |
| | | formatter: (row, value) => { |
| | | return value[0]? `${this.$dayjs(value[0]).format('YYYY-MM-DD')}~${this.$dayjs(value[1]).format('YYYY-MM-DD')}` : '/'; |
| | | }, |
| | | }, |
| | | // { |
| | | // label: '保险有效期', |
| | |
| | | type: 'date', |
| | | format: 'YYYY-MM-DD', |
| | | editDisplay: false, //编辑显示 |
| | | // editDisabled: true, |
| | | // rules: [ |
| | | // { |
| | | // required: true, |
| | | // message: '请输入流量到期时间', |
| | | // trigger: 'blur', |
| | | // }, |
| | | // ], |
| | | }, |
| | | { |
| | | label: '固件版本', |
| | |
| | | labelWidth: 145, |
| | | width: 110, |
| | | editDisplay: false, //编辑显示 |
| | | // editDisabled: true, |
| | | // rules: [ |
| | | // { |
| | | // required: true, |
| | | // message: '请输入固件版本', |
| | | // trigger: 'blur', |
| | | // }, |
| | | // ], |
| | | }, |
| | | { |
| | | label: '固件升级', |
| | |
| | | viewDisabled: true, |
| | | addDisabled: true, |
| | | editDisplay: false, //编辑显示 |
| | | // editDisabled: true, |
| | | addDisplay: false, |
| | | viewDisplay: false, |
| | | // rules: [ |
| | | // { |
| | | // required: true, |
| | | // message: '请输入固件升级', |
| | | // trigger: 'blur', |
| | | // }, |
| | | // ], |
| | | }, |
| | | { |
| | | label: '所属单位', |
| | |
| | | // }, |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | { |
| | | label: '在线时间', |
| | |
| | | }, |
| | | }, |
| | | destroyed () { |
| | | this.treeResolveMap.clear() |
| | | this.websocketMap.forEach((k, v) => { |
| | | if (null != v) { |
| | | v.close() |
| | |
| | | this.operateTitle = row.nickname + ' - ' + row.device_sn |
| | | }, |
| | | |
| | | // 设备下线 |
| | | // 设备注销 |
| | | handleDeviceOffline (row) { |
| | | ElMessageBox.confirm('确定注销该设备吗?', '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning', |
| | | }) |
| | | .then(() => { |
| | | deviceOffline(row.device_sn) |
| | | .then(res => { |
| | | ElMessage.success('注销成功') |
| | | this.cancenOperate = true |
| | | this.cancelSNName = row.nickname |
| | | this.cancenOperateRow = row |
| | | |
| | | }, |
| | | |
| | | this.init() |
| | | }) |
| | | .catch(error => { |
| | | ElMessage.error('注销失败') |
| | | }) |
| | | }) |
| | | .catch(() => { }) |
| | | cancenOperateDo () { |
| | | this.cancenOperate = false |
| | | this.deleteFlag = false |
| | | deviceOffline(this.cancenOperateRow.device_sn, true).then(res => { |
| | | ElMessage.success('注销成功') |
| | | |
| | | this.init() |
| | | }).catch(error => { |
| | | ElMessage.error('注销失败') |
| | | }) |
| | | }, |
| | | |
| | | // 打开存储对象配置页面 |
| | |
| | | }) |
| | | .then(() => { |
| | | let hidden_flag = row.hidden_flag === 1?0:1 |
| | | devicesUpdate({id:row.id, hidden_flag:hidden_flag}) |
| | | devicesUpAndDown({id:row.id, hidden_flag:hidden_flag}) |
| | | .then(res => { |
| | | ElMessage.success('下线成功') |
| | | ElMessage.success(`${txt}成功`) |
| | | this.init() |
| | | }) |
| | | .catch(error => { |
| | |
| | | const submitData = { |
| | | ...row, |
| | | area_code: row.area_code.split(',').pop(), |
| | | insure_start_time: row.duration_of_insurance[0], |
| | | insure_expired_time: row.duration_of_insurance[1], |
| | | insure_start_time: row.duration_of_insurance[0] || null, |
| | | insure_expired_time: row.duration_of_insurance[1] || null, |
| | | deptId: row.dept_id, |
| | | areaCode: row.area_code.split(',').pop(), |
| | | } |
| | |
| | | |
| | | update(submitData).then( |
| | | () => { |
| | | this.onLoad(this.page) |
| | | if (row.domain === 0) { |
| | | // 获取保存的 resolve 函数 |
| | | const resolve = this.treeResolveMap.get(row.device_sn) |
| | | if (resolve) { |
| | | // 重新加载子节点数据 |
| | | var params = { |
| | | childSn: row.device_sn, |
| | | } |
| | | getList(1, 10, params).then(res => { |
| | | const data = res.data.data.records |
| | | data.forEach(e => { |
| | | e.duration_of_insurance = [e.insure_start_time || '', e.insure_expired_time || ''] |
| | | }) |
| | | resolve(data) |
| | | }) |
| | | } |
| | | } else { |
| | | this.onLoad(this.page) |
| | | } |
| | | this.$message({ |
| | | type: 'success', |
| | | message: '操作成功!', |
| | |
| | | area_code: await this.getFullAreaCode(data.area_code), |
| | | area_name: this.form.area_name, |
| | | cnmode_code: this.getDockModeText(this.form.mode_code), |
| | | // domain: data.domain === 0 ? '无人机' : data.domain === 3 ? '机巢' : '未知', |
| | | domainTxt: data.domain === 0 ? '无人机' : data.domain === 3 ? '机巢' : '未知', |
| | | cnstatus: this.form.status === false ? '离线' : '在线', |
| | | duration_of_insurance: [data?.insure_start_time || '', data?.insure_expired_time || ''], |
| | |
| | | }) |
| | | }, |
| | | treeLoad (tree, treeNode, resolve) { |
| | | // 保存resolve |
| | | this.treeResolveMap.set(tree.child_sn, resolve) |
| | | var params = { |
| | | childSn: tree.child_sn, |
| | | } |
| | | getList(1, 10, params).then(res => { |
| | | const data = res.data.data.records |
| | | data.forEach(e => { |
| | | e.duration_of_insurance = [e.insure_start_time || '', e.insure_expired_time || ''] |
| | | }) |
| | | resolve(data) |
| | | }) |
| | | }, |
| | |
| | | right: 0; |
| | | } |
| | | |
| | | :deep(.avue-crud__pagination) { |
| | | position: fixed; |
| | | bottom: 10px; |
| | | right: 30px; |
| | | } |
| | | |
| | | |
| | | </style> |
| | |
| | | watch( |
| | | () => Store.getters.deviceState, |
| | | value => { |
| | | console.log(value, '测试') |
| | | // console.log('设备状态变化', value.deviceInfo[props.deviceInfo.child_sn]) |
| | | if (props.sn && (value.currentSn === props.deviceInfo.child_sn || value.currentSn === props.deviceInfo.device_sn)) { |
| | | debugStatus.value = value.dockInfo[props.deviceInfo.device_sn]?.basic_osd?.mode_code === EDockModeCode.Remote_Debugging |
| | |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | label: '授权功能', |
| | | prop: 'devicePerMenuId', |
| | | labelWidth: 130, |
| | | type: 'tree', |
| | | dicUrl: '/blade-system/manage/api/v1/devicePerMenu/selectDeviceList', |
| | | props: { |
| | | label: 'name', |
| | | value: 'id', |
| | | }, |
| | | multiple: true, |
| | | dataType: 'string', |
| | | span: 24, |
| | | row: true, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: '请输入授权功能', |
| | | trigger: 'blur', |
| | | }, |
| | | ], |
| | | }, |
| | | // { |
| | | // label: '授权功能', |
| | | // prop: 'devicePerMenuId', |
| | | // labelWidth: 130, |
| | | // type: 'tree', |
| | | // dicUrl: '/blade-system/manage/api/v1/devicePerMenu/selectDeviceList', |
| | | // props: { |
| | | // label: 'name', |
| | | // value: 'id', |
| | | // }, |
| | | // multiple: true, |
| | | // dataType: 'string', |
| | | // span: 24, |
| | | // row: true, |
| | | // rules: [ |
| | | // { |
| | | // required: true, |
| | | // message: '请输入授权功能', |
| | | // trigger: 'blur', |
| | | // }, |
| | | // ], |
| | | // }, |
| | | { |
| | | label: '授权时间', |
| | | prop: 'createTime', |
| | |
| | | </el-button> |
| | | </template> |
| | | </avue-crud> |
| | | <el-dialog title="固件上传" append-to-body v-model="firmwareUploadBox" width="40%" height="60%"> |
| | | <el-dialog title="固件上传" class="ztzf-dialog-mange" append-to-body v-model="firmwareUploadBox" width="40%" height="60%"> |
| | | <el-form |
| | | ref="form" |
| | | class="ztzf-form-mange" |
| | | :model="importForm" |
| | | v-loading="loadingForm" |
| | | label-width="80px" |
| | | style="width: 80%; margin-left: 10%" |
| | | :rules="rules" |
| | | > |
| | |
| | | <el-form-item label="说明" label-width="80px" prop="release_note"> |
| | | <el-input type="textarea" v-model="importForm.release_note" clearable></el-input> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="onConfirm">确定</el-button> |
| | | <el-button @click="onCancel">取消</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="onConfirm">确定</el-button> |
| | | <el-button @click="onCancel">取消</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </basic-container> |
| | | </template> |
| | |
| | | const jobId = ref('') |
| | | const handleDetail = row => { |
| | | if (!row.device_sns.length) return ElMessage.warning('没有device_sns') |
| | | if (row.device_sns.length !== 1) return ElMessage.success('即将跳转到集群调度') |
| | | rowData.value = row ? row : {} |
| | | jobId.value = rowData.value?.job_id |
| | | if (row.device_sns.length > 1 && (row.status === 2 || row.status === 1)) { |
| | | const adminUrl = `${import.meta.env.VITE_APP_AREA_NAME}/command-center-dashboard/#/clusterScheduling` |
| | | const targetPath = `taskNo=${encodeURIComponent(rowData.value.job_info_num)}` |
| | | window.open(`${adminUrl}?${targetPath}`, '_blank') |
| | | return |
| | | } |
| | | jobId.value = rowData.value?.job_id |
| | | if (row.status === 2 || row.status === 1) { |
| | | // isShowCurrentTaskDetails.value = true |
| | | // 跳转大屏当前任务详情 |
| | |
| | | type: 'category', |
| | | // data: ['1月', '2月', '3月', '4月', '5月', '6月'], |
| | | axisLine: { |
| | | show: false, // 隐藏轴线 |
| | | }, |
| | | axisLine: { |
| | | show: false, // 隐藏轴线 |
| | | show: true, // 隐藏轴线 |
| | | }, |
| | | axisLabel: { |
| | | color: '#5B5B5D', |
| | |
| | | formatter: '{b}: {c} ({d}%)', |
| | | }, |
| | | legend: { |
| | | orient: 'horizontal', |
| | | left: 'center', |
| | | bottom: '2%', |
| | | orient: 'vertical', |
| | | top: 'center', |
| | | right: '20', |
| | | textStyle: { |
| | | color: '#363636', |
| | | fontSize: 12, |
| | | }, |
| | | itemWidth: 2, // 减小图例标记的宽度 |
| | | itemHeight: 3, // 减小图例标记的高度 |
| | | itemHeight: 6, // 减小图例标记的高度 |
| | | itemGap: 8, // 减小图例项之间的间距 |
| | | formatter: '{name}', // 简化图例文本 |
| | | }, |
| | |
| | | name: '机巢事件统计', |
| | | type: 'pie', |
| | | // roseType: 'radius', |
| | | radius: ['36%', '60%'], |
| | | // center: ['50%', '45%'], |
| | | // radius: '70%', // 设置饼图的半径 |
| | | center: ['50%', '36%'], // 调整饼图位置 |
| | | radius: ['20%', '70%'], |
| | | center: ['30%', '50%'], |
| | | data: [], |
| | | label: { |
| | | show: true, |
| | |
| | | |
| | | <style lang="scss" scoped> |
| | | .task-industry { |
| | | width: 276px; |
| | | width: 300px; |
| | | height: 100%; |
| | | background: #FFFFFF; |
| | | border-radius: 8px 8px 8px 8px; |
| | |
| | | type: 'category', |
| | | data: ['1'], |
| | | axisLine: { |
| | | show: false, // 隐藏轴线 |
| | | show: true, // 隐藏轴线 |
| | | }, |
| | | axisTick: { |
| | | show: true, |
| | | length: 2, |
| | | lineStyle: { |
| | | color: '#363636', |
| | | }, |
| | | }, |
| | | // axisTick: { |
| | | // show: true, |
| | | // length: 2, |
| | | // lineStyle: { |
| | | // color: 'red', |
| | | // }, |
| | | // }, |
| | | axisLabel: { |
| | | color: '#363636', |
| | | margin: 8, |
| | |
| | | </avue-crud> |
| | | |
| | | <!-- 新增弹窗 --> |
| | | <el-dialog title="新增 License" v-model="addDialogVisible" width="70%" :close-on-click-modal="false" |
| | | <el-dialog class="ztzf-dialog-mange" title="新增 License" v-model="addDialogVisible" width="70%" :close-on-click-modal="false" |
| | | @close="resetForm"> |
| | | <el-form :model="newLicense" ref="licenseForm" label-width="120px"> |
| | | <el-form-item label="机构ID" prop="licenseId"> |
| | |
| | | <el-form-item label="机构名称" prop="licenseName" required> |
| | | <el-input v-model="newLicense.licenseName" /> |
| | | </el-form-item> |
| | | <el-form-item label="是否验证过期时间类型" prop="licenseType" required> |
| | | <el-form-item label="过期时间类型" prop="licenseType" required> |
| | | <el-select v-model="newLicense.licenseType" placeholder="请选择"> |
| | | <el-option label="不验证过期时间" :value="1" /> |
| | | <el-option label="验证过期时间" :value="2" /> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="addDialogVisible = false">取消</el-button> |
| | | <el-button type="primary" @click="createLicense">保存</el-button> |
| | | <el-button type="primary" @click="createLicense" :icon="CircleCheck">保存</el-button> |
| | | <el-button @click="addDialogVisible = false" :icon="CircleClose">取消</el-button> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | <script> |
| | | import { getList, add } from '@/api/license/license' |
| | | import { mapGetters } from 'vuex' |
| | | import { CircleCheck, CircleClose } from '@element-plus/icons-vue'; |
| | | |
| | | export default { |
| | | data () { |
| | |
| | | } |
| | | }, |
| | | computed: { |
| | | CircleClose() { |
| | | return CircleClose |
| | | }, |
| | | CircleCheck() { |
| | | return CircleCheck |
| | | }, |
| | | ...mapGetters(['userInfo', 'permission']), |
| | | permissionList () { |
| | | return { |
| | |
| | | viewInstance.value.removeMouseHandler('drawCustomPolygon'); |
| | | } |
| | | |
| | | const emit = defineEmits(['upDateDrawState']); |
| | | const emit = defineEmits(['upDateDrawState',]); |
| | | |
| | | function updatePolygon() { |
| | | let polygon = savePolygonPosition.reduce((pre, cur) => { |
| | |
| | | return pre; |
| | | }, []); |
| | | polygon.push(polygon[0]); |
| | | console.log('绘制', `POLYGON((${polygon.join(',')}))`); |
| | | |
| | | // 接口 |
| | | sdfwUpdate({ |
| | | ids: selectionIds.value, |
| | |
| | | }) |
| | | } |
| | | |
| | | |
| | | function cancel() { |
| | | remove(); |
| | | removeMenuPanel(); |
| | |
| | | <template> |
| | | <el-dialog |
| | | class="spotDialog" |
| | | class="spotDialog ztzf-dialog-mange" |
| | | :title="props.title" |
| | | v-model="uploadPatchDialog" |
| | | width="78%" |
| | | align-center |
| | | |
| | | > |
| | | <div class="container"> |
| | | <!-- 信息展示区 --> |
| | |
| | | :row-class-name="tableRowClassName" |
| | | :data="tableData" |
| | | @row-click="handleLocationPolygon" |
| | | @current-change="handleTableRowChange" |
| | | |
| | | > |
| | | <el-table-column type="index" align="center" :width="pxToRemNum(30)" label="序号"> |
| | | <template #default="{ $index }"> |
| | | {{ |
| | | ($index + 1 + (params.page - 1) * params.pageSize).toString().padStart(2, '0') |
| | | }} |
| | | </template> |
| | | <template #default="{ $index }"> |
| | | {{ ($index + 1).toString().padStart(2, '0') }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="dkbh" align="center" label="图斑名称" show-overflow-tooltip /> |
| | | <el-table-column prop="is_exception" :width="pxToRemNum(50)" align="center" label="图斑状态"> |
| | |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <div class="pagination-container"> |
| | | <el-pagination |
| | | :current-page="params.page" |
| | | :page-size="params.pageSize" |
| | | background |
| | | layout="prev, pager, next, ..." |
| | | :pager-count="3" |
| | | prev-text="上一页" |
| | | next-text="下一页" |
| | | :total="total" |
| | | @size-change="handleSizeChange" |
| | | @current-change="handleCurrentChange" |
| | | /> |
| | | </div> |
| | | |
| | | </div> |
| | | </div> |
| | | <!--绘制按钮--> |
| | |
| | | ref="drawPolygonRef" |
| | | v-if="isEditing" |
| | | @upDateDrawState="handleUpDateDrawState" |
| | | |
| | | /> |
| | | <!-- 完成/取消 --> |
| | | <div class="btnGroups" v-if="props.title === '图斑编辑'"> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { flyVisual } from '@/utils/cesium/mapUtil' |
| | | import { pxToRem, pxToRemNum } from '@/utils/rem' |
| | | import DrawPolygon from '@/views/resource/components/DrawPolygon.vue'; |
| | | import { ElMessage, ElMessageBox } from 'element-plus'; |
| | |
| | | page: 1, |
| | | pageSize: 10, |
| | | }); |
| | | const isInit = ref(true); |
| | | // 图斑管理表格 |
| | | const getTableList = () => { |
| | | const requestParams = { |
| | | patchesInfoId: props.detailid, |
| | | page: params.value.page, |
| | | pageSize: params.value.pageSize, |
| | | |
| | | }; |
| | | tableMapListApi(requestParams).then(res => { |
| | | tableData.value = res.data.data.records?.map(item => ({ |
| | | AlltableMapListApi(requestParams).then(res => { |
| | | tableData.value = res.data.data?.map(item => ({ |
| | | ...item, |
| | | dkfw: item.sdfw && item.is_exception == 1 ? item.sdfw : item.dkfw, |
| | | })); |
| | | total.value = res.data.data.total || res.data.data.length; |
| | | tbJwdList = []; |
| | | viewer?.entities.removeAll(); |
| | | if (!AlltableData.value) { |
| | | if (!tableData.value) { |
| | | viewInstance.value?.flyToContour(); |
| | | } else { |
| | | entitiesAddSpot(); |
| | | } |
| | | }); |
| | | }; |
| | | // 所有图斑数据 |
| | | const getAlltableMapListApi = () => { |
| | | loading.value = true; |
| | | const requestParams = { |
| | | patchesInfoId: props.detailid, |
| | | }; |
| | | AlltableMapListApi(requestParams).then(res => { |
| | | AlltableData.value = res.data.data?.map(item => ({ |
| | | ...item, |
| | | dkfw: item.sdfw && item.is_exception == 1 ? item.sdfw : item.dkfw, |
| | | })); |
| | | |
| | | tbJwdList = []; |
| | | viewer?.entities.removeAll(); |
| | | if (AlltableData.value.length < 1) { |
| | | viewInstance.value?.flyToContour(); |
| | | } else { |
| | | entitiesAddSpot(); |
| | | } |
| | | loading.value = false; |
| | | }); |
| | | }; |
| | | const handleSizeChange = val => { |
| | | params.value.pageSize = val; |
| | | params.value.page = 1; |
| | | getTableList(); |
| | | }; |
| | | const handleCurrentChange = val => { |
| | | params.value.page = val; |
| | | getTableList(); |
| | | }; |
| | | |
| | | |
| | | // 地图 |
| | | const initMap = () => { |
| | |
| | | viewer.scene.globe.depthTestAgainstTerrain = true; |
| | | viewInstance.value.switchContour(true); |
| | | }; |
| | | // 仅弹框初始化时执行的定位逻辑 |
| | | const initMapLocation = () => { |
| | | if (tbJwdList.length === 0 || !homeViewer.value) return; |
| | | |
| | | // 计算所有图斑的包围球(用于初始化定位) |
| | | const allPositions = tbJwdList.flatMap(item => |
| | | Cesium.Cartesian3.fromDegreesArray(item.grouped) |
| | | ); |
| | | const boundingSphere = Cesium.BoundingSphere.fromPoints(allPositions); |
| | | |
| | | // 初始化定位(仅执行一次) |
| | | homeViewer.value.camera.flyToBoundingSphere(boundingSphere, { |
| | | duration: 0, |
| | | offset: new Cesium.HeadingPitchRange( |
| | | Cesium.Math.toRadians(0), |
| | | Cesium.Math.toRadians(-90) |
| | | ), |
| | | }); |
| | | }; |
| | | // 初始化所有图斑 |
| | | const entitiesAddSpot = () => { |
| | | viewer?.entities.removeAll(); |
| | | AlltableData.value.forEach(item => { |
| | | // 取出当中经纬度 |
| | | tbJwdList = []; // 重置经纬度列表 |
| | | |
| | | tableData.value.forEach(item => { |
| | | const numbersWithCommas = item.dkfw.match(/\d+(\.\d+)?/g); |
| | | if (!numbersWithCommas) return; |
| | | // 绘制图斑 |
| | | const grouped = numbersWithCommas.map(item => Number(item)); |
| | | // 为框选存储对比值 |
| | | tbJwdList.push({ |
| | | ...item, |
| | | grouped: grouped, |
| | | }); |
| | | viewInstance.value.removeById('polygon_dk' + item.id); |
| | | // 根据 is_exception 设置颜色 |
| | | const color = |
| | | item.is_exception == 2 ? Cesium.Color.RED.withAlpha(0.5) : Cesium.Color.YELLOW.withAlpha(0.5); |
| | | const outlineColor = item.is_exception == 2 ? Cesium.Color.RED : Cesium.Color.YELLOW; |
| | | |
| | | const grouped = numbersWithCommas.map(Number); |
| | | tbJwdList.push({ ...item, grouped }); // 存储经纬度用于后续操作 |
| | | |
| | | // 绘制图斑(保留原有逻辑,仅移除定位相关代码) |
| | | const fillColor = item.is_exception === 2 |
| | | ? Cesium.Color.RED.withAlpha(0.5) |
| | | : Cesium.Color.YELLOW.withAlpha(0.5); |
| | | const outlineColor = item.is_exception === 2 |
| | | ? Cesium.Color.RED |
| | | : Cesium.Color.YELLOW; |
| | | |
| | | homeViewer.value?.entities?.add({ |
| | | id: 'polygon_dk' + item.id, |
| | | id: `polygon_dk${item.id}`, |
| | | customType: 'pattern_spot_polygon', |
| | | customInfo: { |
| | | ...item, |
| | | }, |
| | | customInfo: item, |
| | | polygon: { |
| | | hierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray(grouped)), |
| | | material: color, |
| | | material: fillColor, |
| | | outline: true, |
| | | outlineColor: outlineColor, |
| | | outlineWidth: 2, |
| | |
| | | polyline: { |
| | | positions: Cesium.Cartesian3.fromDegreesArray(grouped), |
| | | width: 2, |
| | | material: color, |
| | | material: outlineColor, |
| | | clampToGround: true, |
| | | }, |
| | | zIndex: 99, |
| | | }); |
| | | |
| | | if (tbJwdList.length > 0) { |
| | | const positions = tbJwdList.flatMap(item => Cesium.Cartesian3.fromDegreesArray(item.grouped)); |
| | | const boundingSphere = Cesium.BoundingSphere.fromPoints(positions); |
| | | homeViewer.value?.camera.flyToBoundingSphere(boundingSphere, { |
| | | duration: 0, |
| | | offset: new Cesium.HeadingPitchRange(Cesium.Math.toRadians(0), Cesium.Math.toRadians(-90)), |
| | | }); |
| | | } |
| | | viewInstance.value?.removeLeftClickEvent('spotHighlighting'); |
| | | viewInstance.value?.addLeftClickEvent(null, spotHighlighting, 'spotHighlighting'); |
| | | }); |
| | | |
| | | // 仅在初始化阶段执行定位(关键:通过isInit控制) |
| | | if (isInit.value) { |
| | | initMapLocation(); |
| | | isInit.value = false; // 初始化完成,后续不再执行定位 |
| | | } |
| | | |
| | | // 保留图斑点击高亮事件(原有逻辑不变) |
| | | viewInstance.value?.removeLeftClickEvent('spotHighlighting'); |
| | | viewInstance.value?.addLeftClickEvent(null, spotHighlighting, 'spotHighlighting'); |
| | | }; |
| | | |
| | | // 高亮当前选中图斑,并定位 |
| | |
| | | |
| | | updateMapSpotInfo(nowEntity); |
| | | } |
| | | |
| | | // 更新上一个和这一个信息 |
| | | function updateMapSpotInfo(nowEntity) { |
| | | const nowData = nowEntity.customInfo; |
| | | if (!nowEntity) return; |
| | | if (nowEntity.customInfo.id === lastEntity?.customInfo.id) return; |
| | | // 设置新的 |
| | | nowEntity.polygon.material = Cesium.Color.RED.withAlpha(0); |
| | | nowEntity.polyline.material = Cesium.Color.RED; |
| | | // 重置上一个 |
| | | if (lastEntity) { |
| | | const lastData = lastEntity.customInfo; |
| | | const originalFillColor = |
| | |
| | | : Cesium.Color.YELLOW.withAlpha(0.5); |
| | | const originalOutlineColor = |
| | | lastData.is_exception == 2 ? Cesium.Color.RED : Cesium.Color.YELLOW; |
| | | |
| | | lastEntity.polygon.material = originalFillColor; |
| | | lastEntity.polygon.outlineColor = originalOutlineColor; |
| | | lastEntity.polyline.material = originalOutlineColor; |
| | |
| | | lastEntity = nowEntity; |
| | | const numbersWithCommas = nowData.dkfw.match(/\d+(\.\d+)?/g); |
| | | if (numbersWithCommas) { |
| | | // 解析经纬度数组 |
| | | const groupedArr = numbersWithCommas.reduce((acc, val, index, src) => { |
| | | if (index % 2 === 0) acc.push(src.slice(index, index + 2)); |
| | | return acc; |
| | | }, []); |
| | | const polygonCenter = getCenterPoint(groupedArr); |
| | | // 相机定位 |
| | | homeViewer.value.scene.camera.setView({ |
| | | destination: Cesium.Cartesian3.fromDegrees( |
| | | Number(polygonCenter.lng), |
| | | Number(polygonCenter.lat), |
| | | 1500 |
| | | ), |
| | | zIndex: 100, |
| | | |
| | | const positionsData = []; |
| | | for (let i = 0; i < numbersWithCommas.length; i += 2) { |
| | | const lon = Number(numbersWithCommas[i]); |
| | | const lat = Number(numbersWithCommas[i + 1]); |
| | | positionsData.push([lon, lat, 10]); |
| | | } |
| | | flyVisual({ |
| | | positionsData: positionsData, |
| | | viewer: homeViewer.value, |
| | | multiple: 15, |
| | | |
| | | }); |
| | | } |
| | | // flyMapSpot(nowEntity?.customInfo) |
| | | } |
| | | // 清空选中的数据 |
| | | const clearSelect = () => { |
| | |
| | | viewer?.entities.removeAll(); |
| | | }; |
| | | // 编辑 |
| | | |
| | | const handleSelectionChange = row => { |
| | | let curRowIsSelect = row; |
| | | curRowIsSelect && handleLocationPolygon(row); |
| | | // 如果是同一个图斑且正在编辑,则取消编辑 |
| | | if (selectionIds.value === row.id && isEditing.value) { |
| | | isEditing.value = false; |
| | | handleUpDateDrawState(false); |
| | | selectionIds.value = null; |
| | | selectionList.value = []; |
| | | return; |
| | | } |
| | | |
| | | // 定位到选中的图斑 |
| | | handleLocationPolygon(row); |
| | | |
| | | // 仅异常图斑可编辑 |
| | | if (row.is_exception !== 2) { |
| | | ElMessage.warning('仅异常图斑支持编辑绘制'); |
| | | return; |
| | | } |
| | | |
| | | // 设置编辑状态 |
| | | selectionIds.value = row.id; |
| | | selectionList.value = row; |
| | | |
| | | if (isEditing.value) { |
| | | //当前已编辑 → 取消编辑(关闭绘制、重置状态) |
| | | isEditing.value = false; |
| | | handleUpDateDrawState(false); // 通知DrawPolygon取消绘制 |
| | | } else { |
| | | // 当前未编辑 → 开启编辑(仅异常图斑可编辑) |
| | | if (row.is_exception === 2 && curRowIsSelect) { |
| | | isEditing.value = true; |
| | | handleUpDateDrawState(true); // 通知DrawPolygon开启绘制 |
| | | } else { |
| | | ElMessage.warning('仅异常图斑支持编辑绘制'); |
| | | isEditing.value = false; |
| | | } |
| | | } |
| | | isEditing.value = true; |
| | | handleUpDateDrawState(true); |
| | | }; |
| | | const handleUpDateDrawState = show => { |
| | | isEditing.value = show; // 同步编辑状态 |
| | |
| | | } |
| | | }; |
| | | // 删除 |
| | | const handleDelete = row => { |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm('确认删除当前行图斑?', '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | |
| | | deletePatches({ ids: row.id }).then(res => { |
| | | if (res.data.code !== 0) return ElMessage.warning('删除失败'); |
| | | ElMessage.success('删除成功'); |
| | | getTableList(); |
| | | getspotManagementTableApi(); |
| | | getAlltableMapListApi(); |
| | | tableData.value = tableData.value.filter(item => item.id !== row.id); |
| | | //从地图上移除对应的图斑实体 |
| | | const entityId = `polygon_dk${row.id}`; |
| | | viewer?.entities.removeById(entityId); |
| | | const exceptionCountItem = infoList.value.find(item => item.name === '异常图斑数量'); |
| | | if (exceptionCountItem && row.is_exception === 2) { |
| | | exceptionCountItem.value = Math.max(0, parseInt(exceptionCountItem.value) - 1); |
| | | } |
| | | const totalCountItem = infoList.value.find(item => item.name === '图斑数量'); |
| | | if (totalCountItem) { |
| | | totalCountItem.value = Math.max(0, parseInt(totalCountItem.value) - 1); |
| | | } |
| | | |
| | | // 清除选中状态 |
| | | if (selectionIds.value === row.id) { |
| | | selectionIds.value = null; |
| | | selectionList.value = []; |
| | | isEditing.value = false; |
| | | handleUpDateDrawState(false); |
| | | } |
| | | |
| | | }); |
| | | }); |
| | | }; |
| | |
| | | publicCesiumInstance = null; |
| | | }; |
| | | |
| | | |
| | | watch(uploadPatchDialog, newVal => { |
| | | if (newVal) { |
| | | |
| | | isInit.value = true; |
| | | setTimeout(() => { |
| | | initMap(); |
| | | getTableList(); |
| | | getAlltableMapListApi(); |
| | | initMap(); |
| | | getTableList(); |
| | | getspotManagementTableApi(); |
| | | }, 0); |
| | | } else { |
| | | tableData.value = []; |
| | | isEditing.value = false; |
| | | handleUpDateDrawState(false); |
| | | destroyMap(); |
| | | isInit.value = false; |
| | | clearSelect(); |
| | | } |
| | | refreshonload(); |
| | | }); |
| | |
| | | font-size: 16px !important; |
| | | color: #363636 !important; |
| | | } |
| | | :global(.spotDialog .el-dialog__body) { |
| | | padding: 2rem 2rem 0 !important; |
| | | |
| | | } |
| | | .container { |
| | | display: flex; |
| | | flex-direction: column; |
| | |
| | | // 表格主体 |
| | | .el-table__body { |
| | | tr:hover > td { |
| | | background-color: rgba(0, 0, 0, 0.6) !important; |
| | | background-color: rgba(64, 158, 255,0.3) !important; |
| | | } |
| | | |
| | | td { |
| | |
| | | |
| | | // 选中行 |
| | | .current-row td { |
| | | background-color: rgba(0, 0, 0, 0.6) !important; |
| | | |
| | | background-color: rgba(64, 158, 255,0.3) !important; |
| | | } |
| | | } |
| | | :deep(.el-table__body) { |
| | |
| | | <el-button type="primary" text icon="el-icon-edit" @click="uploadPatch(scope.row, 'edit')" |
| | | >编辑 |
| | | </el-button> |
| | | <el-button type="primary" text icon="el-icon-delete" @click="rowDel(scope.row)" |
| | | <el-button :disabled="scope.row.patches_type_desc==='综合类'" type="primary" text icon="el-icon-delete" @click="rowDel(scope.row)" |
| | | >删除 |
| | | </el-button> |
| | | </template> |
| | | </avue-crud> |
| | | |
| | | <el-dialog title="上传图斑" append-to-body align-center v-model="box" width="550px"> |
| | | <el-dialog title="上传图斑" class="ztzf-dialog-mange" append-to-body align-center v-model="box" width="550px"> |
| | | <el-form |
| | | ref="ruleFormRef" |
| | | style="max-width: 600px" |
| | |
| | | </basic-container> |
| | | </template> |
| | | <script setup> |
| | | import {findAreaName} from '@/utils/areaUtils' |
| | | import { findAreaName } from '@/utils/areaUtils'; |
| | | import { |
| | | spotManagementTableApi, |
| | | searchManagementApi, |
| | |
| | | border: true, |
| | | index: true, |
| | | indexLabel: '序号', |
| | | indexWidth: 60, |
| | | indexWidth: 60, |
| | | selection: true, |
| | | grid: false, |
| | | menuWidth: 240, |
| | |
| | | data.value = d.records.map(i => ({ |
| | | ...i, |
| | | dataFrom: i.date_from === 0 ? '本地上传' : '国土调查云', |
| | | areaName: findAreaName(i.area_code, regionalData.value, true) |
| | | areaName: findAreaName(i.area_code, regionalData.value, true), |
| | | })); |
| | | loading.value = false; |
| | | selectionClear(); |
| | |
| | | }; |
| | | // 图斑上传 |
| | | const uploadFlightFile = (file, t) => { |
| | | loading.value = true |
| | | loading.value = true; |
| | | const fileSuffix = file.name.substring(file.name.lastIndexOf('.') + 1); |
| | | if (!['kmz', 'kml', 'zip'].includes(fileSuffix)) { |
| | | return ElMessage.error('请上传zip/kmz/kml格式的文件'); |
| | | } |
| | | |
| | | if (file) { |
| | | box.value = false; |
| | | } |
| | | let data = new FormData(); |
| | | let type = t === '3' ? '' : t; |
| | | const params = { |
| | |
| | | |
| | | ElMessage.success('上传成功'); |
| | | |
| | | box.value = false; |
| | | |
| | | loading.value = false; |
| | | ruleForm.name = ''; |
| | | ruleForm.region = ''; |
| | | |
| | | if (ruleFormRef.value) { |
| | | ruleFormRef.value.resetFields(); |
| | | } |
| | | loading.value = true |
| | | |
| | | searchReset(); |
| | | }); |
| | | }; |
| | |
| | | <template #category="{ row }"> |
| | | <el-tag>{{ row.categoryName }}</el-tag> |
| | | </template> |
| | | <template #menu="{ row }"> |
| | | <el-button |
| | | :disabled="row.patches_type === '综合类'" |
| | | type="primary" |
| | | text |
| | | icon="el-icon-delete" |
| | | @click="rowDel(row)" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </avue-crud> |
| | | </basic-container> |
| | | </template> |
| | |
| | | selection: true, |
| | | grid: false, |
| | | menuWidth: 180, |
| | | labelWidth: 100, |
| | | dialogWidth: 880, |
| | | labelWidth: 90, |
| | | dialogWidth: 600, |
| | | dialogClickModal: false, |
| | | height: 'auto', |
| | | calcHeight: 20, |
| | |
| | | gridBtn: false, |
| | | searchShowBtn: false, |
| | | columnBtn: false, |
| | | delBtn: false, |
| | | column: [ |
| | | { |
| | | label: '类型名称', |
| | | prop: 'patches_type', |
| | | search: true, |
| | | searchSpan: 4, |
| | | span: 24, |
| | | rules: [{ required: true, message: '请输入类型名称', trigger: 'blur' }], |
| | | }, |
| | | { |
| | |
| | | </el-row> |
| | | <!-- 表单模块 --> |
| | | <el-dialog |
| | | class="ztzf-dialog-mange" |
| | | :title="title" |
| | | v-model="box" |
| | | width="50%" |
| | |
| | | <el-form-item label="姓名:"> |
| | | <el-input |
| | | class="ztzf-input" |
| | | :style="{ width: pxToRem(230) }" |
| | | :style="{ width: pxToRem(350) }" |
| | | v-model="userInfo.realName" |
| | | disabled |
| | | /> |
| | |
| | | margin: 16px; |
| | | padding: 10px; |
| | | background-color: #ffffff; |
| | | height: 100%; |
| | | } |
| | | .titleBoxs { |
| | | margin: 0 24px; |
| | |
| | | :deep(.el-form-item__label) { |
| | | color: #000 !important; |
| | | } |
| | | :deep(.el-button) { |
| | | width: 150px !important; |
| | | } |
| | | // :deep(.el-button) { |
| | | // width: 150px !important; |
| | | // } |
| | | .info { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | justify-content: center; |
| | | align-items: center; |
| | | padding: 0 80px 0 50px; |
| | | .section:first-child{ |
| | | margin-right: 50px;} |
| | | } |
| | | .password { |
| | | padding: 0 120px 0 50px; |
| | | } |
| | | .butn { |
| | | // position: absolute; |
| | | // bottom: 20px; |
| | | // left: 50%; |
| | | // transform: translate(-50%); |
| | | display: flex; |
| | | justify-content: center; |
| | | cursor: pointer; |
| | | |
| | | img { |
| | | width: 96px; |
| | | height: 32px; |
| | |
| | | |
| | | <!-- 新建工单对话框 --> |
| | | <el-dialog |
| | | class="ztzf-dialog-mange" |
| | | v-model="dialogVisible" |
| | | title="新建工单" |
| | | width="70%" |
| | |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row> |
| | | <div class="add-box-btns"> |
| | | <el-button type="danger" @click="submitForm(1)">发起</el-button> |
| | | <el-button type="primary" @click="submitForm(0)">存草稿</el-button> |
| | | <el-button @click="dialogVisible = false">取消</el-button> |
| | | </div> |
| | | </el-row> |
| | | <!-- <el-row>--> |
| | | <!-- <div class="add-box-btns">--> |
| | | <!-- <el-button type="danger" @click="submitForm(1)">发起</el-button>--> |
| | | <!-- <el-button type="primary" @click="submitForm(0)">存草稿</el-button>--> |
| | | <!-- <el-button @click="dialogVisible = false">取消</el-button>--> |
| | | <!-- </div>--> |
| | | <!-- </el-row>--> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="danger" @click="submitForm(1)">发起</el-button> |
| | | <el-button type="primary" @click="submitForm(0)">存草稿</el-button> |
| | | <el-button @click="dialogVisible = false" :icon="CircleClose">取消</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 工单详情对话框 --> |
| | | <el-dialog |
| | | class="ztzf-dialog-mange" |
| | | align-center |
| | | v-model="detailVisible" |
| | | :title="detailTitle" |
| | |
| | | <map-container v-if="detailVisible" ref="MapContainer"></map-container> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row> |
| | | <div class="add-box-btns"> |
| | | <el-button |
| | | type="danger" |
| | | v-if="form.status == 0 || (form.status == 2 && userInfo.user_id == form.create_user)" |
| | | @click="submitForm(1)" |
| | | >发布</el-button |
| | | > |
| | | <el-button |
| | | type="primary" |
| | | v-if="form.status == 0 || (form.status == 2 && userInfo.user_id == form.create_user)" |
| | | @click="submitForm(0)" |
| | | >保存</el-button |
| | | > |
| | | <!-- <el-button type="primary" v-if="form.status == 0 || userInfo.user_id == form.create_user" |
| | | @click="submitForm(0)">保存</el-button> --> |
| | | |
| | | <el-button |
| | | type="primary" |
| | | v-if="form.status == 1 && hasPaddingBtnPermission()" |
| | | @click="orderLogPass(form.id)" |
| | | >通过</el-button |
| | | > |
| | | <el-button |
| | | type="danger" |
| | | v-if="form.status == 1 && hasRejectionBtnPermission()" |
| | | @click="orderLogReject(form.id)" |
| | | >驳回</el-button |
| | | > |
| | | </div> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button |
| | | type="danger" |
| | | v-if="form.status == 0 || (form.status == 2 && userInfo.user_id == form.create_user)" |
| | | @click="submitForm(1)" |
| | | >发布</el-button |
| | | > |
| | | <el-button |
| | | type="primary" |
| | | v-if="form.status == 0 || (form.status == 2 && userInfo.user_id == form.create_user)" |
| | | @click="submitForm(0)" |
| | | >保存</el-button |
| | | > |
| | | <!-- <el-button type="primary" v-if="form.status == 0 || userInfo.user_id == form.create_user" |
| | | @click="submitForm(0)">保存</el-button> --> |
| | | |
| | | <el-button |
| | | type="primary" |
| | | v-if="form.status == 1 && hasPaddingBtnPermission()" |
| | | @click="orderLogPass(form.id)" |
| | | >通过</el-button |
| | | > |
| | | <el-button |
| | | type="danger" |
| | | v-if="form.status == 1 && hasRejectionBtnPermission()" |
| | | @click="orderLogReject(form.id)" |
| | | >驳回</el-button |
| | | > |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 工单详情 --> |
| | | <el-dialog |
| | | class="ztzf-dialog-mange" |
| | | align-center |
| | | v-model="detailVisibleCopy" |
| | | title="工单详情" |
| | |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row> |
| | | <div class="add-box-btns"> |
| | | <el-button |
| | | type="danger" |
| | | v-if="form.status == 0 || (form.status == 2 && userInfo.user_id == form.create_user)" |
| | | @click="submitForm(1)" |
| | | >发布</el-button |
| | | > |
| | | <!-- <el-button type="primary" v-if="form.status == 0 || userInfo.user_id == form.create_user" |
| | | @click="submitForm(0)">保存</el-button> --> |
| | | |
| | | <el-button |
| | | type="primary" |
| | | v-if="form.status == 1 && hasPaddingBtnPermission()" |
| | | @click="orderLogPass(form.id)" |
| | | >通过</el-button |
| | | > |
| | | <el-button |
| | | type="danger" |
| | | v-if="form.status == 1 && hasRejectionBtnPermission()" |
| | | @click="orderLogReject(form.id)" |
| | | >驳回</el-button |
| | | > |
| | | <el-button @click="detailVisibleCopy = false">取消</el-button> |
| | | </div> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button |
| | | type="danger" |
| | | v-if="form.status == 0 || (form.status == 2 && userInfo.user_id == form.create_user)" |
| | | @click="submitForm(1)" |
| | | >发布</el-button |
| | | > |
| | | <!-- <el-button type="primary" v-if="form.status == 0 || userInfo.user_id == form.create_user" |
| | | @click="submitForm(0)">保存</el-button> --> |
| | | |
| | | <el-button |
| | | type="primary" |
| | | v-if="form.status == 1 && hasPaddingBtnPermission()" |
| | | @click="orderLogPass(form.id)" |
| | | >通过</el-button |
| | | > |
| | | <el-button |
| | | type="danger" |
| | | v-if="form.status == 1 && hasRejectionBtnPermission()" |
| | | @click="orderLogReject(form.id)" |
| | | >驳回</el-button |
| | | > |
| | | <el-button @click="detailVisibleCopy = false">取消</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </basic-container> |
| | | </template> |
| | |
| | | import 'dayjs/locale/zh-cn'; // 导入中文语言包 |
| | | import weekday from 'dayjs/plugin/weekday'; |
| | | import elTooltipCopy from '@/components/ElTooltipCopy.vue'; |
| | | import { CircleClose } from '@element-plus/icons-vue'; |
| | | |
| | | dayjs.extend(weekday); |
| | | dayjs.locale('zh-cn'); |
| | |
| | | } |
| | | }, |
| | | computed: { |
| | | CircleClose() { |
| | | return CircleClose |
| | | }, |
| | | ...mapGetters(['userInfo', 'permission']), |
| | | filteredTabs() { |
| | | // rejection_and_draft 权限控制“已驳回”和“草稿”tab |
| | |
| | | </div> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <div class="dialog-footer-new"> |
| | | <el-button type="danger" :loading="submitLoading" @click="submitForm">发布</el-button> |
| | | <el-button type="infoprimary" plain :loading="draftLoading" @click="saveDraft" |
| | | >存草稿</el-button |
| | | > |
| | | |
| | | <el-button @click="handleCancel">取 消</el-button> |
| | | <el-button @click="handleCancel" :icon="CircleClose">取 消</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </div> |
| | | |
| | | <!-- 操作按钮 --> |
| | | <div class="dialog-footer1"> |
| | | <div class="dialog-footer1-new"> |
| | | <div class="leftBtn" :class="currentIndex === 0 ? 'disableds' : ''" @click="leftClick"> |
| | | 上一页 |
| | | </div> |
| | |
| | | @click="rejectTicket" |
| | | >不通过</el-button |
| | | > |
| | | <el-button @click="detailVisible = false">取消</el-button> |
| | | <el-button @click="detailVisible = false":icon="CircleClose">取消</el-button> |
| | | </template> |
| | | <template v-else-if="currentDetail.status === 0"> |
| | | <el-button |
| | |
| | | title="批量审核" |
| | | width="1100" |
| | | append-to-body |
| | | class="ztzf-dialog-mange" |
| | | custom-class="review-dialog" |
| | | @close="cancleBatchReject" |
| | | > |
| | |
| | | title="工单复核" |
| | | width="30%" |
| | | append-to-body |
| | | custom-class="re-check-dialog" |
| | | class="ztzf-dialog-mange" |
| | | @close="reCheckDialog = false" |
| | | > |
| | | <div class="dialog-footer"> |
| | |
| | | import elTooltipCopy from '@/components/ElTooltipCopy.vue'; |
| | | import getBaseConfig from '@/buildConfig/config'; |
| | | import CreateQRcode from '@/components/CreateQRcode/CreateQRcode.vue'; |
| | | import { CircleClose } from '@element-plus/icons-vue'; |
| | | const { envName } = getBaseConfig(); |
| | | function regExp(label, name) { |
| | | var reg = new RegExp(label + '=([^&]*)(&|$)', 'g'); |
| | |
| | | |
| | | this.loadAMapScripts(); |
| | | this.fetchDropdownData(); |
| | | // console.log('permission.tickets_processing_btn', this.permission.tickets_processing_btn); |
| | | // console.log('permission', this.permission.tickets_tab_pending); |
| | | |
| | | }, |
| | | |
| | | mounted() { |
| | |
| | | } |
| | | |
| | | let curQueryParams = {}; |
| | | |
| | | let isTabProcessed = false; |
| | | if (href.indexOf('?') != -1 && href.split('?').length > 0) { |
| | | curQueryParams = href |
| | | .split('?')[1] |
| | |
| | | return pre; |
| | | }, {}); |
| | | |
| | | const { orderNumber = undefined, day = undefined } = curQueryParams; |
| | | const { orderNumber = undefined, day = undefined, tab = undefined } = curQueryParams; |
| | | |
| | | // 日历传值 |
| | | if (day) { |
| | |
| | | find && (find.query = {}); |
| | | }); |
| | | } |
| | | if (tab) { |
| | | const isTabValid = this.filteredTabs.some(t => t.name === tab); |
| | | if (isTabValid) { |
| | | this.activeTab = tab; |
| | | this.handleTabChangeAfterJump(); |
| | | isTabProcessed = true; |
| | | const find = this.$store.state.tags.bsTagList.find(i => i.path === '/tickets/ticket'); |
| | | find && (find.query = {}); |
| | | } |
| | | } |
| | | } |
| | | |
| | | this.fetchTabCounts(); // 新增:初始化时获取 tab 数据 |
| | | this.fetchTableData(); |
| | | }, |
| | | computed: { |
| | | CircleClose() { |
| | | return CircleClose |
| | | }, |
| | | firstRowData() { |
| | | return this.tableData.length > 0 ? this.tableData[0] : null; |
| | | }, |
| | |
| | | // 修改这里:使用 types 数组查找对应的 label |
| | | value: |
| | | this.types.find(t => t.value === this.currentDetail.type)?.label || |
| | | this.currentDetail.type || |
| | | '/', |
| | | this.currentDetail.type |
| | | }, |
| | | { label: '关联任务', value: this.currentDetail.job_name || '/' }, |
| | | { label: '任务发起人', value: this.currentDetail.creator }, |
| | |
| | | label: '关联算法', |
| | | value: |
| | | this.algorithms.find(t => t.value === this.currentDetail.aiType)?.label || |
| | | this.currentDetail.aiType || |
| | | '/', |
| | | this.currentDetail.aiType |
| | | }, |
| | | { label: '发起单位', value: this.currentDetail.department }, |
| | | { label: '发起任务时间', value: this.currentDetail.startTime }, |
| | |
| | | }, |
| | | |
| | | handleSFNodeClick(data) { |
| | | console.log(data.dictKey, '666666666'); |
| | | this.filters.type = ''; |
| | | this.filters.algorithm = ''; |
| | | this.filters.type = data.dictKey; |
| | |
| | | |
| | | handleTabChange(tab) { |
| | | this.activeTab = tab.props?.name || tab.name; |
| | | |
| | | const isReview = this.findObject(this.option.column, 'isReview'); |
| | | // 根据条件切换显隐 |
| | | isReview.hide = !['all', 'completed', 'myTickets'].includes(this.activeTab); |
| | |
| | | this.fetchTableData(); |
| | | this.fetchTabCounts(); // 切换 tab 时重新获取数据 |
| | | }, |
| | | |
| | | //新增 跳转后触发的Tab切换 |
| | | handleTabChangeAfterJump() { |
| | | const isReview = this.findObject(this.option.column, 'isReview'); |
| | | isReview.hide = !['all', 'completed', 'myTickets'].includes(this.activeTab); |
| | | this.handleReset(); |
| | | this.page.currentPage = 1; |
| | | this.fetchTableData(); |
| | | this.fetchTabCounts(); |
| | | }, |
| | | handleSearch() { |
| | | this.page.currentPage = 1; |
| | | this.fetchTableData(); |
| | |
| | | <style lang="scss"> |
| | | .custom-dialog { |
| | | max-height: 96vh; |
| | | .el-dialog__body { |
| | | |
| | | border-top: 0.1rem solid #f0f0f0; |
| | | } |
| | | } |
| | | .custom-qrcode-popover { |
| | | min-width: 160px !important; |
| | |
| | | width: 100%; |
| | | } |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: center; |
| | | :deep(.el-dialog__body) { |
| | | border-top: 0.1rem solid #f0f0f0; |
| | | } |
| | | .dialog-footer-new { |
| | | text-align: right; |
| | | padding-top: 16px; |
| | | border-top: 1px solid #ebeef5; |
| | | |
| | |
| | | } |
| | | } |
| | | } |
| | | .dialog-footer1 { |
| | | .dialog-footer1-new { |
| | | position: sticky; |
| | | bottom: 28px; |
| | | left: 0; |
| | |
| | | :deep(.el-dialog__body) { |
| | | padding: 0; |
| | | background-color: #f5f7fa; |
| | | border-top: 0.1rem solid #f0f0f0; |
| | | } |
| | | } |
| | | |
| | |
| | | :deep(.el-dialog__body) { |
| | | padding: 0; |
| | | background-color: #f5f7fa; |
| | | border-top: 0.1rem solid #f0f0f0; |
| | | } |
| | | } |
| | | |
| | |
| | | </div> |
| | | |
| | | <div class="action-area"> |
| | | <!-- <img :src="st7" alt="" /> --> |
| | | <!-- <span class="todo-date">{{ item.date?.slice(0, 10).replace(/-/g, '.') }}</span> --> |
| | | <span class="todo-date">{{ item.name }}</span> |
| | | <!-- <span class="todo-date">{{ item.name }}</span> --> |
| | | <el-tooltip effect="dark" :content="item.name" placement="top"> |
| | | <span class="todo-date">{{item.name}}</span> |
| | | </el-tooltip> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | .action-area { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-right: 42px; |
| | | margin-right: 22px; |
| | | |
| | | img { |
| | | width: 15px; |
| | |
| | | |
| | | .todo-date { |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #343434; |
| | | margin-left: 2px; |
| | | font-size: 14px; |
| | | color: #343434; |
| | | margin-left: 2px; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | max-width: 200px; |
| | | display: inline-block; |
| | | } |
| | | } |
| | | } |
| | |
| | | :key="index" |
| | | @click="timeClick(item, index)" |
| | | > |
| | | {{ timeListStr[index] }} |
| | | {{ timeListStr[index] }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <div class="card-group"> |
| | | <div class="main-card"> |
| | | <div class="status-grid"> |
| | | <div class="status-item" v-for="(item, index) in eventTypeList" :key="index"> |
| | | <div class="status-item" v-for="(item, index) in eventTypeList" :key="index" @click="jumpEventDetails(item,index)"> |
| | | <div class="statusCon"> |
| | | <div class="status-label">{{ item.name }}</div> |
| | | <div class="status-value">{{ item.value }}<span>个</span></div> |
| | |
| | | import overviewImg3 from '@/assets/images/workbench/tc3.svg'; |
| | | import overviewImg4 from '@/assets/images/workbench/tc4.svg'; |
| | | import overviewImg5 from '@/assets/images/workbench/tc5.svg'; |
| | | import { useRouter } from 'vue-router' |
| | | const router = useRouter() |
| | | let checked = ref('CURRENT_YEAR'); |
| | | let timeListStr = ['本周', '本月', '本年']; |
| | | let timeListEnum = ['CURRENT_WEEK', 'CURRENT_MONTH', 'CURRENT_YEAR']; |
| | |
| | | }); |
| | | const dateSelect = ref('CURRENT_YEAR'); |
| | | const eventTypeList = ref([ |
| | | { name: '待审核', value: 0, img: overviewImg2, color: '#FF472F', status: '2', rate: 0 }, |
| | | { name: '待处理', value: 0, img: overviewImg3, color: '#FF7411', status: '0', rate: 0 }, |
| | | { name: '处理中', value: 0, img: overviewImg4, color: '#FFC300', status: '3', rate: 0 }, |
| | | { name: '已完成', value: 0, img: overviewImg5, color: '#0291A1', status: '4', rate: 0 }, |
| | | { name: '待审核', value: 0, img: overviewImg2, color: '#FF472F', status: '2', rate: 0 ,tagging:'pending' }, |
| | | { name: '待处理', value: 0, img: overviewImg3, color: '#FF7411', status: '0', rate: 0 ,tagging:'processing' }, |
| | | { name: '处理中', value: 0, img: overviewImg4, color: '#FFC300', status: '3', rate: 0 ,tagging:'inProgress'}, |
| | | { name: '已完成', value: 0, img: overviewImg5, color: '#0291A1', status: '4', rate: 0 ,tagging:'completed'}, |
| | | ]); |
| | | // 工单统计 |
| | | const getTypeData = () => { |
| | |
| | | dateSelect.value = item; |
| | | getTypeData(); |
| | | }; |
| | | // 跳转事件工单 |
| | | const jumpEventDetails = (item,index)=>{ |
| | | // console.log('tiaozhuan',item); |
| | | router.replace({ |
| | | path: `/tickets/ticket`, |
| | | query: { tab: item.tagging } |
| | | }); |
| | | } |
| | | // 图表 |
| | | const echartsRef = ref(null); |
| | | let { chart } = useEchartsResize(echartsRef); |
| | |
| | | width: 144px; |
| | | background: #f6f8fe; |
| | | border-radius: 8px 8px 8px 8px; |
| | | |
| | | cursor: pointer; |
| | | img { |
| | | width: 26px; |
| | | height: 26px; |