From ac540b51fc76deec7289498a3cf7569970ffd73d Mon Sep 17 00:00:00 2001
From: rain <1679827795@qq.com>
Date: Mon, 14 Apr 2025 18:50:22 +0800
Subject: [PATCH] 新建工单样式优化

---
 src/views/tickets/ticket.vue |  399 +++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 249 insertions(+), 150 deletions(-)

diff --git a/src/views/tickets/ticket.vue b/src/views/tickets/ticket.vue
index e57bfd7..0745d79 100644
--- a/src/views/tickets/ticket.vue
+++ b/src/views/tickets/ticket.vue
@@ -57,11 +57,9 @@
 
     <!-- 新建工单对话框 -->
     <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" class="create-ticket-form">
-        <!-- 基本信息 -->
+      <el-form :model="form" :rules="rules" ref="form" label-width="90px" class="create-ticket-form">
         <div class="form-section">
-          <div class="section-title">基本信息</div>
-          <el-row :gutter="12">
+          <el-row :gutter="16">
             <el-col :span="12">
               <el-form-item label="工单名称" prop="name">
                 <el-input v-model="form.name" placeholder="请输入工单名称"></el-input>
@@ -75,11 +73,11 @@
               </el-form-item>
             </el-col>
           </el-row>
-          <el-row :gutter="12">
+
+          <el-row :gutter="16">
             <el-col :span="12">
               <el-form-item label="所属部门" prop="department">
-                <el-select v-model="form.department" placeholder="请选择所属部门" @change="handleDepartmentChange"
-                  class="full-width">
+                <el-select v-model="form.department" placeholder="请选择所属部门" @change="handleDepartmentChange" class="full-width">
                   <el-option v-for="dept in departments" :key="dept.value" :label="dept.label" :value="dept.value" />
                 </el-select>
               </el-form-item>
@@ -92,7 +90,8 @@
               </el-form-item>
             </el-col>
           </el-row>
-          <el-row :gutter="12">
+
+          <el-row :gutter="16">
             <el-col :span="12">
               <el-form-item label="关联算法" prop="algorithm">
                 <el-select v-model="form.algorithm" placeholder="请选择关联算法" class="full-width">
@@ -100,56 +99,53 @@
                 </el-select>
               </el-form-item>
             </el-col>
-          </el-row>
-        </div>
-
-        <!-- 修改位置信息部分 -->
-        <div class="form-section">
-          <div class="section-title">位置信息</div>
-          <el-row :gutter="12">
-            <el-col :span="24">
-              <el-form-item label="地图选址" prop="location">
-                <div class="map-select">
-                  <!-- 替换地图为按钮 -->
-                  <avue-input-map v-model="form.location" :params="mapParams" @change="handleLocationChange"
-                    type="button">
-                    <el-button type="primary" plain>
-                      <i class="el-icon-map-location"></i> 选择位置
+            <el-col :span="12">
+              <el-form-item label="选择位置" prop="location">
+                <div class="location-wrapper">
+                  <avue-input-map v-model="form.location" :params="mapParams" @change="handleLocationChange" type="button">
+                    <el-button type="primary" plain class="map-button">
+                      <i class="el-icon-map-location"></i> 地图选点
                     </el-button>
                   </avue-input-map>
-
-                  <!-- 添加位置信息显示 -->
-                  <div v-if="form.location && form.location.length >= 2" class="selected-location">
-                    <p>已选位置: {{ formatLocation(form.location) }}</p>
-                    <p>详细地址: {{ form.address || '获取中...' }}</p>
-                  </div>
+                  <div v-if="form.location?.length >= 2" class="location-text">{{ form.address || '获取地址中...' }}</div>
                 </div>
               </el-form-item>
             </el-col>
           </el-row>
-        </div>
 
