feat(系统设置): 用户邀请
This commit is contained in:
parent
6e1229b332
commit
409f1538a3
|
@ -14,6 +14,8 @@ import {
|
||||||
GetOrgsUrl,
|
GetOrgsUrl,
|
||||||
GetProjectsUrl,
|
GetProjectsUrl,
|
||||||
GetUserInfoUrl,
|
GetUserInfoUrl,
|
||||||
|
InviteUserUrl,
|
||||||
|
RegisterByInviteUrl,
|
||||||
} from '@/api/requrls/setting/user';
|
} from '@/api/requrls/setting/user';
|
||||||
import type {
|
import type {
|
||||||
UserListItem,
|
UserListItem,
|
||||||
|
@ -27,6 +29,8 @@ import type {
|
||||||
BatchAddParams,
|
BatchAddParams,
|
||||||
ResetUserPasswordParams,
|
ResetUserPasswordParams,
|
||||||
OrgsItem,
|
OrgsItem,
|
||||||
|
InviteUserParams,
|
||||||
|
RegisterByInviteParams,
|
||||||
} from '@/models/setting/user';
|
} from '@/models/setting/user';
|
||||||
import type { CommonList, TableQueryParams } from '@/models/common';
|
import type { CommonList, TableQueryParams } from '@/models/common';
|
||||||
|
|
||||||
|
@ -100,3 +104,13 @@ export function getSystemOrgs() {
|
||||||
export function getSystemProjects() {
|
export function getSystemProjects() {
|
||||||
return MSR.get<OrgsItem[]>({ url: GetProjectsUrl });
|
return MSR.get<OrgsItem[]>({ url: GetProjectsUrl });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 邀请用户
|
||||||
|
export function inviteUser(data: InviteUserParams) {
|
||||||
|
return MSR.post({ url: InviteUserUrl, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户注册
|
||||||
|
export function registerByInvite(data: RegisterByInviteParams) {
|
||||||
|
return MSR.post({ url: RegisterByInviteUrl, data });
|
||||||
|
}
|
||||||
|
|
|
@ -26,3 +26,7 @@ export const BatchAddOrgUrl = '/system/user/add-org-member';
|
||||||
export const GetOrgsUrl = '/system/user/get/organization';
|
export const GetOrgsUrl = '/system/user/get/organization';
|
||||||
// 查找项目
|
// 查找项目
|
||||||
export const GetProjectsUrl = '/system/user/get/project';
|
export const GetProjectsUrl = '/system/user/get/project';
|
||||||
|
// 用户注册
|
||||||
|
export const RegisterByInviteUrl = '/system/user/register-by-invite';
|
||||||
|
// 邀请用户
|
||||||
|
export const InviteUserUrl = '/system/user/invite';
|
||||||
|
|
|
@ -108,3 +108,15 @@ export interface OrgsItem {
|
||||||
children?: OrgsItem[];
|
children?: OrgsItem[];
|
||||||
leafNode: boolean;
|
leafNode: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface InviteUserParams {
|
||||||
|
inviteEmails: string[];
|
||||||
|
userRoleIds: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RegisterByInviteParams {
|
||||||
|
inviteId: string;
|
||||||
|
name: string;
|
||||||
|
password: string;
|
||||||
|
phone: string;
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Recordable } from '#/global';
|
import JSEncrypt from 'jsencrypt';
|
||||||
import { isObject } from './is';
|
import { isObject } from './is';
|
||||||
|
|
||||||
type TargetContext = '_self' | '_parent' | '_blank' | '_top';
|
type TargetContext = '_self' | '_parent' | '_blank' | '_top';
|
||||||
|
@ -247,3 +247,16 @@ export function getFilterList(targetMap: Record<string, any>[], sourceMap: Recor
|
||||||
});
|
});
|
||||||
return filteredData;
|
return filteredData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密
|
||||||
|
* @param input 输入的字符串
|
||||||
|
* @param publicKey 公钥
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function encrypted(input: string) {
|
||||||
|
const publicKey = localStorage.getItem('salt') || '';
|
||||||
|
const encrypt = new JSEncrypt({ default_key_size: '1024' });
|
||||||
|
encrypt.setPublicKey(publicKey);
|
||||||
|
return encrypt.encrypt(input);
|
||||||
|
}
|
||||||
|
|
|
@ -2,10 +2,14 @@
|
||||||
<div class="invite-page">
|
<div class="invite-page">
|
||||||
<div class="form-box w-1/3 rounded-[12px] bg-white">
|
<div class="form-box w-1/3 rounded-[12px] bg-white">
|
||||||
<div class="form-box-title">{{ t('invite.title') }}</div>
|
<div class="form-box-title">{{ t('invite.title') }}</div>
|
||||||
<a-form class="p-[24px_40px_40px_40px]" :model="form" :rules="rules" layout="vertical" @submit="confirmInvite">
|
<a-form
|
||||||
<a-form-item field="email" class="hidden-item">
|
ref="registerFormRef"
|
||||||
<a-input v-model="form.email" :placeholder="t('invite.emailPlaceholder')" allow-clear />
|
class="p-[24px_40px_40px_40px]"
|
||||||
</a-form-item>
|
:model="form"
|
||||||
|
:rules="rules"
|
||||||
|
layout="vertical"
|
||||||
|
@submit="confirmInvite"
|
||||||
|
>
|
||||||
<a-form-item field="name" class="hidden-item">
|
<a-form-item field="name" class="hidden-item">
|
||||||
<a-input v-model="form.name" :placeholder="t('invite.namePlaceholder')" allow-clear />
|
<a-input v-model="form.name" :placeholder="t('invite.namePlaceholder')" allow-clear />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
@ -39,15 +43,15 @@
|
||||||
</template>
|
</template>
|
||||||
</a-popover>
|
</a-popover>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item field="repassword" class="hidden-item">
|
<a-form-item field="rePassword" class="hidden-item">
|
||||||
<a-input-password
|
<a-input-password
|
||||||
v-model="form.repassword"
|
v-model="form.rePassword"
|
||||||
:placeholder="t('invite.repasswordPlaceholder')"
|
:placeholder="t('invite.repasswordPlaceholder')"
|
||||||
autocomplete="new-password"
|
autocomplete="new-password"
|
||||||
allow-clear
|
allow-clear
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-button type="primary" html-type="submit">{{ t('invite.confirm') }}</a-button>
|
<a-button type="primary" :loading="loading" html-type="submit">{{ t('invite.confirm') }}</a-button>
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -55,32 +59,29 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { FormInstance, Message } from '@arco-design/web-vue';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { validateEmail, validatePasswordLength, validateWordPassword } from '@/utils/validate';
|
import { validatePasswordLength, validateWordPassword } from '@/utils/validate';
|
||||||
|
import { registerByInvite } from '@/api/modules/setting/user';
|
||||||
|
import { sleep, encrypted } from '@/utils';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const form = ref({
|
const form = ref({
|
||||||
name: '',
|
name: '',
|
||||||
email: '',
|
|
||||||
password: '',
|
password: '',
|
||||||
repassword: '',
|
rePassword: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const pswValidateRes = ref(false);
|
const pswValidateRes = ref(false);
|
||||||
const pswLengthValidateRes = ref(false);
|
const pswLengthValidateRes = ref(false);
|
||||||
|
const registerFormRef = ref<FormInstance>();
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
const rules = {
|
const rules = {
|
||||||
email: [
|
|
||||||
{ required: true, message: t('invite.emailNotNull') },
|
|
||||||
{
|
|
||||||
validator: (value: string, callback: (error?: string) => void) => {
|
|
||||||
if (!validateEmail(value)) {
|
|
||||||
callback(t('invite.emailErr'));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: [{ required: true, message: t('invite.nameNotNull') }],
|
name: [{ required: true, message: t('invite.nameNotNull') }],
|
||||||
password: [
|
password: [
|
||||||
{ required: true, message: t('invite.passwordNotNull') },
|
{ required: true, message: t('invite.passwordNotNull') },
|
||||||
|
@ -96,7 +97,16 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
repassword: [{ required: true, message: t('invite.repasswordNotNull') }],
|
rePassword: [
|
||||||
|
{ required: true, message: t('invite.repasswordNotNull') },
|
||||||
|
{
|
||||||
|
validator: (value: string, callback: (error?: string) => void) => {
|
||||||
|
if (value !== form.value.password) {
|
||||||
|
callback(t('invite.repasswordNotSame'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
function validatePsw(value: string) {
|
function validatePsw(value: string) {
|
||||||
|
@ -104,7 +114,30 @@
|
||||||
pswLengthValidateRes.value = validatePasswordLength(value);
|
pswLengthValidateRes.value = validatePasswordLength(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function confirmInvite() {}
|
function confirmInvite() {
|
||||||
|
registerFormRef.value?.validate(async (errors) => {
|
||||||
|
if (!errors) {
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
await registerByInvite({
|
||||||
|
inviteId: route.query.inviteId as string,
|
||||||
|
name: form.value.name,
|
||||||
|
password: encrypted(form.value.password) || '',
|
||||||
|
phone: '',
|
||||||
|
});
|
||||||
|
Message.success(t('invite.success'));
|
||||||
|
await sleep(300);
|
||||||
|
router.push({
|
||||||
|
name: 'login',
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -14,6 +14,7 @@ export default {
|
||||||
'invite.passwordTipTitle': 'The passwords must match both, only the following rules are supported',
|
'invite.passwordTipTitle': 'The passwords must match both, only the following rules are supported',
|
||||||
'invite.passwordLengthRule': 'The length is 8-32 digits',
|
'invite.passwordLengthRule': 'The length is 8-32 digits',
|
||||||
'invite.passwordWordRule': 'Must contain numbers and letters, Chinese or spaces are not allowed',
|
'invite.passwordWordRule': 'Must contain numbers and letters, Chinese or spaces are not allowed',
|
||||||
|
'invite.success': 'Registered successfully',
|
||||||
'personal.info': 'Personal Info',
|
'personal.info': 'Personal Info',
|
||||||
'personal.switchOrg': 'Switch Org',
|
'personal.switchOrg': 'Switch Org',
|
||||||
'personal.exit': 'Log out',
|
'personal.exit': 'Log out',
|
||||||
|
|
|
@ -14,6 +14,7 @@ export default {
|
||||||
'invite.passwordTipTitle': '密码须同时符合,仅支持以下规则',
|
'invite.passwordTipTitle': '密码须同时符合,仅支持以下规则',
|
||||||
'invite.passwordLengthRule': '长度为8-32位',
|
'invite.passwordLengthRule': '长度为8-32位',
|
||||||
'invite.passwordWordRule': '必须包含数字和字母,不允许输入中文或空格',
|
'invite.passwordWordRule': '必须包含数字和字母,不允许输入中文或空格',
|
||||||
|
'invite.success': '注册成功',
|
||||||
'personal.info': '个人信息',
|
'personal.info': '个人信息',
|
||||||
'personal.switchOrg': '切换组织',
|
'personal.switchOrg': '切换组织',
|
||||||
'personal.exit': '退出系统',
|
'personal.exit': '退出系统',
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
import { GetLoginLogoUrl } from '@/api/requrls/setting/config';
|
import { GetLoginLogoUrl } from '@/api/requrls/setting/config';
|
||||||
import type { LoginData } from '@/models/user';
|
import type { LoginData } from '@/models/user';
|
||||||
import { WorkbenchRouteEnum } from '@/enums/routeEnum';
|
import { WorkbenchRouteEnum } from '@/enums/routeEnum';
|
||||||
import JSEncrypt from 'jsencrypt';
|
import { encrypted } from '@/utils';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -100,12 +100,6 @@
|
||||||
password: 'metersphere',
|
password: 'metersphere',
|
||||||
});
|
});
|
||||||
|
|
||||||
const encrypted = (input: string, publicKey: string) => {
|
|
||||||
const encrypt = new JSEncrypt({ default_key_size: '1024' });
|
|
||||||
encrypt.setPublicKey(publicKey);
|
|
||||||
return encrypt.encrypt(input);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = async ({
|
const handleSubmit = async ({
|
||||||
errors,
|
errors,
|
||||||
values,
|
values,
|
||||||
|
@ -117,10 +111,9 @@
|
||||||
if (!errors) {
|
if (!errors) {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const publicKey = localStorage.getItem('salt') || '';
|
|
||||||
await userStore.login({
|
await userStore.login({
|
||||||
username: encrypted(values.username, publicKey),
|
username: encrypted(values.username),
|
||||||
password: encrypted(values.password, publicKey),
|
password: encrypted(values.password),
|
||||||
authenticate: values.authenticate,
|
authenticate: values.authenticate,
|
||||||
} as LoginData);
|
} as LoginData);
|
||||||
Message.success(t('login.form.login.success'));
|
Message.success(t('login.form.login.success'));
|
||||||
|
|
|
@ -73,6 +73,11 @@
|
||||||
<a-checkbox-group v-model:model-value="form.use">
|
<a-checkbox-group v-model:model-value="form.use">
|
||||||
<a-checkbox v-for="use of useList" :key="use.value" :value="use.value">{{ t(use.label) }}</a-checkbox>
|
<a-checkbox v-for="use of useList" :key="use.value" :value="use.value">{{ t(use.label) }}</a-checkbox>
|
||||||
</a-checkbox-group>
|
</a-checkbox-group>
|
||||||
|
<MsFormItemSub
|
||||||
|
v-if="form.use.length === 3"
|
||||||
|
:text="t('system.resourcePool.allUseTip')"
|
||||||
|
:show-fill-icon="false"
|
||||||
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<template v-if="isCheckedPerformance">
|
<template v-if="isCheckedPerformance">
|
||||||
<a-form-item :label="t('system.resourcePool.mirror')" field="testResourceDTO.loadTestImage" class="form-item">
|
<a-form-item :label="t('system.resourcePool.mirror')" field="testResourceDTO.loadTestImage" class="form-item">
|
||||||
|
@ -88,14 +93,10 @@
|
||||||
:placeholder="t('system.resourcePool.testHeapPlaceholder')"
|
:placeholder="t('system.resourcePool.testHeapPlaceholder')"
|
||||||
:max-length="250"
|
:max-length="250"
|
||||||
></a-input>
|
></a-input>
|
||||||
<div class="mt-[4px] text-[12px] text-[var(--color-text-4)]">
|
<MsFormItemSub
|
||||||
{{ t('system.resourcePool.testHeapExample', { heap: defaultHeap }) }}
|
:text="t('system.resourcePool.testHeapExample', { heap: defaultHeap })"
|
||||||
<MsIcon
|
@fill="fillHeapByDefault"
|
||||||
type="icon-icon_corner_right_up"
|
/>
|
||||||
class="cursor-pointer text-[rgb(var(--primary-6))]"
|
|
||||||
@click="fillHeapByDefault"
|
|
||||||
></MsIcon>
|
|
||||||
</div>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -344,6 +345,8 @@
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
import MsBatchForm from '@/components/business/ms-batch-form/index.vue';
|
import MsBatchForm from '@/components/business/ms-batch-form/index.vue';
|
||||||
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
import MsCodeEditor from '@/components/pure/ms-code-editor/index.vue';
|
||||||
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
|
import MsFormItemSub from '@/components/business/ms-form-item-sub/index.vue';
|
||||||
import JobTemplateDrawer from './components/jobTemplateDrawer.vue';
|
import JobTemplateDrawer from './components/jobTemplateDrawer.vue';
|
||||||
import { getYaml, YamlType, job } from './template';
|
import { getYaml, YamlType, job } from './template';
|
||||||
import { downloadStringFile, sleep } from '@/utils';
|
import { downloadStringFile, sleep } from '@/utils';
|
||||||
|
|
|
@ -84,41 +84,37 @@
|
||||||
title: 'system.resourcePool.tableColumnName',
|
title: 'system.resourcePool.tableColumnName',
|
||||||
slotName: 'name',
|
slotName: 'name',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
width: 200,
|
showTooltip: true,
|
||||||
showInTable: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'system.resourcePool.tableColumnStatus',
|
title: 'system.resourcePool.tableColumnStatus',
|
||||||
slotName: 'enable',
|
slotName: 'enable',
|
||||||
dataIndex: 'enable',
|
dataIndex: 'enable',
|
||||||
showInTable: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'system.resourcePool.tableColumnDescription',
|
title: 'system.resourcePool.tableColumnDescription',
|
||||||
dataIndex: 'description',
|
dataIndex: 'description',
|
||||||
showInTable: true,
|
showTooltip: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'system.resourcePool.tableColumnType',
|
title: 'system.resourcePool.tableColumnType',
|
||||||
dataIndex: 'type',
|
dataIndex: 'type',
|
||||||
showInTable: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'system.resourcePool.tableColumnCreateTime',
|
title: 'system.resourcePool.tableColumnCreateTime',
|
||||||
dataIndex: 'createTime',
|
dataIndex: 'createTime',
|
||||||
showInTable: true,
|
width: 170,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'system.resourcePool.tableColumnUpdateTime',
|
title: 'system.resourcePool.tableColumnUpdateTime',
|
||||||
dataIndex: 'updateTime',
|
dataIndex: 'updateTime',
|
||||||
showInTable: true,
|
width: 170,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'system.resourcePool.tableColumnActions',
|
title: 'system.resourcePool.tableColumnActions',
|
||||||
slotName: 'action',
|
slotName: 'action',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: 140,
|
width: 140,
|
||||||
showInTable: true,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const tableStore = useTableStore();
|
const tableStore = useTableStore();
|
||||||
|
|
|
@ -69,6 +69,7 @@ export default {
|
||||||
'system.resourcePool.batchAddResource': '批量添加资源',
|
'system.resourcePool.batchAddResource': '批量添加资源',
|
||||||
'system.resourcePool.changeAddTypeTip': '切换后,已添加资源内容将继续现在 yaml 内;可批量修改已添加资源',
|
'system.resourcePool.changeAddTypeTip': '切换后,已添加资源内容将继续现在 yaml 内;可批量修改已添加资源',
|
||||||
'system.resourcePool.changeAddTypePopTitle': '切换添加资源类型?',
|
'system.resourcePool.changeAddTypePopTitle': '切换添加资源类型?',
|
||||||
|
'system.resourcePool.allUseTip': '如果配置多个测试类型,会存在抢占资源的情况,建议一种测试类型配置一个资源池',
|
||||||
'system.resourcePool.ip': 'IP',
|
'system.resourcePool.ip': 'IP',
|
||||||
'system.resourcePool.ipRequired': 'IP 地址不能为空',
|
'system.resourcePool.ipRequired': 'IP 地址不能为空',
|
||||||
'system.resourcePool.ipPlaceholder': '请输入 IP 地址',
|
'system.resourcePool.ipPlaceholder': '请输入 IP 地址',
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
:title="t('system.user.invite')"
|
:title="t('system.user.invite')"
|
||||||
title-align="start"
|
title-align="start"
|
||||||
class="ms-modal-form ms-modal-medium"
|
class="ms-modal-form ms-modal-medium"
|
||||||
:loading="inviteLoading"
|
|
||||||
>
|
>
|
||||||
<a-form ref="inviteFormRef" class="rounded-[4px]" :model="emailForm" layout="vertical">
|
<a-form ref="inviteFormRef" class="rounded-[4px]" :model="emailForm" layout="vertical">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
|
@ -42,8 +41,10 @@
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<a-button type="secondary" @click="cancelInvite">{{ t('system.user.inviteCancel') }}</a-button>
|
<a-button type="secondary" :disabled="inviteLoading" @click="cancelInvite">
|
||||||
<a-button type="primary" @click="emailInvite">
|
{{ t('system.user.inviteCancel') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" :loading="inviteLoading" @click="emailInvite">
|
||||||
{{ t('system.user.inviteSendEmail') }}
|
{{ t('system.user.inviteSendEmail') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
|
@ -56,6 +57,7 @@
|
||||||
import { FormInstance, Message, ValidatedError } from '@arco-design/web-vue';
|
import { FormInstance, Message, ValidatedError } from '@arco-design/web-vue';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
|
import MsTagsInput from '@/components/pure/ms-tags-input/index.vue';
|
||||||
|
import { inviteUser } from '@/api/modules/setting/user';
|
||||||
|
|
||||||
import type { SystemRole } from '@/models/setting/user';
|
import type { SystemRole } from '@/models/setting/user';
|
||||||
|
|
||||||
|
@ -103,7 +105,10 @@
|
||||||
function cancelInvite() {
|
function cancelInvite() {
|
||||||
inviteVisible.value = false;
|
inviteVisible.value = false;
|
||||||
inviteFormRef.value?.resetFields();
|
inviteFormRef.value?.resetFields();
|
||||||
emailForm.value = cloneDeep(defaultInviteForm);
|
emailForm.value.emails = [];
|
||||||
|
emailForm.value.userGroup = props.userGroupOptions
|
||||||
|
.filter((e: SystemRole) => e.selected === true)
|
||||||
|
.map((e: SystemRole) => e.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function emailInvite() {
|
function emailInvite() {
|
||||||
|
@ -111,8 +116,12 @@
|
||||||
if (!errors) {
|
if (!errors) {
|
||||||
try {
|
try {
|
||||||
inviteLoading.value = true;
|
inviteLoading.value = true;
|
||||||
cancelInvite();
|
await inviteUser({
|
||||||
|
inviteEmails: emailForm.value.emails,
|
||||||
|
userRoleIds: emailForm.value.userGroup,
|
||||||
|
});
|
||||||
Message.success(t('system.user.inviteSuccess'));
|
Message.success(t('system.user.inviteSuccess'));
|
||||||
|
inviteVisible.value = false;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
:mask-closable="false"
|
:mask-closable="false"
|
||||||
@close="handleUserModalClose"
|
@close="handleUserModalClose"
|
||||||
>
|
>
|
||||||
|
<a-alert class="mb-[16px]">{{ t('system.user.createUserTip') }}</a-alert>
|
||||||
<a-form ref="userFormRef" class="rounded-[4px]" :model="userForm" layout="vertical">
|
<a-form ref="userFormRef" class="rounded-[4px]" :model="userForm" layout="vertical">
|
||||||
<MsBatchForm
|
<MsBatchForm
|
||||||
ref="batchFormRef"
|
ref="batchFormRef"
|
||||||
|
|
|
@ -39,6 +39,7 @@ export default {
|
||||||
'system.user.addUser': 'Add user',
|
'system.user.addUser': 'Add user',
|
||||||
'system.user.addUserSuccess': 'Added successfully',
|
'system.user.addUserSuccess': 'Added successfully',
|
||||||
'system.user.updateUserSuccess': 'Updated successfully',
|
'system.user.updateUserSuccess': 'Updated successfully',
|
||||||
|
'system.user.createUserTip': 'The initial password is email address',
|
||||||
'system.user.createUserName': 'Name',
|
'system.user.createUserName': 'Name',
|
||||||
'system.user.createUserNameNotNull': 'Name cannot be blank',
|
'system.user.createUserNameNotNull': 'Name cannot be blank',
|
||||||
'system.user.createUserNameOverLength': 'Name length cannot exceed 50',
|
'system.user.createUserNameOverLength': 'Name length cannot exceed 50',
|
||||||
|
|
|
@ -38,6 +38,7 @@ export default {
|
||||||
'system.user.addUser': '添加用户',
|
'system.user.addUser': '添加用户',
|
||||||
'system.user.addUserSuccess': '添加成功',
|
'system.user.addUserSuccess': '添加成功',
|
||||||
'system.user.updateUserSuccess': '更新成功',
|
'system.user.updateUserSuccess': '更新成功',
|
||||||
|
'system.user.createUserTip': '初始密码为邮箱地址',
|
||||||
'system.user.createUserName': '姓名',
|
'system.user.createUserName': '姓名',
|
||||||
'system.user.createUserNameNotNull': '姓名不能为空',
|
'system.user.createUserNameNotNull': '姓名不能为空',
|
||||||
'system.user.createUserNameOverLength': '姓名长度不能超过50',
|
'system.user.createUserNameOverLength': '姓名长度不能超过50',
|
||||||
|
|
Loading…
Reference in New Issue