20260802220544
This commit is contained in:
1 parent
c00329b5a4
commit
4fc9040a8a
60 files changed
+6273
-908
No files matched your search
@@ -9,8 +9,6 @@ import { loadDataApi, nextIdApi, pageDataApi, saveObjectApi } from "@/services/a
|
||||
import { buildTree, sortTree } from "@/utils/tree";
|
||||
|
||||
const ALL_CATEGORIES_KEY = "__fms_tree_root__";
|
||||
const CATEGORY_COLUMNS = ["b_id", "b_parent_id", "b_name", "b_level", "b_path", "b_xh", "b_canuse"];
|
||||
|
||||
const categories = ref([]);
|
||||
const categoryLoading = ref(false);
|
||||
const selectedCategoryKey = ref(ALL_CATEGORIES_KEY);
|
||||
@@ -22,14 +20,20 @@ const categoryById = computed(
|
||||
|
||||
const categoryTree = computed(() => {
|
||||
const roots = buildTree(categories.value, {
|
||||
mapNode: (item) => ({
|
||||
key: String(item.b_id),
|
||||
title: Number(item.b_canuse) === 1 ? item.b_name : `${item.b_name}(停用)`,
|
||||
b_id: String(item.b_id),
|
||||
b_parent_id: item.b_parent_id == null ? null : String(item.b_parent_id),
|
||||
b_xh: item.b_xh,
|
||||
children: [],
|
||||
}),
|
||||
mapNode: (item) => {
|
||||
let title = item.b_name;
|
||||
if (Number(item.b_canuse) !== 1) {
|
||||
title = `${title}(停用)`;
|
||||
}
|
||||
return {
|
||||
key: String(item.b_id),
|
||||
title,
|
||||
b_id: String(item.b_id),
|
||||
b_parent_id: item.b_parent_id == null ? null : String(item.b_parent_id),
|
||||
b_xh: item.b_xh,
|
||||
children: [],
|
||||
};
|
||||
},
|
||||
});
|
||||
sortTree(roots);
|
||||
return roots;
|
||||
@@ -44,7 +48,11 @@ const categoryFilterCondition = computed(() => {
|
||||
|
||||
const columnExtensions = computed(() => ({
|
||||
b_cate_id: {
|
||||
formatter: ({ value }) => categoryById.value.get(String(value || ""))?.b_name || value || "",
|
||||
formatter: ({ value }) => {
|
||||
const cat = categoryById.value.get(String(value || ""));
|
||||
if (!cat) return value || "";
|
||||
return cat.b_name || value || "";
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -72,12 +80,7 @@ function collectDescendantIds(rootId) {
|
||||
async function loadCategories() {
|
||||
categoryLoading.value = true;
|
||||
try {
|
||||
const response = await loadDataApi(
|
||||
"b_othercompany_bmfl",
|
||||
"",
|
||||
"b_path ASC, b_xh ASC, b_id ASC",
|
||||
CATEGORY_COLUMNS,
|
||||
);
|
||||
const response = await loadDataApi("b_othercompany_bmfl", "", "b_path ASC, b_xh ASC, b_id ASC");
|
||||
categories.value = response.data || [];
|
||||
|
||||
const existingKeys = new Set(categories.value.map((item) => String(item.b_id)));
|
||||
@@ -187,6 +190,7 @@ function openEditCategoryModal(node) {
|
||||
addModalParentId.value = parentId;
|
||||
addModalParentName.value = parent?.b_name || "";
|
||||
addForm.b_name = category.b_name || "";
|
||||
|
||||
addModalVisible.value = true;
|
||||
}
|
||||
|
||||
@@ -364,7 +368,9 @@ async function confirmDeleteCategory(node) {
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(loadCategories);
|
||||
onMounted(() => {
|
||||
loadCategories();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -413,6 +419,7 @@ onMounted(loadCategories);
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -472,4 +479,5 @@ onMounted(loadCategories);
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup>
|
||||
import { computed, h, onMounted, reactive, ref } from "vue";
|
||||
import { computed, h, onMounted, reactive, ref, watch } from "vue";
|
||||
import { message, Modal } from "antdv-next";
|
||||
import { Pencil, Plus, RefreshCw, Trash2 } from "@lucide/vue";
|
||||
import { Pencil, Plus, RefreshCw, Save, Trash2 } from "@lucide/vue";
|
||||
import FmsModuleListPage from "@/components/fms-module-list/FmsModuleListPage.vue";
|
||||
import FmsTree from "@/components/FmsTree.vue";
|
||||
import { loadDataApi, nextIdApi, pageDataApi, saveObjectApi } from "@/services/api";
|
||||
@@ -32,9 +32,28 @@ const categoryById = computed(
|
||||
);
|
||||
const tableKey = computed(() => selectedModuleCode.value);
|
||||
const shouldLoadData = computed(() => Boolean(selectedModuleCode.value));
|
||||
|
||||
// 编辑表格:当前模块列表实例、选中行、保存/删除状态
|
||||
const moduleListRef = ref(null);
|
||||
const selectedRowKeys = ref([]);
|
||||
const editableSaving = ref(false);
|
||||
const dirtyCount = ref(0);
|
||||
|
||||
const rowSelection = computed(() => ({
|
||||
selectedRowKeys: selectedRowKeys.value,
|
||||
onChange: (keys) => {
|
||||
selectedRowKeys.value = keys;
|
||||
},
|
||||
}));
|
||||
const selectedCategoryKeys = computed(() =>
|
||||
selectedCategoryKey.value ? [selectedCategoryKey.value] : [],
|
||||
);
|
||||
|
||||
// 切换数据模块时清空编辑状态,避免残留脏标记与选中项。
|
||||
watch(selectedModuleCode, () => {
|
||||
selectedRowKeys.value = [];
|
||||
dirtyCount.value = 0;
|
||||
});
|
||||
const modalTitle = computed(() => {
|
||||
if (editingCategoryId.value) return modalType.value === "node" ? "修改节点" : "修改分类";
|
||||
return modalType.value === "node" ? "添加节点" : "添加分类";
|
||||
@@ -82,7 +101,7 @@ function buildCategoryTreeNode(item) {
|
||||
const module = moduleByCode.value.get(String(moduleCode));
|
||||
title = appStore.t(module?.b_i18n, module?.b_name || item.b_name || moduleCode);
|
||||
} else {
|
||||
title = appStore.t(item.b_i18n, item.b_name);
|
||||
title = item.b_name;
|
||||
}
|
||||
if (Number(item.b_canuse) !== 1) {
|
||||
title = `${title}(${appStore.t("common.disabled", "停用")})`;
|
||||
@@ -92,7 +111,6 @@ function buildCategoryTreeNode(item) {
|
||||
title,
|
||||
b_id: String(item.b_id),
|
||||
b_parent_id: item.b_parent_id == null ? null : String(item.b_parent_id),
|
||||
b_i18n: item.b_i18n || "",
|
||||
b_node_type: nodeType,
|
||||
b_module_code: moduleCode,
|
||||
b_xh: item.b_xh,
|
||||
@@ -108,10 +126,6 @@ function getNodeType(item) {
|
||||
return "category";
|
||||
}
|
||||
|
||||
function buildCategoryI18nKey(id) {
|
||||
return `category.base_otherdata.${id}`;
|
||||
}
|
||||
|
||||
function updateSelectedModule(key) {
|
||||
selectedCategoryKey.value = key;
|
||||
|
||||
@@ -280,7 +294,7 @@ function openAddModal(node, type) {
|
||||
modalParentId.value = node?.isFmsRoot ? null : String(node?.b_id || node?.key || "");
|
||||
modalParentName.value = node?.isFmsRoot ? "" : node?.title || "";
|
||||
form.b_name = "";
|
||||
form.b_module_code = "";
|
||||
form.b_module_code = "";
|
||||
modalVisible.value = true;
|
||||
}
|
||||
|
||||
@@ -300,6 +314,7 @@ function openEditModal(node) {
|
||||
modalParentName.value = parentId ? categoryById.value.get(parentId)?.b_name || "" : "";
|
||||
form.b_name = category.b_name || "";
|
||||
form.b_module_code = category.b_module_code || "";
|
||||
|
||||
modalVisible.value = true;
|
||||
}
|
||||
|
||||
@@ -320,7 +335,6 @@ function buildNewCategory(id, name, moduleCode, nodeType) {
|
||||
b_id: id,
|
||||
b_parent_id: parentId || null,
|
||||
b_name: name,
|
||||
b_i18n: nodeType === "category" ? buildCategoryI18nKey(id) : null,
|
||||
b_node_type: nodeType,
|
||||
b_xh: nextSort(parentId),
|
||||
b_canuse: 1,
|
||||
@@ -364,7 +378,7 @@ async function saveCategory() {
|
||||
saving.value = true;
|
||||
try {
|
||||
if (editingCategoryId.value) {
|
||||
await saveObjectApi([
|
||||
const saves = [
|
||||
{
|
||||
table: "b_other_bmfl",
|
||||
key_field: "b_id",
|
||||
@@ -372,24 +386,25 @@ async function saveCategory() {
|
||||
{
|
||||
b_id: editingCategoryId.value,
|
||||
b_name: name,
|
||||
b_i18n:
|
||||
nodeType === "category" ? buildCategoryI18nKey(editingCategoryId.value) : null,
|
||||
b_node_type: nodeType,
|
||||
b_module_code: moduleCode,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
];
|
||||
await saveObjectApi(saves);
|
||||
message.success(isNodeModal.value ? "节点已修改" : "分类已修改");
|
||||
} else {
|
||||
const idRes = await nextIdApi();
|
||||
await saveObjectApi([
|
||||
const newId = String(idRes.data);
|
||||
const saves = [
|
||||
{
|
||||
table: "b_other_bmfl",
|
||||
key_field: "b_id",
|
||||
inserts: [buildNewCategory(String(idRes.data), name, moduleCode, nodeType)],
|
||||
inserts: [buildNewCategory(newId, name, moduleCode, nodeType)],
|
||||
},
|
||||
]);
|
||||
];
|
||||
await saveObjectApi(saves);
|
||||
message.success(isNodeModal.value ? "节点已添加" : "分类已添加");
|
||||
}
|
||||
|
||||
@@ -470,6 +485,50 @@ function confirmDeleteCategory(node) {
|
||||
});
|
||||
}
|
||||
|
||||
// ---- 编辑表格:新增行 / 保存 / 批量删除 ----
|
||||
async function addNewRow() {
|
||||
await moduleListRef.value?.addRow?.();
|
||||
}
|
||||
|
||||
async function saveEditableChanges() {
|
||||
if (editableSaving.value) return;
|
||||
if (dirtyCount.value <= 0) {
|
||||
message.info("没有需要保存的修改");
|
||||
return;
|
||||
}
|
||||
editableSaving.value = true;
|
||||
try {
|
||||
await moduleListRef.value?.saveChanges?.();
|
||||
dirtyCount.value = 0;
|
||||
} finally {
|
||||
editableSaving.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function confirmBatchDelete() {
|
||||
if (!selectedRowKeys.value.length) {
|
||||
message.warning("请先选择要删除的记录");
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: `确定删除选中的 ${selectedRowKeys.value.length} 条记录?`,
|
||||
content: "此操作不可恢复",
|
||||
okText: "删除",
|
||||
cancelText: "取消",
|
||||
okButtonProps: { danger: true },
|
||||
onOk: async () => {
|
||||
editableSaving.value = true;
|
||||
try {
|
||||
await moduleListRef.value?.deleteSelected?.(selectedRowKeys.value);
|
||||
selectedRowKeys.value = [];
|
||||
dirtyCount.value = 0;
|
||||
} finally {
|
||||
editableSaving.value = false;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadCategories();
|
||||
loadDataModules();
|
||||
@@ -502,9 +561,40 @@ onMounted(() => {
|
||||
<main class="data-panel">
|
||||
<FmsModuleListPage
|
||||
v-if="shouldLoadData"
|
||||
ref="moduleListRef"
|
||||
:key="tableKey"
|
||||
:data-code="selectedModuleCode"
|
||||
/>
|
||||
:editable="true"
|
||||
:row-draggable="true"
|
||||
:row-selection="rowSelection"
|
||||
@dirty-change="({ count }) => (dirtyCount = count)"
|
||||
>
|
||||
<template #actions>
|
||||
<a-space>
|
||||
<a-button
|
||||
type="primary"
|
||||
ghost
|
||||
:disabled="!shouldLoadData"
|
||||
@click="addNewRow"
|
||||
>
|
||||
<Plus :size="15" />
|
||||
新增行
|
||||
</a-button>
|
||||
<a-button type="primary" :loading="editableSaving" @click="saveEditableChanges">
|
||||
<Save :size="15" />
|
||||
保存
|
||||
</a-button>
|
||||
<a-button
|
||||
danger
|
||||
:disabled="!selectedRowKeys.length"
|
||||
@click="confirmBatchDelete"
|
||||
>
|
||||
<Trash2 :size="15" />
|
||||
批量删除
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</FmsModuleListPage>
|
||||
<div v-else class="data-empty">
|
||||
<a-empty description="暂无数据" />
|
||||
</div>
|
||||
@@ -537,6 +627,7 @@ onMounted(() => {
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -604,4 +695,5 @@ onMounted(() => {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
</style>
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user