From e6d08ae91981aabc6f4ea4091ff6165a3719ea70 Mon Sep 17 00:00:00 2001
From: 张诺 <zhang_12370@163.com>
Date: 星期四, 09 四月 2026 13:41:08 +0800
Subject: [PATCH] 阳光彩印-“销售台账”新增台账时选择客户名称要求不带出纳税识别号,直接出客户名称

---
 src/views/collaborativeApproval/knowledgeBase/index.vue |  316 +++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 275 insertions(+), 41 deletions(-)

diff --git a/src/views/collaborativeApproval/knowledgeBase/index.vue b/src/views/collaborativeApproval/knowledgeBase/index.vue
index aeb1ba4..ff8da1b 100644
--- a/src/views/collaborativeApproval/knowledgeBase/index.vue
+++ b/src/views/collaborativeApproval/knowledgeBase/index.vue
@@ -46,11 +46,13 @@
     </div>
 
     <!-- 鏂板/缂栬緫鐭ヨ瘑寮圭獥 -->
-    <el-dialog
+    <FormDialog
       v-model="dialogVisible"
       :title="dialogTitle"
-      width="800px"
-      :close-on-click-modal="false"
+      :width="'800px'"
+      @close="closeKnowledgeDialog"
+      @confirm="submitForm"
+      @cancel="closeKnowledgeDialog"
     >
       <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
         <el-row :gutter="20">
@@ -115,7 +117,14 @@
         <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="鍒涘缓浜�" prop="creator">
-              <el-input v-model="form.creator" placeholder="璇疯緭鍏ュ垱寤轰汉" />
+              <el-select v-model="form.creator" placeholder="璇烽�夋嫨鍒涘缓浜�" style="width: 100%" filterable>
+                <el-option
+                  v-for="user in userList"
+                  :key="user.userId"
+                  :label="user.nickName"
+                  :value="user.nickName"
+                />
+              </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -124,21 +133,52 @@
             </el-form-item>
           </el-col>
         </el-row>
+        <el-form-item label="闄勪欢鏉愭枡" prop="files">
+          <el-upload
+            v-model:file-list="fileList"
+            :action="upload.url"
+            multiple
+            ref="fileUpload"
+            auto-upload
+            :headers="upload.headers"
+            :before-upload="handleBeforeUpload"
+            :on-error="handleUploadError"
+            :on-success="handleUploadSuccess"
+            :on-remove="handleRemove"
+            :on-preview="handlePreview"
+            :show-file-list="true"
+          >
+            <el-button type="primary">涓婁紶</el-button>
+            <template #file="{ file }">
+              <div style="display:flex; align-items:center; gap: 10px; width: 100%;">
+                <span style="flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
+                  {{ file.name }}
+                </span>
+                <div style="display:flex; align-items:center; gap: 6px;">
+                  <el-button link type="success" :icon="Download" @click="handleDownload(file)" />
+                  <el-button link type="primary" :icon="View" @click="handlePreview(file)" />
+                  <el-button link type="danger" :icon="Delete" @click="triggerRemoveFile(file)" />
+                </div>
+              </div>
+            </template>
+            <template #tip>
+              <div class="el-upload__tip">
+                鏀寔鏂囨。锛坉oc, docx, xls, xlsx, pdf, txt锛夊拰鍥剧墖锛坖pg, jpeg, png, gif锛夋牸寮�
+              </div>
+            </template>
+          </el-upload>
+        </el-form-item>
       </el-form>
-      <template #footer>
-        <span class="dialog-footer">
-          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
-          <el-button type="primary" @click="submitForm">纭畾</el-button>
-        </span>
-      </template>
-    </el-dialog>
+    </FormDialog>
 
     <!-- 鏌ョ湅鐭ヨ瘑璇︽儏寮圭獥 -->
-    <el-dialog
+    <FormDialog
       v-model="viewDialogVisible"
       title="鐭ヨ瘑璇︽儏"
-      width="900px"
-      :close-on-click-modal="false"
+      :width="'900px'"
+      @close="closeViewDialog"
+      @confirm="handleViewDialogConfirm"
+      @cancel="closeViewDialog"
     >
       <div class="knowledge-detail">
         <el-descriptions :column="2" border>
@@ -183,13 +223,24 @@
           <h4>鍏抽敭瑕佺偣</h4>
           <div class="key-points">
             <el-tag
