无人机管理后台前端(已迁走)
罗广辉
2025-09-19 5151d7aac52e01760ba61498496b98de1f835c22
Merge branch 'feature/v6.0/6.0.2' into prod
19 files modified
3 files added
781 ■■■■ changed files
src/api/algorithmMange/algorithmMange.js 17 ●●●●● patch | view | raw | blame | history
src/components/commonDialog.vue 48 ●●●●● patch | view | raw | blame | history
src/page/index/tags.vue 2 ●●● patch | view | raw | blame | history
src/styles/common.scss 1 ●●●● patch | view | raw | blame | history
src/styles/element-ui.scss 70 ●●●●● patch | view | raw | blame | history
src/views/algorithmMange/algorithmMange.vue 302 ●●●●● patch | view | raw | blame | history
src/views/dataCenter/components/dataCenterMap.vue 3 ●●●● patch | view | raw | blame | history
src/views/dataCenter/dataCenter.vue 2 ●●●●● patch | view | raw | blame | history
src/views/device/addDevice.vue 27 ●●●● patch | view | raw | blame | history
src/views/device/airport.vue 8 ●●●●● patch | view | raw | blame | history
src/views/device/components/DockControlPanel.vue 1 ●●●● patch | view | raw | blame | history
src/views/device/components/firmwareManage.vue 14 ●●●●● patch | view | raw | blame | history
src/views/job/components/TaskTop/TaskEvent.vue 5 ●●●● patch | view | raw | blame | history
src/views/job/components/TaskTop/TaskTime.vue 16 ●●●● patch | view | raw | blame | history
src/views/license/license.vue 4 ●●●● patch | view | raw | blame | history
src/views/resource/patchManagement.vue 2 ●●● patch | view | raw | blame | history
src/views/resource/patchTypeManagement.vue 17 ●●●● patch | view | raw | blame | history
src/views/system/param.vue 1 ●●●● patch | view | raw | blame | history
src/views/tickets/orderLog.vue 139 ●●●● patch | view | raw | blame | history
src/views/tickets/ticket.vue 58 ●●●●● patch | view | raw | blame | history
src/views/wel/components/backlog.vue 20 ●●●●● patch | view | raw | blame | history
src/views/wel/components/proportionStatic.vue 24 ●●●● patch | view | raw | blame | history
src/api/algorithmMange/algorithmMange.js
New file
@@ -0,0 +1,17 @@
import request from '@/axios';
// 算法列表
export const getAlgorithmManageList = (params) => {
  return request({
    url: `/drone-device-core/ai/page`,
    method: 'get',
    params: params,
  })
};
export const algorithmManageEdit = data => {
  return request({
    url: '/drone-device-core/ai/edit',
    method: 'put',
    data: data,
  });
};
src/components/commonDialog.vue
New file
@@ -0,0 +1,48 @@
<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>
src/page/index/tags.vue
@@ -23,7 +23,7 @@
      <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>
