diff --git a/docSite/content/zh-cn/docs/development/configuration.md b/docSite/content/zh-cn/docs/development/configuration.md index eb5b6b653818..57a7fa1262fe 100644 --- a/docSite/content/zh-cn/docs/development/configuration.md +++ b/docSite/content/zh-cn/docs/development/configuration.md @@ -21,16 +21,16 @@ weight: 708 "lafEnv": "https://laf.dev" // laf环境。 https://laf.run (杭州阿里云) ,或者私有化的laf环境。如果使用 Laf openapi 功能,需要最新版的 laf 。 }, "systemEnv": { - "vectorMaxProcess": 15, - "qaMaxProcess": 15, + "vectorMaxProcess": 15, // 向量处理线程数量 + "qaMaxProcess": 15, // 问答拆分线程数量 "tokenWorkers": 50, // Token 计算线程保持数,会持续占用内存,不能设置太大。 "pgHNSWEfSearch": 100 // 向量搜索参数。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。 }, "llmModels": [ { + "provider": "OpenAI", // 模型提供商,主要用于分类展示,目前已经内置提供商包括:https://github.com/labring/FastGPT/blob/main/packages/global/core/ai/provider.ts, 可 pr 提供新的提供商,或直接填写 Other "model": "gpt-4o-mini", // 模型名(对应OneAPI中渠道的模型名) "name": "gpt-4o-mini", // 模型别名 - "avatar": "/imgs/model/openai.svg", // 模型的logo "maxContext": 125000, // 最大上下文 "maxResponse": 16000, // 最大回复 "quoteMaxToken": 120000, // 最大引用内容 @@ -38,7 +38,7 @@ weight: 708 "charsPointsPrice": 0, // n积分/1k token(商业版) "censor": false, // 是否开启敏感校验(商业版) "vision": true, // 是否支持图片输入 - "datasetProcess": true, // 是否设置为知识库处理模型(QA),务必保证至少有一个为true,否则知识库会报错 + "datasetProcess": true, // 是否设置为文本理解模型(QA),务必保证至少有一个为true,否则知识库会报错 "usedInClassify": true, // 是否用于问题分类(务必保证至少有一个为true) "usedInExtractFields": true, // 是否用于内容提取(务必保证至少有一个为true) "usedInToolCall": true, // 是否用于工具调用(务必保证至少有一个为true) @@ -48,12 +48,13 @@ weight: 708 "customCQPrompt": "", // 自定义文本分类提示词(不支持工具和函数调用的模型 "customExtractPrompt": "", // 自定义内容提取提示词 "defaultSystemChatPrompt": "", // 对话默认携带的系统提示词 - "defaultConfig": {} // 请求API时,挟带一些默认配置(比如 GLM4 的 top_p) + "defaultConfig": {}, // 请求API时,挟带一些默认配置(比如 GLM4 的 top_p) + "fieldMap": {} // 字段映射(o1 模型需要把 max_tokens 映射为 max_completion_tokens) }, { + "provider": "OpenAI", "model": "gpt-4o", "name": "gpt-4o", - "avatar": "/imgs/model/openai.svg", "maxContext": 125000, "maxResponse": 4000, "quoteMaxToken": 120000, @@ -71,14 +72,15 @@ weight: 708 "customCQPrompt": "", "customExtractPrompt": "", "defaultSystemChatPrompt": "", - "defaultConfig": {} + "defaultConfig": {}, + "fieldMap": {} }, { + "provider": "OpenAI", "model": "o1-mini", "name": "o1-mini", - "avatar": "/imgs/model/openai.svg", "maxContext": 125000, - "maxResponse": 4000, + "maxResponse": 65000, "quoteMaxToken": 120000, "maxTemperature": 1.2, "charsPointsPrice": 0, @@ -99,11 +101,11 @@ weight: 708 } }, { + "provider": "OpenAI", "model": "o1-preview", "name": "o1-preview", - "avatar": "/imgs/model/openai.svg", "maxContext": 125000, - "maxResponse": 4000, + "maxResponse": 32000, "quoteMaxToken": 120000, "maxTemperature": 1.2, "charsPointsPrice": 0, @@ -126,21 +128,18 @@ weight: 708 ], "vectorModels": [ { - "model": "text-embedding-ada-002", // 模型名(与OneAPI对应) - "name": "Embedding-2", // 模型展示名 - "avatar": "/imgs/model/openai.svg", // logo - "charsPointsPrice": 0, // n积分/1k token - "defaultToken": 700, // 默认文本分割时候的 token - "maxToken": 3000, // 最大 token - "weight": 100, // 优先训练权重 - "defaultConfig": {}, // 自定义额外参数。例如,如果希望使用 embedding3-large 的话,可以传入 dimensions:1024,来返回1024维度的向量。(目前必须小于1536维度) - "dbConfig": {}, // 存储时的额外参数(非对称向量模型时候需要用到) - "queryConfig": {} // 参训时的额外参数 + "provider": "OpenAI", + "model": "text-embedding-3-small", + "name": "text-embedding-3-small", + "charsPointsPrice": 0, + "defaultToken": 512, + "maxToken": 3000, + "weight": 100 }, { + "provider": "OpenAI", "model": "text-embedding-3-large", "name": "text-embedding-3-large", - "avatar": "/imgs/model/openai.svg", "charsPointsPrice": 0, "defaultToken": 512, "maxToken": 3000, @@ -150,13 +149,16 @@ weight: 708 } }, { - "model": "text-embedding-3-small", - "name": "text-embedding-3-small", - "avatar": "/imgs/model/openai.svg", - "charsPointsPrice": 0, - "defaultToken": 512, - "maxToken": 3000, - "weight": 100 + "provider": "OpenAI", + "model": "text-embedding-ada-002", // 模型名(与OneAPI对应) + "name": "Embedding-2", // 模型展示名 + "charsPointsPrice": 0, // n积分/1k token + "defaultToken": 700, // 默认文本分割时候的 token + "maxToken": 3000, // 最大 token + "weight": 100, // 优先训练权重 + "defaultConfig": {}, // 自定义额外参数。例如,如果希望使用 embedding3-large 的话,可以传入 dimensions:1024,来返回1024维度的向量。(目前必须小于1536维度) + "dbConfig": {}, // 存储时的额外参数(非对称向量模型时候需要用到) + "queryConfig": {} // 参训时的额外参数 } ], "reRankModels": [], @@ -183,25 +185,33 @@ weight: 708 } ``` -## 关于模型 logo +## 模型提供商 + +为了方便模型分类展示,FastGPT 内置了部分模型提供商的名字和 Logo。如果你期望补充提供商,可[提交 Issue](https://github.com/labring/FastGPT/issues),并提供几个信息: + +1. 厂商官网地址 +2. 厂商 SVG logo,建议是正方形图片。 + +目前已支持的提供商, 复制 "-" 之前的字符串,作为 provider 的值。 -统一放置在项目的`public/imgs/model/xxx`目录中,目前内置了以下几种,如果有需要,可以PR增加。默认logo为 Hugging face 的 logo~ +- OpenAI +- Claude +- Gemini +- MistralAI +- Qwen - 通义千问 +- Doubao - 豆包 +- ChatGLM - 智谱 +- DeepSeek - 深度求索 +- Moonshot - 月之暗面 +- MiniMax +- SparkDesk - 讯飞星火 +- Hunyuan - 腾讯混元 +- Baichuan - 百川 +- Yi - 零一万物 +- Ernie - 文心一言 +- Ollama +- Other - 其他 -- /imgs/model/baichuan.svg - 百川智能 -- /imgs/model/chatglm.svg - 智谱清言 -- /imgs/model/claude.svg - claude -- /imgs/model/deepseek.svg - deepseek -- /imgs/model/doubao.svg - 火山豆包 -- /imgs/model/ernie.svg - 文心一言 -- /imgs/model/gemini.svg - gemini -- /imgs/model/huggingface.svg - Hugging face【默认logo】 -- /imgs/model/minimax.svg - minimax -- /imgs/model/moonshot.svg - 月之暗面 -- /imgs/model/openai.svg - OpenAI GPT -- /imgs/model/qwen.svg - 通义千问 -- /imgs/model/sparkDesk.svg - 讯飞星火 -- /imgs/model/yi.svg - 零一万物 -- /imgs/model/hunyuan.svg - 腾讯混元 ## 特殊模型 diff --git a/docSite/content/zh-cn/docs/development/upgrading/4816.md b/docSite/content/zh-cn/docs/development/upgrading/4816.md index 702d7987c825..9760f7840ed9 100644 --- a/docSite/content/zh-cn/docs/development/upgrading/4816.md +++ b/docSite/content/zh-cn/docs/development/upgrading/4816.md @@ -7,6 +7,46 @@ toc: true weight: 808 --- +## 更新指南 + +### 1. 更新镜像: + +- 更新 fastgpt 镜像 tag: v4.8.16-beta +- 更新 fastgpt-pro 商业版镜像 tag: v4.8.16-beta +- Sandbox 镜像 tag: v4.8.16-beta + +### 2. 更新配置文件 + +参考最新的[配置文件](/docs/development/configuration/),更新 `config.json` 或 admin 中模型文件配置。给 LLMModel 和 VectorModel 增加 `provider` 字段,以便进行模型分类。例如: + +```json +{ + "provider": "OpenAI", // 这是新增的 + "model": "gpt-4o", + "name": "gpt-4o", + "maxContext": 125000, + "maxResponse": 4000, + "quoteMaxToken": 120000, + "maxTemperature": 1.2, + "charsPointsPrice": 0, + "censor": false, + "vision": true, + "datasetProcess": true, + "usedInClassify": true, + "usedInExtractFields": true, + "usedInToolCall": true, + "usedInQueryExtension": true, + "toolChoice": true, + "functionCall": false, + "customCQPrompt": "", + "customExtractPrompt": "", + "defaultSystemChatPrompt": "", + "defaultConfig": {}, + "fieldMap": {} +} +``` + + ## 完整更新内容 @@ -18,12 +58,14 @@ weight: 808 6. 新增 - 商业版支持飞书和语雀知识库导入。[点击查看教程](/docs/guide/knowledge_base/lark_dataset/) 7. 新增 - sandbox 新增 createHmac 加密全局方法。 8. 新增 - 工作流右键支持全部折叠。 -9. 优化 - 工作流/简易模式变量初始化代码,去除监听初始化,避免因渲染顺序不一致导致的失败。 -10. 优化 - 工作流获取数据类型不一致数据时,增加类型转化,避免 undefined。 -11. 修复 - 无法自动切换默认语言。增加分享链接,强制执行一次切换默认语言。 -12. 修复 - 数组选择器自动兼容 4.8.13 以前的数据。 -13. 修复 - 站点同步知识库,链接同步时未使用选择器。 -14. 修复 - 简易模式转工作流,没有把系统配置项转化。 -15. 修复 - 插件独立运行,变量初始值未赋上。 -16. 修复 - 工作流使用弹窗组件时,关闭弹窗后,有时候会出现页面偏移。 -17. 修复 - 插件调试时,日志未保存插件输入参数。 \ No newline at end of file +9. 优化 - 模型选择器。 +10. 优化 - SSR 渲染,预判断是移动端还是 pc 端,减少页面抖动。 +11. 优化 - 工作流/简易模式变量初始化代码,去除监听初始化,避免因渲染顺序不一致导致的失败。 +12. 优化 - 工作流获取数据类型不一致数据时,增加类型转化,避免 undefined。 +13. 修复 - 无法自动切换默认语言。增加分享链接,强制执行一次切换默认语言。 +14. 修复 - 数组选择器自动兼容 4.8.13 以前的数据。 +15. 修复 - 站点同步知识库,链接同步时未使用选择器。 +16. 修复 - 简易模式转工作流,没有把系统配置项转化。 +17. 修复 - 插件独立运行,变量初始值未赋上。 +18. 修复 - 工作流使用弹窗组件时,关闭弹窗后,有时候会出现页面偏移。 +19. 修复 - 插件调试时,日志未保存插件输入参数。 \ No newline at end of file diff --git a/packages/global/common/system/constants.ts b/packages/global/common/system/constants.ts index 5c6b192d6075..1ca44a6118d7 100644 --- a/packages/global/common/system/constants.ts +++ b/packages/global/common/system/constants.ts @@ -2,3 +2,5 @@ export const HUMAN_ICON = `/icon/human.svg`; export const LOGO_ICON = `/icon/logo.svg`; export const HUGGING_FACE_ICON = `/imgs/model/huggingface.svg`; export const DEFAULT_TEAM_AVATAR = `/imgs/avatar/defaultTeamAvatar.svg`; + +export const isProduction = process.env.NODE_ENV === 'production'; diff --git a/packages/global/core/ai/model.d.ts b/packages/global/core/ai/model.d.ts index 1d31fa83c748..38687fbc2a6d 100644 --- a/packages/global/core/ai/model.d.ts +++ b/packages/global/core/ai/model.d.ts @@ -1,7 +1,10 @@ +import type { ModelProviderIdType } from './provider'; + export type LLMModelItemType = { + provider: ModelProviderIdType; model: string; name: string; - avatar?: string; + avatar?: string; // model icon, from provider maxContext: number; maxResponse: number; quoteMaxToken: number; @@ -31,6 +34,7 @@ export type LLMModelItemType = { }; export type VectorModelItemType = { + provider: ModelProviderIdType; model: string; // model name name: string; // show name avatar?: string; diff --git a/packages/global/core/ai/model.ts b/packages/global/core/ai/model.ts index f40e31354d1b..ff6d07f59331 100644 --- a/packages/global/core/ai/model.ts +++ b/packages/global/core/ai/model.ts @@ -1,7 +1,9 @@ import type { LLMModelItemType, VectorModelItemType } from './model.d'; +import { getModelProvider, ModelProviderIdType } from './provider'; export const defaultQAModels: LLMModelItemType[] = [ { + provider: 'OpenAI', model: 'gpt-4o-mini', name: 'gpt-4o-mini', maxContext: 16000, @@ -23,6 +25,7 @@ export const defaultQAModels: LLMModelItemType[] = [ export const defaultVectorModels: VectorModelItemType[] = [ { + provider: 'OpenAI', model: 'text-embedding-3-small', name: 'Embedding-2', charsPointsPrice: 0, @@ -31,3 +34,15 @@ export const defaultVectorModels: VectorModelItemType[] = [ weight: 100 } ]; + +export const getModelFromList = ( + modelList: { provider: ModelProviderIdType; name: string; model: string }[], + model: string +) => { + const modelData = modelList.find((item) => item.model === model) ?? modelList[0]; + const provider = getModelProvider(modelData.provider); + return { + ...modelData, + avatar: provider.avatar + }; +}; diff --git a/packages/global/core/ai/provider.ts b/packages/global/core/ai/provider.ts new file mode 100644 index 000000000000..8ca7bfcaa587 --- /dev/null +++ b/packages/global/core/ai/provider.ts @@ -0,0 +1,121 @@ +import { i18nT } from '../../../web/i18n/utils'; + +export type ModelProviderIdType = + | 'OpenAI' + | 'Claude' + | 'Gemini' + | 'MistralAI' + | 'Qwen' + | 'Doubao' + | 'ChatGLM' + | 'DeepSeek' + | 'Moonshot' + | 'MiniMax' + | 'SparkDesk' + | 'Hunyuan' + | 'Baichuan' + | 'Yi' + | 'Ernie' + | 'Ollama' + | 'Other'; + +export type ModelProviderType = { + id: ModelProviderIdType; + name: string; + avatar: string; +}; + +export const ModelProviderList: ModelProviderType[] = [ + { + id: 'OpenAI', + name: 'OpenAI', + avatar: 'model/openai' + }, + { + id: 'Claude', + name: 'Claude', + avatar: 'model/claude' + }, + { + id: 'Gemini', + name: 'Gemini', + avatar: 'model/gemini' + }, + { + id: 'MistralAI', + name: 'MistralAI', + avatar: 'model/huggingface' + }, + { + id: 'Qwen', + name: i18nT('common:model_qwen'), + avatar: 'model/qwen' + }, + { + id: 'Doubao', + name: i18nT('common:model_doubao'), + avatar: 'model/doubao' + }, + { + id: 'ChatGLM', + name: i18nT('common:model_chatglm'), + avatar: 'model/chatglm' + }, + { + id: 'DeepSeek', + name: 'DeepSeek', + avatar: 'model/deepseek' + }, + { + id: 'Moonshot', + name: i18nT('common:model_moonshot'), + avatar: 'model/moonshot' + }, + { + id: 'MiniMax', + name: 'MiniMax', + avatar: 'model/minimax' + }, + { + id: 'SparkDesk', + name: i18nT('common:model_sparkdesk'), + avatar: 'model/sparkDesk' + }, + { + id: 'Hunyuan', + name: i18nT('common:model_hunyuan'), + avatar: 'model/hunyuan' + }, + { + id: 'Baichuan', + name: i18nT('common:model_baichuan'), + avatar: 'model/baichuan' + }, + { + id: 'Yi', + name: i18nT('common:model_yi'), + avatar: 'model/yi' + }, + { + id: 'Ernie', + name: i18nT('common:model_ernie'), + avatar: 'model/ernie' + }, + { + id: 'Ollama', + name: 'Ollama', + avatar: 'model/ollama' + }, + { + id: 'Other', + name: i18nT('common:model_other'), + avatar: 'model/huggingface' + } +]; +export const ModelProviderMap = Object.fromEntries( + ModelProviderList.map((item) => [item.id, item]) +); + +export const getModelProvider = (provider: ModelProviderIdType) => { + return ModelProviderMap[provider] ?? ModelProviderMap.Other; +}; diff --git a/packages/service/common/file/constants.ts b/packages/service/common/file/constants.ts index a3449c4beb52..3245e5f8dbc1 100644 --- a/packages/service/common/file/constants.ts +++ b/packages/service/common/file/constants.ts @@ -1,6 +1,6 @@ import path from 'path'; +import { isProduction } from '@fastgpt/global/common/system/constants'; -export const tmpFileDirPath = - process.env.NODE_ENV === 'production' ? '/app/tmp' : path.join(process.cwd(), 'tmp'); +export const tmpFileDirPath = isProduction ? '/app/tmp' : path.join(process.cwd(), 'tmp'); export const previewMaxCharCount = 3000; diff --git a/packages/service/common/file/utils.ts b/packages/service/common/file/utils.ts index 938187f96065..3a623e597e01 100644 --- a/packages/service/common/file/utils.ts +++ b/packages/service/common/file/utils.ts @@ -1,4 +1,4 @@ -import { isProduction } from '../system/constants'; +import { isProduction } from '@fastgpt/global/common/system/constants'; import fs from 'fs'; import path from 'path'; diff --git a/packages/service/common/system/constants.ts b/packages/service/common/system/constants.ts index af250cfdc4f1..1fe15f292acf 100644 --- a/packages/service/common/system/constants.ts +++ b/packages/service/common/system/constants.ts @@ -1,3 +1 @@ export const FastGPTProUrl = process.env.PRO_URL ? `${process.env.PRO_URL}/api` : ''; - -export const isProduction = process.env.NODE_ENV === 'production'; diff --git a/packages/web/common/system/nextjs.ts b/packages/web/common/system/nextjs.ts new file mode 100644 index 000000000000..60b0c7bac532 --- /dev/null +++ b/packages/web/common/system/nextjs.ts @@ -0,0 +1,15 @@ +import { I18nNsType } from '../../types/i18next'; +import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; + +export const serviceSideProps = async (content: any, ns: I18nNsType = []) => { + const lang = content.req?.cookies?.NEXT_LOCALE || content.locale; + const extraLng = content.req?.cookies?.NEXT_LOCALE ? undefined : content.locales; + + // Device size + const deviceSize = content.req?.cookies?.NEXT_DEVICE_SIZE || 'pc'; + + return { + ...(await serverSideTranslations(lang, ['common', ...ns], null, extraLng)), + deviceSize + }; +}; diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts index 1308d0f1e043..51c616371daf 100644 --- a/packages/web/components/common/Icon/constants.ts +++ b/packages/web/components/common/Icon/constants.ts @@ -29,6 +29,7 @@ export const iconPaths = { 'common/courseLight': () => import('./icons/common/courseLight.svg'), 'common/customTitleLight': () => import('./icons/common/customTitleLight.svg'), 'common/data': () => import('./icons/common/data.svg'), + 'common/dingtalkFill': () => import('./icons/common/dingtalkFill.svg'), 'common/editor/resizer': () => import('./icons/common/editor/resizer.svg'), 'common/errorFill': () => import('./icons/common/errorFill.svg'), 'common/file/move': () => import('./icons/common/file/move.svg'), @@ -91,7 +92,6 @@ export const iconPaths = { 'common/voiceLight': () => import('./icons/common/voiceLight.svg'), 'common/warn': () => import('./icons/common/warn.svg'), 'common/wechatFill': () => import('./icons/common/wechatFill.svg'), - 'common/dingtalkFill': () => import('./icons/common/dingtalkFill.svg'), configmap: () => import('./icons/configmap.svg'), copy: () => import('./icons/copy.svg'), 'core/app/aiFill': () => import('./icons/core/app/aiFill.svg'), @@ -256,7 +256,6 @@ export const iconPaths = { 'core/workflow/template/formInput': () => import('./icons/core/workflow/template/formInput.svg'), 'core/workflow/template/getTime': () => import('./icons/core/workflow/template/getTime.svg'), 'core/workflow/template/google': () => import('./icons/core/workflow/template/google.svg'), - 'core/workflow/template/searxng': () => import('./icons/core/workflow/template/searxng.svg'), 'core/workflow/template/httpRequest': () => import('./icons/core/workflow/template/httpRequest.svg'), 'core/workflow/template/ifelse': () => import('./icons/core/workflow/template/ifelse.svg'), @@ -275,6 +274,7 @@ export const iconPaths = { 'core/workflow/template/readFiles': () => import('./icons/core/workflow/template/readFiles.svg'), 'core/workflow/template/reply': () => import('./icons/core/workflow/template/reply.svg'), 'core/workflow/template/runApp': () => import('./icons/core/workflow/template/runApp.svg'), + 'core/workflow/template/searxng': () => import('./icons/core/workflow/template/searxng.svg'), 'core/workflow/template/stopTool': () => import('./icons/core/workflow/template/stopTool.svg'), 'core/workflow/template/systemConfig': () => import('./icons/core/workflow/template/systemConfig.svg'), @@ -341,6 +341,22 @@ export const iconPaths = { 'modal/selectSource': () => import('./icons/modal/selectSource.svg'), 'modal/setting': () => import('./icons/modal/setting.svg'), 'modal/teamPlans': () => import('./icons/modal/teamPlans.svg'), + 'model/baichuan': () => import('./icons/model/baichuan.svg'), + 'model/chatglm': () => import('./icons/model/chatglm.svg'), + 'model/claude': () => import('./icons/model/claude.svg'), + 'model/deepseek': () => import('./icons/model/deepseek.svg'), + 'model/doubao': () => import('./icons/model/doubao.svg'), + 'model/ernie': () => import('./icons/model/ernie.svg'), + 'model/gemini': () => import('./icons/model/gemini.svg'), + 'model/huggingface': () => import('./icons/model/huggingface.svg'), + 'model/hunyuan': () => import('./icons/model/hunyuan.svg'), + 'model/minimax': () => import('./icons/model/minimax.svg'), + 'model/moonshot': () => import('./icons/model/moonshot.svg'), + 'model/ollama': () => import('./icons/model/ollama.svg'), + 'model/openai': () => import('./icons/model/openai.svg'), + 'model/qwen': () => import('./icons/model/qwen.svg'), + 'model/sparkDesk': () => import('./icons/model/sparkDesk.svg'), + 'model/yi': () => import('./icons/model/yi.svg'), more: () => import('./icons/more.svg'), moreLine: () => import('./icons/moreLine.svg'), out: () => import('./icons/out.svg'), diff --git a/projects/app/public/imgs/model/baichuan.svg b/packages/web/components/common/Icon/icons/model/baichuan.svg similarity index 100% rename from projects/app/public/imgs/model/baichuan.svg rename to packages/web/components/common/Icon/icons/model/baichuan.svg diff --git a/projects/app/public/imgs/model/chatglm.svg b/packages/web/components/common/Icon/icons/model/chatglm.svg similarity index 100% rename from projects/app/public/imgs/model/chatglm.svg rename to packages/web/components/common/Icon/icons/model/chatglm.svg diff --git a/projects/app/public/imgs/model/claude.svg b/packages/web/components/common/Icon/icons/model/claude.svg similarity index 100% rename from projects/app/public/imgs/model/claude.svg rename to packages/web/components/common/Icon/icons/model/claude.svg diff --git a/projects/app/public/imgs/model/deepseek.svg b/packages/web/components/common/Icon/icons/model/deepseek.svg similarity index 100% rename from projects/app/public/imgs/model/deepseek.svg rename to packages/web/components/common/Icon/icons/model/deepseek.svg diff --git a/packages/web/components/common/Icon/icons/model/doubao.svg b/packages/web/components/common/Icon/icons/model/doubao.svg new file mode 100644 index 000000000000..f964a1a268f2 --- /dev/null +++ b/packages/web/components/common/Icon/icons/model/doubao.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/projects/app/public/imgs/model/ernie.svg b/packages/web/components/common/Icon/icons/model/ernie.svg similarity index 100% rename from projects/app/public/imgs/model/ernie.svg rename to packages/web/components/common/Icon/icons/model/ernie.svg diff --git a/projects/app/public/imgs/model/gemini.svg b/packages/web/components/common/Icon/icons/model/gemini.svg similarity index 100% rename from projects/app/public/imgs/model/gemini.svg rename to packages/web/components/common/Icon/icons/model/gemini.svg diff --git a/projects/app/public/imgs/model/huggingface.svg b/packages/web/components/common/Icon/icons/model/huggingface.svg similarity index 100% rename from projects/app/public/imgs/model/huggingface.svg rename to packages/web/components/common/Icon/icons/model/huggingface.svg diff --git a/projects/app/public/imgs/model/hunyuan.svg b/packages/web/components/common/Icon/icons/model/hunyuan.svg similarity index 100% rename from projects/app/public/imgs/model/hunyuan.svg rename to packages/web/components/common/Icon/icons/model/hunyuan.svg diff --git a/projects/app/public/imgs/model/minimax.svg b/packages/web/components/common/Icon/icons/model/minimax.svg similarity index 100% rename from projects/app/public/imgs/model/minimax.svg rename to packages/web/components/common/Icon/icons/model/minimax.svg diff --git a/projects/app/public/imgs/model/moonshot.svg b/packages/web/components/common/Icon/icons/model/moonshot.svg similarity index 100% rename from projects/app/public/imgs/model/moonshot.svg rename to packages/web/components/common/Icon/icons/model/moonshot.svg diff --git a/packages/web/components/common/Icon/icons/model/ollama.svg b/packages/web/components/common/Icon/icons/model/ollama.svg new file mode 100644 index 000000000000..c5f4f94a113e --- /dev/null +++ b/packages/web/components/common/Icon/icons/model/ollama.svg @@ -0,0 +1,119 @@ + + + + diff --git a/projects/app/public/imgs/model/openai.svg b/packages/web/components/common/Icon/icons/model/openai.svg similarity index 100% rename from projects/app/public/imgs/model/openai.svg rename to packages/web/components/common/Icon/icons/model/openai.svg diff --git a/packages/web/components/common/Icon/icons/model/qwen.svg b/packages/web/components/common/Icon/icons/model/qwen.svg new file mode 100644 index 000000000000..c46b8f052017 --- /dev/null +++ b/packages/web/components/common/Icon/icons/model/qwen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/projects/app/public/imgs/model/sparkDesk.svg b/packages/web/components/common/Icon/icons/model/sparkDesk.svg similarity index 100% rename from projects/app/public/imgs/model/sparkDesk.svg rename to packages/web/components/common/Icon/icons/model/sparkDesk.svg diff --git a/projects/app/public/imgs/model/yi.svg b/packages/web/components/common/Icon/icons/model/yi.svg similarity index 89% rename from projects/app/public/imgs/model/yi.svg rename to packages/web/components/common/Icon/icons/model/yi.svg index 06372ab65af2..4607c3dad747 100644 --- a/projects/app/public/imgs/model/yi.svg +++ b/packages/web/components/common/Icon/icons/model/yi.svg @@ -1,4 +1,4 @@ - + { const { isPc } = useSystem(); + return ( { const { t } = useTranslation(); - const ref = useRef(null); + const ButtonRef = useRef(null); + const { isOpen, onOpen, onClose } = useDisclosure(); const [cloneValue, setCloneValue] = useState(value); - useOutsideClick({ - ref: ref, - handler: onClose - }); + const MenuRef = useRef<(HTMLDivElement | null)[]>([]); + const SelectedItemRef = useRef<(HTMLDivElement | null)[]>([]); + + useEffect(() => { + if (isOpen) { + for (let i = 0; i < MenuRef.current.length; i++) { + const menu = MenuRef.current[i]; + const selectedItem = SelectedItemRef.current[i]; + if (menu && selectedItem) { + menu.scrollTop = selectedItem.offsetTop - menu.offsetTop - 100; + } + } + } + }, [isOpen]); + + const minWidth = `${MenuRef.current?.[0]?.offsetWidth || 0}px`; const RenderList = useCallback( ({ index, list }: { index: number; list: MultipleSelectProps['list'] }) => { @@ -37,11 +61,14 @@ export const MultipleRowSelect = ({ return ( <> { + MenuRef.current[index] = ref; + }} className="nowheel" flex={'1 0 auto'} - // width={0} px={2} borderLeft={index !== 0 ? 'base' : 'none'} + minW={index !== 0 ? minWidth : 'auto'} maxH={`${maxH}px`} overflowY={'auto'} whiteSpace={'nowrap'} @@ -49,13 +76,17 @@ export const MultipleRowSelect = ({ {list.map((item) => ( { + if (item.value === selectedValue) { + SelectedItemRef.current[index] = ref; + } + }} py={2} cursor={'pointer'} px={2} borderRadius={'md'} _hover={{ - bg: 'primary.50', - color: 'primary.600' + bg: 'primary.50' }} onClick={() => { const newValue = [...cloneValue]; @@ -81,6 +112,7 @@ export const MultipleRowSelect = ({ }} {...(item.value === selectedValue ? { + bg: 'primary.50', color: 'primary.600' } : {})} @@ -109,60 +141,73 @@ export const MultipleRowSelect = ({ }, [value, onOpen]); return ( - - } - _active={{ - transform: 'none' - }} - {...(isOpen - ? { - borderColor: 'primary.600', - color: 'primary.700', - boxShadow: '0px 0px 0px 2.4px rgba(51, 112, 255, 0.15)' - } - : { - borderColor: 'myGray.200', - boxShadow: 'none' - })} - {...styles} - onClick={() => (isOpen ? onClose() : onOpenSelect())} + + - {label ?? placeholder} - - {isOpen && ( - } + variant={'whitePrimaryOutline'} + size={'lg'} + fontSize={'sm'} + textAlign={'left'} + _active={{ + transform: 'none' + }} + {...(isOpen ? { - transform: 'translateY(-105%)', - top: '0' + boxShadow: '0px 0px 0px 2.4px rgba(51, 112, 255, 0.15)', + borderColor: 'primary.600', + color: 'primary.700' } - : { - transform: 'translateY(105%)', - bottom: '0' - })} - py={2} - bg={'white'} + : {})} + {...ButtonProps} + > + {label ?? placeholder} + + { + const w = ButtonRef.current?.clientWidth; + if (w) { + return `${w}px !important`; + } + + const width = ButtonProps?.width; + return Array.isArray(width) + ? width.map((item) => `${item} !important`) + : `${width} !important`; + })()} + w={'auto'} + px={'6px'} + py={'6px'} border={'1px solid #fff'} - boxShadow={'5'} - borderRadius={'md'} - zIndex={1} - minW={'100%'} - w={'max-content'} + boxShadow={ + '0px 2px 4px rgba(161, 167, 179, 0.25), 0px 0px 1px rgba(121, 141, 159, 0.25);' + } + zIndex={99} + maxH={'40vh'} + overflowY={'auto'} + display={'flex'} > - - - - - )} + + + ); }; @@ -176,7 +221,7 @@ export const MultipleRowArraySelect = ({ maxH = 300, onSelect, popDirection = 'bottom', - styles + ButtonProps }: MultipleArraySelectProps) => { const { t } = useTranslation(); const ref = useRef(null); @@ -318,7 +363,7 @@ export const MultipleRowArraySelect = ({ borderColor: 'myGray.200', boxShadow: 'none' })} - {...styles} + {...ButtonProps} onClick={() => (isOpen ? onClose() : onOpenSelect())} className="nowheel" > @@ -343,7 +388,7 @@ export const MultipleRowArraySelect = ({ border={'1px solid #fff'} boxShadow={'5'} borderRadius={'md'} - zIndex={1} + zIndex={1000} minW={'100%'} w={'max-content'} > diff --git a/packages/web/components/common/MySelect/type.d.ts b/packages/web/components/common/MySelect/type.d.ts index 10dc2de2a815..783d1e395776 100644 --- a/packages/web/components/common/MySelect/type.d.ts +++ b/packages/web/components/common/MySelect/type.d.ts @@ -1,3 +1,5 @@ +import { ButtonProps } from '@chakra-ui/react'; + type ListItemType = { alias?: string; label: string | React.ReactNode; @@ -12,9 +14,9 @@ export type MultipleSelectProps = { emptyTip?: string; maxH?: number; onSelect: (val: any[]) => void; - styles?: ButtonProps; popDirection?: 'top' | 'bottom'; changeOnEverySelect?: boolean; + ButtonProps?: ButtonProps; }; export type MultipleArraySelectProps = Omit & { value?: any[][]; diff --git a/packages/web/context/useSystem.tsx b/packages/web/context/useSystem.tsx new file mode 100644 index 000000000000..48268e595f99 --- /dev/null +++ b/packages/web/context/useSystem.tsx @@ -0,0 +1,45 @@ +import React, { ReactNode, useMemo } from 'react'; +import { createContext } from 'use-context-selector'; +import { useMediaQuery } from '@chakra-ui/react'; +import Cookies from 'js-cookie'; +import { useEffect } from 'react'; + +const CookieKey = 'NEXT_DEVICE_SIZE'; +const setSize = (value: string) => { + Cookies.set(CookieKey, value, { expires: 30 }); + localStorage.setItem(CookieKey, value); +}; + +type useSystemContextType = { + isPc: boolean; +}; + +export const useSystemStoreContext = createContext({ + isPc: true +}); + +const SystemStoreContextProvider = ({ + children, + device +}: { + children: ReactNode; + device?: 'pc' | 'mobile'; +}) => { + const [isPc] = useMediaQuery('(min-width: 900px)'); + + useEffect(() => { + setSize(isPc ? 'pc' : 'mobile'); + }, [isPc]); + + const contextValue = useMemo( + () => ({ + isPc: device ? device === 'pc' : isPc + }), + [device, isPc] + ); + return ( + {children} + ); +}; + +export default SystemStoreContextProvider; diff --git a/packages/web/hooks/useBeforeunload.ts b/packages/web/hooks/useBeforeunload.ts index 5759b40f595f..2860e0d06989 100644 --- a/packages/web/hooks/useBeforeunload.ts +++ b/packages/web/hooks/useBeforeunload.ts @@ -1,5 +1,6 @@ import { useTranslation } from 'next-i18next'; import { useEffect } from 'react'; +import { isProduction } from '@fastgpt/global/common/system/constants'; export const useBeforeunload = (props?: { callback?: () => any; tip?: string }) => { const { t } = useTranslation(); @@ -7,16 +8,15 @@ export const useBeforeunload = (props?: { callback?: () => any; tip?: string }) const { tip = t('common:common.Confirm to leave the page'), callback } = props || {}; useEffect(() => { - const listen = - process.env.NODE_ENV === 'production' - ? (e: any) => { - e.preventDefault(); - e.returnValue = tip; - callback?.(); - } - : () => { - callback?.(); - }; + const listen = isProduction + ? (e: any) => { + e.preventDefault(); + e.returnValue = tip; + callback?.(); + } + : () => { + callback?.(); + }; window.addEventListener('beforeunload', listen); return () => { diff --git a/packages/web/hooks/useSystem.ts b/packages/web/hooks/useSystem.ts index be7816cba2d9..a086e8f83362 100644 --- a/packages/web/hooks/useSystem.ts +++ b/packages/web/hooks/useSystem.ts @@ -1,7 +1,8 @@ -import { useMediaQuery } from '@chakra-ui/react'; +import { useSystemStoreContext } from '../context/useSystem'; +import { useContextSelector } from 'use-context-selector'; export const useSystem = () => { - const [isPc] = useMediaQuery('(min-width: 900px)'); + const isPc = useContextSelector(useSystemStoreContext, (state) => state.isPc); return { isPc }; }; diff --git a/packages/web/i18n/en/account_info.json b/packages/web/i18n/en/account_info.json index 1d715432b9ab..09f4809a5bb3 100644 --- a/packages/web/i18n/en/account_info.json +++ b/packages/web/i18n/en/account_info.json @@ -77,7 +77,7 @@ "usage_balance_notice": "Due to the system upgrade, the original \"automatic renewal and deduction from balance\" mode has been cancelled, and the balance recharge entrance has been closed. \nYour balance can be used to purchase points", "user_account": "Username", "user_team_team_name": "Team", - "verification_code_required": "Verification code cannot be empty", + "verification_code": "Verification code", "you_can_convert": "you can redeem", "yuan": "Yuan" } diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index 8fa435339a66..4ac9fa80aaa6 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -906,6 +906,16 @@ "item_name": "Field Name", "just_now": "just", "key_repetition": "Key Repetition", + "model_baichuan": "Baichuan", + "model_chatglm": "ChatGLM", + "model_doubao": "Doubao", + "model_ernie": "Ernie", + "model_hunyuan": "Hunyuan", + "model_moonshot": "Moonshot", + "model_other": "Other", + "model_qwen": "Qwen", + "model_sparkdesk": "SprkDesk", + "model_yi": "Yi", "move.confirm": "Confirm move", "navbar.Account": "Account", "navbar.Chat": "Chat", diff --git a/packages/web/i18n/zh-CN/account_info.json b/packages/web/i18n/zh-CN/account_info.json index 06bee0c7d9f0..816ec86281b7 100644 --- a/packages/web/i18n/zh-CN/account_info.json +++ b/packages/web/i18n/zh-CN/account_info.json @@ -77,7 +77,7 @@ "usage_balance_notice": "由于系统升级,原“自动续费从余额扣款”模式取消,余额充值入口关闭。您的余额可用于购买积分", "user_account": "账号", "user_team_team_name": "团队名", - "verification_code_required": "验证码不能为空", + "verification_code": "验证码", "you_can_convert": "您可以兑换", "yuan": "元" } diff --git a/packages/web/i18n/zh-CN/common.json b/packages/web/i18n/zh-CN/common.json index 83d928716d6c..e92904693ebb 100644 --- a/packages/web/i18n/zh-CN/common.json +++ b/packages/web/i18n/zh-CN/common.json @@ -905,6 +905,16 @@ "item_name": "字段名", "just_now": "刚刚", "key_repetition": "key 重复", + "model_baichuan": "百川智能", + "model_chatglm": "ChatGLM", + "model_doubao": "豆包", + "model_ernie": "文心一言", + "model_hunyuan": "腾讯混元", + "model_moonshot": "月之暗面", + "model_other": "自定义", + "model_qwen": "阿里千问", + "model_sparkdesk": "讯飞星火", + "model_yi": "零一万物", "move.confirm": "确认移动", "navbar.Account": "账号", "navbar.Chat": "聊天", diff --git a/packages/web/i18n/zh-Hant/account_info.json b/packages/web/i18n/zh-Hant/account_info.json index 84c71e6945b1..8a7053137feb 100644 --- a/packages/web/i18n/zh-Hant/account_info.json +++ b/packages/web/i18n/zh-Hant/account_info.json @@ -77,7 +77,7 @@ "usage_balance_notice": "由於系統升級,原「自動續費從餘額扣款」模式取消,餘額儲值入口關閉。\n您的餘額可用於購買積分", "user_account": "帳號", "user_team_team_name": "團隊名", - "verification_code_required": "驗證碼不能為空", + "verification_code": "驗證碼", "you_can_convert": "您可以兌換", "yuan": "元" } diff --git a/packages/web/i18n/zh-Hant/common.json b/packages/web/i18n/zh-Hant/common.json index 3c50d5756ca0..17216d3bbb28 100644 --- a/packages/web/i18n/zh-Hant/common.json +++ b/packages/web/i18n/zh-Hant/common.json @@ -907,6 +907,16 @@ "item_name": "欄位名稱", "just_now": "剛剛", "key_repetition": "鍵值重複", + "model_baichuan": "百川智能", + "model_chatglm": "ChatGLM", + "model_doubao": "豆包", + "model_ernie": "文心一言", + "model_hunyuan": "騰訊混元", + "model_moonshot": "月之暗面", + "model_other": "自訂", + "model_qwen": "阿里千問", + "model_sparkdesk": "訊飛星火", + "model_yi": "零一萬物", "move.confirm": "確認移動", "navbar.Account": "帳戶", "navbar.Chat": "對話", diff --git a/projects/app/data/config.json b/projects/app/data/config.json index 34d1b2eae600..0799be5df8c3 100644 --- a/projects/app/data/config.json +++ b/projects/app/data/config.json @@ -11,9 +11,9 @@ }, "llmModels": [ { + "provider": "OpenAI", // 模型提供商,主要用于分类展示,目前已经内置提供商包括:https://github.com/labring/FastGPT/blob/main/packages/global/core/ai/provider.ts, 可 pr 提供新的提供商,或直接填写 Other "model": "gpt-4o-mini", // 模型名(对应OneAPI中渠道的模型名) "name": "gpt-4o-mini", // 模型别名 - "avatar": "/imgs/model/openai.svg", // 模型的logo "maxContext": 125000, // 最大上下文 "maxResponse": 16000, // 最大回复 "quoteMaxToken": 120000, // 最大引用内容 @@ -35,9 +35,9 @@ "fieldMap": {} // 字段映射(o1 模型需要把 max_tokens 映射为 max_completion_tokens) }, { + "provider": "OpenAI", "model": "gpt-4o", "name": "gpt-4o", - "avatar": "/imgs/model/openai.svg", "maxContext": 125000, "maxResponse": 4000, "quoteMaxToken": 120000, @@ -59,9 +59,9 @@ "fieldMap": {} }, { + "provider": "OpenAI", "model": "o1-mini", "name": "o1-mini", - "avatar": "/imgs/model/openai.svg", "maxContext": 125000, "maxResponse": 65000, "quoteMaxToken": 120000, @@ -84,9 +84,9 @@ } }, { + "provider": "OpenAI", "model": "o1-preview", "name": "o1-preview", - "avatar": "/imgs/model/openai.svg", "maxContext": 125000, "maxResponse": 32000, "quoteMaxToken": 120000, @@ -111,21 +111,18 @@ ], "vectorModels": [ { - "model": "text-embedding-ada-002", // 模型名(与OneAPI对应) - "name": "Embedding-2", // 模型展示名 - "avatar": "/imgs/model/openai.svg", // logo - "charsPointsPrice": 0, // n积分/1k token - "defaultToken": 700, // 默认文本分割时候的 token - "maxToken": 3000, // 最大 token - "weight": 100, // 优先训练权重 - "defaultConfig": {}, // 自定义额外参数。例如,如果希望使用 embedding3-large 的话,可以传入 dimensions:1024,来返回1024维度的向量。(目前必须小于1536维度) - "dbConfig": {}, // 存储时的额外参数(非对称向量模型时候需要用到) - "queryConfig": {} // 参训时的额外参数 + "provider": "OpenAI", + "model": "text-embedding-3-small", + "name": "text-embedding-3-small", + "charsPointsPrice": 0, + "defaultToken": 512, + "maxToken": 3000, + "weight": 100 }, { + "provider": "OpenAI", "model": "text-embedding-3-large", "name": "text-embedding-3-large", - "avatar": "/imgs/model/openai.svg", "charsPointsPrice": 0, "defaultToken": 512, "maxToken": 3000, @@ -135,13 +132,16 @@ } }, { - "model": "text-embedding-3-small", - "name": "text-embedding-3-small", - "avatar": "/imgs/model/openai.svg", - "charsPointsPrice": 0, - "defaultToken": 512, - "maxToken": 3000, - "weight": 100 + "provider": "OpenAI", + "model": "text-embedding-ada-002", // 模型名(与OneAPI对应) + "name": "Embedding-2", // 模型展示名 + "charsPointsPrice": 0, // n积分/1k token + "defaultToken": 700, // 默认文本分割时候的 token + "maxToken": 3000, // 最大 token + "weight": 100, // 优先训练权重 + "defaultConfig": {}, // 自定义额外参数。例如,如果希望使用 embedding3-large 的话,可以传入 dimensions:1024,来返回1024维度的向量。(目前必须小于1536维度) + "dbConfig": {}, // 存储时的额外参数(非对称向量模型时候需要用到) + "queryConfig": {} // 参训时的额外参数 } ], "reRankModels": [], diff --git a/projects/app/public/imgs/model/doubao.svg b/projects/app/public/imgs/model/doubao.svg deleted file mode 100644 index b619a2e8607d..000000000000 --- a/projects/app/public/imgs/model/doubao.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - diff --git a/projects/app/public/imgs/model/qwen.svg b/projects/app/public/imgs/model/qwen.svg deleted file mode 100644 index dc90972d9405..000000000000 --- a/projects/app/public/imgs/model/qwen.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/projects/app/src/components/Select/AIModelSelector.tsx b/projects/app/src/components/Select/AIModelSelector.tsx index 3a5ef89edbf3..e72e24be08f4 100644 --- a/projects/app/src/components/Select/AIModelSelector.tsx +++ b/projects/app/src/components/Select/AIModelSelector.tsx @@ -1,14 +1,16 @@ -import React, { useCallback, useMemo } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'next-i18next'; import { useSystemStore } from '@/web/common/system/useSystemStore'; -import { useRouter } from 'next/router'; import MySelect, { SelectProps } from '@fastgpt/web/components/common/MySelect'; import { HUGGING_FACE_ICON, LOGO_ICON } from '@fastgpt/global/common/system/constants'; -import { Box, Flex, useDisclosure } from '@chakra-ui/react'; +import { Box, Flex, HStack, useDisclosure } from '@chakra-ui/react'; import Avatar from '@fastgpt/web/components/common/Avatar'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import dynamic from 'next/dynamic'; +import { ModelProviderList } from '@fastgpt/global/core/ai/provider'; +import MultipleRowSelect from '@fastgpt/web/components/common/MySelect/MultipleRowSelect'; +import { getModelFromList } from '@fastgpt/global/core/ai/model'; const AiPointsModal = dynamic(() => import('@/pages/price/components/Points').then((mod) => mod.AiPointsModal) @@ -18,10 +20,9 @@ type Props = SelectProps & { disableTip?: string; }; -const AIModelSelector = ({ list, onchange, disableTip, ...props }: Props) => { +const OneRowSelector = ({ list, onchange, disableTip, ...props }: Props) => { const { t } = useTranslation(); const { feConfigs, llmModelList, vectorModelList } = useSystemStore(); - const router = useRouter(); const { isOpen: isOpenAiPointsModal, @@ -40,9 +41,7 @@ const AIModelSelector = ({ list, onchange, disableTip, ...props }: Props) => { }, [props.size]); const avatarList = list.map((item) => { - const modelData = - llmModelList.find((model) => model.model === item.value) || - vectorModelList.find((model) => model.model === item.value); + const modelData = getModelFromList([...llmModelList, ...vectorModelList], item.value); return { value: item.value, @@ -55,14 +54,14 @@ const AIModelSelector = ({ list, onchange, disableTip, ...props }: Props) => { fallbackSrc={HUGGING_FACE_ICON} w={avatarSize} /> - {item.label} + {modelData.name} ) }; }); const expandList = useMemo(() => { - return feConfigs.show_pay + return feConfigs?.show_pay ? avatarList.concat({ label: ( @@ -108,5 +107,121 @@ const AIModelSelector = ({ list, onchange, disableTip, ...props }: Props) => { ); }; +const MultipleRowSelector = ({ list, onchange, disableTip, ...props }: Props) => { + const { t } = useTranslation(); + const { feConfigs, llmModelList, vectorModelList } = useSystemStore(); + const [value, setValue] = useState([]); + + const { + isOpen: isOpenAiPointsModal, + onClose: onCloseAiPointsModal, + onOpen: onOpenAiPointsModal + } = useDisclosure(); + + const avatarSize = useMemo(() => { + const size = { + sm: '1rem', + md: '1.2rem', + lg: '1.4rem' + }; + //@ts-ignore + return props.size ? size[props.size] : size['md']; + }, [props.size]); + + const selectorList = useMemo(() => { + const renderList = ModelProviderList.map<{ + label: React.JSX.Element; + value: string; + children: { label: string | React.ReactNode; value: string }[]; + }>((provider) => ({ + label: ( + + + {t(provider.name as any)} + + ), + value: provider.id, + children: [] + })); + + for (const item of list) { + const modelData = getModelFromList([...llmModelList, ...vectorModelList], item.value); + const provider = + renderList.find((item) => item.value === (modelData?.provider || 'Other')) ?? + renderList[renderList.length - 1]; + + provider.children.push({ + label: modelData.name, + value: modelData.model + }); + } + + return renderList.filter((item) => item.children.length > 0); + }, [avatarSize, list, llmModelList, t, vectorModelList]); + + const onSelect = useCallback( + (e: string[]) => { + return onchange?.(e[1]); + }, + [onchange] + ); + + const SelectedModel = useMemo(() => { + const modelData = getModelFromList([...llmModelList, ...vectorModelList], props.value); + + setValue([modelData.provider, props.value]); + + return ( + + + {modelData?.name} + + ); + }, [avatarSize, llmModelList, props.value, vectorModelList]); + + return ( + + + + + + {isOpenAiPointsModal && } + + ); +}; + +const AIModelSelector = (props: Props) => { + return props.list.length > 10 ? ( + + ) : ( + + ); +}; export default AIModelSelector; diff --git a/projects/app/src/components/core/ai/SettingLLMModel/index.tsx b/projects/app/src/components/core/ai/SettingLLMModel/index.tsx index 31f3ca8e43d6..2a2567ca041c 100644 --- a/projects/app/src/components/core/ai/SettingLLMModel/index.tsx +++ b/projects/app/src/components/core/ai/SettingLLMModel/index.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { LLMModelTypeEnum, llmModelTypeFilterMap } from '@fastgpt/global/core/ai/constants'; import { Box, Button, css, useDisclosure } from '@chakra-ui/react'; @@ -10,6 +10,7 @@ import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import { useTranslation } from 'next-i18next'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { useMount } from 'ahooks'; +import { getModelFromList } from '@fastgpt/global/core/ai/model'; type Props = { llmModelType?: `${LLMModelTypeEnum}`; @@ -29,15 +30,19 @@ const SettingLLMModel = ({ const model = defaultData.model; - const modelList = llmModelList.filter((model) => { - if (!llmModelType) return true; - const filterField = llmModelTypeFilterMap[llmModelType]; - if (!filterField) return true; - //@ts-ignore - return !!model[filterField]; - }); + const modelList = useMemo( + () => + llmModelList.filter((modelData) => { + if (!llmModelType) return true; + const filterField = llmModelTypeFilterMap[llmModelType]; + if (!filterField) return true; + //@ts-ignore + return !!modelData[filterField]; + }), + [llmModelList, llmModelType] + ); - const selectedModel = modelList.find((item) => item.model === model) || modelList[0]; + const selectedModel = useMemo(() => getModelFromList(modelList, model), [modelList, model]); const { isOpen: isOpenAIChatSetting, diff --git a/projects/app/src/pages/_app.tsx b/projects/app/src/pages/_app.tsx index 89261209ec40..0fc36a62aad2 100644 --- a/projects/app/src/pages/_app.tsx +++ b/projects/app/src/pages/_app.tsx @@ -14,6 +14,7 @@ import NextHead from '@/components/common/NextHead'; import { ReactElement, useEffect } from 'react'; import { NextPage } from 'next'; import { getWebReqUrl } from '@fastgpt/web/common/system/utils'; +import SystemStoreContextProvider from '@fastgpt/web/context/useSystem'; type NextPageWithLayout = NextPage & { setLayout?: (page: ReactElement) => JSX.Element; @@ -55,11 +56,13 @@ function App({ Component, pageProps }: AppPropsWithLayout) { {scripts?.map((item, i) => )} - - - {setLayout()} - - + + + + {setLayout()} + + + ); diff --git a/projects/app/src/pages/_error.tsx b/projects/app/src/pages/_error.tsx index bbaae955a39c..3cf5a5c4352c 100644 --- a/projects/app/src/pages/_error.tsx +++ b/projects/app/src/pages/_error.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react'; import { useRouter } from 'next/router'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { Box } from '@chakra-ui/react'; import { TrackEventName } from '@/web/common/system/constants'; diff --git a/projects/app/src/pages/account/apikey.tsx b/projects/app/src/pages/account/apikey.tsx index f7ad3f3c9390..eef200b5123a 100644 --- a/projects/app/src/pages/account/apikey.tsx +++ b/projects/app/src/pages/account/apikey.tsx @@ -3,7 +3,7 @@ import ApiKeyTable from '@/components/support/apikey/Table'; import { useTranslation } from 'next-i18next'; import { Box } from '@chakra-ui/react'; import AccountContainer, { TabEnum } from './components/AccountContainer'; -import { serviceSideProps } from '../../web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; const ApiKey = () => { const { t } = useTranslation(); diff --git a/projects/app/src/pages/account/bill/index.tsx b/projects/app/src/pages/account/bill/index.tsx index 53aede2c0455..477baa082696 100644 --- a/projects/app/src/pages/account/bill/index.tsx +++ b/projects/app/src/pages/account/bill/index.tsx @@ -6,7 +6,7 @@ import { useTranslation } from 'next-i18next'; import ApplyInvoiceModal from './components/ApplyInvoiceModal'; import { useRouter } from 'next/router'; import AccountContainer, { TabEnum } from '../components/AccountContainer'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; export enum InvoiceTabEnum { bill = 'bill', diff --git a/projects/app/src/pages/account/components/AccountContainer.tsx b/projects/app/src/pages/account/components/AccountContainer.tsx index 68a4054a02ab..4515feeb26aa 100644 --- a/projects/app/src/pages/account/components/AccountContainer.tsx +++ b/projects/app/src/pages/account/components/AccountContainer.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useMemo } from 'react'; +import React, { useCallback, useMemo, useRef } from 'react'; import { Box, Flex, useTheme } from '@chakra-ui/react'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useRouter } from 'next/router'; @@ -42,7 +42,7 @@ const AccountContainer = ({ return router.pathname.split('/').pop() as TabEnum; }, [router.pathname]); - const tabList = [ + const tabList = useRef([ { icon: 'support/user/userLight', label: t('account:personal_information'), @@ -108,7 +108,7 @@ const AccountContainer = ({ label: t('account:logout'), value: TabEnum.loginout } - ]; + ]); const { openConfirm, ConfirmModal } = useConfirm({ content: t('account:confirm_logout') @@ -129,57 +129,54 @@ const AccountContainer = ({ ); return ( - <> - - - - {isPc ? ( - - - flex={1} - mx={'auto'} - mt={2} - w={'100%'} - list={tabList} - value={currentTab} - onChange={setCurrentTab} - /> - - - - V{systemVersion} - - + + + {isPc ? ( + + + flex={1} + mx={'auto'} + mt={2} + w={'100%'} + list={tabList.current} + value={currentTab} + onChange={setCurrentTab} + /> + + + + V{systemVersion} + - ) : ( - - - m={'auto'} - w={'100%'} - size={isPc ? 'md' : 'sm'} - list={tabList.map((item) => ({ - value: item.value, - label: item.label - }))} - value={currentTab} - onChange={setCurrentTab} - /> - - )} - - - {children} + + ) : ( + + + m={'auto'} + w={'100%'} + size={isPc ? 'md' : 'sm'} + list={tabList.current.map((item) => ({ + value: item.value, + label: item.label + }))} + value={currentTab} + onChange={setCurrentTab} + /> - - - - + )} + + + {children} + + + + ); }; diff --git a/projects/app/src/pages/account/individuation.tsx b/projects/app/src/pages/account/individuation.tsx index d40229e5f4a9..d8eec2ac9167 100644 --- a/projects/app/src/pages/account/individuation.tsx +++ b/projects/app/src/pages/account/individuation.tsx @@ -10,7 +10,7 @@ import { UserUpdateParams } from '@/types/user'; import TimezoneSelect from '@fastgpt/web/components/common/MySelect/TimezoneSelect'; import I18nLngSelector from '@/components/Select/I18nLngSelector'; import AccountContainer from './components/AccountContainer'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; const Individuation = () => { const { t } = useTranslation(); diff --git a/projects/app/src/pages/account/info/components/UpdateNotificationModal.tsx b/projects/app/src/pages/account/info/components/UpdateNotificationModal.tsx index 7fe747bcc5ed..5adbb505fa84 100644 --- a/projects/app/src/pages/account/info/components/UpdateNotificationModal.tsx +++ b/projects/app/src/pages/account/info/components/UpdateNotificationModal.tsx @@ -1,14 +1,5 @@ -import React, { useCallback } from 'react'; -import { - ModalBody, - Box, - Flex, - Input, - ModalFooter, - Button, - HStack, - useDisclosure -} from '@chakra-ui/react'; +import React from 'react'; +import { ModalBody, Box, Flex, Input, ModalFooter, Button, HStack } from '@chakra-ui/react'; import MyModal from '@fastgpt/web/components/common/MyModal'; import { useTranslation } from 'next-i18next'; import { useForm } from 'react-hook-form'; @@ -89,7 +80,7 @@ const UpdateNotificationModal = ({ onClose }: { onClose: () => void }) => { > - {t('account_info:verification_code_required')} + {t('account_info:verification_code')} { const { t } = useTranslation(); diff --git a/projects/app/src/pages/account/promotion.tsx b/projects/app/src/pages/account/promotion.tsx index 65345c517252..be9ed529d191 100644 --- a/projects/app/src/pages/account/promotion.tsx +++ b/projects/app/src/pages/account/promotion.tsx @@ -26,7 +26,7 @@ import { useLoading } from '@fastgpt/web/hooks/useLoading'; import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; import AccountContainer, { TabEnum } from './components/AccountContainer'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; const Promotion = () => { const { t } = useTranslation(); diff --git a/projects/app/src/pages/account/team/index.tsx b/projects/app/src/pages/account/team/index.tsx index 7b9c3fdcb696..4cf5d5e9c106 100644 --- a/projects/app/src/pages/account/team/index.tsx +++ b/projects/app/src/pages/account/team/index.tsx @@ -1,4 +1,4 @@ -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import AccountContainer from '../components/AccountContainer'; import { Box, Button, Flex, useDisclosure } from '@chakra-ui/react'; import Icon from '@fastgpt/web/components/common/Icon'; diff --git a/projects/app/src/pages/account/usage/index.tsx b/projects/app/src/pages/account/usage/index.tsx index 5e50325374f9..649b4448aa93 100644 --- a/projects/app/src/pages/account/usage/index.tsx +++ b/projects/app/src/pages/account/usage/index.tsx @@ -31,7 +31,7 @@ import { formatNumber } from '@fastgpt/global/common/math/tools'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; import AccountContainer, { TabEnum } from '../components/AccountContainer'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; const UsageDetail = dynamic(() => import('./UsageDetail')); diff --git a/projects/app/src/pages/app/detail/components/SimpleApp/Header.tsx b/projects/app/src/pages/app/detail/components/SimpleApp/Header.tsx index c636a9875992..72a2be37c330 100644 --- a/projects/app/src/pages/app/detail/components/SimpleApp/Header.tsx +++ b/projects/app/src/pages/app/detail/components/SimpleApp/Header.tsx @@ -19,7 +19,7 @@ import { formatTime2YMDHMS } from '@fastgpt/global/common/string/time'; import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useDatasetStore } from '@/web/core/dataset/store/dataset'; import SaveButton from '../Workflow/components/SaveButton'; -import { useBoolean, useDebounceEffect } from 'ahooks'; +import { useBoolean, useDebounceEffect, useLockFn } from 'ahooks'; import { appWorkflow2Form } from '@fastgpt/global/core/app/utils'; import { compareSimpleAppSnapshot, @@ -29,6 +29,7 @@ import { import PublishHistories from '../PublishHistoriesSlider'; import { AppVersionSchemaType } from '@fastgpt/global/core/app/version'; import { useBeforeunload } from '@fastgpt/web/hooks/useBeforeunload'; +import { isProduction } from '@fastgpt/global/common/system/constants'; const Header = ({ forbiddenSaveSnapshot, @@ -152,15 +153,22 @@ const Header = ({ { wait: 500 } ); - const onLeaveAutoSave = useCallback(() => { + const onLeaveAutoSave = useLockFn(async () => { if (isSaved) return; try { console.log('Leave auto save'); - onClickSave({ isPublish: false, versionName: t('app:auto_save') }); + return onClickSave({ isPublish: false, versionName: t('app:auto_save') }); } catch (error) { console.error(error); } - }, [isSaved, onClickSave, t]); + }); + useEffect(() => { + return () => { + if (isProduction) { + onLeaveAutoSave(); + } + }; + }, []); useBeforeunload({ tip: t('common:core.common.tip.leave page'), callback: onLeaveAutoSave diff --git a/projects/app/src/pages/app/detail/index.tsx b/projects/app/src/pages/app/detail/index.tsx index 87cc6dbfd6d5..54da870e5f19 100644 --- a/projects/app/src/pages/app/detail/index.tsx +++ b/projects/app/src/pages/app/detail/index.tsx @@ -2,7 +2,7 @@ import React, { useEffect } from 'react'; import { Box } from '@chakra-ui/react'; import dynamic from 'next/dynamic'; import Loading from '@fastgpt/web/components/common/MyLoading'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import NextHead from '@/components/common/NextHead'; import { useContextSelector } from 'use-context-selector'; import AppContextProvider, { AppContext } from './components/context'; diff --git a/projects/app/src/pages/app/list/index.tsx b/projects/app/src/pages/app/list/index.tsx index 923b4fea5ce9..b29296e3dde1 100644 --- a/projects/app/src/pages/app/list/index.tsx +++ b/projects/app/src/pages/app/list/index.tsx @@ -1,7 +1,7 @@ import React, { useMemo, useState } from 'react'; import { Box, Flex, Button, useDisclosure, Input, InputGroup } from '@chakra-ui/react'; import { AddIcon } from '@chakra-ui/icons'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { useUserStore } from '@/web/support/user/useUserStore'; import { useTranslation } from 'next-i18next'; import dynamic from 'next/dynamic'; diff --git a/projects/app/src/pages/chat/index.tsx b/projects/app/src/pages/chat/index.tsx index 78c469847d98..e80019041444 100644 --- a/projects/app/src/pages/chat/index.tsx +++ b/projects/app/src/pages/chat/index.tsx @@ -15,7 +15,7 @@ import ChatHistorySlider from './components/ChatHistorySlider'; import SliderApps from './components/SliderApps'; import ChatHeader from './components/ChatHeader'; import { useUserStore } from '@/web/support/user/useUserStore'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { getChatTitleFromChatMessage } from '@fastgpt/global/core/chat/utils'; import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt'; import { getMyApps } from '@/web/core/app/api'; diff --git a/projects/app/src/pages/chat/share.tsx b/projects/app/src/pages/chat/share.tsx index 4d25f6747a32..ab6e4eb7e006 100644 --- a/projects/app/src/pages/chat/share.tsx +++ b/projects/app/src/pages/chat/share.tsx @@ -11,7 +11,7 @@ import type { StartChatFnProps } from '@/components/core/chat/ChatContainer/type import PageContainer from '@/components/PageContainer'; import ChatHeader from './components/ChatHeader'; import ChatHistorySlider from './components/ChatHistorySlider'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { useTranslation } from 'next-i18next'; import { getInitOutLinkChatInfo } from '@/web/core/chat/api'; import { getChatTitleFromChatMessage } from '@fastgpt/global/core/chat/utils'; diff --git a/projects/app/src/pages/chat/team.tsx b/projects/app/src/pages/chat/team.tsx index 4879eed56b43..5bb080de15af 100644 --- a/projects/app/src/pages/chat/team.tsx +++ b/projects/app/src/pages/chat/team.tsx @@ -8,7 +8,7 @@ import PageContainer from '@/components/PageContainer'; import { getMyTokensApps } from '@/web/core/chat/api'; import ChatHistorySlider from './components/ChatHistorySlider'; import ChatHeader from './components/ChatHeader'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { useTranslation } from 'next-i18next'; import ChatBox from '@/components/core/chat/ChatContainer/ChatBox'; import type { StartChatFnProps } from '@/components/core/chat/ChatContainer/type'; diff --git a/projects/app/src/pages/dataset/detail/index.tsx b/projects/app/src/pages/dataset/detail/index.tsx index 18a770ca53a8..809ac15dd306 100644 --- a/projects/app/src/pages/dataset/detail/index.tsx +++ b/projects/app/src/pages/dataset/detail/index.tsx @@ -5,7 +5,7 @@ import { useToast } from '@fastgpt/web/hooks/useToast'; import { getErrText } from '@fastgpt/global/common/error/utils'; import dynamic from 'next/dynamic'; import PageContainer from '@/components/PageContainer'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { useTranslation } from 'next-i18next'; import MetaDataCard from './components/MetaDataCard'; import NavBar from './components/NavBar'; diff --git a/projects/app/src/pages/dataset/list/index.tsx b/projects/app/src/pages/dataset/list/index.tsx index 43f87d6a68a5..d62a64aea5b5 100644 --- a/projects/app/src/pages/dataset/list/index.tsx +++ b/projects/app/src/pages/dataset/list/index.tsx @@ -2,7 +2,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { Box, Flex, Button, InputGroup, InputLeftElement, Input } from '@chakra-ui/react'; import { useRouter } from 'next/router'; import { useTranslation } from 'next-i18next'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import ParentPaths from '@/components/common/folder/Path'; import List from './component/List'; import { DatasetsContext } from './context'; diff --git a/projects/app/src/pages/index.tsx b/projects/app/src/pages/index.tsx index 846001547121..2579384df411 100644 --- a/projects/app/src/pages/index.tsx +++ b/projects/app/src/pages/index.tsx @@ -1,4 +1,4 @@ -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import React, { useEffect } from 'react'; import Loading from '@fastgpt/web/components/common/MyLoading'; import { useRouter } from 'next/router'; diff --git a/projects/app/src/pages/login/components/LoginForm/WechatForm.tsx b/projects/app/src/pages/login/components/LoginForm/WechatForm.tsx index bb4f96d66001..4d08509f9c04 100644 --- a/projects/app/src/pages/login/components/LoginForm/WechatForm.tsx +++ b/projects/app/src/pages/login/components/LoginForm/WechatForm.tsx @@ -32,8 +32,10 @@ const WechatForm = ({ setPageType, loginSuccess }: Props) => { useQuery(['getWXLoginResult', wechatInfo?.code], () => getWXLoginResult(wechatInfo?.code || ''), { refetchInterval: 3 * 1000, enabled: !!wechatInfo?.code, - onSuccess(data: ResLogin) { - loginSuccess(data); + onSuccess(data: ResLogin | undefined) { + if (data) { + loginSuccess(data); + } } }); diff --git a/projects/app/src/pages/login/fastlogin.tsx b/projects/app/src/pages/login/fastlogin.tsx index 8a95a2cfb6ab..fe1da52aedfe 100644 --- a/projects/app/src/pages/login/fastlogin.tsx +++ b/projects/app/src/pages/login/fastlogin.tsx @@ -6,7 +6,7 @@ import { clearToken, setToken } from '@/web/support/user/auth'; import { postFastLogin } from '@/web/support/user/api'; import { useToast } from '@fastgpt/web/hooks/useToast'; import Loading from '@fastgpt/web/components/common/MyLoading'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { getErrText } from '@fastgpt/global/common/error/utils'; import { useTranslation } from 'next-i18next'; const FastLogin = ({ diff --git a/projects/app/src/pages/login/index.tsx b/projects/app/src/pages/login/index.tsx index 6a7d52b3747b..460252bd93aa 100644 --- a/projects/app/src/pages/login/index.tsx +++ b/projects/app/src/pages/login/index.tsx @@ -18,7 +18,7 @@ import { useUserStore } from '@/web/support/user/useUserStore'; import { useChatStore } from '@/web/core/chat/context/useChatStore'; import LoginForm from './components/LoginForm/LoginForm'; import dynamic from 'next/dynamic'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { clearToken, setToken } from '@/web/support/user/auth'; import Script from 'next/script'; import Loading from '@fastgpt/web/components/common/MyLoading'; diff --git a/projects/app/src/pages/login/provider.tsx b/projects/app/src/pages/login/provider.tsx index ce25800c6596..5ac82d7fee05 100644 --- a/projects/app/src/pages/login/provider.tsx +++ b/projects/app/src/pages/login/provider.tsx @@ -7,7 +7,7 @@ import { clearToken, setToken } from '@/web/support/user/auth'; import { oauthLogin } from '@/web/support/user/api'; import { useToast } from '@fastgpt/web/hooks/useToast'; import Loading from '@fastgpt/web/components/common/MyLoading'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { getErrText } from '@fastgpt/global/common/error/utils'; import { useTranslation } from 'next-i18next'; import { OAuthEnum } from '@fastgpt/global/support/user/constant'; diff --git a/projects/app/src/pages/more/index.tsx b/projects/app/src/pages/more/index.tsx index 7b2aba4263cb..0340b5f5da5e 100644 --- a/projects/app/src/pages/more/index.tsx +++ b/projects/app/src/pages/more/index.tsx @@ -4,7 +4,7 @@ import { ChevronRightIcon } from '@chakra-ui/icons'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { useRouter } from 'next/router'; import { useSystemStore } from '@/web/common/system/useSystemStore'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { useTranslation } from 'next-i18next'; import { getDocPath } from '@/web/common/system/doc'; diff --git a/projects/app/src/pages/price/index.tsx b/projects/app/src/pages/price/index.tsx index 48ed46069448..581acfbb6f2a 100644 --- a/projects/app/src/pages/price/index.tsx +++ b/projects/app/src/pages/price/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { Box, Flex } from '@chakra-ui/react'; import { useUserStore } from '@/web/support/user/useUserStore'; import { getTeamPlanStatus } from '@/web/support/user/team/api'; diff --git a/projects/app/src/pages/toolkit/index.tsx b/projects/app/src/pages/toolkit/index.tsx index b0d0cbe8a102..3b15815f770a 100644 --- a/projects/app/src/pages/toolkit/index.tsx +++ b/projects/app/src/pages/toolkit/index.tsx @@ -1,4 +1,4 @@ -import { serviceSideProps } from '@/web/common/utils/i18n'; +import { serviceSideProps } from '@fastgpt/web/common/system/nextjs'; import { getPluginGroups, getSystemPlugTemplates } from '@/web/core/app/api/plugin'; import { Box, Flex, Grid, useDisclosure } from '@chakra-ui/react'; import Avatar from '@fastgpt/web/components/common/Avatar'; diff --git a/projects/app/src/service/common/system/index.ts b/projects/app/src/service/common/system/index.ts index 525a546d4ad1..b960d7ed7d21 100644 --- a/projects/app/src/service/common/system/index.ts +++ b/projects/app/src/service/common/system/index.ts @@ -5,7 +5,8 @@ import type { FastGPTConfigFileType } from '@fastgpt/global/common/system/types/ import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants'; import { getFastGPTConfigFromDB } from '@fastgpt/service/common/system/config/controller'; import { PluginTemplateType } from '@fastgpt/global/core/plugin/type'; -import { FastGPTProUrl, isProduction } from '@fastgpt/service/common/system/constants'; +import { FastGPTProUrl } from '@fastgpt/service/common/system/constants'; +import { isProduction } from '@fastgpt/global/common/system/constants'; import { initFastGPTConfig } from '@fastgpt/service/common/system/tools'; import json5 from 'json5'; import { SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type'; diff --git a/projects/app/src/service/core/app/plugin.ts b/projects/app/src/service/core/app/plugin.ts index 7bfb1f2b8778..3147803ede32 100644 --- a/projects/app/src/service/core/app/plugin.ts +++ b/projects/app/src/service/core/app/plugin.ts @@ -1,4 +1,5 @@ -import { FastGPTProUrl, isProduction } from '@fastgpt/service/common/system/constants'; +import { FastGPTProUrl } from '@fastgpt/service/common/system/constants'; +import { isProduction } from '@fastgpt/global/common/system/constants'; import { cloneDeep } from 'lodash'; import { getCommunityCb, getCommunityPlugins } from '@fastgpt/plugins/register'; import { GET, POST } from '@fastgpt/service/common/api/plusRequest'; diff --git a/projects/app/src/service/core/app/template.ts b/projects/app/src/service/core/app/template.ts index 4b79cc37d0fe..bb6bad9bd820 100644 --- a/projects/app/src/service/core/app/template.ts +++ b/projects/app/src/service/core/app/template.ts @@ -1,4 +1,4 @@ -import { isProduction } from '@fastgpt/service/common/system/constants'; +import { isProduction } from '@fastgpt/global/common/system/constants'; import { readdirSync, readFileSync } from 'fs'; import path from 'path'; diff --git a/projects/app/src/web/common/hooks/useCopyData.tsx b/projects/app/src/web/common/hooks/useCopyData.tsx index a9724eb44bfa..4cbb2c021c7d 100644 --- a/projects/app/src/web/common/hooks/useCopyData.tsx +++ b/projects/app/src/web/common/hooks/useCopyData.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'next-i18next'; import { useToast } from '@fastgpt/web/hooks/useToast'; import { useCallback } from 'react'; import { hasHttps } from '@fastgpt/web/common/system/utils'; -import { isProduction } from '@fastgpt/service/common/system/constants'; +import { isProduction } from '@fastgpt/global/common/system/constants'; /** * copy text data diff --git a/projects/app/src/web/common/utils/i18n.ts b/projects/app/src/web/common/utils/i18n.ts index 78b017bc1aa4..16b7fa09c115 100644 --- a/projects/app/src/web/common/utils/i18n.ts +++ b/projects/app/src/web/common/utils/i18n.ts @@ -20,10 +20,3 @@ export const langMap = { avatar: 'common/language/China' } }; - -export const serviceSideProps = (content: any, ns: I18nNsType = []) => { - const lang = content.req?.cookies?.NEXT_LOCALE || content.locale; - - const extraLng = content.req?.cookies?.NEXT_LOCALE ? undefined : content.locales; - return serverSideTranslations(lang, ['common', ...ns], null, extraLng); -};