-              v-for="(point, index) in currentKnowledge.keyPoints.split(',')"
+              v-for="(point, index) in currentKnowledge.keyPoints?.split(',') || []"
               :key="index"
               type="success"
               style="margin-right: 8px; margin-bottom: 8px;"
             >
               {{ point.trim() }}
             </el-tag>
+          </div>
+        </div>
+
+        <div class="detail-section" v-if="currentKnowledge.commonFileList && currentKnowledge.commonFileList.length > 0">
+          <h4>闄勪欢鏉愭枡</h4>
+          <div class="file-list">
+            <div v-for="file in currentKnowledge.commonFileList" :key="file.id" class="file-item">
+              <div class="file-info">
+                <el-link :href="file.url" target="_blank" :download="file.name">{{ file.name }}</el-link>
+              </div>
+            </div>
           </div>
         </div>
 
@@ -219,24 +270,22 @@
           </div>
         </div>
       </div>
-
-      <template #footer>
-        <span class="dialog-footer">
-          <el-button @click="viewDialogVisible = false">鍏抽棴</el-button>
-          <el-button type="primary" @click="copyKnowledge">澶嶅埗鐭ヨ瘑</el-button>
-          <!-- <el-button type="success" @click="markAsFavorite">鏀惰棌@</el-button> -->
-        </span>
-      </template>
-    </el-dialog>
+    </FormDialog>
+    <filePreview ref="filePreviewRef" />
   </div>
 </template>
 
 <script setup>
-import { Search } from "@element-plus/icons-vue";
-import { onMounted, ref, reactive, toRefs, getCurrentInstance, computed } from "vue";
+import { Search, Download, View, Delete } from "@element-plus/icons-vue";
+import { onMounted, ref, reactive, toRefs, getCurrentInstance, computed, watch } from "vue";
 import { ElMessage, ElMessageBox } from "element-plus";
 import PIMTable from "@/components/PIMTable/PIMTable.vue";
-import { listKnowledgeBase, delKnowledgeBase,addKnowledgeBase,updateKnowledgeBase } from "@/api/collaborativeApproval/knowledgeBase.js";
+import FormDialog from '@/components/Dialog/FormDialog.vue';
+import filePreview from '@/components/filePreview/index.vue'
+import { listKnowledgeBase, delKnowledgeBase,addKnowledgeBase,updateKnowledgeBase, delKnowledgeBaseFile } from "@/api/collaborativeApproval/knowledgeBase.js";
+import useUserStore from '@/store/modules/user';
+import { userListNoPageByTenantId } from '@/api/system/user.js';
+import { getToken } from "@/utils/auth";
 
 // 琛ㄥ崟楠岃瘉瑙勫垯
 const rules = {
@@ -268,6 +317,13 @@
   },
   tableData: [],
   selectedIds: [],
+  fileList: [],
+  upload: {
+    // 涓婁紶鐨勫湴鍧�
+    url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+    // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+    headers: { Authorization: "Bearer " + getToken() },
+  },
   form: {
     title: "",
     type: "",
@@ -277,7 +333,8 @@
     solution: "",
     keyPoints: "",
     creator: "",
-    usageCount: 0
+    usageCount: 0,
+    files: []
   },
   dialogVisible: false,
   dialogTitle: "",
@@ -292,6 +349,8 @@
   page,
   tableData,
   selectedIds,
+  fileList,
+  upload,
   form,
   dialogVisible,
   dialogTitle,
@@ -302,6 +361,30 @@
 
 // 琛ㄥ崟寮曠敤
 const formRef = ref();
+const fileUpload = ref()
+const filePreviewRef = ref()
+// 鐢ㄦ埛鐩稿叧
+const userStore = useUserStore();
+const userList = ref([]);
+
+const normalizeKnowledgeFiles = (files = []) => {
+  const list = Array.isArray(files) ? files : []
+  return list.map((f, index) => {
+    const name = f?.name || f?.originalName || f?.fileName || ''
+    const url = f?.url || f?.path || ''
+    return {
+      ...f,
+      name,
+      url,
+      uid: f?.uid || f?.id || `${Date.now()}_${index}`,
+      status: f?.status || 'success',
+    }
+  })
+}
+
+const getUploadFileUrl = (file) => {
+  return file?.url || file?.response?.data?.tempPath || file?.response?.data?.url
+}
 
 // 琛ㄦ牸鍒楅厤缃�
 const tableColumn = ref([
@@ -389,6 +472,15 @@
   }
 ]);
 
