|
|
@@ -6,7 +6,7 @@
|
|
|
</el-button>
|
|
|
</div>
|
|
|
<el-scrollbar class="tree-scrollbar">
|
|
|
- <el-tree v-loading="loading" :data="treeData" :props="treeProps" node-key="id" default-expand-all
|
|
|
+ <el-tree ref="treeRef" v-loading="loading" :data="treeData" :props="treeProps" node-key="id"
|
|
|
:expand-on-click-node="false">
|
|
|
<template #default="{ node, data }">
|
|
|
<span class="custom-tree-node">
|
|
|
@@ -102,6 +102,12 @@
|
|
|
<el-input v-model="form.note" type="textarea" :rows="4"
|
|
|
:placeholder="t('document.document.form.notePlaceholder')" />
|
|
|
</el-form-item>
|
|
|
+ <el-form-item :label="t('document.document.form.keywords')" prop="keywords">
|
|
|
+ <el-select v-loading="keywordLoading" v-model="form.keywords" multiple
|
|
|
+ :placeholder="t('document.document.form.keywordsPlaceholder')" style="width: 100%">
|
|
|
+ <el-option v-for="keyword in keywordList" :key="keyword.id" :label="keyword.content" :value="keyword.id" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
</el-form>
|
|
|
<template #footer>
|
|
|
<div class="dialog-footer">
|
|
|
@@ -117,13 +123,14 @@
|
|
|
<script setup lang="ts">
|
|
|
import { ref, reactive, onMounted, onUnmounted, nextTick, getCurrentInstance, watch, computed } from 'vue';
|
|
|
import { useI18n } from 'vue-i18n';
|
|
|
-import { listFolder, addFolder, delFolder, getFolder, updateFolder } from '@/api/document/folder';
|
|
|
+import { listFolder, addFolder, delFolder, getFolder, updateFolder, getNameByCenterId } from '@/api/document/folder';
|
|
|
import { FolderListVO, FolderForm } from '@/api/document/folder/types';
|
|
|
import { countTempDocuments } from '@/api/document/document';
|
|
|
import { Folder, Document, Location, OfficeBuilding, MoreFilled, ArrowRight } from '@element-plus/icons-vue';
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
import type { FormInstance } from 'element-plus';
|
|
|
import type { ComponentInternalInstance } from 'vue';
|
|
|
+import request from '@/utils/request';
|
|
|
|
|
|
interface Props {
|
|
|
projectId?: number | string;
|
|
|
@@ -133,20 +140,48 @@ const props = defineProps<Props>();
|
|
|
|
|
|
const emit = defineEmits<{
|
|
|
folderClick: [folder: FolderListVO];
|
|
|
- addDocument: [folder: FolderListVO];
|
|
|
+ addDocument: [folder: FolderListVO, projectInfo?: { projectName: string; centerId: number }];
|
|
|
refresh: [];
|
|
|
}>();
|
|
|
|
|
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
const { t } = useI18n();
|
|
|
|
|
|
+// 标签类型定义
|
|
|
+interface KeywordVO {
|
|
|
+ id: number;
|
|
|
+ content: string;
|
|
|
+ note?: string;
|
|
|
+}
|
|
|
+
|
|
|
// 数据定义
|
|
|
const loading = ref(false);
|
|
|
const buttonLoading = ref(false);
|
|
|
const treeData = ref<FolderListVO[]>([]);
|
|
|
+const treeRef = ref();
|
|
|
const folderFormRef = ref<FormInstance>();
|
|
|
const scanFormRef = ref<FormInstance>();
|
|
|
const tempDocumentCount = ref(0);
|
|
|
+const keywordList = ref<KeywordVO[]>([]);
|
|
|
+const keywordLoading = ref(false);
|
|
|
+
|
|
|
+// 获取标签列表
|
|
|
+const getKeywordList = async () => {
|
|
|
+ keywordLoading.value = true;
|
|
|
+ try {
|
|
|
+ const res = await request({
|
|
|
+ url: '/setting/keyword/listOnFolder',
|
|
|
+ method: 'get'
|
|
|
+ });
|
|
|
+ keywordList.value = res.data || [];
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('获取标签列表失败');
|
|
|
+ console.error('获取标签列表失败:', error);
|
|
|
+ keywordList.value = [];
|
|
|
+ } finally {
|
|
|
+ keywordLoading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
|
|
|
// 对话框
|
|
|
const dialog = reactive({
|
|
|
@@ -163,7 +198,7 @@ const isRestricted = ref(false);
|
|
|
const restrictionLevelValue = ref(0);
|
|
|
|
|
|
// 表单初始数据
|
|
|
-const initFormData: FolderForm = {
|
|
|
+const initFormData: FolderForm & { keywords?: number[] } = {
|
|
|
id: undefined,
|
|
|
projectId: undefined,
|
|
|
parentId: undefined,
|
|
|
@@ -171,11 +206,12 @@ const initFormData: FolderForm = {
|
|
|
name: '',
|
|
|
status: 0,
|
|
|
note: '',
|
|
|
- restrictionLevel: -1
|
|
|
+ restrictionLevel: -1,
|
|
|
+ keywords: []
|
|
|
};
|
|
|
|
|
|
// 表单数据
|
|
|
-const form = ref<FolderForm>({ ...initFormData });
|
|
|
+const form = ref<FolderForm & { keywords?: number[] }>({ ...initFormData });
|
|
|
|
|
|
// 表单验证规则
|
|
|
const rules = {
|
|
|
@@ -205,6 +241,10 @@ const getList = async () => {
|
|
|
|
|
|
loading.value = true;
|
|
|
try {
|
|
|
+ // 保存当前展开的节点
|
|
|
+ const expandedKeys = treeRef.value?.store?.nodesMap ?
|
|
|
+ Object.keys(treeRef.value.store.nodesMap).filter(key => treeRef.value.store.nodesMap[key].expanded) : [];
|
|
|
+
|
|
|
const res = await listFolder({ projectId: props.projectId } as any);
|
|
|
const folders = res.data || [];
|
|
|
|
|
|
@@ -223,6 +263,18 @@ const getList = async () => {
|
|
|
|
|
|
treeData.value = [...folders, tempFolder];
|
|
|
|
|
|
+ // 恢复展开状态
|
|
|
+ nextTick(() => {
|
|
|
+ if (expandedKeys.length > 0 && treeRef.value) {
|
|
|
+ expandedKeys.forEach(key => {
|
|
|
+ const node = treeRef.value.store.nodesMap[key];
|
|
|
+ if (node) {
|
|
|
+ node.expanded = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
// 获取临时文件夹文档数量
|
|
|
await getTempDocumentCount();
|
|
|
} catch (error) {
|
|
|
@@ -277,24 +329,28 @@ const cancel = () => {
|
|
|
};
|
|
|
|
|
|
// 新建文件夹(顶级)
|
|
|
-const handleAddFolder = () => {
|
|
|
+const handleAddFolder = async () => {
|
|
|
reset();
|
|
|
currentNode.value = null;
|
|
|
form.value.projectId = props.projectId;
|
|
|
form.value.parentId = undefined;
|
|
|
form.value.type = 1; // 默认选择国家类型
|
|
|
+ // 获取标签列表
|
|
|
+ await getKeywordList();
|
|
|
dialog.visible = true;
|
|
|
dialog.title = t('document.document.dialog.addFolder');
|
|
|
dialog.isEdit = false;
|
|
|
};
|
|
|
|
|
|
// 新增子节点(指定类型)
|
|
|
-const handleAddChildWithType = (data: FolderListVO, type: number) => {
|
|
|
+const handleAddChildWithType = async (data: FolderListVO, type: number) => {
|
|
|
reset();
|
|
|
currentNode.value = data;
|
|
|
form.value.projectId = props.projectId;
|
|
|
form.value.parentId = data.id;
|
|
|
form.value.type = type;
|
|
|
+ // 获取标签列表
|
|
|
+ await getKeywordList();
|
|
|
dialog.visible = true;
|
|
|
const typeLabel =
|
|
|
type === 0 ? t('document.document.type.folder') : type === 1 ? t('document.document.type.country') : t('document.document.type.center');
|
|
|
@@ -368,6 +424,9 @@ const handleEdit = async (data: FolderListVO) => {
|
|
|
restrictionLevelValue.value = form.value.restrictionLevel;
|
|
|
}
|
|
|
|
|
|
+ // 获取标签列表
|
|
|
+ await getKeywordList();
|
|
|
+
|
|
|
currentNode.value = null;
|
|
|
dialog.visible = true;
|
|
|
dialog.title = t('document.document.dialog.editFolder');
|
|
|
@@ -465,11 +524,29 @@ const handleMenuItemClick = (command: string, data: FolderListVO | null) => {
|
|
|
};
|
|
|
|
|
|
// 下拉菜单命令处理
|
|
|
-const handleCommand = (command: string, data: FolderListVO) => {
|
|
|
+const handleCommand = async (command: string, data: FolderListVO) => {
|
|
|
if (command.startsWith('add:')) {
|
|
|
const cmdPart = command.split(':')[1];
|
|
|
if (cmdPart === 'document') {
|
|
|
- emit('addDocument', data);
|
|
|
+ // 查找该文件夹所属的中心ID
|
|
|
+ const centerId = findCenterId(data);
|
|
|
+ console.log('新增文档 - 所属中心ID:', centerId);
|
|
|
+ console.log('新增文档 - 当前文件夹信息:', data);
|
|
|
+
|
|
|
+ // 如果找到中心ID,调用接口获取项目名称
|
|
|
+ if (centerId !== undefined) {
|
|
|
+ try {
|
|
|
+ const res = await getNameByCenterId(centerId);
|
|
|
+ console.log('获取到的项目信息:', res.data);
|
|
|
+ emit('addDocument', data, res.data);
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取项目名称失败:', error);
|
|
|
+ ElMessage.error('获取项目名称失败');
|
|
|
+ emit('addDocument', data);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ emit('addDocument', data);
|
|
|
+ }
|
|
|
} else {
|
|
|
const type = parseInt(cmdPart);
|
|
|
handleAddChildWithType(data, type);
|
|
|
@@ -481,6 +558,40 @@ const handleCommand = (command: string, data: FolderListVO) => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+// 查找文件夹所属的中心ID
|
|
|
+const findCenterId = (folder: FolderListVO): number | undefined => {
|
|
|
+ // 如果当前节点就是中心,直接返回其ID
|
|
|
+ if (folder.type === 2) {
|
|
|
+ return folder.id;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果有父节点ID,递归查找父节点
|
|
|
+ if (folder.parentId !== undefined && folder.parentId !== null) {
|
|
|
+ const parentFolder = findFolderById(treeData.value, folder.parentId);
|
|
|
+ if (parentFolder) {
|
|
|
+ return findCenterId(parentFolder);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return undefined;
|
|
|
+};
|
|
|
+
|
|
|
+// 根据ID查找文件夹
|
|
|
+const findFolderById = (folders: FolderListVO[], id: number): FolderListVO | undefined => {
|
|
|
+ for (const folder of folders) {
|
|
|
+ if (folder.id === id) {
|
|
|
+ return folder;
|
|
|
+ }
|
|
|
+ if (folder.children && folder.children.length > 0) {
|
|
|
+ const found = findFolderById(folder.children, id);
|
|
|
+ if (found) {
|
|
|
+ return found;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return undefined;
|
|
|
+};
|
|
|
+
|
|
|
// 点击文件夹节点
|
|
|
const handleFolderClick = (data: FolderListVO) => {
|
|
|
emit('folderClick', data);
|