feat(系统设置): 系统组织与用户修改组织&撤销删除

This commit is contained in:
RubyLiu 2023-08-15 14:58:34 +08:00 committed by 刘瑞斌
parent e5fa9b4383
commit f536854655
9 changed files with 162 additions and 21 deletions

View File

@ -2,17 +2,28 @@ import MSR from '@/api/http/index';
import * as orgUrl from '@/api/requrls/setting/system/organizationAndProject';
import { TableQueryParams } from '@/models/common';
import { AddUserToOrgOrProjectParams } from '@/models/setting/systemOrg';
import { CreateOrUpdateSystemOrgParams } from '@/models/setting/system/orgAndProject';
// 获取组织列表
export function postOrgTable(data: TableQueryParams) {
return MSR.post({ url: orgUrl.postOrgTableUrl, data });
}
// 创建或修改组织
export function createOrUpdateOrg(data: CreateOrUpdateSystemOrgParams) {
return MSR.post({ url: data.id ? orgUrl.postModifyOrgUrl : orgUrl.postAddOrgUrl, data });
}
// 删除组织
export function deleteOrg(id: string) {
return MSR.get({ url: `${orgUrl.getDeleteOrgUrl}${id}` });
}
// 撤销删除组织
export function revokeDeleteOrg(id: string) {
return MSR.get({ url: `${orgUrl.getRecoverOrgUrl}${id}` });
}
// 启用或禁用组织
export function enableOrDisableOrg(id: string, isEnable = true) {
return MSR.get({ url: `${isEnable ? orgUrl.getEnableOrgUrl : orgUrl.getDisableOrgUrl}${id}` });

View File

@ -12,6 +12,13 @@ export default {
'common.retry': 'Retry',
'common.end': 'End',
'common.enable': 'Enable',
'common.close': 'Close',
'common.confirmEnable': 'Confirm enable',
'common.confirmClose': 'Confirm close',
'common.enableSuccess': 'Enable success',
'common.enableFailed': 'Enable failed',
'common.closeSuccess': 'Close success',
'common.closeFailed': 'Close failed',
'common.all': 'All',
'common.operation': 'Operation',
'common.remove': 'Remove',
@ -30,4 +37,6 @@ export default {
'common.removeSuccess': 'Remove success',
'common.removeFailed': 'Remove failed',
'common.admin': 'Admin',
'common.revokeDelete': 'Revoke delete',
'common.revokeDeleteSuccess': 'Revoke delete success',
};

View File

@ -12,6 +12,13 @@ export default {
'common.retry': '重试',
'common.end': '结束',
'common.enable': '启用',
'common.close': '关闭',
'common.confirmEnable': '确认启用',
'common.confirmClose': '确认关闭',
'common.enableSuccess': '启用成功',
'common.enableFailed': '启用失败',
'common.closeSuccess': '关闭成功',
'common.closeFailed': '关闭失败',
'common.all': '全部',
'common.operation': '操作',
'common.remove': '移除',
@ -30,4 +37,6 @@ export default {
'common.removeSuccess': '移除成功',
'common.removeFailed': '移除失败',
'common.admin': '管理员',
'common.revokeDelete': '撤销删除',
'common.revokeDeleteSuccess': '已撤销删除',
};

View File

@ -0,0 +1,6 @@
export interface CreateOrUpdateSystemOrgParams {
id?: string;
name: string;
description: string;
memberIds: string[];
}

View File

@ -19,7 +19,10 @@
<a-input v-model="form.name" :placeholder="t('system.organization.organizationNamePlaceholder')" />
</a-form-item>
<a-form-item field="name" :label="t('system.organization.organizationAdmin')">
<MsUserSelector v-model:value="form.admin" placeholder="system.organization.organizationAdminPlaceholder" />
<MsUserSelector
v-model:value="form.memberIds"
placeholder="system.organization.organizationAdminPlaceholder"
/>
</a-form-item>
<a-form-item field="description" :label="t('system.organization.description')">
<a-input v-model="form.description" :placeholder="t('system.organization.descriptionPlaceholder')" />
@ -34,11 +37,14 @@
import { reactive, ref, watchEffect } from 'vue';
import type { FormInstance, ValidatedError } from '@arco-design/web-vue';
import MsUserSelector from '@/components/bussiness/ms-user-selector/index.vue';
import { createOrUpdateOrg } from '@/api/modules/setting/system/organizationAndProject';
import { Message } from '@arco-design/web-vue';
import { CreateOrUpdateSystemOrgParams } from '@/models/setting/system/orgAndProject';
const { t } = useI18n();
const props = defineProps<{
visible: boolean;
organizationId?: string;
currentOrganization?: CreateOrUpdateSystemOrgParams;
}>();
const formRef = ref<FormInstance>();
@ -47,9 +53,9 @@
(e: 'cancel'): void;
}>();
const form = reactive({
const form = reactive<{ name: string; memberIds: string[]; description: string }>({
name: '',
admin: [],
memberIds: [],
description: '',
});
@ -63,11 +69,31 @@
};
const handleBeforeOk = () => {
formRef.value?.validate((errors: undefined | Record<string, ValidatedError>) => {
formRef.value?.validate(async (errors: undefined | Record<string, ValidatedError>) => {
if (errors) {
return false;
}
try {
await createOrUpdateOrg({ id: props.currentOrganization?.id, ...form });
Message.success(
props.currentOrganization?.id
? t('system.organization.updateOrganizationSuccess')
: t('system.organization.createOrganizationSuccess')
);
handleCancel();
return true;
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
return false;
}
});
};
watchEffect(() => {
if (props.currentOrganization) {
form.name = props.currentOrganization.name;
form.memberIds = props.currentOrganization.memberIds;
form.description = props.currentOrganization.description;
}
});
</script>

View File

@ -1,5 +1,15 @@
<template>
<MsBaseTable v-bind="propsRes" v-on="propsEvent">
<template #name="{ record }">
<span>{{ record.name }}</span>
<a-tooltip background-color="#FFFFFF">
<template #content>
<span class="text-[var(--color-text-1)]">{{ t('system.organization.revokeDeleteToolTip') }}</span>
<MsButton class="ml-[8px]" @click="handleRevokeDelete(record)">{{ t('common.revokeDelete') }}</MsButton>
</template>
<MsIcon v-if="record.deleted" type="icon-icon_alarm_clock" class="ml-[4px] text-[rgb(var(--danger-6))]" />
</a-tooltip>
</template>
<template #creator="{ record }">
<span>{{ record.createUser }}</span>
<span v-if="record.orgAdmins.length > 0" class="text-[var(--color-text-4)]">{{
@ -13,7 +23,10 @@
<span class="primary-color" @click="showProjectDrawer(record)">{{ record.projectCount }}</span>
</template>
<template #operation="{ record }">
<template v-if="!record.enable">
<template v-if="record.deleted">
<MsButton @click="handleRevokeDelete(record)">{{ t('common.revokeDelete') }}</MsButton>
</template>
<template v-else-if="!record.enable">
<MsButton @click="handleEnableOrDisableOrg(record)">{{ t('common.enable') }}</MsButton>
<MsButton @click="handleDelete(record)">{{ t('common.delete') }}</MsButton>
</template>
@ -25,7 +38,12 @@
</template>
</template>
</MsBaseTable>
<AddOrganizationModal type="edit" :visible="orgVisible" @cancel="handleAddOrgModalCancel" />
<AddOrganizationModal
type="edit"
:current-organization="currentUpdateOrganization"
:visible="orgVisible"
@cancel="handleAddOrgModalCancel"
/>
<AddUserModal :organization-id="currentOrganizationId" :visible="userVisible" @cancel="handleAddUserModalCancel" />
<ProjectDrawer v-bind="currentProjectDrawer" @cancel="handleProjectDrawerCancel" />
<UserDrawer v-bind="currentUserDrawer" @cancel="handleUserDrawerCancel" />
@ -38,7 +56,12 @@
import { useTableStore } from '@/store';
import { ref, reactive, watch } from 'vue';
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
import { postOrgTable, deleteOrg, enableOrDisableOrg } from '@/api/modules/setting/system/organizationAndProject';
import {
postOrgTable,
deleteOrg,
enableOrDisableOrg,
revokeDeleteOrg,
} from '@/api/modules/setting/system/organizationAndProject';
import { TableKeyEnum } from '@/enums/tableEnum';
import { MsTableColumn } from '@/components/pure/ms-table/type';
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
@ -49,6 +72,7 @@
import UserDrawer from './userDrawer.vue';
import AddUserModal from './addUserModal.vue';
import useModal from '@/hooks/useModal';
import { CreateOrUpdateSystemOrgParams } from '@/models/setting/system/orgAndProject';
export interface SystemOrganizationProps {
keyword: string;
@ -61,18 +85,19 @@
const userVisible = ref(false);
const orgVisible = ref(false);
const currentOrganizationId = ref('');
const { deleteModal } = useModal();
const currentUpdateOrganization = ref<CreateOrUpdateSystemOrgParams>();
const { deleteModal, openModal } = useModal();
const organizationColumns: MsTableColumn = [
{
title: 'system.organization.ID',
dataIndex: 'num',
width: 100,
ellipsis: true,
},
{
title: 'system.organization.name',
dataIndex: 'name',
slotName: 'name',
editable: true,
},
{
title: 'system.organization.member',
@ -168,19 +193,38 @@
};
const handleEnableOrDisableOrg = async (record: any, isEnable = true) => {
const title = isEnable ? t('system.organization.enableTitle') : t('system.organization.enableTitle');
const content = isEnable ? t('system.organization.enableContent') : t('system.organization.endContent');
const okText = isEnable ? t('common.confirmEnable') : t('common.confirmClose');
openModal({
type: 'warning',
cancelText: t('common.cancel'),
title,
content,
okText,
onBeforeOk: async () => {
try {
await enableOrDisableOrg(record.id, isEnable);
Message.success(t('common.updateSuccess'));
Message.success(isEnable ? t('common.enableSuccess') : t('common.closeSuccess'));
fetchData();
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
}
},
hideCancel: false,
});
};
const showOrganizationModal = (record: any) => {
currentOrganizationId.value = record.id;
orgVisible.value = true;
currentUpdateOrganization.value = {
id: record.id,
name: record.name,
description: record.description,
memberIds: record.orgAdmins.map((item: any) => item.id) || [],
};
};
const showAddUserModal = (record: any) => {
@ -190,6 +234,7 @@
const handleProjectDrawerCancel = () => {
currentProjectDrawer.visible = false;
fetchData();
};
const showProjectDrawer = (record: TableData) => {
@ -205,13 +250,27 @@
const handleUserDrawerCancel = () => {
currentUserDrawer.visible = false;
fetchData();
};
const handleAddUserModalCancel = () => {
userVisible.value = false;
fetchData();
};
const handleAddOrgModalCancel = () => {
orgVisible.value = false;
fetchData();
};
const handleRevokeDelete = async (record: TableData) => {
try {
await revokeDeleteOrg(record.id);
Message.success(t('common.revokeDeleteSuccess'));
fetchData();
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
}
};
watch(

View File

@ -21,6 +21,12 @@
></a-input-search>
</div>
<ms-base-table class="mt-[16px]" v-bind="propsRes" v-on="propsEvent">
<template #name="{ record }">
<span>{{ record.name }}</span>
<span v-if="record.adminFlag" class="ml-[4px] text-[var(--color-text-4)]">{{
`(${t('common.admin')})`
}}</span>
</template>
<template #operation="{ record }">
<MsRemoveButton
:title="t('system.organization.removeName', { name: record.name })"
@ -68,7 +74,7 @@
const projectColumn: MsTableColumn = [
{
title: 'system.organization.userName',
dataIndex: 'name',
slotName: 'name',
},
{
title: 'system.organization.email',

View File

@ -43,4 +43,12 @@ export default {
'system.organization.deleteName': 'Are you sure to delete {name}',
'system.organization.deleteTip':
'Delete the organization and delete the project data under that organization together. Please be cautious!',
'system.organization.revokeDeleteToolTip': 'The organization will be deleted automatically after 30 days',
'system.organization.createOrganizationSuccess': 'Create organization success',
'system.organization.enableTitle': 'Start organization',
'system.organization.endTitle': 'Close organization',
'system.organization.enableContent': 'The organization after opening is displayed in the organization switching list',
'system.organization.endContent':
'The organization after closing is not displayed in the organization switching list',
'system.organization.updateOrganizationSuccess': 'Update organization success',
};

View File

@ -40,4 +40,11 @@ export default {
'system.organization.addSuccess': '添加成功',
'system.organization.deleteName': '确认删除 {name} 这个组织吗',
'system.organization.deleteTip': '删除组织同时将该组织下的项目数据一起删除,请谨慎操作!',
'system.organization.revokeDeleteToolTip': '该组织将与 30 天后自动删除',
'system.organization.createOrganizationSuccess': '创建组织成功',
'system.organization.enableTitle': '开启组织',
'system.organization.endTitle': '关闭组织',
'system.organization.enableContent': '开启后的组织展示在组织切换列表',
'system.organization.endContent': '关闭后的组织不展示在组织切换列表',
'system.organization.updateOrganizationSuccess': '更新组织成功',
};