feat: 系统设置-组织-成员页面搭建

This commit is contained in:
xinxin.wu 2023-07-05 16:12:56 +08:00 committed by fit2-zhao
parent d653f9f483
commit cfd3737321
14 changed files with 591 additions and 1 deletions

View File

@ -13,7 +13,7 @@ export default mergeConfig(
},
proxy: {
'/front': {
target: 'http://101.43.186.75:8081/',
target: 'http://172.16.200.18:8081/',
changeOrigin: true,
rewrite: (path: string) => path.replace(/^\/front/, ''),
},

View File

@ -0,0 +1,12 @@
import MSR from '@/api/http/index';
import { GetMemberListUrl, AddMemberUrl } from '@/api/requrls/system/member';
import type { UserListItem, CreateUserParams } from '@/models/system/user';
import type { TableQueryParams } from '@/models/common';
export function getMemberList(data: TableQueryParams) {
return MSR.post<UserListItem[]>({ url: GetMemberListUrl, data });
}
export function batchCreateUser(data: CreateUserParams) {
return MSR.post({ url: AddMemberUrl, data });
}

View File

@ -0,0 +1,2 @@
export const GetMemberListUrl = '/member/page';
export const AddMemberUrl = '/member/add';

View File

@ -21,6 +21,7 @@ export default {
'menu.settings': 'System Settings',
'menu.settings.system': 'System',
'menu.settings.organization': 'Organization',
'menu.settings.organization.member': 'Member',
'menu.settings.system.usergroup': 'User Group',
'menu.settings.system.user': 'User',
'menu.settings.system.organizationAndProject': 'Org & Project',

View File

@ -21,6 +21,7 @@ export default {
'menu.settings': '系统设置',
'menu.settings.system': '系统',
'menu.settings.organization': '组织',
'menu.settings.organization.member': '成员',
'menu.settings.system.user': '用户',
'menu.settings.system.usergroup': '用户组',
'menu.settings.system.organizationAndProject': '组织与项目',

View File

@ -6,6 +6,7 @@ import './api-test';
import './system/user';
import './system/project';
import './system/resourcePool';
import './system/member';
Mock.setup({
timeout: '600-1000',

View File

@ -0,0 +1,259 @@
import Mock from 'mockjs';
import setupMock, { successTableResponseWrap } from '@/utils/setup-mock';
const getMemberList = () => {
return [
{
id: '103423',
name: '成员1',
email: 'dehihu@kds.sd',
enable: true,
createTime: 1686905750716,
updateTime: 0,
lastOrganizationId: 'string',
phone: '18473647583',
source: 'string',
lastProjectId: 'string',
createUser: 'string',
updateUser: 'string',
projectList: [
{
id: 'string',
num: 0,
name: '项目 1',
description: 'blabla',
createTime: 0,
updateTime: 0,
createUser: 'string',
updateUser: 'string',
deleted: true,
deleteUser: 'string',
deleteTime: 0,
enable: true,
},
{
id: 'string',
num: 0,
name: '项目 2',
description: 'blabla',
createTime: 0,
updateTime: 0,
createUser: 'string',
updateUser: 'string',
deleted: true,
deleteUser: 'string',
deleteTime: 0,
enable: true,
},
{
id: 'string',
num: 0,
name: '项目 3',
description: 'blabla',
createTime: 0,
updateTime: 0,
createUser: 'string',
updateUser: 'string',
deleted: true,
deleteUser: 'string',
deleteTime: 0,
enable: true,
},
{
id: 'string',
num: 0,
name: '项目 4',
description: 'blabla',
createTime: 0,
updateTime: 0,
createUser: 'string',
updateUser: 'string',
deleted: true,
deleteUser: 'string',
deleteTime: 0,
enable: true,
},
],
userRoleList: [
{
id: 'string',
name: '角色 1',
description: 'sdadasd',
internal: true,
type: 'string',
createTime: 0,
updateTime: 0,
createUser: 'string',
scopeId: 'string',
pos: 0,
},
{
id: 'string',
name: '角色 2',
description: 'sdadasd',
internal: true,
type: 'string',
createTime: 0,
updateTime: 0,
createUser: 'string',
scopeId: 'string',
pos: 0,
},
{
id: 'string',
name: '角色 3',
description: 'sdadasd',
internal: true,
type: 'string',
createTime: 0,
updateTime: 0,
createUser: 'string',
scopeId: 'string',
pos: 0,
},
{
id: 'string',
name: '角色 4',
description: 'sdadasd',
internal: true,
type: 'string',
createTime: 0,
updateTime: 0,
createUser: 'string',
scopeId: 'string',
pos: 0,
},
],
},
{
id: '103233',
name: '成员2',
email: 'dehihu@kds.sd',
enable: true,
createTime: 1686905750716,
updateTime: 0,
lastOrganizationId: 'string',
phone: '18473647583',
source: 'string',
lastProjectId: 'string',
createUser: 'string',
updateUser: 'string',
projectList: [
{
id: 'string',
num: 0,
name: '项目 1',
description: 'blabla',
createTime: 0,
updateTime: 0,
createUser: 'string',
updateUser: 'string',
deleted: true,
deleteUser: 'string',
deleteTime: 0,
enable: true,
},
{
id: 'string',
num: 0,
name: '项目 2',
description: 'blabla',
createTime: 0,
updateTime: 0,
createUser: 'string',
updateUser: 'string',
deleted: true,
deleteUser: 'string',
deleteTime: 0,
enable: true,
},
{
id: 'string',
num: 0,
name: '组织 3',
description: 'blabla',
createTime: 0,
updateTime: 0,
createUser: 'string',
updateUser: 'string',
deleted: true,
deleteUser: 'string',
deleteTime: 0,
enable: true,
},
{
id: 'string',
num: 0,
name: '项目 4',
description: 'blabla',
createTime: 0,
updateTime: 0,
createUser: 'string',
updateUser: 'string',
deleted: true,
deleteUser: 'string',
deleteTime: 0,
enable: true,
},
],
userRoleList: [
{
id: 'string',
name: '角色 1',
description: 'sdadasd',
internal: true,
type: 'string',
createTime: 0,
updateTime: 0,
createUser: 'string',
scopeId: 'string',
pos: 0,
},
{
id: 'string',
name: '角色 2',
description: 'sdadasd',
internal: true,
type: 'string',
createTime: 0,
updateTime: 0,
createUser: 'string',
scopeId: 'string',
pos: 0,
},
{
id: 'string',
name: '角色 3',
description: 'sdadasd',
internal: true,
type: 'string',
createTime: 0,
updateTime: 0,
createUser: 'string',
scopeId: 'string',
pos: 0,
},
{
id: 'string',
name: '角色 4',
description: 'sdadasd',
internal: true,
type: 'string',
createTime: 0,
updateTime: 0,
createUser: 'string',
scopeId: 'string',
pos: 0,
},
],
},
];
};
setupMock({
setup: () => {
Mock.mock(new RegExp('/member/page'), () => {
return successTableResponseWrap(getMemberList());
});
},
});

View File

@ -0,0 +1,4 @@
export interface AddMemberForm {
members: string[];
userGroups: string;
}

View File

@ -81,6 +81,29 @@ const System: AppRouteRecordRaw = {
},
],
},
{
path: 'organization',
name: 'settingOrganization',
redirect: '/setting/organization/member',
component: null,
meta: {
locale: 'menu.settings.organization',
roles: ['*'],
hideChildrenInMenu: true,
},
children: [
{
path: 'member',
name: 'settingOrganizationMember',
component: () => import('@/views/organization/member/index.vue'),
meta: {
locale: 'menu.settings.organization.member',
roles: ['*'],
isTopMenu: true,
},
},
],
},
],
};

View File

@ -0,0 +1,109 @@
<template>
<a-modal
v-model:visible="memberVisible"
title-align="start"
width="680px"
ok-text="保存"
@ok="handelOk"
@cancel="handleCancel"
>
<template #title> {{ t('organization.member.addMember') }} </template>
<div class="form">
<a-form :model="form" size="large" :style="{ width: '600px' }" layout="vertical">
<a-form-item
v-model="form.members"
field="members"
:label="t('organization.member.member')"
asterisk-position="end"
:rules="[{ required: true, message: t('organization.member.pleaseSelectMember') }]"
>
<a-select
v-model="form.members"
multiple
:placeholder="t('organization.member.selectMemberScope')"
allow-clear
>
<a-option v-for="item of memberList" :key="item.value">{{ item.label }}</a-option>
</a-select>
</a-form-item>
<a-form-item
v-model="form.userGroups"
field="userGroups"
:label="t('organization.member.tableColunmUsergroup')"
asterisk-position="end"
:rules="[{ required: true }]"
>
<a-select v-model="form.userGroups">
<a-option v-for="item of userGroupOptions" :key="item.value">{{ item.label }}</a-option>
</a-select>
</a-form-item>
</a-form>
</div>
</a-modal>
</template>
<script setup lang="ts">
import { ref, watchEffect, reactive } from 'vue';
import { useI18n } from '@/hooks/useI18n';
import type { AddMemberForm } from '@/models/system/member';
const { t } = useI18n();
const emit = defineEmits<{
(e: 'cancel'): void;
}>();
const props = defineProps<{
visible: boolean;
}>();
const userGroupOptions = ref([
{
label: 'Beijing',
value: 'Beijing',
},
{
label: 'Shanghai',
value: 'Shanghai',
},
{
label: 'Guangzhou',
value: 'Guangzhou',
},
]);
const memberList = ref([
{
label: 'Beijing',
value: 'Beijing',
},
{
label: 'Shanghai',
value: 'Shanghai',
},
{
label: 'Guangzhou',
value: 'Guangzhou',
},
]);
const memberVisible = ref<boolean>(props.visible);
const form = reactive<AddMemberForm>({
userGroups: '',
members: [],
});
watchEffect(() => {
memberVisible.value = props.visible;
});
const handelOk = () => {
// eslint-disable-next-line no-console
console.log('ok');
// eslint-disable-next-line no-use-before-define
handleCancel();
};
const handleCancel = () => {
emit('cancel');
};
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,140 @@
<template>
<div>
<div class="mb-4 flex items-center justify-between">
<div>
<a-button class="mr-3" type="primary" @click="AddMember">{{ t('organization.member.addMember') }}</a-button>
</div>
<a-input-search :placeholder="t('organization.member.searchMember')" class="w-[230px]"></a-input-search>
</div>
<ms-base-table
v-bind="propsRes"
:action-config="tableBatchActions"
@selected-change="handleTableSelect"
v-on="propsEvent"
>
<template #project="{ record }">
<a-tag v-for="pro of record.projectList.slice(0, 2)" :key="pro.id" class="mr-[4px] bg-transparent" bordered>
{{ pro.name }}
</a-tag>
</template>
<template #userRole="{ record }">
<a-tag
v-for="org of record.userRoleList.slice(0, 2)"
:key="org.id"
class="mr-[4px] border-[rgb(var(--primary-5))] bg-transparent !text-[rgb(var(--primary-5))]"
bordered
>
{{ org.name }}
</a-tag>
</template>
<template #enable="{ record }">
<div v-if="record.enable" class="flex items-center">
<icon-check-circle-fill class="mr-[2px] text-[rgb(var(--success-6))]" />
{{ t('organization.member.tableEnable') }}
</div>
<div v-else class="flex items-center text-[var(--color-text-4)]">
<icon-stop class="mr-[2px]" />
{{ t('organization.member.tableDisable') }}
</div>
</template>
<template #action="{ record }">
<MsButton @click="deleteMember(record)">{{ t('organization.member.remove') }}</MsButton>
</template>
</ms-base-table>
<add-member-modal :visible="addMemberVisible" @cancel="addMemberVisible = false" />
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { useI18n } from '@/hooks/useI18n';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
import MsButton from '@/components/pure/ms-button/index.vue';
import useTable from '@/components/pure/ms-table/useTable';
import addMemberModal from './components/addMemberModal.vue';
import { getMemberList } from '@/api/modules/system/member';
import type { MsTableColumn } from '@/components/pure/ms-table/type';
const columns: MsTableColumn = [
{
title: 'organization.member.tableColunmEmail',
dataIndex: 'email',
width: 200,
},
{
title: 'organization.member.tableColunmName',
dataIndex: 'name',
},
{
title: 'organization.member.tableColunmPhone',
dataIndex: 'phone',
},
{
title: 'organization.member.tableColunmPro',
slotName: 'project',
dataIndex: 'projectList',
width: 250,
},
{
title: 'organization.member.tableColunmUsergroup',
slotName: 'userRole',
dataIndex: 'userRoleList',
width: 250,
},
{
title: 'organization.member.tableColunmStatus',
slotName: 'enable',
dataIndex: 'enable',
},
{
title: 'organization.member.tableColunmActions',
slotName: 'action',
fixed: 'right',
width: 80,
},
];
const tableBatchActions = {
baseAction: [
{
label: 'organization.member.batchActionAddProject',
eventTag: 'batchAddProject',
},
{
label: 'organization.member.batchActionAddUsergroup',
eventTag: 'batchAddUsergroup',
},
],
};
const { propsRes, propsEvent, loadList, setKeyword } = useTable(getMemberList, {
columns,
scroll: { y: 'auto', x: 1200 },
selectable: true,
});
const keyword = ref('');
const addMemberVisible = ref<boolean>(false);
onMounted(async () => {
setKeyword(keyword.value);
await loadList();
});
const { t } = useI18n();
function deleteMember(record: any) {
console.log(record, 1);
}
const tableSelected = ref<(string | number)[]>([]);
function handleTableSelect(selectArr: (string | number)[]) {
tableSelected.value = selectArr;
}
function AddMember() {
addMemberVisible.value = true;
}
</script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,19 @@
export default {
'organization.member.addMember': 'Add Member',
'organization.member.searchMember': 'Search by name or email address',
'organization.member.remove': 'Remove',
'organization.member.batchActionAddProject': 'dd to project',
'organization.member.batchActionAddUsergroup': 'Add to usergroup',
'organization.member.tableEnable': 'Enabled',
'organization.member.tableDisable': 'Disabled',
'organization.member.tableColunmEmail': 'Email',
'organization.member.tableColunmName': 'Name',
'organization.member.tableColunmPhone': 'Phone',
'organization.member.tableColunmPro': 'Project',
'organization.member.tableColunmUsergroup': 'UserGroup',
'organization.member.tableColunmStatus': 'Status',
'organization.member.tableColunmActions': 'Actions',
'organization.member.member': 'Member',
'organization.member.selectMemberScope': 'Select the member you want to add. Multiple selection is supported',
'organization.member.pleaseSelectMember': 'Please select user',
};

View File

@ -0,0 +1,19 @@
export default {
'organization.member.addMember': '添加成员',
'organization.member.searchMember': '通过名称或邮箱搜索搜索',
'organization.member.remove': '移除',
'organization.member.batchActionAddProject': '添加至项目',
'organization.member.batchActionAddUsergroup': '添加至用户组',
'organization.member.tableEnable': '正常',
'organization.member.tableDisable': '禁用',
'organization.member.tableColunmEmail': '邮箱',
'organization.member.tableColunmName': '姓名',
'organization.member.tableColunmPhone': '手机',
'organization.member.tableColunmPro': '项目',
'organization.member.tableColunmUsergroup': '用户组',
'organization.member.tableColunmStatus': '状态',
'organization.member.tableColunmActions': '操作',
'organization.member.member': '成员',
'organization.member.selectMemberScope': '请选择需要添加的成员支持多选',
'organization.member.pleaseSelectMember': '请选择成员',
};