Merge branch 'ga-2025-07' into 'dev'

feat: 组织搜索模糊搜索添加

See merge request itc-framework/ma/2024/front!93
This commit is contained in:
890147
2025-07-18 07:16:38 +00:00
3 changed files with 98 additions and 17 deletions

View File

@ -13,6 +13,7 @@ enum Api {
Page = '/organization/department/page', Page = '/organization/department/page',
Tree = '/organization/department/tree', Tree = '/organization/department/tree',
Trees = '/organization/department/trees', Trees = '/organization/department/trees',
queryDeptTrees = '/organization/department/queryDeptTrees',
EnabledTree = '/organization/department/enabled-tree', EnabledTree = '/organization/department/enabled-tree',
Info = '/organization/department/info', Info = '/organization/department/info',
Department = '/organization/department', Department = '/organization/department',
@ -54,6 +55,24 @@ export async function getDepartmentTrees(
}, },
); );
} }
/**
* @description: 查询部门树(新,名称查询返回树)
*/
export async function getQueryDeptTrees(
params?: any,
mode: ErrorMessageMode = 'modal',
) {
return defHttp.get<DepartmentTreeModel>(
{
url: Api.queryDeptTrees,
params,
},
{
errorMessageMode: mode,
},
);
}
/** /**
* @description: 查询部门树 * @description: 查询部门树

View File

@ -1,19 +1,29 @@
<template> <template>
<div class="tree-box">
<a-input-search
:bordered="false"
class="search-input"
placeholder="请输入组织名称搜索"
v-model:value="params.name"
allowClear
@search="searchDepart">
</a-input-search>
<div class="select-department-tree"> <div class="select-department-tree">
<a-tree v-model:expandedKeys="expandedKeys" v-model:selectedKeys="selectedKeys" v-model:checkedKeys="checkedKeys" <a-tree v-model:expandedKeys="expandedKeys" v-model:selectedKeys="selectedKeys" v-model:checkedKeys="checkedKeys"
:selectable="props.selectable" :multiple="props.multiple" v-model:checkable="checkable" :selectable="props.selectable" :multiple="props.multiple" v-model:checkable="checkable"
v-model:tree-data="treeData" :load-data="loadData" @select="selectData"> v-model:tree-data="treeData" :load-data="loadData" @select="selectData">
<template #title="{ title, key }"> <template #title="{ title, key }">
<span v-if="key === '0-0-1-0'" style="color: #1890ff">{{ title }}</span> <span v-html="highLightSearch(title)"></span>
<template v-else>{{ title }}</template> <!-- <span v-if="key === '0-0-1-0'" style="color: #1890ff">{{key}}{{ title }}</span>
<template v-else>{{ title }}</template> -->
</template> </template>
</a-tree> </a-tree>
</div> </div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, watch, onMounted } from 'vue'; import { ref, watch, onMounted } from 'vue';
import { getDepartmentTrees } from '/@/api/system/department'; import { getDepartmentTrees, getQueryDeptTrees } from '/@/api/system/department';
import { useUserStore } from '/@/store/modules/user'; import { useUserStore } from '/@/store/modules/user';
const props = defineProps({ const props = defineProps({
multiple: { multiple: {
@ -62,6 +72,17 @@ const params = ref({
onMounted(() => { onMounted(() => {
getList() getList()
}) })
const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const highLightSearch = (title) => {
const keyword = params.value.name;
if (!keyword) return title;
const escapedKeyword = escapeRegExp(keyword);
const reg = new RegExp(escapedKeyword, 'g');
return title.replace(reg, `<span class="highlight">${keyword}</span>`);
}
const loadData = (node) => { const loadData = (node) => {
return new Promise(async (resolve: (value?: unknown) => void) => { return new Promise(async (resolve: (value?: unknown) => void) => {
if (node.dataRef.children.length) { if (node.dataRef.children.length) {
@ -76,27 +97,36 @@ const loadData = (node) => {
excludeDeptTypes: props.justCompany ? '0' : '', excludeDeptTypes: props.justCompany ? '0' : '',
ids: props.defaultDepts ids: props.defaultDepts
} }
let list = resetTreeList(await getDepartmentTrees(param)) let list = resetTreeList(await getQueryDeptTrees(param))
node.dataRef.children = list[0].children node.dataRef.children = list[0].children
treeData.value = [...treeData.value]; treeData.value = [...treeData.value];
resolve(); resolve();
}); });
} }
async function getList() { function searchDepart() {
getList('search')
}
async function getList(type = 'default') {
if (props.parentNode) { if (props.parentNode) {
params.value.id = props.parentNode params.value.id = props.parentNode
} }
let list = resetTreeList(await getDepartmentTrees(params.value)) let list = resetTreeList(await getQueryDeptTrees(params.value), type, true)
treeData.value = list treeData.value = list
emit('query-completed'); emit('query-completed');
} }
function resetTreeList(list) { function resetTreeList(list, type='default', isFirst = false) {
if(type == 'search' && isFirst) {
expandedKeys.value = []
}
const result = list.map(item => { const result = list.map(item => {
if(type == 'search' && item.children && item.children.length) {
expandedKeys.value.push(item.id)
}
return { return {
...item, ...item,
...{ ...{
key: item.id, key: item.id,
children: resetTreeList(item.children), children: resetTreeList(item.children, type),
title: item.name title: item.name
} }
} }
@ -126,3 +156,30 @@ watch(
} }
); );
</script> </script>
<style lang="less" scoped>
.search-input{
padding: 4px 8px;
:deep(.ant-input-group-addon) {
.ant-btn {
border: none!important;
box-shadow: none!important;
}
}
}
:deep(.highlight) {
color: orange;
font-weight: bold;
background-color: #fff2e8;
}
.tree-box {
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
.select-department-tree {
flex: 1;
overflow: scroll;
}
}
</style>

View File

@ -175,6 +175,9 @@
} }
function show() { function show() {
if (props.disabled) {
return;
}
visible.value = true; visible.value = true;
loading.value = true; loading.value = true;
if(props.defaultDeptField) { if(props.defaultDeptField) {
@ -234,7 +237,9 @@
width: 60%; width: 60%;
height: 100%; height: 100%;
position: relative; position: relative;
overflow: scroll; // overflow: scroll;
display: flex;
flex-direction: column;
.loading-box { .loading-box {
position: absolute; position: absolute;