Prechádzať zdrojové kódy

fix(hiddenDanger): 状态精简 2 个 + 处理弹窗独立化

- 状态筛选项去掉'处理中',仅保留'待处理'/'已处理'
- 卡片统计同步:未处理仅算'待处理'
- 状态标签颜色:待处理=danger,已处理=success
- 新增独立'安全隐患处理'弹窗(handleDialog):
  * 只读展示:隐患编号/隐患名称
  * 处理结果下拉(5 项,可扩展)
  * 处理描述(多行,必填)
  * 照片上传(走 /risk/file/upload)
  * 提交按钮:'提交处理结果',强制状态=已处理
- 原 dialog 仅走新增(提交按钮统一 v-hasPermi='risk:hiddenDanger:add')
- 移除 getStatusTag 中'处理中'配色
klxj001 3 dní pred
rodič
commit
d0acd5a5a7
1 zmenil súbory, kde vykonal 174 pridanie a 13 odobranie
  1. 174 13
      src/views/risk/hiddenDanger/index.vue

+ 174 - 13
src/views/risk/hiddenDanger/index.vue

@@ -51,7 +51,6 @@
           >
             <el-option label="全部状态" value="" />
             <el-option label="待处理" value="待处理" />
-            <el-option label="处理中" value="处理中" />
             <el-option label="已处理" value="已处理" />
           </el-select>
         </el-form-item>
@@ -242,19 +241,87 @@
       <template #footer>
         <div class="dialog-footer">
           <el-button @click="cancel">取消</el-button>
-          <!-- 新增走 risk:hiddenDanger:add,处理走 risk:hiddenDanger:handle -->
+          <!-- 新增走 risk:hiddenDanger:add(处理走独立 handleDialog) -->
           <el-button
-            v-if="!form.id"
             v-hasPermi="['risk:hiddenDanger:add']"
             type="primary"
             @click="submitForm"
           >提交保存</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 安全隐患处理弹窗(独立,字段精简:处理结果/描述/照片) -->
+    <el-dialog
+      v-model="handleDialog.visible"
+      :title="handleDialog.title"
+      width="640px"
+      append-to-body
+      :close-on-click-modal="false"
+      @close="cancelHandle"
+    >
+      <el-form ref="handleFormRef" :model="handleForm" :rules="handleRules" label-width="100px">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="隐患编号">
+              <span class="readonly-text">{{ handleForm.dangerCode }}</span>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="隐患名称">
+              <span class="readonly-text">{{ handleForm.dangerTitle }}</span>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="处理结果" prop="handleResult">
+          <el-select v-model="handleForm.handleResult" placeholder="请选择处理结果" style="width: 100%">
+            <el-option
+              v-for="opt in handleResultOptions"
+              :key="opt.value"
+              :label="opt.label"
+              :value="opt.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="处理描述" prop="handleMeasures">
+          <el-input
+            v-model="handleForm.handleMeasures"
+            type="textarea"
+            :rows="5"
+            placeholder="请详细描述处理过程和采取的措施..."
+            maxlength="500"
+            show-word-limit
+          />
+        </el-form-item>
+        <el-form-item label="照片上传">
+          <div class="upload-row">
+            <el-button type="primary" plain @click="triggerHandlePhotoUpload">选择文件</el-button>
+            <span class="upload-tip">{{ handlePhotoFileList.length > 0 ? `已选择 ${handlePhotoFileList.length} 个文件` : '未选择任何文件' }}</span>
+          </div>
+          <input
+            ref="handlePhotoInputRef"
+            type="file"
+            multiple
+            accept=".jpg,.jpeg,.png"
+            style="display: none"
+            @change="onHandlePhotoInputChange"
+          />
+          <div v-if="handlePreviewPhotos.length > 0" class="photo-preview-list">
+            <div v-for="(url, idx) in handlePreviewPhotos" :key="idx" class="photo-thumb">
+              <el-image :src="url" :preview-src-list="handlePreviewPhotos" :initial-index="idx" fit="cover" />
+              <el-icon class="photo-remove" @click="removeHandlePhoto(idx)"><CircleCloseFilled /></el-icon>
+            </div>
+          </div>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="cancelHandle">取消</el-button>
           <el-button
-            v-else
             v-hasPermi="['risk:hiddenDanger:handle']"
             type="primary"
-            @click="submitForm"
-          >提交保存</el-button>
+            @click="submitHandle"
+          >提交处理结果</el-button>
         </div>
       </template>
     </el-dialog>
@@ -402,12 +469,37 @@ const dialog = reactive({
   title: '新增安全隐患'
 });
 
+// 处理弹窗(独立,字段精简:处理结果/描述/照片)
+const handleDialog = reactive({
+  visible: false,
+  title: '安全隐患处理'
+});
+
 const viewDialog = reactive({
   visible: false
 });
 
 const viewForm = ref<any>({});
 
