From 09c5667700fb6da21d29c41e51fa5482a4b40bc9 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期五, 24 十月 2025 11:22:22 +0800
Subject: [PATCH] 新公司部署相关配置修改
---
src/views/archiveManagement/index.vue | 1031 ++++++++++++++++++++++++++++++++++++--------------------
1 files changed, 655 insertions(+), 376 deletions(-)
diff --git a/src/views/archiveManagement/index.vue b/src/views/archiveManagement/index.vue
index c3e56e4..8db8de6 100644
--- a/src/views/archiveManagement/index.vue
+++ b/src/views/archiveManagement/index.vue
@@ -5,23 +5,22 @@
<div class="tree-header">
<h3>鏂囨。绠$悊</h3>
<el-button icon="Plus" size="small" type="primary" @click="append('')"
- >鏂板
- </el-button
- >
+ >鏂板
+ </el-button>
</div>
<!-- 鎼滅储妗� -->
<div class="search-box">
<el-input
- v-model="filterText"
- clearable
- placeholder="杈撳叆鍏抽敭瀛楄繘琛屾悳绱�"
- size="small"
- @input="handleFilter"
+ v-model="filterText"
+ clearable
+ placeholder="杈撳叆鍏抽敭瀛楄繘琛屾悳绱�"
+ size="small"
+ @input="handleFilter"
>
<template #prefix>
<el-icon>
- <Search/>
+ <Search />
</el-icon>
</template>
</el-input>
@@ -29,62 +28,73 @@
<div class="tree-container">
<el-tree
- ref="treeRef"
- :data="treeData"
- :default-expand-all="false"
- :expand-on-click-node="false"
- :filter-node-method="filterNode"
- :props="props"
- class="custom-tree"
- node-key="id"
- @node-click="handleNodeClick"
+ ref="treeRef"
+ :data="treeData"
+ :default-expand-all="false"
+ :expand-on-click-node="false"
+ :filter-node-method="filterNode"
+ :props="props"
+ :lazy="false"
+ :load="undefined"
+ :render-after-expand="true"
+ :auto-expand-parent="true"
+ :indent="20"
+ class="custom-tree"
+ node-key="id"
+ @node-click="handleNodeClick"
+ @node-expand="handleNodeExpand"
>
<template #default="{ node, data }">
- <div class="tree-node-content" @dblclick="headerDbClick(node,data)">
+ <div
+ class="tree-node-content"
+ :data-temp-id="data._tempId"
+ :data-node-id="data.id"
+ @dblclick="headerDbClick(node, data)"
+ >
<div class="node-icon">
<el-icon
- v-if="!node.isLeaf"
- :class="{ expanded: node.expanded }"
+ v-if="!node.isLeaf"
+ :class="{ expanded: node.expanded }"
>
- <Folder/>
+ <Folder />
</el-icon>
<el-icon v-else>
- <Document/>
+ <Document />
</el-icon>
</div>
<div class="node-label">
<span v-if="!data.isEdit" class="label-text">{{
- node.label
- }}</span>
+ node.label
+ }}</span>
<el-input
- v-else
- :ref="(el) => setInputRef(el, data)"
- v-model="newName"
- autofocus
- class="tree-input"
- placeholder="璇疯緭鍏ヨ妭鐐瑰悕绉�"
- size="small"
- @blur="(event) => handleInputBlur(event, data, node)"
- @keyup.enter="
- (event) => handleInputBlur(event, data, node)
- "
+ v-else
+ :ref="(el) => setInputRef(data.id || data._tempId, el)"
+ v-model="newName"
+ autofocus
+ class="tree-input"
+ placeholder="璇疯緭鍏ヨ妭鐐瑰悕绉�"
+ size="small"
+ @blur="(event) => handleInputBlur(event, data, node)"
+ @keyup.enter="(event) => handleInputBlur(event, data, node)"
+ @keyup.esc="() => cancelEdit(data, node)"
/>
</div>
<div v-show="!data.isEdit" class="node-actions">
<el-button
- icon="Plus"
- link
- size="small"
- title="鏂板瀛愯妭鐐�"
- @click.stop="append(data)"
+ icon="Plus"
+ link
+ size="small"
+ :title="getNodeDepth(data) >= 7 ? '宸茶揪鍒版渶澶у祵濂楀眰绾э紙7灞傦級' : '鏂板瀛愯妭鐐�'"
+ :disabled="getNodeDepth(data) >= 7"
+ @click.stop="append(data)"
></el-button>
<el-button
- icon="Delete"
- link
- size="small"
- title="鍒犻櫎"
- @click.stop="remove(node, data)"
+ icon="Delete"
+ link
+ size="small"
+ title="鍒犻櫎"
+ @click.stop="remove(node, data)"
></el-button>
</div>
</div>
@@ -95,168 +105,236 @@
</div>
<div class="right">
<el-row :gutter="24">
- <el-col :offset="20" :span="2"
- >
- <el-button :icon="Delete" type="danger" @click="delHandler">鍒犻櫎</el-button>
- </el-col
- >
- <el-col :span="2"
- >
- <el-button
- :disabled="!tableSwitch"
- :icon="Plus"
- type="primary"
- @click="add"
- >鏂板
- </el-button
+ <el-col :span="10">
+ <div>
+ <el-input
+ style="float: left; width: 50%"
+ v-model="searchText"
+ placeholder="璇疯緭鍏ュ叧閿瓧鏌ヨ鏂囦欢"
+ clearable
+ @input="handleSearch"
+ @clear="handleSearch"
+ >
+ <template #prefix>
+ <el-icon>
+ <Search />
+ </el-icon>
+ </template>
+ <template #suffix>
+ <el-button @click="handleSearch" link style="border: none">
+ <span>鎼滅储</span>
+ </el-button>
+ </template>
+ </el-input>
+ </div>
+ </el-col>
+ <el-col :offset="8" :span="3">
+ <el-button :icon="Delete" type="danger" @click="delHandler"
+ >鍒犻櫎</el-button
>
- </el-col
- >
+ </el-col>
+ <el-col :span="3">
+ <el-button
+ :disabled="!tableSwitch"
+ :icon="Plus"
+ type="primary"
+ @click="add"
+ >鏂板
+ </el-button>
+ </el-col>
</el-row>
<ETable
- :border="true"
- :columns="columns"
- :loading="loading"
- :maxHeight="1200"
- :show-selection="true"
- :table-data="tableData"
- @edit="handleEdit"
- @selection-change="handleSelectionChange"
+ :border="true"
+ :columns="columns"
+ :loading="loading"
+ :maxHeight="1200"
+ :show-selection="true"
+ :table-data="tableData"
+ @edit="handleEdit"
+ @selection-change="handleSelectionChange"
+ style="height: calc(65vh);"
>
</ETable>
<Pagination
- :layout="'total, prev, pager, next, jumper'"
- :limit="queryParams.pageSize"
- :page="queryParams.current"
- :show-total="true"
- :total="total"
- @pagination="handlePageChange"
+ :layout="'total, prev, pager, next, jumper'"
+ :limit="queryParams.pageSize"
+ :page="queryParams.current"
+ :show-total="true"
+ :total="total"
+ @pagination="handlePageChange"
></Pagination>
</div>
<archiveDialog
- ref="archiveDialogs"
- v-model:centerDialogVisible="dialogVisible"
- :row="row"
- @centerDialogVisible="centerDialogVisible"
- @submitForm="submitForm"
-
+ ref="archiveDialogs"
+ v-model:centerDialogVisible="dialogVisible"
+ :row="row"
+ @centerDialogVisible="centerDialogVisible"
+ @submitForm="submitForm"
>
</archiveDialog>
</el-card>
</template>
<script setup>
-import {nextTick, onMounted, reactive, ref} from "vue";
+import { computed, nextTick, onMounted, reactive, ref } from "vue";
import ETable from "@/components/Table/ETable.vue";
-import {ElButton, ElIcon, ElInput, ElMessage, ElMessageBox} from "element-plus";
+import {
+ ElButton,
+ ElIcon,
+ ElInput,
+ ElMessage,
+ ElMessageBox,
+} from "element-plus";
import archiveDialog from "./mould/archiveDialog.vue";
import Pagination from "@/components/Pagination/index.vue";
-import {Delete, Document, Folder, Plus, Search,} from "@element-plus/icons-vue";
-import {addOrEditTree, delArchive, delTree, getArchiveList, getTree,} from "@/api/archiveManagement";
+import {
+ Delete,
+ Document,
+ Folder,
+ Plus,
+ Search,
+} from "@element-plus/icons-vue";
+import {
+ addOrEditTree,
+ delArchive,
+ delTree,
+ getArchiveList,
+ getTree,
+} from "@/api/archiveManagement";
-const dialogVisible = ref(false); // 鎺у埗褰掓。瀵硅瘽妗嗘樉绀�
+// ===== 鍝嶅簲寮忕姸鎬佺鐞� =====
+const searchText = ref("");
+const dialogVisible = ref(false);
const loading = ref(false);
const tableData = ref([]);
const treeData = ref([]);
const newName = ref("");
-const inputRefs = ref(new Map()); // 瀛樺偍杈撳叆妗嗗紩鐢�
-const filterText = ref(""); // 鎼滅储鍏抽敭瀛�
-const treeRef = ref(); // 鏍戠粍浠跺紩鐢�
-const total = ref(0); // 鎬昏褰曟暟
+const inputRefs = ref(new Map());
+const filterText = ref("");
+const treeRef = ref();
+const total = ref(0);
+const row = ref({});
+const selectedRows = reactive([]);
+const rowClickData = ref({});
+const tableSwitch = ref(false);
+const archiveDialogs = ref(null);
+
+// ===== 閰嶇疆甯搁噺 =====
const columns = [
- {prop: "name", label: "鍚嶇О", minWidth: 180},
- {prop: "type", label: "绫诲瀷", minWidth: 120},
- {prop: "status", label: "鐘舵��", minWidth: 100},
+ { prop: "name", label: "鍚嶇О", minWidth: 180 },
+ { prop: "type", label: "绫诲瀷", minWidth: 120 },
+ { prop: "status", label: "鐘舵��", minWidth: 100 },
];
-const selectedRows = reactive([]); // 瀛樺偍閫変腑琛屾暟鎹�
-const handleSelectionChange = (selection) => {
- selectedRows.splice(0, selectedRows.length, ...selection);
-};
+
const queryParams = reactive({
searchAll: "",
current: 1,
- pageSize: 10, // 鍥哄畾姣忛〉10鏉�
- treeId: null, // 褰撳墠鏍戣妭鐐笽D
+ pageSize: 10,
+ treeId: null,
});
-// 鎼滅储杩囨护鍔熻兘
+
+const props = {
+ label: "name",
+ children: "children",
+ isLeaf: "leaf",
+};
+
+// ===== 璁$畻灞炴�� =====
+// 璁$畻鎬昏妭鐐规暟
+const totalNodeCount = computed(() => {
+ const countNodes = (nodes) => {
+ let count = 0;
+ for (const node of nodes || []) {
+ count += 1;
+ if (node.children) {
+ count += countNodes(node.children);
+ }
+ }
+ return count;
+ };
+ return countNodes(treeData.value);
+});
+
+// 妫�鏌ユ槸鍚︿负澶ч噺鑺傜偣锛堣秴杩�1000涓妭鐐规椂鎻愮ず鎬ц兘浼樺寲锛�
+const isLargeTree = computed(() => totalNodeCount.value > 1000);
+
+// 鑾峰彇鑺傜偣娣卞害鐨勫嚱鏁�
+const getNodeDepth = (nodeData) => {
+ if (!nodeData || !nodeData.id) return 0;
+
+ let depth = 1;
+ const node = treeRef.value?.getNode(nodeData.id);
+ let parentNode = node?.parent;
+
+ while (parentNode && parentNode.data && parentNode.data.id) {
+ depth++;
+ parentNode = parentNode.parent;
+ }
+
+ return depth;
+};
+
+// ===== 宸ュ叿鍑芥暟 =====
+const handleError = (error, defaultMsg = "鎿嶄綔澶辫触锛岃绋嶅悗閲嶈瘯") => {
+ console.error(error);
+ ElMessage.error(defaultMsg);
+};
+
+const showSuccess = (msg = "鎿嶄綔鎴愬姛") => {
+ ElMessage.success(msg);
+};
+
+// 鎼滅储鏌ヨ鍑芥暟
+const handleSearch = () => {
+ queryParams.searchAll = searchText.value;
+ queryParams.current = 1; // 閲嶇疆鍒扮涓�椤�
+ getArchiveListData();
+};
+
+const showConfirm = (message, title = "纭鎿嶄綔") => {
+ return ElMessageBox.confirm(message, title, {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ });
+};
+
+// ===== 鍩虹鍔熻兘鍑芥暟 =====
+const handleSelectionChange = (selection) => {
+ selectedRows.splice(0, selectedRows.length, ...selection);
+};
+
const handleFilter = () => {
treeRef.value?.filter(filterText.value);
};
-const row = ref({}); // 褰撳墠閫変腑琛屾暟鎹�
+
const filterNode = (value, data) => {
if (!value) return true;
return data.name?.toLowerCase().includes(value.toLowerCase());
};
-const submitForm = async (res) => {
- try {
- if (res && res.code === 200) {
- ElMessage.success("鎿嶄綔鎴愬姛");
- dialogVisible.value = false;
- // 鍒锋柊鍒楄〃鏁版嵁
- await getArchiveListData();
- } else {
- ElMessage.error("鎿嶄綔澶辫触: " + (res?.message || res?.msg || "鏈煡閿欒"));
- }
- } catch (error) {
- console.error("鎻愪氦琛ㄥ崟閿欒:", error);
- ElMessage.error("鎿嶄綔澶辫触锛岃绋嶅悗閲嶈瘯");
- }
-};
-// 褰撳墠缁勪欢鐨勬暟鎹�
-const initTreeData = ref([]); // 鏍戝舰鏁版嵁
+
const centerDialogVisible = (val) => {
dialogVisible.value = val;
};
-const tableSwitch = ref(false);
-// 澶勭悊鑺傜偣鐐瑰嚮
-const handleNodeClick = (data) => {
- initTreeData.value = data || [];
- tableSwitch.value = true;
- // 鍒囨崲鑺傜偣鏃堕噸缃埌绗竴椤�
- queryParams.current = 1;
- queryParams.treeId = data.id;
- getArchiveListData();
-};
-const archiveDialogs = ref(null); // 琛ㄦ牸缁勪欢寮曠敤
-// 鏂板褰掓。
-const add = () => {
+// ===== 鏁版嵁鑾峰彇鍑芥暟 =====
+const getList = async () => {
try {
- row.value = {}; // 娓呯┖琛屾暟鎹紝纭繚鏄柊澧炴ā寮�
- newName.value = ""; // 娓呯┖杈撳叆妗�
- dialogVisible.value = true;
-
- // 纭繚缁勪欢寮曠敤瀛樺湪鍚庡啀璋冪敤鏂规硶
- nextTick(() => {
- if (archiveDialogs.value && typeof archiveDialogs.value.initForm === 'function') {
- archiveDialogs.value.initForm(initTreeData); // 閲嶇疆琛ㄥ崟
- }
- });
+ const res = await getTree();
+ treeData.value =
+ res.code === 200 ? res.data?.records || res.data || [] : [];
} catch (error) {
- console.error("鏂板褰掓。閿欒:", error);
- ElMessage.error("鎵撳紑鏂板鐣岄潰澶辫触");
- }
-};
-// 澶勭悊鍒嗛〉鍙樺寲
-const handlePageChange = (pagination) => {
- try {
- const { page, limit } = pagination;
- queryParams.current = page;
- if (limit) {
- queryParams.pageSize = limit;
- }
- getArchiveListData();
- } catch (error) {
- console.error("鍒嗛〉澶勭悊閿欒:", error);
- ElMessage.error("鍒嗛〉鎿嶄綔澶辫触");
+ handleError(error, "鑾峰彇鏍戠粨鏋勬暟鎹け璐�");
+ treeData.value = [];
}
};
const getArchiveListData = async () => {
try {
loading.value = true;
- let res = await getArchiveList({
+ const res = await getArchiveList({
treeId: queryParams.treeId,
current: queryParams.current,
size: queryParams.pageSize,
+ searchAll: queryParams.searchAll,
});
if (res.code !== 200) {
@@ -265,23 +343,94 @@
total.value = 0;
return;
}
+
tableData.value = res.data?.records || res.data || [];
total.value = res.data?.total || 0;
- // 纭繚鍒嗛〉鍙傛暟姝g‘鏇存柊
+
if (res.data?.current) {
queryParams.current = res.data.current;
}
- // pageSize 鍥哄畾涓�20锛屼笉浠庡悗绔幏鍙�
-
} catch (error) {
- ElMessage.error("鑾峰彇鏁版嵁澶辫触");
+ handleError(error, "鑾峰彇褰掓。鏁版嵁澶辫触");
tableData.value = [];
total.value = 0;
} finally {
loading.value = false;
}
};
-// 鍒犻櫎閫変腑鐨勫綊妗h褰�
+
+// ===== 琛ㄥ崟鎻愪氦澶勭悊 =====
+const submitForm = async (res) => {
+ try {
+ if (res?.code === 200) {
+ showSuccess();
+ dialogVisible.value = false;
+ await getArchiveListData();
+ } else {
+ ElMessage.error("鎿嶄綔澶辫触: " + (res?.message || res?.msg || "鏈煡閿欒"));
+ }
+ } catch (error) {
+ handleError(error, "鎻愪氦琛ㄥ崟澶辫触");
+ }
+};
+// ===== 鑺傜偣鎿嶄綔鍑芥暟 =====
+const handleNodeClick = (data) => {
+ rowClickData.value = data;
+ tableSwitch.value = true;
+ queryParams.current = 1;
+ queryParams.treeId = data.id;
+ getArchiveListData();
+};
+
+// 鑺傜偣灞曞紑浜嬩欢澶勭悊
+const handleNodeExpand = (data, node, instance) => {
+ // 灞曞紑鍚庣◢寰欢杩燂紝纭繚瀛愯妭鐐规覆鏌撳畬鎴�
+ setTimeout(() => {
+ // 濡傛灉鏈夋柊娣诲姞鐨勭紪杈戠姸鎬佽妭鐐癸紝鑱氱劍鍒板畠
+ if (data.children && data.children.length > 0) {
+ const editingChild = data.children.find(child => child.isEdit && child._tempId);
+ if (editingChild) {
+ focusInput(editingChild._tempId, 200);
+ }
+ }
+ }, 100);
+};
+
+const handlePageChange = (pagination) => {
+ try {
+ const { page, limit } = pagination;
+ queryParams.current = page;
+ if (limit) queryParams.pageSize = limit;
+ getArchiveListData();
+ } catch (error) {
+ handleError(error, "鍒嗛〉鎿嶄綔澶辫触");
+ }
+};
+
+// ===== 寮圭獥鎿嶄綔鍑芥暟 =====
+const openDialog = (isEdit = false, rowData = {}) => {
+ try {
+ row.value = isEdit ? { ...rowData } : {};
+ newName.value = "";
+ dialogVisible.value = true;
+
+ nextTick(() => {
+ if (archiveDialogs.value) {
+ const method = isEdit ? "editForm" : "initForm";
+ if (typeof archiveDialogs.value[method] === "function") {
+ archiveDialogs.value[method](isEdit ? rowData : rowClickData.value);
+ }
+ }
+ });
+ } catch (error) {
+ handleError(error, `鎵撳紑${isEdit ? "缂栬緫" : "鏂板"}鐣岄潰澶辫触`);
+ }
+};
+
+const add = () => openDialog(false);
+const handleEdit = (rows) => openDialog(true, rows);
+
+// ===== 鍒犻櫎鎿嶄綔鍑芥暟 =====
const delHandler = async () => {
if (selectedRows.length === 0) {
ElMessage.warning("璇烽�夋嫨瑕佸垹闄ょ殑鏁版嵁");
@@ -289,285 +438,393 @@
}
try {
- await ElMessageBox.confirm(
+ await showConfirm(
`纭畾瑕佸垹闄ら�変腑鐨� ${selectedRows.length} 鏉¤褰曞悧锛焋,
- '鍒犻櫎纭',
- {
- confirmButtonText: '纭畾',
- cancelButtonText: '鍙栨秷',
- type: 'warning',
- }
+ "鍒犻櫎纭"
);
const ids = selectedRows.map((row) => row.id);
const { code, msg } = await delArchive(ids);
-
+
if (code !== 200) {
ElMessage.error("鍒犻櫎澶辫触: " + msg);
return;
}
- ElMessage.success("鍒犻櫎鎴愬姛");
- // 鍒犻櫎鎴愬姛鍚庨噸鏂拌幏鍙栨暟鎹�
+ showSuccess("鍒犻櫎鎴愬姛");
await getArchiveListData();
- // 娓呯┖閫変腑鐘舵��
selectedRows.splice(0, selectedRows.length);
-
} catch (error) {
- if (error !== 'cancel') {
- console.error("鍒犻櫎褰掓。澶辫触:", error);
- ElMessage.error("鍒犻櫎鎿嶄綔澶辫触锛岃绋嶅悗閲嶈瘯");
+ if (error !== "cancel") {
+ handleError(error, "鍒犻櫎鎿嶄綔澶辫触");
}
}
};
-// 鍙屽嚮缂栬緫鑺傜偣
+
+const remove = async (node, data) => {
+ if (!data?.id) {
+ ElMessage.warning("鏃犳硶鍒犻櫎姝よ妭鐐�");
+ return;
+ }
+
+ try {
+ await showConfirm(`纭畾瑕佸垹闄よ妭鐐� "${data.name}" 鍚楋紵`, "鍒犻櫎纭");
+
+ const { code, msg } = await delTree([data.id]);
+
+ if (code !== 200) {
+ ElMessage.error("鍒犻櫎澶辫触: " + msg);
+ return;
+ }
+
+ showSuccess("鍒犻櫎鎴愬姛");
+ await getList();
+ } catch (error) {
+ if (error !== "cancel") {
+ handleError(error, "鍒犻櫎鑺傜偣澶辫触");
+ }
+ }
+};
+// ===== 鏍戣妭鐐圭紪杈戝嚱鏁� =====
+const setInputRef = (key, el) => {
+ if (el && key) {
+ inputRefs.value.set(key, el);
+ }
+};
+
const headerDbClick = (node, data) => {
- data.isEdit = true;
- newName.value = data.name;
- nextTick(() => {
- const inputEl = inputRefs.value.get(data.id || data);
- if (inputEl) {
- inputEl.focus();
- inputEl.select();
- }
- });
-};
-
-// 璁剧疆杈撳叆妗嗗紩鐢ㄧ殑鏂规硶
-const setInputRef = (el, data) => {
- if (el) {
- inputRefs.value.set(data.id || data, el);
- if (data.isEdit) {
- nextTick(() => {
- // el.focus();
- // el.select();
- });
- }
+ try {
+ data.isEdit = true;
+ newName.value = data.name;
+
+ nextTick(() => {
+ const key = data._tempId || data.id;
+ if (key) {
+ focusInput(key, 50);
+ }
+ });
+ } catch (error) {
+ console.error('杩涘叆缂栬緫妯″紡澶辫触:', error);
+ ElMessage.error('杩涘叆缂栬緫妯″紡澶辫触');
}
};
-// 澶勭悊杈撳叆妗嗗け鐒�
+// 鍙栨秷缂栬緫鍔熻兘
+const cancelEdit = (data, node) => {
+ try {
+ data.isEdit = false;
+
+ // 濡傛灉鏄柊鍒涘缓鐨勪复鏃惰妭鐐癸紝鍒犻櫎瀹�
+ if (data._tempId && !data.id) {
+ if (node.parent) {
+ const parent = node.parent.data;
+ const index = parent.children?.indexOf(data);
+ if (index > -1) {
+ parent.children.splice(index, 1);
+ }
+ } else {
+ // 鏍硅妭鐐�
+ const index = treeData.value.indexOf(data);
+ if (index > -1) {
+ treeData.value.splice(index, 1);
+ }
+ }
+
+ // 娓呯悊杈撳叆妗嗗紩鐢�
+ const key = data._tempId;
+ if (inputRefs.value.has(key)) {
+ inputRefs.value.delete(key);
+ }
+ }
+
+ // 閲嶇疆鍚嶇О
+ newName.value = "";
+ } catch (error) {
+ console.error('鍙栨秷缂栬緫澶辫触:', error);
+ }
+};
+
+const expandParentNodes = (node) => {
+ if (node?.parent?.data) {
+ node.parent.expanded = true;
+ expandParentNodes(node.parent);
+ }
+};
+
const handleInputBlur = async (event, comeTreeData, node) => {
try {
- if (!comeTreeData.isEdit) return; // 濡傛灉涓嶆槸缂栬緫鐘舵�侊紝鐩存帴杩斿洖
-
- if (event.relatedTarget && event.relatedTarget.tagName === "BUTTON") {
+ if (!comeTreeData.isEdit || event.relatedTarget?.tagName === "BUTTON")
return;
- }
-
+
comeTreeData.isEdit = false;
const newValue = newName.value.trim();
-
- if (comeTreeData.name === newValue) {
- return;
- }
-
- if (newValue === "") {
- newName.value = comeTreeData.name || "鏂拌妭鐐�";
+
+ // 濡傛灉鍚嶇О涓虹┖锛屽鐞嗙┖鍚嶇О鎯呭喌
+ if (!newValue) {
+ // 濡傛灉鏄柊鍒涘缓鐨勪复鏃惰妭鐐癸紝鍒犻櫎瀹�
+ if (comeTreeData._tempId && !comeTreeData.id) {
+ cancelEdit(comeTreeData, node);
+ } else {
+ // 宸插瓨鍦ㄧ殑鑺傜偣锛屾仮澶嶅師鍚嶇О
+ newName.value = comeTreeData.name || "鏂拌妭鐐�";
+ }
ElMessage.warning("鑺傜偣鍚嶇О涓嶈兘涓虹┖");
return;
}
-
- // 鑾峰彇鐖惰妭鐐圭殑id - 閫氳繃 node 鍙傛暟鏇村噯纭湴鑾峰彇
- let parentId = null;
- if (node && node.parent && node.parent.data) {
- parentId = node.parent.data.id;
+
+ // 濡傛灉鍚嶇О娌℃湁鏀瑰彉锛岀洿鎺ヨ繑鍥�
+ if (comeTreeData.name === newValue) {
+ return;
}
-
+
+ const parentId = node?.parent?.data?.id || null;
+
const result = await addOrEditTree({
name: newValue,
- parentId: parentId || null, // 濡傛灉娌℃湁鐖惰妭鐐癸紝鍒欎负 null
+ parentId,
id: comeTreeData.id || null,
});
- if (result.code === 200) {
+
+ if (result.code === 200) {
comeTreeData.name = newValue;
if (!comeTreeData.id && result.data) {
comeTreeData.id = result.data.id || result.data;
+ // 娓呯悊涓存椂ID
+ if (comeTreeData._tempId) {
+ const tempKey = comeTreeData._tempId;
+ delete comeTreeData._tempId;
+
+ // 鏇存柊寮曠敤鏄犲皠
+ if (inputRefs.value.has(tempKey)) {
+ const inputEl = inputRefs.value.get(tempKey);
+ inputRefs.value.delete(tempKey);
+ if (comeTreeData.id && inputEl) {
+ inputRefs.value.set(comeTreeData.id, inputEl);
+ }
+ }
+ }
}
- ElMessage.success("淇濆瓨鎴愬姛");
-
- // 鍒锋柊鏍戞暟鎹苟灞曞紑褰撳墠鑺傜偣
+ showSuccess("淇濆瓨鎴愬姛");
+
const currentNodeId = comeTreeData.id;
await getList();
-
- // 绛夊緟DOM鏇存柊鍚庡睍寮�鑺傜偣
+
nextTick(() => {
if (currentNodeId && treeRef.value) {
const targetNode = treeRef.value.getNode(currentNodeId);
if (targetNode) {
// 灞曞紑褰撳墠鑺傜偣
targetNode.expanded = true;
- // 濡傛灉鏈夌埗鑺傜偣锛屼篃灞曞紑鐖惰妭鐐硅矾寰�
+
+ // 灞曞紑鎵�鏈夌埗鑺傜偣
expandParentNodes(targetNode);
+
+ // 婊氬姩鍒拌妭鐐逛綅缃�
+ setTimeout(() => {
+ const nodeElement = document.querySelector(`[data-node-id="${currentNodeId}"]`);
+ if (nodeElement) {
+ nodeElement.scrollIntoView({
+ behavior: 'smooth',
+ block: 'center'
+ });
+ }
+ }, 300);
}
}
});
} else {
- comeTreeData.name = comeTreeData.name || "鏂拌妭鐐�";
+ // 淇濆瓨澶辫触锛屾仮澶嶅師鍚嶇О鎴栧垹闄や复鏃惰妭鐐�
+ if (comeTreeData._tempId && !comeTreeData.id) {
+ cancelEdit(comeTreeData, node);
+ } else {
+ comeTreeData.name = comeTreeData.name || "鏂拌妭鐐�";
+ }
ElMessage.error("淇濆瓨澶辫触: " + (result.msg || "鏈煡閿欒"));
}
-
} catch (error) {
- console.error("淇濆瓨鑺傜偣澶辫触:", error);
- comeTreeData.name = comeTreeData.name || "鏂拌妭鐐�";
- ElMessage.error("淇濆瓨澶辫触锛岃绋嶅悗閲嶈瘯");
+ handleError(error, "淇濆瓨鑺傜偣澶辫触");
+ // 鍑洪敊鏃跺鐞嗕复鏃惰妭鐐�
+ if (comeTreeData._tempId && !comeTreeData.id) {
+ cancelEdit(comeTreeData, node);
+ } else {
+ comeTreeData.name = comeTreeData.name || "鏂拌妭鐐�";
+ }
}
};
-onMounted(async () => {
- await getList();
+// ===== 鑺傜偣鏂板鍑芥暟 =====
+const createNewNode = (name, isEdit = true) => ({
+ name,
+ isEdit,
+ _tempId: Date.now() + Math.random(), // 娣诲姞涓存椂ID
});
-const props = {
- label: "name",
- children: "children", // 鏀逛负 children 浠ュ尮閰嶆爣鍑嗙粨鏋�
- isLeaf: "leaf",
-};
-// 灞曞紑鐖惰妭鐐硅矾寰�
-const expandParentNodes = (node) => {
- if (node && node.parent && node.parent.data) {
- // 閫掑綊灞曞紑鎵�鏈夌埗鑺傜偣
- node.parent.expanded = true;
- expandParentNodes(node.parent);
- }
-};
-
-// 鍒犻櫎鏍戣妭鐐�
-const remove = async (node, data) => {
- if (!data || !data.id) {
- ElMessage.warning("鏃犳硶鍒犻櫎姝よ妭鐐�");
- return;
- }
-
- try {
- await ElMessageBox.confirm(
- `纭畾瑕佸垹闄よ妭鐐� "${data.name}" 鍚楋紵`,
- '鍒犻櫎纭',
- {
- confirmButtonText: '纭畾',
- cancelButtonText: '鍙栨秷',
- type: 'warning',
+const focusInput = (nodeKey, delay = 100) => {
+ setTimeout(() => {
+ const inputEl = inputRefs.value.get(nodeKey);
+ if (inputEl) {
+ try {
+ // 鍏堟粴鍔ㄥ埌鍙鍖哄煙
+ inputEl.$el?.scrollIntoView?.({
+ behavior: "smooth",
+ block: "center",
+ });
+
+ // 鑱氱劍骞堕�変腑鎵�鏈夋枃鏈紝纭繚鍙互鐩存帴缂栬緫
+ setTimeout(() => {
+ inputEl.focus();
+ inputEl.select();
+
+ // 纭繚鍏夋爣鍦ㄨ緭鍏ユ鏈熬锛堝鏋渟elect澶辫触鐨勮瘽锛�
+ const inputElement = inputEl.ref || inputEl.input || inputEl.$el?.querySelector('input');
+ if (inputElement) {
+ inputElement.setSelectionRange(0, inputElement.value.length);
+
+ // 纭繚杈撳叆妗嗗湪瑙嗗彛涓ぎ
+ setTimeout(() => {
+ inputElement.scrollIntoView({
+ behavior: 'smooth',
+ block: 'center'
+ });
+ }, 100);
+ }
+ }, 100);
+ } catch (error) {
+ console.warn('鑱氱劍杈撳叆妗嗗け璐�:', error);
+ // 澶囩敤鏂规锛氱洿鎺ヨ仛鐒�
+ try {
+ inputEl.focus();
+ // 灏濊瘯閫変腑鏂囨湰
+ setTimeout(() => {
+ const inputElement = inputEl.ref || inputEl.input || inputEl.$el?.querySelector('input');
+ if (inputElement) {
+ inputElement.select();
+ }
+ }, 200);
+ } catch (e) {
+ console.warn('澶囩敤鑱氱劍鏂规涔熷け璐�:', e);
+ }
}
- );
-
- const { code, msg } = await delTree([data.id]);
-
- if (code !== 200) {
- ElMessage.error("鍒犻櫎澶辫触: " + msg);
- return;
+ } else {
+ console.warn('鏈壘鍒拌緭鍏ユ鍏冪礌锛宬ey:', nodeKey);
}
-
- ElMessage.success("鍒犻櫎鎴愬姛");
- await getList();
-
- } catch (error) {
- if (error !== 'cancel') {
- console.error("鍒犻櫎鑺傜偣澶辫触:", error);
- ElMessage.error("鍒犻櫎澶辫触锛岃绋嶅悗閲嶈瘯");
- }
- }
+ }, delay);
};
const append = async (data) => {
- if (data === "") {
- // 鏂板鏍硅妭鐐�
- const newNode = {
- name: "鏂拌妭鐐�",
- isEdit: true,
- };
- treeData.value.push(newNode);
- newName.value = "鏂拌妭鐐�";
-
- nextTick(() => {
- const inputEl = inputRefs.value.get(newNode.id || newNode);
- if (inputEl) {
- inputEl.focus();
- inputEl.select();
- }
- });
- } else {
- const hasChildren = data.children;
- const nodeKey = data.id || data;
- const node = treeRef.value?.getNode(nodeKey);
- const isExpanded = node?.expanded;
-
- // 濡傛灉鏈夊瓙绾т笖鏈睍寮�锛屽厛灞曞紑鑺傜偣
- if (hasChildren && !isExpanded) {
- if (treeRef.value && treeRef.value.store && treeRef.value.store.nodesMap[nodeKey]) {
- treeRef.value.store.nodesMap[nodeKey].expanded = true;
- }
- }
-
- const newNode = {
- name: "鏂板瓙鑺傜偣",
- isEdit: true,
- };
-
- if (!data.children) {
- data.children = [];
- }
- data.children.push(newNode);
- newName.value = "鏂板瓙鑺傜偣";
-
- // 纭繚鐖惰妭鐐瑰睍寮�
- if (node) {
- node.expanded = true;
- expandParentNodes(node);
- }
-
- // 鏍规嵁鏄惁闇�瑕佸睍寮�鏉ュ喅瀹氬欢杩熸椂闂�
- const delay = hasChildren && !isExpanded ? 200 : 50;
-
- // 绛夊緟DOM鏇存柊瀹屾垚鍚庡啀鑱氱劍
- nextTick(() => {
- setTimeout(() => {
- const inputEl = inputRefs.value.get(newNode.id || newNode);
- if (inputEl) {
- inputEl.focus();
- inputEl.select();
-
- // 婊氬姩鍒版柊澧炵殑鑺傜偣浣嶇疆
- inputEl.$el?.scrollIntoView?.({
- behavior: "smooth",
- block: "nearest",
- });
+ try {
+ // 妫�鏌ュ祵濂楀眰绾ч檺鍒�
+ const getNodeDepth = (nodeData, currentDepth = 1) => {
+ if (!nodeData || data === "") return 0; // 鏍硅妭鐐逛笉绠楀眰绾�
+
+ let depth = currentDepth;
+ let current = nodeData;
+
+ // 閫氳繃鏍戠粍浠惰幏鍙栫埗鑺傜偣鏉ヨ绠楁繁搴�
+ if (current.id) {
+ const node = treeRef.value?.getNode(current.id);
+ let parentNode = node?.parent;
+
+ while (parentNode && parentNode.data && parentNode.data.id) {
+ depth++;
+ parentNode = parentNode.parent;
}
- }, delay);
- });
- }
-};
-
-// 缂栬緫褰掓。
-const handleEdit = (rows) => {
- try {
- row.value = { ...rows }; // 浣跨敤娣辨嫹璐濋伩鍏嶅紩鐢ㄩ棶棰�
- dialogVisible.value = true;
-
- // 纭繚缁勪欢寮曠敤瀛樺湪鍚庡啀璋冪敤鏂规硶
- nextTick(() => {
- if (archiveDialogs.value && typeof archiveDialogs.value.editForm === 'function') {
- archiveDialogs.value.editForm(rows); // 璋冪敤缂栬緫鏂规硶
}
- });
- } catch (error) {
- console.error("缂栬緫褰掓。閿欒:", error);
- ElMessage.error("鎵撳紑缂栬緫鐣岄潰澶辫触");
- }
-};
+
+ return depth;
+ };
-// 绉婚櫎鎳掑姞杞斤紝鐩存帴鑾峰彇鏁版嵁
-const getList = async () => {
- try {
- let res = await getTree();
- if (res.code === 200) {
- treeData.value = res.data?.records || res.data || [];
+ const currentDepth = getNodeDepth(data);
+
+ // 闄愬埗鏈�澶�7灞傚祵濂�
+ if (currentDepth >= 7) {
+ ElMessage.warning('鏈�澶氬彧鑳藉祵濂�7灞傝妭鐐癸紝褰撳墠宸茶揪鍒版渶澶у眰绾ч檺鍒�');
+ return;
+ }
+
+ // 鍦ㄥぇ閲忚妭鐐规椂鎻愮ず鎬ц兘娉ㄦ剰浜嬮」
+ if (isLargeTree.value && totalNodeCount.value > 2000) {
+ const confirmed = await ElMessageBox.confirm(
+ `褰撳墠鏍戠粨鏋勫寘鍚� ${totalNodeCount.value} 涓妭鐐癸紝鑺傜偣杈冨鍙兘褰卞搷鎬ц兘銆傚缓璁�冭檻鍒嗗眰绠$悊銆傛槸鍚︾户缁坊鍔狅紵`,
+ '鎬ц兘鎻愮ず',
+ {
+ confirmButtonText: '缁х画娣诲姞',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning',
+ }
+ ).catch(() => false);
+
+ if (!confirmed) return;
+ }
+
+ if (data === "") {
+ // 鏂板鏍硅妭鐐�
+ const newNode = createNewNode("鏂拌妭鐐�");
+ treeData.value.push(newNode);
+ newName.value = "鏂拌妭鐐�";
+
+ await nextTick();
+ focusInput(newNode._tempId, 200);
} else {
- treeData.value = [];
+ const hasChildren = data.children && data.children.length > 0;
+ const nodeKey = data.id || data;
+ const node = treeRef.value?.getNode(nodeKey);
+
+ // 鍒涘缓鏂板瓙鑺傜偣
+ const newNode = createNewNode("鏂板瓙鑺傜偣");
+
+ if (!data.children) {
+ data.children = [];
+ }
+ data.children.push(newNode);
+ newName.value = "鏂板瓙鑺傜偣";
+
+ // 寮哄埗鏇存柊鏍戠粨鏋�
+ await nextTick();
+
+ // 纭繚鐖惰妭鐐瑰睍寮�浠ユ樉绀烘柊鑺傜偣
+ if (node) {
+ node.expanded = true;
+
+ // 濡傛灉鏄涓�娆℃坊鍔犲瓙鑺傜偣锛岀瓑寰呭睍寮�鍔ㄧ敾骞剁‘淇濆彲瑙�
+ if (!hasChildren) {
+ await new Promise(resolve => setTimeout(resolve, 300));
+
+ // 灞曞紑鍚庢粴鍔ㄥ埌鏂拌妭鐐逛綅缃�
+ setTimeout(() => {
+ const newNodeElement = document.querySelector(`[data-temp-id="${newNode._tempId}"]`);
+ if (newNodeElement) {
+ newNodeElement.scrollIntoView({
+ behavior: 'smooth',
+ block: 'center'
+ });
+ }
+ }, 100);
+ }
+
+ // 灞曞紑鎵�鏈夌埗鑺傜偣纭繚瀹屽叏鍙
+ let parentNode = node.parent;
+ while (parentNode && parentNode.data && parentNode.data.id) {
+ parentNode.expanded = true;
+ parentNode = parentNode.parent;
+ }
+ }
+
+ // 鑱氱劍鍒版柊鍒涘缓鐨勮緭鍏ユ
+ const delay = hasChildren ? 150 : 500; // 濡傛灉涔嬪墠娌℃湁瀛愯妭鐐癸紝寤惰繜鏇撮暱鏃堕棿绛夊睍寮�
+ focusInput(newNode._tempId, delay);
}
} catch (error) {
- treeData.value = [];
+ console.error('鏂板鑺傜偣澶辫触:', error);
+ ElMessage.error('鏂板鑺傜偣澶辫触锛岃閲嶈瘯');
}
};
+
+// ===== 鐢熷懡鍛ㄦ湡 =====
+onMounted(()=>{
+ getList();
+ getArchiveListData();
+});
</script>
<style lang="scss" scoped>
.custom-tree-node {
@@ -624,18 +881,27 @@
border-radius: 8px;
background: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
+ max-height: calc(100vh - 240px); // 闄愬埗鏈�澶ч珮搴︼紝鍚敤婊氬姩
.custom-tree {
padding: 8px;
background: transparent;
+ // 浣跨敤GPU鍔犻�熸彁鍗囨粴鍔ㄦ�ц兘
+ transform: translateZ(0);
+ will-change: scroll-position;
:deep(.el-tree-node) {
+ // 鍑忓皯涓嶅繀瑕佺殑閲嶇粯
+ contain: layout style;
+
.el-tree-node__content {
height: 36px;
padding: 0 8px;
border-radius: 6px;
margin: 2px 0;
transition: all 0.2s ease;
+ // 浼樺寲娓叉煋鎬ц兘
+ will-change: background-color;
&:hover {
background-color: #f0f9ff;
@@ -715,13 +981,19 @@
color: #909399;
min-height: auto;
- &:hover {
+ &:hover:not(:disabled) {
color: #1890ff;
background-color: #f0f9ff;
}
- &.el-button--text:hover {
+ &.el-button--text:hover:not(:disabled) {
background-color: #f0f9ff;
+ }
+
+ &:disabled {
+ color: #c0c4cc;
+ cursor: not-allowed;
+ background-color: transparent;
}
}
}
@@ -737,11 +1009,13 @@
:deep(.el-input__wrapper) {
border-radius: 4px;
- border: 1px solid #d9d9d9;
+ border: 1px solid #40a9ff;
transition: all 0.2s ease;
+ box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
&:hover {
- border-color: #40a9ff;
+ border-color: #1890ff;
+ box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.15);
}
&.is-focus {
@@ -754,10 +1028,15 @@
padding: 4px 8px;
font-size: 14px;
color: #303133;
+ background-color: #fff;
&::placeholder {
color: #bfbfbf;
}
+
+ &:focus {
+ background-color: #f8fcff;
+ }
}
}
--
Gitblit v1.9.3