Merge branch 'gaoang2024-7' into 'dev'
合并需求 See merge request itc-framework/ma/2024/front!7
This commit is contained in:
@ -23,19 +23,23 @@ const props = defineProps({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
value: {
|
selectedNodes: {
|
||||||
type: String,
|
type: Array,
|
||||||
default: ''
|
default: () => []
|
||||||
},
|
},
|
||||||
parentNode: {
|
parentNode: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
|
isArray: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const emit = defineEmits(['change-value', 'query-completed']);
|
const emit = defineEmits(['change-value', 'query-completed', 'select']);
|
||||||
const expandedKeys = ref<string[]>([]);
|
const expandedKeys = ref([]);
|
||||||
const selectedKeys = ref<string[]>([]);
|
const selectedKeys = ref([]);
|
||||||
const checkedKeys = ref<string[]>([]);
|
const checkedKeys = ref([]);
|
||||||
const checkable = ref(false)
|
const checkable = ref(false)
|
||||||
const treeData = ref([])
|
const treeData = ref([])
|
||||||
const params = ref({
|
const params = ref({
|
||||||
@ -45,7 +49,6 @@ const params = ref({
|
|||||||
parentNode: false
|
parentNode: false
|
||||||
})
|
})
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
selectedKeys.value = [props.value]
|
|
||||||
getList()
|
getList()
|
||||||
})
|
})
|
||||||
const loadData = (node) => {
|
const loadData = (node) => {
|
||||||
@ -88,7 +91,7 @@ function resetTreeList(list) {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
function selectData(selectedKeys, e) {
|
function selectData(selectedKeys, e) {
|
||||||
emit('change-value', e.selectedNodes);
|
emit('change-value', e.node, e.selected);
|
||||||
}
|
}
|
||||||
watch(expandedKeys, () => {
|
watch(expandedKeys, () => {
|
||||||
console.log('expandedKeys', expandedKeys);
|
console.log('expandedKeys', expandedKeys);
|
||||||
@ -99,4 +102,14 @@ watch(selectedKeys, () => {
|
|||||||
watch(checkedKeys, () => {
|
watch(checkedKeys, () => {
|
||||||
console.log('checkedKeys', checkedKeys);
|
console.log('checkedKeys', checkedKeys);
|
||||||
});
|
});
|
||||||
|
watch(
|
||||||
|
() => props.selectedNodes,
|
||||||
|
() => {
|
||||||
|
selectedKeys.value = props.selectedNodes.map(item => item.id)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -12,12 +12,12 @@
|
|||||||
<div class="choose-dep-box">
|
<div class="choose-dep-box">
|
||||||
<div class="choose-dep">
|
<div class="choose-dep">
|
||||||
<a-spin :spinning="loading" class="loading-box" />
|
<a-spin :spinning="loading" class="loading-box" />
|
||||||
<SelectDepartmentTreeV2 v-if="visible" :parentNode="parentNode" :value="props.value" @changeValue="departChange" @queryCompleted="queryCompleted"></SelectDepartmentTreeV2>
|
<SelectDepartmentTreeV2 v-if="visible" :multiple="multiple" :isArray="isArray" :parentNode="parentNode" :selectedNodes="selectedNodes" @changeValue="departChange" @queryCompleted="queryCompleted"></SelectDepartmentTreeV2>
|
||||||
</div>
|
</div>
|
||||||
<div class="choosen-dep">
|
<div class="choosen-dep">
|
||||||
<div v-for="item in selectedNodes" class="choosen-item">
|
<div v-for="item in selectedNodes" class="choosen-item">
|
||||||
<div class="choosen-label">{{ item.name }}</div>
|
<div class="choosen-label">{{ item.name }}</div>
|
||||||
<close-outlined class="close" @click="deleteItem" />
|
<close-outlined class="close" @click="deleteItem(item)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -41,7 +41,6 @@
|
|||||||
const valChanged = ref(false);
|
const valChanged = ref(false);
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
value: String,
|
|
||||||
prefix: String,
|
prefix: String,
|
||||||
suffix: String,
|
suffix: String,
|
||||||
placeholder: String,
|
placeholder: String,
|
||||||
@ -49,13 +48,20 @@
|
|||||||
disabled: Boolean,
|
disabled: Boolean,
|
||||||
parentNode: String,
|
parentNode: String,
|
||||||
size: String,
|
size: String,
|
||||||
|
value: {
|
||||||
|
type: String || Array,
|
||||||
|
},
|
||||||
|
isArray: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
bordered: {
|
bordered: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
multiple: {
|
multiple: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: false
|
||||||
},
|
},
|
||||||
componentProps: {
|
componentProps: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -69,16 +75,18 @@
|
|||||||
|
|
||||||
// Embedded in the form, just use the hook binding to perform form verification
|
// Embedded in the form, just use the hook binding to perform form verification
|
||||||
|
|
||||||
onMounted(() => {});
|
onMounted(() => {
|
||||||
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.value,
|
() => props.value,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) {
|
let ids = props.isArray ? val?.join(',') : val
|
||||||
|
if (ids) {
|
||||||
if (props.sepTextField && !valChanged.value) {
|
if (props.sepTextField && !valChanged.value) {
|
||||||
departNames.value = props.row[camelCaseString(props.sepTextField)];
|
departNames.value = props.row[camelCaseString(props.sepTextField)];
|
||||||
} else {
|
} else {
|
||||||
getDefaultList(val);
|
getDefaultList(ids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -87,9 +95,9 @@
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
async function getDefaultList(id) {
|
async function getDefaultList(ids) {
|
||||||
let param = {
|
let param = {
|
||||||
id: id,
|
ids: ids,
|
||||||
code: '',
|
code: '',
|
||||||
name: '',
|
name: '',
|
||||||
parentNode: false
|
parentNode: false
|
||||||
@ -127,8 +135,21 @@
|
|||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function departChange(nodes) {
|
function departChange(node, isSelect) {
|
||||||
selectedNodes.value = nodes;
|
if (props.multiple) {
|
||||||
|
if (isSelect) {
|
||||||
|
selectedNodes.value.push(node.dataRef)
|
||||||
|
} else {
|
||||||
|
selectedNodes.value = selectedNodes.value.filter(item => item.id !== node.dataRef.id)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isSelect) {
|
||||||
|
selectedNodes.value = [node.dataRef]
|
||||||
|
} else {
|
||||||
|
selectedNodes.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
valChanged.value = true;
|
valChanged.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +157,11 @@
|
|||||||
visible.value = true;
|
visible.value = true;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
if (props.value) {
|
if (props.value) {
|
||||||
getDefaultList(props.value);
|
if(props.isArray && !props.value.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let ids = props.isArray ? props.value.join(',') : props.value
|
||||||
|
getDefaultList(ids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,13 +170,15 @@
|
|||||||
let idList = selectedNodes.value.map((item) => item.id);
|
let idList = selectedNodes.value.map((item) => item.id);
|
||||||
const names = nameList.join(',');
|
const names = nameList.join(',');
|
||||||
const ids = idList.join(',');
|
const ids = idList.join(',');
|
||||||
emits('update:value', ids);
|
emits('update:value', props.isArray ? idList : ids);
|
||||||
departNames.value = names;
|
departNames.value = names;
|
||||||
updateSepTextField(names);
|
updateSepTextField(names);
|
||||||
|
emits('change', props.isArray ? idList : ids);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteItem() {
|
function deleteItem(item) {
|
||||||
selectedNodes.value = [];
|
selectedNodes.value = selectedNodes.value.filter(m => item.id !== m.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :class="{ disabled }" class="form-select-user" @click="show">
|
<div :class="{ disabled }" class="form-select-user" @click="show">
|
||||||
<a-input v-model:value="userNames" :disabled="disabled" :placeholder="placeholder" :size="size" readonly>
|
<a-button type="primary" v-if="buttonShow">{{ t('添加人员') }}</a-button>
|
||||||
|
<a-input v-model:value="userNames" v-if="!buttonShow" :disabled="disabled" :placeholder="placeholder" :size="size" readonly>
|
||||||
<template v-if="prefix" #prefix>
|
<template v-if="prefix" #prefix>
|
||||||
<Icon :icon="prefix" />
|
<Icon :icon="prefix" />
|
||||||
</template>
|
</template>
|
||||||
@ -69,8 +70,8 @@
|
|||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
import { ModalPanel } from '/@/components/ModalPanel/index';
|
import { ModalPanel } from '/@/components/ModalPanel/index';
|
||||||
import { getUserPageListNew, getUserMulti } from '/@/api/system/user';
|
import { getUserPageListNew, getUserMulti } from '/@/api/system/user';
|
||||||
import SelectDepartmentTreeV2 from './SelectDepartmentTreeV2.vue';
|
import SelectDepartmentTreeV2 from '/@/components/Form/src/components/SelectDepartmentTreeV2.vue';
|
||||||
import SelectUserListV2 from './SelectUserListV2.vue';
|
import SelectUserListV2 from '/@/components/Form/src/components/SelectUserListV2.vue';
|
||||||
import { camelCaseString } from '/@/utils/stringUtil';
|
import { camelCaseString } from '/@/utils/stringUtil';
|
||||||
|
|
||||||
const emits = defineEmits(['update:value', 'selectedId', 'change']);
|
const emits = defineEmits(['update:value', 'selectedId', 'change']);
|
||||||
@ -99,7 +100,11 @@
|
|||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
row: Object, // 行数据,在表格里用的到
|
row: Object, // 行数据,在表格里用的到
|
||||||
sepTextField: String // 将文本表示存储在独立字段
|
sepTextField: String, // 将文本表示存储在独立字段
|
||||||
|
buttonShow: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
});
|
});
|
||||||
let timeoutId = null;
|
let timeoutId = null;
|
||||||
let resetMemberList = [];
|
let resetMemberList = [];
|
||||||
|
|||||||
@ -136,14 +136,13 @@ export const useUserStore = defineStore({
|
|||||||
const { token } = data;
|
const { token } = data;
|
||||||
// save token
|
// save token
|
||||||
this.setToken(token);
|
this.setToken(token);
|
||||||
router.replace(params.targetURL || params.redirect || userInfo?.homePath || PageEnum.BASE_HOME)
|
|
||||||
|
|
||||||
return await this.afterLoginAction(false);
|
return await this.afterLoginAction(false, params.targetURL || params.redirect);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async afterLoginAction(goHome?: boolean): Promise<GetUserInfoModel | null> {
|
async afterLoginAction(goHome?: boolean, redirect?): Promise<GetUserInfoModel | null> {
|
||||||
if (!this.getToken) return null;
|
if (!this.getToken) return null;
|
||||||
|
|
||||||
// get user info
|
// get user info
|
||||||
@ -166,6 +165,7 @@ export const useUserStore = defineStore({
|
|||||||
});
|
});
|
||||||
router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw);
|
router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw);
|
||||||
}
|
}
|
||||||
|
redirect && (await router.replace(decodeURIComponent(redirect)));
|
||||||
goHome && (await router.replace(userInfo?.homePath || PageEnum.BASE_HOME));
|
goHome && (await router.replace(userInfo?.homePath || PageEnum.BASE_HOME));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -51,7 +51,7 @@
|
|||||||
title: '基础信息',
|
title: '基础信息',
|
||||||
field: 'parentId',
|
field: 'parentId',
|
||||||
label: t('上级组织'),
|
label: t('上级组织'),
|
||||||
component: 'TreeSelect',
|
component: 'Dept',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '请选择上级组织',
|
placeholder: '请选择上级组织',
|
||||||
fieldNames: {
|
fieldNames: {
|
||||||
|
|||||||
@ -136,7 +136,7 @@
|
|||||||
{
|
{
|
||||||
field: 'departmentIds',
|
field: 'departmentIds',
|
||||||
label: t('所属机构'),
|
label: t('所属机构'),
|
||||||
component: 'TreeSelect',
|
component: 'Dept',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '请选择所属机构',
|
placeholder: '请选择所属机构',
|
||||||
fieldNames: {
|
fieldNames: {
|
||||||
@ -144,6 +144,7 @@
|
|||||||
key: 'id',
|
key: 'id',
|
||||||
value: 'id',
|
value: 'id',
|
||||||
},
|
},
|
||||||
|
isArray: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
getPopupContainer: () => document.body,
|
getPopupContainer: () => document.body,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
|
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
|
||||||
<DeptTree class="w-1/3 xl:w-1/4" @select="handleSelect" />
|
<div class="dept-v2 w-1/3 xl:w-1/4">
|
||||||
|
<div class="tree-title">
|
||||||
|
组织列表
|
||||||
|
</div>
|
||||||
|
<DeptTreeV2 @select="handleSelect" />
|
||||||
|
</div>
|
||||||
<BasicTable @register="registerTable" class="w-2/3 xl:w-3/4">
|
<BasicTable @register="registerTable" class="w-2/3 xl:w-3/4">
|
||||||
<template #toolbar>
|
<template #toolbar>
|
||||||
<a-button type="primary" v-auth="'user:add'" @click="handleCreate">{{
|
<a-button type="primary" v-auth="'user:add'" @click="handleCreate">{{
|
||||||
@ -53,6 +58,7 @@
|
|||||||
import { useModal } from '/@/components/Modal';
|
import { useModal } from '/@/components/Modal';
|
||||||
import AccountModal from './components/UserModal.vue';
|
import AccountModal from './components/UserModal.vue';
|
||||||
import DeptTree from './components/DeptTree.vue';
|
import DeptTree from './components/DeptTree.vue';
|
||||||
|
import DeptTreeV2 from '/@/components/Form/src/components/SelectDepartmentTreeV2.vue'
|
||||||
import { useI18n } from '/@/hooks/web/useI18n';
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
import { Tag } from 'ant-design-vue';
|
import { Tag } from 'ant-design-vue';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@ -157,7 +163,7 @@
|
|||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'UserManagement',
|
name: 'UserManagement',
|
||||||
components: { BasicTable, PageWrapper, DeptTree, AccountModal, TableAction },
|
components: { BasicTable, PageWrapper, DeptTree, AccountModal, TableAction, DeptTreeV2 },
|
||||||
setup() {
|
setup() {
|
||||||
const { notification } = useMessage();
|
const { notification } = useMessage();
|
||||||
const selectDeptId = ref('');
|
const selectDeptId = ref('');
|
||||||
@ -301,7 +307,7 @@
|
|||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSelect(deptId = '') {
|
function handleSelect([deptId]) {
|
||||||
selectDeptId.value = deptId;
|
selectDeptId.value = deptId;
|
||||||
reload();
|
reload();
|
||||||
}
|
}
|
||||||
@ -326,3 +332,20 @@
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.dept-v2 {
|
||||||
|
margin-right: 16px;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 8px;
|
||||||
|
height: 100%;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
.tree-title {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
:deep(.select-department-tree) {
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
v-if="item.show"
|
v-if="item.show"
|
||||||
:is="item.component"
|
:is="item.component"
|
||||||
:memberList="props.memberList"
|
:memberList="props.memberList"
|
||||||
|
v-bind="item.componentProps"
|
||||||
@change="changeList"
|
@change="changeList"
|
||||||
>
|
>
|
||||||
<a-button type="primary">{{ item.name }}</a-button>
|
<a-button type="primary">{{ item.name }}</a-button>
|
||||||
@ -34,7 +35,9 @@
|
|||||||
import Icon from '/@/components/Icon/index';
|
import Icon from '/@/components/Icon/index';
|
||||||
import Posts from '/@bpmn/components/member/Posts.vue';
|
import Posts from '/@bpmn/components/member/Posts.vue';
|
||||||
import Roles from '/@bpmn/components/member/Roles.vue';
|
import Roles from '/@bpmn/components/member/Roles.vue';
|
||||||
import Users from '/@bpmn/components/member/Users.vue';
|
// import Users from '/@bpmn/components/member/Users.vue';
|
||||||
|
|
||||||
|
import SelectUserV2 from './SelectUserV2.vue';
|
||||||
import NodeApprover from '/@bpmn/components/member/NodeApprover.vue';
|
import NodeApprover from '/@bpmn/components/member/NodeApprover.vue';
|
||||||
import UpperManagement from '/@bpmn/components/member/UpperManagement.vue';
|
import UpperManagement from '/@bpmn/components/member/UpperManagement.vue';
|
||||||
import FormFields from '/@bpmn/components/member/FormFields.vue';
|
import FormFields from '/@bpmn/components/member/FormFields.vue';
|
||||||
@ -86,7 +89,7 @@
|
|||||||
return [
|
return [
|
||||||
{ name: t('添加岗位'), component: Posts, show: true },
|
{ name: t('添加岗位'), component: Posts, show: true },
|
||||||
{ name: t('添加角色'), component: Roles, show: true },
|
{ name: t('添加角色'), component: Roles, show: true },
|
||||||
{ name: t('添加人员'), component: Users, show: true },
|
{ name: t('添加人员'), component: SelectUserV2, show: true, componentProps: {buttonShow: true, multiple: true} },
|
||||||
{ name: t('节点审批人'), component: NodeApprover, show: props.isCommonType ? false : true },
|
{ name: t('节点审批人'), component: NodeApprover, show: props.isCommonType ? false : true },
|
||||||
{
|
{
|
||||||
name: t('上级领导'),
|
name: t('上级领导'),
|
||||||
@ -108,7 +111,7 @@
|
|||||||
if (val === MemberType.API) return t('API审批人');
|
if (val === MemberType.API) return t('API审批人');
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
function changeList(list: Array<MemberConfig>) {
|
function changeList(list) {
|
||||||
emits('update:memberList', list);
|
emits('update:memberList', list);
|
||||||
}
|
}
|
||||||
function deleteItem(index: number) {
|
function deleteItem(index: number) {
|
||||||
|
|||||||
@ -0,0 +1,472 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="{ disabled }" class="form-select-user" @click="show">
|
||||||
|
<a-button type="primary" v-if="buttonShow">{{ t('添加人员') }}</a-button>
|
||||||
|
<a-input v-model:value="userNames" v-if="!buttonShow" :disabled="disabled" :placeholder="placeholder" :size="size" readonly>
|
||||||
|
<template v-if="prefix" #prefix>
|
||||||
|
<Icon :icon="prefix" />
|
||||||
|
</template>
|
||||||
|
<template v-if="suffix" #suffix>
|
||||||
|
<Icon :icon="suffix" />
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
|
<ModalPanel :title="t('选择人员')" :visible="visible" :width="900" class="select-user-model" @close="close" @submit="submit">
|
||||||
|
<div class="select-user">
|
||||||
|
<div class="select-user-left">
|
||||||
|
<a-tabs v-model:activeKey="activeKey" :tabBarGutter="20">
|
||||||
|
<a-tab-pane key="department" tab="组织架构"></a-tab-pane>
|
||||||
|
<a-tab-pane key="allPerson" tab="所有人"></a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
<div class="person-search">
|
||||||
|
<a-form-item label="" name="name">
|
||||||
|
<a-input v-model:value="selectPersonNames" :placeholder="searchPlaceholder" :size="size" class="search-input"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
</div>
|
||||||
|
<div v-show="activeKey === 'department'" class="select-user-box">
|
||||||
|
<div class="department-tree">
|
||||||
|
<a-spin :spinning="treeLoading" class="loading-box" />
|
||||||
|
<div class="department-tree-box">
|
||||||
|
<SelectDepartmentTreeV2 v-if="visible && activeKey === 'department'" class="tree-select" @changeValue="departChange" @queryCompleted="departCompleted"></SelectDepartmentTreeV2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="user-select-box">
|
||||||
|
<SelectUserListV2 :data="searchDepartMemberList" emptyDescription="暂无人员" @selectId="changeDepMemberSelect"></SelectUserListV2>
|
||||||
|
<div v-if="false" class="user-select-pagination">
|
||||||
|
<a-pagination v-model:current="searchDepartMemberParams.limit" :pageSize="searchDepartMemberParams.size" :total="searchDepartMemberTotal" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-show="activeKey === 'allPerson'" class="all-user-select-box">
|
||||||
|
<SelectUserListV2 :data="searchAllMemberList" @selectId="changeMemberSelect"></SelectUserListV2>
|
||||||
|
<div v-if="searchAllMemberTotal > 25" class="all-user-select-pagination">
|
||||||
|
<a-form-item label="" name="pagination">
|
||||||
|
<a-pagination
|
||||||
|
v-model:current="searchAllMemberParams.limit"
|
||||||
|
:pageSize="searchAllMemberParams.size"
|
||||||
|
:show-size-changer="false"
|
||||||
|
:show-total="(total) => `共${total}人`"
|
||||||
|
:total="searchAllMemberTotal"
|
||||||
|
hideOnSinglePage
|
||||||
|
showLessItems
|
||||||
|
size="small"
|
||||||
|
@change="changeAllMemberPage"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="select-user-right">
|
||||||
|
<!-- <div class="selected-user-title sub-title">
|
||||||
|
已选列表
|
||||||
|
</div> -->
|
||||||
|
<SelectUserListV2 :data="selectedMemberList" canDel emptyDescription="暂无已选择人员,<br> 请从左侧添加人员" viewList @delId="delMember"></SelectUserListV2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModalPanel>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { watch, ref } from 'vue';
|
||||||
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
import { useI18n } from '/@/hooks/web/useI18n';
|
||||||
|
import { ModalPanel } from '/@/components/ModalPanel/index';
|
||||||
|
import { getUserPageListNew, getUserMulti } from '/@/api/system/user';
|
||||||
|
import SelectDepartmentTreeV2 from '/@/components/Form/src/components/SelectDepartmentTreeV2.vue';
|
||||||
|
import SelectUserListV2 from '/@/components/Form/src/components/SelectUserListV2.vue';
|
||||||
|
import { camelCaseString } from '/@/utils/stringUtil';
|
||||||
|
|
||||||
|
const emits = defineEmits(['update:value', 'selectedId', 'change']);
|
||||||
|
const { t } = useI18n();
|
||||||
|
const userNames = ref('');
|
||||||
|
const treeLoading = ref(true);
|
||||||
|
const visible = ref(false);
|
||||||
|
const activeKey = ref('department');
|
||||||
|
const selectedMemberList = ref([]);
|
||||||
|
const selectPersonNames = ref('');
|
||||||
|
const valChanged = ref(false);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
prefix: String,
|
||||||
|
suffix: String,
|
||||||
|
placeholder: String,
|
||||||
|
readonly: Boolean,
|
||||||
|
disabled: Boolean,
|
||||||
|
size: String,
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
row: Object, // 行数据,在表格里用的到
|
||||||
|
sepTextField: String, // 将文本表示存储在独立字段
|
||||||
|
buttonShow: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
memberList: {
|
||||||
|
type: Array,
|
||||||
|
default: []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let timeoutId = null;
|
||||||
|
let resetMemberList = [];
|
||||||
|
const searchPlaceholder = '请输入姓名或工号搜索';
|
||||||
|
|
||||||
|
function updateSepTextField(v) {
|
||||||
|
if (!props.sepTextField || !props.row) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
props.row[camelCaseString(props.sepTextField)] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 防止输入多次调用搜索接口导致问题,使用防抖
|
||||||
|
watch(selectPersonNames, (newValue) => {
|
||||||
|
if (newValue && activeKey.value !== 'allPerson') {
|
||||||
|
activeKey.value = 'allPerson';
|
||||||
|
}
|
||||||
|
if (timeoutId) {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
}
|
||||||
|
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
// 调用搜索接口
|
||||||
|
console.log('执行搜索API操作, 查询参数为:', newValue);
|
||||||
|
searchNameChanged(newValue);
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
watch(activeKey, (newValue) => {
|
||||||
|
searchAllMemberList.value = [];
|
||||||
|
searchAllMemberTotal.value = 0;
|
||||||
|
searchDepartMemberList.value = [];
|
||||||
|
treeLoading.value = true;
|
||||||
|
if (newValue !== 'allPerson') {
|
||||||
|
selectPersonNames.value = '';
|
||||||
|
} else {
|
||||||
|
if (!timeoutId) {
|
||||||
|
searchNameChanged('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
watch(
|
||||||
|
props,
|
||||||
|
async () => {
|
||||||
|
if (props.value && !valChanged.value && props.sepTextField) {
|
||||||
|
const idArr = props.value.split(',');
|
||||||
|
const valStr = props.row[camelCaseString(props.sepTextField)];
|
||||||
|
const valArr = valStr.split(',');
|
||||||
|
userNames.value = valStr;
|
||||||
|
const initValue = idArr.map((id, index) => {
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
name: valArr[index]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
selectedMemberList.value = initValue;
|
||||||
|
resetMemberList = cloneDeep(initValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (props.value && !resetMemberList.length) {
|
||||||
|
const list = await getUserMulti(props.value);
|
||||||
|
selectedMemberList.value = list;
|
||||||
|
resetMemberList = cloneDeep(list);
|
||||||
|
const nameList = resetMemberList.map((item) => {
|
||||||
|
return item.name;
|
||||||
|
});
|
||||||
|
userNames.value = nameList.join(',');
|
||||||
|
}
|
||||||
|
if(props.memberList) {
|
||||||
|
const list = props.memberList.filter(item => {
|
||||||
|
return item.memberType == 0
|
||||||
|
})
|
||||||
|
selectedMemberList.value = list
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const searchDepartMemberParams = ref({
|
||||||
|
limit: 1,
|
||||||
|
size: 10000,
|
||||||
|
departmentId: ''
|
||||||
|
});
|
||||||
|
const searchDepartMemberTotal = ref(0);
|
||||||
|
const searchDepartMemberList = ref([]);
|
||||||
|
const searchAllMemberParams = ref({
|
||||||
|
limit: 1,
|
||||||
|
size: 25,
|
||||||
|
isSearchAll: true,
|
||||||
|
keyword: ''
|
||||||
|
});
|
||||||
|
const searchAllMemberTotal = ref(0);
|
||||||
|
const searchAllMemberList = ref([]);
|
||||||
|
|
||||||
|
async function departChange(e) {
|
||||||
|
searchDepartMemberParams.value.departmentId = e[0].id;
|
||||||
|
let res = await getUserList(searchDepartMemberParams.value);
|
||||||
|
searchDepartMemberTotal.value = res.total;
|
||||||
|
searchDepartMemberList.value = setSelected(res.list);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function searchNameChanged(val) {
|
||||||
|
searchAllMemberParams.value.limit = 1;
|
||||||
|
searchAllMemberParams.value.keyword = val;
|
||||||
|
getAllMemberList();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAllMemberList() {
|
||||||
|
let res = await getUserList(searchAllMemberParams.value);
|
||||||
|
searchAllMemberTotal.value = res.total;
|
||||||
|
searchAllMemberList.value = setSelected(res.list);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSelected(list) {
|
||||||
|
const idList = selectedMemberList.value.map((item) => item.id);
|
||||||
|
const ids = idList.join(',');
|
||||||
|
list.forEach((item) => {
|
||||||
|
if (ids?.includes(item.id)) {
|
||||||
|
item.selected = true;
|
||||||
|
} else {
|
||||||
|
item.selected = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getUserList(params) {
|
||||||
|
return await getUserPageListNew(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
function departCompleted() {
|
||||||
|
treeLoading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeDepMemberSelect(id) {
|
||||||
|
let list = searchDepartMemberList.value;
|
||||||
|
searchDepartMemberList.value = handleListSelected(list, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeMemberSelect(id) {
|
||||||
|
let list = searchAllMemberList.value;
|
||||||
|
searchAllMemberList.value = handleListSelected(list, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleListSelected(list, id) {
|
||||||
|
let selected = false;
|
||||||
|
let selectedItem;
|
||||||
|
list.forEach((item) => {
|
||||||
|
if (item.id === id) {
|
||||||
|
item.selected = !!!item.selected;
|
||||||
|
selected = item.selected;
|
||||||
|
selectedItem = item;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let memberList = selectedMemberList.value;
|
||||||
|
if (selected) {
|
||||||
|
memberList.push(selectedItem);
|
||||||
|
selectedMemberList.value = memberList;
|
||||||
|
} else {
|
||||||
|
selectedMemberList.value = memberList.filter((m) => m.id !== id);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeAllMemberPage(page) {
|
||||||
|
searchAllMemberParams.value.limit = page;
|
||||||
|
getAllMemberList();
|
||||||
|
}
|
||||||
|
|
||||||
|
function show() {
|
||||||
|
visible.value = true;
|
||||||
|
treeLoading.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function delMember(id) {
|
||||||
|
if (activeKey.value === 'department') {
|
||||||
|
changeDepMemberSelect(id);
|
||||||
|
} else {
|
||||||
|
changeMemberSelect(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function submit() {
|
||||||
|
let idsList = [];
|
||||||
|
let namesList = [];
|
||||||
|
selectedMemberList.value.forEach((item) => {
|
||||||
|
idsList.push(item.id);
|
||||||
|
namesList.push(item.name);
|
||||||
|
item.memberType = 0
|
||||||
|
});
|
||||||
|
const ids = idsList.join(',');
|
||||||
|
const names = namesList.join(',');
|
||||||
|
resetMemberList = cloneDeep(selectedMemberList.value);
|
||||||
|
userNames.value = names;
|
||||||
|
let finalList = props.memberList.filter(item => item.memberType !== 0).concat(selectedMemberList.value)
|
||||||
|
updateSepTextField(names);
|
||||||
|
emits('update:value', ids);
|
||||||
|
emits('selectedId', ids);
|
||||||
|
emits('change', finalList);
|
||||||
|
valChanged.value = false;
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
selectedMemberList.value = cloneDeep(resetMemberList);
|
||||||
|
visible.value = false;
|
||||||
|
activeKey.value = 'department';
|
||||||
|
searchDepartMemberList.value = [];
|
||||||
|
searchAllMemberList.value = [];
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="less">
|
||||||
|
.select-user-model {
|
||||||
|
.content {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.sub-title {
|
||||||
|
height: 30px;
|
||||||
|
padding: 0 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
color: rgba(144, 147, 153, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-user {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
// border: 1px solid #eaeaea;
|
||||||
|
|
||||||
|
.select-user-left {
|
||||||
|
width: 75%;
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid #eaeaea;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
:deep(.ant-tabs-nav) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
.ant-tabs-nav-wrap {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.person-search {
|
||||||
|
padding: 4px;
|
||||||
|
|
||||||
|
:deep(.ant-form-item) {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-user-box {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
display: flex;
|
||||||
|
border-top: 1px solid #eaeaea;
|
||||||
|
|
||||||
|
.department-tree {
|
||||||
|
position: relative;
|
||||||
|
width: 65%;
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid #eaeaea;
|
||||||
|
|
||||||
|
.loading-box {
|
||||||
|
position: absolute;
|
||||||
|
top: 49%;
|
||||||
|
left: 49%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.department-tree-box {
|
||||||
|
// overflow: scroll;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 4px 8px;
|
||||||
|
|
||||||
|
.department-tree-title {
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-select {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-select-box {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.user-select-title {
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-select-list {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
overflow-y: scroll;
|
||||||
|
|
||||||
|
.user-select-item {
|
||||||
|
height: 30px;
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-select-pagination {
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.all-user-select-box {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.all-user-select-title {
|
||||||
|
}
|
||||||
|
|
||||||
|
.all-user-select-pagination {
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.ant-form-item {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-user-right {
|
||||||
|
width: 25%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.selected-user-title {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -187,8 +187,10 @@
|
|||||||
function addModelerListener() {
|
function addModelerListener() {
|
||||||
bpmnModeler.on('shape.added', (e: any) => {
|
bpmnModeler.on('shape.added', (e: any) => {
|
||||||
let shape = e.element ? bpmnModeler.get('elementRegistry').get(e.element.id) : e.shape;
|
let shape = e.element ? bpmnModeler.get('elementRegistry').get(e.element.id) : e.shape;
|
||||||
|
if (shape.type !== 'label') {
|
||||||
changePanel(shape.type, shape.id);
|
changePanel(shape.type, shape.id);
|
||||||
bpmnCanvas.elementEventName = 'added';
|
bpmnCanvas.elementEventName = 'added';
|
||||||
|
}
|
||||||
});
|
});
|
||||||
bpmnModeler.on('selection.changed', (e: any) => {
|
bpmnModeler.on('selection.changed', (e: any) => {
|
||||||
bpmnCanvas.elementEventName = 'change';
|
bpmnCanvas.elementEventName = 'change';
|
||||||
|
|||||||
Reference in New Issue
Block a user