This commit is contained in:
Archer
2023-10-30 13:26:42 +08:00
committed by GitHub
parent 008d0af010
commit 60ee160131
216 changed files with 4429 additions and 2229 deletions

View File

@@ -1,16 +1,12 @@
import { strIsLink } from '../string/tools';
export const fileImgs = [
{ suffix: 'pdf', src: '/imgs/files/pdf.svg' },
{ suffix: 'csv', src: '/imgs/files/csv.svg' },
{ suffix: '(doc|docs)', src: '/imgs/files/doc.svg' },
{ suffix: 'txt', src: '/imgs/files/txt.svg' },
{ suffix: 'md', src: '/imgs/files/markdown.svg' },
{ suffix: '.', src: '/imgs/files/file.svg' }
{ suffix: 'md', src: '/imgs/files/markdown.svg' }
// { suffix: '.', src: '/imgs/files/file.svg' }
];
export function getFileIcon(name = '') {
return (
fileImgs.find((item) => new RegExp(item.suffix, 'gi').test(name))?.src || '/imgs/files/file.svg'
);
export function getFileIcon(name = '', defaultImg = '/imgs/files/file.svg') {
return fileImgs.find((item) => new RegExp(item.suffix, 'gi').test(name))?.src || defaultImg;
}

View File

@@ -1,5 +1,6 @@
import { DatasetCollectionTypeEnum } from './constant';
import { getFileIcon } from '../../common/file/icon';
import { strIsLink } from '../../common/string/tools';
export function getCollectionIcon(
type: `${DatasetCollectionTypeEnum}` = DatasetCollectionTypeEnum.file,
@@ -7,9 +8,11 @@ export function getCollectionIcon(
) {
if (type === DatasetCollectionTypeEnum.folder) {
return '/imgs/files/folder.svg';
} else if (type === DatasetCollectionTypeEnum.link) {
}
if (type === DatasetCollectionTypeEnum.link) {
return '/imgs/files/link.svg';
} else if (type === DatasetCollectionTypeEnum.virtual) {
}
if (type === DatasetCollectionTypeEnum.virtual) {
if (name === '手动录入') {
return '/imgs/files/manual.svg';
} else if (name === '手动标注') {
@@ -19,3 +22,25 @@ export function getCollectionIcon(
}
return getFileIcon(name);
}
export function getSourceNameIcon({
sourceName,
sourceId
}: {
sourceName: string;
sourceId?: string;
}) {
if (strIsLink(sourceId)) {
return '/imgs/files/link.svg';
}
const fileIcon = getFileIcon(sourceName, '');
if (fileIcon) {
return fileIcon;
}
if (sourceName === '手动录入') {
return '/imgs/files/manual.svg';
} else if (sourceName === '手动标注') {
return '/imgs/files/mark.svg';
}
return '/imgs/files/collection.svg';
}

View File

@@ -0,0 +1,59 @@
export enum FlowNodeInputTypeEnum {
systemInput = 'systemInput', // history, userChatInput, variableInput
input = 'input', // one line input
textarea = 'textarea',
numberInput = 'numberInput',
select = 'select',
slider = 'slider',
custom = 'custom',
target = 'target', // data input
switch = 'switch',
chatInput = 'chatInput',
selectApp = 'selectApp',
// chat special input
aiSettings = 'aiSettings',
maxToken = 'maxToken',
selectChatModel = 'selectChatModel',
// dataset special input
selectDataset = 'selectDataset',
hidden = 'hidden'
}
export enum FlowNodeOutputTypeEnum {
answer = 'answer',
source = 'source',
hidden = 'hidden'
}
export enum FlowNodeTypeEnum {
empty = 'empty',
variable = 'variable',
userGuide = 'userGuide',
questionInput = 'questionInput',
historyNode = 'historyNode',
chatNode = 'chatNode',
datasetSearchNode = 'datasetSearchNode',
answerNode = 'answerNode',
classifyQuestion = 'classifyQuestion',
contentExtract = 'contentExtract',
httpRequest = 'httpRequest',
runApp = 'app',
pluginModule = 'pluginModule',
pluginInput = 'pluginInput',
pluginOutput = 'pluginOutput'
}
export enum FlowNodeSpecialInputKeyEnum {
'answerText' = 'text',
'agents' = 'agents', // cq agent key
'pluginId' = 'pluginId'
}
export enum FlowNodeValTypeEnum {
'string' = 'string',
'number' = 'number',
'boolean' = 'boolean',
'chatHistory' = 'chatHistory',
'datasetQuote' = 'datasetQuote',
'any' = 'any'
}

View File

@@ -0,0 +1,57 @@
import {
FlowNodeInputTypeEnum,
FlowNodeOutputTypeEnum,
FlowNodeValTypeEnum,
FlowNodeTypeEnum
} from './constant';
export type FlowNodeChangeProps = {
moduleId: string;
type:
| 'attr' // key: attr, value: new value
| 'updateInput' // key: update input key, value: new input value
| 'replaceInput' // key: old input key, value: new input value
| 'addInput' // key: null, value: new input value
| 'delInput' // key: delete input key, value: null
| 'updateOutput' // key: update output key, value: new output value
| 'replaceOutput' // key: old output key, value: new output value
| 'addOutput' // key: null, value: new output value
| 'delOutput'; // key: delete output key, value: null
key?: string;
value?: any;
index?: number;
};
export type FlowNodeInputItemType = {
key: string; // 字段名
value?: any;
valueType?: `${FlowNodeValTypeEnum}`;
type: `${FlowNodeInputTypeEnum}`;
label: string;
edit?: boolean;
connected?: boolean;
description?: string;
placeholder?: string;
max?: number;
min?: number;
step?: number;
required?: boolean;
list?: { label: string; value: any }[];
markList?: { label: string; value: any }[];
customData?: () => any;
valueCheck?: (value: any) => boolean;
};
export type FlowNodeOutputTargetItemType = {
moduleId: string;
key: string;
};
export type FlowNodeOutputItemType = {
key: string; // 字段名
label?: string;
edit?: boolean;
description?: string;
valueType?: `${FlowNodeValTypeEnum}`;
type?: `${FlowNodeOutputTypeEnum}`;
targets: FlowNodeOutputTargetItemType[];
};

44
packages/global/core/module/type.d.ts vendored Normal file
View File

@@ -0,0 +1,44 @@
import { FlowNodeTypeEnum } from './node/constant';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from './node/type';
export type FlowModuleTemplateType = {
id: string;
flowType: `${FlowNodeTypeEnum}`; // unique
logo?: string;
name: string;
description?: string;
intro?: string;
showStatus?: boolean; // chatting response step status
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
};
export type FlowModuleItemType = FlowModuleTemplateType & {
moduleId: string;
};
export type SystemModuleTemplateType = {
label: string;
list: FlowModuleTemplateType[];
}[];
export type ModuleItemType = {
name: string;
logo?: string;
intro?: string;
description?: string;
moduleId: string;
position?: {
x: number;
y: number;
};
flowType: `${FlowNodeTypeEnum}`;
showStatus?: boolean;
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
};
/* function type */
export type SelectAppItemType = {
id: string;
name: string;
logo: string;
};

View File

@@ -0,0 +1,47 @@
import {
FlowNodeInputTypeEnum,
FlowNodeSpecialInputKeyEnum,
FlowNodeTypeEnum
} from './node/constant';
import { FlowNodeInputItemType, FlowNodeOutputItemType } from './node/type';
import { ModuleItemType } from './type';
export function getPluginTemplatePluginIdInput(pluginId: string) {
return {
key: FlowNodeSpecialInputKeyEnum.pluginId,
type: FlowNodeInputTypeEnum.hidden,
label: 'pluginId',
value: pluginId,
connected: true
};
}
export function formatPluginIOModules(
pluginId: string,
modules: ModuleItemType[]
): {
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
} {
const pluginInput = modules.find((module) => module.flowType === FlowNodeTypeEnum.pluginInput);
const customOutput = modules.find((module) => module.flowType === FlowNodeTypeEnum.pluginOutput);
return {
inputs: pluginInput
? [
getPluginTemplatePluginIdInput(pluginId),
...pluginInput.inputs.map((item) => ({
...item,
edit: false,
connected: false
}))
]
: [],
outputs: customOutput
? customOutput.outputs.map((item) => ({
...item,
edit: false
}))
: []
};
}

View File

@@ -0,0 +1,28 @@
import { ModuleItemType } from '../module/type';
export const defaultModules: ModuleItemType[] = [
{
moduleId: 'fph4s3',
name: '自定义输出',
flowType: 'pluginOutput',
showStatus: false,
position: {
x: 994.1266684738011,
y: -45.87689365278443
},
inputs: [],
outputs: []
},
{
moduleId: 'w09v30',
name: '自定义输入',
flowType: 'pluginInput',
showStatus: false,
position: {
x: 457.57860319995154,
y: -44.25099042468186
},
inputs: [],
outputs: []
}
];

View File

@@ -0,0 +1,21 @@
import type { ModuleItemType } from '../module/type.d';
export type CreateOnePluginParams = {
name: string;
avatar: string;
intro: string;
modules?: ModuleItemType[];
};
export type UpdatePluginParams = {
id: string;
name?: string;
avatar?: string;
intro?: string;
modules?: ModuleItemType[];
};
export type PluginListItemType = {
_id: string;
name: string;
avatar: string;
intro: string;
};

11
packages/global/core/plugin/type.d.ts vendored Normal file
View File

@@ -0,0 +1,11 @@
import type { ModuleItemType } from '../module/type.d';
export type PluginItemSchema = {
_id: string;
userId: string;
name: string;
avatar: string;
intro: string;
updateTime: Date;
modules: ModuleItemType[];
};

View File

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

View File

@@ -0,0 +1,9 @@
export enum InformTypeEnum {
system = 'system'
}
export const InformTypeMap = {
[InformTypeEnum.system]: {
label: '系统通知'
}
};

View File

@@ -1,3 +1,5 @@
import { InformTypeEnum } from './constant';
export type UserModelSchema = {
_id: string;
username: string;
@@ -18,3 +20,13 @@ export type UserModelSchema = {
datasetMaxCount?: number;
};
};
export type UserInformSchema = {
_id: string;
userId: string;
time: Date;
type: `${InformTypeEnum}`;
title: string;
content: string;
read: boolean;
};

View File

@@ -0,0 +1,8 @@
export type PaySchema = {
_id: string;
userId: string;
createTime: Date;
price: number;
orderId: string;
status: 'SUCCESS' | 'REFUND' | 'NOTPAY' | 'CLOSED';
};

View File

@@ -0,0 +1 @@
export const imageBaseUrl = '/api/system/img/';

View File

@@ -0,0 +1,25 @@
import { imageBaseUrl } from './constant';
import { MongoImage } from './schema';
export function getMongoImgUrl(id: string) {
return `${imageBaseUrl}${id}`;
}
export async function uploadMongoImg({ base64Img, userId }: { base64Img: string; userId: string }) {
const base64Data = base64Img.split(',')[1];
const { _id } = await MongoImage.create({
userId,
binary: Buffer.from(base64Data, 'base64')
});
return getMongoImgUrl(String(_id));
}
export async function readMongoImg({ id }: { id: string }) {
const data = await MongoImage.findById(id);
if (!data) {
return Promise.reject('Image not found');
}
return data?.binary;
}

View File

@@ -0,0 +1,16 @@
import { connectionMongo, type Model } from '../../mongo';
const { Schema, model, models } = connectionMongo;
const ImageSchema = new Schema({
userId: {
type: Schema.Types.ObjectId,
ref: 'user',
required: true
},
binary: {
type: Buffer
}
});
export const MongoImage: Model<{ userId: string; binary: Buffer }> =
models['image'] || model('image', ImageSchema);

View File

@@ -63,6 +63,7 @@ const TrainingDataSchema = new Schema({
try {
TrainingDataSchema.index({ lockTime: 1 });
TrainingDataSchema.index({ userId: 1 });
TrainingDataSchema.index({ datasetCollectionId: 1 });
TrainingDataSchema.index({ expireAt: 1 }, { expireAfterSeconds: 7 * 24 * 60 });
} catch (error) {
console.log(error);

View File

@@ -0,0 +1,63 @@
import { CreateOnePluginParams, UpdatePluginParams } from '@fastgpt/global/core/plugin/controller';
import { MongoPlugin } from './schema';
import { FlowModuleTemplateType } from '@fastgpt/global/core/module/type';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
import { formatPluginIOModules } from '@fastgpt/global/core/module/utils';
export async function createOnePlugin(data: CreateOnePluginParams & { userId: string }) {
const { _id } = await MongoPlugin.create(data);
return _id;
}
export async function updateOnePlugin({
id,
userId,
...data
}: UpdatePluginParams & { userId: string }) {
await MongoPlugin.findOneAndUpdate({ _id: id, userId }, data);
}
export async function deleteOnePlugin({ id, userId }: { id: string; userId: string }) {
await MongoPlugin.findOneAndDelete({ _id: id, userId });
}
export async function getUserPlugins({ userId }: { userId: string }) {
return MongoPlugin.find({ userId }, 'name avatar intro');
}
export async function getOnePluginDetail({ id, userId }: { userId: string; id: string }) {
return MongoPlugin.findOne({ _id: id, userId });
}
/* plugin templates */
export async function getUserPlugins2Templates({
userId
}: {
userId: string;
}): Promise<FlowModuleTemplateType[]> {
const plugins = await MongoPlugin.find({ userId }).lean();
return plugins.map((plugin) => ({
id: String(plugin._id),
flowType: FlowNodeTypeEnum.pluginModule,
logo: plugin.avatar,
name: plugin.name,
description: plugin.intro,
intro: plugin.intro,
showStatus: false,
inputs: [],
outputs: []
}));
}
/* one plugin 2 module detail */
export async function getPluginModuleDetail({ id, userId }: { userId: string; id: string }) {
const plugin = await getOnePluginDetail({ id, userId });
if (!plugin) return Promise.reject('plugin not found');
return {
id: String(plugin._id),
flowType: FlowNodeTypeEnum.pluginModule,
logo: plugin.avatar,
name: plugin.name,
description: plugin.intro,
intro: plugin.intro,
showStatus: false,
...formatPluginIOModules(String(plugin._id), plugin.modules)
};
}

View File

@@ -0,0 +1,42 @@
import { connectionMongo, type Model } from '../../common/mongo';
const { Schema, model, models } = connectionMongo;
import type { PluginItemSchema } from '@fastgpt/global/core/plugin/type.d';
export const ModuleCollectionName = 'plugins';
const PluginSchema = new Schema({
userId: {
type: Schema.Types.ObjectId,
ref: 'user',
required: true
},
name: {
type: String,
required: true
},
avatar: {
type: String,
default: '/icon/logo.svg'
},
intro: {
type: String,
default: ''
},
updateTime: {
type: Date,
default: () => new Date()
},
modules: {
type: Array,
default: []
}
});
try {
PluginSchema.index({ userId: 1 });
} catch (error) {
console.log(error);
}
export const MongoPlugin: Model<PluginItemSchema> =
models[ModuleCollectionName] || model(ModuleCollectionName, PluginSchema);

View File

@@ -0,0 +1,32 @@
import { connectionMongo, type Model } from '../../../common/mongo';
const { Schema, model, models } = connectionMongo;
import { PromotionRecordSchema as PromotionRecordType } from '@fastgpt/global/support/activity/type.d';
const PromotionRecordSchema = new Schema({
userId: {
type: Schema.Types.ObjectId,
ref: 'user',
required: true
},
objUId: {
type: Schema.Types.ObjectId,
ref: 'user',
required: false
},
createTime: {
type: Date,
default: () => new Date()
},
type: {
type: String,
required: true,
enum: ['pay', 'register']
},
amount: {
type: Number,
required: true
}
});
export const MongoPromotionRecord: Model<PromotionRecordType> =
models['promotionRecord'] || model('promotionRecord', PromotionRecordSchema);

View File

@@ -0,0 +1,45 @@
import { MongoUserInform } from './schema';
import { MongoUser } from '../schema';
import { InformTypeEnum } from '@fastgpt/global/support/user/constant';
export type SendInformProps = {
type: `${InformTypeEnum}`;
title: string;
content: string;
};
export async function sendInform2AllUser({ type, title, content }: SendInformProps) {
const users = await MongoUser.find({}, '_id');
await MongoUserInform.insertMany(
users.map(({ _id }) => ({
type,
title,
content,
userId: _id
}))
);
}
export async function sendInform2OneUser({
type,
title,
content,
userId
}: SendInformProps & { userId: string }) {
const inform = await MongoUserInform.findOne({
type,
title,
content,
userId,
time: { $gte: new Date(Date.now() - 5 * 60 * 1000) }
});
if (inform) return;
await MongoUserInform.create({
type,
title,
content,
userId
});
}

View File

@@ -0,0 +1,42 @@
import { connectionMongo, type Model } from '../../../common/mongo';
const { Schema, model, models } = connectionMongo;
import type { UserInformSchema } from '@fastgpt/global/support/user/type.d';
import { InformTypeMap } from '@fastgpt/global/support/user/constant';
const InformSchema = new Schema({
userId: {
type: Schema.Types.ObjectId,
ref: 'user',
required: true
},
time: {
type: Date,
default: () => new Date()
},
type: {
type: String,
enum: Object.keys(InformTypeMap)
},
title: {
type: String,
required: true
},
content: {
type: String,
required: true
},
read: {
type: Boolean,
default: false
}
});
try {
InformSchema.index({ time: -1 });
InformSchema.index({ userId: 1 });
} catch (error) {
console.log(error);
}
export const MongoUserInform: Model<UserInformSchema> =
models['inform'] || model('inform', InformSchema);

View File

@@ -0,0 +1,31 @@
import { connectionMongo, type Model } from '../../../common/mongo';
const { Schema, model, models } = connectionMongo;
import { PaySchema as PayType } from '@fastgpt/global/support/wallet/type.d';
const PaySchema = new Schema({
userId: {
type: Schema.Types.ObjectId,
ref: 'user',
required: true
},
createTime: {
type: Date,
default: () => new Date()
},
price: {
type: Number,
required: true
},
orderId: {
type: String,
required: true
},
status: {
// 支付的状态
type: String,
default: 'NOTPAY',
enum: ['SUCCESS', 'REFUND', 'NOTPAY', 'CLOSED']
}
});
export const MongoPay: Model<PayType> = models['pay'] || model('pay', PaySchema);