From ff5b4a4202405b26393c5f71999e43f3e2746499 Mon Sep 17 00:00:00 2001
From: 张诺 <zhang_12370@163.com>
Date: 星期三, 08 四月 2026 15:13:12 +0800
Subject: [PATCH] feat(知识库): 添加批量操作和文件删除功能
---
src/pages/cooperativeOffice/collaborativeApproval/knowledgeBase/detail.vue | 78 +++++++++++---
src/pages/cooperativeOffice/collaborativeApproval/knowledgeBase/index.vue | 206 ++++++++++++++++++++++++++++++++++++++++-
src/api/managementMeetings/knowledgeBase.js | 11 ++
3 files changed, 269 insertions(+), 26 deletions(-)
diff --git a/src/api/managementMeetings/knowledgeBase.js b/src/api/managementMeetings/knowledgeBase.js
index ad0ce77..2493fbe 100644
--- a/src/api/managementMeetings/knowledgeBase.js
+++ b/src/api/managementMeetings/knowledgeBase.js
@@ -33,4 +33,13 @@
method: "delete",
data: query,
});
-}
\ No newline at end of file
+}
+
+// 鍒犻櫎鐭ヨ瘑搴撴枃浠�
+export function delKnowledgeBaseFile(fileIds) {
+ return request({
+ url: "/knowledgeBaseFile/del",
+ method: "delete",
+ data: fileIds,
+ });
+}
diff --git a/src/pages/cooperativeOffice/collaborativeApproval/knowledgeBase/detail.vue b/src/pages/cooperativeOffice/collaborativeApproval/knowledgeBase/detail.vue
index 88af8c9..a8f708a 100644
--- a/src/pages/cooperativeOffice/collaborativeApproval/knowledgeBase/detail.vue
+++ b/src/pages/cooperativeOffice/collaborativeApproval/knowledgeBase/detail.vue
@@ -108,10 +108,10 @@
<view class="upload-tip" v-if="!readonly">
鏀寔鏂囨。锛坉oc, docx, xls, xlsx, pdf, txt锛夊拰鍥剧墖锛坖pg, jpeg, png, gif锛夋牸寮�
</view>
- <view class="file-list" v-if="form.commonFileList && form.commonFileList.length > 0">
- <view v-for="(file, index) in form.commonFileList" :key="index" class="file-item">
+ <view class="file-list" v-if="form.files && form.files.length > 0">
+ <view v-for="(file, index) in form.files" :key="index" class="file-item">
<up-icon name="file-text" size="20" color="#667eea"></up-icon>
- <text class="file-name" @click="previewFile(file)">{{ file.name || file.fileName }}</text>
+ <text class="file-name">{{ file.name || file.fileName }}</text>
<up-icon v-if="!readonly" name="close-circle-fill" size="18" color="#ff4d4f" @click="handleRemoveFile(index)"></up-icon>
</view>
</view>
@@ -172,9 +172,12 @@
import {
addKnowledgeBase,
updateKnowledgeBase,
+ delKnowledgeBaseFile,
} from "@/api/managementMeetings/knowledgeBase";
import { userListNoPageByTenantId } from "@/api/system/user";
import upload from "@/utils/upload";
+ import { getToken } from "@/utils/auth";
+ import config from "@/config";
defineOptions({ name: "knowledge-base-detail" });
@@ -206,7 +209,7 @@
creator: userStore.nickName || "",
usageCount: 0,
tempFileIds: [],
- commonFileList: []
+ files: []
});
// 閫夋嫨鍣ㄧ姸鎬�
@@ -300,11 +303,11 @@
if (!form.value.tempFileIds) form.value.tempFileIds = [];
form.value.tempFileIds.push(res.data.tempId);
- if (!form.value.commonFileList) form.value.commonFileList = [];
- form.value.commonFileList.push({
- id: res.data.tempId,
+ if (!form.value.files) form.value.files = [];
+ form.value.files.push({
+ tempId: res.data.tempId,
name: item.name || '鏈懡鍚嶆枃浠�',
- url: res.data.url
+ url: res.data.url || res.data.tempPath
});
showToast('涓婁紶鎴愬姛');
@@ -321,20 +324,48 @@
const deleteFile = (event) => {
const { index } = event;
- form.value.commonFileList.splice(index, 1);
- if (form.value.tempFileIds) {
- form.value.tempFileIds.splice(index, 1);
- }
+ handleRemoveFile(index);
};
- const handleRemoveFile = (index) => {
- form.value.commonFileList.splice(index, 1);
- if (form.value.tempFileIds) {
- form.value.tempFileIds.splice(index, 1);
+ const handleRemoveFile = async (index) => {
+ const list = Array.isArray(form.value.files)
+ ? form.value.files
+ : [];
+ const file = list[index];
+ if (!file) return;
+
+ const fileId = file.id;
+ const tempId = file.tempId || file.tempFileId;
+ const isEditMode = detailType.value === 2;
+ const canDeleteRemote = isEditMode && !!fileId;
+
+ try {
+ if (canDeleteRemote) {
+ uni.showLoading({ title: "鍒犻櫎涓�...", mask: true });
+ const res = await delKnowledgeBaseFile([fileId]);
+ uni.hideLoading();
+ if (res.code !== 200) {
+ showToast(res.msg || "鍒犻櫎澶辫触");
+ return;
+ }
+ }
+
+ form.value.files.splice(index, 1);
+ if (form.value.tempFileIds) {
+ const idx = form.value.tempFileIds.findIndex(
+ v => String(v) === String(tempId || fileId)
+ );
+ if (idx > -1) form.value.tempFileIds.splice(idx, 1);
+ }
+ } catch (e) {
+ uni.hideLoading();
+ console.error("鍒犻櫎闄勪欢澶辫触:", e);
+ showToast("鍒犻櫎澶辫触");
}
};
const previewFile = (file) => {
+ console.log("previewFile", file);
if (file.url) {
// 濡傛灉鏄浘鐗囷紝棰勮鍥剧墖
const isImage = /\.(jpg|jpeg|png|gif)$/i.test(file.name || file.fileName || file.url);
@@ -345,7 +376,10 @@
} else {
// 鍏朵粬鏂囦欢灏濊瘯鎵撳紑
uni.downloadFile({
- url: file.url,
+ url: file.url.startsWith("http") ? file.url : (config.baseUrl + file.url),
+ header: {
+ Authorization: "Bearer " + getToken(),
+ },
success: (res) => {
if (res.statusCode === 200) {
uni.openDocument({
@@ -401,8 +435,14 @@
if (!knowledgeId.value || String(data.id) === String(knowledgeId.value)) {
form.value = JSON.parse(JSON.stringify(data));
// 鍏煎澶勭悊鏂囦欢鍒楄〃
- if (form.value.commonFileList) {
- form.value.tempFileIds = form.value.commonFileList.map(f => f.id || f.tempId);
+ if (form.value.files) {
+ const ids = (form.value.files || [])
+ .map(f => f?.tempId || f?.tempFileId || f?.id)
+ .filter(v => v !== undefined && v !== null && v !== "");
+ form.value.tempFileIds = ids;
+ }
+ if (!Array.isArray(form.value.files)) {
+ form.value.files = [];
}
}
}
diff --git a/src/pages/cooperativeOffice/collaborativeApproval/knowledgeBase/index.vue b/src/pages/cooperativeOffice/collaborativeApproval/knowledgeBase/index.vue
index 5370e3c..a68e1cb 100644
--- a/src/pages/cooperativeOffice/collaborativeApproval/knowledgeBase/index.vue
+++ b/src/pages/cooperativeOffice/collaborativeApproval/knowledgeBase/index.vue
@@ -2,7 +2,32 @@
<view class="sales-accoun">
<!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 -->
<PageHeader title="鐭ヨ瘑搴�"
- @back="goBack" />
+ @back="goBack">
+ <template #right>
+ <view class="header-actions">
+ <uni-icons v-if="!batchMode"
+ type="download"
+ size="20"
+ color="#333"
+ @click="handleExport" />
+ <uni-icons v-if="!batchMode"
+ type="trash"
+ size="20"
+ color="#333"
+ @click="enterBatchMode" />
+ <uni-icons v-if="batchMode"
+ type="trash"
+ size="20"
+ color="#333"
+ @click="handleBatchDelete" />
+ <uni-icons v-if="batchMode"
+ type="closeempty"
+ size="20"
+ color="#333"
+ @click="exitBatchMode" />
+ </view>
+ </template>
+ </PageHeader>
<!-- 鎼滅储鍜岀瓫閫夊尯鍩� -->
<view class="search-section">
<view class="search-bar">
@@ -20,6 +45,18 @@
color="#999"></u-icon>
</view>
</view>
+ <view class="filter-row">
+ <view class="filter-input">
+ <up-input v-model="typeName"
+ readonly
+ placeholder="璇烽�夋嫨鐭ヨ瘑绫诲瀷"
+ @click="showTypeSheet = true" />
+ </view>
+ <view class="filter-reset"
+ @click="resetFilters">
+ 閲嶇疆
+ </view>
+ </view>
</view>
<!-- 鎷滆璁板綍鍒楄〃 -->
<view class="ledger-list"
@@ -35,6 +72,13 @@
color="#ffffff"></up-icon>
</view>
<text class="item-id">鐭ヨ瘑鏍囬锛歿{ item.title || '-' }}</text>
+ </view>
+ <view v-if="batchMode"
+ class="select-icon"
+ @click.stop="toggleSelection(item)">
+ <uni-icons :type="isSelected(item) ? 'checkbox-filled' : 'checkbox'"
+ size="20"
+ :color="isSelected(item) ? '#667eea' : '#999'" />
</view>
</view>
<up-divider></up-divider>
@@ -66,25 +110,26 @@
</view>
</view>
<!-- 鎸夐挳鍖哄煙 -->
- <view class="action-buttons">
+ <view class="action-buttons"
+ v-if="!batchMode">
<u-button type="info"
size="small"
class="action-btn"
plain
- @click="viewDetail(item, 3)">
+ @click.stop="viewDetail(item, 3)">
鏌ョ湅璇︽儏
</u-button>
<u-button type="primary"
size="small"
class="action-btn"
- @click="viewDetail(item, 2)">
+ @click.stop="viewDetail(item, 2)">
缂栬緫
</u-button>
<u-button type="error"
size="small"
class="action-btn"
plain
- @click="confirmDelete(item)">
+ @click.stop="confirmDelete(item)">
鍒犻櫎
</u-button>
</view>
@@ -102,6 +147,12 @@
size="24"
color="#ffffff"></up-icon>
</view>
+
+ <up-action-sheet :show="showTypeSheet"
+ :actions="typeOptions"
+ title="璇烽�夋嫨鐭ヨ瘑绫诲瀷"
+ @select="onTypeSelect"
+ @close="showTypeSheet = false" />
</view>
</template>
@@ -115,6 +166,8 @@
delKnowledgeBase,
} from "@/api/managementMeetings/knowledgeBase";
import useUserStore from "@/store/modules/user";
+ import config from "@/config";
+ import { getToken } from "@/utils/auth";
defineOptions({ name: "knowledge-base-index" });
@@ -129,9 +182,13 @@
// 鎼滅储鍏抽敭璇�
const name = ref("");
+ const type = ref("");
+ const showTypeSheet = ref(false);
// 鎷滆璁板綍鏁版嵁
const visitList = ref([]);
+ const batchMode = ref(false);
+ const selectedIds = ref([]);
// 杩斿洖涓婁竴椤�
const goBack = () => {
@@ -139,6 +196,30 @@
};
const { knowledge_type } = useDict("knowledge_type");
+ const typeOptions = computed(() => {
+ const opts = (knowledge_type?.value || []).map(item => ({
+ name: item.label,
+ value: item.value
+ }));
+ return [{ name: "鍏ㄩ儴", value: "" }, ...opts];
+ });
+
+ const typeName = computed(() => {
+ const item = typeOptions.value.find(i => String(i.value) === String(type.value));
+ return item ? item.name : (type.value || "");
+ });
+
+ const onTypeSelect = (action) => {
+ type.value = action.value;
+ showTypeSheet.value = false;
+ handleQuery();
+ };
+
+ const resetFilters = () => {
+ name.value = "";
+ type.value = "";
+ handleQuery();
+ };
// 鏍煎紡鍖栧洖娆炬柟寮�
const formatReceiptType = params => {
@@ -190,6 +271,7 @@
current: -1,
size: -1,
title: name.value,
+ type: type.value || undefined,
};
listKnowledgeBase(params)
.then(res => {
@@ -234,6 +316,49 @@
});
};
+ const enterBatchMode = () => {
+ batchMode.value = true;
+ selectedIds.value = [];
+ };
+
+ const exitBatchMode = () => {
+ batchMode.value = false;
+ selectedIds.value = [];
+ };
+
+ const toggleSelection = item => {
+ const id = item?.id;
+ if (!id) return;
+ const idx = selectedIds.value.findIndex(v => String(v) === String(id));
+ if (idx > -1) {
+ selectedIds.value.splice(idx, 1);
+ } else {
+ selectedIds.value.push(id);
+ }
+ };
+
+ const isSelected = item => {
+ const id = item?.id;
+ if (!id) return false;
+ return selectedIds.value.some(v => String(v) === String(id));
+ };
+
+ const handleBatchDelete = () => {
+ if (selectedIds.value.length === 0) {
+ showToast("璇烽�夋嫨瑕佸垹闄ょ殑鐭ヨ瘑");
+ return;
+ }
+ uni.showModal({
+ title: "鍒犻櫎纭",
+ content: `纭畾瑕佸垹闄ら�変腑鐨� ${selectedIds.value.length} 鏉$煡璇嗗悧锛焋,
+ success: res => {
+ if (res.confirm) {
+ deleteKnowledge(selectedIds.value);
+ }
+ },
+ });
+ };
+
// 鍒犻櫎纭
const confirmDelete = item => {
uni.showModal({
@@ -250,11 +375,15 @@
// 鎵ц鍒犻櫎
const deleteKnowledge = id => {
showLoadingToast("鍒犻櫎涓�...");
- delKnowledgeBase([id])
+ const ids = Array.isArray(id) ? id : [id];
+ delKnowledgeBase(ids)
.then(res => {
closeToast();
if (res.code === 200) {
showToast("鍒犻櫎鎴愬姛");
+ if (batchMode.value) {
+ exitBatchMode();
+ }
getList(); // 閲嶆柊鑾峰彇鍒楄〃
} else {
showToast("鍒犻櫎澶辫触");
@@ -264,6 +393,41 @@
closeToast();
showToast("鍒犻櫎澶辫触");
});
+ };
+
+ const handleExport = async () => {
+ try {
+ uni.showLoading({ title: "瀵煎嚭涓�...", mask: true });
+ const params = {
+ title: name.value || undefined,
+ type: type.value || undefined,
+ };
+ const query = Object.entries(params)
+ .filter(([, v]) => v !== undefined && v !== null && v !== "")
+ .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)
+ .join("&");
+ const url = config.baseUrl + "/knowledgeBase/export" + (query ? `?${query}` : "");
+ const res = await uni.downloadFile({
+ url,
+ header: {
+ Authorization: "Bearer " + getToken(),
+ },
+ });
+ uni.hideLoading();
+
+ if (res.statusCode !== 200) {
+ showToast("瀵煎嚭澶辫触");
+ return;
+ }
+ uni.openDocument({
+ filePath: res.tempFilePath,
+ showMenu: true,
+ fail: () => showToast("鎵撳紑鏂囦欢澶辫触"),
+ });
+ } catch (e) {
+ uni.hideLoading();
+ showToast("瀵煎嚭澶辫触");
+ }
};
onMounted(() => {
@@ -318,6 +482,36 @@
z-index: 100;
}
+ .header-actions {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ padding-right: 8px;
+ }
+
+ .filter-row {
+ margin-top: 10px;
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ }
+
+ .filter-input {
+ flex: 1;
+ }
+
+ .filter-reset {
+ padding: 6px 12px;
+ background: #f5f7fa;
+ border-radius: 6px;
+ color: #666;
+ font-size: 12px;
+ }
+
+ .select-icon {
+ padding-left: 10px;
+ }
+
.action-buttons {
display: flex;
justify-content: flex-end;
--
Gitblit v1.9.3