From e6dd812f10c48ca71c035445a8ebc34b6f93bb87 Mon Sep 17 00:00:00 2001
From: linwe <872216996@qq.com>
Date: Thu, 17 Apr 2025 21:38:14 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 src/views/tickets/ticket.vue   |  238 ++++++++++++++++++-------
 src/views/tickets/orderLog.vue |  232 +++++++++++++++---------
 src/api/tickets/orderLog.js    |   29 +++
 3 files changed, 341 insertions(+), 158 deletions(-)

diff --git a/src/api/tickets/orderLog.js b/src/api/tickets/orderLog.js
index 9ccc471..4f496c2 100644
--- a/src/api/tickets/orderLog.js
+++ b/src/api/tickets/orderLog.js
@@ -50,6 +50,7 @@
   });
 };
 
+
 // 导出
 export const orderLogExport = (data) => {
   return request({
@@ -60,3 +61,31 @@
   });
 };
 
+export const jobStatusNum = () => {
+  return request({
+    url: '/drone-device-core/wayline/orderLog/jobStatusNum',
+    method: 'get'
+  });
+};
+
+
+// 草稿转发布
+export const userPublish = (id) => {
+  return request({
+    url: '/drone-device-core/wayline/orderLog/userPublish',
+    method: 'get',
+    params: { id }, 
+  });
+};
+//删除
+export const deleteOrderLog = (id) => {
+  return request({
+    url: '/drone-device-core/wayline/orderLog/deleteOrderLog',
+    method: 'get',
+    params: { id }, 
+  });
+};
+
+
+
+
diff --git a/src/views/tickets/orderLog.vue b/src/views/tickets/orderLog.vue
index 9ff71c5..28d407a 100644
--- a/src/views/tickets/orderLog.vue
+++ b/src/views/tickets/orderLog.vue
@@ -11,7 +11,7 @@
 <template>
     <basic-container>
         <el-tabs v-model="activeTab" @tab-click="handleTabChange">
-            <el-tab-pane v-for="tab in tabs" :key="tab.name" :label="`${tab.label} (${tab.count})`" :name="tab.name">
+            <el-tab-pane v-for="tab in filteredTabs" :key="tab.name" :label="`${tab.label} (${tab.count})`" :name="tab.name">
                 <div class="tab-content">
                     <!-- 查询条件筛选栏 -->
                     <div class="filter-bar">
@@ -67,28 +67,42 @@
                         :table-loading="loading" @current-change="currentChange" @refresh-change="refreshChange"
                         @on-load="onLoad" @search-change="searchChange" @size-change="sizeChange">
                         <template #menu-left>
-                            <el-button type="primary" icon="el-icon-plus" @click="handleAdd">新建工单</el-button>
+                            <el-button v-if="hasAddBtnPermission()&&activeTab!='WAIT_AUDIT'" type="primary" icon="el-icon-plus"@click="handleAdd" >新建工单</el-button>
                             <el-button type="success" plain icon="el-icon-download" @click="exportData">导出</el-button>
                         </template>
 
                         <template #menu="{ row }">
                             <div v-if="row.status == 1 && userInfo.user_id != row.create_user">
-                                <el-button type="text" icon="el-icon-view" @click="handleViewDetail(row)">审核</el-button>
+                                <el-button v-if="hasPaddingBtnPermission()" type="text" icon="el-icon-view" @click="handleViewDetail(row)">审核</el-button>
+                                <el-button type="text" icon="el-icon-view" @click="handleViewDetail(row)">详情</el-button>
                             </div>
 
                             <div v-if="userInfo.user_id == row.create_user">
                                 <!--待审核状态-->
                                 <div v-if="row.status == 1">
-                                    <el-button type="text" icon="el-icon-view"
+                                    <el-button type="text" icon="el-icon-warning-outline"
                                         @click="orderLogRecall(row.id)">撤回</el-button>
-                                </div>
-                                <!--已驳回-->
-                                <div v-if="row.status == 2">
                                     <el-button type="text" icon="el-icon-view"
-                                        @click="rejectDetail(row.id)">驳回原因</el-button>
+                                        @click="handleViewDetail(row)">详情</el-button>
                                 </div>
+                            </div>
+                            <!--已驳回-->
+                            <div v-if="row.status == 2">
+                                <el-button type="text" icon="el-icon-warning-outline"
+                                    @click="rejectDetail(row.id)">驳回原因</el-button>
                                 <el-button type="text" icon="el-icon-view" @click="handleViewDetail(row)">详情</el-button>
                             </div>
+                            <!--草稿-->
+                            <div v-if="row.status == 0 && userInfo.user_id == row.create_user">
+                                <el-button type="text" icon="el-icon-edit-outline"
+                                    @click="handleViewDetail(row)">编辑</el-button>
+                                <el-button type="text" icon="el-icon-position"
+                                    @click="userPublishPush(row.id)">发布</el-button>
+                                <el-button type="text" icon="el-icon-delete"
+                                    @click="deleteOrderLog(row.id)">删除</el-button>
+                            </div>
+
+
                         </template>
                         <template #status="{ row }">
                             <el-tag :type="getStatusTagType(row.status)">{{ mapStatus(row.status) }}</el-tag>
@@ -104,8 +118,10 @@
         </el-tabs>
 
         <!-- 新建工单对话框 -->