src/styles/common.scss
@@ -2,6 +2,7 @@
@import './variables.scss';
@import './base.scss';
@import './tool.scss';
@import './element-ui.scss';
a {
  text-decoration: none;
  color: #333;
src/styles/element-ui.scss
@@ -138,4 +138,74 @@
      }
    }
  }
}
//======以下针对表格功能 增删查改样式和弹窗=========
.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;
  }
}
src/views/algorithmMange/algorithmMange.vue
New file
@@ -0,0 +1,302 @@
<template>
  <div class="algorithmMange">
    <div class="ztzf-search-mange">
      <el-form :model="params" inline>
       <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 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="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>
                <el-table-column prop="qua_rate" label="最低准确率" align="center">
          <template #header>
            <el-tooltip placement="bottom" effect="light" content="AI识别率高于最低准确率时会生成待审核状态的事件">
              <el-icon><QuestionFilled /></el-icon>
            </el-tooltip>
            <span>最低准确率</span>
          </template>
        </el-table-column>
                <el-table-column prop="pass_rate" label="最高准确率" align="center">
          <template #header>
            <el-tooltip placement="bottom" effect="light" content="AI识别率高于最高准确率时会生成待处理状态的事件">
              <el-icon><QuestionFilled /></el-icon>
            </el-tooltip>
            <span>最高准确率</span>
          </template>
        </el-table-column>
        <el-table-column prop="event_type" label="事件生成类型" show-overflow-tooltip align="center">
          <template #default="scope">
            {{ scope.row.event_type == 0 ? '常规类' : '紧急类' }}
          </template>
        </el-table-column>
                <el-table-column prop="remark" label="算法描述" show-overflow-tooltip />
                <el-table-column label="操作" width="180" align="center">
                    <template #default="scope">
            <el-button icon="el-icon-view" type="text" @click="handleDetail(scope.row)">查看</el-button>
                        <el-button icon="el-icon-edit" type="text" @click="handleEdit(scope.row)">编辑</el-button>
                    </template>
                </el-table-column>
            </el-table>
        </div>
        <div class="pagination">
            <el-pagination class="ztzf-pagination" popper-class="custom-pagination-dropdown" background
                :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>
  <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-select class="ztzf-select" :teleported="false" v-model="editParams.alg_type" disabled>
            <el-option v-for="item in sfTypes" :key="item.id" :label="item.dictValue" :value="item.dictKey" ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="最低准确率" prop="qua_rate">
          <el-input v-model="editParams.qua_rate" placeholder="请输入最低准确率" required clearable />
        </el-form-item>
        <el-form-item label="最高准确率" prop="pass_rate">
          <el-input v-model="editParams.pass_rate" placeholder="请输入最高准确率" clearable />
        </el-form-item>
        <el-form-item label="事件生成类型" prop="event_type">
          <el-select class="ztzf-select" v-model="editParams.event_type" placeholder="请选择" clearable>
            <el-option label="常规类" value="0"></el-option>
            <el-option label="紧急类" value="1"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="算法描述">
          <el-input v-model="editParams.remark" placeholder="请输入算法描述" clearable />
        </el-form-item>
      </el-form>
    </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({
  current: 1,
  size: 10,
  algName: '',
  algTypeCode: '',
});
let tableList = ref([])
let isShowViewTest = ref(false)
let rowView = ref({})
let isShowEditView = ref(false)
let sfTypes = ref([])
const ruleFormRef = ref()
let editParams = ref({
  model_name: '',
  alg_type: '',
  qua_rate: '',
  pass_rate: '',
  event_type: '',
  remark: ''
})
const rules = reactive({
  qua_rate: [
    { required: true, message: '请输入最低准确率', trigger: 'blur' },
    {
      validator: (rule, value, callback) => {
        if (!/^\d+(\.\d+)?$/.test(value)) {
          callback(new Error('请输入有效的数字(整数或小数)'));
        } else if (parseFloat(value) < 0.1) {
          callback(new Error('最低准确率不能小于0.1'));
        } else if (parseFloat(value) >= parseFloat(editParams.value.pass_rate)) {
          callback(new Error('最低准确率必须小于最高准确率'));
        } else {
          callback();
        }
      },
      trigger: 'blur'
    }
  ],
  pass_rate: [
    { required: true, message: '请输入最低准确率', trigger: 'blur' },
    {
      validator: (rule, value, callback) => {
        if (!/^\d+(\.\d+)?$/.test(value)) {
          callback(new Error('请输入有效的数字(整数或小数)'));
        } else if (parseFloat(value) > 1) {
          callback(new Error('最高准确率不能大于1'));
        } else {
          callback();
        }
      },
      trigger: 'blur'
    }
  ],
  event_type: [
    {
      required: true,
      message: '请选择事件生成类型',
      trigger: 'change',
    },
  ],
})
function cancelSearch() {
  params.value = {
    algName: '',
    algTypeCode: '',
  }
  params.value.current = 1
  getList()
}
function getList() {
  getAlgorithmManageList(params.value).then(res => {
    tableList.value = res.data.data.records || []
    total.value = res.data.data.total || 0
  })
}
function getSFType() {
  getDictionaryByCode('WORK_ORDER_TYPE').then(res => {
    sfTypes.value = res.data.data.WORK_ORDER_TYPE || []
  });
}
function handleDetail(row) {
  isShowViewTest.value = true
  rowView.value = row
}
function handleEdit(row) {
  isShowEditView.value = true
  editParams.value = { ...row }
}
function handleSizeChange(val) {
  params.value.size = val
  getList()
}
function handleCurrentChange(val) {
  params.value.current = val
  getList()
}
async function submit(formValidate) {
  if (!formValidate) return
  await formValidate.validate((valid, fields) => {
    if (valid) {
      algorithmManageEdit(editParams.value).then(res => {
        ElMessage.success('保存成功')
        isShowEditView.value = false
        getList()
      })
    }
  })
}
onMounted(() => {
  getList()
  getSFType()
})
</script>
<style lang="scss" scoped>
  .algorithmMange {
    height: 0;
    flex: 1;
    margin: 0 10px 10px 10px;
    background-color: #ffffff;
    padding: 10px 20px;
    border-radius: 5px;
    display: flex;
    flex-direction: column;
    .search-box {
      height: 40px;
      .btns {
        display: flex;
        justify-content: end;
      }
    }
    :deep(.el-input) {
      .el-input__wrapper {
        width: 200px;
      }
    }
    // 表格
    .mange-table {
      height: 0;
      flex: 1;
      margin-top: 18px;
      overflow: auto;
    }
    :deep(.el-pagination) {
      display: flex;
      justify-content: right;
    }
    :deep(.el-pagination button) {
      background: center center no-repeat none !important;
      color: #8eb8ea !important;
    }
    :deep(.ztzf-select){
      .el-select__selection {
        width: 200px;
      }
    }
  }
