From 4a836815f12e8ba717702cc8ed431e1b4f96134c Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期五, 25 四月 2025 13:55:34 +0800
Subject: [PATCH] 新增内部线索相关管理逻辑

---
 src/views/overlay-clue/report/components/QuestionDetail.vue |  196 ++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 162 insertions(+), 34 deletions(-)

diff --git a/src/views/overlay-clue/report/components/QuestionDetail.vue b/src/views/overlay-clue/report/components/QuestionDetail.vue
index f0f6603..7352c04 100644
--- a/src/views/overlay-clue/report/components/QuestionDetail.vue
+++ b/src/views/overlay-clue/report/components/QuestionDetail.vue
@@ -7,7 +7,11 @@
     destroy-on-close
   >
     <template #header>
-      <span> 娣诲姞闂</span>
+      <span>
+        {{
+          uploaded ? '闂璇︽儏' : createMode ? '娣诲姞闂' : '淇敼闂'
+        }}</span
+      >
     </template>
     <el-form
       label-width="90px"
@@ -18,19 +22,25 @@
     >
       <el-form-item label="闂鍚嶇О" prop="cqName">
         <el-input
+          :disabled="uploaded"
           v-model="formObj.cqName"
           placeholder="璇疯緭鍏ラ棶棰樺悕绉�"
         ></el-input>
       </el-form-item>
       <el-form-item label="闂鎻忚堪" prop="cqDescription">
         <el-input
+          :disabled="uploaded"
           v-model="formObj.cqDescription"
           type="textarea"
           placeholder="璇疯緭鍏ラ棶棰樻弿杩�"
         ></el-input>
       </el-form-item>
       <el-form-item label="鎵�鍦ㄨ闀�" prop="cqStreet">
-        <el-select v-model="formObj.cqStreet" placeholder="鎵�鍦ㄨ闀�">
+        <el-select
+          v-model="formObj.cqStreet"
+          placeholder="鎵�鍦ㄨ闀�"
+          :disabled="uploaded"
+        >
           <el-option
             v-for="s in streets"
             :key="s.value"
@@ -41,22 +51,29 @@
       </el-form-item>
       <el-form-item label="璇︾粏鍦板潃" prop="cqAddress">
         <el-input
+          :disabled="uploaded"
           v-model="formObj.cqAddress"
           placeholder="璇疯緭鍏ュ湴鍧�鎴栬�呴�氳繃鈥滃潗鏍囨嬀鍙栤�濊嚜鍔ㄨ幏寰�"
         ></el-input>
       </el-form-item>
       <el-form-item label="鍧愭爣" prop="coordinate">
         <el-input
+          :disabled="uploaded"
           style="width: 300px; margin-right: 8px"
           v-model="formObj.coordinate"
           placeholder="缁忕含搴﹀潗鏍囷紝鏍煎紡涓�121.123452,31.231235"
         ></el-input>
-        <el-button plain type="primary" @click="openMapDialog"
+        <el-button
+          :disabled="uploaded"
+          plain
+          type="primary"
+          @click="openMapDialog"
           >鍧愭爣鎷惧彇</el-button
         >
       </el-form-item>
       <el-form-item label="闂鍥剧墖" prop="files">
         <el-upload
+          :class="uploadableClz"
           ref="uploadRef"
           :file-list="fileList"
           action=""
@@ -64,16 +81,49 @@
           list-type="picture-card"
           name="images"
           accept="image/png, image/jpeg"
-          :limit="3"
+          :limit="maxImageCount"
           multiple
           :on-preview="handleFilePreview"
           :on-remove="handleFileRemove"
           :on-change="handleFileChange"
         >
           <el-icon><Plus /></el-icon>