-        <el-dialog v-model="dialogVisible" title="新建工单" width="70%" :close-on-click-modal="false" @close="resetForm">
-            <el-form :model="form" :rules="rules" ref="form" label-width="100px">
+        <el-dialog  v-model="dialogVisible" title="新建工单" width="70%" :close-on-click-modal="false" @close="resetForm">
+           
+       
+            <el-form :model="form" :rules="rules" ref="testform" label-width="100px">
                 <el-row :gutter="20">
                     <el-col :span="12">
                         <el-form-item label="工单名称" prop="name">
@@ -271,6 +287,9 @@
                         <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 && userInfo.user_id != form.create_user"
                             @click="orderLogPass(form.id)">通过</el-button>
                         <el-button type="danger" v-if="form.status == 1 && userInfo.user_id != form.create_user"
@@ -311,6 +330,9 @@
     orderLogReject,
     orderLogPass,
     orderLogExport,
+    jobStatusNum,
+    userPublish,
+    deleteOrderLog
 } from '@/api/tickets/orderLog'
 import { getTicketInfo } from '@/api/tickets/ticket'
 import { getDictionary } from '@/api/system/dictbiz'
@@ -325,16 +347,16 @@
 
 export default {
     name: 'TicketPage',
-    data () {
+    data() {
         return {
             activeTab: 'all',
 
             tabs: [
                 { label: '全部工单', name: 'all', value: null, count: 0 },
-                { label: '待审核', name: 'pending', value: 1, count: 0 },
-                { label: '已驳回', name: 'processing', value: 2, count: 0 },
-                { label: '已通过', name: 'inProgress', value: 3, count: 0 },
-                { label: '草稿', name: 'completed', value: 0, count: 0 },
+                { label: '待审核', name: 'WAIT_AUDIT', value: 1, count: 0 },
+                { label: '已驳回', name: 'REJECTED', value: 2, count: 0 },
+                { label: '已通过', name: 'PASS', value: 3, count: 0 },
+                { label: '草稿', name: 'DRAFT', value: 0, count: 0 },
             ],
             filters: {
                 key_word: '',
@@ -391,7 +413,7 @@
                     { label: '创建人', prop: 'creator_name', width: 50, ellipsis: true, overHidden: true },
                     { label: '关联机巢', prop: 'device_names', width: 80, ellipsis: true, overHidden: true },
                     {
-                        label: '工单周期凭次',
+                        label: '工单周期频次',
                         prop: '',
                         width: 108,
                         formatter: row => this.formatCycleTime(row),
@@ -429,7 +451,7 @@
             mapLoaded: false,
         }
     },
-    async created () {
+    async created() {
         var response = await getDictionary({ code: 'SF' })
         var word_order_typeResponse = await getDictionary({ code: 'WORK_ORDER_TYPE' })
         this.ai_types = response.data.data
@@ -443,15 +465,28 @@
             value: item.id,
         }))
     },
-    mounted () {
+    mounted() {
         this.fetchTableData()
     },
     computed: {
-        ...mapGetters(['userInfo']),
+        ...mapGetters(['userInfo', 'permission']),
+        filteredTabs() {
+            // rejection_and_draft 权限控制“已驳回”和“草稿”tab
+            const canShowRejectAndDraft = this.permission?.rejection_and_draft === true;
+            return this.tabs.map(tab => {
+                if (tab.name === 'DRAFT') {
+                    return { ...tab, isShow: canShowRejectAndDraft };
+                }
+                if (tab.name === 'REJECTED') {
+                    return { ...tab, isShow: canShowRejectAndDraft };
+                }
+                return { ...tab, isShow: true };
+            }).filter(tab => tab.isShow);
+        },
     },
 
     methods: {
-        searchChange (params, done) {
+        searchChange(params, done) {
             console.log('searchChange')
             this.query = params
             this.parentId = ''
@@ -459,7 +494,7 @@
             this.onLoad(this.page, params)
             done()
         },
-        async onLoad (page, params = {}) {
+        async onLoad(page, params = {}) {
             this.loading = true
             getList(
                 null,
@@ -474,11 +509,11 @@
 
 
         },
-        selectionClear () {
+        selectionClear() {
             this.selectionList = []
             this.$refs.crud.toggleSelection()
         },
-        async loadAMapScripts () {
+        async loadAMapScripts() {
             try {
                 // await loadAMap();
                 // await loadAMapUI();
@@ -488,12 +523,12 @@
                 this.$message.error('地图加载失败,请检查网络或API Key配置')
             }
         },
-        formatCycleTime (row) {
+        formatCycleTime(row) {
             return row.begin_time + '-' + row.end_time + '<br/>'
-                + row.rep_rule_type + row.rep_rule_val
+                 + row.rep_rule_val
         },
 
-        async fetchTableData () {
+        async fetchTableData() {
             this.loading = true
             try {
                 let params = this.getQueryParam()
@@ -508,12 +543,10 @@
                     return item
                 })
 
-                if (this.activeTab === 'all') {
-                    this.updateGlobalCounts(records, total)
-                }
 
+                console.log('权限检查:', this.permission);
                 this.page.total = total || 0
-                this.updateTabCounts()
+                this.updateGlobalCounts()
             } catch (error) {
                 console.error('获取数据失败:', error)
                 this.$message.error(error.message || '获取数据失败')
@@ -524,7 +557,7 @@
             }
         },
 
-        getQueryParam () {
+        getQueryParam() {
             const currentTab = this.tabs.find(tab => tab.name === this.activeTab)
             if (this.filters.dateRange) {
                 console.log(
@@ -563,11 +596,13 @@
             }
             return params
         },
-        sizeChange (pageSize) {
+        sizeChange(pageSize) {
             this.page.pageSize = pageSize
         },
-        async submitForm (status) {
-            this.$refs.form.validate(async valid => {
+        async submitForm(status) {
+            console.log(this.$refs.testform, '111111')
+            this.$refs.testform.validate(async valid => {
+
                 if (valid) {
                     let dateRange = this.form.date_range
                     console.log('dateRange' + dateRange)
@@ -594,7 +629,7 @@
             })
         },
         //驳回原因显示
-        async rejectDetail (id) {
+        async rejectDetail(id) {
             const response = await orderLogDetails(id)
             let data = response.data.data
             this.$confirm(data.remark, '驳回原因', {
@@ -608,7 +643,7 @@
                 this.detailVisible = true
             })
         },
-        formatDate (date) {
+        formatDate(date) {
             if (!date) return undefined
             const d = new Date(date)
             return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(
@@ -616,7 +651,7 @@
             ).padStart(2, '0')} 00:00:00`
         },
 
-        mapStatus (status) {
+        mapStatus(status) {
             const statusTextMap = {
                 0: '草稿',
                 1: '待审核',
@@ -626,7 +661,7 @@
             return statusTextMap[status] || '未知状态'
         },
 
-        getStatusTagType (status) {
+        getStatusTagType(status) {
             const statusMap = {
                 1: 'warning',
                 2: 'info',
@@ -637,19 +672,19 @@
             return statusMap[status] || 'info'
         },
 
-        handleTabChange (tab) {
+        handleTabChange(tab) {
             this.activeTab = tab.props?.name || tab.name
             this.filters.status = ''
             this.page.currentPage = 1
             this.fetchTableData()
         },
 
-        handleSearch () {
+        handleSearch() {
             this.page.currentPage = 1
             this.fetchTableData()
         },
 
-        handleReset () {
+        handleReset() {
             this.filters = {
                 keyword: '',
                 department: '',
@@ -661,55 +696,39 @@
             this.fetchTableData()
         },
 
-        currentChange (currentPage) {
+        currentChange(currentPage) {
             this.page.currentPage = currentPage
         },
 
-        updateGlobalCounts (records, total) {
+        async updateGlobalCounts() {
             const counts = {
-                all: total,
-                pending: 0,
-                processing: 0,
-                inProgress: 0,
-                completed: 0,
-                closed: 0,
-                myTickets: 0,
-            }
+                all: 0,
+                DRAFT: 0,
+                WAIT_AUDIT: 0,
+                REJECTED: 0,
+                PASS: 0,
 
-            records.forEach(item => {
-                const tab = this.tabs.find(t => t.value === Number(item.status))
+            }
+            var reponse = await jobStatusNum();
+            console.log("统计" + reponse.data.data);
+            reponse.data.data.forEach(item => {
+                const tab = this.tabs.find(t => t.name === item.dict_key);
                 if (tab) {
-                    counts[tab.name] = (counts[tab.name] || 0) + 1
+                    tab.count = item.num;
                 }
-            })
+            });
 
-            this.globalCounts = counts
         },
 
-        updateTabCounts () {
-            if (this.activeTab === 'all') {
-                this.tabs.forEach(tab => {
-                    tab.count = this.globalCounts[tab.name] || 0
-                })
-            } else {
-                this.tabs.forEach(tab => {
-                    if (tab.name === this.activeTab) {
-                        tab.count = this.tableData.length
-                    } else {
-                        tab.count = this.globalCounts[tab.name] || 0
-                    }
-                })
-            }
-        },
 
-        handleAdd () {
+        handleAdd() {
             this.form = {}
             this.dialogVisible = true
             //航线列表
             this.asyncgetWaylineFileListByArea()
         },
 
-        resetForm () {
+        resetForm() {
             this.form = {
                 name: '',
                 type: '',
@@ -720,19 +739,18 @@
                 content: '',
                 photos: [],
             }
-            if (this.$refs.form) {
-                this.$refs.form.resetFields()
+            if (this.$refs.testform) {
+                this.$refs.testform.resetFields()
             }
         },
 
-        formatLocation (location) {
+        formatLocation(location) {
             if (!Array.isArray(location)) {
                 return '未知位置'
             }
             return `${location[0].toFixed(6)}, ${location[1].toFixed(6)}`
         },
-
-        async handleViewDetail (row) {
+        async handleViewDetail(row) {
             const response = await orderLogDetails(row.id)
             this.form = {
                 ...response.data.data,
@@ -744,7 +762,7 @@
             this.device_sns = response.data.data.deviceList
         },
         //导出
-        async exportData () {
+        async exportData() {
             this.$confirm('是否智飞工单数据?', '提示', {
                 confirmButtonText: '确定',
                 cancelButtonText: '取消',
@@ -758,19 +776,55 @@
                 })
             })
         },
+        hasAddBtnPermission() {
+            // undefined 或 false 都返回 false,只有 true 返回 true
+            console.log('this.permission.order_log_add :', this.permission.order_log_add );
+            return this.permission && this.permission.order_log_add === true;
+        },
+        hasPaddingBtnPermission() {
+            // undefined 或 false 都返回 false,只有 true 返回 true
+            console.log('权限检查:', this.permission);
+            return this.permission && this.permission.order_log_review === true;
+        },
+        //自己点发布
+        userPublishPush(id) {
+            this.$confirm('确定发布吗?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning',
+            }).then(() => {
+                let response = userPublish(id);
+                this.$message.success('发布成功');
+                this.fetchTableData();
 
-        refreshChange () {
+            })
+        },
+
+        //删除
+        deleteOrderLog(id) {
+            this.$confirm('确定删除吗?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning',
+            }).then(() => {
+                let response = deleteOrderLog(id);
+                this.$message.success('删除');
+                this.fetchTableData();
+
+            })
+        },
+        refreshChange() {
             this.fetchTableData()
         },
         //获取航线列表
-        async asyncgetWaylineFileListByArea (name) {
+        async asyncgetWaylineFileListByArea(name) {
             var wayLineListResponse = await getWaylineFileListByArea(this.userInfo.detail.areaCode)
             this.wayLineList = wayLineListResponse.data.data
 
             this.initMapLine()
         },
 
-        initMapLine () {
+        initMapLine() {
             let currentLine = this.wayLineList.find(item => item.wayline_id == this.form.file_id)
 
             if (!currentLine) return
@@ -812,7 +866,7 @@
 
 
         //可飞行机巢列表
-        async getFlyingNestBy (waylineId) {
+        async getFlyingNestBy(waylineId) {
             this.initMapLine()
 
             //按照航线来
@@ -825,7 +879,7 @@
         },
 
         //撤回
-        async orderLogRecall (id) {
+        async orderLogRecall(id) {
             this.$confirm('确定撤回则到草稿箱。', '是否撤回?', {
                 confirmButtonText: '确定',
                 cancelButtonText: '取消',
@@ -835,13 +889,13 @@
                 this.handleSearch()
             })
         },
-        onLoad () {
+        onLoad() {
             this.fetchTableData()
         },
         /**
          * 通过
          */
-        async orderLogPass (id) {
+        async orderLogPass(id) {
             let response = await orderLogPass(id)
             let data = response.data.data
             this.$message.success('审核通过')
@@ -850,7 +904,7 @@
         /**
          * 驳回
          */
-        async orderLogReject (id) {
+        async orderLogReject(id) {
             this.$prompt('', '驳回原因', {
                 confirmButtonText: '确定',
                 cancelButtonText: '取消',
@@ -865,8 +919,8 @@
 
     watch: {
         tableData: {
-            handler () {
-                this.updateTabCounts()
+            handler() {
+                // this.updateTabCounts()
             },
             deep: true,
         },
diff --git a/src/views/tickets/ticket.vue b/src/views/tickets/ticket.vue
index 673180f..399a94f 100644
--- a/src/views/tickets/ticket.vue
+++ b/src/views/tickets/ticket.vue
@@ -1,7 +1,7 @@
 <template>
   <basic-container>
     <el-tabs v-model="activeTab" @tab-click="handleTabChange">
-      <el-tab-pane v-for="tab in tabs" :key="tab.name" :label="`${tab.label} (${tab.count})`" :name="tab.name">
+      <el-tab-pane v-for="tab in filteredTabs" :key="tab.name" :label="`${tab.label} (${tab.count})`" :name="tab.name">
         <div class="tab-content">
           <!-- 查询条件筛选栏 -->
           <div class="filter-bar">
@@ -30,13 +30,14 @@
           <!-- 表格部分 -->
           <avue-crud ref="avueCrud" v-model="tableData" :option="option" :data="tableData" v-model:page="page"
             @size-change="sizeChange" @current-change="handleCurrentChange" :table-loading="loading"
-            @selection-change="handleSelectionChange">
+            @selection-change="handleSelectionChange" :permission="permissionList">
             <template #menu-left>
-              <el-button v-if="activeTab === 'all' || activeTab === 'myTickets'" type="primary" icon="el-icon-plus"
-                @click="handleAdd">新建工单</el-button>
-              <el-button v-if="activeTab === 'pending'" type="success" icon="el-icon-check"
+              <el-button v-if="(activeTab === 'all' || activeTab === 'myTickets') && permissionList.addBtn"
+                type="primary" icon="el-icon-plus" @click="handleAdd">新建工单</el-button>
+              <el-button v-if="activeTab === 'pending' && permissionList.reviewBtn" type="success" icon="el-icon-check"
                 @click="openReviewDialog">批量审核</el-button>
-              <el-button type="success" plain icon="el-icon-download" @click="exportData">导出</el-button>
+              <el-button v-if="permissionList.exportBtn" type="success" plain icon="el-icon-download"
+                @click="exportData">导出</el-button>
             </template>
             <template #menu="{ row }">
               <template v-if="row.status === -1">
@@ -100,7 +101,7 @@
           <el-row :gutter="16">
             <el-col :span="12">
               <el-form-item label="关联算法" prop="algorithm">
-                <el-select v-model="form.algorithm" placeholder="请选择关联算法" class="full-width">
+                <el-select v-model="form.algorithm" multiple placeholder="请选择关联算法" class="full-width">
                   <el-option v-for="item in algorithms" :key="item.value" :label="item.label" :value="item.value" />
                 </el-select>
               </el-form-item>
@@ -114,7 +115,9 @@
                       <i class="el-icon-map-location"></i> 地图选点
                     </el-button>
                   </avue-input-map>
-                  <div v-if="form.location?.length >= 2" class="location-text">{{ form.address || '获取地址中...' }}</div>
+                  <!-- <div v-if="form.location?.length >= 3">
+  {{ form.location[2] || '获取地址中...' }}
+</div> -->
                 </div>
               </el-form-item>
             </el-col>
@@ -131,7 +134,8 @@
                 <el-upload ref="upload" :action="'#'" :auto-upload="false" list-type="picture-card"
                   :on-change="handleFileChange" :on-remove="handleUploadRemove" :before-upload="beforeUpload"
                   :file-list="form.photos" :limit="1" accept="image/*" class="uploader">
-                  <i class="el-icon-plus"></i>
+                  <span
+                    style="font-size: 32px; display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">+</span>
                 </el-upload>
                 <div class="upload-tip">支持jpg/png格式图片,单张不超过5MB</div>
               </el-form-item>
@@ -151,6 +155,7 @@
     <!-- 工单详情对话框 -->
     <el-dialog v-model="detailVisible" title="工单详情" width="80%" append-to-body>
       <div class="detail-container">
+        <div class="event-title-center">{{ currentDetail.orderName || '事件名称' }}</div>
         <!-- 工单状态流程 -->
         <div class="custom-steps-container">
           <!-- 标题行 -->
@@ -200,16 +205,16 @@
         </div>
 
         <!-- 基本信息表格 -->
-        <el-table :data="formattedDetailFields" border style="width: 100%; margin-bottom: 20px;">
+        <el-table :show-header="false" :data="formattedDetailFields" border style="width: 100%; margin-bottom: 20px;">
           <el-table-column prop="label1" label="基本信息" width="150" />
           <el-table-column>
             <template #default="{ row }">
               <!-- 修复工单名称可编辑 -->
-              <template v-if="currentDetail.status === 0 && row.label1 === '工单名称'">
+              <template v-if="currentDetail.status === 0 && row.label1 === '工单名称'&&hasProcessingBtnPermission()">
                 <el-input v-model="currentDetail.orderName" placeholder="请输入工单名称" />
               </template>
               <!-- 修复任务接收单位为下拉框 -->
-              <template v-else-if="currentDetail.status === 0 && row.label1 === '任务接收单位'">
+              <template v-else-if="currentDetail.status === 0 && row.label1 === '发起单位'">
                 <el-select v-model="currentDetail.department" placeholder="请选择任务接收单位" @change="handleDepartmentChange">
                   <el-option v-for="item in departments" :key="item.value" :label="item.label" :value="item.value" />
                 </el-select>
@@ -221,11 +226,11 @@
           <el-table-column>
             <template #default="{ row }">
               <!-- 修复工单内容可编辑 -->
-              <template v-if="currentDetail.status === 0 && row.label2 === '工单内容'">
+              <template v-if="currentDetail.status === 0 && row.label2 === '工单内容'&&hasProcessingBtnPermission()">
                 <el-input type="textarea" v-model="currentDetail.content" placeholder="请输入工单内容" />
               </template>
               <!-- 修复工单类型为下拉框 -->
-              <template v-else-if="currentDetail.status === 0 && row.label2 === '工单类型'">
+              <template v-else-if="currentDetail.status === 0 && row.label2 === '工单类型' && hasProcessingBtnPermission()">
                 <el-select v-model="currentDetail.type" placeholder="请选择工单类型">
                   <el-option v-for="item in types" :key="item.value" :label="item.label" :value="item.value" />
                 </el-select>
@@ -246,7 +251,7 @@
         <div v-if="[3, 4, 5].includes(currentDetail.status)" class="form-section">
           <div class="section-title">事件处理详情</div>
           <!-- 处理中状态显示输入框 -->
-          <template v-if="currentDetail.status === 3">
+          <template v-if="currentDetail.status === 3 && hasProcessedAndOverBtnPermission()">
             <el-input type="textarea" v-model="currentDetail.processingDetail" placeholder="请输入事件处理详情" :rows="4"
               style="width: 100%; margin-bottom: 10px;" />
           </template>
@@ -259,22 +264,24 @@
         </div>
 
         <!-- 上传图片 -->
-        <div v-if="[3, 4].includes(currentDetail.status)" class="form-section">
-          <div class="section-title">上传图片</div>
-          <el-upload ref="upload" :action="'#'" :auto-upload="false" list-type="picture-card"
-            :on-change="handleFileChange" :on-remove="handleUploadRemove" :before-upload="beforeUpload" :file-list="[]"
-            accept="image/*">
-            <i class="el-icon-plus"></i>
+        <div v-if="[3, 4].includes(currentDetail.status)" class="form-section" style="margin-bottom: 32px;">
+          <div class="section-title" v-if="hasProcessedAndOverBtnPermission()">上传图片</div>
+          <el-upload v-if="hasProcessedAndOverBtnPermission()" ref="upload" :action="'#'" :auto-upload="false"
+            list-type="picture-card" :on-change="handleFileChange" :on-remove="handleUploadRemove"
+            :before-upload="beforeUpload" :file-list="[]" :limit="1" accept="image/*">
+            <span
+              style="font-size: 32px; display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">+</span>
           </el-upload>
-          <div class="el-upload__tip">支持 jpg/png 格式图片,最多 5 张,单张不超过 5MB</div>
+          <div class="el-upload__tip" style="margin-top: 12px;" v-if="hasProcessedAndOverBtnPermission()">
+            支持 jpg/png 格式图片,单张不超过 5MB
+          </div>
         </div>
-
         <!-- 图片和地图部分 -->
         <div class="media-section">
           <el-row :gutter="20">
             <el-col :span="12">
               <div class="media-box">
-                <div class="media-title">事件图片/事件视频</div>
+                <div class="media-title">事件图片</div>
                 <div class="media-content">
                   <el-image v-if="currentDetail.mediaUrl" :src="currentDetail.mediaUrl"
                     :preview-src-list="[currentDetail.mediaUrl]" fit="cover" style="width: 100%; height: 300px;">
@@ -337,24 +344,23 @@
         <div class="dialog-footer">
           <template v-if="currentDetail.status === 2">
             <!-- 待审核 -->
-            <el-button type="primary" @click="approveTicket">通过</el-button>
-            <el-button type="danger" @click="rejectTicket">不通过</el-button>
+            <el-button v-if="hasReviewBtnPermission()" type="primary" @click="approveTicket">通过</el-button>
+            <el-button v-if="hasReviewBtnPermission()" type="danger" @click="rejectTicket">不通过</el-button>
             <el-button @click="detailVisible = false">取消</el-button>
           </template>
           <template v-else-if="currentDetail.status === 0">
-
-            <el-button type="primary" @click="approveAndDispatch">通过并派发</el-button>
-            <el-button type="danger" @click="rejectTicket">不通过</el-button>
+            <el-button v-if="hasProcessingBtnPermission()" type="primary" @click="approveAndDispatch">通过并派发</el-button>
+            <el-button v-if="hasProcessingBtnPermission()" type="danger" @click="rejectTicket">不通过</el-button>
             <el-button @click="detailVisible = false">取消</el-button>
           </template>
-          <template v-else-if="currentDetail.status === 3">
+          <template v-if="currentDetail.status === 3">
             <!-- 处理中 -->
-            <el-button type="primary" @click="completeTicket">完成工单</el-button>
+            <el-button v-if="hasProcessedAndOverBtnPermission()" type="primary" @click="completeTicket">完成工单</el-button>
             <el-button @click="detailVisible = false">取消</el-button>
           </template>
           <template v-else-if="currentDetail.status === 4">
             <!-- 已完成 -->
-            <el-button type="primary" @click="finalizeTicket">完结工单</el-button>
+            <el-button v-if="hasProcessedAndOverBtnPermission()" type="primary" @click="finalizeTicket">完结工单</el-button>
             <el-button @click="detailVisible = false">取消</el-button>
           </template>
           <template v-else-if="currentDetail.status === 5">
@@ -443,7 +449,9 @@
   name: "TicketPage",
   data() {
     return {
+      submitLoading: false, // 新增loading状态
       activeTab: "all",
+      // tabs 只保留静态结构,不做权限判断
       tabs: [
         { label: "全部工单", name: "all", value: null, count: 0 },
         { label: "待审核", name: "pending", value: 2, count: 0 },
@@ -451,7 +459,7 @@
         { label: "处理中", name: "inProgress", value: 3, count: 0 },
         { label: "已完成", name: "completed", value: 4, count: 0 },
         { label: "已完结", name: "closed", value: 5, count: 0 },
-        { label: "我发起的", name: "myTickets", value: null, count: 0 },
+        { label: "我发起的工单", name: "myTickets", value: null, count: 0 },
       ],
       filters: {
         keyword: "",
@@ -525,7 +533,7 @@
         type: '',
         department: '',
         handler: '',
-        algorithm: '',
+        algorithm: [], // 关联算法改为数组
         location: [],  // 将存储为[经度, 纬度, 地址]格式
         address: '',
         content: '',
@@ -594,6 +602,8 @@
     this.loadAMapScripts();
     this.fetchDropdownData();
     this.fetchTabCounts(); // 新增:初始化时获取 tab 数据
+    console.log('permission.tickets_processing_btn', this.permission.tickets_processing_btn);
+    console.log('permission', this.permission.tickets_tab_pending);
   },
   mounted() {
     this.fetchTableData();
@@ -646,7 +656,7 @@
           editable: false,
         },
         {
-          label: "任务接收单位",
+          label: "发起单位",
           value: this.currentDetail.department,
           editable: false,
         },
@@ -672,7 +682,7 @@
         { label: "事件地址", value: this.currentDetail.address, editable: false },
         { label: "工单类型", value: this.currentDetail.type, editable: this.currentDetail.status === 0, type: "select", options: this.types },
         { label: "关联算法", value: this.currentDetail.aiType, editable: false },
-        { label: "任务接收单位", value: this.currentDetail.department, editable: false },
+        { label: "发起单位", value: this.currentDetail.department, editable: false },
         { label: "发起任务时间", value: this.currentDetail.startTime, editable: false },
         { label: "工单内容", value: this.currentDetail.content, editable: this.currentDetail.status === 0, type: "textarea" },
       ];
@@ -681,12 +691,12 @@
       const fields = [
         { label: "工单名称", value: this.currentDetail.orderName },
         { label: "工单类型", value: this.currentDetail.type },
-        { label: "任务处理人", value: this.currentDetail.handler || '未分配' }, // 显示处理人
+        { label: "关联任务", value: this.currentDetail.job_name || '暂无关联航线' },
         { label: "任务发起人", value: this.currentDetail.creator },
         { label: "当前状态", value: this.mapStatus(this.currentDetail.status) },
         { label: "事件地址", value: this.currentDetail.address }, // 包含经纬度信息
         { label: "关联算法", value: this.currentDetail.aiType },
-        { label: "任务接收单位", value: this.currentDetail.department },
+        { label: "发起单位", value: this.currentDetail.department },
         { label: "发起任务时间", value: this.currentDetail.startTime },
         { label: "工单内容", value: this.currentDetail.content },
       ];
@@ -710,7 +720,38 @@
       }
       return this.fixedStatuses; // 默认流程
     },
-    ...mapGetters(['userInfo']),
+    ...mapGetters(['userInfo', 'permission']),
+    // 动态过滤tabs,保证isShow为true/false
+    filteredTabs() {
+      // 统一处理权限,undefined视为false
+      const tabStatus = this.permission?.tickets_tab_status === true;
+      const tabPending = this.permission?.tickets_tab_pending === true;
+      const tabMyTickets = this.permission?.tickets_tab_mytickets === true;
+      return this.tabs.map(tab => {
+        if (tab.name === 'all') {
+          return { ...tab, isShow: true };
+        }
+        if (tab.name === 'pending') {
+          return { ...tab, isShow: tabPending };
+        }
+        if (['processing', 'inProgress', 'completed', 'closed'].includes(tab.name)) {
+          return { ...tab, isShow: tabStatus };
+        }
+        if (tab.name === 'myTickets') {
+          return { ...tab, isShow: tabMyTickets };
+        }
+        return { ...tab, isShow: false };
+      }).filter(tab => tab.isShow);
+    },
+    permissionList() {
+      // 可根据实际后端权限key调整
+      return {
+        addBtn: this.validData(this.permission.tickets_add, false),
+        delBtn: this.validData(this.permission.tickets_delete, false),
+        exportBtn: this.validData(this.permission.tickets_export, false,),
+        reviewBtn: this.validData(this.permission.tickets_review, false),
+      };
+    },
   },
   methods: {
     async loadAMapScripts() {
@@ -823,8 +864,11 @@
 
         // 确保算法数据的映射一致
         this.algorithms = ai_type.map(item => ({
-          label: item.dict_value, // 修改为 label
-          value: item.dict_key,  // 修改为 value
+          dict_key: item.dict_key,
+          dict_value: item.dict_value,
+          // 同时添加 label 和 value 以兼容两处使用
+          label: item.dict_value,
+          value: item.dict_key
         }));
 
         // 构建用户ID和名称的映射关系
@@ -858,7 +902,8 @@
           size: Number(this.page.pageSize),       // 使用每页条数
           ai_type: this.filters.algorithm || undefined, // 添加算法参数
           // 添加 is_draft 参数,仅在"我发起的"标签页时设置为1
-          is_draft: currentTab?.name === 'myTickets' ? 1 : undefined
+          is_draft: currentTab?.name === 'myTickets' ? 1 : undefined,
+          user_id: currentTab?.name === 'myTickets' ? this.userInfo.user_id : undefined,
         };
 
         const response = await getList(params);
@@ -870,11 +915,11 @@
         let filteredRecords = records;
 
         // 如果是"我发起的"tab,过滤数据
-        if (currentTab?.name === 'myTickets') {
-          filteredRecords = records.filter(item =>
-            String(item.create_user_id) === String(item.user_id)
-          );
-        }
+        // if (currentTab?.name === 'myTickets') {
+        //   filteredRecords = records.filter(item =>
+        //     String(item.create_user_id) === String(item.user_id)
+        //   );
+        // }
 
         this.tableData = filteredRecords.map(item => {
           const longitude = Number(item.longitude) || 0;
@@ -902,15 +947,12 @@
             processing_details: item.processing_details || '', // 添加处理详情字段
             update_photo_url: item.update_photo_url || '', // 添加处理图片字段
             work_type: item.work_type !== undefined ? Number(item.work_type) : 0, // 保留work_type字段并转为数字
+            job_name: item.job_name || '', 
           };
         });
 
         // 更新总数显示
-        if (currentTab?.name === 'myTickets') {
-          this.page.total = filteredRecords.length;
-        } else {
-          this.page.total = total || 0;
-        }
+        this.page.total = total || 0;
 
         await this.fetchTabCounts();
       } catch (error) {
@@ -924,6 +966,8 @@
     },
 
     async submitForm() {
+      if (this.submitLoading) return; // 防止重复提交
+      this.submitLoading = true;
       try {
         // 提交时需要完整验证
         await this.$refs.form.validate();
@@ -948,7 +992,7 @@
           latitude: String(this.form.location[1]),
           address: this.form.address,
           eventDictKey: this.form.type,
-          aiType: this.form.algorithm,
+          aiType: Array.isArray(this.form.algorithm) ? this.form.algorithm : [this.form.algorithm], // 传数组
           updateUser: this.form.handler,
           createDept: this.form.department,
           isDraft: 0
@@ -980,10 +1024,19 @@
           this.$message.error(error.message || '工单创建失败,请稍后重试');
         }
       }
+      finally {
+        this.submitLoading = false;
+      }
     },
 
     async saveDraft() {
+      if (this.submitLoading) return; // 防止重复提交
+      this.submitLoading = true;
       try {
+        let handlerValue = this.form.handler;
+        if (!handlerValue || handlerValue === '未分配') {
+          handlerValue = undefined;
+        }
         const submitData = {
           id: this.form.id,
           eventName: this.form.name || undefined,
@@ -993,8 +1046,8 @@
           latitude: this.form.location?.[1] ? String(this.form.location[1]) : undefined,
           address: this.form.address || undefined,
           eventDictKey: this.form.type || undefined,
-          aiType: this.form.algorithm || undefined,
-          updateUser: this.form.handler || undefined,
+          aiType: Array.isArray(this.form.algorithm) ? this.form.algorithm : [this.form.algorithm], // 传数组
+          updateUser: handlerValue,
           createDept: this.form.department || undefined,
           isDraft: 1
         };
@@ -1026,16 +1079,20 @@
       } catch (error) {
         this.$message.error(error.message || '保存草稿失败,请稍后重试');
       }
+      finally {
+        this.submitLoading = false;
+      }
     },
 
-    async handleLocationChange(val) {
-
-
-      // 处理 Proxy 对象的值
+    handleLocationChange(val) {
       let locationValue = val.value;
-      if (locationValue && locationValue.length >= 3) {
-        // 确保我们获取到实际的数组值
-        this.form.location = [locationValue[0], locationValue[1]];
+      if (locationValue && locationValue.length >= 2) {
+        // 兼容第三项为地址
+        this.form.location = [
+          Number(locationValue[0]),
+          Number(locationValue[1]),
+          locationValue[2] || ''
+        ];
         this.form.address = locationValue[2] || '';
       } else {
         this.form.location = [];
@@ -1142,7 +1199,7 @@
         type: '',
         department: '',
         handler: '',
-        algorithm: '',
+        algorithm: [], // 关联算法改为数组
         location: [],  // 将存储为[经度, 纬度, 地址]格式
         address: '',
         content: '',
@@ -1178,6 +1235,7 @@
         mediaUrl: row.photo_url || row.video_url || '',
         updatePhotoUrl: row.update_photo_url || '',
         photos: [],
+        job_name: row.job_name || '', // 新增
       };
 
       try {
@@ -1517,6 +1575,21 @@
     async approveAndDispatch() {
       this.dispatchDialogVisible = true; // 打开派发对话框
     },
+    hasProcessingBtnPermission() {
+      // undefined 或 false 都返回 false,只有 true 返回 true
+      console.log('权限检查:', this.permission);
+      return this.permission && this.permission.tickets_processing_btn === true;
+    },
+    hasProcessedAndOverBtnPermission() {
+      // undefined 或 false 都返回 false,只有 true 返回 true
+      console.log('权限检查:', this.permission);
+      return this.permission && this.permission.tickets_view_processedAndOver === true;
+    },
+    hasReviewBtnPermission() {
+      // undefined 或 false 都返回 false,只有 true 返回 true
+      console.log('权限检查:', this.permission);
+      return this.permission && this.permission.tickets_review_btn === true;
+    },
     async submitDispatch() {
       this.$refs.dispatchForm.validate(async (valid) => {
         if (valid) {
@@ -1616,19 +1689,40 @@
         映射后类型值: typeValue
       });
 
+      let algorithmArr = [];
+      if (Array.isArray(row.aiType)) {
+        algorithmArr = row.aiType;
+      } else if (typeof row.aiType === 'string' && row.aiType) {
+        algorithmArr = row.aiType.split(',').map(i => i.trim());
+      }
       this.form = {
         id: row.id,
         name: row.orderName,
         type: typeValue,
         department: deptId,
         handler: handlerId, // 使用映射后的处理人ID
-        algorithm: row.aiType,
-        location: row.location,
-        address: row.address,
+        algorithm: algorithmArr, // 回显为数组
+        location: Array.isArray(row.location) && row.location.length >= 2
+          ? [Number(row.location[0]), Number(row.location[1])]
+          : [],
+        address: row.address || '',
         content: row.content,
         photos: [],
       };
-
+      this.form.location = Array.isArray(row.location) && row.location.length >= 2
+        ? [
+          Number(row.location[0]),
+          Number(row.location[1]),
+          row.location[2] || row.address || ''
+        ]
+        : [];
+      this.form.address = this.form.location[2] || '';
+      // 设置地图中心点
+      if (Array.isArray(this.form.location) && this.form.location.length >= 2) {
+        this.mapParams.center = [Number(this.form.location[0]), Number(this.form.location[1])];
+      } else {
+        this.mapParams.center = null; // 没有经纬度时用默认
+      }
       // 如果有图片,添加到表单中
       if (row.photo_url) {
         this.form.photos = [{
@@ -1802,7 +1896,7 @@
       }
     },
 
-    cancleBatchReject(){
+    cancleBatchReject() {
       reviewDialogVisible = false;
       this.fetchTableData();
     },
@@ -2346,7 +2440,13 @@
   color: #409eff;
   font-weight: bold;
 }
-
+.event-title-center {
+  text-align: center;
+  font-size: 20px;
+  font-weight: bold;
+  margin-bottom: 12px;
+  color: #333;
+}
 .custom-steps {
   margin-top: -20px;
 

--
Gitblit v1.9.3