+// 鐩戝惉瀵硅瘽妗嗘墦寮�锛岃幏鍙栫敤鎴峰垪琛�
+watch(dialogVisible, (newVal) => {
+  if (newVal) {
+    userListNoPageByTenantId().then((res) => {
+      userList.value = res.data || [];
+    });
+  }
+});
+
 // 鐢熷懡鍛ㄦ湡
 onMounted(() => {
   getList();
@@ -413,8 +505,15 @@
   listKnowledgeBase({...page.value, ...searchForm.value})
   .then(res => {
     tableLoading.value = false;
-    tableData.value = res.data.records
-    page.total = res.data.total;
+    page.value.total = res.data.total;
+    // 濡傛灉褰撳墠椤垫暟瓒呰繃鎬婚〉鏁帮紝閲嶇疆鍒扮1椤靛苟閲嶆柊鏌ヨ
+    const maxPage = Math.ceil(res.data.total / page.value.size) || 1;
+    if (page.value.current > maxPage && maxPage > 0) {
+      page.value.current = 1;
+      // 閲嶆柊鏌ヨ绗�1椤垫暟鎹�
+      return getList();
+    }
+    tableData.value = res.data.records;
   }).catch(err => {
     tableLoading.value = false;
   })
@@ -422,9 +521,14 @@
 
 // 鍒嗛〉澶勭悊
 const pagination = (obj) => {
+  const oldSize = page.value.size;
   page.value.current = obj.page;
   page.value.size = obj.limit;
-  handleQuery();
+  // 濡傛灉 size 鏀瑰彉浜嗭紝閲嶇疆鍒扮1椤碉紝閬垮厤褰撳墠椤佃秴鍑鸿寖鍥�
+  if (oldSize !== obj.limit) {
+    page.value.current = 1;
+  }
+  getList();
 };
 
 // 閫夋嫨鍙樺寲澶勭悊
@@ -437,7 +541,8 @@
   dialogType.value = type;
   if (type === "add") {
     dialogTitle.value = "鏂板鐭ヨ瘑";
-    // 閲嶇疆琛ㄥ崟
+    // 閲嶇疆琛ㄥ崟锛岄粯璁ゅ垱寤轰汉涓哄綋鍓嶇敤鎴�
+    fileList.value = [];
     Object.assign(form.value, {
       title: "",
       type: "",
@@ -446,11 +551,15 @@
       problem: "",
       solution: "",
       keyPoints: "",
-      creator: "",
-      usageCount: 0
+      creator: userStore.nickName || "",
+      usageCount: 0,
+      files: []
     });
   } else if (type === "edit" && row) {
     dialogTitle.value = "缂栬緫鐭ヨ瘑";
+    const existingFiles = row.files || row.commonFileList || [];
+    const normalizedFiles = normalizeKnowledgeFiles(existingFiles);
+    fileList.value = normalizedFiles;
     Object.assign(form.value, {
       id: row.id,
       title: row.title,
@@ -461,7 +570,15 @@
       solution: row.solution,
       keyPoints: row.keyPoints,
       creator: row.creator,
-      usageCount: row.usageCount
+      usageCount: row.usageCount,
+      files: normalizedFiles.map(f => ({
+        id: f.id,
+        tempId: f.tempId,
+        name: f.name,
+        url: f.url,
+        uid: f.uid
+      })),
+      
     });
   }
   dialogVisible.value = true;
@@ -550,6 +667,123 @@
   });
 };
 
