pull/213/head
xiaojunnuo 2024-10-03 01:29:12 +08:00
parent aeed24e87d
commit c9d18f6d8a
17 changed files with 100 additions and 34 deletions

View File

@ -16,6 +16,11 @@ export class HttpError extends Error {
return;
}
super(error.message);
if (error?.message?.indexOf("ssl3_get_record:wrong version number") > -1) {
this.message = "http协议错误服务端要求http协议请检查是否使用了https请求";
}
this.name = error.name;
this.code = error.code;
this.cause = error.cause;

View File

@ -1,7 +1,7 @@
import axios from "axios";
import { get } from "lodash-es";
import Adapter from "axios-mock-adapter";
import { errorLog, errorCreate } from "./tools";
import { errorLog, errorCreate, response } from "./tools";
import { env } from "/src/utils/util.env";
import { useUserStore } from "../store/modules/user";
/**
@ -96,6 +96,10 @@ function createService() {
const userStore = useUserStore();
userStore.logout();
}
if (error?.config?.onError) {
error.config.onError(error);
}
return Promise.reject(error);
}
);

View File

@ -55,6 +55,9 @@ export function errorLog(error: any) {
if (error.response?.data?.message) {
message = error.response.data.message;
}
if (message.indexOf("ssl3_get_record:wrong version number" > -1)) {
message = "http协议错误服务端要求http协议请检查是否使用了https请求";
}
// 显示提示
uiContext.get().notification.error({ message });
}

View File

@ -13,13 +13,21 @@ const emit = defineEmits<{
}>();
const optionsRef = ref([]);
const message = ref("");
const getOptions = async () => {
return await doRequest({
type: props.type,
typeName: props.typeName,
action: props.action,
input: props.form
});
return await doRequest(
{
type: props.type,
typeName: props.typeName,
action: props.action,
input: props.form
},
{
onError(err) {
message.value = err.message;
}
}
);
};
const filterOption = (input: string, option: any) => {
@ -53,7 +61,8 @@ watch(
</script>
<template>
<a-select
<div>
<a-select
class="remote-select"
show-search
:filter-option="filterOption"
@ -62,6 +71,10 @@ watch(
@click="onClick"
@update:value="emit('update:value', $event)"
/>
<div class="helper">
{{ message }}
</div>
</div>
</template>
<style lang="less"></style>

View File

@ -14,7 +14,7 @@ export type RequestHandleReq<T = any> = {
input: T;
};
export async function doRequest(req: RequestHandleReq) {
export async function doRequest(req: RequestHandleReq, opts?: any = {}) {
const url = req.type === "access" ? "/pi/handle/access" : "/pi/handle/plugin";
const { typeName, action, data, input } = req;
const res = await request({
@ -25,7 +25,8 @@ export async function doRequest(req: RequestHandleReq) {
action,
data,
input
}
},
...opts
});
return res;
}

View File

@ -1,7 +1,7 @@
<template>
<div>
<contextHolder />
<a-input :value="value" :allow-clear="true" @update:value="emit('update:value', $event)">
<a-input v-bind="attrs" :value="value" :allow-clear="true" @update:value="emit('update:value', $event)">
<template #suffix>
<a-tag class="cursor-pointer" @click="getDeviceId">ID</a-tag>
</template>

View File

@ -33,18 +33,19 @@ type Text = {
title?: string;
};
const text = computed<Text>(() => {
const vipLabel = userStore.vipLabel;
const map = {
isPlus: {
button: {
name: "专业版已开通",
name: `${vipLabel}已开通`,
title: "到期时间:" + expireTime.value
},
icon: {
name: "",
title: "专业版已开通"
title: `${vipLabel}已开通`
},
nav: {
name: "专业版",
name: `${vipLabel}`,
title: "到期时间:" + expireTime.value
}
},
@ -82,7 +83,7 @@ const expiredDays = computed(() => {
if (userStore.plusInfo?.isPlus && !userStore.isPlus) {
//
const days = dayjs().diff(dayjs(userStore.plusInfo.expireTime), "day");
return `专业版已过期${days}`;
return `${userStore.vipLabel}已过期${days}`;
}
return "";
});
@ -100,15 +101,16 @@ async function doActive() {
const res = await api.doActive(formState);
if (res) {
await userStore.reInit();
const vipLabel = userStore.vipLabel;
Modal.success({
title: "激活成功",
content: `您已成功激活专业版,有效期至:${dayjs(userStore.plusInfo.expireTime).format("YYYY-MM-DD")}`,
content: `您已成功激活${vipLabel},有效期至:${dayjs(userStore.plusInfo.expireTime).format("YYYY-MM-DD")}`,
onOk() {
if (!(settingStore.installInfo.bindUserId > 0)) {
//
Modal.confirm({
title: "是否绑定袖手账号",
content: "绑定账号后,可以避免专业版License丢失强烈建议绑定",
content: "绑定账号后,可以避免License丢失强烈建议绑定",
onOk() {
router.push("/sys/account");
}
@ -130,8 +132,15 @@ function openUpgrade() {
}
const placeholder = "请输入激活码";
const isPlus = userStore.isPlus;
let title = "激活专业版/商业版";
if (userStore.isComm) {
title = "续期商业版";
} else if (userStore.isPlus) {
title = "续期专业版/升级商业版";
}
modal.confirm({
title: isPlus ? "续期专业版" : "激活专业版",
title,
async onOk() {
return await doActive();
},
@ -139,6 +148,7 @@ function openUpgrade() {
okText: "激活",
width: 500,
content: () => {
const vipLabel = userStore.vipLabel;
return (
<div class="mt-10 mb-10">
<div>
@ -153,7 +163,7 @@ function openUpgrade() {
</div>
<div>
<h3 class="block-header">{isPlus ? "续期" : "立刻激活"}</h3>
<div>{isPlus ? "当前专业版已激活,到期时间" + dayjs(userStore.plusInfo.expireTime).format("YYYY-MM-DD") : ""}</div>
<div>{isPlus ? `当前${vipLabel}已激活,到期时间` + dayjs(userStore.plusInfo.expireTime).format("YYYY-MM-DD") : ""}</div>
<div class="mt-10">
<div class="flex-o w-100">
<span>站点ID</span>

View File

@ -350,7 +350,7 @@ function install(app: App, options: any = {}) {
}
columnProps.column.resizable = true;
if (!columnProps.column.width) {
columnProps.column.width = 100;
columnProps.column.width = -1;
} else if (typeof columnProps.column?.width === "string" && columnProps.column.width.indexOf("px") > -1) {
columnProps.column.width = parseInt(columnProps.column.width.replace("px", ""));
}

View File

@ -23,6 +23,7 @@ interface PlusInfo {
vipType: string;
expireTime: number;
isPlus: boolean;
isComm: boolean;
}
const USER_INFO_KEY = "USER_INFO";
@ -46,10 +47,21 @@ export const useUserStore = defineStore({
return this.token || LocalStorage.get(TOKEN_KEY);
},
isAdmin(): boolean {
return this.getUserInfo?.id === 1;
return this.getUserInfo.id === 1 || this.getUserInfo.roles?.includes(1);
},
isPlus(): boolean {
return this.plusInfo?.isPlus && this.plusInfo?.expireTime > new Date().getTime();
},
isComm(): boolean {
return this.plusInfo?.isComm && this.plusInfo?.expireTime > new Date().getTime();
},
vipLabel(): string {
const vipLabelMap: any = {
free: "免费版",
vip: "专业版",
comm: "商业版"
};
return vipLabelMap[this.plusInfo?.vipType];
}
},
actions: {

View File

@ -40,7 +40,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
type: "text",
form: { show: false }, // 表单配置
column: {
width: 70,
width: 100,
sorter: true
}
},
@ -74,7 +74,8 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti
},
editForm: { component: { disabled: true } },
column: {
sorter: true
sorter: true,
width: 200
}
},
password: {

View File

@ -17,18 +17,21 @@
# password: root
# database: postgres
typeorm:
dataSource:
default:
database: './data/db-comm.sqlite'
#plus:
# server:
# baseUrls: ['https://api.ai.handsfree.work', 'https://api.ai.docmirror.cn']
plus:
server:
baseUrls: ['https://api.ai.handsfree.work', 'https://api.ai.docmirror.cn']
#typeorm:
# dataSource:
# default:
# database: './data/db2.sqlite'
#account:
# server:
# baseUrl: 'http://127.0.0.1:1017/subject'
baseUrls: ['http://127.0.0.1:11007']
account:
server:
baseUrl: 'https://ai.handsfree.work/subject'
baseUrl: 'http://127.0.0.1:1017/subject'
#account:
# server:
# baseUrl: 'https://ai.handsfree.work/subject'

View File

@ -24,6 +24,7 @@
"@alicloud/pop-core": "^1.7.10",
"@certd/acme-client": "^1.25.9",
"@certd/lib-huawei": "^1.25.9",
"@certd/commcial-core": "^1.25.9",
"@certd/lib-jdcloud": "^1.25.9",
"@certd/lib-k8s": "^1.25.9",
"@certd/midway-flyway-js": "^1.25.9",

View File

@ -49,6 +49,9 @@ export class RoleController extends CrudController<RoleService> {
@Query('id')
id: number
) {
if (id === 1) {
throw new Error('不能删除默认的管理员角色');
}
return await super.delete(id);
}

View File

@ -73,8 +73,11 @@ export class UserController extends CrudController<UserService> {
@Post('/delete', { summary: 'sys:auth:user:remove' })
async delete(
@Query('id')
id : number
id: number
) {
if (id === 1) {
throw new Error('不能删除默认的管理员用户');
}
return await super.delete(id);
}

View File

@ -66,4 +66,6 @@ export class UserEntity {
static of(user: Partial<UserEntity>) {
return Object.assign(new UserEntity(), user);
}
roleIds: number[];
}

View File

@ -3,6 +3,7 @@ import { BaseController } from '../../../basic/base-controller.js';
import { Constants } from '../../../basic/constants.js';
import { UserService } from '../../authority/service/user-service.js';
import { getPlusInfo } from '@certd/pipeline';
import { RoleService } from '../../authority/service/role-service.js';
/**
*/
@ -11,10 +12,13 @@ import { getPlusInfo } from '@certd/pipeline';
export class MineController extends BaseController {
@Inject()
userService: UserService;
@Inject()
roleService: RoleService;
@Post('/info', { summary: Constants.per.authOnly })
public async info() {
const userId = this.getUserId();
const user = await this.userService.info(userId);
user.roleIds = await this.roleService.getRoleIdsByUserId(userId);
delete user.password;
return this.ok(user);
}

View File

@ -27,4 +27,5 @@ export class UserSettingsEntity {
default: () => 'CURRENT_TIMESTAMP',
})
updateTime: Date;
}