+// 处理表单(独立,不与新增表单混用)
+const handleForm = ref<any>({
+  id: undefined,
+  dangerCode: '',
+  dangerTitle: '',
+  handleResult: '',
+  handleMeasures: '',
+  photoList: '[]'
+});
+const handleFormRef = ref<FormInstance>();
+const handleRules = {
+  handleResult: [{ required: true, message: '请选择处理结果', trigger: 'change' }],
+  handleMeasures: [{ required: true, message: '请输入处理描述文案', trigger: 'blur' }]
+};
+// 处理照片(预览)
+const handlePreviewPhotos = ref<string[]>([]);
+const handlePhotoFileList = ref<any[]>([]);
+const handlePhotoInputRef = ref<HTMLInputElement>();
+
 // 客户端按筛选条件过滤(用于顶部统计的同步展示)
 const filteredList = computed(() => {
   return hiddenDangerList.value;
@@ -436,8 +528,9 @@ const loadStats = async () => {
   } catch (e) {
     const list = hiddenDangerList.value || [];
     statsCards.value[0].value = list.length;
+    // 未处理隐患统计(只统计"待处理")
     statsCards.value[1].value = list.filter(
-      (it) => it.handleStatus === '待处理' || it.handleStatus === '处理中'
+      (it) => it.handleStatus === '待处理'
     ).length;
     statsCards.value[2].value = list.filter((it) => it.handleStatus === '已处理').length;
   }
@@ -465,12 +558,15 @@ const handleAdd = () => {
 };
 
 const handleUpdate = async (row: RiskHiddenDangerVo) => {
-  reset();
+  // 重置处理表单 + 加载隐患信息(只读字段)
+  resetHandleForm();
   const res = await getHiddenDanger(row.id);
-  Object.assign(form.value, res.data);
-  loadPhotosToPreview(parsePhotoList(res.data.photoList));
-  dialog.visible = true;
-  dialog.title = '处理安全隐患';
+  handleForm.value.id = res.data.id;
+  handleForm.value.dangerCode = res.data.dangerCode || '';
+  handleForm.value.dangerTitle = res.data.dangerTitle || '';
+  // 处理后照片作为历史保留(如有)
+  handlePreviewPhotos.value = parsePhotoList(res.data.photoList);
+  handleDialog.visible = true;
 };
 
 const handleView = async (row: RiskHiddenDangerVo) => {
@@ -536,6 +632,63 @@ const closeDialog = () => {
   reset();
 };
 
+// 处理弹窗 - 提交(状态强制变"已处理")
+const submitHandle = () => {
+  handleFormRef.value?.validate(async (valid: boolean) => {
+    if (!valid) return;
+    handleForm.value.photoList = JSON.stringify(handlePreviewPhotos.value);
+    await handleHiddenDanger(handleForm.value.id, handleForm.value as RiskHiddenDangerBo);
+    proxy?.$modal.msgSuccess('处理成功');
+    handleDialog.visible = false;
+    await getList();
+  });
+};
+
+const cancelHandle = () => {
+  handleDialog.visible = false;
+  resetHandleForm();
+};
+
+const resetHandleForm = () => {
+  handleForm.value = {
+    id: undefined,
+    dangerCode: '',
+    dangerTitle: '',
+    handleResult: '',
+    handleMeasures: '',
+    photoList: '[]'
+  };
+  handlePreviewPhotos.value = [];
+  handlePhotoFileList.value = [];
+  handleFormRef.value?.resetFields();
+};
+
+// ============ 处理照片上传(独立预览队列) ============
+const triggerHandlePhotoUpload = () => handlePhotoInputRef.value?.click();
+const onHandlePhotoInputChange = async (e: Event) => {
+  const files = (e.target as HTMLInputElement).files;
+  if (!files || files.length === 0) return;
+  const list = Array.from(files);
+  handlePhotoFileList.value = list;
+  for (const f of list) {
+    try {
+      const upRes: any = await uploadFile(f as any);
+      if (upRes?.data?.url) {
+        handlePreviewPhotos.value.push(upRes.data.url);
+      }
+    } catch (err) {
+      proxy?.$modal.msgError(`照片 ${f.name} 上传失败`);
+    }
+  }
+  if (handlePhotoInputRef.value) handlePhotoInputRef.value.value = '';
+};
+const removeHandlePhoto = (idx: number) => {
+  handlePreviewPhotos.value.splice(idx, 1);
+  if (handlePreviewPhotos.value.length === 0) {
+    handlePhotoFileList.value = [];
+  }
+};
+
 const disabledFutureDate = (time: Date) => {
   return time.getTime() > Date.now();
 };
@@ -560,12 +713,20 @@ const getRiskLevelTag = (level: string): any => {
 const getStatusTag = (status: string): any => {
   const map: Record<string, string> = {
     待处理: 'danger',
-    处理中: 'warning',
     已处理: 'success'
   };
   return map[status] || 'info';
 };
 
+// 安全隐患处理结果字典(可扩展)
+const handleResultOptions = ref<Array<{ label: string; value: string }>>([
+  { label: '隐患已消除', value: '隐患已消除' },
+  { label: '已设置警戒', value: '已设置警戒' },
+  { label: '已上报整改', value: '已上报整改' },
+  { label: '临时管控', value: '临时管控' },
+  { label: '其他', value: '其他' }
+]);
+
 // ============ 照片上传(自管理文件 + 预览) ============
 const parsePhotoList = (val: any): string[] => {
   if (!val) return [];