From 771cd475a2aad9938f4e2085ca018ba31bdc1d7f Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Thu, 20 Nov 2025 14:11:03 +0800
Subject: [PATCH] feat:工单详情
---
src/views/tickets/ticket.vue | 471 ++-------------
src/views/tickets/ticketComponent/CreateTicketDialog.vue | 5
src/views/tickets/ticketComponent/TicketDetailDialog.vue | 1247 +++++++++++++++++++++++++-----------------
3 files changed, 799 insertions(+), 924 deletions(-)
diff --git a/src/views/tickets/ticket.vue b/src/views/tickets/ticket.vue
index a38190d..644cb20 100644
--- a/src/views/tickets/ticket.vue
+++ b/src/views/tickets/ticket.vue
@@ -9,7 +9,6 @@
>
<basic-main-content>
<!-- 查询条件筛选栏 -->
- <!-- 查询条件筛选栏 -->
<div class="ztzf-form-search">
<el-form :model="filters" inline>
<el-row :gutter="24">
@@ -26,33 +25,7 @@
</el-form-item>
</el-col>
- <!-- <el-select
- v-model="filters.department"
- placeholder="请选择所属部门"
- class="filter-item"
- clearable
- >
- <el-option
- v-for="item in departments"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select> -->
- <!-- <el-select
- v-model="filters.type"
- placeholder="请选择工单类型"
- class="filter-item"
- clearable
- @change="handleSearch"
- >
- <el-option
- v-for="item in types"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select> -->
+
<el-col :span="5">
<el-form-item label="选择日期:">
<el-date-picker
@@ -87,34 +60,6 @@
</el-form-item>
</el-col>
- <!-- <el-select
- v-model="filters.algorithm"
- placeholder="请选择关联算法"
- class="filter-item"
- clearable
- @change="handleSearch"
- >
- <el-option
- v-for="item in algorithms"
- :key="item.dict_key"
- :label="item.dict_value"
- :value="item.dict_key"
- />
- </el-select> -->
- <!-- <el-tree-select
- popper-class="custom-tree-select"
- :style="{ width: pxToRem(186) }"
- placeholder="请选择关联算法"
- v-model="dictKey"
- :data="dataList"
- :default-expanded-keys="[dictKey]"
- check-strictly
- node-key="id"
- :props="treePropsSF"
- @node-click="handleSFNodeClick"
- clearable
- @clear="handleClear"
- /> -->
<el-col :span="4">
<el-form-item label="选择算法:">
<el-tree-select
@@ -270,37 +215,37 @@
</el-tabs>
<!-- 新建工单对话框 -->
- <create-ticket-dialog
- v-model="dialogVisible"
- :departments="departments"
- :department-users="departmentUsers"
- :types="types"
- :all-algorithms="allAlgorithms"
- :edit-data="editFormData"
- :map-center="inputMapShowDefaultCenter"
- @create-success="handleCreateSuccess"
- @draft-success="handleDraftSuccess"
- @create-error="handleCreateError"
-/>
+ <create-ticket-dialog
+ v-model="dialogVisible"
+ :departments="departments"
+ :department-users="departmentUsers"
+ :types="types"
+ :all-algorithms="allAlgorithms"
+ :edit-data="editFormData"
+ :map-center="inputMapShowDefaultCenter"
+ @create-success="handleCreateSuccess"
+ @draft-success="handleDraftSuccess"
+ @create-error="handleCreateError"
+ />
<!-- 工单详情对话框 -->
-<ticket-detail-dialog
- v-model="detailVisible"
- :current-detail="currentDetail"
- :current-index="currentIndex"
- :total-items="tableData.length"
- :algorithms="algorithms"
- :types="types"
- :permission="permission"
- :step-status-list="stepStatusList"
- :work-type="workType"
- @detail-success="handleDetailSuccess"
- @detail-error="handleDetailError"
- @prev-item="handlePrevItem"
- @next-item="handleNextItem"
- @update:current-detail="handleCurrentDetailUpdate"
- @approve-and-dispatch="handleApproveAndDispatch"
-/>
+ <ticket-detail-dialog
+ v-model="detailVisible"
+ :current-detail="currentDetail"
+ :current-index="currentIndex"
+ :total-items="tableData.length"
+ :algorithms="algorithms2"
+ :types="types"
+ :permission="permission"
+ :step-status-list="stepStatusList"
+ :work-type="workType"
+ @detail-success="handleDetailSuccess"
+ @detail-error="handleDetailError"
+ @prev-item="handlePrevItem"
+ @next-item="handleNextItem"
+ @update:current-detail="handleCurrentDetailUpdate"
+ @approve-and-dispatch="handleApproveAndDispatch"
+ />
<!-- 派发工单对话框 -->
<dispatch-dialog
@@ -418,8 +363,6 @@
flowEvent,
getstatusCount,
getStepInfo,
- getReviewById,
- getCreateEventJob,
exportTheTicket
} from '@/api/tickets/ticket';
import { getSFDictionaryTree } from '@/api/job/task';
@@ -448,12 +391,6 @@
data() {
return {
currentIndex: null, // 当前显示的数据索引
-
-
- approveLoading: false,
- rejectLoading: false,
- dispatchLoading: false,
- completeLoading: false,
finalizeLoading: false,
createoredit: '',
activeTab: 'all',
@@ -486,6 +423,7 @@
algorithms: [],
algorithms2: [],
+ algorithms3: [],
statuses: [
{ label: '待审核', value: '2' },
{ label: '待处理', value: '0' },
@@ -604,7 +542,6 @@
},
created() {
this.inputMapShowDefaultCenter = null;
-
this.loadAMapScripts();
this.fetchDropdownData();
},
@@ -691,134 +628,7 @@
? this.departmentUsers[this.dispatchForm.department] || []
: [];
},
- detailTableData() {
- return [
- {
- label: '工单名称',
- value: this.currentDetail.orderName,
- editable: this.currentDetail.status === 0,
- type: 'input',
- },
- {
- label: '关键任务',
- value: this.currentDetail.keyData,
- editable: false,
- },
- {
- label: '工单创建人',
- value: this.currentDetail.creator,
- editable: false,
- },
- {
- label: '当前状态',
- value: this.mapStatus(this.currentDetail.status),
- editable: false,
- },
- {
- 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.startTime,
- editable: false,
- },
- {
- label: '工单内容',
- value: this.currentDetail.content,
- editable: this.currentDetail.status === 0,
- type: 'textarea',
- },
- ];
- },
- detailFields() {
- return [
- {
- label: '工单名称',
- value: this.currentDetail.orderName,
- editable: this.currentDetail.status === 0,
- type: 'input',
- },
- { label: '关键任务', value: this.currentDetail.keyData, editable: false },
- { label: '工单创建人', value: this.currentDetail.creator, editable: false },
- { label: '当前状态', value: this.mapStatus(this.currentDetail.status), editable: false },
- { 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.startTime, editable: false },
- {
- label: '工单内容',
- value: this.currentDetail.content,
- editable: this.currentDetail.status === 0,
- type: 'textarea',
- },
- ];
- },
- formattedDetailFields() {
- const fields = [
- { label: '工单名称', value: this.currentDetail.orderName },
- {
- label: '工单类型',
- // 修改这里:使用 types 数组查找对应的 label
- value:
- this.types.find(t => t.value === this.currentDetail.type)?.label ||
- this.currentDetail.type,
- },
- { label: '关联任务', value: this.currentDetail.job_name || '/' },
- { label: '工单创建人', value: this.currentDetail.creator },
- { label: '当前状态', value: this.mapStatus(this.currentDetail.status) },
- { label: '事件地址', value: this.currentDetail.address || this.currentDetail.latAndLon }, // 包含经纬度信息
- {
- label: '关联算法',
- value:
- this.algorithms.find(t => t.value === this.currentDetail.aiType)?.label ||
- this.currentDetail.aiType,
- },
- { label: '发起单位', value: this.currentDetail.department },
- { label: '发起任务时间', value: this.currentDetail.startTime },
- { label: '工单内容', value: this.currentDetail.content },
- ];
- // 过滤掉值为 '/' 的列
- const filteredFields = fields.filter(field => field.value !== '/');
- // 将字段分成两列
- const formattedFields = [];
- for (let i = 0; i < filteredFields.length; i += 2) {
- formattedFields.push({
- label1: filteredFields[i]?.label || '',
- value1: filteredFields[i]?.value || (filteredFields[i]?.label ? '暂无数据' : ''),
- label2: filteredFields[i + 1]?.label || '',
- value2: filteredFields[i + 1]?.value || (filteredFields[i + 1]?.label ? '暂无数据' : ''),
- });
- }
-
- return formattedFields;
- },
dynamicFixedStatuses() {
// 直接使用接口返回的 stepInfos
return this.stepInfos.map(step => String(step.status));
@@ -962,7 +772,6 @@
// 更新当前详情
updateCurrentDetail() {
this.currentDetail = this.tableData[this.currentIndex];
- console.log('当前',this.currentDetail);
this.currentDetail.mediaUrl = this.currentDetail.photo_url;
this.currentDetail.updatePhotoUrl = this.currentDetail.update_photo_url;
this.currentDetail.processingDetail = this.currentDetail.processingDetail;
@@ -981,9 +790,7 @@
this.currentDetail = detail;
this.dispatchDialogVisible = true;
},
- async handleQRCode(val) {
- val.showQR = !val.showQR;
- },
+
async loadAMapScripts() {
try {
const areaCode = this.userInfo.detail.areaCode;
@@ -1015,7 +822,6 @@
this.$message.error('地图加载失败,请检查网络或API Key配置');
}
},
-
async fetchDropdownData() {
try {
const response = await getTicketInfo();
@@ -1067,7 +873,7 @@
}
},
-
+ // 获取表格数据
async fetchTableData() {
if (this.isFetching) return;
this.isFetching = true;
@@ -1172,7 +978,41 @@
}
},
+ handleTypeChange(typeValue) {
+ // this.form.algorithm = [];
+ if (!typeValue) {
+ // 未选择类型时清空算法列表
+ this.algorithms2 = [];
+ this.algorithms3 = [];
+ return;
+ }
+ const matchedCategory = this.allAlgorithms.find(category => category.dict_key === typeValue);
+
+ if (
+ !matchedCategory ||
+ !matchedCategory.algorithms ||
+ matchedCategory.algorithms.length === 0
+ ) {
+ // 无匹配的算法时清空
+ this.algorithms2 = [];
+ this.algorithms3 = [];
+ this.$message.info('该工单类型暂无关联算法');
+ return;
+ }
+ this.algorithms2 = matchedCategory.algorithms.map(algo => ({
+ label: algo.dict_value,
+ value: algo.dict_key,
+ dict_key: algo.dict_key,
+ dict_value: algo.dict_value,
+ }));
+ this.algorithms3 = matchedCategory.algorithms.map(algo => ({
+ label: algo.dict_value,
+ value: algo.dict_key,
+ dict_key: algo.dict_key,
+ dict_value: algo.dict_value,
+ }));
+ },
formatDate(date) {
if (!date) return undefined;
const d = new Date(date);
@@ -1294,13 +1134,6 @@
},
- formatLocation(location) {
- if (!Array.isArray(location)) {
- return '未知位置';
- }
- return `${location[0].toFixed(6)}, ${location[1].toFixed(6)}`;
- },
-
async getStepInfoData(val) {
try {
const orderNum = val
@@ -1331,8 +1164,6 @@
};
});
}
- console.log('stepInfos',this.stepInfos);
-
return true; // 表示成功获取数据
} catch (error) {
console.error('获取步骤信息失败:', error);
@@ -1367,10 +1198,8 @@
// 获取步骤信息
await this.getStepInfoData(row.orderNumber);
-
this.currentDetail.status = row.status;
-
- console.log(detailData, 'detailDatadetailDatadetailData');
+
this.currentDetail = {
...detailData,
showQR: false,
@@ -1380,7 +1209,7 @@
console.log('this.currentDetail', this.currentDetail);
this.detailVisible = true;
-
+ this.handleTypeChange(this.currentDetail.type);
// 重置上传组件的文件列表
this.$nextTick(() => {
if (this.$refs.MapContainer && this.$refs.MapContainer.initAddEntity) {
@@ -1397,41 +1226,7 @@
handleDetailError(error) {
console.error('工单操作失败:', error);
},
- getStepHandler(status) {
- const step = this.stepInfos.find(step => step.status === status);
- return step ? step.name : '';
- },
- getStepTime(status) {
- const step = this.stepInfos.find(step => step.status === status);
- // 如果 step 不存在或 step.time 为 0,返回 false
- return step && step.time && step.time !== '0' ? step.time : false;
- },
- getStepCreateTime(status) {
- const step = this.stepInfos.find(step => step.status === status);
- return step ? step.create_time : null;
- },
- getActiveStep() {
- // 步骤索引适配
- const arr = this.stepStatusList;
- const index = arr.indexOf(String(this.currentDetail.status));
- return index !== -1 ? index + 2 : 1;
- },
-
- openMap() {
- const areaCode = this.userInfo.detail.areaCode;
- const subAreaCode = areaCode ? areaCode.substring(0, 6) : '';
- getAdcodeObj(geoJson, 'adcode', subAreaCode);
- this.$message.info('地图选址功能暂未实现');
- },
-
- handlePreview(file) {
- this.$message.info(`预览图片:${file.name}`);
- },
-
- handleRemove(file) {
- this.$message.info(`移除图片:${file.name}`);
- },
refreshChange() {
if (this.isFetching) return;
@@ -1508,113 +1303,11 @@
工单状态: this.mapStatus(Number(item.status || 0)),
};
},
- async approveTicket() {
- if (this.approveLoading) return;
- this.approveLoading = true;
- try {
- const data = {
- id: this.currentDetail.id,
- status: this.currentDetail.status,
- isPass: 0, // 0 表示通过
- eventNum: this.currentDetail.orderNumber,
- };
- const file = this.currentDetail.file || null; // 如果没有文件,则为 null
-
- const response = await flowEvent(data, file);
- if (response.data.code === 0) {
- this.$message.success('工单已通过');
- this.detailVisible = false;
- this.fetchTableData();
- } else {
- throw new Error(response.data.msg || '操作失败');
- }
- } catch (error) {
- this.$message.error(error.message || '操作失败,请稍后重试');
- } finally {
- this.approveLoading = false;
- }
- },
- async rejectTicket() {
- if (this.rejectLoading) return;
- this.rejectLoading = true;
- try {
- const data = {
- id: this.currentDetail.id,
- status: this.currentDetail.status,
- isPass: 1, // 1 表示不通过
- };
-
- const response = await flowEvent(data);
- if (response.data.code === 0) {
- this.$message.success('工单未通过');
- this.detailVisible = false;
- this.fetchTableData();
- } else {
- throw new Error(response.data.msg || '操作失败');
- }
- } catch (error) {
- this.$message.error(error.message || '操作失败,请稍后重试');
- } finally {
- this.rejectLoading = false;
- }
- },
- async submitProcessing() {
- if (this.currentDetail.status !== 3) {
- this.$message.warning('只有处理中状态的工单可以提交处理详情');
- return;
- }
-
- try {
- const data = {
- id: this.currentDetail.id, // 当前工单 ID
- status: this.currentDetail.status, // 当前工单状态
- processing_details: this.currentDetail.processingDetail, // 事件处理详情
- };
-
- // 如果有图片,添加 file 参数
- const file = this.currentDetail.photos?.[0]?.raw || null;
-
- const response = await flowEvent(data, file);
- if (response.data.code === 0) {
- this.$message.success('处理详情提交成功');
- this.detailVisible = false;
- this.fetchTableData();
- } else {
- throw new Error(response.data.msg || '提交失败');
- }
- } catch (error) {
- console.error('处理详情提交失败:', error);
- this.$message.error(error.message || '提交失败,请稍后重试');
- }
- },
markAsCompleted() {
this.$message.success('工单已标记为完成');
},
-
- async approveAndDispatch() {
- if (this.dispatchLoading) return;
-
- // 添加必填项检查
- if (!this.currentDetail.orderName || !this.currentDetail.orderName.trim()) {
- this.$message.warning('请填写工单名称');
- return;
- }
- if (!this.currentDetail.aiType) {
- this.$message.warning('请选择关联算法');
- return;
- }
- if (!this.currentDetail.content || !this.currentDetail.content.trim()) {
- this.$message.warning('请填写工单内容');
- return;
- }
-
- // 通过验证后,打开派发对话框
- this.dispatchDialogVisible = true;
-
- console.log('受理', this.currentDetail);
- },
- // 派发成功回调
+ // 派发成功回调
handleDispatchSuccess() {
this.detailVisible = false;
this.fetchTableData();
@@ -1625,21 +1318,7 @@
// 可以在这里处理错误,或者保持空实现
console.error('派发失败:', error);
},
- hasProcessingBtnPermission() {
- // undefined 或 false 都返回 false,只有 true 返回 true
- // console.log('权限检查:', this.permission.tickets_processing_btn)
- 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 finalizeTicket() {
if (this.finalizeLoading) return;
this.finalizeLoading = true;
@@ -2032,14 +1711,6 @@
};
</script>
<style lang="scss">
-.custom-dialog {
- max-height: 96vh;
-
- .el-dialog__body {
- border-top: 0.1rem solid #f0f0f0;
- }
-}
-
.custom-qrcode-popover {
min-width: 160px !important;
min-height: 140px !important;
diff --git a/src/views/tickets/ticketComponent/CreateTicketDialog.vue b/src/views/tickets/ticketComponent/CreateTicketDialog.vue
index b7eaa42..3c9f952 100644
--- a/src/views/tickets/ticketComponent/CreateTicketDialog.vue
+++ b/src/views/tickets/ticketComponent/CreateTicketDialog.vue
@@ -397,16 +397,13 @@
this.dialogVisible = false;
this.resetForm();
},
-
handleTypeChange(typeValue) {
this.form.algorithm = [];
if (!typeValue) {
this.availableAlgorithms = [];
return;
}
-
const matchedCategory = this.allAlgorithms.find(category => category.dict_key === typeValue);
-
if (!matchedCategory || !matchedCategory.algorithms || matchedCategory.algorithms.length === 0) {
this.availableAlgorithms = [];
this.$message.info('该工单类型暂无关联算法');
@@ -421,7 +418,7 @@
}));
},
- handleDepartmentChange(deptId) {
+ handleDepartmentChange() {
this.form.handler = '';
},
diff --git a/src/views/tickets/ticketComponent/TicketDetailDialog.vue b/src/views/tickets/ticketComponent/TicketDetailDialog.vue
index dc1acca..af8f87a 100644
--- a/src/views/tickets/ticketComponent/TicketDetailDialog.vue
+++ b/src/views/tickets/ticketComponent/TicketDetailDialog.vue
@@ -15,8 +15,7 @@
</div>
<div class="event-title-center">{{ currentDetail.orderName || '事件名称' }}</div>
</div>
- <div v-if="totalTime" class="event-total-time">总耗时:{{ totalTime }}</div>
-
+ <div v-if="totalTime" class="event-total-time">总耗时:{{ totalTime }}</div>
<!-- 工单状态流程 -->
<div class="custom-steps-container">
<!-- 标题行 -->
@@ -380,392 +379,431 @@
</el-dialog>
</template>
-<script>
+<script setup>
+import { ref, computed, watch, nextTick } from 'vue';
import { flowEvent, getStepInfo } from '@/api/tickets/ticket';
import { getSmallImg, getShowImg } from '@/utils/util';
import CreateQRcode from '@/components/CreateQRcode/CreateQRcode.vue';
-
-export default {
- name: 'TicketDetailDialog',
- components: {
- CreateQRcode
+import { ElMessage} from 'element-plus';
+// 定义props
+const props = defineProps({
+ modelValue: {
+ type: Boolean,
+ default: false
},
- props: {
- modelValue: {
- type: Boolean,
- default: false
+ currentDetail: {
+ type: Object,
+ default: () => ({})
+ },
+ currentIndex: {
+ type: Number,
+ default: 0
+ },
+ totalItems: {
+ type: Number,
+ default: 0
+ },
+ algorithms: {
+ type: Array,
+ default: () => []
+ },
+ types: {
+ type: Array,
+ default: () => []
+ },
+ permission: {
+ type: Object,
+ default: () => ({})
+ },
+ stepStatusList: {
+ type: Array,
+ default: () => []
+ },
+ workType: {
+ type: Number,
+ default: 0
+ }
+});
+
+// 定义emits
+const emit = defineEmits([
+ 'update:modelValue',
+ 'detail-success',
+ 'detail-error',
+ 'prev-item',
+ 'next-item',
+ 'update:currentDetail',
+ 'approve-and-dispatch'
+]);
+
+// 响应式数据
+const stepInfos = ref([]);
+const totalTime = ref('');
+const approveLoading = ref(false);
+const rejectLoading = ref(false);
+const dispatchLoading = ref(false);
+const completeLoading = ref(false);
+const finalizeLoading = ref(false);
+const uploadRef = ref(null);
+const mapContainerRef = ref(null);
+
+// 计算属性
+const dialogVisible = computed({
+ get() {
+ return props.modelValue;
+ },
+ set(value) {
+ emit('update:modelValue', value);
+ }
+});
+
+const isEditMode = computed(() => {
+ return props.currentDetail.status === -1;
+});
+
+const formattedDetailFields = computed(() => {
+ const fields = [
+ { label: '工单名称', value: props.currentDetail.orderName },
+ {
+ label: '工单类型',
+ value: props.types.find(t => t.value === props.currentDetail.type)?.label || props.currentDetail.type,
},
- currentDetail: {
- type: Object,
- default: () => ({})
+ { label: '关联任务', value: props.currentDetail.job_name || '/' },
+ { label: '工单创建人', value: props.currentDetail.creator },
+ { label: '当前状态', value: mapStatus(props.currentDetail.status) },
+ { label: '事件地址', value: props.currentDetail.address || props.currentDetail.latAndLon },
+ {
+ label: '关联算法',
+ value: props.algorithms.find(t => t.value === props.currentDetail.aiType)?.label || props.currentDetail.aiType,
},
- currentIndex: {
- type: Number,
- default: 0
- },
- totalItems: {
- type: Number,
- default: 0
- },
- algorithms: {
- type: Array,
- default: () => []
- },
- types: {
- type: Array,
- default: () => []
- },
- permission: {
- type: Object,
- default: () => ({})
- },
- stepStatusList: {
- type: Array,
- default: () => []
- },
- workType: {
- type: Number,
- default: 0
+ { label: '发起单位', value: props.currentDetail.department },
+ { label: '发起任务时间', value: props.currentDetail.startTime },
+ { label: '工单内容', value: props.currentDetail.content },
+ ];
+
+ const filteredFields = fields.filter(field => field.value !== '/');
+ const formattedFields = [];
+ for (let i = 0; i < filteredFields.length; i += 2) {
+ formattedFields.push({
+ label1: filteredFields[i]?.label || '',
+ value1: filteredFields[i]?.value || (filteredFields[i]?.label ? '暂无数据' : ''),
+ label2: filteredFields[i + 1]?.label || '',
+ value2: filteredFields[i + 1]?.value || (filteredFields[i + 1]?.label ? '暂无数据' : ''),
+ });
+ }
+
+ return formattedFields;
+});
+
+// 监听
+watch(
+ () => props.modelValue,
+ (newVal) => {
+ if (newVal) {
+ loadStepInfo();
+ initMap();
+ }
+ }
+);
+
+watch(
+ () => props.currentDetail,
+ (newVal) => {
+ if (newVal && dialogVisible.value) {
+ loadStepInfo();
+ initMap();
}
},
- emits: [
- 'update:modelValue',
- 'detail-success',
- 'detail-error',
- 'prev-item',
- 'next-item',
- 'update:currentDetail'
- ],
- data() {
- return {
- stepInfos: [],
- totalTime: '',
- approveLoading: false,
- rejectLoading: false,
- dispatchLoading: false,
- completeLoading: false,
- finalizeLoading: false
+ { deep: true }
+);
+
+// 方法
+const handleClose = () => {
+ dialogVisible.value = false;
+};
+
+const handlePrev = () => {
+ if (props.currentIndex > 0) {
+ emit('prev-item');
+ }
+};
+
+const handleNext = () => {
+ if (props.currentIndex < props.totalItems - 1) {
+ emit('next-item');
+ }
+};
+
+const loadStepInfo = async () => {
+ try {
+ const stepResponse = await getStepInfo(props.currentDetail.orderNumber);
+ const steps = Array.isArray(stepResponse.data.data)
+ ? stepResponse.data.data
+ : stepResponse.data.data?.steps || [];
+
+ const finishedStep = steps.find(s => String(s.status) === '4');
+ totalTime.value = finishedStep && finishedStep.total_time ? finishedStep.total_time : '';
+
+ stepInfos.value = steps.map(step => ({
+ status: String(step.status),
+ name: step.name,
+ time: step.time,
+ create_time: step.create_time,
+ }));
+ } catch (error) {
+ stepInfos.value = [];
+ }
+};
+
+const initMap = () => {
+ nextTick(() => {
+ if (mapContainerRef.value && mapContainerRef.value.initAddEntity && props.currentDetail.location) {
+ mapContainerRef.value.initAddEntity('point', props.currentDetail.location);
+ }
+ });
+};
+
+const mapStatus = (status) => {
+ const statusTextMap = {
+ '-1': '草稿',
+ 2: '待审核',
+ 0: '待处理',
+ 3: '处理中',
+ 4: '已完成',
+ };
+ return statusTextMap[status] || '未知状态';
+};
+
+const getStepHandler = (status) => {
+ const step = stepInfos.value.find(step => step.status === status);
+ return step ? step.name : '';
+};
+
+const getStepTime = (status) => {
+ const step = stepInfos.value.find(step => step.status === status);
+ return step && step.time && step.time !== '0' ? step.time : false;
+};
+
+const getStepCreateTime = (status) => {
+ const step = stepInfos.value.find(step => step.status === status);
+ return step ? step.create_time : null;
+};
+
+const getActiveStep = () => {
+ const arr = props.stepStatusList;
+ const index = arr.indexOf(String(props.currentDetail.status));
+ return index !== -1 ? index + 2 : 1;
+};
+
+const handleQRCode = (val) => {
+ emit('update:currentDetail', {
+ ...props.currentDetail,
+ showQR: !val.showQR
+ });
+};
+
+const getThumbUrl = (url) => {
+ if (!url) return '';
+ return getSmallImg(url);
+};
+
+const getPreviewUrl = (url) => {
+ if (!url) return '';
+ return getShowImg(url);
+};
+
+const hasProcessingBtnPermission = () => {
+ return props.permission && props.permission.tickets_processing_btn === true;
+};
+
+const hasProcessedAndOverBtnPermission = () => {
+ return props.permission && props.permission.tickets_view_processedAndOver === true;
+};
+
+const hasReviewBtnPermission = () => {
+ return props.permission && props.permission.tickets_review_btn === true;
+};
+
+// 文件操作方法
+const handleFileChange = (file, fileList) => {
+ emit('update:currentDetail', {
+ ...props.currentDetail,
+ photos: fileList
+ });
+};
+
+const handleUploadRemove = (file, fileList) => {
+ emit('update:currentDetail', {
+ ...props.currentDetail,
+ photos: fileList
+ });
+};
+
+const beforeUpload = (file) => {
+ const isImage = file.type.includes('image');
+ const isLt5M = file.size / 1024 / 1024 < 5;
+
+ if (!isImage) {
+ ElMessage.error('只能上传图片文件!');
+ return false;
+ }
+ if (!isLt5M) {
+ ElMessage.error('图片大小不能超过5MB!');
+ return false;
+ }
+ return true;
+};
+
+// 工单操作方法
+const handleApprove = async () => {
+ if (approveLoading.value) return;
+ approveLoading.value = true;
+
+ try {
+ const data = {
+ id: props.currentDetail.id,
+ status: props.currentDetail.status,
+ isPass: 0,
+ eventNum: props.currentDetail.orderNumber,
};
- },
- computed: {
- dialogVisible: {
- get() {
- return this.modelValue;
- },
- set(value) {
- this.$emit('update:modelValue', value);
- }
- },
- isEditMode() {
- return this.currentDetail.status === -1;
- },
- formattedDetailFields() {
- const fields = [
- { label: '工单名称', value: this.currentDetail.orderName },
- {
- label: '工单类型',
- value: this.types.find(t => t.value === this.currentDetail.type)?.label || this.currentDetail.type,
- },
- { label: '关联任务', value: this.currentDetail.job_name || '/' },
- { label: '工单创建人', value: this.currentDetail.creator },
- { label: '当前状态', value: this.mapStatus(this.currentDetail.status) },
- { label: '事件地址', value: this.currentDetail.address || this.currentDetail.latAndLon },
- {
- label: '关联算法',
- value: this.algorithms.find(t => t.value === this.currentDetail.aiType)?.label || this.currentDetail.aiType,
- },
- { label: '发起单位', value: this.currentDetail.department },
- { label: '发起任务时间', value: this.currentDetail.startTime },
- { label: '工单内容', value: this.currentDetail.content },
- ];
- const filteredFields = fields.filter(field => field.value !== '/');
- const formattedFields = [];
- for (let i = 0; i < filteredFields.length; i += 2) {
- formattedFields.push({
- label1: filteredFields[i]?.label || '',
- value1: filteredFields[i]?.value || (filteredFields[i]?.label ? '暂无数据' : ''),
- label2: filteredFields[i + 1]?.label || '',
- value2: filteredFields[i + 1]?.value || (filteredFields[i + 1]?.label ? '暂无数据' : ''),
- });
- }
-
- return formattedFields;
+ const response = await flowEvent(data);
+ if (response.data.code === 0) {
+ ElMessage.success('工单已通过');
+ emit('detail-success');
+ handleClose();
+ } else {
+ throw new Error(response.data.msg || '操作失败');
}
- },
- watch: {
- modelValue(newVal) {
- if (newVal) {
- this.loadStepInfo();
- this.initMap();
- }
- },
- currentDetail: {
- handler(newVal) {
- if (newVal && this.dialogVisible) {
- this.loadStepInfo();
- this.initMap();
- }
- },
- deep: true
+ } catch (error) {
+ ElMessage.error(error.message || '操作失败,请稍后重试');
+ emit('detail-error', error);
+ } finally {
+ approveLoading.value = false;
+ }
+};
+
+const handleReject = async () => {
+ if (rejectLoading.value) return;
+ rejectLoading.value = true;
+
+ try {
+ const data = {
+ id: props.currentDetail.id,
+ status: props.currentDetail.status,
+ isPass: 1,
+ };
+
+ const response = await flowEvent(data);
+ if (response.data.code === 0) {
+ ElMessage.success('工单未通过');
+ emit('detail-success');
+ handleClose();
+ } else {
+ throw new Error(response.data.msg || '操作失败');
}
- },
- methods: {
- handleClose() {
- this.dialogVisible = false;
- },
+ } catch (error) {
+ ElMessage.error(error.message || '操作失败,请稍后重试');
+ emit('detail-error', error);
+ } finally {
+ rejectLoading.value = false;
+ }
+};
- handlePrev() {
- if (this.currentIndex > 0) {
- this.$emit('prev-item');
- }
- },
+const handleApproveAndDispatch = () => {
+ // 触发派发工单操作,由父组件处理
+ emit('approve-and-dispatch', props.currentDetail);
+};
- handleNext() {
- if (this.currentIndex < this.totalItems - 1) {
- this.$emit('next-item');
- }
- },
-
- async loadStepInfo() {
- try {
- const stepResponse = await getStepInfo(this.currentDetail.orderNumber);
- const steps = Array.isArray(stepResponse.data.data)
- ? stepResponse.data.data
- : stepResponse.data.data?.steps || [];
-
- const finishedStep = steps.find(s => String(s.status) === '4');
- this.totalTime = finishedStep && finishedStep.total_time ? finishedStep.total_time : '';
-
- this.stepInfos = steps.map(step => ({
- status: String(step.status),
- name: step.name,
- time: step.time,
- create_time: step.create_time,
- }));
- } catch (error) {
- console.error('加载步骤信息失败:', error);
- this.stepInfos = [];
- }
- },
-
- initMap() {
- this.$nextTick(() => {
- if (this.$refs.mapContainerRef && this.$refs.mapContainerRef.initAddEntity && this.currentDetail.location) {
- this.$refs.mapContainerRef.initAddEntity('point', this.currentDetail.location);
- }
- });
- },
-
- mapStatus(status) {
- const statusTextMap = {
- '-1': '草稿',
- 2: '待审核',
- 0: '待处理',
- 3: '处理中',
- 4: '已完成',
- };
- return statusTextMap[status] || '未知状态';
- },
-
- getStepHandler(status) {
- const step = this.stepInfos.find(step => step.status === status);
- return step ? step.name : '';
- },
-
- getStepTime(status) {
- const step = this.stepInfos.find(step => step.status === status);
- return step && step.time && step.time !== '0' ? step.time : false;
- },
-
- getStepCreateTime(status) {
- const step = this.stepInfos.find(step => step.status === status);
- return step ? step.create_time : null;
- },
-
- getActiveStep() {
- const arr = this.stepStatusList;
- console.log('stepStatusList',this.stepStatusList);
-
- const index = arr.indexOf(String(this.currentDetail.status));
- return index !== -1 ? index + 2 : 1;
- },
-
- handleQRCode(val) {
- this.$emit('update:currentDetail', {
- ...this.currentDetail,
- showQR: !val.showQR
- });
- },
-
- getThumbUrl(url) {
- if (!url) return '';
- return getSmallImg(url);
- },
-
- getPreviewUrl(url) {
- if (!url) return '';
- return getShowImg(url);
- },
-
- hasProcessingBtnPermission() {
- return this.permission && this.permission.tickets_processing_btn === true;
- },
-
- hasProcessedAndOverBtnPermission() {
- return this.permission && this.permission.tickets_view_processedAndOver === true;
- },
-
- hasReviewBtnPermission() {
- return this.permission && this.permission.tickets_review_btn === true;
- },
-
- // 文件操作方法
- handleFileChange(file, fileList) {
- this.$emit('update:currentDetail', {
- ...this.currentDetail,
- photos: fileList
- });
- },
-
- handleUploadRemove(file, fileList) {
- this.$emit('update:currentDetail', {
- ...this.currentDetail,
- photos: fileList
- });
- },
-
- beforeUpload(file) {
- const isImage = file.type.includes('image');
- const isLt5M = file.size / 1024 / 1024 < 5;
-
- if (!isImage) {
- this.$message.error('只能上传图片文件!');
- return false;
- }
- if (!isLt5M) {
- this.$message.error('图片大小不能超过5MB!');
- return false;
- }
- return true;
- },
-
- // 工单操作方法
- async handleApprove() {
- if (this.approveLoading) return;
- this.approveLoading = true;
-
- try {
- const data = {
- id: this.currentDetail.id,
- status: this.currentDetail.status,
- isPass: 0,
- eventNum: this.currentDetail.orderNumber,
- };
-
- const response = await flowEvent(data);
- if (response.data.code === 0) {
- this.$message.success('工单已通过');
- this.$emit('detail-success');
- this.handleClose();
- } else {
- throw new Error(response.data.msg || '操作失败');
- }
- } catch (error) {
- this.$message.error(error.message || '操作失败,请稍后重试');
- this.$emit('detail-error', error);
- } finally {
- this.approveLoading = false;
- }
- },
-
- async handleReject() {
- if (this.rejectLoading) return;
- this.rejectLoading = true;
-
- try {
- const data = {
- id: this.currentDetail.id,
- status: this.currentDetail.status,
- isPass: 1,
- };
-
- const response = await flowEvent(data);
- if (response.data.code === 0) {
- this.$message.success('工单未通过');
- this.$emit('detail-success');
- this.handleClose();
- } else {
- throw new Error(response.data.msg || '操作失败');
- }
- } catch (error) {
- this.$message.error(error.message || '操作失败,请稍后重试');
- this.$emit('detail-error', error);
- } finally {
- this.rejectLoading = false;
- }
- },
-
- handleApproveAndDispatch() {
- // 触发派发工单操作,由父组件处理
- this.$emit('approve-and-dispatch', this.currentDetail);
- },
-
- async handleComplete() {
- if (this.completeLoading) return;
- this.completeLoading = true;
-
- try {
- if (!this.currentDetail.processingDetail) {
- this.$message.warning('请先填写事件处理详情');
- return;
- }
-
- if (!this.currentDetail.photos || this.currentDetail.photos.length === 0) {
- this.$message.warning('请选择上传图片');
- this.completeLoading = false;
- return;
- }
-
- const data = {
- id: this.currentDetail.id,
- status: this.currentDetail.status,
- processingDetails: this.currentDetail.processingDetail,
- eventNum: this.currentDetail.orderNumber,
- };
-
- const file = this.currentDetail.photos?.[0]?.raw || null;
-
- const response = await flowEvent(data, file);
-
- if (response.data.code === 0) {
- this.$message.success('工单已完成');
- this.$emit('detail-success');
- this.handleClose();
- } else {
- throw new Error(response.data.msg || '操作失败');
- }
- } catch (error) {
- console.error('完成工单失败:', error);
- this.$message.error(error.message || '操作失败,请稍后重试');
- this.$emit('detail-error', error);
- } finally {
- this.completeLoading = false;
- }
+const handleComplete = async () => {
+ if (completeLoading.value) return;
+ completeLoading.value = true;
+
+ try {
+ if (!props.currentDetail.processingDetail) {
+ ElMessage.warning('请先填写事件处理详情');
+ return;
}
+
+ if (!props.currentDetail.photos || props.currentDetail.photos.length === 0) {
+ ElMessage.warning('请选择上传图片');
+ completeLoading.value = false;
+ return;
+ }
+
+ const data = {
+ id: props.currentDetail.id,
+ status: props.currentDetail.status,
+ processingDetails: props.currentDetail.processingDetail,
+ eventNum: props.currentDetail.orderNumber,
+ };
+
+ const file = props.currentDetail.photos?.[0]?.raw || null;
+
+ const response = await flowEvent(data, file);
+
+ if (response.data.code === 0) {
+ ElMessage.success('工单已完成');
+ emit('detail-success');
+ handleClose();
+ } else {
+ throw new Error(response.data.msg || '操作失败');
+ }
+ handleClose();
+ } catch (error) {
+ console.error('完成工单失败:', error);
+ ElMessage.error(error.message || '操作失败,请稍后重试');
+ emit('detail-error', error);
+ handleClose();
+ } finally {
+ completeLoading.value = false;
+ handleClose();
}
};
</script>
+
<style lang="scss">
.custom-dialog {
- max-height: 95vh;
-
- :deep(.el-dialog__body) {
+ max-height: 96vh;
+ transition: max-height 0.3s ease-out;
+ .el-dialog__body {
border-top: 0.1rem solid #f0f0f0;
+ }
+}
+
+.custom-qrcode-popover {
+ min-width: 160px !important;
+ min-height: 140px !important;
+ position: relative;
+
+ .qrcode-content {
+ margin-top: 8px;
+
+ .close-btn {
+ position: absolute;
+ top: 2px;
+ right: 2px;
+ width: 16px;
+ height: 16px;
+ line-height: 16px;
+ text-align: center;
+ cursor: pointer;
+ color: #999;
+ font-size: 16px;
+ z-index: 10;
+ }
}
}
</style>
<style lang="scss" scoped>
+.uploadImg {
+ margin-bottom: 32px;
+}
+
+.tableCss {
+ width: 100%;
+ margin-bottom: 10px;
+}
.step-timer {
position: absolute;
@@ -777,6 +815,138 @@
color: #666;
font-size: 12px;
}
+
+.event-total-time {
+ text-align: center;
+ color: #666;
+ font-size: 15px;
+ margin-bottom: 12px;
+}
+
+
+.el-dialog {
+ .el-form-item {
+ margin-bottom: 20px;
+ }
+}
+
+.el-upload {
+ width: 100%;
+ display: flex;
+ flex-wrap: wrap;
+
+ :deep(.el-upload-list__item) {
+ transition: all 0.3s ease;
+ }
+
+ :deep(.el-upload-list__item:hover) {
+ background-color: #f5f7fa;
+ }
+}
+
+.el-upload__tip {
+ font-size: 12px;
+ color: #909399;
+ margin-top: 12px;
+}
+
+:deep(.el-dialog__body) {
+ border-top: 0.1rem solid #f0f0f0;
+}
+
+
+.dialog-footer1-new {
+ position: sticky;
+ bottom: 28px;
+ left: 0;
+ right: 0;
+ background: white;
+ z-index: 10;
+ padding: 16px 20px;
+ border-top: 1px solid #ebeef5;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ .el-button + .el-button {
+ margin-left: 12px;
+ }
+
+ .btngroups {
+ margin-left: 12px;
+ }
+
+ .el-button {
+ padding: 9px 20px;
+
+ &:last-child {
+ margin-left: 12px;
+ margin-right: 12px;
+ }
+ }
+}
+
+.map-container {
+ width: 100%;
+ height: 400px;
+ margin-bottom: 15px;
+ border: 1px solid #dcdfe6;
+ border-radius: 4px;
+ overflow: hidden;
+
+ :deep(.el-input-map) {
+ height: 100%;
+ }
+}
+
+
+.map-select {
+ display: flex;
+ align-items: flex-start;
+ gap: 15px;
+
+ .selected-location {
+ flex: 1;
+ padding: 5px 10px;
+ background-color: #f5f7fa;
+ border-radius: 4px;
+
+ p {
+ margin: 5px 0;
+ color: #606266;
+ font-size: 14px;
+ }
+ }
+}
+
+.preview-image {
+ border-radius: 4px;
+ overflow: hidden;
+ background-color: #f5f7fa;
+}
+
+.image-placeholder,
+.image-error,
+.no-media {
+ height: 200px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ color: #909399;
+ background-color: #f5f7fa;
+ border-radius: 4px;
+
+ i {
+ font-size: 32px;
+ margin-bottom: 8px;
+ }
+}
+
+.no-media {
+ border: 1px dashed #d9d9d9;
+}
+
.detail-container {
padding: 0 20px;
@@ -790,44 +960,7 @@
}
}
}
-.event-title-center {
- text-align: center;
- font-size: 20px;
- font-weight: bold;
- margin-bottom: 5px;
- color: #333;
-}
-.event-total-time {
- text-align: center;
- color: #666;
- font-size: 15px;
- margin-bottom: 12px;
-}
-.custom-steps-container {
- width: 100%;
- margin: 10px 0;
-}
-.steps-titles {
- display: flex;
- justify-content: space-between;
- margin-bottom: 14px;
- position: relative;
-}
-
-.step-title {
- text-align: center;
- flex: 1;
- font-size: 14px;
- color: #999;
- position: relative;
- padding-bottom: 5px;
-}
-
-.step-title.active {
- color: #409eff;
- font-weight: bold;
-}
.status-flow {
margin-bottom: 20px;
@@ -887,78 +1020,11 @@
}
}
}
-.step-description {
- font-size: 14px;
- color: #666;
- line-height: 1.5;
- display: block;
- text-align: center;
- &:first-child {
- font-weight: bold;
- margin-bottom: 4px;
- }
+.basic-info {
+ margin-bottom: 20px;
}
-.PopUpTableScrolls {
- max-height: 600px;
- overflow-y: scroll;
- overflow-x: hidden;
-}
-.tableCss {
- width: 100%;
- margin-bottom: 10px;
-}
-/* 必填项样式 */
-.required-label {
- position: relative;
- display: inline-block;
- .required-star {
- color: #f56c6c;
- margin-right: 4px;
- }
-}
-/* 必填输入框样式 */
-.required-input {
- width: 100%;
-
- :deep(.el-input__inner),
- :deep(.el-textarea__inner) {
- &:focus {
- border-color: #409eff;
- }
- }
-}
-/* 新建工单和处理工单的上传组件样式 */
-.create-upload,
-.detail-upload {
- :deep(.el-upload--picture-card) {
- width: 120px;
- height: 100px;
- line-height: 100px;
- }
-
- /* 隐藏额外的上传按钮 */
- :deep(.el-upload.el-upload--picture-card) {
- display: none;
- }
-
- /* 当没有图片时显示上传按钮 */
- :deep(.el-upload.el-upload--picture-card:first-child) {
- display: flex;
- }
-
- /* 上传组件的预览图片样式 */
- :deep(.el-upload-list--picture-card .el-upload-list__item) {
- width: 120px;
- height: 100px;
- }
-}
-.el-upload__tip {
- font-size: 12px;
- color: #909399;
- margin-top: 12px;
-}
.media-section {
// margin-bottom: 20px;
@@ -967,6 +1033,32 @@
align-items: center;
}
}
+
+.leftBtn {
+ width: 70px;
+ height: 32px;
+ background-color: #999;
+ border-radius: 5px;
+ text-align: center;
+ line-height: 32px;
+ color: #fff;
+ cursor: pointer;
+ opacity: 0.8;
+}
+
+.disableds {
+ background: #999 !important;
+ cursor: not-allowed !important;
+ pointer-events: none;
+ opacity: 0.3 !important;
+}
+
+.PopUpTableScrolls {
+ max-height: 600px;
+ overflow-y: scroll;
+ overflow-x: hidden;
+}
+
.media-box {
width: 100%;
border: 1px solid #dcdfe6;
@@ -1006,75 +1098,50 @@
}
}
}
+
.image-placeholder,
.image-error,
.no-media {
- height: 200px;
display: flex;
- flex-direction: column;
align-items: center;
justify-content: center;
+ height: 100%;
color: #909399;
background-color: #f5f7fa;
border-radius: 4px;
+}
- i {
- font-size: 32px;
- margin-bottom: 8px;
- }
+.image-placeholder i,
+.image-error i {
+ font-size: 32px;
+ margin-bottom: 8px;
}
.no-media {
border: 1px dashed #d9d9d9;
}
-.dialog-footer1-new {
- position: sticky;
- bottom: 28px;
- left: 0;
- right: 0;
- background: white;
- z-index: 10;
- padding: 16px 20px;
- border-top: 1px solid #ebeef5;
+
+.info-table {
+ margin-bottom: 20px;
+}
+
+.info-item {
display: flex;
- justify-content: space-between;
- align-items: center;
-
- .el-button + .el-button {
- margin-left: 12px;
- }
-
- .btngroups {
- margin-left: 12px;
- }
-
- .el-button {
- padding: 9px 20px;
-
- &:last-child {
- margin-left: 12px;
- margin-right: 12px;
- }
- }
-}
-.leftBtn {
- width: 70px;
- height: 32px;
- background-color: #999;
- border-radius: 5px;
- text-align: center;
- line-height: 32px;
- color: #fff;
- cursor: pointer;
- opacity: 0.8;
+ margin-bottom: 10px;
}
-.disableds {
- background: #999 !important;
- cursor: not-allowed !important;
- pointer-events: none;
- opacity: 0.3 !important;
+.info-label {
+ font-weight: bold;
+ width: 120px;
+ color: #606266;
}
+
+.info-value {
+ flex: 1;
+ color: #303133;
+ word-break: break-word;
+}
+
.readonly-processing-detail {
background-color: #f5f7fa;
padding: 12px;
@@ -1091,4 +1158,144 @@
margin-bottom: 4px;
}
}
-</style>
\ No newline at end of file
+
+// 添加删除按钮样式
+.danger-button {
+ color: #f56c6c;
+}
+
+.danger-button:hover {
+ color: #f78989;
+}
+
+.custom-steps-container {
+ width: 100%;
+ margin: 10px 0;
+}
+
+.steps-titles {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 14px;
+ position: relative;
+}
+
+.step-title {
+ text-align: center;
+ flex: 1;
+ font-size: 14px;
+ color: #999;
+ position: relative;
+ padding-bottom: 5px;
+}
+
+.step-title.active {
+ color: #409eff;
+ font-weight: bold;
+}
+
+.event-title-center {
+ text-align: center;
+ font-size: 20px;
+ font-weight: bold;
+ margin-bottom: 5px;
+ color: #333;
+}
+
+.custom-steps {
+ margin-top: -20px;
+
+ :deep(.el-step__description) {
+ margin-top: 8px;
+ padding: 0 20px;
+ }
+}
+
+.step-description {
+ font-size: 14px;
+ color: #666;
+ line-height: 1.5;
+ display: block;
+ text-align: center;
+
+ &:first-child {
+ font-weight: bold;
+ margin-bottom: 4px;
+ }
+}
+
+// 覆盖其他相关样式
+.status-flow {
+ .custom-steps {
+ .el-step__description {
+ position: relative;
+ margin: 0;
+ padding: 0;
+ }
+
+ // 移除之前的样式
+ .init-step-info,
+ .step-info {
+ display: block;
+ width: auto;
+ text-align: center;
+ }
+ }
+}
+
+/* 新建工单和处理工单的上传组件样式 */
+.create-upload,
+.detail-upload {
+ :deep(.el-upload--picture-card) {
+ width: 120px;
+ height: 100px;
+ line-height: 100px;
+ }
+
+ /* 隐藏额外的上传按钮 */
+ :deep(.el-upload.el-upload--picture-card) {
+ display: none;
+ }
+
+ /* 当没有图片时显示上传按钮 */
+ :deep(.el-upload.el-upload--picture-card:first-child) {
+ display: flex;
+ }
+
+ /* 上传组件的预览图片样式 */
+ :deep(.el-upload-list--picture-card .el-upload-list__item) {
+ width: 120px;
+ height: 100px;
+ }
+}
+
+/* 原有图片预览的样式 */
+.el-image-viewer__wrapper {
+ :deep(.el-image-viewer__img) {
+ max-width: 100%;
+ max-height: 100%;
+ object-fit: contain;
+ }
+}
+/* 必填项样式 */
+.required-label {
+ position: relative;
+ display: inline-block;
+
+ .required-star {
+ color: #f56c6c;
+ margin-right: 4px;
+ }
+}
+/* 必填输入框样式 */
+.required-input {
+ width: 100%;
+
+ :deep(.el-input__inner),
+ :deep(.el-textarea__inner) {
+ &:focus {
+ border-color: #409eff;
+ }
+ }
+}
+</style>
--
Gitblit v1.9.3