feat(license): 用户限制&部分 bug 修复
This commit is contained in:
parent
896520a8be
commit
44231d851a
|
@ -4,11 +4,18 @@ import { useI18n } from '@/hooks/useI18n';
|
||||||
import useUser from '@/hooks/useUser';
|
import useUser from '@/hooks/useUser';
|
||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
import { NO_RESOURCE_ROUTE_NAME } from '@/router/constants';
|
import { NO_RESOURCE_ROUTE_NAME } from '@/router/constants';
|
||||||
|
import useLicenseStore from '@/store/modules/setting/license';
|
||||||
|
|
||||||
import type { ErrorMessageMode } from '#/axios';
|
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 { t } = useI18n();
|
||||||
|
const licenseStore = useLicenseStore();
|
||||||
const { logout, isLoginPage, isWhiteListPage } = useUser();
|
const { logout, isLoginPage, isWhiteListPage } = useUser();
|
||||||
let errMessage = '';
|
let errMessage = '';
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
@ -39,6 +46,77 @@ export default function checkStatus(status: number, msg: string, errorMessageMod
|
||||||
errMessage = msg || t('api.errMsg408');
|
errMessage = msg || t('api.errMsg408');
|
||||||
break;
|
break;
|
||||||
case 500:
|
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');
|
errMessage = msg || t('api.errMsg500');
|
||||||
break;
|
break;
|
||||||
case 501:
|
case 501:
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { deepMerge, setObjToUrlParams } from '@/utils';
|
||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
import { isString } from '@/utils/is';
|
import { isString } from '@/utils/is';
|
||||||
|
|
||||||
|
import type CommonResponse from '@/models/common';
|
||||||
import { ContentTypeEnum, RequestEnum } from '@/enums/httpEnum';
|
import { ContentTypeEnum, RequestEnum } from '@/enums/httpEnum';
|
||||||
|
|
||||||
import { MSAxios } from './Axios';
|
import { MSAxios } from './Axios';
|
||||||
|
@ -135,7 +136,7 @@ const transform: AxiosTransform = {
|
||||||
/**
|
/**
|
||||||
* @description: 响应拦截器处理
|
* @description: 响应拦截器处理
|
||||||
*/
|
*/
|
||||||
responseInterceptors: (res: AxiosResponse<any>) => {
|
responseInterceptors: (res: AxiosResponse<CommonResponse<any>>) => {
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -169,8 +170,8 @@ const transform: AxiosTransform = {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(e as unknown as string);
|
throw new Error(e as unknown as string);
|
||||||
}
|
}
|
||||||
checkStatus(error?.response?.status, msg, errorMessageMode);
|
checkStatus(response?.status, msg, response?.data?.code, errorMessageMode);
|
||||||
return Promise.reject(error?.response?.data?.message || error);
|
return Promise.reject(response?.data?.message || error);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useLicenseStore from '@/store/modules/setting/license';
|
import useLicenseStore from '@/store/modules/setting/license';
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
|
||||||
|
|
||||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
|
|
@ -30,4 +30,13 @@ export default {
|
||||||
'asyncTask.uploadFileProgress': 'File upload progress {percent}; {done} successful, {fail} failed',
|
'asyncTask.uploadFileProgress': 'File upload progress {percent}; {done} successful, {fail} failed',
|
||||||
'asyncTask.uploadFileSuccess': 'File upload completed: {done} successfully, {fail} failed',
|
'asyncTask.uploadFileSuccess': 'File upload completed: {done} successfully, {fail} failed',
|
||||||
'asyncTask.uploadFileSuccessTitle': 'Upload completed',
|
'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',
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,4 +30,10 @@ export default {
|
||||||
'asyncTask.uploadFileProgress': '文件上传进度 {percent};成功 {done} 个,失败 {fail} 个',
|
'asyncTask.uploadFileProgress': '文件上传进度 {percent};成功 {done} 个,失败 {fail} 个',
|
||||||
'asyncTask.uploadFileSuccess': '文件上传完成:成功 {done} 个,失败 {fail} 个',
|
'asyncTask.uploadFileSuccess': '文件上传完成:成功 {done} 个,失败 {fail} 个',
|
||||||
'asyncTask.uploadFileSuccessTitle': '上传完成',
|
'asyncTask.uploadFileSuccessTitle': '上传完成',
|
||||||
|
// 通用业务提示
|
||||||
|
'user.openSourceCreateUsersLimit': '系统用户数已达到最大用户数限制30人(社区版),如需添加更多用户,可申请',
|
||||||
|
'user.businessTry': '企业版试用',
|
||||||
|
'user.businessCreateUsersLimitThirty': '系统用户数已达到最大用户数限制30人 (社区版),如需添加更多用户,可申请',
|
||||||
|
'user.businessCreateUsersLimitMax': '系统用户数已达到最大用户订阅数 {count} 人,如需添加更多用户,可申请',
|
||||||
|
'user.businessScaling': '企业版扩容',
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,6 @@ export interface License {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LicenseInfo {
|
export interface LicenseInfo {
|
||||||
status: string;
|
status: string | null;
|
||||||
license: License;
|
license: License;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,22 +3,26 @@ import dayjs from 'dayjs';
|
||||||
|
|
||||||
import { getLicenseInfo } from '@/api/modules/setting/authorizedManagement';
|
import { getLicenseInfo } from '@/api/modules/setting/authorizedManagement';
|
||||||
|
|
||||||
|
import type { LicenseInfo } from '@/models/setting/authorizedManagement';
|
||||||
|
|
||||||
const useLicenseStore = defineStore('license', {
|
const useLicenseStore = defineStore('license', {
|
||||||
persist: true,
|
persist: true,
|
||||||
state: (): { status: string | null; expiredDuring: boolean; expiredDays: number } => ({
|
state: (): { licenseInfo: LicenseInfo | null; expiredDuring: boolean; expiredDays: number } => ({
|
||||||
status: '',
|
licenseInfo: null,
|
||||||
expiredDuring: false,
|
expiredDuring: false,
|
||||||
expiredDays: 0,
|
expiredDays: 0,
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setLicenseStatus(status: string) {
|
setLicenseInfo(info: LicenseInfo) {
|
||||||
this.status = status;
|
this.licenseInfo = info;
|
||||||
},
|
},
|
||||||
removeLicenseStatus() {
|
removeLicenseStatus() {
|
||||||
this.status = null;
|
if (this.licenseInfo) {
|
||||||
|
this.licenseInfo.status = null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
hasLicense() {
|
hasLicense() {
|
||||||
return this.status === 'valid';
|
return this.licenseInfo?.status === 'valid';
|
||||||
},
|
},
|
||||||
getExpirationTime(resTime: string) {
|
getExpirationTime(resTime: string) {
|
||||||
const today = Date.now();
|
const today = Date.now();
|
||||||
|
@ -42,10 +46,11 @@ const useLicenseStore = defineStore('license', {
|
||||||
if (!result || !result.status || !result.license || !result.license.count) {
|
if (!result || !result.status || !result.license || !result.license.count) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setLicenseStatus(result.status);
|
this.setLicenseInfo(result);
|
||||||
// 计算license时间
|
// 计算license时间
|
||||||
this.getExpirationTime(result.license.expired);
|
this.getExpirationTime(result.license.expired);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1254,14 +1254,15 @@
|
||||||
saveLoading.value = true;
|
saveLoading.value = true;
|
||||||
}
|
}
|
||||||
let params;
|
let params;
|
||||||
|
const requestParams = makeRequestParams();
|
||||||
if (props.isDefinition) {
|
if (props.isDefinition) {
|
||||||
params = {
|
params = {
|
||||||
...(fullParams || makeRequestParams()),
|
...(fullParams || requestParams),
|
||||||
...props.otherParams,
|
...props.otherParams,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
params = {
|
params = {
|
||||||
...(fullParams || makeRequestParams()),
|
...(fullParams || requestParams),
|
||||||
...saveModalForm.value,
|
...saveModalForm.value,
|
||||||
path: isHttpProtocol.value ? saveModalForm.value.path : undefined,
|
path: isHttpProtocol.value ? saveModalForm.value.path : undefined,
|
||||||
...props.otherParams,
|
...props.otherParams,
|
||||||
|
@ -1280,6 +1281,17 @@
|
||||||
requestVModel.value.url = res.path;
|
requestVModel.value.url = res.path;
|
||||||
requestVModel.value.path = res.path;
|
requestVModel.value.path = res.path;
|
||||||
requestVModel.value.moduleId = res.moduleId;
|
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) {
|
if (!props.isDefinition) {
|
||||||
saveModalVisible.value = false;
|
saveModalVisible.value = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -965,9 +965,15 @@
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isReplace = ref(false);
|
||||||
|
|
||||||
function handleClose() {
|
function handleClose() {
|
||||||
|
if (isReplace.value) {
|
||||||
|
isReplace.value = false;
|
||||||
|
} else {
|
||||||
emit('applyStep', cloneDeep(makeRequestParams()) as RequestParam);
|
emit('applyStep', cloneDeep(makeRequestParams()) as RequestParam);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// const showAddDependencyDrawer = ref(false);
|
// const showAddDependencyDrawer = ref(false);
|
||||||
// const addDependencyMode = ref<'pre' | 'post'>('pre');
|
// const addDependencyMode = ref<'pre' | 'post'>('pre');
|
||||||
|
@ -1019,8 +1025,9 @@
|
||||||
* @param newStep 替换的新步骤
|
* @param newStep 替换的新步骤
|
||||||
*/
|
*/
|
||||||
function handleReplace(newStep: ScenarioStepItem) {
|
function handleReplace(newStep: ScenarioStepItem) {
|
||||||
|
isReplace.value = true;
|
||||||
emit('replace', {
|
emit('replace', {
|
||||||
...newStep,
|
...cloneDeep(newStep),
|
||||||
name: activeStep.value?.name || newStep.name,
|
name: activeStep.value?.name || newStep.name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
block-node
|
block-node
|
||||||
draggable
|
draggable
|
||||||
hide-switcher
|
hide-switcher
|
||||||
@select="(selectedKeys, node) => handleStepSelect(selectedKeys, node as ScenarioStepItem)"
|
@select="(selectedKeys, node) => handleStepSelect(node as ScenarioStepItem)"
|
||||||
@expand="handleStepExpand"
|
@expand="handleStepExpand"
|
||||||
@more-actions-close="() => setFocusNodeKey('')"
|
@more-actions-close="() => setFocusNodeKey('')"
|
||||||
@more-action-select="handleStepMoreActionSelect"
|
@more-action-select="handleStepMoreActionSelect"
|
||||||
|
@ -1069,6 +1069,7 @@
|
||||||
steps.value.splice(index, 1, newStep);
|
steps.value.splice(index, 1, newStep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
activeStep.value = newStep;
|
||||||
}
|
}
|
||||||
Message.success(t('apiScenario.replaceSuccess'));
|
Message.success(t('apiScenario.replaceSuccess'));
|
||||||
scenario.value.unSaved = true;
|
scenario.value.unSaved = true;
|
||||||
|
@ -1080,7 +1081,7 @@
|
||||||
customApiDrawerVisible.value = false;
|
customApiDrawerVisible.value = false;
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
// 等待抽屉关闭后再打开新的抽屉
|
// 等待抽屉关闭后再打开新的抽屉
|
||||||
handleStepSelect([newStep.uniqueId], newStep);
|
handleStepSelect(newStep);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,10 +81,10 @@ export default function useStepOperation({
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理步骤选中事件
|
* 处理步骤选中事件
|
||||||
* @param _selectedKeys 选中的 key集合
|
|
||||||
* @param step 点击的步骤节点
|
* @param step 点击的步骤节点
|
||||||
*/
|
*/
|
||||||
async function handleStepSelect(_selectedKeys: Array<string | number>, step: ScenarioStepItem) {
|
async function handleStepSelect(step: ScenarioStepItem) {
|
||||||
|
activeStep.value = step;
|
||||||
const _stepType = getStepType(step);
|
const _stepType = getStepType(step);
|
||||||
const offspringIds: string[] = [];
|
const offspringIds: string[] = [];
|
||||||
mapTree(step.children || [], (e) => {
|
mapTree(step.children || [], (e) => {
|
||||||
|
@ -94,7 +94,6 @@ export default function useStepOperation({
|
||||||
selectedKeys.value = [step.uniqueId, ...offspringIds];
|
selectedKeys.value = [step.uniqueId, ...offspringIds];
|
||||||
if (_stepType.isCopyApi || _stepType.isQuoteApi || step.stepType === ScenarioStepType.CUSTOM_REQUEST) {
|
if (_stepType.isCopyApi || _stepType.isQuoteApi || step.stepType === ScenarioStepType.CUSTOM_REQUEST) {
|
||||||
// 复制 api、引用 api、自定义 api打开抽屉
|
// 复制 api、引用 api、自定义 api打开抽屉
|
||||||
activeStep.value = step;
|
|
||||||
if (
|
if (
|
||||||
step.isQuoteScenarioStep ||
|
step.isQuoteScenarioStep ||
|
||||||
(stepDetails.value[step.id] === undefined && step.copyFromStepId) ||
|
(stepDetails.value[step.id] === undefined && step.copyFromStepId) ||
|
||||||
|
@ -106,7 +105,6 @@ export default function useStepOperation({
|
||||||
}
|
}
|
||||||
customApiDrawerVisible.value = true;
|
customApiDrawerVisible.value = true;
|
||||||
} else if (step.stepType === ScenarioStepType.API_CASE) {
|
} else if (step.stepType === ScenarioStepType.API_CASE) {
|
||||||
activeStep.value = step;
|
|
||||||
if (
|
if (
|
||||||
step.isQuoteScenarioStep ||
|
step.isQuoteScenarioStep ||
|
||||||
(_stepType.isCopyCase && stepDetails.value[step.id] === undefined && step.copyFromStepId) ||
|
(_stepType.isCopyCase && stepDetails.value[step.id] === undefined && step.copyFromStepId) ||
|
||||||
|
@ -119,7 +117,6 @@ export default function useStepOperation({
|
||||||
}
|
}
|
||||||
customCaseDrawerVisible.value = true;
|
customCaseDrawerVisible.value = true;
|
||||||
} else if (step.stepType === ScenarioStepType.SCRIPT) {
|
} else if (step.stepType === ScenarioStepType.SCRIPT) {
|
||||||
activeStep.value = step;
|
|
||||||
if (
|
if (
|
||||||
step.isQuoteScenarioStep ||
|
step.isQuoteScenarioStep ||
|
||||||
(stepDetails.value[step.id] === undefined && step.copyFromStepId) ||
|
(stepDetails.value[step.id] === undefined && step.copyFromStepId) ||
|
||||||
|
|
|
@ -242,6 +242,7 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleCancel = (shouldSearch: boolean) => {
|
const handleCancel = (shouldSearch: boolean) => {
|
||||||
|
formRef.value?.resetFields();
|
||||||
emit('cancel', shouldSearch);
|
emit('cancel', shouldSearch);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -143,9 +143,10 @@
|
||||||
try {
|
try {
|
||||||
const result = await getLicenseInfo();
|
const result = await getLicenseInfo();
|
||||||
licenseInfo.value = result;
|
licenseInfo.value = result;
|
||||||
licenseStore.setLicenseStatus(licenseInfo.value?.status);
|
licenseStore.setLicenseInfo(licenseInfo.value);
|
||||||
licenseStore.getExpirationTime(licenseInfo.value.license.expired);
|
licenseStore.getExpirationTime(licenseInfo.value.license.expired);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
@ -174,6 +175,7 @@
|
||||||
getLicenseDetail();
|
getLicenseDetail();
|
||||||
cancelHandler();
|
cancelHandler();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
drawerLoading.value = false;
|
drawerLoading.value = false;
|
||||||
|
|
Loading…
Reference in New Issue