+// 鍏抽棴鐭ヨ瘑琛ㄥ崟瀵硅瘽妗�
+const closeKnowledgeDialog = () => {
+  // 娓呯┖琛ㄥ崟鏁版嵁锛岄粯璁ゅ垱寤轰汉涓哄綋鍓嶇敤鎴�
+  fileList.value = [];
+  Object.assign(form.value, {
+    id: undefined,
+    title: "",
+    type: "",
+    scenario: "",
+    efficiency: "",
+    problem: "",
+    solution: "",
+    keyPoints: "",
+    creator: userStore.nickName || "",
+    usageCount: 0,
+    files: []
+  });
+  // 娓呴櫎琛ㄥ崟楠岃瘉鐘舵��
+  if (formRef.value) {
+    formRef.value.clearValidate();
+  }
+  dialogVisible.value = false;
+};
+
+// 鍏抽棴鏌ョ湅璇︽儏瀵硅瘽妗�
+const closeViewDialog = () => {
+  viewDialogVisible.value = false;
+};
+
+// 澶勭悊鏌ョ湅璇︽儏瀵硅瘽妗嗙‘璁わ紙鎵ц澶嶅埗鎿嶄綔锛�
+const handleViewDialogConfirm = () => {
+  copyKnowledge();
+  closeViewDialog();
+};
+
+// 涓婁紶鍓嶆牎妫�
+function handleBeforeUpload(file) {
+  proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
+  return true;
+}
+// 涓婁紶澶辫触
+function handleUploadError(err) {
+  proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
+  proxy.$modal.closeLoading();
+}
+// 涓婁紶鎴愬姛鍥炶皟
+function handleUploadSuccess(res, file, uploadFiles) {
+  proxy.$modal.closeLoading();
+  if (res.code === 200) {
+    if (!form.value.files) {
+      form.value.files = [];
+    }
+    file.tempId = res?.data?.tempId
+    file.url = res?.data?.tempPath || res?.data?.url
+    file.name = res?.data?.originalName || file?.name
+    form.value.files.push({
+      tempId: file.tempId,
+      url: file.url,
+      name: file.name,
+      uid: file.uid,
+    });
+    proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
+  } else {
+    proxy.$modal.msgError(res.msg);
+    fileUpload.value?.handleRemove?.(file) || proxy.$refs.fileUpload?.handleRemove?.(file);
+  }
+}
+// 绉婚櫎鏂囦欢
+function handleRemove(file, fileList) {
+  // 濡傛灉鏄紪杈戞ā寮忎笖鏂囦欢鏈塱d锛岃皟鐢ˋPI鍒犻櫎
+  if (dialogType.value === "edit" && file.id) {
+    delKnowledgeBaseFile([file.id]).then((res) => {
+      if (res.code === 200) {
+        proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+        // 浠巉orm.value.files涓Щ闄�
+        const index = form.value.files.findIndex(f => f.id === file.id);
+        if (index > -1) {
+          form.value.files.splice(index, 1);
+        }
+      } else {
+        proxy.$modal.msgError(res.msg || "鍒犻櫎澶辫触");
+        // 濡傛灉鍒犻櫎澶辫触锛岄噸鏂版坊鍔犲洖鏂囦欢鍒楄〃
+        fileList.push(file);
+      }
+    }).catch((error) => {
+      proxy.$modal.msgError("鍒犻櫎澶辫触");
+      // 濡傛灉鍒犻櫎澶辫触锛岄噸鏂版坊鍔犲洖鏂囦欢鍒楄〃
+      fileList.push(file);
+    });
+  } else {
+    // 鏂颁笂浼犵殑鏂囦欢锛岀洿鎺ヤ粠form.value.files涓Щ闄�
+    const index = form.value.files.findIndex(f => f.name === file.name && f.url === file.url);
+    if (index > -1) {
+      form.value.files.splice(index, 1);
+    }
+  }
+}
+
+// 鏂囦欢棰勮/涓嬭浇
+const handleDownload = (file) => {
+  const url = getUploadFileUrl(file)
+  if (!url) return
+  proxy?.$modal?.loading?.("姝e湪涓嬭浇鏂囦欢锛岃绋嶅��...")
+  proxy.$download.name(url);
+  proxy?.$modal?.closeLoading?.()
+}
+
+function handlePreview(file) {
+  const url = getUploadFileUrl(file)
+  if (!url) return
+  filePreviewRef.value?.open?.(url)
+}
+
+function triggerRemoveFile(file) {
+  fileUpload.value?.handleRemove?.(file) || proxy.$refs.fileUpload?.handleRemove?.(file);
+}
+
 // 鎻愪氦鐭ヨ瘑琛ㄥ崟
 const submitForm = async () => {
   try {
@@ -559,7 +793,7 @@
       addKnowledgeBase({...form.value}).then(res => {
         if(res.code == 200){
           ElMessage.success("娣诲姞鎴愬姛");
-          dialogVisible.value = false;
+          closeKnowledgeDialog();
           getList();
         }
       }).catch(err => {
@@ -569,7 +803,7 @@
       updateKnowledgeBase({...form.value}).then(res => {
         if(res.code == 200){
           ElMessage.success("鏇存柊鎴愬姛");
-          dialogVisible.value = false;
+          closeKnowledgeDialog();
           getList();
         }
       }).catch(err => {
@@ -662,12 +896,12 @@
 }
 
 .detail-content {
-  background: #f8f9fa;
-  padding: 16px;
-  border-radius: 6px;
   line-height: 1.6;
   color: #606266;
-  white-space: pre-wrap;
+}
+
+.detail-section {
+  margin-top: 24px;
 }
 
 .key-points {

--
Gitblit v1.9.3