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