mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 21:13:50 +00:00
v4.6.5 (#620)
This commit is contained in:
@@ -6,10 +6,10 @@
|
||||
module.exports = {
|
||||
i18n: {
|
||||
defaultLocale: 'zh',
|
||||
locales: ['en', 'zh', 'zh-Hans', 'zh-CN'],
|
||||
localeDetection: false
|
||||
locales: ['en', 'zh'],
|
||||
localeDetection: true
|
||||
},
|
||||
localePath:
|
||||
typeof window === 'undefined' ? require('path').resolve('./public/locales') : '/locales',
|
||||
typeof window === 'undefined' ? require('path').resolve('./public/locales') : '/public/locales',
|
||||
reloadOnPrerender: process.env.NODE_ENV === 'development'
|
||||
};
|
||||
|
@@ -45,7 +45,7 @@ const nextConfig = {
|
||||
},
|
||||
transpilePackages: ['@fastgpt/*'],
|
||||
experimental: {
|
||||
serverComponentsExternalPackages: ['mongoose', 'winston', 'winston-mongodb', 'pg'],
|
||||
serverComponentsExternalPackages: ['mongoose', 'pg'],
|
||||
outputFileTracingRoot: path.join(__dirname, '../../')
|
||||
}
|
||||
};
|
||||
|
@@ -10,12 +10,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@chakra-ui/anatomy": "^2.2.1",
|
||||
"@chakra-ui/icons": "^2.0.17",
|
||||
"@chakra-ui/react": "^2.7.0",
|
||||
"@chakra-ui/icons": "^2.1.1",
|
||||
"@chakra-ui/next-js": "^2.1.5",
|
||||
"@chakra-ui/react": "^2.8.1",
|
||||
"@chakra-ui/styled-system": "^2.9.1",
|
||||
"@chakra-ui/system": "^2.5.8",
|
||||
"@emotion/react": "^11.10.6",
|
||||
"@emotion/styled": "^11.10.6",
|
||||
"@chakra-ui/system": "^2.6.1",
|
||||
"@emotion/react": "^11.11.1",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@fastgpt/plugins": "workspace:*",
|
||||
"@fastgpt/global": "workspace:*",
|
||||
"@fastgpt/service": "workspace:*",
|
||||
@@ -23,33 +24,25 @@
|
||||
"@node-rs/jieba": "^1.7.2",
|
||||
"@tanstack/react-query": "^4.24.10",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"axios": "^1.5.1",
|
||||
"date-fns": "^2.30.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"downloadjs": "^1.4.7",
|
||||
"echarts": "^5.4.1",
|
||||
"next": "13.5.2",
|
||||
"echarts-gl": "^2.0.9",
|
||||
"formidable": "^2.1.1",
|
||||
"framer-motion": "^9.0.6",
|
||||
"hyperdown": "^2.4.29",
|
||||
"i18next": "^22.5.1",
|
||||
"immer": "^9.0.19",
|
||||
"jschardet": "^3.0.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"lodash": "^4.17.21",
|
||||
"mammoth": "^1.6.0",
|
||||
"mermaid": "^10.2.3",
|
||||
"multer": "1.4.5-lts.1",
|
||||
"nanoid": "^4.0.1",
|
||||
"next": "13.5.2",
|
||||
"next-i18next": "^13.3.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"papaparse": "^5.4.1",
|
||||
"react": "18.2.0",
|
||||
"react-day-picker": "^8.7.1",
|
||||
"react-dom": "18.2.0",
|
||||
"react-hook-form": "^7.43.1",
|
||||
"react-i18next": "^12.3.1",
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"reactflow": "^11.7.4",
|
||||
@@ -59,28 +52,28 @@
|
||||
"remark-math": "^5.1.1",
|
||||
"request-ip": "^3.3.0",
|
||||
"sass": "^1.58.3",
|
||||
"zustand": "^4.3.5"
|
||||
"zustand": "^4.3.5",
|
||||
"i18next": "^22.5.1",
|
||||
"next-i18next": "^13.3.0",
|
||||
"react-i18next": "^12.3.1",
|
||||
"axios": "^1.5.1",
|
||||
"nanoid": "^4.0.1",
|
||||
"dayjs": "^1.11.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@svgr/webpack": "^6.5.1",
|
||||
"@types/downloadjs": "^1.4.3",
|
||||
"@types/formidable": "^2.0.5",
|
||||
"@types/js-cookie": "^3.0.3",
|
||||
"@types/jsonwebtoken": "^9.0.3",
|
||||
"@types/lodash": "^4.14.191",
|
||||
"@types/multer": "^1.4.10",
|
||||
"@types/node": "^20.8.5",
|
||||
"@types/papaparse": "^5.3.7",
|
||||
"@types/react": "18.0.28",
|
||||
"@types/react-dom": "18.0.11",
|
||||
"@types/react": "18.2.0",
|
||||
"@types/react-dom": "18.2.0",
|
||||
"@types/react-syntax-highlighter": "^15.5.6",
|
||||
"@types/request-ip": "^0.0.37",
|
||||
"eslint": "8.34.0",
|
||||
"eslint-config-next": "13.1.6",
|
||||
"typescript": "4.9.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"pnpm": ">=8.6.0"
|
||||
}
|
||||
}
|
||||
|
1
projects/app/public/imgs/module/customFeedback.svg
Normal file
1
projects/app/public/imgs/module/customFeedback.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1702637232008" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6146" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M261.688889 194.218667A67.470222 67.470222 0 1 1 194.218667 261.688889 67.584 67.584 0 0 1 261.688889 194.218667M261.688889 136.533333a125.155556 125.155556 0 1 0 125.155555 125.155556 125.155556 125.155556 0 0 0-125.155555-125.155556zM614.4 444.529778A67.470222 67.470222 0 1 1 547.271111 512a67.584 67.584 0 0 1 67.128889-67.470222M614.4 386.844444a125.155556 125.155556 0 1 0 125.155556 125.155556 125.155556 125.155556 0 0 0-125.155556-125.155556zM408.120889 694.840889A67.470222 67.470222 0 1 1 340.650667 762.311111a67.470222 67.470222 0 0 1 67.470222-67.470222m0-57.685333a125.155556 125.155556 0 1 0 125.155555 125.155555 125.155556 125.155556 0 0 0-125.155555-125.155555z" fill="#1DCCA1" p-id="6147"></path><path d="M489.016889 736.142222h375.011555v52.337778H489.016889zM325.632 788.48h-42.894222C171.804444 788.48 113.777778 711.452444 113.777778 635.335111a143.36 143.36 0 0 1 43.235555-103.651555c30.833778-30.037333 74.296889-45.511111 125.724445-45.511112h242.119111v52.337778H282.737778c-80.554667 0-116.622222 48.810667-116.622222 97.166222s36.522667 100.807111 116.622222 100.807112h42.894222zM743.537778 538.168889h-40.618667v-52.337778h40.618667c78.620444 0 114.346667-51.541333 114.346666-99.555555s-35.384889-98.417778-114.346666-98.417778H337.123556v-52.337778h406.414222C853.333333 235.52 910.222222 311.409778 910.222222 386.844444a147.911111 147.911111 0 0 1-42.780444 104.903112 168.732444 168.732444 0 0 1-123.904 46.421333z" fill="#1DCCA1" p-id="6148"></path><path d="M910.222222 762.311111l-136.533333 102.4V659.911111l136.533333 102.4z" fill="#1DCCA1" p-id="6149"></path></svg>
|
After Width: | Height: | Size: 1.9 KiB |
@@ -247,6 +247,10 @@
|
||||
"Save and out": "Save out",
|
||||
"UnSave": "UnSave"
|
||||
},
|
||||
"feedback": {
|
||||
"Custom feedback": "Custom feedback",
|
||||
"close custom feedback": "Close Feedback"
|
||||
},
|
||||
"logs": {
|
||||
"Source And Time": "Source & Time"
|
||||
},
|
||||
|
@@ -247,6 +247,10 @@
|
||||
"Save and out": "保存并退出",
|
||||
"UnSave": "不保存"
|
||||
},
|
||||
"feedback": {
|
||||
"Custom feedback": "自定义反馈",
|
||||
"close custom feedback": "关闭反馈"
|
||||
},
|
||||
"logs": {
|
||||
"Source And Time": "来源 & 时间"
|
||||
},
|
||||
|
@@ -18,7 +18,8 @@ type pluginType = {
|
||||
name: string;
|
||||
avatar: string;
|
||||
intro: string;
|
||||
modules: 直接从高级编排导出配置复制过来;
|
||||
showStatus?: boolean; // 是否需要展示组件运行状态
|
||||
modules: []; //直接从高级编排导出配置复制过来;
|
||||
};
|
||||
```
|
||||
|
||||
|
319
projects/app/public/pluginTemplates/customFeedback.json
Normal file
319
projects/app/public/pluginTemplates/customFeedback.json
Normal file
@@ -0,0 +1,319 @@
|
||||
{
|
||||
"author": "FastGPT Team",
|
||||
"templateType": "other",
|
||||
"name": "自定义反馈",
|
||||
"avatar": "/imgs/module/customFeedback.svg",
|
||||
"intro": "该模块被触发时,会给当前的对话记录增加一条反馈。可用于自动记录对话效果等。",
|
||||
"showStatus": false,
|
||||
"modules": [
|
||||
{
|
||||
"moduleId": "w90mfp",
|
||||
"name": "定义插件输入",
|
||||
"avatar": "/imgs/module/input.png",
|
||||
"flowType": "pluginInput",
|
||||
"showStatus": false,
|
||||
"position": {
|
||||
"x": 515.1887815471657,
|
||||
"y": -169.04905809653783
|
||||
},
|
||||
"inputs": [
|
||||
{
|
||||
"key": "defaultFeedback",
|
||||
"valueType": "string",
|
||||
"label": "默认反馈内容",
|
||||
"type": "textarea",
|
||||
"required": false,
|
||||
"description": "",
|
||||
"edit": true,
|
||||
"editField": {
|
||||
"key": true,
|
||||
"name": true,
|
||||
"description": true,
|
||||
"required": true,
|
||||
"dataType": true,
|
||||
"inputType": true
|
||||
},
|
||||
"connected": true
|
||||
},
|
||||
{
|
||||
"key": "customFeedback",
|
||||
"valueType": "string",
|
||||
"label": "自定义反馈内容",
|
||||
"type": "target",
|
||||
"required": false,
|
||||
"description": "",
|
||||
"edit": true,
|
||||
"editField": {
|
||||
"key": true,
|
||||
"name": true,
|
||||
"description": true,
|
||||
"required": true,
|
||||
"dataType": true,
|
||||
"inputType": true
|
||||
},
|
||||
"connected": true
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"key": "defaultFeedback",
|
||||
"valueType": "string",
|
||||
"label": "默认反馈内容",
|
||||
"type": "source",
|
||||
"edit": true,
|
||||
"targets": [
|
||||
{
|
||||
"moduleId": "49de3g",
|
||||
"key": "defaultFeedback"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "customFeedback",
|
||||
"valueType": "string",
|
||||
"label": "自定义反馈内容",
|
||||
"type": "source",
|
||||
"edit": true,
|
||||
"targets": [
|
||||
{
|
||||
"moduleId": "49de3g",
|
||||
"key": "customFeedback"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"moduleId": "49de3g",
|
||||
"name": "HTTP模块",
|
||||
"avatar": "/imgs/module/http.png",
|
||||
"flowType": "httpRequest",
|
||||
"showStatus": true,
|
||||
"position": {
|
||||
"x": 1086.8929621216014,
|
||||
"y": -451.7550009773506
|
||||
},
|
||||
"inputs": [
|
||||
{
|
||||
"key": "switch",
|
||||
"type": "target",
|
||||
"label": "core.module.input.label.switch",
|
||||
"valueType": "any",
|
||||
"showTargetInApp": true,
|
||||
"showTargetInPlugin": true,
|
||||
"connected": false
|
||||
},
|
||||
{
|
||||
"key": "system_httpMethod",
|
||||
"type": "select",
|
||||
"valueType": "string",
|
||||
"label": "core.module.input.label.Http Request Method",
|
||||
"value": "POST",
|
||||
"list": [
|
||||
{
|
||||
"label": "GET",
|
||||
"value": "GET"
|
||||
},
|
||||
{
|
||||
"label": "POST",
|
||||
"value": "POST"
|
||||
}
|
||||
],
|
||||
"required": true,
|
||||
"showTargetInApp": false,
|
||||
"showTargetInPlugin": false,
|
||||
"connected": false
|
||||
},
|
||||
{
|
||||
"key": "system_httpReqUrl",
|
||||
"type": "input",
|
||||
"valueType": "string",
|
||||
"label": "core.module.input.label.Http Request Url",
|
||||
"description": "core.module.input.description.Http Request Url",
|
||||
"placeholder": "https://api.ai.com/getInventory",
|
||||
"required": false,
|
||||
"showTargetInApp": false,
|
||||
"showTargetInPlugin": false,
|
||||
"value": "/api/plugins/customFeedback",
|
||||
"connected": false
|
||||
},
|
||||
{
|
||||
"key": "system_httpHeader",
|
||||
"type": "textarea",
|
||||
"valueType": "string",
|
||||
"label": "core.module.input.label.Http Request Header",
|
||||
"description": "core.module.input.description.Http Request Header",
|
||||
"placeholder": "core.module.input.description.Http Request Header",
|
||||
"required": false,
|
||||
"showTargetInApp": false,
|
||||
"showTargetInPlugin": false,
|
||||
"value": "",
|
||||
"connected": false
|
||||
},
|
||||
{
|
||||
"key": "DYNAMIC_INPUT_KEY",
|
||||
"type": "target",
|
||||
"valueType": "any",
|
||||
"label": "core.module.inputType.dynamicTargetInput",
|
||||
"description": "core.module.input.description.dynamic input",
|
||||
"required": false,
|
||||
"showTargetInApp": false,
|
||||
"showTargetInPlugin": true,
|
||||
"hideInApp": true,
|
||||
"connected": false
|
||||
},
|
||||
{
|
||||
"valueType": "string",
|
||||
"label": "defaultFeedback",
|
||||
"type": "target",
|
||||
"required": true,
|
||||
"description": "",
|
||||
"edit": true,
|
||||
"editField": {
|
||||
"key": true,
|
||||
"name": true,
|
||||
"description": true,
|
||||
"required": true,
|
||||
"dataType": true
|
||||
},
|
||||
"connected": true,
|
||||
"key": "defaultFeedback"
|
||||
},
|
||||
{
|
||||
"key": "customFeedback",
|
||||
"valueType": "string",
|
||||
"label": "customFeedback",
|
||||
"type": "target",
|
||||
"required": true,
|
||||
"description": "",
|
||||
"edit": true,
|
||||
"editField": {
|
||||
"key": true,
|
||||
"name": true,
|
||||
"description": true,
|
||||
"required": true,
|
||||
"dataType": true
|
||||
},
|
||||
"connected": true
|
||||
},
|
||||
{
|
||||
"key": "system_addInputParam",
|
||||
"type": "addInputParam",
|
||||
"valueType": "any",
|
||||
"label": "",
|
||||
"required": false,
|
||||
"showTargetInApp": false,
|
||||
"showTargetInPlugin": false,
|
||||
"editField": {
|
||||
"key": true,
|
||||
"name": true,
|
||||
"description": true,
|
||||
"required": true,
|
||||
"dataType": true
|
||||
},
|
||||
"defaultEditField": {
|
||||
"label": "",
|
||||
"key": "",
|
||||
"description": "",
|
||||
"inputType": "target",
|
||||
"valueType": "string",
|
||||
"required": true
|
||||
},
|
||||
"connected": false
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"key": "finish",
|
||||
"label": "core.module.output.label.running done",
|
||||
"description": "core.module.output.description.running done",
|
||||
"valueType": "boolean",
|
||||
"type": "source",
|
||||
"targets": []
|
||||
},
|
||||
{
|
||||
"key": "system_addOutputParam",
|
||||
"type": "addOutputParam",
|
||||
"valueType": "any",
|
||||
"label": "",
|
||||
"targets": [],
|
||||
"editField": {
|
||||
"key": true,
|
||||
"name": true,
|
||||
"description": true,
|
||||
"dataType": true
|
||||
},
|
||||
"defaultEditField": {
|
||||
"label": "",
|
||||
"key": "",
|
||||
"description": "",
|
||||
"outputType": "source",
|
||||
"valueType": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "source",
|
||||
"valueType": "string",
|
||||
"label": "response",
|
||||
"description": "",
|
||||
"edit": true,
|
||||
"editField": {
|
||||
"key": true,
|
||||
"name": true,
|
||||
"description": true,
|
||||
"dataType": true
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"moduleId": "s15f3v",
|
||||
"key": "text"
|
||||
}
|
||||
],
|
||||
"key": "response"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"moduleId": "s15f3v",
|
||||
"name": "指定回复",
|
||||
"avatar": "/imgs/module/reply.png",
|
||||
"flowType": "answerNode",
|
||||
"position": {
|
||||
"x": 1705.6337348182756,
|
||||
"y": -37.53826066726282
|
||||
},
|
||||
"inputs": [
|
||||
{
|
||||
"key": "switch",
|
||||
"type": "target",
|
||||
"label": "core.module.input.label.switch",
|
||||
"valueType": "any",
|
||||
"showTargetInApp": true,
|
||||
"showTargetInPlugin": true,
|
||||
"connected": false
|
||||
},
|
||||
{
|
||||
"key": "text",
|
||||
"type": "textarea",
|
||||
"valueType": "any",
|
||||
"label": "回复的内容",
|
||||
"description": "可以使用 \\n 来实现连续换行。\n可以通过外部模块输入实现回复,外部模块输入时会覆盖当前填写的内容。\n如传入非字符串类型数据将会自动转成字符串",
|
||||
"placeholder": "可以使用 \\n 来实现连续换行。\n可以通过外部模块输入实现回复,外部模块输入时会覆盖当前填写的内容。\n如传入非字符串类型数据将会自动转成字符串",
|
||||
"showTargetInApp": true,
|
||||
"showTargetInPlugin": true,
|
||||
"connected": true
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"key": "finish",
|
||||
"label": "core.module.output.label.running done",
|
||||
"description": "core.module.output.description.running done",
|
||||
"valueType": "boolean",
|
||||
"type": "source",
|
||||
"targets": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -4,6 +4,7 @@
|
||||
"name": "core.module.template.textEditor",
|
||||
"avatar": "/imgs/module/textEditor.svg",
|
||||
"intro": "core.module.template.textEditor intro",
|
||||
"showStatus": false,
|
||||
"modules": [
|
||||
{
|
||||
"moduleId": "w90mfp",
|
@@ -4,6 +4,7 @@
|
||||
"name": "core.module.template.TFSwitch",
|
||||
"avatar": "/imgs/module/tfSwitch.svg",
|
||||
"intro": "core.module.template.TFSwitch intro",
|
||||
"showStatus": false,
|
||||
"modules": [
|
||||
{
|
||||
"moduleId": "w90mfp",
|
@@ -2,7 +2,7 @@ import { useSpeech } from '@/web/common/hooks/useSpeech';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { Box, Flex, Image, Spinner, Textarea } from '@chakra-ui/react';
|
||||
import React, { useRef, useEffect, useCallback, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import MyTooltip from '../MyTooltip';
|
||||
import MyIcon from '../Icon';
|
||||
import styles from './index.module.scss';
|
||||
@@ -216,7 +216,7 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')}
|
||||
pl={5}
|
||||
alignItems={'center'}
|
||||
bg={'white'}
|
||||
color={'myBlue.600'}
|
||||
color={'blue.500'}
|
||||
visibility={isSpeaking && isTransCription ? 'visible' : 'hidden'}
|
||||
>
|
||||
<Spinner size={'sm'} mr={4} />
|
||||
@@ -244,7 +244,7 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')}
|
||||
alignItems={'center'}
|
||||
justifyContent={'center'}
|
||||
rounded={'md'}
|
||||
color={'myBlue.600'}
|
||||
color={'blue.500'}
|
||||
top={0}
|
||||
left={0}
|
||||
bottom={0}
|
||||
@@ -260,7 +260,7 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')}
|
||||
h={'16px'}
|
||||
color={'myGray.700'}
|
||||
cursor={'pointer'}
|
||||
_hover={{ color: 'myBlue.600' }}
|
||||
_hover={{ color: 'blue.500' }}
|
||||
position={'absolute'}
|
||||
bg={'white'}
|
||||
right={'-8px'}
|
||||
@@ -396,7 +396,7 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')}
|
||||
name={isSpeaking ? 'core/chat/stopSpeechFill' : 'core/chat/recordFill'}
|
||||
width={['20px', '22px']}
|
||||
height={['20px', '22px']}
|
||||
color={'myBlue.600'}
|
||||
color={'blue.500'}
|
||||
/>
|
||||
</MyTooltip>
|
||||
</Flex>
|
||||
@@ -415,7 +415,7 @@ ${images.map((img) => JSON.stringify({ src: img.src })).join('\n')}
|
||||
h={['28px', '32px']}
|
||||
w={['28px', '32px']}
|
||||
borderRadius={'md'}
|
||||
bg={isSpeaking || isChatting ? '' : !havInput ? '#E5E5E5' : 'myBlue.600'}
|
||||
bg={isSpeaking || isChatting ? '' : !havInput ? '#E5E5E5' : 'blue.500'}
|
||||
cursor={havInput ? 'pointer' : 'not-allowed'}
|
||||
lineHeight={1}
|
||||
onClick={() => {
|
||||
|
@@ -105,7 +105,7 @@ const QuoteModal = ({
|
||||
className="hover-data"
|
||||
display={'none'}
|
||||
alignItems={'center'}
|
||||
color={'myBlue.600'}
|
||||
color={'blue.500'}
|
||||
href={`/dataset/detail?datasetId=${item.datasetId}¤tTab=dataCard&collectionId=${item.collectionId}`}
|
||||
>
|
||||
{t('core.dataset.Go Dataset')}
|
||||
@@ -164,7 +164,7 @@ const QuoteModal = ({
|
||||
cursor={'pointer'}
|
||||
color={'myGray.600'}
|
||||
_hover={{
|
||||
color: 'myBlue.700'
|
||||
color: 'blue.600'
|
||||
}}
|
||||
onClick={() => onclickEdit(item)}
|
||||
/>
|
||||
|
@@ -147,7 +147,7 @@ const ResponseTags = ({
|
||||
name="common/routePushLight"
|
||||
w={'14px'}
|
||||
cursor={'pointer'}
|
||||
_hover={{ color: 'myBlue.600' }}
|
||||
_hover={{ color: 'blue.500' }}
|
||||
onClick={async (e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
|
@@ -35,7 +35,7 @@ const SelectMarkCollection = ({
|
||||
const theme = useTheme();
|
||||
const [selectedDatasetId, setSelectedDatasetId] = useState<string>();
|
||||
const [selectedDatasetCollectionIds, setSelectedDatasetCollectionIds] = useState<string[]>([]);
|
||||
const { paths, parentId, setParentId, datasets, isFetching } = useDatasetSelect();
|
||||
const { paths, setParentId, datasets, isFetching } = useDatasetSelect();
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -70,7 +70,7 @@ const SelectMarkCollection = ({
|
||||
}}
|
||||
{...(selected
|
||||
? {
|
||||
bg: 'myBlue.300'
|
||||
bg: 'blue.200'
|
||||
}
|
||||
: {})}
|
||||
onClick={() => {
|
||||
|
@@ -27,7 +27,8 @@ import {
|
||||
BoxProps,
|
||||
FlexProps,
|
||||
Image,
|
||||
Textarea
|
||||
Textarea,
|
||||
Checkbox
|
||||
} from '@chakra-ui/react';
|
||||
import { feConfigs } from '@/web/common/system/staticData';
|
||||
import { EventNameEnum, eventBus } from '@/web/common/utils/eventbus';
|
||||
@@ -43,7 +44,11 @@ import { useRouter } from 'next/router';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
import { updateChatAdminFeedback, updateChatUserFeedback } from '@/web/core/chat/api';
|
||||
import {
|
||||
closeCustomFeedback,
|
||||
updateChatAdminFeedback,
|
||||
updateChatUserFeedback
|
||||
} from '@/web/core/chat/api';
|
||||
import type { AdminMarkType } from './SelectMarkCollection';
|
||||
|
||||
import MyIcon from '@/components/Icon';
|
||||
@@ -63,6 +68,7 @@ import { splitGuideModule } from '@fastgpt/global/core/module/utils';
|
||||
import type { AppTTSConfigType } from '@fastgpt/global/core/module/type.d';
|
||||
import MessageInput from './MessageInput';
|
||||
import { ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import ChatBoxDivider from '../core/chat/Divider';
|
||||
|
||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 24);
|
||||
|
||||
@@ -492,7 +498,7 @@ const ChatBox = (
|
||||
const colorMap = {
|
||||
loading: 'myGray.700',
|
||||
running: '#67c13b',
|
||||
finish: 'myBlue.600'
|
||||
finish: 'blue.500'
|
||||
};
|
||||
if (!isChatting) return;
|
||||
const chatContent = chatHistory[chatHistory.length - 1];
|
||||
@@ -660,7 +666,7 @@ const ChatBox = (
|
||||
<Card
|
||||
className="markdown"
|
||||
{...MessageCardStyle}
|
||||
bg={'myBlue.300'}
|
||||
bg={'blue.200'}
|
||||
borderRadius={'8px 0 8px 8px'}
|
||||
textAlign={'left'}
|
||||
>
|
||||
@@ -853,16 +859,56 @@ const ChatBox = (
|
||||
|
||||
<ResponseTags responseData={item.responseData} isShare={!!shareId} />
|
||||
|
||||
{/* custom feedback */}
|
||||
{item.customFeedbacks && item.customFeedbacks.length > 0 && (
|
||||
<Box>
|
||||
<ChatBoxDivider
|
||||
icon={'core/app/customFeedback'}
|
||||
text={t('core.app.feedback.Custom feedback')}
|
||||
/>
|
||||
{item.customFeedbacks.map((text, i) => (
|
||||
<Box key={`${text}${i}`}>
|
||||
<MyTooltip label={t('core.app.feedback.close custom feedback')}>
|
||||
<Checkbox
|
||||
onChange={(e) => {
|
||||
if (e.target.checked && appId && chatId && item.dataId) {
|
||||
closeCustomFeedback({
|
||||
appId,
|
||||
chatId,
|
||||
chatItemId: item.dataId,
|
||||
index: i
|
||||
});
|
||||
// update dom
|
||||
setChatHistory((state) =>
|
||||
state.map((chatItem) =>
|
||||
chatItem.dataId === item.dataId
|
||||
? {
|
||||
...chatItem,
|
||||
customFeedbacks: chatItem.customFeedbacks?.filter(
|
||||
(item, index) => index !== i
|
||||
)
|
||||
}
|
||||
: chatItem
|
||||
)
|
||||
);
|
||||
}
|
||||
console.log(e);
|
||||
}}
|
||||
>
|
||||
{text}
|
||||
</Checkbox>
|
||||
</MyTooltip>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
{/* admin mark content */}
|
||||
{showMarkIcon && item.adminFeedback && (
|
||||
<Box>
|
||||
<Flex alignItems={'center'} py={2}>
|
||||
<MyIcon name={'core/app/markLight'} w={'14px'} color={'myGray.900'} />
|
||||
<Box ml={2} color={'myGray.500'}>
|
||||
{t('chat.Admin Mark Content')}
|
||||
</Box>
|
||||
<Box h={'1px'} bg={'myGray.300'} flex={'1'} />
|
||||
</Flex>
|
||||
<ChatBoxDivider
|
||||
icon="core/app/markLight"
|
||||
text={t('chat.Admin Mark Content')}
|
||||
/>
|
||||
<Box whiteSpace={'pre'}>{`${item.adminFeedback.q || ''}${
|
||||
item.adminFeedback.a ? `\n${item.adminFeedback.a}` : ''
|
||||
}`}</Box>
|
||||
@@ -942,7 +988,10 @@ const ChatBox = (
|
||||
setAdminMarkData={(e) => setAdminMarkData({ ...e, chatItemId: adminMarkData.chatItemId })}
|
||||
onClose={() => setAdminMarkData(undefined)}
|
||||
onSuccess={(adminFeedback) => {
|
||||
if (!appId || !chatId || !adminMarkData.chatItemId) return;
|
||||
updateChatAdminFeedback({
|
||||
appId,
|
||||
chatId,
|
||||
chatItemId: adminMarkData.chatItemId,
|
||||
...adminFeedback
|
||||
});
|
||||
@@ -1089,7 +1138,7 @@ function ChatAvatar({ src, type }: { src?: string; type: 'Human' | 'AI' }) {
|
||||
borderRadius={'lg'}
|
||||
border={theme.borders.base}
|
||||
boxShadow={'0 0 5px rgba(0,0,0,0.1)'}
|
||||
bg={type === 'Human' ? 'white' : 'myBlue.100'}
|
||||
bg={type === 'Human' ? 'white' : 'blue.50'}
|
||||
>
|
||||
<Avatar src={src} w={'100%'} h={'100%'} />
|
||||
</Box>
|
||||
@@ -1170,7 +1219,7 @@ function ChatController({
|
||||
<MyIcon
|
||||
{...controlIconStyle}
|
||||
name={'copy'}
|
||||
_hover={{ color: 'myBlue.700' }}
|
||||
_hover={{ color: 'blue.600' }}
|
||||
onClick={() => copyData(chat.value)}
|
||||
/>
|
||||
</MyTooltip>
|
||||
|
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1702637232008"
|
||||
class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6146"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128">
|
||||
<path
|
||||
d="M261.688889 194.218667A67.470222 67.470222 0 1 1 194.218667 261.688889 67.584 67.584 0 0 1 261.688889 194.218667M261.688889 136.533333a125.155556 125.155556 0 1 0 125.155555 125.155556 125.155556 125.155556 0 0 0-125.155555-125.155556zM614.4 444.529778A67.470222 67.470222 0 1 1 547.271111 512a67.584 67.584 0 0 1 67.128889-67.470222M614.4 386.844444a125.155556 125.155556 0 1 0 125.155556 125.155556 125.155556 125.155556 0 0 0-125.155556-125.155556zM408.120889 694.840889A67.470222 67.470222 0 1 1 340.650667 762.311111a67.470222 67.470222 0 0 1 67.470222-67.470222m0-57.685333a125.155556 125.155556 0 1 0 125.155555 125.155555 125.155556 125.155556 0 0 0-125.155555-125.155555z"
|
||||
fill="#1DCCA1" p-id="6147"></path>
|
||||
<path
|
||||
d="M489.016889 736.142222h375.011555v52.337778H489.016889zM325.632 788.48h-42.894222C171.804444 788.48 113.777778 711.452444 113.777778 635.335111a143.36 143.36 0 0 1 43.235555-103.651555c30.833778-30.037333 74.296889-45.511111 125.724445-45.511112h242.119111v52.337778H282.737778c-80.554667 0-116.622222 48.810667-116.622222 97.166222s36.522667 100.807111 116.622222 100.807112h42.894222zM743.537778 538.168889h-40.618667v-52.337778h40.618667c78.620444 0 114.346667-51.541333 114.346666-99.555555s-35.384889-98.417778-114.346666-98.417778H337.123556v-52.337778h406.414222C853.333333 235.52 910.222222 311.409778 910.222222 386.844444a147.911111 147.911111 0 0 1-42.780444 104.903112 168.732444 168.732444 0 0 1-123.904 46.421333z"
|
||||
fill="#1DCCA1" p-id="6148"></path>
|
||||
<path d="M910.222222 762.311111l-136.533333 102.4V659.911111l136.533333 102.4z" fill="#1DCCA1" p-id="6149"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
@@ -124,7 +124,8 @@ const iconPaths = {
|
||||
'common/confirm/deleteTip': () => import('./icons/common/confirm/deleteTip.svg'),
|
||||
'common/confirm/commonTip': () => import('./icons/common/confirm/commonTip.svg'),
|
||||
'common/routePushLight': () => import('./icons/common/routePushLight.svg'),
|
||||
'common/viewLight': () => import('./icons/common/viewLight.svg')
|
||||
'common/viewLight': () => import('./icons/common/viewLight.svg'),
|
||||
'core/app/customFeedback': () => import('./icons/core/app/customFeedback.svg')
|
||||
};
|
||||
|
||||
export type IconName = keyof typeof iconPaths;
|
||||
|
@@ -129,7 +129,7 @@ const Navbar = ({ unread }: { unread: number }) => {
|
||||
{...itemStyles}
|
||||
{...(item.activeLink.includes(router.pathname)
|
||||
? {
|
||||
color: 'myBlue.700',
|
||||
color: 'blue.600',
|
||||
bg: 'white !important',
|
||||
boxShadow: '1px 1px 10px rgba(0,0,0,0.2)'
|
||||
}
|
||||
|
@@ -25,9 +25,9 @@ const Loading = ({
|
||||
justifyContent={'center'}
|
||||
flexDirection={'column'}
|
||||
>
|
||||
<Spinner thickness="4px" speed="0.65s" emptyColor="myGray.100" color="myBlue.600" size="xl" />
|
||||
<Spinner thickness="4px" speed="0.65s" emptyColor="myGray.100" color="blue.500" size="xl" />
|
||||
{text && (
|
||||
<Box mt={2} color="myBlue.700" fontWeight={'bold'}>
|
||||
<Box mt={2} color="blue.600" fontWeight={'bold'}>
|
||||
{text}
|
||||
</Box>
|
||||
)}
|
||||
|
@@ -23,7 +23,7 @@ function MyLink(e: any) {
|
||||
<Box as={'li'} mb={1}>
|
||||
<Box
|
||||
as={'span'}
|
||||
color={'blue.600'}
|
||||
color={'blue.500'}
|
||||
textDecoration={'underline'}
|
||||
cursor={'pointer'}
|
||||
onClick={() => {
|
||||
|
@@ -77,7 +77,7 @@ const QuestionGuide = ({ text }: { text: string }) => {
|
||||
name={'core/chat/sendLight'}
|
||||
w={'14px'}
|
||||
cursor={'pointer'}
|
||||
_hover={{ color: 'myBlue.600' }}
|
||||
_hover={{ color: 'blue.500' }}
|
||||
onClick={() => eventBus.emit(EventNameEnum.sendQuestion, { text })}
|
||||
/>
|
||||
</MyTooltip>
|
||||
|
@@ -123,7 +123,7 @@ const MermaidBlock = ({ code }: { code: string }) => {
|
||||
position={'absolute'}
|
||||
color={'myGray.600'}
|
||||
_hover={{
|
||||
color: 'myBlue.700'
|
||||
color: 'blue.600'
|
||||
}}
|
||||
right={0}
|
||||
top={0}
|
||||
|
@@ -1,20 +1,23 @@
|
||||
.waitingAnimation::after {
|
||||
.waitingAnimation > :last-child::after {
|
||||
display: inline-block;
|
||||
content: '';
|
||||
width: 4px;
|
||||
width: 3px;
|
||||
height: 14px;
|
||||
transform: translate(4px, 2px) scaleY(1.3);
|
||||
background-color: var(--chakra-colors-chakra-body-text);
|
||||
background-color: var(--chakra-colors-blue-700);
|
||||
animation: blink 0.6s infinite;
|
||||
}
|
||||
|
||||
.animation {
|
||||
> :last-child::after {
|
||||
height: 20px;
|
||||
|
||||
&::after {
|
||||
display: inline-block;
|
||||
content: '';
|
||||
width: 4px;
|
||||
width: 3px;
|
||||
height: 14px;
|
||||
transform: translate(4px, 2px) scaleY(1.3);
|
||||
background-color: var(--chakra-colors-chakra-body-text);
|
||||
background-color: var(--chakra-colors-blue-700);
|
||||
animation: blink 0.6s infinite;
|
||||
}
|
||||
}
|
||||
|
@@ -96,10 +96,10 @@ function A({ children, ...props }: any) {
|
||||
name={'core/chat/quoteSign'}
|
||||
transform={'translateY(-2px)'}
|
||||
w={'18px'}
|
||||
color={'myBlue.600'}
|
||||
color={'blue.500'}
|
||||
cursor={'pointer'}
|
||||
_hover={{
|
||||
color: 'myBlue.800'
|
||||
color: 'blue.700'
|
||||
}}
|
||||
onClick={() => getFileAndOpen(props.href)}
|
||||
/>
|
||||
@@ -131,7 +131,7 @@ const Markdown = ({ source, isChatting = false }: { source: string; isChatting?:
|
||||
return (
|
||||
<ReactMarkdown
|
||||
className={`markdown ${styles.markdown}
|
||||
${isChatting ? (source === '' ? styles.waitingAnimation : styles.animation) : ''}
|
||||
${isChatting ? `${formatSource ? styles.waitingAnimation : styles.animation}` : ''}
|
||||
`}
|
||||
remarkPlugins={[RemarkGfm, RemarkMath, RemarkBreaks]}
|
||||
rehypePlugins={[RehypeKatex]}
|
||||
|
@@ -41,7 +41,7 @@ const MyMenu = ({ width, offset = [0, 10], Button, menuList }: Props) => {
|
||||
e.stopPropagation();
|
||||
item.onClick && item.onClick();
|
||||
}}
|
||||
color={item.isActive ? 'myBlue.600' : ''}
|
||||
color={item.isActive ? 'blue.500' : ''}
|
||||
whiteSpace={'pre-wrap'}
|
||||
>
|
||||
{item.child}
|
||||
|
@@ -32,7 +32,7 @@ const PromptTemplate = ({
|
||||
cursor={'pointer'}
|
||||
{...(item.title === selectTemplateTitle?.title
|
||||
? {
|
||||
bg: 'myBlue.100'
|
||||
bg: 'blue.50'
|
||||
}
|
||||
: {})}
|
||||
onClick={() => setSelectTemplateTitle(item)}
|
||||
|
@@ -62,7 +62,7 @@ const MySelect = (
|
||||
{...(isOpen
|
||||
? {
|
||||
boxShadow: '0px 0px 4px #A8DBFF',
|
||||
borderColor: 'myBlue.600'
|
||||
borderColor: 'blue.500'
|
||||
}
|
||||
: {})}
|
||||
{...props}
|
||||
@@ -93,7 +93,7 @@ const MySelect = (
|
||||
{...menuItemStyles}
|
||||
{...(value === item.value
|
||||
? {
|
||||
color: 'myBlue.600',
|
||||
color: 'blue.500',
|
||||
bg: 'myWhite.300'
|
||||
}
|
||||
: {})}
|
||||
|
@@ -44,9 +44,9 @@ const SideTabs = ({ list, size = 'md', activeId, onChange, ...props }: Props) =>
|
||||
alignItems={'center'}
|
||||
{...(activeId === item.id
|
||||
? {
|
||||
bg: ' myBlue.300 !important',
|
||||
bg: ' blue.200 !important',
|
||||
fontWeight: 'bold',
|
||||
color: 'myBlue.700 ',
|
||||
color: 'blue.600 ',
|
||||
cursor: 'default'
|
||||
}
|
||||
: {
|
||||
|
@@ -69,7 +69,7 @@ const MySlider = ({
|
||||
<SliderMark
|
||||
value={value}
|
||||
textAlign="center"
|
||||
bg="myBlue.600"
|
||||
bg="blue.500"
|
||||
color="white"
|
||||
px={1}
|
||||
minW={'18px'}
|
||||
@@ -95,9 +95,9 @@ const MySlider = ({
|
||||
right: '-3px'
|
||||
}}
|
||||
>
|
||||
<SliderFilledTrack bg={'myBlue.600'} />
|
||||
<SliderFilledTrack bg={'blue.500'} />
|
||||
</SliderTrack>
|
||||
<SliderThumb border={'3px solid'} borderColor={'myBlue.600'}></SliderThumb>
|
||||
<SliderThumb border={'3px solid'} borderColor={'blue.500'}></SliderThumb>
|
||||
</Slider>
|
||||
);
|
||||
};
|
||||
|
@@ -55,10 +55,10 @@ const Tabs = ({ list, size = 'md', activeId, onChange, ...props }: Props) => {
|
||||
whiteSpace={'nowrap'}
|
||||
{...(activeId === item.id
|
||||
? {
|
||||
color: 'myBlue.700',
|
||||
color: 'blue.600',
|
||||
cursor: 'default',
|
||||
fontWeight: 'bold',
|
||||
borderBottomColor: 'myBlue.700'
|
||||
borderBottomColor: 'blue.600'
|
||||
}
|
||||
: {
|
||||
cursor: 'pointer'
|
||||
|
@@ -10,9 +10,9 @@ const Tag = ({ children, colorSchema = 'blue', ...props }: Props) => {
|
||||
const theme = useMemo(() => {
|
||||
const map = {
|
||||
blue: {
|
||||
borderColor: 'myBlue.600',
|
||||
borderColor: 'blue.500',
|
||||
bg: '#F2FBFF',
|
||||
color: 'myBlue.700'
|
||||
color: 'blue.600'
|
||||
},
|
||||
green: {
|
||||
borderColor: '#67c13b',
|
||||
|
@@ -43,13 +43,13 @@ const MyRadio = ({
|
||||
position={'relative'}
|
||||
{...(value === item.value
|
||||
? {
|
||||
borderColor: 'myBlue.500',
|
||||
bg: 'myBlue.100'
|
||||
borderColor: 'blue.400',
|
||||
bg: 'blue.50'
|
||||
}
|
||||
: {
|
||||
bg: 'myWhite.300',
|
||||
_hover: {
|
||||
borderColor: 'myBlue.500'
|
||||
borderColor: 'blue.400'
|
||||
}
|
||||
})}
|
||||
_after={{
|
||||
@@ -66,7 +66,7 @@ const MyRadio = ({
|
||||
...(value === item.value
|
||||
? {
|
||||
border: '5px solid',
|
||||
borderColor: 'myBlue.700'
|
||||
borderColor: 'blue.600'
|
||||
}
|
||||
: {
|
||||
border: '2px solid',
|
||||
|
@@ -52,7 +52,7 @@ const TagTextarea = ({ defaultValues, onUpdate, ...props }: Props) => {
|
||||
bg={'myWhite.600'}
|
||||
{...(focus && {
|
||||
boxShadow: '0px 0px 4px #A8DBFF',
|
||||
borderColor: 'myBlue.600'
|
||||
borderColor: 'blue.500'
|
||||
})}
|
||||
{...props}
|
||||
onClick={() => {
|
||||
|
@@ -3,8 +3,7 @@ import MyModal from '@/components/MyModal';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import React, { Dispatch, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { Box, Flex } from '@chakra-ui/react';
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import ParentPaths from '@/components/common/ParentPaths';
|
||||
|
||||
type PathItemType = {
|
||||
@@ -53,13 +52,12 @@ const DatasetSelectContainer = ({
|
||||
}
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
h={'80vh'}
|
||||
w={'100%'}
|
||||
maxW={['90vw', '900px']}
|
||||
isCentered
|
||||
>
|
||||
<Flex flexDirection={'column'} h={'90vh'}>
|
||||
<Box flex={'1 0 0'}>{children}</Box>
|
||||
</Flex>
|
||||
{children}
|
||||
</MyModal>
|
||||
);
|
||||
};
|
||||
|
@@ -66,7 +66,7 @@ const AIChatSettingsModal = ({
|
||||
fontSize: ['sm', 'md']
|
||||
};
|
||||
const selectTemplateBtn: BoxProps = {
|
||||
color: 'myBlue.600',
|
||||
color: 'blue.500',
|
||||
cursor: 'pointer'
|
||||
};
|
||||
|
||||
|
@@ -82,7 +82,7 @@ export const DatasetSelectModal = ({
|
||||
p={3}
|
||||
border={theme.borders.base}
|
||||
boxShadow={'sm'}
|
||||
bg={'myBlue.300'}
|
||||
bg={'blue.200'}
|
||||
>
|
||||
<Flex alignItems={'center'} h={'38px'}>
|
||||
<Avatar src={item.avatar} w={['24px', '28px']}></Avatar>
|
||||
|
@@ -12,10 +12,7 @@ import type {
|
||||
FlowModuleItemType,
|
||||
FlowModuleTemplateType
|
||||
} from '@fastgpt/global/core/module/type.d';
|
||||
import type {
|
||||
FlowNodeOutputTargetItemType,
|
||||
FlowNodeChangeProps
|
||||
} from '@fastgpt/global/core/module/node/type';
|
||||
import type { FlowNodeChangeProps } from '@fastgpt/global/core/module/node/type';
|
||||
import React, {
|
||||
type SetStateAction,
|
||||
type Dispatch,
|
||||
|
@@ -60,7 +60,7 @@ const SelectAppModal = ({
|
||||
cursor={'pointer'}
|
||||
{...(selectedApps.includes(app._id)
|
||||
? {
|
||||
bg: 'myBlue.200',
|
||||
bg: 'blue.100',
|
||||
onClick: () => {
|
||||
setSelectedApps(selectedApps.filter((e) => e !== app._id));
|
||||
}
|
||||
|
@@ -36,7 +36,7 @@ const ButtonEdge = (
|
||||
targetPosition
|
||||
});
|
||||
|
||||
const edgeStyle = {
|
||||
const edgeStyle: React.CSSProperties = {
|
||||
...style,
|
||||
...(selected
|
||||
? {
|
||||
@@ -63,6 +63,7 @@ const ButtonEdge = (
|
||||
color={'black'}
|
||||
cursor={'pointer'}
|
||||
border={'1px solid #fff'}
|
||||
zIndex={selected ? 1000 : 0}
|
||||
_hover={{
|
||||
boxShadow: '0 0 6px 2px rgba(0, 0, 0, 0.08)'
|
||||
}}
|
||||
@@ -71,7 +72,7 @@ const ButtonEdge = (
|
||||
<MyIcon
|
||||
name="closeSolid"
|
||||
w={'100%'}
|
||||
color={selected ? 'myBlue.800' : 'myGray.500'}
|
||||
color={selected ? 'blue.700' : 'myGray.500'}
|
||||
></MyIcon>
|
||||
</Flex>
|
||||
</EdgeLabelRenderer>
|
||||
|
@@ -65,7 +65,7 @@ const NodePluginInput = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||
w={'14px'}
|
||||
cursor={'pointer'}
|
||||
mr={3}
|
||||
_hover={{ color: 'myBlue.600' }}
|
||||
_hover={{ color: 'blue.500' }}
|
||||
onClick={() =>
|
||||
setEditField({
|
||||
inputType: item.type,
|
||||
|
@@ -84,7 +84,7 @@ const NodePluginOutput = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||
w={'14px'}
|
||||
cursor={'pointer'}
|
||||
ml={3}
|
||||
_hover={{ color: 'myBlue.600' }}
|
||||
_hover={{ color: 'blue.500' }}
|
||||
onClick={() =>
|
||||
setEditField({
|
||||
inputType: item.type,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { EditNodeFieldType, FlowNodeInputItemType } from '@fastgpt/global/core/module/node/type';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import {
|
||||
onChangeNode,
|
||||
useFlowProviderStore,
|
||||
@@ -81,7 +81,7 @@ const InputLabel = ({
|
||||
w={'14px'}
|
||||
cursor={'pointer'}
|
||||
ml={3}
|
||||
_hover={{ color: 'myBlue.600' }}
|
||||
_hover={{ color: 'blue.500' }}
|
||||
onClick={() =>
|
||||
setEditField({
|
||||
inputType: type,
|
||||
|
@@ -41,7 +41,7 @@ const OutputLabel = ({
|
||||
w={'14px'}
|
||||
cursor={'pointer'}
|
||||
mr={3}
|
||||
_hover={{ color: 'myBlue.600' }}
|
||||
_hover={{ color: 'blue.500' }}
|
||||
onClick={() =>
|
||||
setEditField({
|
||||
key: outputKey,
|
||||
|
@@ -96,8 +96,10 @@ const Container = React.memo(function Container(props: Props) {
|
||||
minZoom={0.1}
|
||||
maxZoom={1.5}
|
||||
defaultEdgeOptions={{
|
||||
animated: true
|
||||
animated: true,
|
||||
zIndex: 0
|
||||
}}
|
||||
elevateEdgesOnSelect
|
||||
connectionLineStyle={{ strokeWidth: 2, stroke: '#5A646Es' }}
|
||||
nodeTypes={nodeTypes}
|
||||
edgeTypes={edgeTypes}
|
||||
|
@@ -88,7 +88,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
href={feConfigs.openAPIDocUrl || getDocPath('/docs/development/openapi')}
|
||||
target={'_blank'}
|
||||
ml={1}
|
||||
color={'myBlue.600'}
|
||||
color={'blue.500'}
|
||||
>
|
||||
查看文档
|
||||
</Link>
|
||||
|
@@ -156,7 +156,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
<MyIcon
|
||||
name={'common/addCircleLight'}
|
||||
w={['16px', '18px']}
|
||||
color={'myBlue.600'}
|
||||
color={'blue.500'}
|
||||
cursor={'pointer'}
|
||||
/>
|
||||
}
|
||||
@@ -177,7 +177,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
gap={3}
|
||||
{...(userInfo?.team?.teamId === team.teamId
|
||||
? {
|
||||
bg: 'myBlue.300'
|
||||
bg: 'blue.200'
|
||||
}
|
||||
: {
|
||||
_hover: {
|
||||
@@ -198,7 +198,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
{team.teamName}
|
||||
</Box>
|
||||
{userInfo?.team?.teamId === team.teamId ? (
|
||||
<MyIcon name={'common/tickFill'} w={'16px'} color={'myBlue.600'} />
|
||||
<MyIcon name={'common/tickFill'} w={'16px'} color={'blue.500'} />
|
||||
) : (
|
||||
<Button size={'xs'} variant={'base'} onClick={() => onSwitchTeam(team.teamId)}>
|
||||
{t('user.team.Check Team')}
|
||||
@@ -235,7 +235,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
ml={2}
|
||||
cursor={'pointer'}
|
||||
_hover={{
|
||||
color: 'myBlue.600'
|
||||
color: 'blue.500'
|
||||
}}
|
||||
onClick={() => {
|
||||
if (!userInfo?.team) return;
|
||||
@@ -260,7 +260,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
size="sm"
|
||||
borderRadius={'md'}
|
||||
ml={3}
|
||||
leftIcon={<MyIcon name={'common/inviteLight'} w={'14px'} color={'myBlue.600'} />}
|
||||
leftIcon={<MyIcon name={'common/inviteLight'} w={'14px'} color={'blue.500'} />}
|
||||
onClick={() => {
|
||||
if (userInfo.team.maxSize <= members.length) {
|
||||
toast({
|
||||
@@ -283,11 +283,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
borderRadius={'md'}
|
||||
ml={3}
|
||||
leftIcon={
|
||||
<MyIcon
|
||||
name={'support/account/loginoutLight'}
|
||||
w={'14px'}
|
||||
color={'myBlue.600'}
|
||||
/>
|
||||
<MyIcon name={'support/account/loginoutLight'} w={'14px'} color={'blue.500'} />
|
||||
}
|
||||
onClick={() => {
|
||||
openLeaveConfirm(() => onLeaveTeam(userInfo?.team?.teamId))();
|
||||
@@ -339,7 +335,7 @@ const TeamManageModal = ({ onClose }: { onClose: () => void }) => {
|
||||
name={'edit'}
|
||||
cursor={'pointer'}
|
||||
w="14px"
|
||||
_hover={{ color: 'myBlue.600' }}
|
||||
_hover={{ color: 'blue.500' }}
|
||||
/>
|
||||
</MenuButton>
|
||||
}
|
||||
|
10
projects/app/src/global/core/chat/api.d.ts
vendored
10
projects/app/src/global/core/chat/api.d.ts
vendored
@@ -12,6 +12,7 @@ export type GetChatSpeechProps = {
|
||||
export type InitChatProps = {
|
||||
appId?: string;
|
||||
chatId?: string;
|
||||
loadCustomFeedbacks?: boolean;
|
||||
};
|
||||
export type InitOutLinkChatProps = {
|
||||
chatId?: string;
|
||||
@@ -74,5 +75,14 @@ export type DeleteChatItemProps = {
|
||||
};
|
||||
|
||||
export type AdminUpdateFeedbackParams = AdminFbkType & {
|
||||
appId: string;
|
||||
chatId: string;
|
||||
chatItemId: string;
|
||||
};
|
||||
|
||||
export type CloseCustomFeedbackParams = {
|
||||
appId: string;
|
||||
chatId: string;
|
||||
chatItemId: string;
|
||||
index: number;
|
||||
};
|
||||
|
@@ -288,7 +288,7 @@ async function initPgData() {
|
||||
const limit = 10;
|
||||
// add column
|
||||
try {
|
||||
await Promise.all([
|
||||
await Promise.allSettled([
|
||||
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ADD COLUMN team_id VARCHAR(50);`),
|
||||
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ADD COLUMN tmb_id VARCHAR(50);`),
|
||||
PgClient.query(`ALTER TABLE ${PgDatasetTableName} ALTER COLUMN user_id DROP NOT NULL;`)
|
||||
|
@@ -2,79 +2,15 @@ import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
import multer from 'multer';
|
||||
import path from 'path';
|
||||
import { uploadFile } from '@fastgpt/service/common/file/gridfs/controller';
|
||||
import { BucketNameEnum } from '@fastgpt/global/common/file/constants';
|
||||
|
||||
const nanoid = customAlphabet('1234567890abcdef', 12);
|
||||
|
||||
type FileType = {
|
||||
fieldname: string;
|
||||
originalname: string;
|
||||
encoding: string;
|
||||
mimetype: string;
|
||||
filename: string;
|
||||
path: string;
|
||||
size: number;
|
||||
};
|
||||
import { getUploadModel } from '@fastgpt/service/common/file/upload/multer';
|
||||
|
||||
/**
|
||||
* Creates the multer uploader
|
||||
*/
|
||||
const maxSize = 500 * 1024 * 1024;
|
||||
class UploadModel {
|
||||
uploader = multer({
|
||||
limits: {
|
||||
fieldSize: maxSize
|
||||
},
|
||||
preservePath: true,
|
||||
storage: multer.diskStorage({
|
||||
filename: (_req, file, cb) => {
|
||||
const { ext } = path.parse(decodeURIComponent(file.originalname));
|
||||
cb(null, nanoid() + ext);
|
||||
}
|
||||
})
|
||||
}).any();
|
||||
|
||||
async doUpload(req: NextApiRequest, res: NextApiResponse) {
|
||||
return new Promise<{
|
||||
files: FileType[];
|
||||
bucketName: `${BucketNameEnum}`;
|
||||
metadata: Record<string, any>;
|
||||
}>((resolve, reject) => {
|
||||
// @ts-ignore
|
||||
this.uploader(req, res, (error) => {
|
||||
if (error) {
|
||||
return reject(error);
|
||||
}
|
||||
|
||||
resolve({
|
||||
...req.body,
|
||||
files:
|
||||
// @ts-ignore
|
||||
req.files?.map((file) => ({
|
||||
...file,
|
||||
originalname: decodeURIComponent(file.originalname)
|
||||
})) || [],
|
||||
metadata: (() => {
|
||||
if (!req.body?.metadata) return {};
|
||||
try {
|
||||
return JSON.parse(req.body.metadata);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
return {};
|
||||
}
|
||||
})()
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const upload = new UploadModel();
|
||||
const upload = getUploadModel({
|
||||
maxSize: 500 * 1024 * 1024
|
||||
});
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
@@ -82,6 +18,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
const { userId, teamId, tmbId } = await authCert({ req, authToken: true });
|
||||
const { files, bucketName, metadata } = await upload.doUpload(req, res);
|
||||
|
||||
if (!bucketName) {
|
||||
throw new Error('bucketName is empty');
|
||||
}
|
||||
|
||||
const upLoadResults = await Promise.all(
|
||||
files.map((file) =>
|
||||
uploadFile({
|
||||
|
@@ -4,7 +4,7 @@ import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { UrlFetchParams, UrlFetchResponse } from '@fastgpt/global/common/file/api.d';
|
||||
import { urlsFetch } from '@fastgpt/global/common/file/tools';
|
||||
import { urlsFetch } from '@fastgpt/service/common/string/cheerio';
|
||||
|
||||
const fetchContent = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
try {
|
||||
|
@@ -53,7 +53,7 @@ function simpleChatTemplate({
|
||||
key: 'userChatInput',
|
||||
type: 'systemInput',
|
||||
label: '用户问题',
|
||||
connected: true
|
||||
connected: false
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
@@ -95,7 +95,7 @@ function simpleChatTemplate({
|
||||
label: '对话模型',
|
||||
required: true,
|
||||
value: formData.aiSettings.model,
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'temperature',
|
||||
@@ -115,7 +115,7 @@ function simpleChatTemplate({
|
||||
value: 10
|
||||
}
|
||||
],
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'maxToken',
|
||||
@@ -135,7 +135,7 @@ function simpleChatTemplate({
|
||||
value: 4000
|
||||
}
|
||||
],
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'isResponseAnswerText',
|
||||
@@ -143,21 +143,21 @@ function simpleChatTemplate({
|
||||
label: '返回AI内容',
|
||||
valueType: 'boolean',
|
||||
value: true,
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quoteTemplate',
|
||||
type: 'hidden',
|
||||
label: '引用内容模板',
|
||||
valueType: 'string',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quotePrompt',
|
||||
type: 'hidden',
|
||||
label: '引用内容提示词',
|
||||
valueType: 'string',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'aiSettings',
|
||||
@@ -176,7 +176,7 @@ function simpleChatTemplate({
|
||||
placeholder:
|
||||
'模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}',
|
||||
value: formData.aiSettings.systemPrompt,
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quoteQA',
|
||||
@@ -191,7 +191,7 @@ function simpleChatTemplate({
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.chat history',
|
||||
valueType: 'chatHistory',
|
||||
connected: true,
|
||||
connected: false,
|
||||
value: 8
|
||||
},
|
||||
{
|
||||
@@ -292,21 +292,21 @@ function datasetTemplate({
|
||||
value: formData.dataset.datasets,
|
||||
type: FlowNodeInputTypeEnum.custom,
|
||||
label: '关联的知识库',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'similarity',
|
||||
value: 0.1,
|
||||
type: FlowNodeInputTypeEnum.slider,
|
||||
label: '相关度',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'limit',
|
||||
value: 2000,
|
||||
type: FlowNodeInputTypeEnum.slider,
|
||||
label: '单次搜索上限',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'switch',
|
||||
@@ -403,7 +403,7 @@ function datasetTemplate({
|
||||
label: '对话模型',
|
||||
required: true,
|
||||
value: formData.aiSettings.model,
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'temperature',
|
||||
@@ -423,7 +423,7 @@ function datasetTemplate({
|
||||
value: 10
|
||||
}
|
||||
],
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'maxToken',
|
||||
@@ -443,7 +443,7 @@ function datasetTemplate({
|
||||
value: 4000
|
||||
}
|
||||
],
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'isResponseAnswerText',
|
||||
@@ -451,21 +451,21 @@ function datasetTemplate({
|
||||
label: '返回AI内容',
|
||||
valueType: 'boolean',
|
||||
value: true,
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quoteTemplate',
|
||||
type: 'hidden',
|
||||
label: '引用内容模板',
|
||||
valueType: 'string',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quotePrompt',
|
||||
type: 'hidden',
|
||||
label: '引用内容提示词',
|
||||
valueType: 'string',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'aiSettings',
|
||||
@@ -484,7 +484,7 @@ function datasetTemplate({
|
||||
placeholder:
|
||||
'模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。可使用变量,例如 {{language}}',
|
||||
value: formData.aiSettings.systemPrompt,
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quoteQA',
|
||||
@@ -499,7 +499,7 @@ function datasetTemplate({
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.chat history',
|
||||
valueType: 'chatHistory',
|
||||
connected: true,
|
||||
connected: false,
|
||||
value: 8
|
||||
},
|
||||
{
|
||||
|
@@ -39,49 +39,49 @@ function chatModelInput(formData: AppSimpleEditFormType): FlowNodeInputItemType[
|
||||
value: formData.aiSettings.model,
|
||||
type: 'custom',
|
||||
label: '对话模型',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'temperature',
|
||||
value: formData.aiSettings.temperature,
|
||||
type: 'slider',
|
||||
label: '温度',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'maxToken',
|
||||
value: formData.aiSettings.maxToken,
|
||||
type: 'custom',
|
||||
label: '回复上限',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'systemPrompt',
|
||||
value: formData.aiSettings.systemPrompt || '',
|
||||
type: 'textarea',
|
||||
label: '系统提示词',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: ModuleInputKeyEnum.aiChatIsResponseText,
|
||||
value: true,
|
||||
type: 'hidden',
|
||||
label: '返回AI内容',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quoteTemplate',
|
||||
value: formData.aiSettings.quoteTemplate || '',
|
||||
type: 'hidden',
|
||||
label: '引用内容模板',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'quotePrompt',
|
||||
value: formData.aiSettings.quotePrompt || '',
|
||||
type: 'hidden',
|
||||
label: '引用内容提示词',
|
||||
connected: true
|
||||
connected: false
|
||||
},
|
||||
{
|
||||
key: 'switch',
|
||||
@@ -93,7 +93,7 @@ function chatModelInput(formData: AppSimpleEditFormType): FlowNodeInputItemType[
|
||||
key: 'history',
|
||||
type: 'target',
|
||||
label: 'core.module.input.label.chat history',
|
||||
connected: true,
|
||||
connected: false,
|
||||
value: 6
|
||||
},
|
||||
{
|
||||
@@ -118,9 +118,9 @@ function simpleChatTemplate(formData: AppSimpleEditFormType): ModuleItemType[] {
|
||||
inputs: [
|
||||
{
|
||||
key: 'userChatInput',
|
||||
connected: true,
|
||||
connected: false,
|
||||
label: '用户问题',
|
||||
type: 'target'
|
||||
type: 'systemInput'
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
@@ -179,8 +179,8 @@ function datasetTemplate(formData: AppSimpleEditFormType): ModuleItemType[] {
|
||||
{
|
||||
key: 'userChatInput',
|
||||
label: '用户问题',
|
||||
type: 'target',
|
||||
connected: true
|
||||
type: 'systemInput',
|
||||
connected: false
|
||||
}
|
||||
],
|
||||
outputs: [
|
||||
@@ -319,7 +319,7 @@ function datasetTemplate(formData: AppSimpleEditFormType): ModuleItemType[] {
|
||||
type: FlowNodeInputTypeEnum.textarea,
|
||||
valueType: ModuleIOValueTypeEnum.string,
|
||||
label: '回复的内容',
|
||||
connected: true
|
||||
connected: false
|
||||
}
|
||||
],
|
||||
outputs: [],
|
||||
|
@@ -78,12 +78,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
}
|
||||
}
|
||||
},
|
||||
robotBadFeedbackCount: {
|
||||
customFeedbacksCount: {
|
||||
$size: {
|
||||
$filter: {
|
||||
input: '$chatitems',
|
||||
as: 'item',
|
||||
cond: { $ifNull: ['$$item.robotBadFeedback', false] }
|
||||
cond: { $gt: [{ $size: { $ifNull: ['$$item.customFeedbacks', []] } }, 0] }
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -102,7 +102,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
$sort: {
|
||||
userBadFeedbackCount: -1,
|
||||
userGoodFeedbackCount: -1,
|
||||
robotBadFeedbackCount: -1,
|
||||
customFeedbacksCount: -1,
|
||||
updateTime: -1
|
||||
}
|
||||
},
|
||||
@@ -118,7 +118,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
messageCount: { $size: '$chatitems' },
|
||||
userGoodFeedbackCount: 1,
|
||||
userBadFeedbackCount: 1,
|
||||
robotBadFeedbackCount: 1,
|
||||
customFeedbacksCount: 1,
|
||||
markCount: 1
|
||||
}
|
||||
}
|
||||
|
@@ -4,22 +4,29 @@ import { connectToDatabase } from '@/service/mongo';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import type { AdminUpdateFeedbackParams } from '@/global/core/chat/api.d';
|
||||
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
|
||||
import { autChatCrud } from '@/service/support/permission/auth/chat';
|
||||
|
||||
/* 初始化我的聊天框,需要身份验证 */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await connectToDatabase();
|
||||
const { chatItemId, datasetId, dataId, q, a } = req.body as AdminUpdateFeedbackParams;
|
||||
const { appId, chatId, chatItemId, datasetId, dataId, q, a } =
|
||||
req.body as AdminUpdateFeedbackParams;
|
||||
|
||||
if (!chatItemId || !datasetId || !dataId || !q) {
|
||||
throw new Error('missing parameter');
|
||||
}
|
||||
|
||||
const { userId } = await authCert({ req, authToken: true });
|
||||
await autChatCrud({
|
||||
req,
|
||||
authToken: true,
|
||||
appId,
|
||||
chatId,
|
||||
per: 'r'
|
||||
});
|
||||
|
||||
await MongoChatItem.findOneAndUpdate(
|
||||
{
|
||||
userId,
|
||||
dataId: chatItemId
|
||||
},
|
||||
{
|
||||
|
47
projects/app/src/pages/api/core/chat/feedback/closeCustom.ts
Normal file
47
projects/app/src/pages/api/core/chat/feedback/closeCustom.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import type {
|
||||
AdminUpdateFeedbackParams,
|
||||
CloseCustomFeedbackParams
|
||||
} from '@/global/core/chat/api.d';
|
||||
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
|
||||
import { autChatCrud } from '@/service/support/permission/auth/chat';
|
||||
|
||||
/* 初始化我的聊天框,需要身份验证 */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await connectToDatabase();
|
||||
const { appId, chatId, chatItemId, index } = req.body as CloseCustomFeedbackParams;
|
||||
|
||||
if (!chatItemId || !appId || !chatId || !chatItemId) {
|
||||
throw new Error('missing parameter');
|
||||
}
|
||||
|
||||
await autChatCrud({
|
||||
req,
|
||||
authToken: true,
|
||||
appId,
|
||||
chatId,
|
||||
per: 'r'
|
||||
});
|
||||
await authCert({ req, authToken: true });
|
||||
|
||||
await MongoChatItem.findOneAndUpdate(
|
||||
{ dataId: chatItemId },
|
||||
{ $unset: { [`customFeedbacks.${index}`]: 1 } }
|
||||
);
|
||||
await MongoChatItem.findOneAndUpdate(
|
||||
{ dataId: chatItemId },
|
||||
{ $pull: { customFeedbacks: null } }
|
||||
);
|
||||
|
||||
jsonRes(res);
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error: err
|
||||
});
|
||||
}
|
||||
}
|
@@ -14,7 +14,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
try {
|
||||
await connectToDatabase();
|
||||
|
||||
let { appId, chatId } = req.query as InitChatProps;
|
||||
let { appId, chatId, loadCustomFeedbacks } = req.query as InitChatProps;
|
||||
|
||||
if (!appId) {
|
||||
return jsonRes(res, {
|
||||
@@ -43,7 +43,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
const { history } = await getChatItems({
|
||||
chatId,
|
||||
limit: 30,
|
||||
field: `dataId obj value adminFeedback userBadFeedback userGoodFeedback robotBadFeedback ${ModuleOutputKeyEnum.responseData}`
|
||||
field: `dataId obj value adminFeedback userBadFeedback userGoodFeedback ${
|
||||
ModuleOutputKeyEnum.responseData
|
||||
} ${loadCustomFeedbacks ? 'customFeedbacks' : ''}`
|
||||
});
|
||||
|
||||
jsonRes<InitChatResponse>(res, {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import type { HttpBodyType } from '@fastgpt/global/core/module/api.d';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common';
|
||||
|
||||
type Props = HttpBodyType<{
|
||||
input: string;
|
||||
@@ -13,6 +14,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
data: { input, rule = '' }
|
||||
} = req.body as Props;
|
||||
|
||||
await authRequestFromLocal({ req });
|
||||
|
||||
const result = (() => {
|
||||
if (typeof input === 'string') {
|
||||
const defaultReg: any[] = [
|
||||
|
52
projects/app/src/pages/api/plugins/customFeedback/index.ts
Normal file
52
projects/app/src/pages/api/plugins/customFeedback/index.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import type { HttpBodyType } from '@fastgpt/global/core/module/api.d';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { addCustomFeedbacks } from '@fastgpt/service/core/chat/controller';
|
||||
import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common';
|
||||
|
||||
type Props = HttpBodyType<{
|
||||
defaultFeedback: string;
|
||||
customFeedback: string;
|
||||
}>;
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
const {
|
||||
chatId,
|
||||
responseChatItemId: chatItemId,
|
||||
data: { defaultFeedback, customFeedback }
|
||||
} = req.body as Props;
|
||||
|
||||
await authRequestFromLocal({ req });
|
||||
|
||||
const feedback = customFeedback || defaultFeedback;
|
||||
|
||||
if (!feedback) {
|
||||
return res.json({
|
||||
response: ''
|
||||
});
|
||||
}
|
||||
|
||||
// wait the chat finish
|
||||
setTimeout(() => {
|
||||
addCustomFeedbacks({
|
||||
chatId,
|
||||
chatItemId,
|
||||
feedbacks: [feedback]
|
||||
});
|
||||
}, 60000);
|
||||
|
||||
if (!chatId || !chatItemId) {
|
||||
return res.json({
|
||||
response: `\\n\\n**自动反馈调试**: ${feedback}\\n\\n`
|
||||
});
|
||||
}
|
||||
|
||||
return res.json({
|
||||
response: ''
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
res.status(500).send(getErrText(err));
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import type { HttpBodyType } from '@fastgpt/global/core/module/api.d';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { replaceVariable } from '@fastgpt/global/common/string/tools';
|
||||
import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common';
|
||||
|
||||
type Props = HttpBodyType<{
|
||||
text: string;
|
||||
@@ -14,6 +15,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
data: { text, ...obj }
|
||||
} = req.body as Props;
|
||||
|
||||
await authRequestFromLocal({ req });
|
||||
|
||||
const textResult = replaceVariable(text, obj);
|
||||
|
||||
res.json({
|
||||
|
@@ -195,12 +195,14 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
// get and concat history
|
||||
const { history } = await getChatItems({ chatId, limit: 30, field: `dataId obj value` });
|
||||
const concatHistories = history.concat(chatMessages);
|
||||
const responseChatItemId: string | undefined = messages[messages.length - 1].dataId;
|
||||
|
||||
/* start flow controller */
|
||||
const { responseData, answerText } = await dispatchModules({
|
||||
res,
|
||||
appId: String(app._id),
|
||||
chatId,
|
||||
responseChatItemId,
|
||||
modules: app.modules,
|
||||
user,
|
||||
teamId: user.team.teamId,
|
||||
@@ -237,7 +239,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
||||
content: [
|
||||
question,
|
||||
{
|
||||
dataId: messages[messages.length - 1].dataId,
|
||||
dataId: responseChatItemId,
|
||||
obj: ChatRoleEnum.AI,
|
||||
value: answerText,
|
||||
responseData
|
||||
|
@@ -29,6 +29,7 @@ import Tag from '@/components/Tag';
|
||||
import MyModal from '@/components/MyModal';
|
||||
import DateRangePicker, { type DateRangeType } from '@/components/DateRangePicker';
|
||||
import { addDays } from 'date-fns';
|
||||
import MyBox from '@/components/common/MyBox';
|
||||
|
||||
const Logs = ({ appId }: { appId: string }) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -96,6 +97,7 @@ const Logs = ({ appId }: { appId: string }) => {
|
||||
<Th>{t('app.Logs Title')}</Th>
|
||||
<Th>{t('app.Logs Message Total')}</Th>
|
||||
<Th>{t('app.Feedback Count')}</Th>
|
||||
<Th>{t('core.app.feedback.Custom feedback')}</Th>
|
||||
<Th>{t('app.Mark Count')}</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
@@ -158,7 +160,9 @@ const Logs = ({ appId }: { appId: string }) => {
|
||||
{item.userBadFeedbackCount}
|
||||
</Flex>
|
||||
)}
|
||||
{!item?.userGoodFeedbackCount && !item?.userBadFeedbackCount && <>-</>}
|
||||
</Td>
|
||||
<Td>{item.customFeedbacksCount || '-'}</Td>
|
||||
<Td>{item.markCount}</Td>
|
||||
</Tr>
|
||||
))}
|
||||
@@ -208,7 +212,7 @@ const Logs = ({ appId }: { appId: string }) => {
|
||||
|
||||
export default React.memo(Logs);
|
||||
|
||||
function DetailLogsModal({
|
||||
const DetailLogsModal = ({
|
||||
appId,
|
||||
chatId,
|
||||
onClose
|
||||
@@ -216,14 +220,14 @@ function DetailLogsModal({
|
||||
appId: string;
|
||||
chatId: string;
|
||||
onClose: () => void;
|
||||
}) {
|
||||
}) => {
|
||||
const ChatBoxRef = useRef<ComponentRef>(null);
|
||||
const { isPc } = useSystemStore();
|
||||
const theme = useTheme();
|
||||
|
||||
const { data: chat } = useQuery(
|
||||
const { data: chat, isFetching } = useQuery(
|
||||
['getChatDetail', chatId],
|
||||
() => getInitChatInfo({ appId, chatId }),
|
||||
() => getInitChatInfo({ appId, chatId, loadCustomFeedbacks: true }),
|
||||
{
|
||||
onSuccess(res) {
|
||||
const history = res.history.map((item) => ({
|
||||
@@ -249,9 +253,11 @@ function DetailLogsModal({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex
|
||||
zIndex={3}
|
||||
<MyBox
|
||||
isLoading={isFetching}
|
||||
display={'flex'}
|
||||
flexDirection={'column'}
|
||||
zIndex={3}
|
||||
position={['fixed', 'absolute']}
|
||||
top={[0, '2%']}
|
||||
right={0}
|
||||
@@ -325,8 +331,8 @@ function DetailLogsModal({
|
||||
chatId={chatId}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
</MyBox>
|
||||
<Box zIndex={2} position={'fixed'} top={0} left={0} bottom={0} right={0} onClick={onClose} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@@ -189,7 +189,7 @@ const SelectUsingWayModal = ({ share, onClose }: { share: OutLinkSchema; onClose
|
||||
w={'16px'}
|
||||
color={'myGray.600'}
|
||||
cursor={'pointer'}
|
||||
_hover={{ color: 'myBlue.600' }}
|
||||
_hover={{ color: 'blue.500' }}
|
||||
onClick={() => {
|
||||
copyData(wayMap[getValues('usingWay')].code);
|
||||
}}
|
||||
|
@@ -77,7 +77,7 @@ const Share = ({ appId }: { appId: string }) => {
|
||||
</Box>
|
||||
<Button
|
||||
variant={'base'}
|
||||
colorScheme={'myBlue'}
|
||||
colorScheme={'blue'}
|
||||
size={['sm', 'md']}
|
||||
{...(shareChatList.length >= 10
|
||||
? {
|
||||
|
@@ -548,7 +548,7 @@ function Settings({ appId }: { appId: string }) {
|
||||
mt={2}
|
||||
px={5}
|
||||
py={4}
|
||||
bg={'myBlue.100'}
|
||||
bg={'blue.50'}
|
||||
position={'relative'}
|
||||
>
|
||||
<Flex alignItems={'center'} py={2}>
|
||||
|
@@ -139,7 +139,7 @@ const AppDetail = ({ currentTab }: { currentTab: `${TabEnum}` }) => {
|
||||
>
|
||||
<IconButton
|
||||
mr={3}
|
||||
icon={<MyIcon name={'backFill'} w={'18px'} color={'myBlue.600'} />}
|
||||
icon={<MyIcon name={'backFill'} w={'18px'} color={'blue.500'} />}
|
||||
bg={'white'}
|
||||
boxShadow={'1px 1px 9px rgba(0,0,0,0.15)'}
|
||||
h={'28px'}
|
||||
|
@@ -61,7 +61,7 @@ const ShareModelList = ({
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
cursor={'pointer'}
|
||||
color={model.isCollection ? 'myBlue.700' : 'blackAlpha.700'}
|
||||
color={model.isCollection ? 'blue.600' : 'blackAlpha.700'}
|
||||
onClick={() => onclickCollection(model._id)}
|
||||
>
|
||||
<MyIcon
|
||||
|
@@ -154,7 +154,7 @@ const ChatHistorySlider = ({
|
||||
variant={'base'}
|
||||
flex={1}
|
||||
h={'100%'}
|
||||
color={'myBlue.700'}
|
||||
color={'blue.600'}
|
||||
borderRadius={'xl'}
|
||||
leftIcon={<MyIcon name={'chat'} w={'16px'} />}
|
||||
overflow={'hidden'}
|
||||
@@ -201,8 +201,8 @@ const ChatHistorySlider = ({
|
||||
bg={item.top ? '#E6F6F6 !important' : ''}
|
||||
{...(item.id === activeChatId
|
||||
? {
|
||||
backgroundColor: 'myBlue.100 !important',
|
||||
color: 'myBlue.700'
|
||||
backgroundColor: 'blue.50 !important',
|
||||
color: 'blue.600'
|
||||
}
|
||||
: {
|
||||
onClick: () => {
|
||||
@@ -290,8 +290,8 @@ const ChatHistorySlider = ({
|
||||
alignItems={'center'}
|
||||
{...(item._id === appId
|
||||
? {
|
||||
backgroundColor: 'myBlue.100 !important',
|
||||
color: 'myBlue.700'
|
||||
backgroundColor: 'blue.50 !important',
|
||||
color: 'blue.600'
|
||||
}
|
||||
: {
|
||||
onClick: () => {
|
||||
@@ -325,7 +325,7 @@ const ChatHistorySlider = ({
|
||||
>
|
||||
<IconButton
|
||||
mr={3}
|
||||
icon={<MyIcon name={'backFill'} w={'18px'} color={'myBlue.600'} />}
|
||||
icon={<MyIcon name={'backFill'} w={'18px'} color={'blue.500'} />}
|
||||
bg={'white'}
|
||||
boxShadow={'1px 1px 9px rgba(0,0,0,0.15)'}
|
||||
h={'28px'}
|
||||
|
@@ -28,7 +28,7 @@ const SliderApps = ({ appId }: { appId: string }) => {
|
||||
>
|
||||
<IconButton
|
||||
mr={3}
|
||||
icon={<MyIcon name={'backFill'} w={'18px'} color={'myBlue.600'} />}
|
||||
icon={<MyIcon name={'backFill'} w={'18px'} color={'blue.500'} />}
|
||||
bg={'white'}
|
||||
boxShadow={'1px 1px 9px rgba(0,0,0,0.15)'}
|
||||
h={'28px'}
|
||||
|
@@ -311,7 +311,7 @@ const CollectionCard = () => {
|
||||
target="_blank"
|
||||
mr={2}
|
||||
textDecoration={'underline'}
|
||||
color={'myBlue.700'}
|
||||
color={'blue.600'}
|
||||
>
|
||||
{datasetDetail.websiteConfig.url}
|
||||
</Link>
|
||||
@@ -371,7 +371,7 @@ const CollectionCard = () => {
|
||||
Button={
|
||||
<MenuButton
|
||||
_hover={{
|
||||
color: 'myBlue.600'
|
||||
color: 'blue.500'
|
||||
}}
|
||||
fontSize={['sm', 'md']}
|
||||
>
|
||||
@@ -381,7 +381,7 @@ const CollectionCard = () => {
|
||||
py={2}
|
||||
borderRadius={'md'}
|
||||
cursor={'pointer'}
|
||||
bg={'myBlue.600'}
|
||||
bg={'blue.500'}
|
||||
overflow={'hidden'}
|
||||
color={'white'}
|
||||
h={['28px', '35px']}
|
||||
@@ -489,7 +489,7 @@ const CollectionCard = () => {
|
||||
data-drag-id={
|
||||
collection.type === DatasetCollectionTypeEnum.folder ? collection._id : undefined
|
||||
}
|
||||
bg={dragTargetId === collection._id ? 'myBlue.200' : ''}
|
||||
bg={dragTargetId === collection._id ? 'blue.100' : ''}
|
||||
userSelect={'none'}
|
||||
onDragStart={(e) => {
|
||||
setDragStartId(collection._id);
|
||||
@@ -579,7 +579,7 @@ const CollectionCard = () => {
|
||||
h={'22px'}
|
||||
borderRadius={'md'}
|
||||
_hover={{
|
||||
color: 'myBlue.600',
|
||||
color: 'blue.500',
|
||||
'& .icon': {
|
||||
bg: 'myGray.100'
|
||||
}
|
||||
|
@@ -163,7 +163,7 @@ const DataCard = () => {
|
||||
<Flex alignItems={'center'}>
|
||||
<IconButton
|
||||
mr={3}
|
||||
icon={<MyIcon name={'backFill'} w={['14px', '18px']} color={'myBlue.600'} />}
|
||||
icon={<MyIcon name={'backFill'} w={['14px', '18px']} color={'blue.500'} />}
|
||||
bg={'white'}
|
||||
boxShadow={'1px 1px 9px rgba(0,0,0,0.15)'}
|
||||
size={'sm'}
|
||||
|
@@ -182,7 +182,7 @@ const FileSelect = ({
|
||||
|
||||
if (text) {
|
||||
text = simpleText(text);
|
||||
const splitRes = splitText2Chunks({
|
||||
const { chunks, tokens } = splitText2Chunks({
|
||||
text,
|
||||
chunkLen,
|
||||
overlapRatio
|
||||
@@ -193,10 +193,10 @@ const FileSelect = ({
|
||||
filename: file.name,
|
||||
icon,
|
||||
rawText: text,
|
||||
tokens: splitRes.tokens,
|
||||
tokens,
|
||||
type: DatasetCollectionTypeEnum.file,
|
||||
fileId,
|
||||
chunks: splitRes.chunks.map((chunk) => ({
|
||||
chunks: chunks.map((chunk) => ({
|
||||
q: chunk,
|
||||
a: ''
|
||||
}))
|
||||
@@ -219,7 +219,7 @@ const FileSelect = ({
|
||||
const onUrlFetch = useCallback(
|
||||
(e: UrlFetchResponse) => {
|
||||
const result: FileItemType[] = e.map<FileItemType>(({ url, content }) => {
|
||||
const splitRes = splitText2Chunks({
|
||||
const { chunks, tokens } = splitText2Chunks({
|
||||
text: content,
|
||||
chunkLen,
|
||||
overlapRatio
|
||||
@@ -229,10 +229,10 @@ const FileSelect = ({
|
||||
filename: url,
|
||||
icon: '/imgs/files/link.svg',
|
||||
rawText: content,
|
||||
tokens: splitRes.tokens,
|
||||
tokens,
|
||||
type: DatasetCollectionTypeEnum.link,
|
||||
rawLink: url,
|
||||
chunks: splitRes.chunks.map((chunk) => ({
|
||||
chunks: chunks.map((chunk) => ({
|
||||
q: chunk,
|
||||
a: ''
|
||||
}))
|
||||
@@ -259,7 +259,7 @@ const FileSelect = ({
|
||||
metadata: { datasetId: datasetDetail._id }
|
||||
});
|
||||
|
||||
const splitRes = splitText2Chunks({
|
||||
const { chunks, tokens } = splitText2Chunks({
|
||||
text: content,
|
||||
chunkLen,
|
||||
overlapRatio
|
||||
@@ -271,10 +271,10 @@ const FileSelect = ({
|
||||
filename,
|
||||
icon: '/imgs/files/txt.svg',
|
||||
rawText: content,
|
||||
tokens: splitRes.tokens,
|
||||
tokens,
|
||||
type: DatasetCollectionTypeEnum.file,
|
||||
fileId: fileIds[0],
|
||||
chunks: splitRes.chunks.map((chunk) => ({
|
||||
chunks: chunks.map((chunk) => ({
|
||||
q: chunk,
|
||||
a: ''
|
||||
}))
|
||||
@@ -352,7 +352,7 @@ const FileSelect = ({
|
||||
ml: 1,
|
||||
as: 'span',
|
||||
cursor: 'pointer',
|
||||
color: 'myBlue.700',
|
||||
color: 'blue.600',
|
||||
_hover: {
|
||||
textDecoration: 'underline'
|
||||
}
|
||||
@@ -417,7 +417,7 @@ const FileSelect = ({
|
||||
mt={1}
|
||||
cursor={'pointer'}
|
||||
textDecoration={'underline'}
|
||||
color={'myBlue.600'}
|
||||
color={'blue.500'}
|
||||
fontSize={'12px'}
|
||||
onClick={() =>
|
||||
fileDownload({
|
||||
|
@@ -195,7 +195,7 @@ const Provider = ({
|
||||
|
||||
setFiles((state) =>
|
||||
state.map((file) => {
|
||||
const splitRes = splitText2Chunks({
|
||||
const { chunks, tokens } = splitText2Chunks({
|
||||
text: file.rawText,
|
||||
chunkLen,
|
||||
overlapRatio: chunkOverlapRatio
|
||||
@@ -203,8 +203,8 @@ const Provider = ({
|
||||
|
||||
return {
|
||||
...file,
|
||||
tokens: splitRes.tokens,
|
||||
chunks: splitRes.chunks.map((chunk) => ({
|
||||
tokens,
|
||||
chunks: chunks.map((chunk) => ({
|
||||
q: chunk,
|
||||
a: ''
|
||||
}))
|
||||
@@ -475,7 +475,7 @@ export const SelectorContainer = ({
|
||||
position={'relative'}
|
||||
alignItems={'center'}
|
||||
_hover={{
|
||||
bg: 'myBlue.100',
|
||||
bg: 'blue.50',
|
||||
'& .delete': {
|
||||
display: 'block'
|
||||
}
|
||||
|
@@ -313,7 +313,7 @@ const InputDataModal = ({
|
||||
borderColor={'transparent'}
|
||||
px={0}
|
||||
_focus={{
|
||||
borderColor: 'myBlue.400',
|
||||
borderColor: 'blue.400',
|
||||
px: 3
|
||||
}}
|
||||
placeholder={t('dataset.data.Index Placeholder')}
|
||||
@@ -332,7 +332,7 @@ const InputDataModal = ({
|
||||
border={theme.borders.base}
|
||||
cursor={'pointer'}
|
||||
_hover={{
|
||||
bg: 'myBlue.100'
|
||||
bg: 'blue.50'
|
||||
}}
|
||||
minH={'100px'}
|
||||
onClick={() =>
|
||||
|
@@ -102,10 +102,10 @@ const Test = ({ datasetId }: { datasetId: string }) => {
|
||||
py={4}
|
||||
borderRight={['none', theme.borders.base]}
|
||||
>
|
||||
<Box border={'2px solid'} borderColor={'myBlue.600'} p={3} mx={4} borderRadius={'md'}>
|
||||
<Box border={'2px solid'} borderColor={'blue.500'} p={3} mx={4} borderRadius={'md'}>
|
||||
<Flex alignItems={'center'}>
|
||||
<Box fontSize={'sm'} fontWeight={'bold'} flex={1}>
|
||||
<MyIcon mr={2} name={'text'} w={'18px'} h={'18px'} color={'myBlue.700'} />
|
||||
<MyIcon mr={2} name={'text'} w={'18px'} h={'18px'} color={'blue.600'} />
|
||||
{t('core.dataset.test.Test Text')}
|
||||
</Box>
|
||||
<Button
|
||||
|
@@ -181,7 +181,7 @@ const Detail = ({ datasetId, currentTab }: { datasetId: string; currentTab: `${T
|
||||
>
|
||||
<IconButton
|
||||
mr={3}
|
||||
icon={<MyIcon name={'backFill'} w={'18px'} color={'myBlue.600'} />}
|
||||
icon={<MyIcon name={'backFill'} w={'18px'} color={'blue.500'} />}
|
||||
bg={'white'}
|
||||
boxShadow={'1px 1px 9px rgba(0,0,0,0.15)'}
|
||||
h={'28px'}
|
||||
|
@@ -79,7 +79,7 @@ const MoveModal = ({
|
||||
: {
|
||||
cursor: 'pointer',
|
||||
_hover: {
|
||||
color: 'myBlue.600'
|
||||
color: 'blue.500'
|
||||
},
|
||||
onClick: () => {
|
||||
setParentId(item.parentId);
|
||||
|
@@ -163,7 +163,7 @@ const Kb = () => {
|
||||
Button={
|
||||
<MenuButton
|
||||
_hover={{
|
||||
color: 'myBlue.600'
|
||||
color: 'blue.500'
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
@@ -221,7 +221,7 @@ const Kb = () => {
|
||||
boxShadow={'none'}
|
||||
position={'relative'}
|
||||
data-drag-id={dataset.type === DatasetTypeEnum.folder ? dataset._id : undefined}
|
||||
borderColor={dragTargetId === dataset._id ? 'myBlue.600' : ''}
|
||||
borderColor={dragTargetId === dataset._id ? 'blue.500' : ''}
|
||||
draggable
|
||||
onDragStart={(e) => {
|
||||
setDragStartId(dataset._id);
|
||||
@@ -287,7 +287,7 @@ const Kb = () => {
|
||||
h={'22px'}
|
||||
borderRadius={'md'}
|
||||
_hover={{
|
||||
color: 'myBlue.600',
|
||||
color: 'blue.500',
|
||||
'& .icon': {
|
||||
bg: 'myGray.100'
|
||||
}
|
||||
|
@@ -158,7 +158,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
float={'right'}
|
||||
fontSize="sm"
|
||||
mt={2}
|
||||
color={'myBlue.600'}
|
||||
color={'blue.500'}
|
||||
cursor={'pointer'}
|
||||
_hover={{ textDecoration: 'underline' }}
|
||||
onClick={() => setPageType('login')}
|
||||
|
@@ -125,7 +125,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
</FormControl>
|
||||
{feConfigs?.show_register && (
|
||||
<>
|
||||
<Flex align={'center'} justifyContent={'space-between'} mt={3} color={'myBlue.600'}>
|
||||
<Flex align={'center'} justifyContent={'space-between'} mt={3} color={'blue.500'}>
|
||||
<Box
|
||||
cursor={'pointer'}
|
||||
_hover={{ textDecoration: 'underline' }}
|
||||
@@ -149,7 +149,7 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
<Link
|
||||
href={getDocPath('/docs/agreement/disclaimer/')}
|
||||
target={'_blank'}
|
||||
color={'myBlue.600'}
|
||||
color={'blue.500'}
|
||||
>
|
||||
免责声明
|
||||
</Link>
|
||||
|
@@ -172,7 +172,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
|
||||
float={'right'}
|
||||
fontSize="sm"
|
||||
mt={2}
|
||||
color={'myBlue.600'}
|
||||
color={'blue.500'}
|
||||
cursor={'pointer'}
|
||||
_hover={{ textDecoration: 'underline' }}
|
||||
onClick={() => setPageType('login')}
|
||||
|
@@ -116,7 +116,7 @@ const Login = () => {
|
||||
{feConfigs?.concatMd && (
|
||||
<Box
|
||||
fontWeight={'bold'}
|
||||
color={'myBlue.700'}
|
||||
color={'blue.600'}
|
||||
cursor={'pointer'}
|
||||
position={'absolute'}
|
||||
right={5}
|
||||
|
@@ -88,7 +88,7 @@ const MyModules = () => {
|
||||
aria-label={'delete'}
|
||||
display={['', 'none']}
|
||||
_hover={{
|
||||
bg: 'myBlue.200'
|
||||
bg: 'blue.100'
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
|
@@ -78,12 +78,12 @@ export function request(url: string, data: any, config: ConfigType, method: Meth
|
||||
|
||||
return instance
|
||||
.request({
|
||||
baseURL: `http://localhost:${process.env.PORT || 3000}`,
|
||||
baseURL: `http://${process.env.HOSTNAME || 'localhost'}:${process.env.PORT || 3000}`,
|
||||
url,
|
||||
method,
|
||||
data: ['POST', 'PUT'].includes(method) ? data : null,
|
||||
params: !['POST', 'PUT'].includes(method) ? data : null,
|
||||
...config // 用户自定义配置,可以覆盖前面的配置
|
||||
...config // custom config
|
||||
})
|
||||
.then((res) => checkRes(res.data))
|
||||
.catch((err) => responseError(err));
|
||||
|
@@ -243,8 +243,8 @@ function formatSplitText(text: string, rawText: string) {
|
||||
|
||||
// empty result. direct split chunk
|
||||
if (result.length === 0) {
|
||||
const splitRes = splitText2Chunks({ text: rawText, chunkLen: 512 });
|
||||
splitRes.chunks.forEach((chunk) => {
|
||||
const { chunks } = splitText2Chunks({ text: rawText, chunkLen: 512, countTokens: false });
|
||||
chunks.forEach((chunk) => {
|
||||
result.push({
|
||||
q: chunk,
|
||||
a: '',
|
||||
|
@@ -40,7 +40,7 @@ export async function dispatchContentExtract(props: Props): Promise<Response> {
|
||||
const extractModel = global.extractModels[0];
|
||||
const chatHistories = getHistories(history, histories);
|
||||
|
||||
const { arg, tokens } = await (async () => {
|
||||
const { arg, tokens, rawResponse } = await (async () => {
|
||||
if (extractModel.functionCall) {
|
||||
return functionCall({
|
||||
...props,
|
||||
@@ -176,6 +176,7 @@ ${content}
|
||||
|
||||
const tokens = response.usage?.total_tokens || 0;
|
||||
return {
|
||||
rawResponse: response?.choices?.[0]?.message?.tool_calls?.[0]?.function?.arguments || '',
|
||||
tokens,
|
||||
arg
|
||||
};
|
||||
@@ -195,7 +196,7 @@ async function completions({
|
||||
json: extractKeys
|
||||
.map(
|
||||
(item) =>
|
||||
`{"key":"${item.key}", "description":"${item.required}", "required":${item.required}${
|
||||
`{"key":"${item.key}", "description":"${item.desc}", "required":${item.required}${
|
||||
item.enum ? `, "enum":"[${item.enum.split('\n')}]"` : ''
|
||||
}}`
|
||||
)
|
||||
@@ -223,6 +224,7 @@ Human: ${content}`
|
||||
|
||||
if (start === -1 || end === -1)
|
||||
return {
|
||||
rawResponse: answer,
|
||||
tokens: totalTokens,
|
||||
arg: {}
|
||||
};
|
||||
@@ -234,11 +236,13 @@ Human: ${content}`
|
||||
|
||||
try {
|
||||
return {
|
||||
rawResponse: answer,
|
||||
tokens: totalTokens,
|
||||
arg: JSON.parse(jsonStr) as Record<string, any>
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
rawResponse: answer,
|
||||
tokens: totalTokens,
|
||||
arg: {}
|
||||
};
|
||||
|
@@ -50,6 +50,7 @@ export async function dispatchModules({
|
||||
appId,
|
||||
modules,
|
||||
chatId,
|
||||
responseChatItemId,
|
||||
histories = [],
|
||||
startParams = {},
|
||||
variables = {},
|
||||
@@ -63,6 +64,7 @@ export async function dispatchModules({
|
||||
appId: string;
|
||||
modules: ModuleItemType[];
|
||||
chatId?: string;
|
||||
responseChatItemId?: string;
|
||||
histories: ChatItemType[];
|
||||
startParams?: Record<string, any>;
|
||||
variables?: Record<string, any>;
|
||||
@@ -201,6 +203,7 @@ export async function dispatchModules({
|
||||
user,
|
||||
appId,
|
||||
chatId,
|
||||
responseChatItemId,
|
||||
stream,
|
||||
detail,
|
||||
variables,
|
||||
|
@@ -21,6 +21,7 @@ export const dispatchHttpRequest = async (props: HttpRequestProps): Promise<Http
|
||||
let {
|
||||
appId,
|
||||
chatId,
|
||||
responseChatItemId,
|
||||
variables,
|
||||
inputs: {
|
||||
system_httpMethod: httpMethod,
|
||||
@@ -57,6 +58,7 @@ export const dispatchHttpRequest = async (props: HttpRequestProps): Promise<Http
|
||||
requestBody: {
|
||||
appId,
|
||||
chatId,
|
||||
responseChatItemId,
|
||||
variables,
|
||||
data: body
|
||||
},
|
||||
|
@@ -4,7 +4,6 @@ import { initPg } from '@fastgpt/service/common/pg';
|
||||
import { MongoUser } from '@fastgpt/service/support/user/schema';
|
||||
import { connectMongo } from '@fastgpt/service/common/mongo/init';
|
||||
import { hashStr } from '@fastgpt/global/common/string/tools';
|
||||
import { getInitConfig } from '@/pages/api/system/getInitData';
|
||||
import { createDefaultTeam } from '@fastgpt/service/support/user/team/controller';
|
||||
import { exit } from 'process';
|
||||
|
||||
@@ -13,9 +12,7 @@ import { exit } from 'process';
|
||||
*/
|
||||
export function connectToDatabase(): Promise<void> {
|
||||
return connectMongo({
|
||||
beforeHook: () => {
|
||||
getInitConfig();
|
||||
},
|
||||
beforeHook: () => {},
|
||||
afterHook: () => {
|
||||
initPg();
|
||||
// start queue
|
||||
|
2
projects/app/src/types/app.d.ts
vendored
2
projects/app/src/types/app.d.ts
vendored
@@ -61,6 +61,6 @@ export type AppLogsListItemType = {
|
||||
messageCount: number;
|
||||
userGoodFeedbackCount: number;
|
||||
userBadFeedbackCount: number;
|
||||
robotBadFeedbackCount: number;
|
||||
customFeedbacksCount: number;
|
||||
markCount: number;
|
||||
};
|
||||
|
1
projects/app/src/types/core/chat/type.d.ts
vendored
1
projects/app/src/types/core/chat/type.d.ts
vendored
@@ -12,6 +12,7 @@ export type ModuleDispatchProps<T> = {
|
||||
user: UserType;
|
||||
appId: string;
|
||||
chatId?: string;
|
||||
responseChatItemId?: string;
|
||||
stream: boolean;
|
||||
detail: boolean; // response detail
|
||||
variables: Record<string, any>;
|
||||
|
@@ -2,4 +2,6 @@ import { GET, POST, PUT, DELETE } from '@/web/common/api/request';
|
||||
import { UrlFetchParams, UrlFetchResponse } from '@fastgpt/global/common/file/api.d';
|
||||
|
||||
export const postFetchUrls = (data: UrlFetchParams) =>
|
||||
POST<UrlFetchResponse>(`/common/tools/urlFetch`, data);
|
||||
POST<UrlFetchResponse>(`/common/tools/urlFetch`, data, {
|
||||
timeout: 300000
|
||||
});
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { GET, POST, DELETE, PUT } from '@/web/common/api/request';
|
||||
import type { ChatHistoryItemType } from '@fastgpt/global/core/chat/type.d';
|
||||
import type {
|
||||
CloseCustomFeedbackParams,
|
||||
InitChatProps,
|
||||
InitChatResponse,
|
||||
InitOutLinkChatProps,
|
||||
@@ -50,8 +51,12 @@ export const delChatRecordById = (data: DeleteChatItemProps) =>
|
||||
*/
|
||||
export const putChatHistory = (data: UpdateHistoryProps) => PUT('/core/chat/updateHistory', data);
|
||||
|
||||
/* -------------- feedback ------------ */
|
||||
export const updateChatUserFeedback = (data: UpdateChatFeedbackProps) =>
|
||||
POST('/core/chat/feedback/updateUserFeedback', data);
|
||||
|
||||
export const updateChatAdminFeedback = (data: AdminUpdateFeedbackParams) =>
|
||||
POST('/core/chat/feedback/adminUpdate', data);
|
||||
|
||||
export const closeCustomFeedback = (data: CloseCustomFeedbackParams) =>
|
||||
POST('/core/chat/feedback/closeCustom', data).catch();
|
||||
|
@@ -5,7 +5,17 @@ import { useLoading } from '@/web/common/hooks/useLoading';
|
||||
import { useRequest } from '@/web/common/hooks/useRequest';
|
||||
import { getDatasetCollectionPathById, getDatasetCollections } from '@/web/core/dataset/api';
|
||||
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
||||
import { Box, Flex, ModalFooter, Button, useTheme, Grid, Card, Image } from '@chakra-ui/react';
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
ModalFooter,
|
||||
Button,
|
||||
useTheme,
|
||||
Grid,
|
||||
Card,
|
||||
Image,
|
||||
ModalBody
|
||||
} from '@chakra-ui/react';
|
||||
import { DatasetCollectionTypeEnum } from '@fastgpt/global/core/dataset/constant';
|
||||
import { getCollectionIcon } from '@fastgpt/global/core/dataset/utils';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
@@ -115,7 +125,9 @@ const SelectCollections = ({
|
||||
FirstPathDom={
|
||||
<>
|
||||
<Box fontWeight={'bold'} fontSize={['sm', 'lg']}>
|
||||
{title || type === 'folder'
|
||||
{title
|
||||
? title
|
||||
: type === 'folder'
|
||||
? t('common.Select One Folder')
|
||||
: t('dataset.collections.Select Collection')}
|
||||
</Box>
|
||||
@@ -133,85 +145,83 @@ const SelectCollections = ({
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Flex flexDirection={'column'} flex={'1 0 0'}>
|
||||
<Box flex={'1 0 0'} px={4} py={2} position={'relative'}>
|
||||
<Grid
|
||||
gridTemplateColumns={['repeat(1,1fr)', 'repeat(2,1fr)', 'repeat(3,1fr)']}
|
||||
gridGap={3}
|
||||
userSelect={'none'}
|
||||
overflowY={'auto'}
|
||||
mt={2}
|
||||
>
|
||||
{collections.map((item) =>
|
||||
(() => {
|
||||
const selected = selectedDatasetCollectionIds.includes(item._id);
|
||||
return (
|
||||
<Card
|
||||
key={item._id}
|
||||
p={3}
|
||||
border={theme.borders.base}
|
||||
boxShadow={'sm'}
|
||||
cursor={'pointer'}
|
||||
_hover={{
|
||||
boxShadow: 'md'
|
||||
}}
|
||||
{...(selected
|
||||
? {
|
||||
bg: 'myBlue.300'
|
||||
}
|
||||
: {})}
|
||||
onClick={() => {
|
||||
if (item.type === DatasetCollectionTypeEnum.folder) {
|
||||
setParentId(item._id);
|
||||
} else {
|
||||
let result: string[] = [];
|
||||
if (max === 1) {
|
||||
result = [item._id];
|
||||
} else if (selected) {
|
||||
result = selectedDatasetCollectionIds.filter((id) => id !== item._id);
|
||||
} else if (selectedDatasetCollectionIds.length < max) {
|
||||
result = [...selectedDatasetCollectionIds, item._id];
|
||||
}
|
||||
setSelectedDatasetCollectionIds(result);
|
||||
onChange && onChange({ parentId, collectionIds: result });
|
||||
<ModalBody flex={'1 0 0'} overflow={'auto'}>
|
||||
<Grid
|
||||
gridTemplateColumns={['repeat(1,1fr)', 'repeat(2,1fr)']}
|
||||
gridGap={3}
|
||||
userSelect={'none'}
|
||||
overflowY={'auto'}
|
||||
mt={2}
|
||||
>
|
||||
{collections.map((item) =>
|
||||
(() => {
|
||||
const selected = selectedDatasetCollectionIds.includes(item._id);
|
||||
return (
|
||||
<Card
|
||||
key={item._id}
|
||||
p={3}
|
||||
border={theme.borders.base}
|
||||
boxShadow={'sm'}
|
||||
cursor={'pointer'}
|
||||
_hover={{
|
||||
boxShadow: 'md'
|
||||
}}
|
||||
{...(selected
|
||||
? {
|
||||
bg: 'blue.200'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Flex alignItems={'center'} h={'38px'}>
|
||||
<Image src={item.icon} w={'18px'} alt={''} />
|
||||
<Box ml={3} fontSize={'sm'}>
|
||||
{item.name}
|
||||
</Box>
|
||||
</Flex>
|
||||
</Card>
|
||||
);
|
||||
})()
|
||||
)}
|
||||
</Grid>
|
||||
{collections.length === 0 && (
|
||||
<Flex mt={'20vh'} flexDirection={'column'} alignItems={'center'}>
|
||||
<MyIcon name="empty" w={'48px'} h={'48px'} color={'transparent'} />
|
||||
<Box mt={2} color={'myGray.500'}>
|
||||
{t('common.folder.No Folder')}
|
||||
</Box>
|
||||
</Flex>
|
||||
: {})}
|
||||
onClick={() => {
|
||||
if (item.type === DatasetCollectionTypeEnum.folder) {
|
||||
setParentId(item._id);
|
||||
} else {
|
||||
let result: string[] = [];
|
||||
if (max === 1) {
|
||||
result = [item._id];
|
||||
} else if (selected) {
|
||||
result = selectedDatasetCollectionIds.filter((id) => id !== item._id);
|
||||
} else if (selectedDatasetCollectionIds.length < max) {
|
||||
result = [...selectedDatasetCollectionIds, item._id];
|
||||
}
|
||||
setSelectedDatasetCollectionIds(result);
|
||||
onChange && onChange({ parentId, collectionIds: result });
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Flex alignItems={'center'} h={'38px'}>
|
||||
<Image src={item.icon} w={'18px'} alt={''} />
|
||||
<Box ml={3} fontSize={'sm'} className="textEllipsis">
|
||||
{item.name}
|
||||
</Box>
|
||||
</Flex>
|
||||
</Card>
|
||||
);
|
||||
})()
|
||||
)}
|
||||
<Loading loading={isLoading} fixed={false} />
|
||||
</Box>
|
||||
{CustomFooter ? (
|
||||
<>{CustomFooter}</>
|
||||
) : (
|
||||
<ModalFooter>
|
||||
<Button
|
||||
isLoading={isResponding}
|
||||
isDisabled={type === 'collection' && selectedDatasetCollectionIds.length === 0}
|
||||
onClick={mutate}
|
||||
>
|
||||
{type === 'folder' ? t('common.Confirm Move') : t('Confirm')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Grid>
|
||||
{collections.length === 0 && (
|
||||
<Flex mt={'20vh'} flexDirection={'column'} alignItems={'center'}>
|
||||
<MyIcon name="empty" w={'48px'} h={'48px'} color={'transparent'} />
|
||||
<Box mt={2} color={'myGray.500'}>
|
||||
{t('common.folder.No Folder')}
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
</Flex>
|
||||
<Loading loading={isLoading} fixed={false} />
|
||||
</ModalBody>
|
||||
{CustomFooter ? (
|
||||
<>{CustomFooter}</>
|
||||
) : (
|
||||
<ModalFooter>
|
||||
<Button
|
||||
isLoading={isResponding}
|
||||
isDisabled={type === 'collection' && selectedDatasetCollectionIds.length === 0}
|
||||
onClick={mutate}
|
||||
>
|
||||
{type === 'folder' ? t('common.Confirm Move') : t('Confirm')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
)}
|
||||
</MyModal>
|
||||
);
|
||||
};
|
||||
|
@@ -1,5 +1,11 @@
|
||||
import { extendTheme, defineStyleConfig, ComponentStyleConfig } from '@chakra-ui/react';
|
||||
import { modalAnatomy, switchAnatomy, selectAnatomy, numberInputAnatomy } from '@chakra-ui/anatomy';
|
||||
import {
|
||||
modalAnatomy,
|
||||
switchAnatomy,
|
||||
selectAnatomy,
|
||||
numberInputAnatomy,
|
||||
checkboxAnatomy
|
||||
} from '@chakra-ui/anatomy';
|
||||
import { createMultiStyleConfigHelpers } from '@chakra-ui/styled-system';
|
||||
|
||||
const { definePartsStyle, defineMultiStyleConfig } = createMultiStyleConfigHelpers(
|
||||
@@ -11,6 +17,8 @@ const { definePartsStyle: selectPart, defineMultiStyleConfig: selectMultiStyle }
|
||||
createMultiStyleConfigHelpers(selectAnatomy.keys);
|
||||
const { definePartsStyle: numInputPart, defineMultiStyleConfig: numInputMultiStyle } =
|
||||
createMultiStyleConfigHelpers(numberInputAnatomy.keys);
|
||||
const { definePartsStyle: checkBoxPart, defineMultiStyleConfig: checkBoxMultiStyle } =
|
||||
createMultiStyleConfigHelpers(checkboxAnatomy.keys);
|
||||
|
||||
// 按键
|
||||
const Button = defineStyleConfig({
|
||||
@@ -68,7 +76,7 @@ const Button = defineStyleConfig({
|
||||
},
|
||||
gray: {
|
||||
bg: '#F5F5F8',
|
||||
color: 'myBlue.700',
|
||||
color: 'blue.600',
|
||||
border: '1px solid #EFF0F1',
|
||||
_hover: {
|
||||
background: '#3370FF1A'
|
||||
@@ -81,12 +89,12 @@ const Button = defineStyleConfig({
|
||||
bg: 'transparent',
|
||||
transition: 'background 0.3s',
|
||||
_hover: {
|
||||
color: 'myBlue.600',
|
||||
color: 'blue.500',
|
||||
background: 'myWhite.400',
|
||||
boxShadow: '0 0 5px rgba(0,0,0,0.1)'
|
||||
},
|
||||
_active: {
|
||||
color: 'myBlue.700'
|
||||
color: 'blue.600'
|
||||
},
|
||||
_disabled: {
|
||||
bg: 'myGray.100 !important',
|
||||
@@ -127,7 +135,7 @@ const Input: ComponentStyleConfig = {
|
||||
borderRadius: 'base',
|
||||
borderColor: 'myGray.200',
|
||||
_focus: {
|
||||
borderColor: 'myBlue.600',
|
||||
borderColor: 'blue.500',
|
||||
boxShadow: '0px 0px 4px #A8DBFF',
|
||||
bg: 'white'
|
||||
},
|
||||
@@ -153,7 +161,7 @@ const NumberInput = numInputMultiStyle({
|
||||
borderRadius: 'base',
|
||||
borderColor: 'myGray.200',
|
||||
_focus: {
|
||||
borderColor: 'myBlue.600 !important',
|
||||
borderColor: 'blue.500 !important',
|
||||
boxShadow: '0px 0px 4px #A8DBFF !important',
|
||||
bg: 'transparent'
|
||||
},
|
||||
@@ -167,7 +175,7 @@ const NumberInput = numInputMultiStyle({
|
||||
border: 'none',
|
||||
color: 'myGray.600',
|
||||
_active: {
|
||||
color: 'myBlue.600'
|
||||
color: 'blue.500'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -187,7 +195,7 @@ const Textarea: ComponentStyleConfig = {
|
||||
borderColor: ''
|
||||
},
|
||||
_focus: {
|
||||
borderColor: 'myBlue.600',
|
||||
borderColor: 'blue.500',
|
||||
boxShadow: '0px 0px 4px #A8DBFF',
|
||||
bg: 'white'
|
||||
}
|
||||
@@ -205,7 +213,7 @@ const Switch = switchMultiStyle({
|
||||
track: {
|
||||
bg: 'myGray.100',
|
||||
_checked: {
|
||||
bg: 'myBlue.700'
|
||||
bg: 'blue.600'
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -218,13 +226,21 @@ const Select = selectMultiStyle({
|
||||
borderColor: 'myGray.200',
|
||||
_focusWithin: {
|
||||
boxShadow: '0px 0px 4px #A8DBFF',
|
||||
borderColor: 'myBlue.600'
|
||||
borderColor: 'blue.500'
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
const Checkbox = checkBoxMultiStyle({
|
||||
baseStyle: checkBoxPart({
|
||||
label: {
|
||||
fontFamily: 'mono' // change the font family of the label
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// 全局主题
|
||||
export const theme = extendTheme({
|
||||
styles: {
|
||||
@@ -238,7 +254,7 @@ export const theme = extendTheme({
|
||||
// lineHeight: 'unset'
|
||||
},
|
||||
a: {
|
||||
color: 'myBlue.700'
|
||||
color: 'blue.600'
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -267,17 +283,17 @@ export const theme = extendTheme({
|
||||
900: '#24282C',
|
||||
1000: '#121416'
|
||||
},
|
||||
myBlue: {
|
||||
100: '#f0f7ff',
|
||||
200: '#EBF7FD',
|
||||
300: '#d6e8ff',
|
||||
400: '#adceff',
|
||||
500: '#85b1ff',
|
||||
600: '#4e83fd',
|
||||
700: '#3370ff',
|
||||
800: '#2152d9',
|
||||
900: '#1237b3',
|
||||
1000: '#07228c'
|
||||
blue: {
|
||||
50: '#f0f7ff',
|
||||
100: '#EBF7FD',
|
||||
200: '#d6e8ff',
|
||||
300: '#adceff',
|
||||
400: '#85b1ff',
|
||||
500: '#4e83fd',
|
||||
600: '#3370ff',
|
||||
700: '#2152d9',
|
||||
800: '#1237b3',
|
||||
900: '#07228c'
|
||||
},
|
||||
myRead: {
|
||||
600: '#ff4d4f'
|
||||
@@ -326,6 +342,7 @@ export const theme = extendTheme({
|
||||
Textarea,
|
||||
Switch,
|
||||
Select,
|
||||
NumberInput
|
||||
NumberInput,
|
||||
Checkbox
|
||||
}
|
||||
});
|
||||
|
Reference in New Issue
Block a user