Browse Source

组件优化

main
likunming 2 months ago
parent
commit
810798ac46
  1. 10
      io.sc.platform.core.frontend/src/platform/components/grid/TreeGridFirstTdContent.vue
  2. 8
      io.sc.platform.core.frontend/src/platform/components/grid/css/grid.css
  3. 79
      io.sc.platform.core.frontend/src/platform/components/select/WOrgSelect.vue
  4. 13
      io.sc.platform.core.frontend/src/platform/components/select/WRoleSelect.vue
  5. 278
      io.sc.platform.core.frontend/src/platform/components/select/WUserSelect.vue
  6. 4
      io.sc.platform.core.frontend/src/platform/components/toolbar/WToolbar.vue
  7. 21
      io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/controller/OrgSearchController.java
  8. 11
      io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/controller/UserSearchController.java
  9. 10
      io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/service/OrgSearchService.java
  10. 4
      io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/service/UserSearchService.java
  11. 147
      io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/service/impl/OrgSearchServiceImpl.java
  12. 202
      io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/service/impl/UserSearchServiceImpl.java
  13. 39
      io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/support/UserSearchConstant.java

10
io.sc.platform.core.frontend/src/platform/components/grid/TreeGridFirstTdContent.vue

@ -1,7 +1,7 @@
<template>
<div class="flex flex-nowrap items-center h-full w-full treeGridFirstTd" style="flex-wrap: nowrap">
<!--层级占位符-->
<span :style="`width:${24 * props.level}px;`"></span>
<span class="flex-shrink-0" :style="`width:${24 * props.level}px;`"></span>
<!--展开按钮-->
<q-btn
v-if="expandableComputed"
@ -10,6 +10,7 @@
padding="0px 0px"
:icon="props.row.expand ? 'bi-dash' : 'bi-plus'"
:loading="lazyloading"
class="flex-shrink-0"
@click.stop="expandFun"
@dblclick.stop="() => {}"
>
@ -18,7 +19,7 @@
</template>
</q-btn>
<!--展开按钮占位符-->
<span v-else style="width: 24px"></span>
<span v-else class="flex-shrink-0" style="width: 24px"></span>
<!--选择框-->
<q-checkbox
v-if="tools.table.configStore.useCheckboxSelection"
@ -26,11 +27,12 @@
flat
dense
:disable="!tools.dataFM.getTreeTickable(props.row)"
class="flex-shrink-0"
@dblclick.stop="() => {}"
@update:model-value="selectedFun(rowDataComputed[tickedField], $event)"
/>
<!-- 图标与显示内容区域 -->
<div class="treeGridIconAndName" @dragover="draggableComputed ? tools.dndFM.iconAndNameDragOver($event, props.row) : () => {}">
<div class="treeGridIconAndName flex-shrink-0" @dragover="draggableComputed ? tools.dndFM.iconAndNameDragOver($event, props.row) : () => {}">
<q-icon v-if="typeof iconComputed === 'string'" :name="iconComputed" size="20px" class="px-1 treeGridIconAndName"></q-icon>
<q-icon v-else-if="typeof iconComputed === 'object'" size="20px" v-bind="iconComputed" class="px-1 treeGridIconAndName"></q-icon>
<span v-else class="px-1 treeGridIconAndName"></span>
@ -38,7 +40,7 @@
<InlineEditComponent :col="props.col" :row="props.row"></InlineEditComponent>
</template>
<template v-else>
<TdContent :value="props.value" class="treeGridIconAndName"></TdContent>
<TdContent :value="props.value" class="treeGridIconAndName flex-shrink-0"></TdContent>
</template>
</div>
</div>

8
io.sc.platform.core.frontend/src/platform/components/grid/css/grid.css

