feat(系统设置): 组织对接添加成员接口
This commit is contained in:
parent
5db28cfb25
commit
146e6996ce
|
@ -1,6 +1,7 @@
|
|||
import MSR from '@/api/http/index';
|
||||
import * as orgUrl from '@/api/requrls/setting/system/organizationAndProject';
|
||||
import { TableQueryParams } from '@/models/common';
|
||||
import { AddUserToOrgOrPorjectParams } from '@/models/setting/systemOrg';
|
||||
|
||||
// 获取组织列表
|
||||
export function postOrgTable(data: TableQueryParams) {
|
||||
|
@ -21,3 +22,11 @@ export function postProjectTableByOrgId(data: TableQueryParams) {
|
|||
export function postUserTableByOrgId(data: TableQueryParams) {
|
||||
return MSR.post({ url: orgUrl.postOrgMemberUrl, data });
|
||||
}
|
||||
// 给组织或项目添加成员
|
||||
export function addUserToOrgOrProject(data: AddUserToOrgOrPorjectParams) {
|
||||
return MSR.post({ url: data.projectId ? orgUrl.postAddProjectMemberUrl : orgUrl.postAddOrgMemberUrl, data });
|
||||
}
|
||||
// 获取用户下拉选项
|
||||
export function getUserByOrganizationOrProject(sourceId: string) {
|
||||
return MSR.get({ url: `${orgUrl.getUserByOrgOrProjectUrl}${sourceId}` });
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ export const postOrgMemberUrl = '/system/organization/list-member';
|
|||
// 添加组织
|
||||
export const postAddOrgUrl = '/system/organization/add';
|
||||
// 添加组织成员
|
||||
export const postAddOrgMemberUrl = '/system/organization/member/add';
|
||||
export const postAddOrgMemberUrl = '/system/organization/add-member';
|
||||
// 删除组织成员
|
||||
export const getDeleteOrgMemberUrl = '/system/organization/remove-member/';
|
||||
// 恢复组织
|
||||
|
@ -35,7 +35,7 @@ export const postProjectMemberUrl = '/system/project/member/list';
|
|||
// 添加项目
|
||||
export const postAddProjectUrl = '/system/project/add';
|
||||
// 添加项目成员
|
||||
export const postAddProjectMemberUrl = '/system/project/member/add';
|
||||
export const postAddProjectMemberUrl = '/system/project/add-member';
|
||||
// 撤销项目
|
||||
export const getRevokeProjectUrl = '/system/project/revoke/';
|
||||
// 移除项目成员
|
||||
|
@ -44,3 +44,5 @@ export const getDeleteProjectMemberUrl = '/system/project/remove-member/';
|
|||
export const getProjectInfoUrl = '/system/project/get/';
|
||||
// 删除项目
|
||||
export const getDeleteProjectUrl = '/system/project/delete/';
|
||||
// 系统-组织及项目,获取用户下拉选项
|
||||
export const getUserByOrgOrProjectUrl = '/system/user/get-option/';
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<a-select
|
||||
:value="value"
|
||||
v-model="currentValue"
|
||||
:disabled="props.disabled"
|
||||
multiple
|
||||
:virtual-list-props="{ height: 200 }"
|
||||
:placeholder="props.placeholder ? t(props.placeholder) : t('common.pleaseSelect')"
|
||||
:placeholder="props.placeholder ? t(props.placeholder) : t('common.pleaseSelectMember')"
|
||||
:options="userOptions"
|
||||
:field-names="fieldNames"
|
||||
@search="handleSearch"
|
||||
|
@ -22,40 +22,66 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import { getUserList } from '@/api/modules/setting/usergroup';
|
||||
import { getUserByOrganizationOrProject } from '@/api/modules/setting/system/organizationAndProject';
|
||||
|
||||
export interface MsUserSelectorProps {
|
||||
value: string[];
|
||||
disabled?: boolean;
|
||||
placeholder?: string;
|
||||
type?: 'organization' | 'usergroup';
|
||||
sourceId?: string;
|
||||
disabledKey?: 'disabled' | 'memberFlag' | 'adminFlag';
|
||||
}
|
||||
|
||||
export interface UserItem {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
disabled?: boolean;
|
||||
memberFlag?: boolean;
|
||||
adminFlag?: boolean;
|
||||
}
|
||||
|
||||
const fieldNames = { value: 'id', label: 'name' };
|
||||
const { t } = useI18n();
|
||||
const props = defineProps<MsUserSelectorProps>();
|
||||
const props = withDefaults(defineProps<MsUserSelectorProps>(), {
|
||||
disabled: false,
|
||||
type: 'usergroup',
|
||||
disabledKey: 'disabled',
|
||||
});
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:value', value: string[]): void;
|
||||
}>();
|
||||
const currentValue = ref(props.value);
|
||||
|
||||
const allOption = ref<UserItem[]>([]);
|
||||
const userOptions = ref<UserItem[]>([]);
|
||||
|
||||
const initUserList = async () => {
|
||||
const res = await getUserList();
|
||||
allOption.value = res;
|
||||
userOptions.value = res;
|
||||
let res: UserItem[] = [];
|
||||
if (props.type === 'organization') {
|
||||
if (!props.sourceId) {
|
||||
return;
|
||||
}
|
||||
res = await getUserByOrganizationOrProject(props.sourceId);
|
||||
} else {
|
||||
res = await getUserList();
|
||||
}
|
||||
res.forEach((item) => {
|
||||
item.disabled = item[props.disabledKey];
|
||||
});
|
||||
allOption.value = [...res];
|
||||
userOptions.value = [...res];
|
||||
};
|
||||
|
||||
const handleSearch = (value: string) => {
|
||||
if (value) {
|
||||
window.setTimeout(() => {
|
||||
userOptions.value = userOptions.value.filter((item) => item.name.includes(value));
|
||||
userOptions.value = userOptions.value.filter(
|
||||
(item) => item.name.includes(value) || currentValue.value.includes(item.id)
|
||||
);
|
||||
}, 60);
|
||||
} else {
|
||||
userOptions.value = allOption.value;
|
||||
|
@ -69,4 +95,10 @@
|
|||
onMounted(() => {
|
||||
initUserList();
|
||||
});
|
||||
watch(
|
||||
() => props.value,
|
||||
(value) => {
|
||||
currentValue.value = value;
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export default {
|
||||
'common.pleaseSelectMember': 'Please select member',
|
||||
};
|
|
@ -1,6 +1,7 @@
|
|||
import dayjsLocale from 'dayjs/locale/en';
|
||||
import localeSettings from './settings';
|
||||
import sys from './sys';
|
||||
import common from './common';
|
||||
|
||||
const _Cmodules: any = import.meta.glob('../../components/**/locale/en-US.ts', { eager: true });
|
||||
const _Vmodules: any = import.meta.glob('../../views/**/locale/en-US.ts', { eager: true });
|
||||
|
@ -15,7 +16,7 @@ Object.keys(_Vmodules).forEach((key) => {
|
|||
if (!defaultModule) return;
|
||||
result = { ...result, ...defaultModule };
|
||||
});
|
||||
console.log('result', result);
|
||||
|
||||
export default {
|
||||
message: {
|
||||
'menu.workplace': 'Workplace',
|
||||
|
@ -45,6 +46,7 @@ export default {
|
|||
...sys,
|
||||
...localeSettings,
|
||||
...result,
|
||||
...common,
|
||||
},
|
||||
dayjsLocale,
|
||||
dayjsLocaleName: 'en-US',
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export default {
|
||||
'common.pleaseSelectMember': '请选择成员',
|
||||
};
|
|
@ -1,6 +1,7 @@
|
|||
import dayjsLocale from 'dayjs/locale/zh-cn';
|
||||
import localeSettings from './settings';
|
||||
import sys from './sys';
|
||||
import common from './common';
|
||||
|
||||
const _Cmodules: any = import.meta.glob('../../components/**/locale/zh-CN.ts', { eager: true });
|
||||
const _Vmodules: any = import.meta.glob('../../views/**/locale/zh-CN.ts', { eager: true });
|
||||
|
@ -44,6 +45,7 @@ export default {
|
|||
...sys,
|
||||
...localeSettings,
|
||||
...result,
|
||||
...common,
|
||||
},
|
||||
dayjsLocale,
|
||||
dayjsLocaleName: 'zh-CN',
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
export interface AddUserToOrgOrPorjectParams {
|
||||
userIds?: string[];
|
||||
organizationId?: string;
|
||||
projectId?: string;
|
||||
// 等待接口改动 将要废弃,以后用userIds
|
||||
memberIds?: string[];
|
||||
}
|
|
@ -22,6 +22,9 @@ const msTableStore = defineStore('msTable', {
|
|||
if (item.showDrag === undefined) {
|
||||
item.showDrag = false;
|
||||
}
|
||||
if (item.showInTable === undefined) {
|
||||
item.showInTable = true;
|
||||
}
|
||||
});
|
||||
tmpMap.set(tableKey, { mode, column });
|
||||
this.selectorColumnMap = tmpMap;
|
||||
|
@ -56,7 +59,7 @@ const msTableStore = defineStore('msTable', {
|
|||
getShowInTableColumns(key: string): MsTableColumn {
|
||||
if (this.selectorColumnMap.has(key)) {
|
||||
const tmpArr = this.selectorColumnMap.get(key)?.column;
|
||||
return tmpArr?.filter((item) => !!item.showInTable) || [];
|
||||
return tmpArr?.filter((item) => item.showInTable) || [];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
|
|
|
@ -14,10 +14,7 @@
|
|||
field="name"
|
||||
required
|
||||
:label="t('system.organization.organizationName')"
|
||||
:rules="[
|
||||
{ required: true, message: t('system.organization.organizationNameRequired') },
|
||||
{ validator: validateName },
|
||||
]"
|
||||
:rules="[{ required: true, message: t('system.organization.organizationNameRequired') }]"
|
||||
>
|
||||
<a-input v-model="form.name" :placeholder="t('system.organization.organizationNamePlaceholder')" />
|
||||
</a-form-item>
|
||||
|
@ -57,16 +54,6 @@
|
|||
|
||||
const currentVisible = ref(props.visible);
|
||||
|
||||
const validateName = (value: string, callback: (error?: string) => void) => {
|
||||
if (value !== '') {
|
||||
// const isExist = props.list.some((item) => item.name === value);
|
||||
// if (isExist) {
|
||||
// callback(t('system.organization.userGroupNameIsExist', { name: value }));
|
||||
// }
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
currentVisible.value = props.visible;
|
||||
});
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
<template>
|
||||
<a-modal
|
||||
v-model:visible="currentVisible"
|
||||
title-align="start"
|
||||
class="ms-modal-form ms-modal-medium"
|
||||
:ok-text="t('system.organization.addMember')"
|
||||
unmount-on-close
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<template #title> {{ t('system.organization.addMember') }} </template>
|
||||
<div class="form">
|
||||
<a-form ref="formRef" :model="form" size="large" :style="{ width: '600px' }" layout="vertical">
|
||||
<a-form-item
|
||||
field="name"
|
||||
:label="t('system.organization.member')"
|
||||
:rules="[{ required: true, message: t('system.organization.addMemberRequired') }]"
|
||||
>
|
||||
<MsUserSelector v-model:value="form.name" type="organization" :source-id="organizationId || projectId" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button type="secondary" @click="handleCancel">
|
||||
{{ t('system.organization.cancel') }}
|
||||
</a-button>
|
||||
<a-button type="primary" :loading="loading" :disabled="form.name.length === 0" @click="handleAddMember">
|
||||
{{ t('system.organization.add') }}
|
||||
</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { reactive, ref, watchEffect, onUnmounted } from 'vue';
|
||||
import { addUserToOrgOrProject } from '@/api/modules/setting/system/organizationAndProject';
|
||||
import { Message, type FormInstance, type ValidatedError } from '@arco-design/web-vue';
|
||||
import MsUserSelector from '@/components/bussiness/ms-user-selector/index.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
organizationId?: string;
|
||||
projectId?: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'cancel'): void;
|
||||
(e: 'submit', value: string[]): void;
|
||||
}>();
|
||||
|
||||
const currentVisible = ref(props.visible);
|
||||
const loading = ref(false);
|
||||
|
||||
const form = reactive({
|
||||
name: [],
|
||||
});
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
watchEffect(() => {
|
||||
currentVisible.value = props.visible;
|
||||
});
|
||||
|
||||
const handleCancel = () => {
|
||||
form.name = [];
|
||||
emit('cancel');
|
||||
};
|
||||
|
||||
const handleAddMember = () => {
|
||||
formRef.value?.validate(async (errors: undefined | Record<string, ValidatedError>) => {
|
||||
loading.value = true;
|
||||
if (errors) {
|
||||
loading.value = false;
|
||||
}
|
||||
const { organizationId, projectId } = props;
|
||||
try {
|
||||
await addUserToOrgOrProject({ memberIds: form.name, organizationId, projectId });
|
||||
Message.success(t('system.organization.addSuccess'));
|
||||
loading.value = false;
|
||||
handleCancel();
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onUnmounted(() => {
|
||||
form.name = [];
|
||||
loading.value = false;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.option-name {
|
||||
color: var(--color-text-1);
|
||||
}
|
||||
.option-email {
|
||||
color: var(--color-text-4);
|
||||
}
|
||||
</style>
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<MsDrawer
|
||||
:width="680"
|
||||
:visible="props.visible"
|
||||
:visible="currentVisible"
|
||||
unmount-on-close
|
||||
:footer="false"
|
||||
:title="t('system.organization.projectName', { name: props.currentName })"
|
||||
|
@ -39,9 +39,10 @@
|
|||
const { t } = useI18n();
|
||||
const props = defineProps<projectDrawerProps>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', v: boolean): void;
|
||||
(e: 'cancel', v: boolean): void;
|
||||
}>();
|
||||
|
||||
const currentVisible = ref(props.visible);
|
||||
const keyword = ref('');
|
||||
|
||||
const projectColumn: MsTableColumn = [
|
||||
|
@ -81,7 +82,7 @@
|
|||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
emit('update:visible', false);
|
||||
emit('cancel', false);
|
||||
};
|
||||
|
||||
const fetchData = async () => {
|
||||
|
@ -95,4 +96,10 @@
|
|||
fetchData();
|
||||
}
|
||||
);
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
currentVisible.value = visible;
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
|
|
@ -149,7 +149,7 @@
|
|||
dataIndex: 'description',
|
||||
},
|
||||
{
|
||||
title: 'system.organization.createUser',
|
||||
title: 'system.organization.creator',
|
||||
dataIndex: 'createUser',
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<MsDrawer
|
||||
:width="680"
|
||||
:visible="props.visible"
|
||||
:visible="currentVisible"
|
||||
unmount-on-close
|
||||
:footer="false"
|
||||
:title="t('system.organization.addMember')"
|
||||
|
@ -20,9 +20,14 @@
|
|||
@press-enter="searchUser"
|
||||
></a-input-search>
|
||||
</div>
|
||||
<ms-base-table class="mt-[16px]" v-bind="propsRes" v-on="propsEvent" />
|
||||
<ms-base-table class="mt-[16px]" v-bind="propsRes" v-on="propsEvent">
|
||||
<template #operation="{ record }">
|
||||
<ms-button @click="handleRemove(record)">{{ t('system.organization.remove') }}</ms-button>
|
||||
</template>
|
||||
</ms-base-table>
|
||||
</div>
|
||||
</MsDrawer>
|
||||
<AddUserModal :organization-id="props.organizationId" :visible="userVisible" @cancel="handleHideUserModal" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -33,6 +38,9 @@
|
|||
import { watch, ref } from 'vue';
|
||||
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||
import AddUserModal from './addUserModal.vue';
|
||||
import { TableData } from '@arco-design/web-vue';
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
|
||||
export interface projectDrawerProps {
|
||||
visible: boolean;
|
||||
|
@ -41,32 +49,29 @@
|
|||
const { t } = useI18n();
|
||||
const props = defineProps<projectDrawerProps>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', v: boolean): void;
|
||||
(e: 'cancel'): void;
|
||||
}>();
|
||||
|
||||
const currentVisible = ref(props.visible);
|
||||
|
||||
const userVisible = ref(false);
|
||||
|
||||
const keyword = ref('');
|
||||
|
||||
const projectColumn: MsTableColumn = [
|
||||
{
|
||||
title: 'system.organization.ID',
|
||||
dataIndex: 'num',
|
||||
},
|
||||
{
|
||||
title: 'system.project.name',
|
||||
title: 'system.organization.userName',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: 'system.organization.status',
|
||||
dataIndex: 'enable',
|
||||
title: 'system.organization.email',
|
||||
dataIndex: 'email',
|
||||
},
|
||||
{
|
||||
title: 'system.organization.creator',
|
||||
dataIndex: 'createUser',
|
||||
},
|
||||
{
|
||||
title: 'system.organization.createTime',
|
||||
dataIndex: 'createTime',
|
||||
title: 'system.organization.phone',
|
||||
dataIndex: 'phone',
|
||||
},
|
||||
{ title: 'system.organization.operation', dataIndex: 'operation' },
|
||||
];
|
||||
|
||||
const { propsRes, propsEvent, loadList, setLoadListParams, setKeyword } = useTable(postUserTableByOrgId, {
|
||||
|
@ -84,7 +89,7 @@
|
|||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
emit('update:visible', false);
|
||||
emit('cancel');
|
||||
};
|
||||
|
||||
const fetchData = async () => {
|
||||
|
@ -92,8 +97,17 @@
|
|||
};
|
||||
|
||||
const handleAddMember = () => {
|
||||
// TODO add member
|
||||
emit('update:visible', false);
|
||||
userVisible.value = true;
|
||||
};
|
||||
|
||||
const handleHideUserModal = () => {
|
||||
userVisible.value = false;
|
||||
};
|
||||
|
||||
const handleRemove = (record: TableData) => {
|
||||
// TODO: remove user
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(record);
|
||||
};
|
||||
|
||||
watch(
|
||||
|
@ -103,4 +117,10 @@
|
|||
fetchData();
|
||||
}
|
||||
);
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
currentVisible.value = visible;
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
|
|
@ -6,6 +6,7 @@ export default {
|
|||
'system.organization.edit': '编辑',
|
||||
'system.organization.save': '保存',
|
||||
'system.organization.end': '结束',
|
||||
'system.organization.remove': '移除',
|
||||
'system.organization.addMember': '添加成员',
|
||||
'system.organization.addMemberPlaceholder': '请选择成员',
|
||||
'system.organization.addMemberRequired': '请选择成员',
|
||||
|
@ -32,4 +33,7 @@ export default {
|
|||
'system.organization.projectCount': '项目({count})',
|
||||
'system.organization.projectName': '项目({name})',
|
||||
'system.project.name': '项目名称',
|
||||
'system.organization.userName': '姓名',
|
||||
'system.organization.email': '邮箱',
|
||||
'system.organization.phone': '手机',
|
||||
};
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<template>
|
||||
<a-modal
|
||||
v-model:visible="currentVisible"
|
||||
v-model="currentVisible"
|
||||
class="ms-modal-form ms-modal-medium"
|
||||
width="680px"
|
||||
text-align="start"
|
||||
:ok-text="t('system.userGroup.add')"
|
||||
unmount-on-close
|
||||
:ok-loading="loading"
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||
import useUserGroupStore from '@/store/modules/setting/usergroup';
|
||||
|
@ -48,6 +48,14 @@
|
|||
|
||||
const store = useUserGroupStore();
|
||||
const couldShowUser = computed(() => store.userGroupInfo.currentType === 'SYSTEM');
|
||||
watch(
|
||||
() => couldShowUser,
|
||||
(val) => {
|
||||
if (!val) {
|
||||
currentTable.value = 'auth';
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
Loading…
Reference in New Issue