perf: plus api

This commit is contained in:
archer
2023-08-22 17:45:18 +08:00
parent 7a231c6501
commit a5f8fae3f2
25 changed files with 136 additions and 499 deletions

View File

@@ -16,7 +16,6 @@
"qaMaxProcess": 15, "qaMaxProcess": 15,
"pgIvfflatProbe": 20 "pgIvfflatProbe": 20
}, },
"plugins": {},
"ChatModels": [ "ChatModels": [
{ {
"model": "gpt-3.5-turbo", "model": "gpt-3.5-turbo",

View File

@@ -150,7 +150,7 @@
"Update password failed": "修改密码异常", "Update password failed": "修改密码异常",
"Update password succseful": "修改密码成功", "Update password succseful": "修改密码成功",
"Usage Record": "使用记录", "Usage Record": "使用记录",
"promption": { "promotion": {
"register": "好友注册", "register": "好友注册",
"pay": "好友充值" "pay": "好友充值"
} }

View File

@@ -0,0 +1,3 @@
import { GET, POST } from './request';
export const textCensor = (data: { text: string }) => POST('/plugins/censor/text_baidu', data);

View File

@@ -1,6 +1,4 @@
import axios, { Method, InternalAxiosRequestConfig, AxiosResponse } from 'axios'; import axios, { Method, InternalAxiosRequestConfig, AxiosResponse } from 'axios';
import { clearToken, getToken } from '@/utils/user';
import { TOKEN_ERROR_CODE } from '@/service/errorCode';
interface ConfigType { interface ConfigType {
headers?: { [key: string]: string }; headers?: { [key: string]: string };
@@ -18,7 +16,7 @@ interface ResponseDataType {
*/ */
function requestStart(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig { function requestStart(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
if (config.headers) { if (config.headers) {
// config.headers.token = getToken(); config.headers.rootkey = process.env.ROOT_KEY;
} }
return config; return config;
@@ -53,14 +51,7 @@ function responseError(err: any) {
if (typeof err === 'string') { if (typeof err === 'string') {
return Promise.reject({ message: err }); return Promise.reject({ message: err });
} }
// 有报错响应
if (err?.code in TOKEN_ERROR_CODE) {
clearToken();
window.location.replace(
`/login?lastRoute=${encodeURIComponent(location.pathname + location.search)}`
);
return Promise.reject({ message: 'token过期重新登录' });
}
if (err?.response?.data) { if (err?.response?.data) {
return Promise.reject(err?.response?.data); return Promise.reject(err?.response?.data);
} }
@@ -69,6 +60,7 @@ function responseError(err: any) {
/* 创建请求实例 */ /* 创建请求实例 */
const instance = axios.create({ const instance = axios.create({
baseURL: global.systemEnv.pluginBaseUrl,
timeout: 60000, // 超时时间 timeout: 60000, // 超时时间
headers: { headers: {
'content-type': 'application/json' 'content-type': 'application/json'
@@ -80,7 +72,11 @@ instance.interceptors.request.use(requestStart, (err) => Promise.reject(err));
/* 响应拦截 */ /* 响应拦截 */
instance.interceptors.response.use(responseSuccess, (err) => Promise.reject(err)); instance.interceptors.response.use(responseSuccess, (err) => Promise.reject(err));
function request(url: string, data: any, config: ConfigType, method: Method): any { export function request(url: string, data: any, config: ConfigType, method: Method): any {
if (!global.systemEnv.pluginBaseUrl) {
return Promise.reject('请安装商业版插件~');
}
/* 去空 */ /* 去空 */
for (const key in data) { for (const key in data) {
if (data[key] === null || data[key] === undefined) { if (data[key] === null || data[key] === undefined) {
@@ -107,22 +103,18 @@ function request(url: string, data: any, config: ConfigType, method: Method): an
* @param {Object} config * @param {Object} config
* @returns * @returns
*/ */
export function GET<T>(url?: string, params = {}, config: ConfigType = {}): Promise<T> { export function GET<T>(url: string, params = {}, config: ConfigType = {}): Promise<T> {
if (!url) return Promise.reject('The Plugin is not installed');
return request(url, params, config, 'GET'); return request(url, params, config, 'GET');
} }
export function POST<T>(url?: string, data = {}, config: ConfigType = {}): Promise<T> { export function POST<T>(url: string, data = {}, config: ConfigType = {}): Promise<T> {
if (!url) return Promise.reject('The Plugin is not installed');
return request(url, data, config, 'POST'); return request(url, data, config, 'POST');
} }
export function PUT<T>(url?: string, data = {}, config: ConfigType = {}): Promise<T> { export function PUT<T>(url: string, data = {}, config: ConfigType = {}): Promise<T> {
if (!url) return Promise.reject('The Plugin is not installed');
return request(url, data, config, 'PUT'); return request(url, data, config, 'PUT');
} }
export function DELETE<T>(url?: string, data = {}, config: ConfigType = {}): Promise<T> { export function DELETE<T>(url: string, data = {}, config: ConfigType = {}): Promise<T> {
if (!url) return Promise.reject('The Plugin is not installed');
return request(url, data, config, 'DELETE'); return request(url, data, config, 'DELETE');
} }

View File

@@ -10,7 +10,7 @@ export const sendAuthCode = (data: {
username: string; username: string;
type: `${UserAuthTypeEnum}`; type: `${UserAuthTypeEnum}`;
googleToken: string; googleToken: string;
}) => POST('/user/sendAuthCode', data); }) => POST(`/plusApi/user/account/sendCode`, data);
export const getTokenLogin = () => GET<UserType>('/user/account/tokenLogin'); export const getTokenLogin = () => GET<UserType>('/user/account/tokenLogin');
export const gitLogin = (params: { code: string; inviterId?: string }) => export const gitLogin = (params: { code: string; inviterId?: string }) =>
@@ -27,7 +27,7 @@ export const postRegister = ({
password: string; password: string;
inviterId: string; inviterId: string;
}) => }) =>
POST<ResLogin>('/user/account/register', { POST<ResLogin>(`/plusApi/user/account/register`, {
username, username,
code, code,
inviterId, inviterId,
@@ -43,7 +43,7 @@ export const postFindPassword = ({
code: string; code: string;
password: string; password: string;
}) => }) =>
POST<ResLogin>('/user/account/updatePasswordByCode', { POST<ResLogin>(`/plusApi/user/account/updatePasswordByCode`, {
username, username,
code, code,
password: createHashPassword(password) password: createHashPassword(password)
@@ -74,9 +74,15 @@ export const getPayCode = (amount: number) =>
GET<{ GET<{
codeUrl: string; codeUrl: string;
payId: string; payId: string;
}>(`/user/getPayCode?amount=${amount}`); }>(`/plusApi/user/pay/getPayCode`, { amount });
export const checkPayResult = (payId: string) => GET<number>(`/user/checkPayResult?payId=${payId}`); export const checkPayResult = (payId: string) =>
GET<number>(`/plusApi/user/pay/checkPayResult`, { payId }).then(() => {
try {
GET('/user/account/paySuccess');
} catch (error) {}
return 'success';
});
export const getInforms = (data: RequestPaging) => export const getInforms = (data: RequestPaging) =>
POST<PagingData<informSchema>>(`/user/inform/list`, data); POST<PagingData<informSchema>>(`/user/inform/list`, data);

View File

@@ -1,10 +1,11 @@
import { useState, useMemo, useCallback } from 'react'; import { useState, useMemo, useCallback } from 'react';
import { sendAuthCode } from '@/api/user'; import { sendAuthCode } from '@/api/user';
import { UserAuthTypeEnum } from '@/constants/common'; import { UserAuthTypeEnum } from '@/constants/common';
let timer: any;
import { useToast } from './useToast'; import { useToast } from './useToast';
import { getClientToken } from '@/utils/plugin/google';
import { feConfigs } from '@/store/static'; import { feConfigs } from '@/store/static';
import { getErrText } from '@/utils/tools';
let timer: any;
export const useSendCode = () => { export const useSendCode = () => {
const { toast } = useToast(); const { toast } = useToast();
@@ -45,7 +46,7 @@ export const useSendCode = () => {
}); });
} catch (error: any) { } catch (error: any) {
toast({ toast({
title: error.message || '发送验证码异常', title: getErrText(error, '验证码发送异常'),
status: 'error' status: 'error'
}); });
} }
@@ -61,3 +62,20 @@ export const useSendCode = () => {
codeCountDown codeCountDown
}; };
}; };
export function getClientToken(googleClientVerKey?: string) {
if (!googleClientVerKey || typeof window.grecaptcha === 'undefined' || !window.grecaptcha?.ready)
return '';
return new Promise<string>((resolve, reject) => {
window.grecaptcha.ready(async () => {
try {
const token = await window.grecaptcha.execute(googleClientVerKey, {
action: 'submit'
});
resolve(token);
} catch (error) {
reject(error);
}
});
});
}

View File

@@ -109,7 +109,7 @@ const Promotion = () => {
<Tr> <Tr>
<Th></Th> <Th></Th>
<Th></Th> <Th></Th>
<Th></Th> <Th>()</Th>
</Tr> </Tr>
</Thead> </Thead>
<Tbody fontSize={'sm'}> <Tbody fontSize={'sm'}>

View File

@@ -0,0 +1,44 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { request } from '@/api/service/request';
import type { Method } from 'axios';
import { connectToDatabase } from '@/service/mongo';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const method = (req.method || 'POST') as Method;
const { path = [], ...query } = req.query as any;
const url = `/${path?.join('/')}`;
if (!url) {
throw new Error('url is empty');
}
const data = {
...req.body,
...query
};
const repose = await request(
url,
data,
{
// @ts-ignore
headers: req.headers
},
method
);
jsonRes(res, {
data: repose
});
} catch (error) {
jsonRes(res, {
code: 500,
error
});
}
}

View File

@@ -97,7 +97,6 @@ export async function getInitConfig() {
global.chatModels = res.ChatModels || defaultChatModels; global.chatModels = res.ChatModels || defaultChatModels;
global.qaModels = res.QAModels || defaultQAModels; global.qaModels = res.QAModels || defaultQAModels;
global.vectorModels = res.VectorModels || defaultVectorModels; global.vectorModels = res.VectorModels || defaultVectorModels;
global.systemPlugins = res.plugins || {};
} catch (error) { } catch (error) {
setDefaultData(); setDefaultData();
console.log('get init config error, set default', error); console.log('get init config error, set default', error);
@@ -110,5 +109,4 @@ export function setDefaultData() {
global.chatModels = defaultChatModels; global.chatModels = defaultChatModels;
global.qaModels = defaultQAModels; global.qaModels = defaultQAModels;
global.vectorModels = defaultVectorModels; global.vectorModels = defaultVectorModels;
global.systemPlugins = {};
} }

View File

@@ -0,0 +1,30 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { TrainingData } from '@/service/mongo';
import { startQueue } from '@/service/utils/tools';
import { authUser } from '@/service/utils/auth';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
const { userId } = await authUser({ req, authToken: true });
await unlockTask(userId);
} catch (error) {}
jsonRes(res);
}
async function unlockTask(userId: string) {
try {
await TrainingData.updateMany(
{
userId
},
{
lockTime: new Date('2000/1/1')
}
);
startQueue();
} catch (error) {
unlockTask(userId);
}
}

View File

@@ -1,64 +0,0 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { User } from '@/service/models/user';
import { connectToDatabase } from '@/service/mongo';
import { generateToken, setCookie } from '@/service/utils/tools';
import { UserAuthTypeEnum } from '@/constants/common';
import { authCode } from '@/service/api/plugins';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
const { username, code, password, inviterId } = req.body;
if (!username || !code || !password) {
throw new Error('缺少参数');
}
await connectToDatabase();
// 验证码校验
await authCode({
username,
type: UserAuthTypeEnum.register,
code
});
// 重名校验
const authRepeat = await User.findOne({
username
});
if (authRepeat) {
throw new Error('该用户已被注册');
}
const response = await User.create({
username,
password,
inviterId: inviterId ? inviterId : undefined
});
// 根据 id 获取用户信息
const user = await User.findById(response._id);
if (!user) {
throw new Error('获取用户信息异常');
}
const token = generateToken(user._id);
setCookie(res, token);
jsonRes(res, {
data: {
user,
token
}
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@@ -1,65 +0,0 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { User } from '@/service/models/user';
import { connectToDatabase } from '@/service/mongo';
import { UserAuthTypeEnum } from '@/constants/common';
import { generateToken, setCookie } from '@/service/utils/tools';
import { authCode } from '@/service/api/plugins';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
const { username, code, password } = req.body;
if (!username || !code || !password) {
throw new Error('缺少参数');
}
await connectToDatabase();
// 验证码校验
await authCode({
username,
code,
type: UserAuthTypeEnum.findPassword
});
if (!authCode) {
throw new Error('验证码错误');
}
// 更新对应的记录
await User.updateOne(
{
username
},
{
password
}
);
// 根据 username 获取用户信息
const user = await User.findOne({
username
});
if (!user) {
throw new Error('获取用户信息异常');
}
const token = generateToken(user._id);
setCookie(res, token);
jsonRes(res, {
data: {
user,
token
}
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@@ -1,112 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { User, Pay, TrainingData } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
import { PaySchema } from '@/types/mongoSchema';
import dayjs from 'dayjs';
import { startQueue } from '@/service/utils/tools';
import { getWxPayQRResult } from '@/service/api/plugins';
/* 校验支付结果 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { payId } = req.query as { payId: string };
const { userId } = await authUser({ req, authToken: true });
// 查找订单记录校验
const payOrder = await Pay.findById<PaySchema>(payId);
if (!payOrder) {
throw new Error('订单不存在');
}
if (payOrder.status !== 'NOTPAY') {
throw new Error('订单已结算');
}
// 获取当前用户
const user = await User.findById(userId);
if (!user) {
throw new Error('找不到用户');
}
const payRes = await getWxPayQRResult(payOrder.orderId);
if (payRes.trade_state === 'SUCCESS') {
// 订单已支付
try {
// 更新订单状态. 如果没有合适的订单,说明订单重复了
const updateRes = await Pay.updateOne(
{
_id: payId,
status: 'NOTPAY'
},
{
status: 'SUCCESS'
}
);
if (updateRes.modifiedCount === 1) {
// 给用户账号充钱
await User.findByIdAndUpdate(userId, {
$inc: { balance: payOrder.price }
});
unlockTask(userId);
return jsonRes(res, {
data: '支付成功'
});
}
} catch (error) {
console.log(error);
// roll back status
try {
await Pay.findByIdAndUpdate(payId, {
status: 'NOTPAY'
});
} catch (error) {}
}
return jsonRes(res, {
code: 500,
data: '更新订单失败,请重试'
});
}
// 校验下是否超过一天
const orderTime = dayjs(payOrder.createTime);
const diffInHours = dayjs().diff(orderTime, 'hours');
if (payRes.trade_state === 'CLOSED' || diffInHours > 24) {
// 订单已关闭
await Pay.findByIdAndUpdate(payId, {
status: 'CLOSED'
});
return jsonRes(res, {
code: 500,
data: '订单已过期'
});
}
throw new Error(payRes?.trade_state_desc || '订单无效');
} catch (err) {
// console.log(err);
jsonRes(res, {
code: 500,
error: err
});
}
}
async function unlockTask(userId: string) {
try {
await TrainingData.updateMany(
{
userId
},
{
lockTime: new Date('2000/1/1')
}
);
startQueue();
} catch (error) {
unlockTask(userId);
}
}

View File

@@ -1,37 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { authUser } from '@/service/utils/auth';
import { Pay } from '@/service/mongo';
import { PRICE_SCALE } from '@/constants/common';
import { getWxPayQRUrl } from '@/service/api/plugins';
/* 获取支付二维码 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
let { amount = 0 } = req.query as { amount: string };
amount = +amount;
const { userId } = await authUser({ req, authToken: true });
const { code_url, orderId } = await getWxPayQRUrl(amount);
// add one pay record
const payOrder = await Pay.create({
userId,
price: amount * PRICE_SCALE,
orderId
});
jsonRes(res, {
data: {
payId: payOrder._id,
codeUrl: code_url
}
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@@ -39,7 +39,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
jsonRes(res, { jsonRes(res, {
data: { data: {
invitedAmount, invitedAmount,
historyAmount: countHistory[0]?.totalAmount || 0 earningsAmount: countHistory[0]?.totalAmount || 0
} }
}); });
} catch (err) { } catch (err) {

View File

@@ -1,47 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { UserAuthTypeEnum } from '@/constants/common';
import { authGoogleToken } from '@/utils/plugin/google';
import requestIp from 'request-ip';
import { sendCode } from '@/service/api/plugins';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const { username, type, googleToken } = req.body as {
username: string;
type: `${UserAuthTypeEnum}`;
googleToken: string;
};
if (!username || !type) {
throw new Error('缺少参数');
}
// google auth
global.systemEnv.googleServiceVerKey &&
(await authGoogleToken({
secret: global.systemEnv.googleServiceVerKey,
response: googleToken,
remoteip: requestIp.getClientIp(req) || undefined
}));
// register switch
if (type === UserAuthTypeEnum.register && !global.feConfigs?.show_register) {
throw new Error('Register is closed');
}
await sendCode({
username,
type
});
jsonRes(res, {
message: '发送验证码成功'
});
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
}

View File

@@ -1,11 +0,0 @@
import { UserAuthTypeEnum } from '../../constants/common';
export type SendCodeBody = {
username: string;
type: `${UserAuthTypeEnum}`;
};
export type AuthCodeBody = {
username: string;
type: `${UserAuthTypeEnum}`;
code: string;
};

View File

@@ -1,21 +0,0 @@
import { GET, POST } from './request';
import type { SendCodeBody, AuthCodeBody } from './plugins.d';
export const sendCode = (data: SendCodeBody) => POST(global.systemPlugins.authCode?.sendUrl, data);
export const authCode = (data: AuthCodeBody) => POST(global.systemPlugins.authCode?.authUrl, data);
export const textCensor = (data: { text: string }) => {
if (!global.systemPlugins.censor?.textUrl) return;
return POST(global.systemPlugins.censor?.textUrl, data);
};
export const getWxPayQRUrl = (amount: number) =>
POST<{
code_url: string;
orderId: string;
}>(global.systemPlugins.pay?.getWxQRUrl, { amount });
export const getWxPayQRResult = (orderId: string) =>
POST<{
trade_state: string;
trade_state_desc: string;
}>(global.systemPlugins.pay?.getWxQRResult, { orderId });

View File

@@ -19,7 +19,7 @@ const PromotionRecordSchema = new Schema({
type: { type: {
type: String, type: String,
required: true, required: true,
enum: ['invite', 'register'] enum: ['pay', 'register']
}, },
amount: { amount: {
type: Number, type: Number,

View File

@@ -15,7 +15,7 @@ import { getChatModel } from '@/service/utils/data';
import { countModelPrice } from '@/service/events/pushBill'; import { countModelPrice } from '@/service/events/pushBill';
import { ChatModelItemType } from '@/types/model'; import { ChatModelItemType } from '@/types/model';
import { UserModelSchema } from '@/types/mongoSchema'; import { UserModelSchema } from '@/types/mongoSchema';
import { textCensor } from '@/service/api/plugins'; import { textCensor } from '@/api/service/plugins';
import { ChatCompletionRequestMessageRoleEnum } from 'openai'; import { ChatCompletionRequestMessageRoleEnum } from 'openai';
import { AppModuleItemType } from '@/types/app'; import { AppModuleItemType } from '@/types/app';

View File

@@ -54,16 +54,16 @@ export const jsonRes = <T = any>(
} }
addLog.error(msg, { addLog.error(msg, {
message: error.message, message: msg,
stack: error.stack, stack: error?.stack,
...(error.config && { ...(error?.config && {
config: { config: {
headers: error.config.headers, headers: error.config.headers,
url: error.config.url, url: error.config.url,
data: error.config.data data: error.config.data
} }
}), }),
...(error.response && { ...(error?.response && {
response: { response: {
status: error.response.status, status: error.response.status,
statusText: error.response.statusText statusText: error.response.statusText
@@ -111,16 +111,16 @@ export const sseErrRes = (res: NextApiResponse, error: any) => {
} }
addLog.error(`sse error: ${msg}`, { addLog.error(`sse error: ${msg}`, {
message: error.message, message: msg,
stack: error.stack, stack: error?.stack,
...(error.config && { ...(error?.config && {
config: { config: {
headers: error.config.headers, headers: error.config.headers,
url: error.config.url, url: error.config.url,
data: error.config.data data: error.config.data
} }
}), }),
...(error.response && { ...(error?.response && {
response: { response: {
status: error.response.status, status: error.response.status,
statusText: error.response.statusText statusText: error.response.statusText

View File

@@ -1,44 +0,0 @@
// @ts-ignore
import Payment from 'wxpay-v3';
export const getPayment = () => {
try {
return new Payment({
appid: process.env.WX_APPID,
mchid: process.env.WX_MCHID,
private_key: process.env.WX_PRIVATE_KEY?.replace(/\\n/g, '\n'),
serial_no: process.env.WX_SERIAL_NO,
apiv3_private_key: process.env.WX_V3_CODE,
notify_url: process.env.WX_NOTIFY_URL
});
} catch (error) {
return Promise.reject(error);
}
};
export const nativePay = async (amount: number, payId: string) => {
try {
const res = await getPayment().native({
description: 'Fast GPT 余额充值',
out_trade_no: payId,
amount: {
total: amount
}
});
return JSON.parse(res.data).code_url as string;
} catch (error) {
return Promise.reject(error);
}
};
export const getPayResult = async (payId: string) => {
try {
const res = await getPayment().getTransactionsByOutTradeNo({
out_trade_no: payId
});
return JSON.parse(res.data);
} catch (error) {
return Promise.reject(error);
}
};

View File

@@ -28,27 +28,13 @@ export type FeConfigsType = {
scripts?: { [key: string]: string }[]; scripts?: { [key: string]: string }[];
}; };
export type SystemEnvType = { export type SystemEnvType = {
googleServiceVerKey?: string; pluginBaseUrl?: string;
gitLoginSecret?: string; gitLoginSecret?: string;
vectorMaxProcess: number; vectorMaxProcess: number;
qaMaxProcess: number; qaMaxProcess: number;
pgIvfflatProbe: number; pgIvfflatProbe: number;
}; };
export type PluginType = {
authCode?: {
sendUrl: string;
authUrl: string;
};
censor?: {
textUrl?: string;
};
pay?: {
getWxQRUrl?: string;
getWxQRResult?: string;
};
};
declare global { declare global {
var mongodb: Mongoose | string | null; var mongodb: Mongoose | string | null;
var pgClient: Pool | null; var pgClient: Pool | null;
@@ -64,7 +50,6 @@ declare global {
var feConfigs: FeConfigsType; var feConfigs: FeConfigsType;
var systemEnv: SystemEnvType; var systemEnv: SystemEnvType;
var systemPlugins: PluginType;
var chatModels: ChatModelItemType[]; var chatModels: ChatModelItemType[];
var qaModels: QAModelItemType[]; var qaModels: QAModelItemType[];
var vectorModels: VectorModelItemType[]; var vectorModels: VectorModelItemType[];

View File

@@ -142,7 +142,7 @@ export interface PromotionRecordSchema {
_id: string; _id: string;
userId: string; // 收益人 userId: string; // 收益人
objUId?: string; // 目标对象如果是withdraw则为空 objUId?: string; // 目标对象如果是withdraw则为空
type: 'invite' | 'shareModel' | 'withdraw'; type: 'register' | 'pay';
createTime: Date; // 记录时间 createTime: Date; // 记录时间
amount: number; amount: number;
} }

View File

@@ -1,37 +0,0 @@
import axios from 'axios';
import { Obj2Query } from '../tools';
export const getClientToken = (googleClientVerKey?: string) => {
if (!googleClientVerKey || typeof window.grecaptcha === 'undefined' || !window.grecaptcha?.ready)
return '';
return new Promise<string>((resolve, reject) => {
window.grecaptcha.ready(async () => {
try {
const token = await window.grecaptcha.execute(googleClientVerKey, {
action: 'submit'
});
resolve(token);
} catch (error) {
reject(error);
}
});
});
};
// service run
export const authGoogleToken = async (data: {
secret: string;
response: string;
remoteip?: string;
}) => {
const res = await axios.post<{
score?: number;
success: boolean;
'error-codes': string[];
}>(`https://www.recaptcha.net/recaptcha/api/siteverify?${Obj2Query(data)}`);
if (res.data.success) {
return Promise.resolve('');
}
return Promise.reject(res?.data?.['error-codes']?.[0] || '非法环境');
};