</style>
src/views/dataCenter/components/dataCenterMap.vue
@@ -1,5 +1,5 @@
<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>
@@ -312,6 +312,7 @@
<style scoped lang="scss">
.mapBox {
  margin-top: 10px;
  z-index: 2;
  height: 650px;
  width: 98%;
src/views/dataCenter/dataCenter.vue
@@ -184,6 +184,7 @@
      <!-- 查看弹框 -->
      <el-dialog
        v-model="dialogVisible"
        class="ztzf-dialog-mange"
        width="60%"
        append-to-body
        @close="dialogClose"
@@ -292,6 +293,7 @@
      <!-- 视频预览 -->
      <el-dialog
        :title="currentVideoTitle"
        class="ztzf-dialog-mange"
        modal-class="videoDialog"
        append-to-body
        width="54%"
src/views/device/addDevice.vue
@@ -11,7 +11,7 @@
                    @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>
@@ -276,6 +276,18 @@
                        },
                    },
                    {
                        label: '创建时间',
                        prop: 'create_time',
                        addDisplay: false,
                        editDisplay: false,
                        overHidden: true,
                        type: 'date',
                        labelWidth: 130,
                        width: 160,
                        format: 'YYYY-MM-DD HH:mm:ss',
                    },
                    {
                        label: '设备描述', // '工作空间描述',
                        prop: 'workspace_desc',
                        type: 'textarea',
@@ -312,18 +324,7 @@
                        ],
                    },
                    
                    {
                        label: '创建时间',
                        prop: 'create_time',
                        addDisplay: false,
                        editDisplay: false,
                        overHidden: true,
                        type: 'date',
                        labelWidth: 130,
                        width: 160,
                        format: 'YYYY-MM-DD HH:mm:ss',
                    },
                    
                ],
src/views/device/airport.vue
@@ -530,9 +530,10 @@
            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: false,
@@ -540,6 +541,9 @@
                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: '保险有效期',
@@ -612,7 +616,6 @@
            editDisplay: false, //编辑显示
            // editDisabled: true,
            addDisplay: false,
            editDisplay: false,
            viewDisplay: false,
            // rules: [
            //   {
@@ -1425,7 +1428,6 @@
            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 || ''],
src/views/device/components/DockControlPanel.vue
@@ -233,6 +233,7 @@
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
src/views/device/components/firmwareManage.vue
@@ -25,12 +25,12 @@
        </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"
      >
@@ -62,11 +62,13 @@
        <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>