+          <template #file="{ file }">
+            <div>
+              <img
+                class="el-upload-list__item-thumbnail"
+                :src="file.url"
+                alt=""
+              />
+              <span class="el-upload-list__item-actions">
+                <span
+                  class="el-upload-list__item-preview"
+                  @click="handleFilePreview(file)"
+                >
+                  <el-icon><zoom-in /></el-icon>
+                </span>
+                <!-- <span
+                  v-if="!disabled"
+                  class="el-upload-list__item-delete"
+                  @click="handleDownload(file)"
+                >
+                  <el-icon><Download /></el-icon>
+                </span> -->
+                <span
+                  v-if="!uploaded"
+                  class="el-upload-list__item-delete"
+                  @click="handleFileRemove(file)"
+                >
+                  <el-icon><Delete /></el-icon>
+                </span>
+              </span>
+            </div>
+          </template>
           <template #tip>
             <div class="el-upload__tip">
-              璇烽�夋嫨灏忎簬500kb鐨刯pg/png鍥剧墖锛屾渶澶�3寮�
+              {{
+                `璇烽�夋嫨灏忎簬500kb鐨刯pg/png鍥剧墖锛屾渶澶�${maxImageCount}寮燻
+              }}
             </div>
           </template>
         </el-upload>
@@ -99,47 +149,78 @@
   ></el-image-viewer>
   <MapSearch
     v-model:show="mapDialogShow"
+    :defaultCoor="
+      formObj.coordinate
+        ? formObj.coordinate.split(',')
+        : undefined
+    "
     @on-submit="selectAddress"
   ></MapSearch>
 </template>
 
 <script setup>
-import { reactive, ref, watch, computed } from 'vue';
+import { reactive, ref, watch, computed, inject } from 'vue';
+import { ElMessage } from 'element-plus';
 import { useFormConfirm } from '@/composables/formConfirm';
 import { streets } from '@/constant/street';
 import clueQuestionApi from '@/api/clue/clueQuestionApi';
+import { $clue } from '@/api/index';
 import MapSearch from '@/components/map/MapSearch.vue';
 
+// 鍐冲畾褰撳墠鏄惁鏄唴閮ㄧ嚎绱㈢浉鍏虫搷浣�
+const isInternal = inject('isInternal', false);
+
 const props = defineProps({
-  clueId: Number,
+  // 搴旀�ョ嚎绱㈠璞�
   clueData: {
     type: Object,
     default: () => {
       return {};
     }
   },
+  // 瀵硅瘽妗嗘樉绀烘帶鍒�
   show: Boolean,
+  // 绾跨储闂瀵硅薄
   question: Object,
-  create: {
+  // 闂鏄惁宸蹭笂浼�
+  uploaded: {
     type: Boolean,
-    default: true
+    default: false
+  },
+  maxImageCount: {
+    type: Number,
+    default: 3
   }
 });
 
 const emit = defineEmits(['update:show', 'onSubmit', 'onClose']);
+
+// 鍒涘缓鎴栨槸淇敼妯″紡
+const createMode = ref(true);
 
 // 涓婃姤寮瑰嚭妗�
 const dialogShow = ref(false);
 const mapDialogShow = ref(false);
 const uploadRef = ref();
 const fileList = ref([]);
+// 鏇存柊妯″紡涓嬶紝璁板綍琚垹闄ょ殑鍘熸湁鍥剧墖
+let deletedFileList = [];
+// 鍐冲畾鏄惁鑳戒笂浼犲浘鐗�
+const uploadableClz = computed(() => {
+  return props.uploaded ||
+    (fileList.value && fileList.value.length >= props.maxImageCount)
+    ? 'question-not-upload'
+    : '';
+});
 
 const previewShow = ref(false);
 const initialIndex = ref(0);
 const urlList = computed(() =>
-  fileList.value.map((value) => {
-    return value.url;
-  })
+  fileList.value
+    ? fileList.value.map((value) => {
+        return value.url;
+      })
+    : []
 );
 
 function handleFilePreview(file) {
@@ -151,12 +232,22 @@
   previewShow.value = false;
 }
 
-function handleFileRemove(file, fileList) {
-  formObj.value.files = fileList;
+function handleFileRemove(file, files) {
+  if (!createMode.value) {
+    if (file.url.indexOf($clue.imgUrl) != -1) {
+      const originUrl = file.url.replace($clue.imgUrl, '');
+      deletedFileList.push(originUrl);
+    }
+  }
+  const index = fileList.value.indexOf(file);
+  fileList.value.splice(index, 1);
+  // fileList.value = fileList;
+  edit.value = true;
 }
 
-function handleFileChange(file, fileList) {
-  formObj.value.files = fileList;
+function handleFileChange(file, files) {
+  fileList.value = files;
+  edit.value = true;
 }
 
 const { formObj, formRef, edit, onSubmit, onCancel, clear } =
@@ -230,23 +321,38 @@
 });
 
 function submit() {
+  if (!fileList.value || fileList.value.length == 0) {
+    ElMessage({
+      message: '鑷冲皯涓婁紶涓�寮犲浘鐗�',
+      type: 'error'
+    });
+    return;
+  }
   const coor = formObj.value.coordinate.split(',');
   const q = {
-    cid: parseInt(props.clueData.cid),
-    cqName: formObj.value.cqName,
-    cqDescription: formObj.value.cqDescription,
-    cqStreet: formObj.value.cqStreet,
-    cqAddress: formObj.value.cqAddress,
+    ...formObj.value,
+    // cqId: formObj.value.cqId,
+    cId: parseInt(props.clueData.cid),
+    // cqName: formObj.value.cqName,
+    // cqDescription: formObj.value.cqDescription,
+    // cqStreet: formObj.value.cqStreet,
+    // cqAddress: formObj.value.cqAddress,
     cqLongitude: parseFloat(coor[0]),
-    cqLatitude: parseFloat(coor[1])
+    cqLatitude: parseFloat(coor[1]),
+    cqInternal: isInternal
+    // cqFilePath: formObj.value.cqFilePath
   };
   const files = [];
-  if (formObj.value.files) {
-    formObj.value.files.forEach((f) => {
-      files.push(f.raw);
+  if (fileList.value) {
+    fileList.value.forEach((f) => {
+      if (f.url.indexOf($clue.imgUrl) == -1) {
+        files.push(f.raw);
+      }
     });
   }
-  return props.create ? uploadQuestion(q, files) : updateQuestion(q, );
+  return createMode.value
+    ? uploadQuestion(q, files)
+    : updateQuestion(q, files);
 }
 
 function cancel() {
@@ -268,12 +374,11 @@
  */
 function uploadQuestion(question, files) {
   loading.value = true;
-
   return clueQuestionApi
     .uploadQuestion(question, files)
     .then(() => {
       dialogShow.value = false;
-      clear();
+      // clear();
       uploadRef.value.clearFiles();
       emit('onSubmit');
     })
@@ -282,19 +387,30 @@
     });
 }
 
-function updateQuestion(question, newFiles, deleteFiles) {
-  
+function updateQuestion(question, newFiles) {
+  loading.value = true;
+  const deleteImgUrl = deletedFileList.join(';');
+  return clueQuestionApi
+    .updateQuestion(question, newFiles, deleteImgUrl)
+    .then(() => {
+      dialogShow.value = false;
+      // clear();
+      uploadRef.value.clearFiles();
+      emit('onSubmit');
+    })
+    .finally(() => {
+      loading.value = false;
+    });
 }
 
 function parseFormObj(question) {
   question.coordinate =
     question.cqLongitude + ',' + question.cqLatitude;
-  fileList.value = [];
-  question.cqFilePath.forEach((f, index) => {
-    fileList.value.push({
+  fileList.value = question.files.map((f, index) => {
+    return {
       name: `${index}`,
       url: f
-    });
+    };
   });
   return { ...question };
 }
@@ -305,16 +421,28 @@
     dialogShow.value = val[0];
     if (val[0]) {
       fileList.value = [];
+      deletedFileList = [];
       if (val[1]) {
+        createMode.value = false;
         formObj.value = parseFormObj(val[1]);
       } else {
+        createMode.value = true;
         formObj.value = {};
       }
+      // edit.value = false
     }
   }
 );
 
 watch(dialogShow, (val) => {
+  if (!val) {
+    clear();
+  }
   emit('update:show', val);
 });
 </script>
+<style scoped>
+:deep(.question-not-upload .el-upload-list > .el-upload) {
+  display: none;
+}
+</style>

--
Gitblit v1.9.3