@ -7,6 +7,14 @@
.w-grid .mouseDisabled {
cursor: not-allowed; /* 将鼠标指针变为禁用图标 */
}
.w-grid .q-table {
table-layout: fixed;
}
.w-grid .q-table td {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.w-grid .q-table__top {
padding: var(--tableTopPadding) var(--tableTopPadding);
}

79
io.sc.platform.core.frontend/src/platform/components/select/WOrgSelect.vue

@ -37,7 +37,7 @@
:tree-default-expand-all="props.defaultExpandAll"
:config-button="false"
:toolbar-actions="['expand']"
:query-criteria="props.queryCriteria"
:query-criteria="queryCriteriaRef"
:columns="[
{ name: 'name', label: $t('name'), sortable: false },
{ name: 'code', label: $t('code'), width: 100, sortable: false },
@ -65,7 +65,7 @@
</template>
<script setup lang="ts">
import { ref, computed, useAttrs, toRaw, watch, onMounted } from 'vue';
import { ref, computed, useAttrs, toRaw, watch, onMounted, onBeforeMount } from 'vue';
import { Tools, axios, Environment, Formater } from '@/platform';
import { FormFieldProps } from '@/platform/components/form/FormField.ts';
import { FormFieldMethods } from '../form/FormField';
@ -76,7 +76,7 @@ const modelValue = defineModel<string | Array<string>>();
const modelObjectValue = ref(<any>[]); //
const orgGridRef = ref();
const orgGridFetchDataUrl = Environment.apiContextPath('/api/system/org');
const orgGridFetchDataUrl = Environment.apiContextPath('/api/lcdp/orgSearch/queryOrg');
const isShow = ref(false);
interface FieldProps extends FormFieldProps {
@ -85,6 +85,10 @@ interface FieldProps extends FormFieldProps {
valueUseId?: boolean;
displayValue?: string | ((args: object) => '');
defaultExpandAll?: boolean;
findByDefaultOrg?: boolean;
findByDefaultOrgWithSub?: boolean;
findByOrgId?: string | Array<() => void>;
findByOrgIdWithSub?: string | Array<() => void>;
queryCriteria?: object;
}
const props = withDefaults(defineProps<FieldProps>(), {
@ -111,6 +115,29 @@ const props = withDefaults(defineProps<FieldProps>(), {
* 机构树默认展开所有节点
*/
defaultExpandAll: true,
/**
* 根据当前登录用户的默认机构进行过滤
* --若默认机构为空不出现任何机构
* --为总行的用户可选全部机构
* 机构过滤的属性有5个这些属性无法配合使用只能生效一个
* 优先级如下queryCriteria > findByOrgIdWithSub > findByOrgId > findByDefaultOrgWithSub > findByDefaultOrg
*/
findByDefaultOrg: false,
/**
* 与findByDefaultOrg逻辑一致并包含用户默认机构下的所有子机构
*/
findByDefaultOrgWithSub: false,
/**
* 根据传入的机构ID或机构ID数组进行过滤
*/
findByOrgId: undefined,
/**
* 与findByOrgId逻辑一致并包含其所有子机构
*/
findByOrgIdWithSub: undefined,
/**
* 查询条件
*/
queryCriteria: undefined,
});
class FieldMethods extends FormFieldMethods {
@ -161,6 +188,7 @@ class FieldMethods extends FormFieldMethods {
}
const fieldMethodsClass = new FieldMethods();
const valueUseColumnName = props.valueUseId ? 'id' : 'code';
const queryCriteriaRef = ref({});
const displayValueComputed = computed(() => {
let result = '';
@ -273,6 +301,51 @@ const setObjectValueByValue = async (value) => {
}
};
//
// queryCriteria > findByOrgIdWithSub > findByOrgId > findByDefaultOrgWithSub > findByDefaultOrg
const getOrgCriteria = () => {
if (props.findByOrgIdWithSub) {
return {
fieldName: 'findByOrgIdWithSub',
operator: 'inSet',
value: Array.isArray(props.findByOrgIdWithSub) ? props.findByOrgIdWithSub : [props.findByOrgIdWithSub],
};
} else if (props.findByOrgId) {
return {
fieldName: 'findByOrgId',
operator: 'inSet',
value: Array.isArray(props.findByOrgId) ? props.findByOrgId : [props.findByOrgId],
};
} else if (props.findByDefaultOrgWithSub) {
return {
fieldName: 'findByDefaultOrgWithSub',
operator: 'equals',
value: true,
};
} else if (props.findByDefaultOrg) {
return {
fieldName: 'findByDefaultOrg',
operator: 'equals',
value: true,
};
} else {
return undefined;
}
};
onBeforeMount(() => {
const orgCriteria = getOrgCriteria();
if (props.queryCriteria || orgCriteria) {
queryCriteriaRef.value['operator'] = 'and';
queryCriteriaRef.value['criteria'] = [];
if (props.queryCriteria) {
queryCriteriaRef.value['criteria'].push(props.queryCriteria);
} else if (orgCriteria) {
queryCriteriaRef.value['criteria'].push(orgCriteria);
}
}
});
onMounted(() => {
setObjectValueByValue(modelValue.value);
});

13
io.sc.platform.core.frontend/src/platform/components/select/WRoleSelect.vue

@ -64,6 +64,7 @@
db-click-operation="none"
@row-click="rowClick"
@update-ticked="updateTicked"
@update-tickeds="updateTickeds"
>
</w-grid>
</div>
@ -201,6 +202,18 @@ const getActualDisplayValue = (row) => {
return '';
};
const updateTickeds = (args) => {
if (args.value && Array.isArray(modelValue.value)) {
fieldMethodsClass.clearValue();
const rows = roleGridRef.value.getRows();
rows.forEach((item) => {
modelValue.value.push(item[valueUseColumnName]);
modelObjectValue.value.push({ value: item[valueUseColumnName], displayValue: getActualDisplayValue(item) });
});
} else {
fieldMethodsClass.clearValue();
}
};
const updateTicked = (args) => {
if (Array.isArray(modelValue.value)) {
fieldMethodsClass.clearValue();

278
io.sc.platform.core.frontend/src/platform/components/select/WUserSelect.vue

@ -26,94 +26,81 @@
<q-btn v-if="!Tools.isEmpty(displayValueComputed)" flat square unelevated dense icon="cancel" @click="fieldMethodsClass.clearValue"></q-btn>
<q-btn flat square unelevated dense icon="person_search">
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]">
<q-splitter v-model="leftWidthRef" style="width: 900px; height: 400px; position: relative">
<template #before>
<q-list>
<!-- 机构 -->
<q-expansion-item icon="account_tree" label="机构">
<q-card class="p-0">
<q-card-section class="p-0">
<w-grid
ref="orgGridRef"
:dense="true"
:tree="true"
:height="250"
:hide-header="true"
separator="none"
:fetch-data-url="Environment.apiContextPath('/api/system/org')"
:config-button="false"
:checkbox-selection="true"
db-click-operation="expand"
:columns="[{ name: 'name', label: $t('org') }]"
@row-click="orgRowClick"
@update-ticked="orgUpdateTicked"
>
</w-grid>
</q-card-section>
</q-card>
</q-expansion-item>
<q-separator />
<!-- 角色 -->
<q-expansion-item icon="person" label="角色">
<q-card class="p-0">
<q-card-section class="p-0">
<w-grid
ref="roleGridRef"
:dense="true"
:height="250"
separator="none"
:fetch-data-url="Environment.apiContextPath('/api/system/role')"
:config-button="false"
:checkbox-selection="true"
db-click-operation="expand"
:columns="[
{ name: 'code', label: $t('code') },
{ name: 'name', label: $t('org') },
]"
@row-click="orgRowClick"
>
</w-grid>
</q-card-section>
</q-card>
</q-expansion-item>
<q-separator />
</q-list>
</template>
<template #after>
<div class="h-full pl-1">
<w-grid
ref="userGridRef"
:checkbox-selection="props.multiple || false"
:dense="true"
:fetch-data-url="userGridFetchDataUrl"
:config-button="false"
title="用户列表"
:sort-by="['loginName']"
:query-form-cols-num="2"
:query-form-fields="[
{ name: 'loginName', label: $t('loginName'), type: 'w-text' },
{ name: 'userName', label: $t('userName'), type: 'w-text' },
]"
:toolbar-actions="['query', 'separator', 'reset']"
:ticked-record="{
columnName: valueUseColumnName,
data: typeof modelValue === 'string' ? [modelValue] : modelValue,
}"
:columns="[
{ name: 'loginName', label: $t('loginName') },
{ name: 'userName', label: $t('userName') },
{ name: 'description', label: $t('description') },
{ name: 'enable', label: $t('status'), format: Formater.enableTag() },
]"
@row-click="userRowClick"
@update-ticked="updateTicked"
@update-tickeds="updateTickeds"
>
</w-grid>
</div>
</template>
</q-splitter>
<div style="width: 750px; height: 350px">
<w-grid
ref="userGridRef"
:checkbox-selection="props.multiple || false"
:dense="true"
:fetch-data-url="userGridFetchDataUrl"
:config-button="false"
title="用户列表"
:sort-by="['loginName']"
:query-form-cols-num="4"
:query-form-row-num="1"
:toolbar-actions="['query', 'separator', 'reset']"
:query-criteria="queryCriteriaRef"
:query-form-fields="[
{ name: 'loginName', label: $t('loginName'), type: 'w-text' },
{ name: 'userName', label: $t('userName'), type: 'w-text' },
{
name: 'orgs',
label: '所属机构',
type: 'w-org-select',
multiple: true,
autogrow: false,
queryCriteria: props.orgQueryCriteria,
findByDefaultOrg: props.findByDefaultOrg,
findByDefaultOrgWithSub: props.findByDefaultOrgWithSub,
findByOrgId: props.findByOrgId,
findByOrgIdWithSub: props.findByOrgIdWithSub,
},
{ name: 'roles', label: '所属角色', type: 'w-role-select', multiple: true, autogrow: false, queryCriteria: props.roleQueryCriteria },
]"
:ticked-record="{
columnName: valueUseColumnName,
data: typeof modelValue === 'string' ? [modelValue] : modelValue,
}"
:columns="[
{ name: 'loginName', label: $t('loginName'), width: 100 },
{ name: 'userName', label: $t('userName'), width: 100 },
{ name: 'enable', label: $t('status'), format: Formater.enableTag(), width: 80 },
{
name: 'orgs',
label: '已配置机构',
sortable: false,
width: 150,
format: (val) => {
if (val) {
return val
.map((item) => item['name'])
.filter(Boolean)
.join(',');
}
return '';
},
},
{
name: 'roles',
label: '已配置角色',
width: '100%',
sortable: false,
format: (val) => {
if (val) {
return val
.map((item) => item['name'])
.filter(Boolean)
.join(',');
}
return '';
},
},
]"
@row-click="userRowClick"
@update-ticked="updateTicked"
@update-tickeds="updateTickeds"
>
</w-grid>
</div>
</q-popup-proxy>
</q-btn>
</template>
@ -125,8 +112,8 @@
</template>
<script setup lang="ts">
import { ref, computed, useAttrs, toRaw, watch, onMounted } from 'vue';
import { Tools, axios, Environment, Formater, $t } from '@/platform';
import { ref, reactive, computed, useAttrs, toRaw, watch, onMounted, onBeforeMount } from 'vue';
import { Tools, axios, Environment, Formater, $t, SessionManager } from '@/platform';
import { FormFieldProps } from '@/platform/components/form/FormField.ts';
import { FormFieldMethods } from '../form/FormField';
@ -134,13 +121,9 @@ const textSelectRef = ref();
const attrs = useAttrs();
const modelValue = defineModel<string | Array<string>>();
const modelObjectValue = ref(<any>[]); //
const orgGridRef = ref();
const roleGridRef = ref();
const userGridRef = ref();
const userGridFetchDataUrl = Environment.apiContextPath('/api/system/user');
const userGridFetchDataByOrgUrl = Environment.apiContextPath('/api/system/user/queryUsersByOrgAndQueryParameter');
const leftWidthRef = ref(30);
const userGridFetchDataUrl = Environment.apiContextPath('/api/lcdp/userSearch/queryUser');
const isShow = ref(false);
interface FieldProps extends FormFieldProps {
@ -148,6 +131,13 @@ interface FieldProps extends FormFieldProps {
counter?: boolean;
valueUseId?: boolean;
displayValue?: string | ((args: object) => '');
findByDefaultOrg?: boolean;
findByDefaultOrgWithSub?: boolean;
findByOrgId?: string | Array<() => void>;
findByOrgIdWithSub?: string | Array<() => void>;
queryCriteria?: object;
orgQueryCriteria?: object;
roleQueryCriteria?: object;
}
const props = withDefaults(defineProps<FieldProps>(), {
showIf: true,
@ -169,6 +159,29 @@ const props = withDefaults(defineProps<FieldProps>(), {
* }
*/
displayValue: 'nameAppendCode',
/**
* 可选用户根据当前登录用户的默认机构进行过滤
* --若默认机构为空无法选择用户
* --为总行的用户可选全部用户
* 根据机构过滤的属性有5个这些属性无法配合使用只能生效一个
* 优先级如下orgQueryCriteria > findByOrgIdWithSub > findByOrgId > findByDefaultOrgWithSub > findByDefaultOrg
*/
findByDefaultOrg: false,
/**
* 与findByDefaultOrg逻辑一致并包含用户默认机构下的所有子机构
*/
findByDefaultOrgWithSub: false,
/**
* 可选用户根据传入的机构ID或机构ID数组进行过滤
*/
findByOrgId: undefined,
/**
* 与findByOrgId逻辑一致并包含其所有子机构
*/
findByOrgIdWithSub: undefined,
queryCriteria: undefined, //
orgQueryCriteria: undefined, //
roleQueryCriteria: undefined, //
});
class FieldMethods extends FormFieldMethods {
updateValue = (value_) => {
@ -218,6 +231,7 @@ class FieldMethods extends FormFieldMethods {
}
const fieldMethodsClass = new FieldMethods();
const valueUseColumnName = props.valueUseId ? 'id' : 'loginName';
const queryCriteriaRef = ref({});
const displayValueComputed = computed(() => {
let result = '';
@ -234,7 +248,6 @@ const getActualDisplayValue = (row) => {
if (!Tools.isEmpty(props.displayValue) && typeof props.displayValue === 'function') {
return props.displayValue({
data: toRaw(row),
orgGrid: orgGridRef.value,
userGrid: userGridRef.value,
});
} else if (!Tools.isEmpty(props.displayValue) && typeof props.displayValue === 'string') {
@ -294,14 +307,6 @@ const userRowClick = (args) => {
}
isShow.value = false;
};
const orgRowClick = (args) => {
userGridRef.value.setFetchDataUrl(userGridFetchDataByOrgUrl + '?orgId=' + args.row['id']);
userGridRef.value.refresh();
console.info('orgRowClick======================');
};
const orgUpdateTicked = (args) => {
console.info('orgUpdateTicked======================');
};
watch(
() => modelValue.value,
@ -309,7 +314,7 @@ watch(
if (newVal !== oldVal) {
fieldMethodsClass.updateValue(newVal);
}
if (Tools.isEmpty(newVal)) {
if (Tools.isEmpty(newVal) || (Array.isArray(modelValue.value) && modelValue.value.length === 0)) {
fieldMethodsClass.clearObjectValue();
} else if (newVal !== oldVal) {
if (modelObjectValue.value.length > 0) {
@ -355,6 +360,69 @@ const setObjectValueByValue = async (value) => {
}
};
//
// orgQueryCriteria > findByOrgIdWithSub > findByOrgId > findByDefaultOrgWithSub > findByDefaultOrg
const getOrgCriteria = () => {
if (props.orgQueryCriteria) {
return {
fieldName: 'orgCriteria',
operator: 'equals',
value: JSON.stringify(props.orgQueryCriteria),
};
} else if (props.findByOrgIdWithSub) {
return {
fieldName: 'findByOrgIdWithSub',
operator: 'inSet',
value: Array.isArray(props.findByOrgIdWithSub) ? props.findByOrgIdWithSub : [props.findByOrgIdWithSub],
};
} else if (props.findByOrgId) {
return {
fieldName: 'findByOrgId',
operator: 'inSet',
value: Array.isArray(props.findByOrgId) ? props.findByOrgId : [props.findByOrgId],
};
} else if (props.findByDefaultOrgWithSub) {
return {
fieldName: 'findByDefaultOrgWithSub',
operator: 'equals',
value: true,
};
} else if (props.findByDefaultOrg) {
return {
fieldName: 'findByDefaultOrg',
operator: 'equals',
value: true,
};
} else {
return undefined;
}
};
/**
* 挂载前根据orgCriteria与roleCriteria重新使用and操作构建用户列表的queryCriteria
* 后台再根据用户查询条件+机构查询条件+角色查询条件过滤可选用户
*/
onBeforeMount(async () => {
const orgCriteria = getOrgCriteria();
if (props.queryCriteria || orgCriteria || props.roleQueryCriteria) {
queryCriteriaRef.value['operator'] = 'and';
queryCriteriaRef.value['criteria'] = [];
if (props.queryCriteria) {
queryCriteriaRef.value['criteria'].push(props.queryCriteria);
}
if (orgCriteria) {
queryCriteriaRef.value['criteria'].push(orgCriteria);
}
if (props.roleQueryCriteria) {
queryCriteriaRef.value['criteria'].push({
fieldName: 'roleCriteria',
operator: 'equals',
value: JSON.stringify(props.roleQueryCriteria),
});
}
}
});
onMounted(() => {
setObjectValueByValue(modelValue.value);
});

4
io.sc.platform.core.frontend/src/platform/components/toolbar/WToolbar.vue

@ -63,8 +63,8 @@ const calcButtonWidth = () => {
const buildButtons = () => {
baseButtons.value.splice(0);
moreButtons.value = [];
//
let availableWidth = containerRef.value.clientWidth;
// (52)
let availableWidth = containerRef.value.clientWidth - 5;
//
const buttonsWidth = toolbar.buttons.reduce((width, button) => width + button.width + props.xGap, 0);
if (buttonsWidth > availableWidth) {

21
io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/controller/OrgSearchController.java

@ -0,0 +1,21 @@
package io.sc.platform.lcdp.frontend.component.controller;
import io.sc.platform.lcdp.frontend.component.service.OrgSearchService;
import io.sc.platform.orm.service.support.QueryParameter;
import io.sc.platform.system.api.org.OrgVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController("io.sc.platform.lcdp.frontend.component.controller.OrgSearchController")
@RequestMapping("/api/lcdp/orgSearch")
public class OrgSearchController {
@Autowired private OrgSearchService service;
@GetMapping("queryOrg")
public Page<OrgVo> queryOrg(QueryParameter queryParameter) throws Exception {
return service.queryOrg(queryParameter);
}
}

11
io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/controller/UserSearchController.java

@ -1,12 +1,11 @@
package io.sc.platform.lcdp.frontend.component.controller;
import io.sc.platform.lcdp.frontend.component.service.UserSearchService;
import io.sc.platform.lcdp.frontend.component.support.UserSearchQueryParameter;
import io.sc.platform.lcdp.frontend.component.vo.UserSearchVo;
import io.sc.platform.orm.service.support.QueryParameter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -15,8 +14,8 @@ import org.springframework.web.bind.annotation.RestController;
public class UserSearchController {
@Autowired private UserSearchService service;
@PostMapping("queryUser")
public Page<UserSearchVo> queryUser(@RequestBody UserSearchQueryParameter userSearchQueryParameter) throws Exception {
return service.queryUser(userSearchQueryParameter);
@GetMapping("queryUser")
public Page<UserSearchVo> queryUser(QueryParameter queryParameter) throws Exception {
return service.queryUser(queryParameter);
}
}

10
io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/service/OrgSearchService.java

@ -0,0 +1,10 @@
package io.sc.platform.lcdp.frontend.component.service;
import io.sc.platform.orm.service.support.QueryParameter;
import io.sc.platform.system.api.org.OrgVo;
import org.springframework.data.domain.Page;
public interface OrgSearchService {
Page<OrgVo> queryOrg(QueryParameter queryParameter) throws Exception;
}

4
io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/service/UserSearchService.java

@ -1,10 +1,10 @@
package io.sc.platform.lcdp.frontend.component.service;
import io.sc.platform.lcdp.frontend.component.support.UserSearchQueryParameter;
import io.sc.platform.lcdp.frontend.component.vo.UserSearchVo;
import io.sc.platform.orm.service.support.QueryParameter;
import org.springframework.data.domain.Page;
public interface UserSearchService {
Page<UserSearchVo> queryUser(UserSearchQueryParameter userSearchQueryParameter) throws Exception;
Page<UserSearchVo> queryUser(QueryParameter queryParameter) throws Exception;
}

147
io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/service/impl/OrgSearchServiceImpl.java

@ -0,0 +1,147 @@
package io.sc.platform.lcdp.frontend.component.service.impl;
import io.sc.platform.lcdp.frontend.component.service.OrgSearchService;
import io.sc.platform.lcdp.frontend.component.service.UserSearchService;
import io.sc.platform.lcdp.frontend.component.support.UserSearchConstant;
import io.sc.platform.lcdp.frontend.component.vo.UserSearchVo;
import io.sc.platform.orm.service.support.OperatorType;
import io.sc.platform.orm.service.support.QueryParameter;
import io.sc.platform.orm.service.support.criteria.Criteria;
import io.sc.platform.orm.service.support.criteria.impl.Equals;
import io.sc.platform.orm.service.support.criteria.impl.InSet;
import io.sc.platform.orm.util.EntityVoUtil;
import io.sc.platform.security.util.SecurityUtil;
import io.sc.platform.system.api.org.OrgVo;
import io.sc.platform.system.department.jpa.entity.DepartmentEntity;
import io.sc.platform.system.org.jpa.entity.OrgEntity;
import io.sc.platform.system.org.service.OrgService;
import io.sc.platform.system.role.jpa.entity.RoleEntity;
import io.sc.platform.system.role.service.RoleService;
import io.sc.platform.system.user.jpa.entity.UserEntity;
import io.sc.platform.system.user.service.UserService;
import io.sc.platform.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class OrgSearchServiceImpl implements OrgSearchService {
@Autowired
private OrgService orgService;
@Autowired
private UserSearchServiceImpl userSearchServiceImpl;
@Override
public Page<OrgVo> queryOrg(QueryParameter queryParameter) throws Exception {
if (existCondition(queryParameter)) {
return existConditionQuery(queryParameter);
} else {
return noConditionQuery(queryParameter);
}
}
private Page<OrgVo> existConditionQuery(QueryParameter queryParameter) throws Exception {
List<Criteria> orgCriteriaList = new ArrayList<>();
/**
* 前端已将 queryCriteria使用用户默认机构查询等重新使用 and 操作进行组装后端需提取特定 criteria 出来进行处理
* 只要存在查询条件最外层一定是 { fieldName: null, operator: 'and', criteria: [...] }
* 所以最外层无需处理直接处理最外层的 criteria 数组
*/
List<Criteria> criterias = queryParameter.getCriterias().get(0).getCriteria();
for (Criteria criteria: criterias) {
if (criteria.getFieldName()!=null) {
Boolean isOrgCriteria = Arrays.stream(UserSearchConstant.ORG_CRITERIA_FIELD_NAMES).anyMatch(criteria.getFieldName()::equals);
if (!isOrgCriteria) {
orgCriteriaList.add(criteria);
} else {
// 当 criteria 中的 fieldName 为特定字段名时,进行特殊处理
orgHandler(criteria.getFieldName(), criteria, orgCriteriaList);
}
} else {
orgCriteriaList.add(criteria);
}
}
QueryParameter newQueryParameter = userSearchServiceImpl.rebuildQueryParameter(queryParameter, orgCriteriaList);
Page<OrgEntity> page = orgService.query(newQueryParameter);
return EntityVoUtil.toVo(page);
}
private Page<OrgVo> noConditionQuery(QueryParameter queryParameter) throws Exception {
Page<OrgEntity> page = orgService.query(queryParameter);
return EntityVoUtil.toVo(page);
}
private Boolean existCondition(QueryParameter queryParameter) {
List<Criteria> list = queryParameter.getCriterias();
if (list !=null && list.size() > 0 && list.get(0).getCriteria() != null && list.get(0).getCriteria().size() > 0) {
return true;
}
return false;
}
private void orgHandler(String fieldName, Criteria criteria, List<Criteria> orgCriteriaList) throws Exception {
switch(fieldName) {
case UserSearchConstant.FN_FINDBYORGIDWITHSUB:
findByOrgIdWithSubHandler((InSet) criteria, orgCriteriaList);
break;
case UserSearchConstant.FN_FINDBYORGID:
findByOrgIdHandler((InSet) criteria, orgCriteriaList);
break;
case UserSearchConstant.FN_FINDBYDEFAULTORGWITHSUB:
findByDefaultOrg(orgCriteriaList, true);
break;
case UserSearchConstant.FN_FINDBYDEFAULTORG:
findByDefaultOrg(orgCriteriaList, false);
break;
}
}
private void findByOrgIdWithSubHandler(InSet criteria, List<Criteria> orgCriteriaList) {
String[] ids = criteria.getValue();
List<OrgEntity> list = orgService.getRepository().findAllById(Arrays.asList(ids));
List<String> orgIds = new ArrayList<>();
if (list!=null && list.size()>0) {
for(OrgEntity org: list) {
orgIds.add(org.getId());
userSearchServiceImpl.recursiveGetChildren(org, orgIds);
}
}
userSearchServiceImpl.criteriaListAddInSet(orgCriteriaList, "id", orgIds);
}
private void findByOrgIdHandler(InSet criteria, List<Criteria> orgCriteriaList) {
String[] ids = criteria.getValue();
List<OrgEntity> list = orgService.getRepository().findAllById(Arrays.asList(ids));
List<String> orgIds = list.stream().map(OrgEntity::getId).collect(Collectors.toList());
userSearchServiceImpl.criteriaListAddInSet(orgCriteriaList, "id", orgIds);
}
private void findByDefaultOrg(List<Criteria> orgCriteriaList, Boolean withSub) {
String orgId = SecurityUtil.getDefaultOrgId();
if (!StringUtil.isNullOrEmpty(orgId)) {
OrgEntity org = orgService.findById(orgId);
if (org!=null) {
// TODO 机构是否为总行机构逻辑还需完善,目前判定 parent 为空为总行机构,多法人情况下该逻辑可能不适用。
if (org.getParent() != null) {
// 非总行机构添加查询条件,总行机构不用添加,查所有用户
List<String> orgIds = new ArrayList<>();
orgIds.add(org.getId());
if (withSub) {
userSearchServiceImpl.recursiveGetChildren(org, orgIds);
}
userSearchServiceImpl.criteriaListAddInSet(orgCriteriaList, "id", orgIds);
}
} else {
// 默认机构为空不允许查询用户
userSearchServiceImpl.criteriaListAddInSet(orgCriteriaList, "id", null);
}
} else {
userSearchServiceImpl.criteriaListAddInSet(orgCriteriaList, "id", null);
}
}
}

202
io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/service/impl/UserSearchServiceImpl.java

@ -1,29 +1,32 @@
package io.sc.platform.lcdp.frontend.component.service.impl;
import io.sc.platform.lcdp.frontend.component.service.UserSearchService;
import io.sc.platform.lcdp.frontend.component.support.UserSearchConstant;
import io.sc.platform.lcdp.frontend.component.support.UserSearchQueryParameter;
import io.sc.platform.lcdp.frontend.component.vo.UserSearchVo;
import io.sc.platform.orm.service.support.OperatorType;
import io.sc.platform.orm.service.support.QueryParameter;
import io.sc.platform.orm.service.support.criteria.Criteria;
import io.sc.platform.orm.service.support.criteria.impl.Equals;
import io.sc.platform.orm.service.support.criteria.impl.InSet;
import io.sc.platform.orm.util.EntityVoUtil;
import io.sc.platform.security.util.SecurityUtil;
import io.sc.platform.system.department.jpa.entity.DepartmentEntity;
import io.sc.platform.system.menu.jpa.entity.MenuEntity;
import io.sc.platform.system.org.jpa.entity.OrgEntity;
import io.sc.platform.system.org.service.OrgService;
import io.sc.platform.system.role.jpa.entity.RoleEntity;
import io.sc.platform.system.role.service.RoleService;
import io.sc.platform.system.user.jpa.entity.UserEntity;
import io.sc.platform.system.user.service.UserService;
import io.sc.platform.util.StringUtil;
import org.h2.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
@Service
@ -37,35 +40,178 @@ public class UserSearchServiceImpl implements UserSearchService {
private RoleService roleService;
@Override
public Page<UserSearchVo> queryUser(UserSearchQueryParameter userSearchQueryParameter) throws Exception {
QueryParameter queryParameter = userSearchQueryParameter.getQueryParameter();
QueryParameter orgQueryParameter = userSearchQueryParameter.getOrgQueryParameter();
QueryParameter roleQueryParameter = userSearchQueryParameter.getRoleQueryParameter();
if (orgQueryParameter!=null) {
List<OrgEntity> orgList = orgService.list(orgQueryParameter);
List<String> orgIds = orgList.stream().map(OrgEntity::getId).collect(Collectors.toList());
if (orgIds!=null && orgIds.size() > 0) {
InSet inSet = new InSet();
inSet.setFieldName("orgs");
inSet.setOperator(OperatorType.inSet);
inSet.setValue(orgIds.toArray(new String[0]));
queryParameter.addCriteria(inSet);
}
public Page<UserSearchVo> queryUser(QueryParameter queryParameter) throws Exception {
if (existCondition(queryParameter)) {
return existConditionQuery(queryParameter);
} else {
return noConditionQuery(queryParameter);
}
if (roleQueryParameter!=null) {
List<RoleEntity> roleList = roleService.list(roleQueryParameter);
List<String> roleIds = roleList.stream().map(RoleEntity::getId).collect(Collectors.toList());
if (roleList!=null && roleList.size() > 0) {
InSet inSet = new InSet();
inSet.setFieldName("roles");
inSet.setOperator(OperatorType.inSet);
inSet.setValue(roleIds.toArray(new String[0]));
queryParameter.addCriteria(inSet);
}
private Page<UserSearchVo> existConditionQuery(QueryParameter queryParameter) throws Exception {
List<Criteria> userCriteriaList = new ArrayList<>();
/**
* 前端已将queryCriteria机构查询条件角色查询条件重新使用 and 操作进行组装后端需提取出来进行处理
* 只要存在查询条件最外层一定是 { fieldName: null, operator: 'and', criteria: [...] }
* 所以最外层无需处理直接处理最外层的 criteria 数组
*/
List<Criteria> criterias = queryParameter.getCriterias().get(0).getCriteria();
for (Criteria criteria: criterias) {
if (criteria.getFieldName()!=null) {
Boolean isOrgCriteria = Arrays.stream(UserSearchConstant.ORG_CRITERIA_FIELD_NAMES).anyMatch(criteria.getFieldName()::equals);
Boolean isRoleCriteria = UserSearchConstant.FN_ROLECRITERIA.equals(criteria.getFieldName());
if (!isOrgCriteria && !isRoleCriteria) {
userCriteriaList.add(criteria);
} else if (isOrgCriteria) {
// 跟机构相关的查询条件处理
orgHandler(criteria.getFieldName(), criteria, userCriteriaList);
} else if (isRoleCriteria) {
// 角色的查询条件处理
roleCriteriaHandler((Equals) criteria, userCriteriaList);
}
} else {
// 非特定 fieldName 添加进用户查询的 criteria 中
userCriteriaList.add(criteria);
}
}
Page<UserEntity> page = userService.query(rebuildQueryParameter(queryParameter, userCriteriaList));
return userEntityPage2UserSearchVoPage(page);
}
private Page<UserSearchVo> noConditionQuery(QueryParameter queryParameter) throws Exception {
Page<UserEntity> page = userService.query(queryParameter);
return userEntityPage2UserSearchVoPage(page);
}
private Boolean existCondition(QueryParameter queryParameter) {
List<Criteria> list = queryParameter.getCriterias();
if (list !=null && list.size() > 0 && list.get(0).getCriteria() != null && list.get(0).getCriteria().size() > 0) {
return true;
}
return false;
}
private void orgHandler(String fieldName, Criteria criteria, List<Criteria> userCriteriaList) throws Exception {
switch(fieldName) {
case UserSearchConstant.FN_ORGCRITERIA:
orgCriteriaHandler((Equals) criteria, userCriteriaList);
break;
case UserSearchConstant.FN_FINDBYORGIDWITHSUB:
findByOrgIdWithSubHandler((InSet) criteria, userCriteriaList);
break;
case UserSearchConstant.FN_FINDBYORGID:
findByOrgIdHandler((InSet) criteria, userCriteriaList);
break;
case UserSearchConstant.FN_FINDBYDEFAULTORGWITHSUB:
findByDefaultOrg(userCriteriaList, true);
break;
case UserSearchConstant.FN_FINDBYDEFAULTORG:
findByDefaultOrg(userCriteriaList, false);
break;
}
}
private void orgCriteriaHandler(Equals criteria, List<Criteria> userCriteriaList) throws Exception {
QueryParameter queryParameter = new QueryParameter();
queryParameter.setCriteria(criteria.getValue());
queryParameter.setPageable(false);
List<OrgEntity> orgList = orgService.list(queryParameter);
List<String> orgIds = orgList.stream().map(OrgEntity::getId).collect(Collectors.toList());
criteriaListAddInSet(userCriteriaList, "orgs", orgIds);
}
private void findByOrgIdWithSubHandler(InSet criteria, List<Criteria> userCriteriaList) {
String[] ids = criteria.getValue();
List<OrgEntity> list = orgService.getRepository().findAllById(Arrays.asList(ids));
List<String> orgIds = new ArrayList<>();
if (list!=null && list.size()>0) {
for(OrgEntity org: list) {
orgIds.add(org.getId());
recursiveGetChildren(org, orgIds);
}
}
criteriaListAddInSet(userCriteriaList, "orgs", orgIds);
}
private void findByOrgIdHandler(InSet criteria, List<Criteria> userCriteriaList) {
String[] ids = criteria.getValue();
List<OrgEntity> list = orgService.getRepository().findAllById(Arrays.asList(ids));
List<String> orgIds = list.stream().map(OrgEntity::getId).collect(Collectors.toList());
criteriaListAddInSet(userCriteriaList, "orgs", orgIds);
}
private void findByDefaultOrg(List<Criteria> userCriteriaList, Boolean withSub) {
String orgId = SecurityUtil.getDefaultOrgId();
String fieldName = "orgs";
if (!StringUtil.isNullOrEmpty(orgId)) {
OrgEntity org = orgService.findById(orgId);
if (org!=null) {
// TODO 机构是否为总行机构逻辑还需完善,目前判定 parent 为空为总行机构,多法人情况下该逻辑可能不适用。
if (org.getParent() != null) {
// 非总行机构添加查询条件,总行机构不用添加,查所有用户
List<String> orgIds = new ArrayList<>();
orgIds.add(org.getId());
if (withSub) {
recursiveGetChildren(org, orgIds);
}
criteriaListAddInSet(userCriteriaList, fieldName, orgIds);
}
} else {
// 默认机构为空不允许查询用户
criteriaListAddInSet(userCriteriaList, fieldName, null);
}
} else {
criteriaListAddInSet(userCriteriaList, fieldName, null);
}
}
public void recursiveGetChildren(OrgEntity org, List<String> ids) {
List<OrgEntity> children =org.getChildren();
if(children!=null && !children.isEmpty()){
for(OrgEntity child : children){
ids.add(child.getId());
recursiveGetChildren(child,ids);
}
}
}
public void criteriaListAddInSet(List<Criteria> criteriaList, String fieldName, List<String> value) {
InSet inSet = new InSet();
inSet.setFieldName(fieldName);
inSet.setOperator(OperatorType.inSet);
if (value!=null && value.size()>0) {
inSet.setValue(value.toArray(new String[0]));
} else {
// 如果传入的value为空,设置一个无法匹配到数据的数组
inSet.setValue(new String[]{Long.toString(System.currentTimeMillis())});
}
criteriaList.add(inSet);
}
private void roleCriteriaHandler(Equals roleCriteria, List<Criteria> userCriteriaList) throws Exception {
QueryParameter roleQueryParameter = new QueryParameter();
roleQueryParameter.setCriteria(roleCriteria.getValue());
roleQueryParameter.setPageable(false);
List<RoleEntity> roleList = roleService.list(roleQueryParameter);
List<String> roleIds = roleList.stream().map(RoleEntity::getId).collect(Collectors.toList());
criteriaListAddInSet(userCriteriaList, "roles", roleIds);
}
public QueryParameter rebuildQueryParameter(QueryParameter oldQueryParameter, List<Criteria> userCriteriaList) {
QueryParameter queryParameter = new QueryParameter();
queryParameter.setCriterias(userCriteriaList);
queryParameter.setSortBy(oldQueryParameter.getSortBy());
queryParameter.setPageable(oldQueryParameter.getPageable());
queryParameter.setPage(oldQueryParameter.getPage());
queryParameter.setOperator(oldQueryParameter.getOperator());
queryParameter.setSize(oldQueryParameter.getSize());
queryParameter.setExportFilename(oldQueryParameter.getExportFilename());
return queryParameter;
}
private Page<UserSearchVo> userEntityPage2UserSearchVoPage(Page<UserEntity> page) throws Exception {
List<UserSearchVo> userList = new ArrayList<>();
if (page.getContent()!=null && page.getContent().size()>0) {
List<UserSearchVo> userList = new ArrayList<>();
for(UserEntity user: page.getContent()) {
UserSearchVo userVo = new UserSearchVo();
userVo.setId(user.getId());

39
io.sc.platform.lcdp/src/main/java/io/sc/platform/lcdp/frontend/component/support/UserSearchConstant.java

@ -0,0 +1,39 @@
package io.sc.platform.lcdp.frontend.component.support;
public class UserSearchConstant {
/**
* 角色criteria查询条件
*/
public final static String FN_ROLECRITERIA="roleCriteria";
/**
* 机构criteria查询条件
*/
public final static String FN_ORGCRITERIA = "orgCriteria";
/**
* 可选用户根据机构ID数组并包含数组中的所有子机构进行过滤
*/
public final static String FN_FINDBYORGIDWITHSUB = "findByOrgIdWithSub";
/**
* 可选用户根据机构ID数组进行过滤
*/
public final static String FN_FINDBYORGID = "findByOrgId";
/**
* 可选用户根据当前登录用户的默认机构及机构下的所有子机构进行过滤
* 若默认机构为空无法选择用户
* 为总行的用户可选全部用户
*/
public final static String FN_FINDBYDEFAULTORGWITHSUB = "findByDefaultOrgWithSub";
/**
* 可选用户根据当前登录用户的默认机构机构进行过滤
* 若默认机构为空无法选择用户
* 为总行的用户可选全部用户
*/
public final static String FN_FINDBYDEFAULTORG = "findByDefaultOrg";
/**
* 根据机构过滤的属性有5个这些属性无法配合使用只能生效一个
* 优先级如下orgCriteria > findByOrgIdWithSub > findByOrgId > findByDefaultOrgWithSub > findByDefaultOrg
*/
public final static String[] ORG_CRITERIA_FIELD_NAMES = new String[]{FN_ORGCRITERIA, FN_FINDBYORGIDWITHSUB, FN_FINDBYORGID, FN_FINDBYDEFAULTORGWITHSUB, FN_FINDBYDEFAULTORG};
}
Loading…
Cancel
Save