diff --git a/packages/global/common/file/constants.ts b/packages/global/common/file/constants.ts index 9cc2201e1..4be4bab22 100644 --- a/packages/global/common/file/constants.ts +++ b/packages/global/common/file/constants.ts @@ -16,7 +16,7 @@ export const bucketNameMap = { } }; -export const ReadFileBaseUrl = `${process.env.FE_DOMAIN || ''}/api/common/file/read`; +export const ReadFileBaseUrl = `${process.env.FE_DOMAIN || ''}${process.env.NEXT_PUBLIC_BASE_URL}/api/common/file/read`; export const documentFileType = '.txt, .docx, .csv, .xlsx, .pdf, .md, .html, .pptx'; export const imageFileType = diff --git a/packages/global/core/chat/adapt.ts b/packages/global/core/chat/adapt.ts index 9b9c34d32..4b4b156d4 100644 --- a/packages/global/core/chat/adapt.ts +++ b/packages/global/core/chat/adapt.ts @@ -14,7 +14,6 @@ import type { ChatCompletionToolMessageParam } from '../../core/ai/type.d'; import { ChatCompletionRequestMessageRoleEnum } from '../../core/ai/constants'; - const GPT2Chat = { [ChatCompletionRequestMessageRoleEnum.System]: ChatRoleEnum.System, [ChatCompletionRequestMessageRoleEnum.User]: ChatRoleEnum.Human, @@ -61,14 +60,14 @@ export const chats2GPTMessages = ({ return { type: 'image_url', image_url: { - url: item.file?.url || '' + url: item.file.url } }; } else if (item.file?.type === ChatFileTypeEnum.file) { return { type: 'file_url', name: item.file?.name || '', - url: item.file?.url || '' + url: item.file.url }; } } diff --git a/packages/web/common/system/utils.ts b/packages/web/common/system/utils.ts index be42ee812..1015f699f 100644 --- a/packages/web/common/system/utils.ts +++ b/packages/web/common/system/utils.ts @@ -9,3 +9,12 @@ export const getUserFingerprint = async () => { export const hasHttps = () => { return window.location.protocol === 'https:'; }; + +export const getWebReqUrl = (url: string = '') => { + if (!url) return '/'; + const baseUrl = process.env.NEXT_PUBLIC_BASE_URL; + if (!baseUrl) return url; + + if (!url.startsWith('/') || url.startsWith(baseUrl)) return url; + return `${baseUrl}${url}`; +}; diff --git a/packages/web/components/common/Avatar/index.tsx b/packages/web/components/common/Avatar/index.tsx index 141f20e47..9f398ac22 100644 --- a/packages/web/components/common/Avatar/index.tsx +++ b/packages/web/components/common/Avatar/index.tsx @@ -1,9 +1,10 @@ import React from 'react'; -import { Box, Flex, Image } from '@chakra-ui/react'; +import { Box } from '@chakra-ui/react'; import type { ImageProps } from '@chakra-ui/react'; import { LOGO_ICON } from '@fastgpt/global/common/system/constants'; import MyIcon from '../Icon'; import { iconPaths } from '../Icon/constants'; +import MyImage from '../Image/MyImage'; const Avatar = ({ w = '30px', src, ...props }: ImageProps) => { // @ts-ignore @@ -14,7 +15,7 @@ const Avatar = ({ w = '30px', src, ...props }: ImageProps) => { ) : ( - { + return {props.alt; +}; +export default React.memo(MyImage); diff --git a/packages/web/components/common/Image/PhotoView.tsx b/packages/web/components/common/Image/PhotoView.tsx index 5d2199aa4..33cbdd615 100644 --- a/packages/web/components/common/Image/PhotoView.tsx +++ b/packages/web/components/common/Image/PhotoView.tsx @@ -1,9 +1,10 @@ import React from 'react'; import { PhotoProvider, PhotoView } from 'react-photo-view'; import 'react-photo-view/dist/react-photo-view.css'; -import { Box, Image, ImageProps } from '@chakra-ui/react'; +import { ImageProps } from '@chakra-ui/react'; import { useSystem } from '../../../hooks/useSystem'; import Loading from '../MyLoading'; +import MyImage from './MyImage'; const MyPhotoView = ({ ...props }: ImageProps) => { const { isPc } = useSystem(); @@ -15,7 +16,7 @@ const MyPhotoView = ({ ...props }: ImageProps) => { loadingElement={} > - + ); diff --git a/packages/web/components/common/MyDrawer/CustomRightDrawer.tsx b/packages/web/components/common/MyDrawer/CustomRightDrawer.tsx index 345673d5c..8d590a251 100644 --- a/packages/web/components/common/MyDrawer/CustomRightDrawer.tsx +++ b/packages/web/components/common/MyDrawer/CustomRightDrawer.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import MyIcon from '../Icon'; -import { Flex, Image, Box, CloseButton, FlexProps } from '@chakra-ui/react'; +import { Flex, Box, CloseButton, FlexProps } from '@chakra-ui/react'; import { useLoading } from '../../../hooks/useLoading'; +import Avatar from '../Avatar'; type Props = FlexProps & { onClose: () => void; @@ -50,15 +50,7 @@ const CustomRightDrawer = ({ py={'10px'} px={5} > - {iconSrc && ( - <> - {iconSrc.startsWith('/') ? ( - - ) : ( - - )} - - )} + {iconSrc && } {title} diff --git a/packages/web/components/common/MyDrawer/MyRightDrawer.tsx b/packages/web/components/common/MyDrawer/MyRightDrawer.tsx index 94bb01232..7dc3c428b 100644 --- a/packages/web/components/common/MyDrawer/MyRightDrawer.tsx +++ b/packages/web/components/common/MyDrawer/MyRightDrawer.tsx @@ -13,6 +13,7 @@ import { Box } from '@chakra-ui/react'; import { useLoading } from '../../../hooks/useLoading'; +import Avatar from '../Avatar'; type Props = DrawerContentProps & { onClose: () => void; @@ -52,15 +53,7 @@ const MyRightDrawer = ({ py={'10px'} px={5} > - {iconSrc && ( - <> - {iconSrc.startsWith('/') ? ( - - ) : ( - - )} - - )} + {iconSrc && } {title} diff --git a/packages/web/components/common/Textarea/CodeEditor/Editor.tsx b/packages/web/components/common/Textarea/CodeEditor/Editor.tsx index 49fb0ba7a..4177ef897 100644 --- a/packages/web/components/common/Textarea/CodeEditor/Editor.tsx +++ b/packages/web/components/common/Textarea/CodeEditor/Editor.tsx @@ -2,9 +2,10 @@ import React, { useCallback, useRef, useState } from 'react'; import Editor, { Monaco, loader } from '@monaco-editor/react'; import { Box, BoxProps } from '@chakra-ui/react'; import MyIcon from '../../Icon'; +import { getWebReqUrl } from '../../../../common/system/utils'; loader.config({ - paths: { vs: '/js/monaco-editor.0.45.0/vs' } + paths: { vs: getWebReqUrl('/js/monaco-editor.0.45.0/vs') } }); type EditorVariablePickerType = { diff --git a/packages/web/components/common/Textarea/JsonEditor/index.tsx b/packages/web/components/common/Textarea/JsonEditor/index.tsx index 18c70163c..feea41284 100644 --- a/packages/web/components/common/Textarea/JsonEditor/index.tsx +++ b/packages/web/components/common/Textarea/JsonEditor/index.tsx @@ -4,9 +4,10 @@ import { Box, BoxProps } from '@chakra-ui/react'; import MyIcon from '../../Icon'; import { useToast } from '../../../../hooks/useToast'; import { useTranslation } from 'next-i18next'; +import { getWebReqUrl } from '../../../../common/system/utils'; loader.config({ - paths: { vs: '/js/monaco-editor.0.45.0/vs' } + paths: { vs: getWebReqUrl('/js/monaco-editor.0.45.0/vs') } }); type EditorVariablePickerType = { diff --git a/packages/web/components/common/Textarea/PromptEditor/modules/ComfirmVar/index.tsx b/packages/web/components/common/Textarea/PromptEditor/modules/ComfirmVar/index.tsx deleted file mode 100644 index 22c669f27..000000000 --- a/packages/web/components/common/Textarea/PromptEditor/modules/ComfirmVar/index.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { Box, Button, Image } from '@chakra-ui/react'; -import { useTranslation } from 'next-i18next'; -export default function ComfirmVar({ - newVariables, - onCancel, - onConfirm -}: { - newVariables: string[]; - onCancel: () => void; - onConfirm: () => void; -}) { - const { t } = useTranslation(); - return ( - <> - - - - - {''} - - {t('common:undefined_var')} - - - {newVariables.map((item, index) => ( - - - {`{{`} - {item} - {`}}`} - - - ))} - - - - - - - - - - ); -} diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json index f7040562d..f51568158 100644 --- a/packages/web/i18n/en/common.json +++ b/packages/web/i18n/en/common.json @@ -1119,7 +1119,6 @@ "tag_list": "Tag List", "team_tag": "Team Tag", "textarea_variable_picker_tip": "Enter \"/\" to select a variable", - "undefined_var": "Referenced an undefined variable, add it automatically?", "unit.character": "Character", "unit.minute": "Minute", "unusable_variable": "No Usable Variables", diff --git a/packages/web/i18n/zh/common.json b/packages/web/i18n/zh/common.json index 1b669e466..9657b3661 100644 --- a/packages/web/i18n/zh/common.json +++ b/packages/web/i18n/zh/common.json @@ -1125,7 +1125,6 @@ "tag_list": "标签列表", "team_tag": "团队标签", "textarea_variable_picker_tip": "输入\"/\"可选择变量", - "undefined_var": "引用了未定义的变量,是否自动添加?", "unit.character": "字符", "unit.minute": "分钟", "unusable_variable": "无可用变量", diff --git a/projects/app/.env.template b/projects/app/.env.template index c6eba736a..9decedb37 100644 --- a/projects/app/.env.template +++ b/projects/app/.env.template @@ -35,6 +35,8 @@ SANDBOX_URL=http://localhost:3001 PRO_URL= # 页面的地址,用于自动补全相对路径资源的 domain FE_DOMAIN=http://localhost:3000 +# 二级路由 +# NEXT_PUBLIC_BASE_URL=/fastai # 日志等级: debug, info, warn, error LOG_LEVEL=debug diff --git a/projects/app/Dockerfile b/projects/app/Dockerfile index 1946263a0..1417f8ae4 100644 --- a/projects/app/Dockerfile +++ b/projects/app/Dockerfile @@ -26,6 +26,7 @@ FROM node:20.14.0-alpine AS builder WORKDIR /app ARG proxy +ARG base_url # copy common node_modules and one project node_modules COPY package.json pnpm-workspace.yaml .npmrc tsconfig.json ./ @@ -39,6 +40,7 @@ RUN [ -z "$proxy" ] || sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' / RUN apk add --no-cache libc6-compat && npm install -g pnpm@9.4.0 ENV NODE_OPTIONS="--max-old-space-size=4096" +ENV NEXT_PUBLIC_BASE_URL=$base_url RUN pnpm --filter=app build # --------- runner ----------- @@ -46,6 +48,7 @@ FROM node:20.14.0-alpine AS runner WORKDIR /app ARG proxy +ARG base_url # create user and use it RUN addgroup --system --gid 1001 nodejs @@ -81,6 +84,7 @@ RUN chown -R nextjs:nodejs /app/data ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 ENV PORT=3000 +ENV NEXT_PUBLIC_BASE_URL=$base_url EXPOSE 3000 diff --git a/projects/app/next.config.js b/projects/app/next.config.js index 1e455e044..73a53cd4e 100644 --- a/projects/app/next.config.js +++ b/projects/app/next.config.js @@ -6,6 +6,7 @@ const isDev = process.env.NODE_ENV === 'development'; /** @type {import('next').NextConfig} */ const nextConfig = { + basePath: process.env.NEXT_PUBLIC_BASE_URL, i18n, output: 'standalone', reactStrictMode: isDev ? false : true, diff --git a/projects/app/src/components/MyImage/index.tsx b/projects/app/src/components/MyImage/index.tsx index c595a888d..46d49c99d 100644 --- a/projects/app/src/components/MyImage/index.tsx +++ b/projects/app/src/components/MyImage/index.tsx @@ -1,5 +1,6 @@ import React, { useState } from 'react'; -import { Image, Skeleton, ImageProps } from '@chakra-ui/react'; +import { Skeleton, ImageProps } from '@chakra-ui/react'; +import CustomImage from '@fastgpt/web/components/common/Image/MyImage'; export const MyImage = (props: ImageProps) => { const [isLoading, setIsLoading] = useState(true); @@ -13,7 +14,7 @@ export const MyImage = (props: ImageProps) => { justifyContent={'center'} my={1} > - {''} {audioPlaying ? ( - {''} +