-        <!-- 工单内容 -->
-        <div class="form-section">
-          <div class="section-title">工单内容</div>
-          <el-form-item label="工单描述" prop="content">
-            <el-input type="textarea" v-model="form.content" rows="3" placeholder="请输入工单内容描述" resize="none"></el-input>
-          </el-form-item>
-          <el-form-item label="附件图片" class="upload-item">
-            <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/*">
-              <i class="el-icon-plus"></i>
-            </el-upload>
-            <div class="el-upload__tip">支持jpg/png格式图片,最多1张,单张不超过5MB</div>
-          </el-form-item>
+          <el-row :gutter="16">
+            <el-col :span="12">
+              <el-form-item label="工单内容" prop="content">
+                <el-input type="textarea" v-model="form.content" :rows="4" placeholder="请输入工单内容描述"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="附件图片" prop="photos" class="upload-wrapper">
+                <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>
+                </el-upload>
+                <div class="upload-tip">支持jpg/png格式图片,单张不超过5MB</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
         </div>
       </el-form>
       <template #footer>
         <div class="dialog-footer">
-          <el-button size="small" @click="dialogVisible = false">取 消</el-button>
-          <el-button size="small" type="info" @click="saveDraft">存草稿</el-button>
-          <el-button size="small" type="primary" @click="submitForm">提 交</el-button>
+          <el-button type="danger" @click="submitForm">确认提交</el-button>
+          <el-button type="primary" plain @click="saveDraft">存草稿</el-button>
+          <el-button @click="dialogVisible = false">取 消</el-button>
         </div>
       </template>
     </el-dialog>
@@ -500,6 +496,27 @@
         department: [{ required: true, message: '请选择所属部门', trigger: 'change' }],
         handler: [{ required: true, message: '请选择处理人员', trigger: 'change' }],
         content: [{ required: true, message: '请输入工单内容', trigger: 'blur' }],
+        algorithm: [{ required: true, message: '请选择关联算法', trigger: 'change' }],
+        location: [{ 
+          validator: (rule, value, callback) => {
+            if (!value || value.length < 2) {
+              callback(new Error('请选择位置信息'));
+            } else {
+              callback();
+            }
+          },
+          trigger: 'change'
+        }],
+        photos: [{ 
+          validator: (rule, value, callback) => {
+            if (!this.form.photos || this.form.photos.length === 0) {
+              callback(new Error('请上传工单图片'));
+            } else {
+              callback();
+            }
+          },
+          trigger: 'change'
+        }],
       },
       departmentUsers: {},
       loading: false,
@@ -523,6 +540,7 @@
       }, // 新增:派发表单验证规则
       stepInfos: [], // 新增:存储步骤信息
       fixedStatuses: ["2", "0", "3", "4", "5"], // 固定的五个状态
+      userNameToIdMap: {}, // 新增用户名到ID的映射
     };
   },
   created() {
@@ -703,6 +721,16 @@
           label: item.dict_value, // 修改为 label
           value: item.dict_key,  // 修改为 value
         }));
+
+        // 构建用户ID和名称的映射关系
+        this.userNameToIdMap = {};
+        dept_data.forEach(dept => {
+          (dept.user_data || []).forEach(user => {
+            this.userNameToIdMap[user.name] = user.id;
+          });
+        });
+
+        console.log('用户名到ID的映射:', this.userNameToIdMap);
       } catch (error) {
         console.error('获取下拉框数据失败:', error);
         this.$message.error('加载下拉框数据失败');
@@ -796,53 +824,63 @@
     },
 
     async submitForm() {
-      this.$refs.form.validate(async (valid) => {
-        if (valid) {
-          if (!this.form.location || this.form.location.length < 2) {
-            this.$message.warning('请在地图上选择位置');
-            return;
-          }
-
-          try {
-            const submitData = {
-              eventName: this.form.name,
-              content: this.form.content,  // 传递工单内容
-              workType: "1",
-              longitude: String(this.form.location[0]),
-              latitude: String(this.form.location[1]),
-              address: this.form.address,
-              eventDictKey: this.form.type,
-              aiType: this.form.algorithm,
-              updateUser: this.form.handler,
-              createDept: this.form.department,
-              isDraft: 0
-            };
-
-            // 如果是编辑状态,添加 id
-            if (this.form.id) {
-              submitData.id = this.form.id;
-            }
-
-            // 获取文件对象
-            let file = null;
-            if (this.form.photos && this.form.photos.length > 0) {
-              file = this.form.photos[0].raw;
-            }
-
-            const response = await createTicket(submitData, file);
-            if (response.data.code === 0) {
-              this.$message.success('工单创建成功');
-              this.dialogVisible = false;
-              this.fetchTableData();
-            } else {
-              throw new Error(response.data.msg || '创建失败');
-            }
-          } catch (error) {
-            console.error('提交失败:', error);
-            this.$message.error(error.message || '工单创建失败,请稍后重试');
-          }
+      try {
+        // 提交时需要完整验证
+        await this.$refs.form.validate();
+        
+        // 验证位置信息
+        if (!this.form.location || this.form.location.length < 2) {
+          this.$message.warning('请在地图上选择位置');
+          return;
         }
-      });
+
+        // 验证图片上传
+        if (!this.form.photos || this.form.photos.length === 0) {
+          this.$message.warning('请上传工单图片');
+          return;
+        }
+
+        const submitData = {
+          eventName: this.form.name,
+          content: this.form.content,
+          workType: "1",
+          longitude: String(this.form.location[0]),
+          latitude: String(this.form.location[1]),
+          address: this.form.address,
+          eventDictKey: this.form.type,
+          aiType: this.form.algorithm,
+          updateUser: this.form.handler,
+          createDept: this.form.department,
+          isDraft: 0
+        };
+
+        if (this.form.id) {
+          submitData.id = this.form.id;
+        }
+
+        // 获取文件对象
+        const file = this.form.photos[0].raw;
+        if (!file) {
+          this.$message.warning('图片文件无效,请重新上传');
+          return;
+        }
+
+        const response = await createTicket(submitData, file);
+        if (response.data.code === 0) {
+          this.$message.success('工单创建成功');
+          this.dialogVisible = false;
+          this.fetchTableData();
+        } else {
+          throw new Error(response.data.msg || '创建失败');
+        }
+      } catch (error) {
+        console.error('提交失败:', error);
+        if (error.message.includes('验证未通过')) {
+          this.$message.warning('请填写完整的工单信息');
+        } else {
+          this.$message.error(error.message || '工单创建失败,请稍后重试');
+        }
+      }
     },
 
     async saveDraft() {
@@ -850,7 +888,7 @@
         const submitData = {
           id: this.form.id,
           eventName: this.form.name || undefined,
-          content: this.form.content || undefined,  // 传递工单内容
+          content: this.form.content || undefined,
           workType: "1",
           longitude: this.form.location?.[0] ? String(this.form.location[0]) : undefined,
           latitude: this.form.location?.[1] ? String(this.form.location[1]) : undefined,
@@ -862,14 +900,10 @@
           isDraft: 1
         };
 
-        // 确保即使为空字符串也会传入 content
-        if (this.form.content !== undefined) {
-          submitData.content = this.form.content;
-        }
-
-        // 如果是编辑状态,添加 id
-        if (this.form.id) {
-          submitData.id = this.form.id;
+        // 草稿时也至少需要工单名称
+        if (!submitData.eventName) {
+          this.$message.warning('请至少输入工单名称');
+          return;
         }
 
         // 过滤掉所有 undefined 的字段
@@ -877,13 +911,12 @@
           submitData[key] === undefined && delete submitData[key]
         );
 
-        // 获取文件对象
         let file = null;
         if (this.form.photos && this.form.photos.length > 0) {
           file = this.form.photos[0].raw;
         }
 
-        const response = await createTicket(submitData, file); // 使用 createTicket 而不是 flowEvent
+        const response = await createTicket(submitData, file);
         if (response.data.code === 0) {
           this.$message.success('草稿保存成功');
           this.dialogVisible = false;
@@ -1322,6 +1355,7 @@
       if (this.currentDetail.status !== 3) {
         this.$message.warning('只有处理中状态的工单可以提交处理详情');
         return;
+
       }
 
       try {
@@ -1451,22 +1485,51 @@
 
     // 添加编辑方法
     handleEdit(row) {
-      // 从原始数据中获取 id 和 dept_id
-      const originalDeptId = row.department?.value || row.dept_id;
+      console.log('编辑原始数据:', row);
+      
+      // 尝试从row.dept_id或通过部门名称查找对应的部门ID
+      let deptId = row.dept_id;  // 优先使用原始数据中的dept_id
+      
+      // 如果没有dept_id,则通过部门名称查找
+      if (!deptId) {
+        // 输出所有可用的部门数据用于调试
+        console.log('可用部门列表:', this.departments);
+        console.log('当前部门名称:', row.department);
+        
+        const deptInfo = this.departments.find(dept => 
+          dept.label && dept.label.trim() === row.department.trim()
+        );
+        deptId = deptInfo?.value;
+      }
+
+      // 获取工单类型值 - 从types中找到匹配的值
+      const typeValue = this.types.find(t => t.label === row.type)?.value || row.event_dict_key;
+      
+      // 获取处理人ID - 使用userNameToIdMap映射
+      const handlerId = this.userNameToIdMap[row.handler] || row.handler;
+      
+      console.log('数据映射:', {
+        部门名称: row.department,
+        找到的部门ID: deptId,
+        原始处理人: row.handler,
+        处理人ID: handlerId,
+        原始工单类型: row.type,
+        映射后类型值: typeValue
+      });
 
       this.form = {
-        id: row.id, // 保存原始 id
+        id: row.id,
         name: row.orderName,
-        type: row.event_dict_key, // 使用原始 key 值
-        department: originalDeptId,
-        handler: row.handler,
-        algorithm: row.content,
+        type: typeValue,
+        department: deptId,
+        handler: handlerId, // 使用映射后的处理人ID
+        algorithm: row.aiType,
         location: row.location,
         address: row.address,
         content: row.content,
         photos: [],
-        content: row.content,
       };
+
       // 如果有图片,添加到表单中
       if (row.photo_url) {
         this.form.photos = [{
@@ -1474,9 +1537,9 @@
           url: row.photo_url
         }];
       }
+
       this.dialogVisible = true;
     },
-
     // 添加删除方法
     handleDelete(row) {
       this.$confirm('确认删除该工单?', '提示', {
@@ -1588,69 +1651,105 @@
 }
 
 .create-ticket-form {
-  padding: 10px;
+  padding: 20px 10px;
 
   .form-section {
-    margin-bottom: 15px;
-    background: #f8f9fa;
+    background-color: #fff;
     border-radius: 4px;
-    padding: 12px;
 
-    .section-title {
-      font-size: 14px;
-      font-weight: 500;
-      color: #303133;
-      margin-bottom: 12px;
-      padding-left: 8px;
-      border-left: 3px solid #409EFF;
-    }
+    .el-row {
+      margin-bottom: 16px;
 
-    .el-form-item {
-      margin-bottom: 12px;
+      &:last-child {
+        margin-bottom: 0;
+      }
     }
   }
 
-  .map-select {
-    display: flex;
-    align-items: center;
-    gap: 10px;
+  .location-wrapper {
+    .map-button {
+      width: 100%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      
+      i {
+        margin-right: 4px;
+      }
+    }
 
     .location-text {
+      margin-top: 8px;
+      padding: 8px 12px;
+      background-color: #f5f7fa;
+      border-radius: 4px;
       color: #606266;
       font-size: 13px;
+      line-height: 1.4;
     }
   }
 
-  .upload-item {
-    margin-bottom: 0;
-  }
+  .upload-wrapper {
+    .uploader {
+      :deep(.el-upload--picture-card) {
+        width: 120px;
+        height: 120px;
+        line-height: 128px;
+      }
 
-  .ticket-upload {
-    :deep(.el-upload--picture-card) {
-      width: 100px;
-      height: 100px;
-      line-height: 100px;
-      margin: 0 8px 8px 0;
+      :deep(.el-upload-list__item) {
+        width: 120px;
+        height: 120px;
+      }
     }
 
-    :deep(.el-upload-list--picture-card .el-upload-list__item) {
-      width: 100px;
-      height: 100px;
-      margin: 0 8px 8px 0;
+    .upload-tip {
+      font-size: 12px;
+      color: #909399;
+      line-height: 1.4;
+      margin-top: 8px;
     }
   }
 
-  .el-upload__tip {
-    font-size: 12px;
-    color: #909399;
-    line-height: 1.2;
-    margin-top: 5px;
+  .el-form-item {
+    margin-bottom: 18px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+
+  :deep(.el-form-item__label) {
+    font-weight: 500;
+    color: #606266;
+  }
+
+  :deep(.el-input__inner) {
+    height: 36px;
+    line-height: 36px;
+  }
+
+  :deep(.el-textarea__inner) {
+    padding: 8px 12px;
   }
 }
 
 .dialog-footer {
   text-align: right;
-  padding-top: 10px;
+  padding-top: 16px;
+  border-top: 1px solid #ebeef5;
+
+  .el-button + .el-button {
+    margin-left: 12px;
+  }
+
+  .el-button {
+    padding: 9px 20px;
+    
+    &:last-child {
+      margin-left: 12px;
+    }
+  }
 }
 
 .map-container {

--
Gitblit v1.9.3