😝优化报表分组,风格与机构分组一致

This commit is contained in:
KaneLeung 2025-07-07 16:30:31 +08:00
parent 625b1318db
commit 3b5d9a99f2

View File

@ -1,47 +1,70 @@
<template>
<div class="group-panel" v-loading="state.isLoading">
<el-button-group class="group-panel-buttonGroup">
<el-button icon="ele-CirclePlus" size="small" @click="createFormShow">{{ $t('新增分组') }}</el-button>
<el-dropdown split-button @command="handleCommand" size="small" :icon="Delete" @click="editFormShow">
{{ $t('编辑分组') }}
<template v-slot:dropdown>
<el-dropdown-menu>
<el-dropdown-item command="del" :icon="Delete">{{ $t('删除分组') }}</el-dropdown-item>
<el-dropdown-item command="refresh" :icon="RefreshRight">{{ $t('刷新分组') }}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-button-group>
<el-card :loading="true" class="group-panel-tree" shadow="never">
<el-card class="box-card" shadow="hover" body-style="height:100%;overflow:auto;padding:5px;width:100%;" v-loading="state.isLoading">
<template #header>
<div class="card-header">
<div class="tree-h-flex">
<div class="tree-h-left">
<el-input :prefix-icon="Search" v-model.lazy="filterText" clearable :placeholder="$t('查询')" />
</div>
<div class="tree-h-right">
<el-dropdown @command="handleCommand">
<el-button style="margin-left: 8px; width: 34px">
<el-icon class="el-icon--center">
<more-filled />
</el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="expandAll">{{ $t('message.list.allExpand') }}</el-dropdown-item>
<el-dropdown-item command="collapseAll">{{ $t('message.list.allFold') }}</el-dropdown-item>
<el-dropdown-item command="create">{{ $t('新增分组') }}</el-dropdown-item>
<el-dropdown-item command="edit">{{ $t('编辑分组') }}</el-dropdown-item>
<el-dropdown-item command="delete">{{ $t('删除分组') }}</el-dropdown-item>
<el-dropdown-item command="refresh">{{ $t('message.list.refresh') }}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</div>
</template>
<div style="margin-bottom: 45px" v-loading="state.loading">
<el-scrollbar>
<div v-if="state.groupTree">
<el-tree
ref="groupTree"
:data="state.groupTree"
:props="state.defaultProps"
:default-expand-all="true"
:expand-on-click-node="false"
:highlight-current="true"
@node-click="(group: SysReportGroup) => emit('nodeClick', group)"
/>
</div>
<div v-else>
<el-empty />
</div>
<el-tree
v-if="state.treeData"
ref="treeRef"
class="filter-tree"
:data="state.treeData"
node-key="id"
:props="{ children: 'children', label: 'label' }"
:filter-node-method="filterNode"
@node-click="(group: SysReportGroup) => emit('nodeClick', group)"
:default-expanded-keys="state.treeData[0] && [state.treeData[0].id]"
highlight-current
>
<template #default="{ node }">
<el-icon v-if="node.level == 1" size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-School /></el-icon>
<el-icon v-else-if="node.level == 2" size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-Refrigerator /></el-icon>
<el-icon v-else size="16" style="margin-right: 3px; display: inline; vertical-align: middle"><ele-CollectionTag /></el-icon>
<highLightKeyword v-if="filterText" :text="node.label" :keyword="filterText" />
<span v-else>{{ node.label }}</span>
</template>
</el-tree>
<el-empty v-else :image-size="100" />
</el-scrollbar>
</el-card>
<EditReportGroup ref="editReportGroup" :title="state.title" @handleQuery="handleQuery"></EditReportGroup>
</div>
</div>
</el-card>
<EditReportGroup ref="editReportGroup" :title="state.title" @handleQuery="fetchTreeData"></EditReportGroup>
</template>
<script setup lang="ts" name="sysReportGroup">
import { onMounted, reactive, ref } from 'vue';
import { onMounted, reactive, ref, watch } from 'vue';
import { ElMessage, ElMessageBox, ElTree } from 'element-plus';
import { Delete, RefreshRight } from '@element-plus/icons-vue';
import { Search, Delete, RefreshRight, MoreFilled } from '@element-plus/icons-vue';
import { useI18n } from 'vue-i18n';
import EditReportGroup from './editReportGroup.vue';
import highLightKeyword from '/@/components/highLightKeyword/index.vue';
import { getAPI } from '/@/utils/axios-utils';
import { SysReportGroup, SysReportGroupApi } from '/@/api-services';
@ -51,25 +74,23 @@ const { t } = useI18n();
// /
const emit = defineEmits(['nodeClick']);
const groupTree = ref<InstanceType<typeof ElTree>>();
const treeRef = ref<InstanceType<typeof ElTree>>();
const editReportGroup = ref<InstanceType<typeof EditReportGroup>>();
const filterText = ref('');
const state = reactive({
/** 是否加载中 */
isLoading: false,
isLoading: false, //
title: '',
groupTree: [],
defaultProps: {
children: 'children',
label: 'label',
},
treeData: [],
});
//
onMounted(() => {
getGroupTree();
fetchTreeData();
});
const getGroupTree = () => {
//
const fetchTreeData = () => {
state.isLoading = true;
getAPI(SysReportGroupApi)
.apiSysReportGroupListGet()
@ -77,13 +98,14 @@ const getGroupTree = () => {
getTree(res.data.result ?? []);
let rootGroup = [{ id: 0, label: t('全部'), value: 0, children: [] }];
rootGroup[0].children = res.data.result as [];
state.groupTree = rootGroup as [];
state.treeData = rootGroup as [];
})
.finally(() => {
state.isLoading = false;
});
};
//
const getTree = (tree: SysReportGroup[]): [] => {
tree.forEach((r: any) => {
r.label = `${r.number}[${r.name}]`;
@ -92,85 +114,90 @@ const getTree = (tree: SysReportGroup[]): [] => {
return [];
};
const handleCommand = (cmd: string) => {
switch (cmd) {
//
case 'refresh':
getGroupTree();
break;
//
watch(filterText, (val) => {
treeRef.value!.filter(val);
});
//
const filterNode = (value: string, data: any) => {
if (!value) return true;
return data.label.includes(value);
};
//
const handleCommand = async (command: string | number | object) => {
if ('expandAll' == command) {
//
for (let i = 0; i < treeRef.value!.store._getAllNodes().length; i++) {
treeRef.value!.store._getAllNodes()[i].expanded = true;
}
} else if ('collapseAll' == command) {
//
for (let i = 0; i < treeRef.value!.store._getAllNodes().length; i++) {
treeRef.value!.store._getAllNodes()[i].expanded = false;
}
} else if ('create' == command) {
//
state.title = t('新增分组');
editReportGroup.value?.openDialog({});
} else if ('edit' == command) {
//
const currData = treeRef.value!.getCurrentNode();
if (!currData) {
ElMessage.error(t('请选择分组后编辑'));
return;
}
if (currData.id == 0) {
ElMessage.error(t('请选择有效的分组节点'));
return;
}
state.title = t('编辑分组');
editReportGroup.value?.openDialog(currData);
} else if ('delete' == command) {
//
case 'del':
const currData = groupTree.value!.getCurrentNode();
if (currData) {
reportGroupDelete(currData.id, currData.label);
}
break;
const currData = treeRef.value!.getCurrentNode();
if (currData.id == 0) {
ElMessage.error(t('请选择有效的分组节点'));
return;
}
ElMessageBox.confirm(t('确认删除?', { label: currData.label }), t('提示'), {
confirmButtonText: t('确定'),
cancelButtonText: t('取消'),
type: 'warning',
}).then(() => {
getAPI(SysReportGroupApi)
.apiSysReportGroupDeletePost({ id: recordId })
.then((res) => {
ElMessage.success(t('删除成功'));
fetchTreeData();
});
});
} else if ('refresh' == command) {
//
fetchTreeData();
}
};
const createFormShow = () => {
state.title = t('新增分组');
editReportGroup.value?.openDialog({});
};
const editFormShow = () => {
const currData = groupTree.value!.getCurrentNode();
if (!currData) {
ElMessage.error(t('请选择分组后编辑'));
return;
}
if (currData.id == 0) {
ElMessage.error(t('请选择有效的分组节点'));
return;
}
state.title = t('编辑分组');
editReportGroup.value?.openDialog(currData);
};
const reportGroupDelete = (recordId: number, label: string) => {
if (recordId == 0) {
ElMessage.error(t('请选择有效的分组节点'));
return;
}
ElMessageBox.confirm(t('确认删除?', { label: label }), t('提示'), {
confirmButtonText: t('确定'),
cancelButtonText: t('取消'),
type: 'warning',
}).then(() => {
getAPI(SysReportGroupApi)
.apiSysReportGroupDeletePost({ id: recordId })
.then((res) => {
ElMessage.success(t('删除成功'));
getGroupTree();
});
});
};
const handleQuery = () => {
getGroupTree();
};
</script>
<style scoped lang="scss">
.group-panel {
background-color: var(--el-fill-color-blank);
display: flex;
flex-direction: column;
height: 100%;
.group-panel-buttonGroup {
width: 100%;
padding: 5px 0 10px 0;
}
.group-panel-tree {
flex: 1;
:deep(.el-card__body) {
padding: 0px;
height: 100%;
}
.box-card {
flex: 1;
> :deep(.el-card__header) {
padding: 5px;
}
}
.tree-h-flex {
display: flex;
}
.tree-h-left {
flex: 1;
width: 100%;
}
.tree-h-right {
width: 42px;
min-width: 42px;
}
</style>