src/views/job/components/TaskTop/TaskEvent.vue
@@ -52,10 +52,7 @@
        type: 'category',
        // data: ['1月', '2月', '3月', '4月', '5月', '6月'],
        axisLine: {
            show: false, // 隐藏轴线
        },
        axisLine: {
            show: false, // 隐藏轴线
            show: true, // 隐藏轴线
        },
        axisLabel: {
            color: '#5B5B5D',
src/views/job/components/TaskTop/TaskTime.vue
@@ -63,15 +63,15 @@
        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,
src/views/license/license.vue
@@ -41,7 +41,7 @@
        </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">
@@ -50,7 +50,7 @@
                <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" />
src/views/resource/patchManagement.vue
@@ -35,7 +35,7 @@
        <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>
src/views/resource/patchTypeManagement.vue
@@ -29,6 +29,17 @@
      <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>
@@ -76,8 +87,8 @@
  selection: true,
  grid: false,
  menuWidth: 180,
  labelWidth: 100,
  dialogWidth: 880,
  labelWidth: 90,
  dialogWidth: 600,
  dialogClickModal: false,
  height: 'auto',
  calcHeight: 20,
@@ -85,12 +96,14 @@
  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' }],
    },
    {
src/views/system/param.vue
@@ -125,6 +125,7 @@
      </el-row>
      <!-- 表单模块 -->
      <el-dialog
        class="ztzf-dialog-mange"
        :title="title"
        v-model="box"
        width="50%"
src/views/tickets/orderLog.vue
@@ -262,6 +262,7 @@
    <!-- 新建工单对话框 -->
    <el-dialog
      class="ztzf-dialog-mange"
      v-model="dialogVisible"
      title="新建工单"
      width="70%"
@@ -384,18 +385,26 @@
          </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">取消</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 工单详情对话框 -->
    <el-dialog
      class="ztzf-dialog-mange"
      align-center
      v-model="detailVisible"
      :title="detailTitle"
@@ -573,43 +582,43 @@
            <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="工单详情"
@@ -778,33 +787,33 @@
          </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>
src/views/tickets/ticket.vue
@@ -414,7 +414,7 @@
        </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
@@ -724,7 +724,7 @@
        </div>
        <!-- 操作按钮 -->
        <div class="dialog-footer1">
        <div class="dialog-footer1-new">
          <div class="leftBtn" :class="currentIndex === 0 ? 'disableds' : ''" @click="leftClick">
            上一页
          </div>
@@ -845,6 +845,7 @@
      title="批量审核"
      width="1100"
      append-to-body
      class="ztzf-dialog-mange"
      custom-class="review-dialog"
      @close="cancleBatchReject"
    >
@@ -922,7 +923,7 @@
      title="工单复核"
      width="30%"
      append-to-body
      custom-class="re-check-dialog"
      class="ztzf-dialog-mange"
      @close="reCheckDialog = false"
    >
      <div class="dialog-footer">
@@ -1177,8 +1178,7 @@
    this.loadAMapScripts();
    this.fetchDropdownData();
    // console.log('permission.tickets_processing_btn', this.permission.tickets_processing_btn);
    // console.log('permission', this.permission.tickets_tab_pending);
  },
  mounted() {
@@ -1191,7 +1191,7 @@
    }
    let curQueryParams = {};
    let isTabProcessed = false;
    if (href.indexOf('?') != -1 && href.split('?').length > 0) {
      curQueryParams = href
        .split('?')[1]
@@ -1204,7 +1204,7 @@
          return pre;
        }, {});
      const { orderNumber = undefined, day = undefined } = curQueryParams;
      const { orderNumber = undefined, day = undefined, tab = undefined } = curQueryParams;
      // 日历传值
      if (day) {
@@ -1233,6 +1233,16 @@
          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 数据
@@ -1346,8 +1356,7 @@
          // 修改这里:使用 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 },
@@ -1357,8 +1366,7 @@
          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 },
@@ -1480,7 +1488,6 @@
    },
    handleSFNodeClick(data) {
      console.log(data.dictKey, '666666666');
      this.filters.type = '';
      this.filters.algorithm = '';
      this.filters.type = data.dictKey;
@@ -2033,7 +2040,6 @@
    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);
@@ -2043,7 +2049,15 @@
      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();
@@ -3096,6 +3110,10 @@
<style lang="scss">
.custom-dialog {
  max-height: 96vh;
  .el-dialog__body {
    border-top: 0.1rem solid #f0f0f0;
  }
}
.custom-qrcode-popover {
  min-width: 160px !important;
@@ -3324,9 +3342,11 @@
    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;
@@ -3342,7 +3362,7 @@
    }
  }
}
.dialog-footer1 {
.dialog-footer1-new {
  position: sticky;
  bottom: 28px;
  left: 0;
@@ -3739,6 +3759,7 @@
  :deep(.el-dialog__body) {
    padding: 0;
    background-color: #f5f7fa;
    border-top: 0.1rem solid #f0f0f0;
  }
}
@@ -3746,6 +3767,7 @@
  :deep(.el-dialog__body) {
    padding: 0;
    background-color: #f5f7fa;
    border-top: 0.1rem solid #f0f0f0;
  }
}
src/views/wel/components/backlog.vue
@@ -30,9 +30,10 @@
            </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>
@@ -397,7 +398,7 @@
      .action-area {
        display: flex;
        align-items: center;
        margin-right: 42px;
        margin-right: 22px;
        img {
          width: 15px;
@@ -406,9 +407,14 @@
        .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;
        }
      }
    }
src/views/wel/components/proportionStatic.vue
@@ -13,7 +13,7 @@
          :key="index"
          @click="timeClick(item, index)"
        >
          {{ timeListStr[index] }}
          {{ timeListStr[index] }}
        </div>
      </div>
    </div>
@@ -21,7 +21,7 @@
      <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>
@@ -51,6 +51,8 @@
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'];
@@ -62,10 +64,10 @@
});
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 = () => {
@@ -95,6 +97,14 @@
  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);
@@ -250,7 +260,7 @@
          width: 144px;
          background: #f6f8fe;
          border-radius: 8px 8px 8px 8px;
          cursor: pointer;
          img {
            width: 26px;
            height: 26px;