feat(license): 用户限制&部分 bug 修复

This commit is contained in:
baiqi 2024-05-31 16:09:10 +08:00 committed by 刘瑞斌
parent 896520a8be
commit 44231d851a
14 changed files with 143 additions and 28 deletions

View File

@ -4,11 +4,18 @@ import { useI18n } from '@/hooks/useI18n';
import useUser from '@/hooks/useUser';
import router from '@/router';
import { NO_RESOURCE_ROUTE_NAME } from '@/router/constants';
import useLicenseStore from '@/store/modules/setting/license';
import type { ErrorMessageMode } from '#/axios';
export default function checkStatus(status: number, msg: string, errorMessageMode: ErrorMessageMode = 'message'): void {
export default function checkStatus(
status: number,
msg: string,
code?: number,
errorMessageMode: ErrorMessageMode = 'message'
): void {
const { t } = useI18n();
const licenseStore = useLicenseStore();
const { logout, isLoginPage, isWhiteListPage } = useUser();
let errMessage = '';
switch (status) {
@ -39,6 +46,77 @@ export default function checkStatus(status: number, msg: string, errorMessageMod
errMessage = msg || t('api.errMsg408');
break;
case 500:
if (code === 101511) {
// 开源版创建用户超数量
Message.error({
content: () =>
h(
'div',
{
style: {
display: 'flex',
alignItems: 'center',
gap: '4px',
},
},
[
h('span', t('user.openSourceCreateUsersLimit')),
h(
'a',
{
href: 'https://jinshuju.net/f/CzzAOe',
target: '_blank',
style: {
color: 'rgb(var(--primary-5))',
},
},
t('user.businessTry')
),
]
),
duration: 0,
closable: true,
});
return;
}
if (code === 101512) {
// 企业版创建用户超数量
Message.error({
content: () =>
h(
'div',
{
style: {
display: 'flex',
alignItems: 'center',
gap: '4px',
},
},
[
h(
'span',
(licenseStore.licenseInfo?.license.count || 30) <= 30
? t('user.businessCreateUsersLimitThirty')
: t('user.businessCreateUsersLimitMax', { count: licenseStore.licenseInfo?.license.count })
),
h(
'a',
{
href: 'https://jinshuju.net/f/CzzAOe',
target: '_blank',
style: {
color: 'rgb(var(--primary-5))',
},
},
t('user.businessScaling')
),
]
),
duration: 0,
closable: true,
});
return;
}
errMessage = msg || t('api.errMsg500');
break;
case 501:

View File

@ -7,6 +7,7 @@ import { deepMerge, setObjToUrlParams } from '@/utils';
import { getToken } from '@/utils/auth';
import { isString } from '@/utils/is';
import type CommonResponse from '@/models/common';
import { ContentTypeEnum, RequestEnum } from '@/enums/httpEnum';
import { MSAxios } from './Axios';
@ -135,7 +136,7 @@ const transform: AxiosTransform = {
/**
* @description:
*/
responseInterceptors: (res: AxiosResponse<any>) => {
responseInterceptors: (res: AxiosResponse<CommonResponse<any>>) => {
return res;
},
@ -169,8 +170,8 @@ const transform: AxiosTransform = {
} catch (e) {
throw new Error(e as unknown as string);
}
checkStatus(error?.response?.status, msg, errorMessageMode);
return Promise.reject(error?.response?.data?.message || error);
checkStatus(response?.status, msg, response?.data?.code, errorMessageMode);
return Promise.reject(response?.data?.message || error);
},
};

View File

@ -9,8 +9,6 @@
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useI18n } from '@/hooks/useI18n';
import useLicenseStore from '@/store/modules/setting/license';

View File

@ -12,8 +12,6 @@
</template>
<script setup lang="ts">
import { ref } from 'vue';
import MsButton from '@/components/pure/ms-button/index.vue';
import { useI18n } from '@/hooks/useI18n';

View File

@ -30,4 +30,13 @@ export default {
'asyncTask.uploadFileProgress': 'File upload progress {percent}; {done} successful, {fail} failed',
'asyncTask.uploadFileSuccess': 'File upload completed: {done} successfully, {fail} failed',
'asyncTask.uploadFileSuccessTitle': 'Upload completed',
// 通用业务提示
'user.openSourceCreateUsersLimit':
'The maximum number of system users has reached 30 (Community Edition). If you need to add more users, you can apply',
'user.businessTry': 'Enterprise Edition Trial',
'user.businessCreateUsersLimitThirty':
'The maximum number of system users has reached 30 (Community Edition). If you need to add more users, you can apply',
'user.businessCreateUsersLimitMax':
'The number of system users has reached the maximum number of user subscriptions {count}. If you want to add more users, you can apply',
'user.businessScaling': 'Enterprise Edition Capacity Expansion',
};

View File

@ -30,4 +30,10 @@ export default {
'asyncTask.uploadFileProgress': '文件上传进度 {percent};成功 {done} 个,失败 {fail} 个',
'asyncTask.uploadFileSuccess': '文件上传完成:成功 {done} 个,失败 {fail} 个',
'asyncTask.uploadFileSuccessTitle': '上传完成',
// 通用业务提示
'user.openSourceCreateUsersLimit': '系统用户数已达到最大用户数限制30人(社区版),如需添加更多用户,可申请',
'user.businessTry': '企业版试用',
'user.businessCreateUsersLimitThirty': '系统用户数已达到最大用户数限制30人 (社区版),如需添加更多用户,可申请',
'user.businessCreateUsersLimitMax': '系统用户数已达到最大用户订阅数 {count} 人,如需添加更多用户,可申请',
'user.businessScaling': '企业版扩容',
};

View File

@ -8,6 +8,6 @@ export interface License {
}
export interface LicenseInfo {
status: string;
status: string | null;
license: License;
}

View File

@ -3,22 +3,26 @@ import dayjs from 'dayjs';
import { getLicenseInfo } from '@/api/modules/setting/authorizedManagement';
import type { LicenseInfo } from '@/models/setting/authorizedManagement';
const useLicenseStore = defineStore('license', {
persist: true,
state: (): { status: string | null; expiredDuring: boolean; expiredDays: number } => ({
status: '',
state: (): { licenseInfo: LicenseInfo | null; expiredDuring: boolean; expiredDays: number } => ({
licenseInfo: null,
expiredDuring: false,
expiredDays: 0,
}),
actions: {
setLicenseStatus(status: string) {
this.status = status;
setLicenseInfo(info: LicenseInfo) {
this.licenseInfo = info;
},
removeLicenseStatus() {
this.status = null;
if (this.licenseInfo) {
this.licenseInfo.status = null;
}
},
hasLicense() {
return this.status === 'valid';
return this.licenseInfo?.status === 'valid';
},
getExpirationTime(resTime: string) {
const today = Date.now();
@ -42,10 +46,11 @@ const useLicenseStore = defineStore('license', {
if (!result || !result.status || !result.license || !result.license.count) {
return;
}
this.setLicenseStatus(result.status);
this.setLicenseInfo(result);
// 计算license时间
this.getExpirationTime(result.license.expired);
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
}
},

View File

@ -1254,14 +1254,15 @@
saveLoading.value = true;
}
let params;
const requestParams = makeRequestParams();
if (props.isDefinition) {
params = {
...(fullParams || makeRequestParams()),
...(fullParams || requestParams),
...props.otherParams,
};
} else {
params = {
...(fullParams || makeRequestParams()),
...(fullParams || requestParams),
...saveModalForm.value,
path: isHttpProtocol.value ? saveModalForm.value.path : undefined,
...props.otherParams,
@ -1280,6 +1281,17 @@
requestVModel.value.url = res.path;
requestVModel.value.path = res.path;
requestVModel.value.moduleId = res.moduleId;
if (!isHttpProtocol.value) {
requestVModel.value = {
...requestVModel.value,
...fApi.value?.formData(), //
uploadFileIds: requestParams.uploadFileIds,
linkFileIds: requestParams.linkFileIds,
};
} else {
requestVModel.value.uploadFileIds = requestParams.uploadFileIds;
requestVModel.value.linkFileIds = requestParams.linkFileIds;
}
if (!props.isDefinition) {
saveModalVisible.value = false;
}

View File

@ -965,9 +965,15 @@
return true;
}
const isReplace = ref(false);
function handleClose() {
if (isReplace.value) {
isReplace.value = false;
} else {
emit('applyStep', cloneDeep(makeRequestParams()) as RequestParam);
}
}
// const showAddDependencyDrawer = ref(false);
// const addDependencyMode = ref<'pre' | 'post'>('pre');
@ -1019,8 +1025,9 @@
* @param newStep 替换的新步骤
*/
function handleReplace(newStep: ScenarioStepItem) {
isReplace.value = true;
emit('replace', {
...newStep,
...cloneDeep(newStep),
name: activeStep.value?.name || newStep.name,
});
}

View File

@ -26,7 +26,7 @@
block-node
draggable
hide-switcher
@select="(selectedKeys, node) => handleStepSelect(selectedKeys, node as ScenarioStepItem)"
@select="(selectedKeys, node) => handleStepSelect(node as ScenarioStepItem)"
@expand="handleStepExpand"
@more-actions-close="() => setFocusNodeKey('')"
@more-action-select="handleStepMoreActionSelect"
@ -1069,6 +1069,7 @@
steps.value.splice(index, 1, newStep);
}
}
activeStep.value = newStep;
}
Message.success(t('apiScenario.replaceSuccess'));
scenario.value.unSaved = true;
@ -1080,7 +1081,7 @@
customApiDrawerVisible.value = false;
nextTick(() => {
//
handleStepSelect([newStep.uniqueId], newStep);
handleStepSelect(newStep);
});
}
}

View File

@ -81,10 +81,10 @@ export default function useStepOperation({
/**
*
* @param _selectedKeys key集合
* @param step
*/
async function handleStepSelect(_selectedKeys: Array<string | number>, step: ScenarioStepItem) {
async function handleStepSelect(step: ScenarioStepItem) {
activeStep.value = step;
const _stepType = getStepType(step);
const offspringIds: string[] = [];
mapTree(step.children || [], (e) => {
@ -94,7 +94,6 @@ export default function useStepOperation({
selectedKeys.value = [step.uniqueId, ...offspringIds];
if (_stepType.isCopyApi || _stepType.isQuoteApi || step.stepType === ScenarioStepType.CUSTOM_REQUEST) {
// 复制 api、引用 api、自定义 api打开抽屉
activeStep.value = step;
if (
step.isQuoteScenarioStep ||
(stepDetails.value[step.id] === undefined && step.copyFromStepId) ||
@ -106,7 +105,6 @@ export default function useStepOperation({
}
customApiDrawerVisible.value = true;
} else if (step.stepType === ScenarioStepType.API_CASE) {
activeStep.value = step;
if (
step.isQuoteScenarioStep ||
(_stepType.isCopyCase && stepDetails.value[step.id] === undefined && step.copyFromStepId) ||
@ -119,7 +117,6 @@ export default function useStepOperation({
}
customCaseDrawerVisible.value = true;
} else if (step.stepType === ScenarioStepType.SCRIPT) {
activeStep.value = step;
if (
step.isQuoteScenarioStep ||
(stepDetails.value[step.id] === undefined && step.copyFromStepId) ||

View File

@ -242,6 +242,7 @@
}
};
const handleCancel = (shouldSearch: boolean) => {
formRef.value?.resetFields();
emit('cancel', shouldSearch);
};

View File

@ -143,9 +143,10 @@
try {
const result = await getLicenseInfo();
licenseInfo.value = result;
licenseStore.setLicenseStatus(licenseInfo.value?.status);
licenseStore.setLicenseInfo(licenseInfo.value);
licenseStore.getExpirationTime(licenseInfo.value.license.expired);
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
loading.value = false;
@ -174,6 +175,7 @@
getLicenseDetail();
cancelHandler();
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);
} finally {
drawerLoading.value = false;