Merge pull request #746 from SuanmoSuanyangTechnology/feature/ui_upgrade_zy
Feature/UI upgrade zy
@@ -68,8 +68,8 @@ export const getModelTypeList = async () => {
|
||||
return response as any[];
|
||||
};
|
||||
// 获取模型列表
|
||||
export const getModelList = async (pageInfo: PageRequest) => {
|
||||
const response = await request.get(`${apiPrefix}/models`, { ...pageInfo, is_active: true });
|
||||
export const getModelList = async (types: string[], pageInfo: PageRequest) => {
|
||||
const response = await request.get(`${apiPrefix}/models`, { ...pageInfo, type: types?.join(','), is_active: true });
|
||||
return response as any;
|
||||
};
|
||||
//获取模型提供者
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 14:00:06
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 17:48:01
|
||||
* @Last Modified time: 2026-03-31 12:25:53
|
||||
*/
|
||||
import { request } from '@/utils/request'
|
||||
import type { AxiosRequestConfig } from 'axios'
|
||||
@@ -63,8 +63,8 @@ export const getDashboardData = () => {
|
||||
|
||||
/****************** User Memory APIs *******************************/
|
||||
export const userMemoryListUrl = '/dashboard/end_users'
|
||||
export const getUserMemoryList = () => {
|
||||
return request.get(userMemoryListUrl)
|
||||
export const getUserMemoryList = (query?: { keyword?: string }) => {
|
||||
return request.get(userMemoryListUrl, query)
|
||||
}
|
||||
// User Memory - Total end users
|
||||
export const getTotalEndUsers = () => {
|
||||
|
||||
19
web/src/assets/images/common/delete_red_big.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组 33</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-工具管理--MCP服务" transform="translate(-1032, -187)" stroke="#FF5D34">
|
||||
<g id="编组-16" transform="translate(1020, 126)">
|
||||
<g id="编组-33" transform="translate(12, 61)">
|
||||
<g id="编组-32" transform="translate(2.5, 3)">
|
||||
<line x1="-1.80133686e-14" y1="2.22222222" x2="11" y2="2.22222222" id="路径-29"></line>
|
||||
<polyline id="路径-30" stroke-linejoin="round" points="3.3 2.2221179 3.3 0 7.7 0 7.7 2.22222222"></polyline>
|
||||
<path d="M1.65,2.23587458 L1.65,9 C1.65,9.55228475 2.09771525,10 2.65,10 L8.35,10 C8.90228475,10 9.35,9.55228475 9.35,9 L9.35,2.22222222 L9.35,2.22222222" id="路径-31" stroke-linejoin="round"></path>
|
||||
<line x1="4.4" y1="4.45203738" x2="4.4" y2="7.78537071" id="路径-32"></line>
|
||||
<line x1="6.6" y1="4.45203738" x2="6.6" y2="7.78537071" id="路径-32"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
17
web/src/assets/images/common/edit_bg.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编辑</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="工作台-提示词-我的历史" transform="translate(-976, -320)">
|
||||
<g id="编组-13备份-6" transform="translate(648, 122)">
|
||||
<g id="编辑" transform="translate(328, 198)">
|
||||
<rect id="矩形" fill="#EBEBEB" fill-rule="nonzero" x="0" y="0" width="18" height="18" rx="6"></rect>
|
||||
<g id="编组-10" transform="translate(4.3, 4.3)" stroke="#5B6167">
|
||||
<path d="M9.4,4.04322919 L9.4,7.4 C9.4,8.5045695 8.5045695,9.4 7.4,9.4 L2,9.4 C0.8954305,9.4 0,8.5045695 0,7.4 L0,2 C0,0.8954305 0.8954305,2.22044605e-16 2,0 L5.38958415,0 L5.38958415,0" id="路径"></path>
|
||||
<line x1="3.74260398" y1="5.68579764" x2="9.4" y2="1.05734433e-14" id="路径-2"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
16
web/src/assets/images/common/edit_bold.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编辑</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||
<g id="平台管理-工具管理--MCP服务" transform="translate(-1032, -135)" stroke="#171719">
|
||||
<g id="编组-16" transform="translate(1020, 126)">
|
||||
<g id="编辑" transform="translate(12, 9)">
|
||||
<g id="编组-10" transform="translate(3, 3)">
|
||||
<path d="M10,4.30130765 L10,8 C10,9.1045695 9.1045695,10 8,10 L2,10 C0.8954305,10 0,9.1045695 0,8 L0,2 C0,0.8954305 0.8954305,2.22044605e-16 2,0 L5.73360016,0 L5.73360016,0" id="路径"></path>
|
||||
<line x1="3.98149359" y1="6.04872089" x2="10" y2="1.12483439e-14" id="路径-2"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
16
web/src/assets/images/common/eye.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>link-outlined</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="API-Key-管理" transform="translate(-1034, -161)" stroke="#171719">
|
||||
<g id="编组-16" transform="translate(1022, 126)">
|
||||
<g id="link-outlined" transform="translate(12, 35)">
|
||||
<g id="编组-14" transform="translate(2.5, 4.15)">
|
||||
<path d="M5.50029186,2.425 C5.92116821,2.425 6.30372933,2.58703648 6.58052274,2.85122056 C6.84862719,3.1071115 7.01717088,3.4597026 7.01717088,3.85 C7.01717088,4.24027468 6.84857286,4.5929387 6.58042003,4.84890344 C6.3036418,5.11310155 5.92112667,5.27520782 5.50029186,5.27520782 C5.07946329,5.27520782 4.69695201,5.11310096 4.42017607,4.84890315 C4.15202505,4.59293829 3.98342734,4.24027444 3.98342734,3.85 C3.98342734,3.45970284 4.15197072,3.10711191 4.42007337,2.85122085 C4.69686448,2.58703707 5.07942175,2.425 5.50029186,2.425 Z" id="路径" fill-rule="nonzero"></path>
|
||||
<path d="M5.5,7.7 C8.53756612,7.7 11,5.39612383 11,3.85 C11,2.30387617 8.53756612,0 5.5,0 C2.46243388,0 0,2.26850164 0,3.85 C0,5.43149836 2.46243388,7.7 5.5,7.7 Z" id="椭圆形"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
17
web/src/assets/images/common/eye_bg.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编辑</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="工作台-提示词-我的历史" transform="translate(-950, -320)">
|
||||
<g id="编组-13备份-6" transform="translate(648, 122)">
|
||||
<g id="编辑" transform="translate(302, 198)">
|
||||
<rect id="矩形" fill="#EBEBEB" fill-rule="nonzero" x="0" y="0" width="18" height="18" rx="6"></rect>
|
||||
<g id="编组-16" transform="translate(2.5, 4.7)" stroke="#5B6167">
|
||||
<ellipse id="椭圆形" cx="6.5" cy="4.3" rx="6.5" ry="4.3"></ellipse>
|
||||
<circle id="椭圆形" cx="6.5" cy="4.3" r="1.75"></circle>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1011 B |
13
web/src/assets/images/common/link.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>link-outlined</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-工具管理--MCP服务" transform="translate(-1032, -161)" fill="#171719" fill-rule="nonzero">
|
||||
<g id="编组-16" transform="translate(1020, 126)">
|
||||
<g id="link-outlined" transform="translate(12, 35)">
|
||||
<path d="M8.8887561,10.1978746 C8.84435493,10.1534734 8.77130783,10.1534734 8.72690666,10.1978746 L7.06257876,11.8622025 C6.29200354,12.6327777 4.99147881,12.7144186 4.14069502,11.8622025 C3.28847892,11.0099864 3.37011979,9.71089398 4.14069502,8.94031876 L5.80502291,7.27599086 C5.84942409,7.23158968 5.84942409,7.15854259 5.80502291,7.11414142 L5.23496912,6.54408763 C5.19056795,6.49968645 5.11752086,6.49968645 5.07311968,6.54408763 L3.40879178,8.20841552 C2.19706941,9.4201379 2.19706941,11.3809511 3.40879178,12.5912411 C4.62051416,13.8015312 6.58132732,13.8029635 7.7916174,12.5912411 L9.4559453,10.9269132 C9.50034647,10.8825121 9.50034647,10.809465 9.4559453,10.7650638 L8.8887561,10.1978746 Z M12.5926734,3.40879178 C11.3809511,2.19706941 9.4201379,2.19706941 8.20984782,3.40879178 L6.54408763,5.07311968 C6.49968645,5.11752086 6.49968645,5.19056795 6.54408763,5.23496912 L7.11270912,5.80359062 C7.15711029,5.84799179 7.23015739,5.84799179 7.27455856,5.80359062 L8.93888646,4.13926272 C9.70946168,3.3686875 11.0099864,3.28704663 11.8607702,4.13926272 C12.7129863,4.99147881 12.6313454,6.29057124 11.8607702,7.06114647 L10.1964423,8.72547436 C10.1520411,8.76987554 10.1520411,8.84292263 10.1964423,8.88732381 L10.7664961,9.4573776 C10.8108973,9.50177877 10.8839444,9.50177877 10.9283455,9.4573776 L12.5926734,7.7930497 C13.8029635,6.58132732 13.8029635,4.62051416 12.5926734,3.40879178 L12.5926734,3.40879178 Z M9.40581494,5.99981516 C9.36141377,5.95541399 9.28836667,5.95541399 9.2439655,5.99981516 L5.99981516,9.2425332 C5.95541399,9.28693438 5.95541399,9.35998147 5.99981516,9.40438265 L6.56700436,9.97157184 C6.61140554,10.015973 6.68445263,10.015973 6.7288538,9.97157184 L9.97157184,6.7288538 C10.015973,6.68445263 10.015973,6.61140554 9.97157184,6.56700436 L9.40581494,5.99981516 Z" id="形状"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -1,12 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>更多</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="记忆库-个人记忆-感知记忆-听觉" transform="translate(-440, -187)" fill-rule="nonzero">
|
||||
<g id="编组-14" transform="translate(28, 168)">
|
||||
<g id="更多" transform="translate(412, 19)">
|
||||
<rect id="矩形" fill="#000000" opacity="0" x="0" y="0" width="24" height="24"></rect>
|
||||
<path d="M5.25,12 C5.25,12.8284271 5.92157288,13.5 6.75,13.5 C7.57842712,13.5 8.25,12.8284271 8.25,12 C8.25,11.1715729 7.57842712,10.5 6.75,10.5 C5.92157288,10.5 5.25,11.1715729 5.25,12 Z M10.5,12 C10.5,12.8284271 11.1715729,13.5 12,13.5 C12.8284271,13.5 13.5,12.8284271 13.5,12 C13.5,11.1715729 12.8284271,10.5 12,10.5 C11.1715729,10.5 10.5,11.1715729 10.5,12 Z M15.75,12 C15.75,12.8284271 16.4215729,13.5 17.25,13.5 C18.0784271,13.5 18.75,12.8284271 18.75,12 C18.75,11.1715729 18.0784271,10.5 17.25,10.5 C16.4215729,10.5 15.75,11.1715729 15.75,12 Z" id="形状" fill="#171719"></path>
|
||||
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>卡片1@3x</title>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-工具管理--MCP服务" transform="translate(-602, -128)" fill="#5B6167" fill-rule="nonzero">
|
||||
<g id="卡片1" transform="translate(252, 112)">
|
||||
<g id="更多" transform="translate(350, 16)">
|
||||
<path d="M5.4,12.4 C6.17319865,12.4 6.8,11.7731986 6.8,11 C6.8,10.2268014 6.17319865,9.6 5.4,9.6 C4.62680135,9.6 4,10.2268014 4,11 C4,11.7731986 4.62680135,12.4 5.4,12.4 Z M11,12.4 C11.7731986,12.4 12.4,11.7731986 12.4,11 C12.4,10.2268014 11.7731986,9.6 11,9.6 C10.2268014,9.6 9.6,10.2268014 9.6,11 C9.6,11.7731986 10.2268014,12.4 11,12.4 Z M16.6,12.4 C17.3731986,12.4 18,11.7731986 18,11 C18,10.2268014 17.3731986,9.6 16.6,9.6 C15.8268014,9.6 15.2,10.2268014 15.2,11 C15.2,11.7731986 15.8268014,12.4 16.6,12.4 Z" id="形状"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,14 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>更多</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="记忆库-个人记忆-感知记忆-文本" transform="translate(-440, -187)" fill-rule="nonzero">
|
||||
<g id="编组-8" transform="translate(12, 76)">
|
||||
<g id="编组-14" transform="translate(16, 92)">
|
||||
<g id="更多" transform="translate(412, 19)">
|
||||
<rect id="矩形" fill="#E4E4E4" x="0" y="0" width="24" height="24" rx="8"></rect>
|
||||
<path d="M5.25,12 C5.25,12.8284271 5.92157288,13.5 6.75,13.5 C7.57842712,13.5 8.25,12.8284271 8.25,12 C8.25,11.1715729 7.57842712,10.5 6.75,10.5 C5.92157288,10.5 5.25,11.1715729 5.25,12 Z M10.5,12 C10.5,12.8284271 11.1715729,13.5 12,13.5 C12.8284271,13.5 13.5,12.8284271 13.5,12 C13.5,11.1715729 12.8284271,10.5 12,10.5 C11.1715729,10.5 10.5,11.1715729 10.5,12 Z M15.75,12 C15.75,12.8284271 16.4215729,13.5 17.25,13.5 C18.0784271,13.5 18.75,12.8284271 18.75,12 C18.75,11.1715729 18.0784271,10.5 17.25,10.5 C16.4215729,10.5 15.75,11.1715729 15.75,12 Z" id="形状" fill="#171719"></path>
|
||||
</g>
|
||||
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>更多@3x</title>
|
||||
<defs>
|
||||
<filter x="-3.4%" y="-6.2%" width="106.8%" height="114.8%" filterUnits="objectBoundingBox" id="filter-1">
|
||||
<feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||
<feGaussianBlur stdDeviation="4" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||
<feColorMatrix values="0 0 0 0 0.0901960784 0 0 0 0 0.0901960784 0 0 0 0 0.0980392157 0 0 0 0.16 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
|
||||
<feMerge>
|
||||
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
|
||||
<feMergeNode in="SourceGraphic"></feMergeNode>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<g id="空间外层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="平台管理-工具管理--MCP服务" transform="translate(-998, -128)" fill-rule="nonzero">
|
||||
<g id="卡片1备份" filter="url(#filter-1)" transform="translate(648, 112)">
|
||||
<g id="更多" transform="translate(350, 16)">
|
||||
<rect id="矩形" fill="#F6F6F6" x="0" y="0" width="22" height="22" rx="8"></rect>
|
||||
<path d="M5.4,12.4 C6.17319865,12.4 6.8,11.7731986 6.8,11 C6.8,10.2268014 6.17319865,9.6 5.4,9.6 C4.62680135,9.6 4,10.2268014 4,11 C4,11.7731986 4.62680135,12.4 5.4,12.4 Z M11,12.4 C11.7731986,12.4 12.4,11.7731986 12.4,11 C12.4,10.2268014 11.7731986,9.6 11,9.6 C10.2268014,9.6 9.6,10.2268014 9.6,11 C9.6,11.7731986 10.2268014,12.4 11,12.4 Z M16.6,12.4 C17.3731986,12.4 18,11.7731986 18,11 C18,10.2268014 17.3731986,9.6 16.6,9.6 C15.8268014,9.6 15.2,10.2268014 15.2,11 C15.2,11.7731986 15.8268014,12.4 16.6,12.4 Z" id="形状" fill="#5B6167"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 158 KiB |
16
web/src/assets/images/menuNew/arrow_t_r.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组 51</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||
<g id="工作台-记忆看板-3" transform="translate(-1400, -140)" stroke="#A8A9AA" stroke-width="1.2">
|
||||
<g id="编组-22" transform="translate(1180, 57)">
|
||||
<g id="编组-51" transform="translate(220, 83)">
|
||||
<g id="编组-49" transform="translate(4.5, 4.5)">
|
||||
<polyline id="路径" points="0 0 7 0 7 7"></polyline>
|
||||
<line x1="7" y1="0" x2="9.71445147e-17" y2="7" id="路径-51"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 938 B |
17
web/src/assets/images/menuNew/logout_red.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>退出</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||
<g id="工作台-记忆看板-3" transform="translate(-1196, -229)" stroke="#FF5D34" stroke-width="1.2">
|
||||
<g id="编组-22" transform="translate(1180, 57)">
|
||||
<g id="退出" transform="translate(16, 172)">
|
||||
<g id="编组-7" transform="translate(2.5, 2)">
|
||||
<path d="M4,12 L2,12 C0.8954305,12 0,11.1045695 0,10 L0,2 C0,0.8954305 0.8954305,2.22044605e-16 2,0 L4,0 L4,0" id="路径"></path>
|
||||
<line x1="11" y1="6" x2="4.5" y2="6" id="路径-6"></line>
|
||||
<polyline id="路径" points="8 3 11 6 8 9"></polyline>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
19
web/src/assets/images/menuNew/settings.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>设置-界面设置</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="工作台-记忆看板-3" transform="translate(-1196, -176)">
|
||||
<g id="编组-22" transform="translate(1180, 57)">
|
||||
<g id="设置-界面设置" transform="translate(16, 119)">
|
||||
<g id="编组-2" transform="translate(2, 2)">
|
||||
<path d="M9.43360402,6.02003217 C9.70219942,5.98544974 9.97412053,5.98544974 10.2427159,6.02003217 C10.3615753,6.03694616 10.4495746,6.13920492 10.4485827,6.25925761 L10.4485827,6.97778158 C10.8355212,7.08416506 11.1878633,7.2900028 11.4705612,7.57481981 L12.0861381,7.21535276 C12.1886462,7.15532215 12.3197841,7.18070349 12.3924911,7.27464643 C12.5566377,7.49314267 12.6927553,7.73134853 12.7976622,7.98369599 C12.8417451,8.09509234 12.7980417,8.22199461 12.6947152,8.28262525 L12.0795484,8.64127201 C12.1812591,9.03280439 12.1812591,9.44382977 12.0795484,9.83536215 L12.6951253,10.1940089 C12.7984653,10.255883 12.8408681,10.3841328 12.7947775,10.4954127 C12.6902734,10.7470629 12.5545635,10.9845849 12.3908368,11.2023979 C12.3178817,11.29706 12.1858902,11.3226521 12.0828433,11.2621154 L11.4681003,10.9034823 C11.1853554,11.1882385 10.8330304,11.3940662 10.4461218,11.5005205 L10.4461218,12.2190308 C10.4472928,12.3391587 10.3591904,12.4415237 10.2402277,12.4582563 C9.97161477,12.49242 9.69975606,12.49242 9.43114314,12.4582563 C9.31227289,12.4413547 9.22425896,12.3390925 9.22524902,12.2190308 L9.22524902,11.5005069 C8.83966141,11.3929856 8.48863308,11.187108 8.20657902,10.9030585 L7.58893771,11.263756 C7.48646614,11.3234892 7.35562246,11.2983389 7.28259844,11.2048724 C7.11845115,10.9862292 6.98233473,10.7478877 6.87742727,10.4954127 C6.83256205,10.383776 6.87616574,10.2561165 6.9799505,10.195253 L7.59757815,9.83618245 C7.54895974,9.65227947 7.52310022,9.46310373 7.52057977,9.27289936 C7.51726668,9.06031128 7.54274952,8.8482532 7.59633403,8.64250245 L6.9807708,8.28344555 C6.87737248,8.2230699 6.83375833,8.09609457 6.87823389,7.98492643 C6.98279132,7.7324117 7.11893329,7.49416785 7.28340506,7.27589055 C7.35624204,7.18108729 7.48825303,7.15531561 7.59139859,7.2157629 L8.2061552,7.57481981 C8.48870496,7.29001094 8.84091669,7.08416484 9.22773725,6.97776791 L9.22773725,6.25925761 C9.22638248,6.13907231 9.31455943,6.03660714 9.43360402,6.02003217 Z M9.85567328,8.1381029 L9.83960916,8.1381029 C9.44388649,8.13394685 9.07614467,8.3416968 8.87546122,8.68278309 C8.67477776,9.02386937 8.67178651,9.44622602 8.86761874,9.79012055 C9.06345096,10.1340151 9.42821335,10.3469528 9.82395519,10.3484022 L9.85608342,10.3484022 C10.4510916,10.3389892 10.929189,9.8552216 10.9315862,9.26014377 C10.9437669,8.6534016 10.4623788,8.15138092 9.85567328,8.1381029 Z" id="形状结合" fill="#171719" fill-rule="nonzero"></path>
|
||||
<path d="M5.99499898,12 L2,12 C0.8954305,12 4.4408921e-16,11.1045695 4.4408921e-16,10 L0,2 C0,0.8954305 0.8954305,2.22044605e-16 2,0 L10,0 C11.1045695,0 12,0.8954305 12,2 L12,4.98927875 L12,4.98927875" id="路径" stroke="#171719" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||
<line x1="0" y1="3.99424593" x2="12" y2="3.99424593" id="路径-2" stroke="#171719" stroke-width="1.2"></line>
|
||||
<circle id="椭圆形" fill="#171719" cx="2.2" cy="2" r="1"></circle>
|
||||
<circle id="椭圆形" fill="#171719" cx="4.4" cy="2" r="1"></circle>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
13
web/src/assets/images/menuNew/userInfo.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>账户</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="工作台-记忆看板-3" transform="translate(-1196, -140)" fill="#171719" fill-rule="nonzero" stroke="#171719" stroke-width="0.4">
|
||||
<g id="编组-22" transform="translate(1180, 57)">
|
||||
<g id="账户" transform="translate(16, 83)">
|
||||
<path d="M8,1 C4.13400675,1 1,4.13400675 1,8 C1,11.8659932 4.13400675,15 8,15 C11.8659932,15 15,11.8659932 15,8 C14.9947583,4.13618002 11.86382,1.0052417 8,1 L8,1 Z M12.4014141,12.3271621 L12.2224629,12.517543 L12.1748711,12.2662539 C12.0428879,11.5485013 11.7289104,10.8766306 11.2629844,10.3149355 C11.1145387,10.1521744 10.8641988,10.135306 10.6952598,10.2766811 C10.5263208,10.4180561 10.4988,10.6674498 10.6328477,10.8422598 C11.1442401,11.4572317 11.4244051,12.2317168 11.4248047,13.0315371 C11.4257399,13.0442165 11.4257399,13.0569476 11.4248047,13.069627 L11.4248047,13.1419512 L11.3638828,13.1819414 C9.31720678,14.5169283 6.67517799,14.5169283 4.62850195,13.1819414 L4.56758008,13.1419648 L4.56758008,13.0334512 C4.56758008,11.1409267 6.10177432,9.60673242 7.99429883,9.60673242 C9.43633406,9.61053035 10.6698828,8.57151634 10.9112248,7.14981524 C11.1525669,5.72811413 10.3309981,4.34023189 8.96849203,3.8679425 C7.60598597,3.39565311 6.10170668,3.97731994 5.4113796,5.24338809 C4.72105252,6.50945624 5.046918,8.08901446 6.18194141,8.97850977 L6.35137695,9.10986914 L6.16099609,9.20315234 C4.9414843,9.79213158 4.07443441,10.9255913 3.82512891,12.2567383 L3.77753711,12.5080273 L3.59858594,12.3176602 C2.45876944,11.1700068 1.82010269,9.61749329 1.8223981,8 C1.81896848,5.20888419 3.68748546,2.76216731 6.38105315,2.03070823 C9.07462084,1.29924914 11.9240679,2.46476648 13.3328918,4.87423832 C14.7417157,7.28371017 14.3599179,10.338544 12.4014141,12.3271621 L12.4014141,12.3271621 Z M5.87924609,6.65787305 C5.88029543,5.48791052 6.82940261,4.5402209 7.9993654,4.54091991 C9.16932819,4.5416197 10.1173016,5.49044339 10.1169523,6.66040633 C10.1166027,7.83036928 9.16806261,8.77862695 7.99809961,8.77862695 C6.82758179,8.77757806 5.87924609,7.82839134 5.87924609,6.65787305 L5.87924609,6.65787305 Z" id="形状"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
BIN
web/src/assets/images/model/bedrock.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
@@ -1,15 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_16762_59518)">
|
||||
<path d="M12.6667 0H3.33333C1.49238 0 0 1.49238 0 3.33333V12.6667C0 14.5076 1.49238 16 3.33333 16H12.6667C14.5076 16 16 14.5076 16 12.6667V3.33333C16 1.49238 14.5076 0 12.6667 0Z" fill="url(#paint0_linear_16762_59518)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.99984 12.093L6.3825 12.6323L5.75184 12.2116L6.4385 11.9823L6.22784 11.3503L5.04917 11.743L4.6665 11.4883V9.66631C4.6665 9.54031 4.59517 9.42497 4.4825 9.3683L3.33317 8.79364V7.20564L4.33317 6.70564L5.33317 7.20564V8.33297C5.33317 8.45964 5.4045 8.57497 5.51717 8.63164L6.8505 9.29831L7.14917 8.70164L5.99984 8.12697V7.20564L7.14917 6.63164C7.26184 6.57497 7.33317 6.45964 7.33317 6.33297V5.33297H6.6665V6.12697L5.6665 6.62697L4.6665 6.12697V4.51164L5.33317 4.06697V5.33297H5.99984V3.62297L6.3825 3.36764L7.99984 3.90697V12.093ZM11.6665 11.333C11.8498 11.333 11.9998 11.4823 11.9998 11.6663C11.9998 11.8503 11.8498 11.9996 11.6665 11.9996C11.4832 11.9996 11.3332 11.8503 11.3332 11.6663C11.3332 11.4823 11.4832 11.333 11.6665 11.333ZM10.9998 3.99964C11.1832 3.99964 11.3332 4.14897 11.3332 4.33297C11.3332 4.51697 11.1832 4.6663 10.9998 4.6663C10.8165 4.6663 10.6665 4.51697 10.6665 4.33297C10.6665 4.14897 10.8165 3.99964 10.9998 3.99964ZM12.3332 7.99964C12.5165 7.99964 12.6665 8.14897 12.6665 8.33297C12.6665 8.51697 12.5165 8.66631 12.3332 8.66631C12.1498 8.66631 11.9998 8.51697 11.9998 8.33297C11.9998 8.14897 12.1498 7.99964 12.3332 7.99964ZM11.3945 8.66631C11.5325 9.05364 11.8992 9.33297 12.3332 9.33297C12.8845 9.33297 13.3332 8.88497 13.3332 8.33297C13.3332 7.78164 12.8845 7.33297 12.3332 7.33297C11.8992 7.33297 11.5325 7.61297 11.3945 7.99964H8.6665V6.66631H10.9998C11.1838 6.66631 11.3332 6.51764 11.3332 6.33297V5.27164C11.7205 5.13364 11.9998 4.76697 11.9998 4.33297C11.9998 3.78164 11.5512 3.33297 10.9998 3.33297C10.4485 3.33297 9.99984 3.78164 9.99984 4.33297C9.99984 4.76697 10.2792 5.13364 10.6665 5.27164V5.99964H8.6665V3.6663C8.6665 3.52297 8.5745 3.39564 8.4385 3.3503L6.4385 2.68364C6.3405 2.65097 6.23384 2.66564 6.1485 2.7223L4.1485 4.05564C4.05584 4.11764 3.99984 4.22164 3.99984 4.33297V6.12697L2.8505 6.70164C2.73784 6.75831 2.6665 6.87364 2.6665 6.99964V8.99964C2.6665 9.12631 2.73784 9.24164 2.8505 9.29831L3.99984 9.87231V11.6663C3.99984 11.7776 4.05584 11.8823 4.1485 11.9436L6.1485 13.277C6.20384 13.3143 6.26784 13.333 6.33317 13.333C6.3685 13.333 6.40384 13.3276 6.4385 13.3156L8.4385 12.649C8.5745 12.6043 8.6665 12.477 8.6665 12.333V10.6663H10.1952L10.7638 11.2356L10.7725 11.227C10.7072 11.3603 10.6665 11.5083 10.6665 11.6663C10.6665 12.2176 11.1152 12.6663 11.6665 12.6663C12.2178 12.6663 12.6665 12.2176 12.6665 11.6663C12.6665 11.115 12.2178 10.6663 11.6665 10.6663C11.5078 10.6663 11.3598 10.707 11.2272 10.773L11.2358 10.7643L10.5692 10.0976C10.5065 10.035 10.4218 9.99964 10.3332 9.99964H8.6665V8.66631H11.3945Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_16762_59518" x1="0" y1="1600" x2="1600" y2="0" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#055F4E"/>
|
||||
<stop offset="1" stop-color="#56C0A7"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_16762_59518">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 3.2 KiB |
BIN
web/src/assets/images/model/ollama.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 7.7 KiB |
BIN
web/src/assets/images/model/openai.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 2.5 KiB |
BIN
web/src/assets/images/model/xinference.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
@@ -1,24 +0,0 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Xorbits Square" clip-path="url(#clip0_9850_26870)">
|
||||
<path id="Vector" d="M8.00391 12.3124C8.69334 13.0754 9.47526 13.7494 10.3316 14.3188C11.0667 14.8105 11.8509 15.2245 12.6716 15.5541C14.1617 14.1465 15.3959 12.4907 16.3192 10.6606L21.7051 0L12.3133 7.38353C10.5832 8.74456 9.12178 10.416 8.00391 12.3124Z" fill="url(#paint0_linear_9850_26870)"/>
|
||||
<path id="Vector_2" d="M7.23504 18.9512C6.56092 18.5012 5.92386 18.0265 5.3221 17.5394L2.06445 24L7.91975 19.3959C7.69034 19.2494 7.46092 19.103 7.23504 18.9512Z" fill="url(#paint1_linear_9850_26870)"/>
|
||||
<path id="Vector_3" d="M19.3161 8.57474C21.0808 10.9147 21.5961 13.5159 20.3996 15.3053C18.6526 17.9189 13.9161 17.8183 9.82024 15.0812C5.72435 12.3441 3.82024 8.0065 5.56729 5.39297C6.76377 3.60356 9.36318 3.0865 12.2008 3.81886C7.29318 1.73474 2.62376 1.94121 0.813177 4.64474C-1.45976 8.04709 1.64435 14.1177 7.74494 18.1889C13.8455 22.26 20.6361 22.8124 22.9091 19.4118C24.7179 16.703 23.1173 12.3106 19.3161 8.57474Z" fill="url(#paint2_linear_9850_26870)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_9850_26870" x1="2.15214" y1="24.3018" x2="21.2921" y2="0.0988218" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#E9A85E"/>
|
||||
<stop offset="1" stop-color="#F52B76"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_9850_26870" x1="2.06269" y1="24.2294" x2="21.2027" y2="0.028252" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#E9A85E"/>
|
||||
<stop offset="1" stop-color="#F52B76"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_9850_26870" x1="-0.613606" y1="3.843" x2="21.4449" y2="18.7258" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#6A0CF5"/>
|
||||
<stop offset="1" stop-color="#AB66F3"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_9850_26870">
|
||||
<rect width="24" height="24" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
19
web/src/assets/images/prompt/delete.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组 33</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="工作台-提示词-我的历史" transform="translate(-1002, -560)" stroke="#5B6167">
|
||||
<g id="编组-13备份-4" transform="translate(648, 362)">
|
||||
<g id="编组-33" transform="translate(354, 198)">
|
||||
<g id="编组-32" transform="translate(3.5, 4)">
|
||||
<line x1="-1.80133686e-14" y1="2.22222222" x2="11" y2="2.22222222" id="路径-29"></line>
|
||||
<polyline id="路径-30" stroke-linejoin="round" points="3.3 2.2221179 3.3 0 7.7 0 7.7 2.22222222"></polyline>
|
||||
<path d="M1.65,2.23587458 L1.65,9 C1.65,9.55228475 2.09771525,10 2.65,10 L8.35,10 C8.90228475,10 9.35,9.55228475 9.35,9 L9.35,2.22222222 L9.35,2.22222222" id="路径-31" stroke-linejoin="round"></path>
|
||||
<line x1="4.4" y1="4.45203738" x2="4.4" y2="7.78537071" id="路径-32"></line>
|
||||
<line x1="6.6" y1="4.45203738" x2="6.6" y2="7.78537071" id="路径-32"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
20
web/src/assets/images/prompt/delete_hover.svg
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组 33</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="工作台-提示词-我的历史" transform="translate(-1002, -320)">
|
||||
<g id="编组-13备份-6" transform="translate(648, 122)">
|
||||
<g id="编组-33" transform="translate(354, 198)">
|
||||
<rect id="矩形" fill-opacity="0.08" fill="#FF5D34" x="0" y="0" width="18" height="18" rx="6"></rect>
|
||||
<g id="编组-32" transform="translate(3.5, 4)" stroke="#FF5D34">
|
||||
<line x1="-1.80133686e-14" y1="2.22222222" x2="11" y2="2.22222222" id="路径-29"></line>
|
||||
<polyline id="路径-30" stroke-linejoin="round" points="3.3 2.2221179 3.3 0 7.7 0 7.7 2.22222222"></polyline>
|
||||
<path d="M1.65,2.23587458 L1.65,9 C1.65,9.55228475 2.09771525,10 2.65,10 L8.35,10 C8.90228475,10 9.35,9.55228475 9.35,9 L9.35,2.22222222 L9.35,2.22222222" id="路径-31" stroke-linejoin="round"></path>
|
||||
<line x1="4.4" y1="4.45203738" x2="4.4" y2="7.78537071" id="路径-32"></line>
|
||||
<line x1="6.6" y1="4.45203738" x2="6.6" y2="7.78537071" id="路径-32"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
16
web/src/assets/images/prompt/edit.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编辑</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="工作台-提示词-我的历史" transform="translate(-976, -560)" stroke="#5B6167">
|
||||
<g id="编组-13备份-4" transform="translate(648, 362)">
|
||||
<g id="编辑" transform="translate(328, 198)">
|
||||
<g id="编组-10" transform="translate(4.3, 4.3)">
|
||||
<path d="M9.4,4.04322919 L9.4,7.4 C9.4,8.5045695 8.5045695,9.4 7.4,9.4 L2,9.4 C0.8954305,9.4 0,8.5045695 0,7.4 L0,2 C0,0.8954305 0.8954305,2.22044605e-16 2,0 L5.38958415,0 L5.38958415,0" id="路径"></path>
|
||||
<line x1="3.74260398" y1="5.68579764" x2="9.4" y2="1.05734433e-14" id="路径-2"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
17
web/src/assets/images/prompt/edit_bg.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编辑</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="工作台-提示词-我的历史" transform="translate(-976, -320)">
|
||||
<g id="编组-13备份-6" transform="translate(648, 122)">
|
||||
<g id="编辑" transform="translate(328, 198)">
|
||||
<rect id="矩形" fill="#EBEBEB" fill-rule="nonzero" x="0" y="0" width="18" height="18" rx="6"></rect>
|
||||
<g id="编组-10" transform="translate(4.3, 4.3)" stroke="#5B6167">
|
||||
<path d="M9.4,4.04322919 L9.4,7.4 C9.4,8.5045695 8.5045695,9.4 7.4,9.4 L2,9.4 C0.8954305,9.4 0,8.5045695 0,7.4 L0,2 C0,0.8954305 0.8954305,2.22044605e-16 2,0 L5.38958415,0 L5.38958415,0" id="路径"></path>
|
||||
<line x1="3.74260398" y1="5.68579764" x2="9.4" y2="1.05734433e-14" id="路径-2"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
16
web/src/assets/images/prompt/eye.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编辑</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="工作台-提示词-我的历史" transform="translate(-950, -560)" stroke="#5B6167">
|
||||
<g id="编组-13备份-4" transform="translate(648, 362)">
|
||||
<g id="编辑" transform="translate(302, 198)">
|
||||
<g id="编组-16" transform="translate(2.5, 4.7)">
|
||||
<ellipse id="椭圆形" cx="6.5" cy="4.3" rx="6.5" ry="4.3"></ellipse>
|
||||
<circle id="椭圆形" cx="6.5" cy="4.3" r="1.75"></circle>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 888 B |
17
web/src/assets/images/prompt/eye_bg.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编辑</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="工作台-提示词-我的历史" transform="translate(-950, -320)">
|
||||
<g id="编组-13备份-6" transform="translate(648, 122)">
|
||||
<g id="编辑" transform="translate(302, 198)">
|
||||
<rect id="矩形" fill="#EBEBEB" fill-rule="nonzero" x="0" y="0" width="18" height="18" rx="6"></rect>
|
||||
<g id="编组-16" transform="translate(2.5, 4.7)" stroke="#5B6167">
|
||||
<ellipse id="椭圆形" cx="6.5" cy="4.3" rx="6.5" ry="4.3"></ellipse>
|
||||
<circle id="椭圆形" cx="6.5" cy="4.3" r="1.75"></circle>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1011 B |
13
web/src/assets/images/workflow/clear.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>clear-outlined</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="应用管理-工作流-配置-开始" transform="translate(-1249, -24)" fill="#171719" fill-rule="nonzero">
|
||||
<g id="编组-11" transform="translate(1242, 17)">
|
||||
<g id="clear-outlined" transform="translate(7, 7)">
|
||||
<path d="M14.4933021,14.4598985 L13.6042691,9.03045685 L13.9045274,9.03045685 C14.146076,9.03045685 14.3406568,8.82436548 14.3406568,8.56852792 L14.3406568,5.15736041 C14.3406568,4.90152284 14.146076,4.69543147 13.9045274,4.69543147 L9.77807205,4.69543147 L9.77807205,1.46192893 C9.77807205,1.20609137 9.58349122,1 9.34194262,1 L6.65806921,1 C6.4165206,1 6.22193978,1.20609137 6.22193978,1.46192893 L6.22193978,4.69543147 L2.09548441,4.69543147 C1.85393581,4.69543147 1.65935498,4.90152284 1.65935498,5.15736041 L1.65935498,8.56852792 C1.65935498,8.82436548 1.85393581,9.03045685 2.09548441,9.03045685 L2.39574275,9.03045685 L1.50670968,14.4598985 C1.50167742,14.4865482 1.5,14.513198 1.5,14.5380711 C1.5,14.7939086 1.69458082,15 1.93612943,15 L14.0638824,15 C14.0890437,15 14.114205,14.9982234 14.1376889,14.9928934 C14.3758827,14.9502538 14.5352377,14.7104061 14.4933021,14.4598985 Z M2.8335496,5.93908629 L7.3961344,5.93908629 L7.3961344,2.24365482 L8.60387743,2.24365482 L8.60387743,5.93908629 L13.1664622,5.93908629 L13.1664622,7.78680203 L2.8335496,7.78680203 L2.8335496,5.93908629 Z M10.6838793,13.7563452 L10.6838793,10.9847716 C10.6838793,10.906599 10.6234922,10.8426396 10.5496857,10.8426396 L9.74452363,10.8426396 C9.67071711,10.8426396 9.61032996,10.906599 9.61032996,10.9847716 L9.61032996,13.7563452 L6.38968187,13.7563452 L6.38968187,10.9847716 C6.38968187,10.906599 6.32929472,10.8426396 6.2554882,10.8426396 L5.45032617,10.8426396 C5.37651966,10.8426396 5.3161325,10.906599 5.3161325,10.9847716 L5.3161325,13.7563452 L2.81342055,13.7563452 L3.56993737,9.13705584 L12.428397,9.13705584 L13.1849139,13.7563452 L10.6838793,13.7563452 Z" id="形状"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
32
web/src/assets/images/workflow/document-extractor.svg
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>3备份</title>
|
||||
<defs>
|
||||
<filter x="-2.9%" y="-6.6%" width="105.8%" height="118.4%" filterUnits="objectBoundingBox" id="filter-1">
|
||||
<feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||
<feGaussianBlur stdDeviation="2" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||
<feColorMatrix values="0 0 0 0 0.0901960784 0 0 0 0 0.0901960784 0 0 0 0 0.0980392157 0 0 0 0.03 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
|
||||
<feMerge>
|
||||
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
|
||||
<feMergeNode in="SourceGraphic"></feMergeNode>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="应用管理-工作流-配置-开始" transform="translate(-371, -676)">
|
||||
<g id="编组-32" transform="translate(340, 111)">
|
||||
<g id="3备份" filter="url(#filter-1)" transform="translate(19, 553)">
|
||||
<g id="编组-6" transform="translate(12, 12)">
|
||||
<rect id="矩形" fill="#02AFD5" x="0" y="0" width="24" height="24" rx="8"></rect>
|
||||
<g id="编组-36" transform="translate(6, 5.2)" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.2">
|
||||
<path d="M2.5,0 L8.21312992,-1.33226763e-15 C8.73846647,-1.33226763e-15 9.24271021,0.206694977 9.61690184,0.57542133 L11.4037719,2.33619321 C11.7852265,2.7120764 12,3.22523874 12,3.76077188 L12,11.1 C12,12.4807119 10.8807119,13.6 9.5,13.6 L2.5,13.6 C1.11928813,13.6 1.33226763e-15,12.4807119 8.8817842e-16,11.1 L0,2.5 C0,1.11928813 1.11928813,0 2.5,0 Z" id="矩形"></path>
|
||||
<path d="M8.5,0.264391446 L8.5,2.0328486 C8.5,2.86127573 9.17157288,3.5328486 10,3.5328486 L11.8153307,3.5328486 L11.8153307,3.5328486" id="路径-10"></path>
|
||||
<line x1="3.66996056" y1="6.5" x2="8.15988708" y2="6.5" id="路径-11"></line>
|
||||
<line x1="3.66996056" y1="9.5001" x2="7.0221777" y2="9.5001" id="路径-13"></line>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
15
web/src/assets/images/workflow/features.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>参与</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="应用管理-工作流-配置-开始" transform="translate(-1211, -24)" fill="#171719" fill-rule="nonzero">
|
||||
<g id="编组-11" transform="translate(1204, 17)">
|
||||
<g id="参与" transform="translate(7, 7)">
|
||||
<g id="编组-35" transform="translate(0.5, 1.5)">
|
||||
<path d="M13.3524137,3.04473843 C13.7876396,3.04473843 14.1979604,3.21975634 14.507738,3.53746403 C14.8173619,3.85501246 14.9923132,4.28005597 15,4.73408333 L15,10.2997805 C15,10.7391566 14.8365789,11.1556006 14.5400225,11.472512 C14.2665266,11.7647393 13.9083222,11.9416683 13.5224454,11.9771815 L13.5155273,13.3373525 C13.5155273,13.6047366 13.3547197,13.8526919 13.1155068,13.9536577 C13.021728,13.9861451 12.9450138,14 12.8673773,14 C12.6896587,14 12.521318,13.9261071 12.40494,13.797113 L10.6609614,11.9676263 L8.48098801,11.9676263 C8.12370606,11.9676263 7.83314543,11.6666401 7.83314543,11.2965385 C7.83314543,10.926437 8.12370606,10.6254507 8.48098801,10.6254507 L10.9635134,10.6254507 C11.1415394,10.6459942 11.2911243,10.7176576 11.3904376,10.8283378 L12.2272215,11.7015163 L12.2272215,11.2966978 C12.2272215,10.9371068 12.5239315,10.6334133 12.8750641,10.6334133 L13.3674798,10.6334133 C13.5491954,10.6334133 13.6969355,10.4803722 13.6969355,10.2921364 L13.6969355,4.72819101 C13.6969355,4.53995518 13.5491954,4.38691404 13.3674798,4.38691404 C13.0060469,4.38691404 12.7121041,4.08592781 12.7121041,3.71582623 C12.7121041,3.34588391 12.9994363,3.04473843 13.3524137,3.04473843 Z M10.4203649,0 C11.3164907,0 12.0455058,0.755172845 12.0455058,1.68345258 L12.0455058,8.25976271 C12.0455058,9.18804245 11.3131085,9.94305605 10.4129855,9.94305605 L5.13154658,9.94305605 L2.58091627,12.7683453 C2.45792764,12.9048242 2.29081685,12.9799911 2.11017731,12.9799911 C2.03346315,12.9799911 1.94675618,12.9634289 1.87234806,12.9344451 C1.62268115,12.8328423 1.462181,12.5875943 1.462181,12.3089033 L1.46940658,9.93604896 C1.08614328,9.89719148 0.730552424,9.71962553 0.459055037,9.42946844 C0.163113662,9.11319403 0,8.69770563 0,8.25960346 L0,1.68345258 C0,0.755172845 0.729015066,0 1.62514092,0 L10.4203649,0 Z M10.4208261,1.33453151 L1.62560213,1.33453151 C1.44388644,1.33453151 1.29614636,1.48757266 1.29614636,1.67580849 L1.29614636,8.25976271 C1.29614636,8.44799854 1.44388644,8.60103969 1.62560213,8.60103969 L2.14030952,8.60103969 C2.31449216,8.60103969 2.48329405,8.67588811 2.60320795,8.80663398 C2.72066209,8.93451331 2.78092651,9.10061312 2.77323973,9.27467552 C2.77323973,9.29060072 2.77293225,9.31273675 2.76570667,9.34156135 L2.75924977,10.5990149 L4.38623552,8.79532709 C4.40698985,8.76475071 4.43450856,8.74850701 4.45295685,8.73879264 L4.47217382,8.72557473 C4.48293533,8.71872689 4.49246695,8.71171981 4.50276724,8.70407571 C4.52905606,8.68464697 4.56180178,8.66028142 4.60638516,8.64483398 L4.65634929,8.63161607 L4.67326022,8.63161607 C4.70446859,8.62078693 4.73721431,8.61362059 4.76857641,8.60788752 L4.78302757,8.59291784 L10.4208261,8.59291784 C10.6025418,8.59291784 10.7502818,8.43987669 10.7502818,8.25164086 L10.7502818,1.67580849 C10.7502818,1.48757266 10.6025418,1.33453151 10.4208261,1.33453151 Z M3.1173004,4.58263471 C3.34559803,4.58263471 3.55975197,4.70939928 3.67612996,4.9132418 C3.85062007,5.22505716 4.19252844,5.51999181 4.63943835,5.74469634 C5.09157528,5.9719489 5.59213898,6.09712095 6.04904171,6.09712095 C6.99467049,6.09712095 8.05882956,5.56983768 8.42149226,4.92168216 C8.53833145,4.71688412 8.7524854,4.59011955 8.98078303,4.59011955 C9.1026955,4.59011955 9.21599877,4.62181069 9.30870145,4.68184869 C9.45797889,4.76513747 9.56497899,4.908942 9.61033104,5.08714495 C9.64815005,5.27283275 9.62339859,5.4460989 9.53976632,5.59356622 C8.85594957,6.7876375 7.23096239,7.43165247 6.04904171,7.43165247 C4.85989546,7.43165247 3.22968125,6.78477096 2.55078405,5.58608138 C2.46745926,5.43256248 2.4448601,5.24862645 2.48775238,5.07966011 C2.53125961,4.90830499 2.63549247,4.76816326 2.78892077,4.67468235 C2.89146254,4.61273333 2.99877011,4.58263471 3.1173004,4.58263471 Z" id="形状结合"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
17
web/src/assets/images/workflow/return.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>退出</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||
<g id="应用管理-工作流-配置-开始" transform="translate(-1402, -24)" stroke="#171719" stroke-width="1.2">
|
||||
<g id="退出" transform="translate(1394, 17)">
|
||||
<g transform="translate(8, 7)" id="编组-7">
|
||||
<g transform="translate(2.5, 2)">
|
||||
<path d="M4,12 L1,12 C0.44771525,12 0,11.5522847 0,11 L0,1 C0,0.44771525 0.44771525,1.11022302e-16 1,0 L4,0 L4,0" id="路径"></path>
|
||||
<line x1="11" y1="6" x2="4.5" y2="6" id="路径-6"></line>
|
||||
<polyline id="路径" points="8 3 11 6 8 9"></polyline>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
13
web/src/assets/images/workflow/run.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组 31</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||
<g id="应用管理-工作流-配置-开始" transform="translate(-1325, -24)" stroke="#171719" stroke-width="1.2">
|
||||
<g id="运行" transform="translate(1318, 17)">
|
||||
<g id="编组-31" transform="translate(7, 7)">
|
||||
<path d="M4.5,3.55424764 L4.5,12.4457524 C4.5,12.9980371 4.94771525,13.4457524 5.5,13.4457524 C5.68741972,13.4457524 5.87106734,13.3930829 6.02999894,13.2937507 L13.1432027,8.8479983 C13.6115392,8.55528797 13.7539124,7.93833759 13.4612021,7.47000106 C13.3807214,7.34123193 13.2719718,7.2324824 13.1432027,7.1520017 L6.02999894,2.70624934 C5.56166241,2.41353901 4.94471203,2.55591217 4.6520017,3.0242487 C4.55266944,3.1831803 4.5,3.36682792 4.5,3.55424764 Z" id="路径-46"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
17
web/src/assets/images/workflow/save.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>保存</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linejoin="round">
|
||||
<g id="应用管理-工作流-配置-开始" transform="translate(-1363, -24)" stroke="#171719" stroke-width="1.2">
|
||||
<g id="保存" transform="translate(1356, 17)">
|
||||
<g transform="translate(7, 7)" id="编组-12">
|
||||
<g transform="translate(2, 1.5)">
|
||||
<path d="M1.5,0 L8.66667187,0 L8.66667187,0 L12,3.60846604 L12,11.5 C12,12.3284271 11.3284271,13 10.5,13 L1.5,13 C0.671572875,13 0,12.3284271 0,11.5 L0,1.5 C0,0.671572875 0.671572875,0 1.5,0 Z" id="矩形"></path>
|
||||
<path d="M3,0.5 L3,3.5 C3,4.05228475 3.44771525,4.5 4,4.5 L8,4.5 L8,4.5" id="路径-12" stroke-linecap="round"></path>
|
||||
<path d="M3,12.5 L3,8.5 C3,7.94771525 3.44771525,7.5 4,7.5 L8,7.5 C8.55228475,7.5 9,7.94771525 9,8.5 L9,12.5 L9,12.5" id="路径" stroke-linecap="round"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
16
web/src/assets/images/workflow/variable.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>聊天</title>
|
||||
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="应用管理-工作流-配置-开始" transform="translate(-1287, -24)" fill-rule="nonzero" stroke="#171719">
|
||||
<g id="聊天变量" transform="translate(1280, 17)">
|
||||
<g id="聊天" transform="translate(7, 7)">
|
||||
<g id="编组-33" transform="translate(1, 1.5)">
|
||||
<path d="M11.6052632,0 C12.9278398,0 14,1.04117982 14,2.32554022 L14,8.58661006 C14,9.87097046 12.9278398,10.9121503 11.6052632,10.9121503 L8.14425438,10.9121503 L4.51100878,12.9285129 C4.15517545,13.1258857 3.71583334,12.8918409 3.68574562,12.504549 L3.68421053,12.4625104 L3.68421053,10.9121503 L2.39473684,10.9121503 C1.10180961,10.9121412 0.0423365236,9.91548324 0.00122806538,8.66055031 L0,8.58661006 L0,2.32554022 C0,1.04117982 1.0721602,0 2.39473684,0 L11.6052632,0 Z" id="路径" stroke-width="1.2"></path>
|
||||
<path d="M3.10551727,8.99854824 C2.95234052,9.00822601 2.799977,8.96934058 2.66928223,8.88721458 C2.56494178,8.81932801 2.5013017,8.70218572 2.5001432,8.57588036 C2.49697286,8.46736073 2.54660892,8.36427058 2.63271163,8.30054623 C2.72675055,8.23401171 2.83974645,8.20118771 2.95401049,8.20721263 C3.03564129,8.20854597 3.1172721,8.21387932 3.19824986,8.22454601 C3.35694014,8.24454607 3.51628348,8.2545461 3.67562682,8.25521277 C3.83112667,8.27120046 3.98683295,8.22694075 4.11186184,8.13121241 C4.16410556,8.07987893 4.27185823,7.91654513 4.40312057,7.39587697 L5.11428816,4.71520259 L4.23267544,4.71520259 L4.36654997,4.21386782 L5.23902003,4.21386782 L5.2625297,4.13120091 C5.35722144,3.72653308 5.51395259,3.33786529 5.72945792,2.9771976 C5.92761883,2.67678848 6.19607537,2.43160427 6.51050148,2.2638622 C6.78478099,2.10186174 7.10020243,2.01052814 7.42346042,2.00119479 C7.57300806,1.9925281 7.72059656,2.03119488 7.84402234,2.1111951 C7.94525052,2.17569025 8.00766373,2.28806964 8.00989614,2.40986263 C8.01069224,2.51180934 7.96774069,2.60900461 7.89234777,2.67586339 C7.81085766,2.74556611 7.70738041,2.78275178 7.60108905,2.78053036 C7.42610914,2.77156458 7.25231402,2.74612317 7.08191713,2.70453014 C7.00030947,2.68636718 6.91724274,2.67587883 6.83375947,2.67319672 C6.71947634,2.67319672 6.60911149,2.74853027 6.50593015,2.8985307 C6.36752518,3.1219189 6.26912558,3.36864744 6.21532448,3.62719946 L6.06969512,4.21786783 L8.21625882,4.16986769 L8.28613478,4.16986769 C8.39669858,4.15910216 8.50394314,4.21204398 8.56433257,4.30720142 C8.63094331,4.41720173 8.6799218,4.53520207 8.70930889,4.65853576 L8.76938917,4.86920303 L8.91436548,4.69853588 C9.05672961,4.51786869 9.22260341,4.35520156 9.40937469,4.21520115 C9.59991804,4.06196908 9.83046563,3.96944956 10.0722168,3.94920038 C10.1783217,3.94523919 10.2820966,3.98158171 10.3634756,4.05120068 C10.4379229,4.11786754 10.4797178,4.21120114 10.4784117,4.30853475 C10.4741349,4.42168559 10.4145328,4.52509771 10.3197214,4.58386888 C10.2642125,4.61986898 10.1740921,4.65720242 9.84822191,4.67720248 C9.70455169,4.68186916 9.5654528,4.73053597 9.45247575,4.81520288 C9.23697042,4.99520339 9.05411741,5.20653734 8.90848806,5.44053801 L8.88432534,5.47920478 L9.10962636,6.47320764 C9.19386936,6.85987542 9.46749582,7.21320976 9.63206353,7.22787648 C9.76267282,7.22787648 9.79728429,7.13454288 9.82079396,7.07187603 L9.83254879,7.04320928 C9.88011168,6.8878533 10.0218445,6.78272329 10.1812756,6.78454187 C10.2673216,6.78358385 10.3499697,6.81877904 10.4098419,6.88187549 C10.468616,6.94587567 10.5012684,7.02854258 10.5,7.11320948 C10.4888129,7.28711576 10.391227,7.44308888 10.2413559,7.52654401 L10.2282949,7.53654404 C10.0846247,7.66321107 9.89654734,7.73654461 9.69998036,7.74121129 C9.4067625,7.74787798 9.12529948,7.63587766 8.92285508,7.43454374 C8.67887201,7.16118259 8.48983209,6.84158253 8.3664595,6.49387437 L8.2920122,6.29120712 L8.15944377,6.46387428 C7.96876847,6.73669301 7.74246154,6.98162708 7.48680593,7.19187637 C7.32550345,7.31521006 7.12763038,7.38587693 6.92061465,7.39454363 C6.79266391,7.39864585 6.66722568,7.35768715 6.56535738,7.27854329 C6.47026817,7.20916987 6.41307562,7.09784149 6.41123841,6.97854243 C6.4109998,6.8823413 6.44948623,6.79026469 6.51768499,6.72387503 C6.58501907,6.65149764 6.6785137,6.61052383 6.77629139,6.61054137 C6.89383975,6.61854139 7.00159242,6.67720823 7.0675501,6.76920849 L7.14134435,6.85454208 L7.23277086,6.78454187 C7.29154504,6.73920841 7.34509484,6.68920826 7.39472637,6.63587478 C7.51227473,6.51720777 7.62198654,6.39120741 7.72190265,6.25854036 L8.14638285,5.66653866 L7.91977572,4.74386934 L5.92798404,4.71186925 L5.37877197,6.84254204 C5.19265373,7.53921071 4.89159932,8.08121227 4.48018005,8.44254664 C4.1049625,8.79485722 3.61528182,8.99291543 3.10551727,8.99854824 L3.10551727,8.99854824 Z" id="路径" stroke-width="0.4" fill="#171719"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.0 KiB |
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2025-12-10 16:46:17
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 13:32:29
|
||||
* @Last Modified time: 2026-03-27 14:17:38
|
||||
*/
|
||||
import { type FC, useRef, useEffect, useState } from 'react'
|
||||
import clsx from 'clsx'
|
||||
@@ -194,7 +194,10 @@ const ChatContent: FC<ChatContentProps> = ({
|
||||
key={idx}
|
||||
size="small"
|
||||
className="rb:text-[12px]!"
|
||||
onClick={() => window.open(`/knowledge/${citation.knowledge_id}/document/${citation.document_id}`, '_blank')}
|
||||
onClick={() => {
|
||||
const params = new URLSearchParams({ documentId: citation.document_id, parentId: citation.knowledge_id });
|
||||
window.open(`/#/knowledge-base/${citation.knowledge_id}/DocumentDetails?${params}`, '_blank');
|
||||
}}
|
||||
>{citation.file_name}</Button>
|
||||
))}
|
||||
</div>}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-03-17 14:22:25
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-23 17:42:38
|
||||
* @Last Modified time: 2026-03-27 17:54:47
|
||||
*/
|
||||
// Toolbar component for chat input area, supporting file upload, audio recording, and variable configuration
|
||||
import { useRef, forwardRef, useImperativeHandle, type ReactNode, useEffect } from 'react'
|
||||
@@ -19,6 +19,7 @@ import type { UploadFileListModalRef } from '@/views/Conversation/types'
|
||||
import type { VariableConfigModalRef } from '@/views/Workflow/types'
|
||||
import type { Variable } from '@/views/Workflow/components/Properties/VariableList/types'
|
||||
import { getFileInfoByUrl } from '@/api/fileStorage';
|
||||
import { transform_file_type } from '@/views/Conversation/components/FileUpload'
|
||||
|
||||
// Exposed methods via ref for parent components to access/set form state
|
||||
export interface ChatToolbarRef {
|
||||
@@ -126,7 +127,7 @@ const ChatToolbar = forwardRef<ChatToolbarRef, ChatToolbarProps>(({
|
||||
status: 'done',
|
||||
name: file_name,
|
||||
size: file_size,
|
||||
type: content_type,
|
||||
type: transform_file_type[content_type] || content_type,
|
||||
} : f)
|
||||
form.setFieldValue('files', updated)
|
||||
onFilesChange?.(updated)
|
||||
|
||||
106
web/src/components/DebounceSelect/index.tsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import { useRef, useState, useCallback, useEffect, type FC } from 'react';
|
||||
import { Select, Spin, Avatar } from 'antd';
|
||||
import type { SelectProps, DefaultOptionType } from 'antd/es/select';
|
||||
|
||||
import { request } from '@/utils/request';
|
||||
|
||||
interface OptionType {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
interface ApiResponse<T> {
|
||||
items?: T[];
|
||||
}
|
||||
|
||||
export interface DebounceSelectProps extends Omit<SelectProps, 'options'> {
|
||||
/** API endpoint URL — mutually exclusive with fetchOptions */
|
||||
url?: string;
|
||||
/** Extra query params merged with the search keyword */
|
||||
params?: Record<string, unknown>;
|
||||
/** Key used as option value */
|
||||
valueKey?: string;
|
||||
/** Key used as option label */
|
||||
labelKey?: string;
|
||||
/** Key name sent to the API for the search keyword */
|
||||
searchKey?: string;
|
||||
/** Custom fetch function — mutually exclusive with url */
|
||||
fetchOptions?: (search: string | null) => Promise<DefaultOptionType[]>;
|
||||
/** Transform raw API items before rendering */
|
||||
format?: (items: OptionType[]) => OptionType[];
|
||||
debounceTimeout?: number;
|
||||
}
|
||||
|
||||
const DebounceSelect: FC<DebounceSelectProps> = ({
|
||||
url,
|
||||
params = { page: 1, pagesize: 20 },
|
||||
valueKey = 'value',
|
||||
labelKey = 'label',
|
||||
searchKey = 'search',
|
||||
fetchOptions,
|
||||
format,
|
||||
debounceTimeout = 300,
|
||||
...props
|
||||
}) => {
|
||||
const [fetching, setFetching] = useState(false);
|
||||
const [options, setOptions] = useState<DefaultOptionType[]>([]);
|
||||
const fetchRef = useRef(0);
|
||||
|
||||
const timerRef = useRef<ReturnType<typeof setTimeout>>();
|
||||
|
||||
// Load initial options on mount
|
||||
useEffect(() => {
|
||||
debounceFetcher(null);
|
||||
}, []);
|
||||
|
||||
const debounceFetcher = useCallback((keyword: string | null) => {
|
||||
clearTimeout(timerRef.current);
|
||||
timerRef.current = setTimeout(() => {
|
||||
fetchRef.current += 1;
|
||||
const fetchId = fetchRef.current;
|
||||
setOptions([]);
|
||||
setFetching(true);
|
||||
|
||||
const promise: Promise<DefaultOptionType[]> = fetchOptions
|
||||
? fetchOptions(keyword)
|
||||
: request
|
||||
.get<ApiResponse<OptionType>>(url!, { ...params, [searchKey]: keyword })
|
||||
.then((res) => {
|
||||
const data: OptionType[] = Array.isArray(res) ? res : res?.items || [];
|
||||
const formatted = format ? format(data) : data.map((item) => ({
|
||||
label: item[labelKey],
|
||||
value: item[valueKey],
|
||||
avatar: item.avatar,
|
||||
raw: item,
|
||||
}));
|
||||
return formatted;
|
||||
});
|
||||
|
||||
promise
|
||||
.then((newOptions) => {
|
||||
if (fetchId !== fetchRef.current) return;
|
||||
setOptions(newOptions);
|
||||
setFetching(false);
|
||||
})
|
||||
.catch(() => setFetching(false));
|
||||
}, debounceTimeout);
|
||||
}, [url, params, searchKey, fetchOptions, format, valueKey, labelKey, debounceTimeout]);
|
||||
|
||||
return (
|
||||
<Select
|
||||
labelInValue
|
||||
filterOption={false}
|
||||
onSearch={debounceFetcher}
|
||||
notFoundContent={fetching ? <Spin size="small" /> : null}
|
||||
{...props}
|
||||
options={options}
|
||||
optionRender={(option) => (
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
{option.data.avatar && <Avatar src={option.data.avatar} size="small" />}
|
||||
{option.label}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default DebounceSelect;
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:02:47
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-02 15:47:24
|
||||
* @Last Modified time: 2026-03-26 14:58:24
|
||||
*/
|
||||
/**
|
||||
* BodyWrapper Component
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px 24px 16px 20px;
|
||||
height: 64px;
|
||||
color: #212332;
|
||||
z-index: 0;
|
||||
font-size: 14px;
|
||||
@@ -25,4 +24,26 @@
|
||||
.header :global(.ant-breadcrumb .ant-breadcrumb-item:last-child a) {
|
||||
color: #212332;
|
||||
font-weight: 600;
|
||||
}
|
||||
.userDropdown:global(.ant-dropdown .ant-dropdown-menu),
|
||||
.userDropdown:global(.ant-dropdown-menu-submenu .ant-dropdown-menu) {
|
||||
padding: 12px 8px;
|
||||
}
|
||||
.userDropdown:global(.ant-dropdown .ant-dropdown-menu .ant-dropdown-menu-item),
|
||||
.userDropdown:global(.ant-dropdown-menu-submenu .ant-dropdown-menu .ant-dropdown-menu-item),
|
||||
.userDropdown:global(.ant-dropdown .ant-dropdown-menu .ant-dropdown-menu-submenu-title),
|
||||
.userDropdown:global(.ant-dropdown-menu-submenu .ant-dropdown-menu .ant-dropdown-menu-submenu-title) {
|
||||
padding-left: 8px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
.userDropdown:global(.ant-dropdown .ant-dropdown-menu .ant-dropdown-menu-item.ant-dropdown-menu-item-danger:not(.ant-dropdown-menu-item-disabled):hover),
|
||||
.userDropdown:global(.ant-dropdown-menu-submenu .ant-dropdown-menu .ant-dropdown-menu-item.ant-dropdown-menu-item-danger:not(.ant-dropdown-menu-item-disabled):hover) {
|
||||
background-color: #F6F6F6;
|
||||
color: #FF5D34;
|
||||
}
|
||||
.userDropdown:global(.ant-dropdown .ant-dropdown-menu .ant-dropdown-menu-item-divider),
|
||||
.userDropdown:global(.ant-dropdown-menu-submenu .ant-dropdown-menu .ant-dropdown-menu-item-divider),
|
||||
.userDropdown:global(.ant-dropdown .ant-dropdown-menu .ant-dropdown-menu-submenu-title-divider),
|
||||
.userDropdown:global(.ant-dropdown-menu-submenu .ant-dropdown-menu .ant-dropdown-menu-submenu-title-divider) {
|
||||
margin: 10px 8px;
|
||||
}
|
||||
@@ -13,12 +13,12 @@
|
||||
* @component
|
||||
*/
|
||||
|
||||
import { type FC, useRef } from 'react';
|
||||
import { Layout, Dropdown, Breadcrumb } from 'antd';
|
||||
import { type FC, useRef, useState } from 'react';
|
||||
import { Layout, Dropdown, Breadcrumb, Flex } from 'antd';
|
||||
import type { MenuProps, BreadcrumbProps } from 'antd';
|
||||
import { UserOutlined, LogoutOutlined, SettingOutlined } from '@ant-design/icons';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import { useUser } from '@/store/user';
|
||||
import { useMenu } from '@/store/menu';
|
||||
@@ -76,27 +76,39 @@ const AppHeader: FC<{source?: 'space' | 'manage';}> = ({source = 'manage'}) => {
|
||||
const userMenuItems: MenuProps['items'] = [
|
||||
{
|
||||
key: '1',
|
||||
icon: <Flex align="center" justify="center" className="rb:size-10 rb:rounded-xl rb:bg-[#155EEF] rb:text-white">
|
||||
{/[\u4e00-\u9fa5]/.test(user.username) ? user.username.slice(0, 2) : user.username[0]}
|
||||
</Flex>,
|
||||
label: (<>
|
||||
<div>{user.username}</div>
|
||||
<div className="rb:text-[12px] rb:text-[#5B6167] rb:mt-2">{user.email}</div>
|
||||
<div className="rb:text-[#212332] rb:leading-5">{user.username}</div>
|
||||
<div className="rb:text-[12px] rb:text-[#7B8085] rb:leading-4.5 rb:mt-0.5 rb:mr-2">{user.email}</div>
|
||||
</>),
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
type: 'divider',
|
||||
className: 'rb:bg-[#EBEBEB]!'
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
icon: <UserOutlined />,
|
||||
label: t('header.userInfo'),
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/menuNew/userInfo.svg')]"></div>,
|
||||
label: <Flex justify="space-between" align="center">
|
||||
{t('header.userInfo')}
|
||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/menuNew/arrow_t_r.svg')]"></div>
|
||||
</Flex>,
|
||||
className: 'rb:text-[#212332]!',
|
||||
onClick: () => {
|
||||
userInfoModalRef.current?.handleOpen()
|
||||
},
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
icon: <SettingOutlined />,
|
||||
label: t('header.settings'),
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/menuNew/settings.svg')]"></div>,
|
||||
label: <Flex justify="space-between" align="center">
|
||||
{t('header.settings')}
|
||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/menuNew/arrow_t_r.svg')]"></div>
|
||||
</Flex>,
|
||||
className: 'rb:text-[#212332]!',
|
||||
onClick: () => {
|
||||
settingModalRef.current?.handleOpen()
|
||||
},
|
||||
@@ -104,12 +116,14 @@ const AppHeader: FC<{source?: 'space' | 'manage';}> = ({source = 'manage'}) => {
|
||||
{
|
||||
key: '5',
|
||||
type: 'divider',
|
||||
className: 'rb:bg-[#EBEBEB]!'
|
||||
},
|
||||
{
|
||||
key: '6',
|
||||
icon: <LogoutOutlined />,
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/menuNew/logout_red.svg')]"></div>,
|
||||
label: t('header.logout'),
|
||||
danger: true,
|
||||
className: 'rb:hover:rb:bg-transparent rb:hover:text-[#FF5D34]!',
|
||||
onClick: handleLogout,
|
||||
},
|
||||
];
|
||||
@@ -147,18 +161,34 @@ const AppHeader: FC<{source?: 'space' | 'manage';}> = ({source = 'manage'}) => {
|
||||
});
|
||||
}
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const handleOpenChange = (open: boolean) => {
|
||||
setOpen(open);
|
||||
}
|
||||
return (
|
||||
<Header className={styles.header}>
|
||||
{/* Breadcrumb navigation */}
|
||||
<Breadcrumb separator="<" items={formatBreadcrumbNames() as BreadcrumbProps['items']} className="rb:font-medium!" />
|
||||
{/* User info dropdown menu */}
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: userMenuItems
|
||||
}}
|
||||
>
|
||||
<div className="rb:cursor-pointer rb:font-medium">{user.username}</div>
|
||||
</Dropdown>
|
||||
{user.username && (
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: userMenuItems
|
||||
}}
|
||||
onOpenChange={handleOpenChange}
|
||||
overlayClassName={styles.userDropdown}
|
||||
>
|
||||
<Flex align="center" className="rb:cursor-pointer rb:font-medium">
|
||||
<Flex align="center" justify="center" className="rb:size-8 rb:rounded-xl rb:bg-[#155EEF] rb:text-white rb:mr-2!">
|
||||
{/[\u4e00-\u9fa5]/.test(user.username) ? user.username.slice(0, 2) : user.username[0]}
|
||||
</Flex>
|
||||
<span className="rb:text-[#212332] rb:text-[12px] rb:leading-4 rb:mr-1">{user.username}</span>
|
||||
<div className={clsx("rb:size-3 rb:bg-cover rb:bg-[url('@/assets/images/common/arrow_up.svg')]", {
|
||||
'rb:rotate-180': !open,
|
||||
})}></div>
|
||||
</Flex>
|
||||
</Dropdown>
|
||||
)}
|
||||
<SettingModal
|
||||
ref={settingModalRef}
|
||||
/>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:11:02
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-03 18:43:42
|
||||
* @Last Modified time: 2026-03-26 15:01:02
|
||||
*/
|
||||
/**
|
||||
* AuthLayout Component
|
||||
@@ -54,14 +54,14 @@ const AuthLayout: FC = () => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Layout style={{ minHeight: '100vh' }}>
|
||||
<Layout className="rb:min-h-screen!">
|
||||
{/* Sidebar navigation */}
|
||||
<Sider />
|
||||
<Layout style={{maxHeight: '100vh', width: '100vh', overflowY: 'auto' }}>
|
||||
<Layout className="rb:max-h-screen! rb:w-screen! rb:overflow-y-auto!">
|
||||
{/* Header with breadcrumbs and user menu */}
|
||||
<AppHeader />
|
||||
{/* Main content area - renders child routes */}
|
||||
<Content style={{ padding: '0 12px 20px 12px', zIndex: 0 }}>
|
||||
<Content className="rb:px-3! rb:pb-3! rb:z-0! rb:flex-1!">
|
||||
<Outlet />
|
||||
</Content>
|
||||
</Layout>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:11:43
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-05 14:57:08
|
||||
* @Last Modified time: 2026-03-26 15:00:54
|
||||
*/
|
||||
/**
|
||||
* AuthSpaceLayout Component
|
||||
@@ -56,14 +56,14 @@ const AuthSpaceLayout: FC = () => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Layout style={{ minHeight: '100vh' }}>
|
||||
<Layout className="rb:min-h-screen!">
|
||||
{/* Sidebar navigation configured for space mode */}
|
||||
<Sider source="space" />
|
||||
<Layout style={{maxHeight: '100vh', width: '100vh', overflowY: 'auto' }}>
|
||||
<Layout className="rb:max-h-screen! rb:w-screen! rb:overflow-y-auto!">
|
||||
{/* Header with breadcrumbs and user menu configured for space mode */}
|
||||
<AppHeader source="space" />
|
||||
{/* Main content area for knowledge base pages - renders child routes */}
|
||||
<Content style={{ padding: '0 12px 12px 12px', zIndex: 0, height: 'calc(100vh - 64px)', overflowY: 'auto' }}>
|
||||
<Content className="rb:px-3! rb:pb-3! rb:z-0! rb:flex-1! rb:overflow-y-auto!">
|
||||
<Outlet />
|
||||
</Content>
|
||||
</Layout>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:12:42
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-28 17:28:41
|
||||
* @Last Modified time: 2026-03-26 15:36:25
|
||||
*/
|
||||
/**
|
||||
* BasicAuthLayout Component
|
||||
@@ -35,7 +35,7 @@ const BasicAuthLayout: FC = () => {
|
||||
}, [getUserInfo]);
|
||||
|
||||
return (
|
||||
<div className="rb:relative rb:h-full rb:w-full">
|
||||
<div className="rb:relative rb:min-h-screen rb:w-screen">
|
||||
{/* Render child routes without additional UI */}
|
||||
<Outlet />
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-10 11:08:27
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 11:19:48
|
||||
* @Last Modified time: 2026-03-26 15:38:31
|
||||
*/
|
||||
/*
|
||||
* PageHeader Component
|
||||
@@ -43,7 +43,7 @@ const PageHeader: FC<ConfigHeaderProps> = ({
|
||||
}) => {
|
||||
return (
|
||||
// Main header container: full width, 64px height, flex layout with space between
|
||||
<Header className={`rb:w-full rb:h-16 rb:grid rb:grid-cols-${extra && centerContent ? '3' : ((extra && !centerContent) || (!extra && centerContent)) ? '2': 1} rb:gap-6 rb:px-4! rb:bg-white!`}>
|
||||
<Header className={`rb:w-full rb:h-16! rb:grid rb:grid-cols-${extra && centerContent ? '3' : ((extra && !centerContent) || (!extra && centerContent)) ? '2': 1} rb:gap-6 rb:px-4! rb:bg-white!`}>
|
||||
<Flex align="center" gap={8}>
|
||||
{avatarUrl
|
||||
? <img src={avatarUrl} alt={avatarUrl} className="rb:size-8 rb:rounded-lg rb:mr-2" />
|
||||
@@ -58,7 +58,7 @@ const PageHeader: FC<ConfigHeaderProps> = ({
|
||||
{operation}
|
||||
</Flex>
|
||||
|
||||
{centerContent && <Flex align="center">
|
||||
{centerContent && <Flex align="center" justify="center">
|
||||
{centerContent}
|
||||
</Flex>}
|
||||
{/* Right section: Extra content (buttons, filters, etc.) */}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:18:19
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-19 20:47:34
|
||||
* @Last Modified time: 2026-03-27 15:52:37
|
||||
*/
|
||||
/**
|
||||
* PageScrollList Component
|
||||
@@ -56,9 +56,10 @@ interface PageScrollListProps<T, Q = Record<string, unknown>> {
|
||||
/** Additional CSS classes */
|
||||
className?: string;
|
||||
needLoading?: boolean;
|
||||
heightClass?: string;
|
||||
}
|
||||
|
||||
const heightClass = 'rb:h-[calc(100vh-124px)]!';
|
||||
const defaultHeightClass = 'rb:h-[calc(100vh-116px)]!';
|
||||
|
||||
/** Infinite scroll list component with pagination support */
|
||||
const PageScrollList = forwardRef(<T, Q = Record<string, unknown>>({
|
||||
@@ -68,6 +69,7 @@ const PageScrollList = forwardRef(<T, Q = Record<string, unknown>>({
|
||||
column = 4,
|
||||
className = '',
|
||||
needLoading = true,
|
||||
heightClass,
|
||||
}: PageScrollListProps<T, Q>, ref: React.Ref<PageScrollListRef>) => {
|
||||
/** Expose refresh method to parent component */
|
||||
useImperativeHandle(ref, () => ({
|
||||
@@ -140,13 +142,13 @@ const PageScrollList = forwardRef(<T, Q = Record<string, unknown>>({
|
||||
<div
|
||||
ref={scrollRef}
|
||||
id="scrollableDiv"
|
||||
className={`rb:overflow-y-auto rb:overflow-x-hidden ${heightClass} ${className}`}
|
||||
className={`rb:overflow-y-auto rb:overflow-x-hidden ${heightClass || defaultHeightClass} ${className}`}
|
||||
>
|
||||
<InfiniteScroll
|
||||
dataLength={data.length}
|
||||
next={() => loadMoreData()}
|
||||
hasMore={hasMore}
|
||||
loader={loading && needLoading ? <PageLoading className={heightClass} /> : false}
|
||||
loader={loading && needLoading ? <PageLoading className={heightClass || defaultHeightClass} /> : false}
|
||||
// endMessage={<Divider plain>It is all, nothing more 🤐</Divider>}
|
||||
scrollableTarget="scrollableDiv"
|
||||
className='rb:h-full!'
|
||||
@@ -154,7 +156,7 @@ const PageScrollList = forwardRef(<T, Q = Record<string, unknown>>({
|
||||
{/* Render grid list or empty state */}
|
||||
{data.length > 0 ? (
|
||||
<Row
|
||||
gutter={[16, 16]}
|
||||
gutter={[12, 12]}
|
||||
>
|
||||
{data.map((item, index) => (
|
||||
<Col key={(item as any).id || index} span={24/column}>
|
||||
@@ -162,7 +164,7 @@ const PageScrollList = forwardRef(<T, Q = Record<string, unknown>>({
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
) : !loading ? <PageEmpty className={heightClass} /> : null}
|
||||
) : !loading ? <PageEmpty className={heightClass || defaultHeightClass} /> : null}
|
||||
</InfiniteScroll>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:25:31
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 12:32:58
|
||||
* @Last Modified time: 2026-03-27 19:11:43
|
||||
*/
|
||||
/**
|
||||
* SiderMenu Component
|
||||
@@ -128,11 +128,35 @@ const Menu: FC<{
|
||||
|
||||
/** Filter menus based on user role and source */
|
||||
useEffect(() => {
|
||||
let menuList: MenuItem[] = []
|
||||
|
||||
if (user.role === 'member' && source === 'space') {
|
||||
setMenus((allMenus[source] || []).filter(menu => menu.code !== 'member'))
|
||||
menuList = (allMenus[source] || []).filter(menu => menu.code !== 'member')
|
||||
} else if (user) {
|
||||
setMenus(allMenus[source] || [])
|
||||
menuList = allMenus[source] || []
|
||||
}
|
||||
|
||||
const noAuthList = ['user', 'pricing'].filter(vo => !user.permissions?.includes(vo) && !user.permissions?.includes('all'))
|
||||
|
||||
if (noAuthList && !noAuthList?.includes('all')) {
|
||||
const filterMenus = (list: MenuItem[]): MenuItem[] =>{
|
||||
const filterList = list?.filter(menu => !noAuthList?.includes(menu.code as string))
|
||||
|
||||
const showList: MenuItem[] = []
|
||||
filterList?.forEach(menu => {
|
||||
const filteredSubs = filterMenus(menu.subs || [])
|
||||
const hadSubs = menu.subs && menu.subs.length > 0
|
||||
if (hadSubs && filteredSubs.length === 0) return
|
||||
if (menu.type === 'group' && (!menu.subs || menu.subs?.length < 1)) return
|
||||
showList.push({ ...menu, subs: filteredSubs })
|
||||
})
|
||||
|
||||
return showList
|
||||
}
|
||||
menuList = filterMenus(menuList)
|
||||
}
|
||||
|
||||
setMenus(menuList)
|
||||
}, [source, allMenus, user])
|
||||
|
||||
/** Handle menu item click and navigate to path */
|
||||
@@ -153,7 +177,7 @@ const Menu: FC<{
|
||||
const iconKey = selectedKeys.includes(menu.path || '') ? `${menu.code}Active` : menu.code;
|
||||
const iconSrc = iconPathMap[iconKey as keyof typeof iconPathMap];
|
||||
const subs = (menu.subs || []).filter(sub => sub.display);
|
||||
|
||||
|
||||
/** Leaf node - menu item without children */
|
||||
if (!subs || subs.length === 0) {
|
||||
if (menu.path) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-02 15:29:46
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 17:11:55
|
||||
* @Last Modified time: 2026-03-26 14:52:23
|
||||
*/
|
||||
/**
|
||||
* RbTable Component
|
||||
@@ -199,7 +199,7 @@ const RbTable = forwardRef(<T = Record<string, unknown>, Q = Record<string, unkn
|
||||
if (scrollY !== undefined) {
|
||||
config.y = scrollY;
|
||||
} else if (isScroll) {
|
||||
config.y = 'calc(100vh - 232px)';
|
||||
config.y = 'calc(100vh - 224px)';
|
||||
}
|
||||
|
||||
return Object.keys(config).length > 0 ? config : undefined;
|
||||
|
||||
@@ -980,6 +980,7 @@ export const en = {
|
||||
scene_id: 'Ontology Scenario',
|
||||
},
|
||||
member: {
|
||||
memberList: 'Member List',
|
||||
username: 'Username',
|
||||
account: 'Account',
|
||||
role: 'Role',
|
||||
@@ -1908,7 +1909,8 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re
|
||||
permissionInfo: 'Permission Information',
|
||||
is_expired: 'Status',
|
||||
active: 'Active',
|
||||
inactive: 'Expired'
|
||||
inactive: 'Expired',
|
||||
noScopes: 'There is no permission information here…',
|
||||
},
|
||||
tool: {
|
||||
mcp: 'MCP Services',
|
||||
|
||||
@@ -1375,6 +1375,7 @@ export const zh = {
|
||||
scene_id: '本体场景',
|
||||
},
|
||||
member: {
|
||||
memberList: '成员列表',
|
||||
username: '用户名',
|
||||
account: '账号',
|
||||
role: '角色',
|
||||
@@ -1905,7 +1906,8 @@ export const zh = {
|
||||
permissionInfo: '授权信息',
|
||||
is_expired: '状态',
|
||||
active: '活跃',
|
||||
inactive: '过期'
|
||||
inactive: '过期',
|
||||
noScopes: '暂无权限信息…',
|
||||
},
|
||||
tool: {
|
||||
mcp: 'MCP 服务',
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
"code": "systemSettings",
|
||||
"label": "systemSettings",
|
||||
"i18nKey": "menu.systemSettings",
|
||||
"path": "/",
|
||||
"path": null,
|
||||
"enable": true,
|
||||
"display": true,
|
||||
"level": 1,
|
||||
|
||||
@@ -32,7 +32,7 @@ export const lightTheme: ThemeConfig = {
|
||||
bodyBg: '#EEEFF4',
|
||||
siderBg: '#FAFCFF',
|
||||
headerPadding: '0 24px 0 20px',
|
||||
headerHeight: 64,
|
||||
headerHeight: 56,
|
||||
headerColor: '#212332',
|
||||
},
|
||||
Menu: {
|
||||
|
||||
@@ -88,17 +88,15 @@ body {
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ant-menu-light .ant-menu-item {
|
||||
font-weight: 500;
|
||||
}
|
||||
.ant-menu-light .ant-menu-item-selected,
|
||||
.ant-menu-light>.ant-menu .ant-menu-item-selected,
|
||||
.ant-menu-light:not(.ant-menu-horizontal) .ant-menu-item:not(.ant-menu-item-selected):hover,
|
||||
.ant-menu-light>.ant-menu:not(.ant-menu-horizontal) .ant-menu-item:not(.ant-menu-item-selected):hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
.ant-menu-light .ant-menu-item-selected,
|
||||
.ant-menu-light>.ant-menu .ant-menu-item-selected {
|
||||
font-weight: 500;
|
||||
}
|
||||
.ant-menu-inline-collapsed-tooltip .ant-tooltip-arrow {
|
||||
display: none;
|
||||
}
|
||||
@@ -380,6 +378,11 @@ body {
|
||||
.ant-select-filled:not(.ant-select-customize-input) .ant-select-selector {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
.ant-input-filled:hover,
|
||||
.ant-select-filled:not(.ant-select-customize-input) .ant-select-selector {
|
||||
background-color: #FFFFFF;
|
||||
border-color: #171719;
|
||||
}
|
||||
.ant-checkbox .ant-checkbox-inner {
|
||||
border-radius: 6px !important;
|
||||
}
|
||||
@@ -392,4 +395,17 @@ body {
|
||||
.ant-dropdown-menu-submenu .ant-dropdown-menu .ant-dropdown-menu-submenu-title-selected {
|
||||
color: #FFFFFF;
|
||||
background-color: #171719;
|
||||
}
|
||||
.ant-dropdown .ant-dropdown-menu .ant-dropdown-menu-item.ant-dropdown-menu-item-danger:not(.ant-dropdown-menu-item-disabled):hover,
|
||||
.ant-dropdown-menu-submenu .ant-dropdown-menu .ant-dropdown-menu-item.ant-dropdown-menu-item-danger:not(.ant-dropdown-menu-item-disabled):hover {
|
||||
background-color: #F6F6F6;
|
||||
color: #FF5D34;
|
||||
}
|
||||
|
||||
.spin.ant-spin-nested-loading .ant-spin-container::after {
|
||||
background: transparent;
|
||||
}
|
||||
.upload-block,
|
||||
.upload-block.ant-upload-wrapper .ant-upload-select {
|
||||
display: block;
|
||||
}
|
||||
@@ -6,20 +6,22 @@
|
||||
*/
|
||||
import React, { useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, App, Space } from 'antd';
|
||||
import { Button, App, Dropdown, Flex } from 'antd';
|
||||
import clsx from 'clsx';
|
||||
import { DeleteOutlined, EditOutlined, EyeOutlined } from '@ant-design/icons';
|
||||
import copy from 'copy-to-clipboard'
|
||||
import type { MenuInfo } from 'rc-menu/lib/interface';
|
||||
|
||||
import type { ApiKey, ApiKeyModalRef } from './types';
|
||||
import ApiKeyModal from './components/ApiKeyModal';
|
||||
import ApiKeyDetailModal from './components/ApiKeyDetailModal';
|
||||
import RbCard from '@/components/RbCard/Card'
|
||||
import RbCard from '@/components/RbCard'
|
||||
import { getApiKeyListUrl, deleteApiKey } from '@/api/apiKey';
|
||||
import PageScrollList, { type PageScrollListRef } from '@/components/PageScrollList'
|
||||
import { formatDateTime } from '@/utils/format';
|
||||
import Tag from '@/components/Tag'
|
||||
import { maskApiKeys } from '@/utils/apiKeyReplacer';
|
||||
import RbDescriptions from '@/components/RbDescriptions';
|
||||
|
||||
/**
|
||||
* API Key Management page component
|
||||
@@ -87,59 +89,85 @@ const ApiKeyManagement: React.FC = () => {
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<div className="rb:flex rb:justify-end rb:mb-3 rb:p-4">
|
||||
<Flex justify="flex-end" className="rb:mb-3!">
|
||||
<Button type="primary" onClick={() => handleEdit()}>
|
||||
{t('apiKey.createApiKey')}
|
||||
</Button>
|
||||
</div>
|
||||
</Flex>
|
||||
|
||||
<PageScrollList<ApiKey, { is_active: boolean; type: string }>
|
||||
ref={scrollListRef}
|
||||
url={getApiKeyListUrl}
|
||||
query={{ is_active: true, type: 'service' }}
|
||||
column={2}
|
||||
column={3}
|
||||
renderItem={(apiKeyItem) => {
|
||||
return (
|
||||
<RbCard
|
||||
title={apiKeyItem.name}
|
||||
>
|
||||
{['id', 'is_expired', 'created_at'].map((key, index) => (
|
||||
<div key={key} className={clsx("rb:flex rb:justify-between rb:gap-5 rb:font-regular rb:text-[14px]", {
|
||||
'rb:mt-3': index !== 0
|
||||
})}>
|
||||
<span className="rb:text-[#5B6167] rb:w-20">{t(`apiKey.${key}`)}</span>
|
||||
<span className="rb:flex-1 rb:text-left rb:py-px rb:rounded rb:font-medium">
|
||||
{ key === 'created_at'
|
||||
? formatDateTime(apiKeyItem[key], 'YYYY-MM-DD HH:mm:ss')
|
||||
: key === 'is_expired'
|
||||
? <Tag color={apiKeyItem[key] ? 'error' : 'processing'}>{apiKeyItem[key] ? t('apiKey.inactive') : t('apiKey.active')}</Tag>
|
||||
: String(apiKeyItem[key as keyof ApiKey])
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
<RbCard
|
||||
title={
|
||||
<Flex justify="space-between">
|
||||
<Flex gap={4} vertical>
|
||||
{apiKeyItem.name}
|
||||
<Flex gap={6}>
|
||||
{apiKeyItem.scopes?.includes('memory') && <Tag>{t('apiKey.memoryEngine')}</Tag>}
|
||||
{apiKeyItem.scopes?.includes('rag') && <Tag color="success">{t('apiKey.knowledgeBase')}</Tag>}
|
||||
{!apiKeyItem.scopes?.includes('memory') && !apiKeyItem.scopes?.includes('rag') && <div>{t('apiKey.noScopes')}</div>}
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: 'edit',
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:cursor-pointer rb:bg-[url('@/assets/images/common/edit_bold.svg')]" />,
|
||||
label: t('common.edit'),
|
||||
onClick: () => handleEdit(apiKeyItem),
|
||||
},
|
||||
{
|
||||
key: 'view',
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:cursor-pointer rb:bg-[url('@/assets/images/common/eye.svg')]" />,
|
||||
label: t('common.view'),
|
||||
onClick: () => handleView(apiKeyItem),
|
||||
},
|
||||
{
|
||||
key: 'delete',
|
||||
danger: true,
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:cursor-pointer rb:bg-[url('@/assets/images/common/delete_red_big.svg')]" />,
|
||||
label: t('common.delete'),
|
||||
onClick: () => handleDelete(apiKeyItem),
|
||||
},
|
||||
]
|
||||
}}
|
||||
placement="bottomRight"
|
||||
>
|
||||
<div className="rb:cursor-pointer rb:size-5.5 rb:bg-[url('@/assets/images/common/more.svg')] rb:hover:bg-[url('@/assets/images/common/more_hover.svg')]"></div>
|
||||
</Dropdown>
|
||||
</Flex>
|
||||
}
|
||||
isNeedTooltip={false}
|
||||
headerClassName="rb:min-h-[78px]!"
|
||||
>
|
||||
<RbDescriptions
|
||||
items={['id', 'is_expired', 'created_at'].map(key => ({
|
||||
key,
|
||||
label: t(`apiKey.${key}`),
|
||||
children: <span className={clsx({
|
||||
'rb:font-medium': key === 'id',
|
||||
})}>
|
||||
{key === 'created_at'
|
||||
? formatDateTime(apiKeyItem[key], 'YYYY-MM-DD HH:mm:ss')
|
||||
: key === 'is_expired'
|
||||
? <Tag color={apiKeyItem[key] ? 'error' : 'processing'}>{apiKeyItem[key] ? t('apiKey.inactive') : t('apiKey.active')}</Tag>
|
||||
: String(apiKeyItem[key as keyof ApiKey])
|
||||
}
|
||||
</span>
|
||||
}))}
|
||||
/>
|
||||
|
||||
<div className="rb:flex rb:items-center rb:justify-between rb:text-[#5B6167] rb:mt-5 rb:p-[8px_16px] rb:bg-[#FFFFFF] rb:border rb:border-[#DFE4ED] rb:rounded-lg rb:leading-5">
|
||||
{maskApiKeys(apiKeyItem.api_key)}
|
||||
|
||||
<Button className="rb:px-2! rb:h-7! rb:group" onClick={() => handleCopy(apiKeyItem.api_key)}>
|
||||
<div
|
||||
className="rb:w-4 rb:h-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/copy.svg')] rb:group-hover:bg-[url('@/assets/images/copy_active.svg')]"
|
||||
></div>
|
||||
{t('common.copy')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Space className="rb:pt-2 rb:min-h-6.25">
|
||||
{apiKeyItem.scopes?.includes('memory') && <Tag>{t('apiKey.memoryEngine')}</Tag>}
|
||||
{apiKeyItem.scopes?.includes('rag') && <Tag color="success">{t('apiKey.knowledgeBase')}</Tag>}
|
||||
</Space>
|
||||
|
||||
<div className="rb:mt-5 rb:flex rb:justify-end rb:gap-2.5">
|
||||
<Button icon={<EyeOutlined />} onClick={() => handleView(apiKeyItem)}></Button>
|
||||
<Button icon={<EditOutlined />} onClick={() => handleEdit(apiKeyItem)}></Button>
|
||||
<Button icon={<DeleteOutlined />} onClick={() => handleDelete(apiKeyItem)}></Button>
|
||||
</div>
|
||||
<Flex align="center" justify="space-between" className="rb:h-8! rb:mt-4! rb:py-1! rb:pl-2.5! rb:pr-1! rb:bg-[#F6F6F6] rb:rounded-md rb:leading-5">
|
||||
{maskApiKeys(apiKeyItem.api_key)}
|
||||
|
||||
<div onClick={() => handleCopy(apiKeyItem.api_key)} className="rb:cursor-pointer rb:rounded-md rb:size-6 rb:bg-[url('@/assets/images/common/copy_dark.svg')] rb:bg-size-[16px_16px] rb:bg-center rb:bg-no-repeat" style={{ backgroundColor: 'rgba(0,0,0,0.08)' }}></div>
|
||||
</Flex>
|
||||
</RbCard>
|
||||
);
|
||||
}}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:29:21
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 12:13:33
|
||||
* @Last Modified time: 2026-03-27 18:13:51
|
||||
*/
|
||||
import { useEffect, useRef, useState, forwardRef, useImperativeHandle, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -44,6 +44,14 @@ import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
|
||||
import DescWrapper from '@/components/FormItem/DescWrapper'
|
||||
import FeaturesConfig from './components/FeaturesConfig'
|
||||
import { getListLogoUrl } from '@/views/ModelManagement/utils';
|
||||
import type { ChatItem } from '@/components/Chat/types'
|
||||
|
||||
export const replaceVariables = (statement: string, variables: Variable[]) => {
|
||||
return statement.replace(/\{\{([^}]+)\}\}/g, (match, name) => {
|
||||
const v = variables.find(item => item.name === name)
|
||||
return v?.value != null && v.value !== '' ? String(v.value) : match
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Agent configuration component
|
||||
@@ -148,8 +156,9 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
model_parameters: {...rest}
|
||||
})
|
||||
if (default_model_config_id === values?.default_model_config_id) {
|
||||
const label = defaultModel?.id === default_model_config_id && defaultModel?.name ? defaultModel.name : vo.label || ''
|
||||
setChatList([{
|
||||
label: defaultModel?.id === default_model_config_id && defaultModel?.name ? defaultModel.name : vo.label || '',
|
||||
label: label,
|
||||
model_config_id: default_model_config_id || '',
|
||||
model_parameters: {...rest},
|
||||
list: []
|
||||
@@ -246,7 +255,7 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
saveAgentConfig(data.app_id, params)
|
||||
.then((res) => {
|
||||
if (flag) {
|
||||
message.success(t('common.saveSuccess'))
|
||||
message.success({ content: t('common.saveSuccess'), duration: 1 })
|
||||
}
|
||||
setIsSave(false)
|
||||
resolve(res)
|
||||
@@ -331,28 +340,13 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
const handleOpenVariableConfig = () => {
|
||||
chatVariableConfigModalRef.current?.handleOpen(chatVariables)
|
||||
}
|
||||
|
||||
/**
|
||||
* Save chat variable configuration
|
||||
* @param values - Variable values
|
||||
*/
|
||||
const handleSaveChatVariable = (variables: Variable[]) => {
|
||||
setChatVariables(variables)
|
||||
const opening_statement = form.getFieldValue(['features', 'opening_statement'])
|
||||
|
||||
if (opening_statement?.statement && opening_statement?.statement.trim() !== '') {
|
||||
const statement = opening_statement.statement as string
|
||||
const replacedContent = statement.replace(/\{\{([^}]+)\}\}/g, (match, name) => {
|
||||
const v = variables.find(item => item.name === name)
|
||||
return v?.value != null && v.value !== '' ? String(v.value) : match
|
||||
})
|
||||
setChatList(prev => prev.map(item => {
|
||||
const list = [...(item.list || [])]
|
||||
if (list.length > 0 && list[0].role === 'assistant') {
|
||||
list[0] = { ...list[0], content: replacedContent }
|
||||
}
|
||||
return { ...item, list }
|
||||
}))
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
setChatVariables(values?.variables || [])
|
||||
@@ -360,43 +354,55 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
|
||||
const handleSaveFeaturesConfig = (value: FeaturesConfigForm) => {
|
||||
form.setFieldValue('features', value)
|
||||
|
||||
if (value?.opening_statement?.statement && value?.opening_statement?.statement.trim() !== '') {
|
||||
setChatList(prev => (prev.map(item => {
|
||||
const firstMsg = item.list?.[0]
|
||||
|
||||
if (firstMsg?.role === 'assistant') {
|
||||
firstMsg.meta_data = {
|
||||
suggested_questions: value.opening_statement?.suggested_questions || []
|
||||
}
|
||||
return item
|
||||
} else {
|
||||
return {
|
||||
...item,
|
||||
list: [{
|
||||
role: 'assistant',
|
||||
content: value.opening_statement?.statement,
|
||||
meta_data: {
|
||||
suggested_questions: value.opening_statement?.suggested_questions || []
|
||||
}
|
||||
}, ...(item.list || [])]
|
||||
}
|
||||
}
|
||||
})))
|
||||
}
|
||||
}
|
||||
const modelLogo = useMemo(() => {
|
||||
return defaultModel?.name && getListLogoUrl(defaultModel.provider, defaultModel.logo as string)
|
||||
}, [defaultModel])
|
||||
|
||||
useEffect(() => {
|
||||
const opening_statement = form.getFieldValue(['features', 'opening_statement'])
|
||||
console.log('opening_statement', opening_statement, defaultModel, chatList)
|
||||
|
||||
if (opening_statement?.enabled && opening_statement?.statement && opening_statement?.statement.trim() !== '') {
|
||||
const assistantMsg: ChatItem = {
|
||||
role: 'assistant',
|
||||
content: replaceVariables(opening_statement.statement, chatVariables),
|
||||
meta_data: {
|
||||
suggested_questions: opening_statement?.suggested_questions
|
||||
}
|
||||
}
|
||||
setChatList(prev => {
|
||||
if (prev.length === 0 && !defaultModel) return prev
|
||||
if (defaultModel && prev.length === 1) {
|
||||
return [{
|
||||
label: defaultModel.name,
|
||||
model_config_id: defaultModel.id,
|
||||
model_parameters: defaultModel.config as unknown as ModelConfig,
|
||||
list: [assistantMsg]
|
||||
}]
|
||||
}
|
||||
|
||||
return prev.map(vo => {
|
||||
if (vo.list?.length === 0) {
|
||||
return { ...vo, list: [assistantMsg] }
|
||||
} else if (vo.list && vo.list[0].role === 'assistant') {
|
||||
return { ...vo, list: [assistantMsg, ...vo.list.slice(1)] }
|
||||
} else {
|
||||
return { ...vo, list: [assistantMsg, ...(vo.list || [])] }
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}, [defaultModel, chatList.length, form.getFieldValue(['features', 'opening_statement']), chatVariables])
|
||||
|
||||
console.log('agent values', values)
|
||||
return (
|
||||
<>
|
||||
{loading && <Spin fullscreen></Spin>}
|
||||
<Row className="rb:h-[calc(100vh-88px)]" gutter={12}>
|
||||
<Col span={12} className="rb:h-full rb:overflow-y-auto">
|
||||
<Row className="rb:h-full!" gutter={12}>
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<Form form={form}>
|
||||
<Flex gap={16} vertical>
|
||||
<Flex gap={12} vertical>
|
||||
<Flex align="center" justify="space-between" className="rb:p-3! rb:bg-white rb:rounded-xl">
|
||||
<Button type="primary" ghost onClick={handleModelConfig} className="rb:group">
|
||||
{modelLogo
|
||||
@@ -417,89 +423,92 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
</Button>
|
||||
</Space>
|
||||
</Flex>
|
||||
<Form.Item name="default_model_config_id" hidden noStyle></Form.Item>
|
||||
<Form.Item name="capability" hidden noStyle></Form.Item>
|
||||
<Form.Item name="model_parameters" hidden noStyle></Form.Item>
|
||||
<Form.Item name="features" hidden noStyle></Form.Item>
|
||||
<Card
|
||||
title={t('application.promptConfiguration')}
|
||||
extra={
|
||||
<Space
|
||||
size={1}
|
||||
className="rb:px-2 rb:h-5.5 rb:rounded-md rb:cursor-pointer rb:border rb:border-[rgba(21,94,239,0.3)] rb:text-[#155EEF]"
|
||||
onClick={handlePrompt}
|
||||
>
|
||||
<div className="rb:size-5 rb:bg-cover rb:bg-[url('@/assets/images/application/aiPrompt.png')]"></div>
|
||||
<span className="rb:font-[PingFangSC, PingFang_SC]!">{t('application.aiPrompt')}</span>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<div className="rb:leading-4.5 rb:text-[12px] rb:mb-2">
|
||||
<span className="rb:font-medium">{t('application.configuration')}</span>
|
||||
<span className="rb:font-regular rb:text-[#5B6167]"> ({t('application.configurationDesc')})</span>
|
||||
</div>
|
||||
|
||||
<Form.Item name="system_prompt" className="rb:mb-0!">
|
||||
<Input.TextArea
|
||||
placeholder={t('application.promptPlaceholder')}
|
||||
styles={{
|
||||
textarea: {
|
||||
minHeight: '200px',
|
||||
borderRadius: '8px',
|
||||
padding: '12px'
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Card>
|
||||
<Flex gap={12} vertical className="rb:h-[calc(100vh-156px)]! rb:overflow-y-auto!">
|
||||
<Form.Item name="default_model_config_id" hidden noStyle></Form.Item>
|
||||
<Form.Item name="capability" hidden noStyle></Form.Item>
|
||||
<Form.Item name="model_parameters" hidden noStyle></Form.Item>
|
||||
<Form.Item name="features" hidden noStyle></Form.Item>
|
||||
<Card
|
||||
title={t('application.promptConfiguration')}
|
||||
extra={
|
||||
<Space
|
||||
size={1}
|
||||
className="rb:px-2 rb:h-5.5 rb:rounded-md rb:cursor-pointer rb:border rb:border-[rgba(21,94,239,0.3)] rb:text-[#155EEF]"
|
||||
onClick={handlePrompt}
|
||||
>
|
||||
<div className="rb:size-5 rb:bg-cover rb:bg-[url('@/assets/images/application/aiPrompt.png')]"></div>
|
||||
<span className="rb:font-[PingFangSC, PingFang_SC]!">{t('application.aiPrompt')}</span>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<div className="rb:leading-4.5 rb:text-[12px] rb:mb-2">
|
||||
<span className="rb:font-medium">{t('application.configuration')}</span>
|
||||
<span className="rb:font-regular rb:text-[#5B6167]"> ({t('application.configurationDesc')})</span>
|
||||
</div>
|
||||
|
||||
<Form.Item name="system_prompt" className="rb:mb-0!">
|
||||
<Input.TextArea
|
||||
placeholder={t('application.promptPlaceholder')}
|
||||
styles={{
|
||||
textarea: {
|
||||
minHeight: '200px',
|
||||
borderRadius: '8px',
|
||||
padding: '12px'
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Card>
|
||||
|
||||
<Form.Item name="knowledge_retrieval" noStyle>
|
||||
<Knowledge />
|
||||
</Form.Item>
|
||||
|
||||
{/* Memory Configuration */}
|
||||
<Card title={t('application.memoryConfiguration')}>
|
||||
<Flex gap={16} vertical className="rb:bg-[#FAFAFA] rb:rounded-xl rb:p-3!">
|
||||
<SwitchFormItem
|
||||
title={t('application.dialogueHistoricalMemory')}
|
||||
name={['memory', 'enabled']}
|
||||
desc={t('application.dialogueHistoricalMemoryDesc')}
|
||||
/>
|
||||
<Form.Item
|
||||
name={['memory', 'memory_config_id']}
|
||||
label={t('application.selectMemoryContent')}
|
||||
extra={<DescWrapper desc={t('application.selectMemoryContentDesc')} className="rb:mt-1" />}
|
||||
layout="vertical"
|
||||
className="rb:mb-0!"
|
||||
>
|
||||
<CustomSelect
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
url={memoryConfigListUrl}
|
||||
hasAll={false}
|
||||
valueKey='config_id'
|
||||
labelKey="config_name"
|
||||
disabled={!values?.memory?.enabled}
|
||||
{/* Memory Configuration */}
|
||||
<Card title={t('application.memoryConfiguration')}>
|
||||
<Flex gap={16} vertical className="rb:bg-[#FAFAFA] rb:rounded-xl rb:p-3!">
|
||||
<SwitchFormItem
|
||||
title={t('application.dialogueHistoricalMemory')}
|
||||
name={['memory', 'enabled']}
|
||||
desc={t('application.dialogueHistoricalMemoryDesc')}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Flex>
|
||||
</Card>
|
||||
<Form.Item
|
||||
name={['memory', 'memory_config_id']}
|
||||
label={t('application.selectMemoryContent')}
|
||||
extra={<DescWrapper desc={t('application.selectMemoryContentDesc')} className="rb:mt-1" />}
|
||||
layout="vertical"
|
||||
className="rb:mb-0!"
|
||||
>
|
||||
<CustomSelect
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
url={memoryConfigListUrl}
|
||||
hasAll={false}
|
||||
valueKey='config_id'
|
||||
labelKey="config_name"
|
||||
disabled={!values?.memory?.enabled}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Flex>
|
||||
</Card>
|
||||
|
||||
<Form.Item name="variables" noStyle>
|
||||
<VariableList />
|
||||
</Form.Item>
|
||||
<Form.Item name="variables" noStyle>
|
||||
<VariableList />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="skills" noStyle>
|
||||
<SkillList />
|
||||
</Form.Item>
|
||||
<Form.Item name="skills" noStyle>
|
||||
<SkillList />
|
||||
</Form.Item>
|
||||
|
||||
{/* Tool Configuration */}
|
||||
<Form.Item name="tools" noStyle>
|
||||
<ToolList />
|
||||
</Form.Item>
|
||||
{/* Tool Configuration */}
|
||||
<Form.Item name="tools" noStyle>
|
||||
<ToolList />
|
||||
</Form.Item>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Form>
|
||||
</Col>
|
||||
<Col span={12} className="rb:h-full rb:overflow-y-hidden">
|
||||
<Col span={12} className="rb:h-full! rb:overflow-y-hidden">
|
||||
<RbCard
|
||||
title={t('application.debuggingAndPreview')}
|
||||
extra={
|
||||
@@ -513,7 +522,7 @@ const Agent = forwardRef<AgentRef, { onFeaturesLoad?: (features: FeaturesConfigF
|
||||
headerType="borderless"
|
||||
headerClassName="rb:h-[56px]! rb:leading-[22px]!"
|
||||
titleClassName="rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-4! rb:pt-0!"
|
||||
bodyClassName="rb:p-4! rb:pt-0! rb:h-[calc(100%-56px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
<Chat
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:29:29
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:18:09
|
||||
* @Last Modified time: 2026-03-26 15:31:36
|
||||
*/
|
||||
import { type FC, useState, useRef, useEffect } from 'react';
|
||||
import clsx from 'clsx';
|
||||
@@ -124,7 +124,7 @@ const Api: FC<{ application: Application | null }> = ({ application }) => {
|
||||
// Calculate total requests across all API keys
|
||||
const totalRequests = apiKeyList.reduce((total, item) => total + item.total_requests, 0);
|
||||
return (
|
||||
<div className="rb:w-250 rb:mx-auto">
|
||||
<div className="rb:w-250 rb:mx-auto rb:max-h-[calc(100vh-88px)]! rb:overflow-y-auto">
|
||||
<Flex gap={20} vertical>
|
||||
<RbCard
|
||||
title={() => (<Flex align="center">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:29:33
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-20 15:16:25
|
||||
* @Last Modified time: 2026-03-27 18:14:25
|
||||
*/
|
||||
import { useEffect, useState, useRef, forwardRef, useImperativeHandle } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -79,7 +79,7 @@ const Cluster = forwardRef<ClusterRef, { onFeaturesLoad?: (features: FeaturesCon
|
||||
saveMultiAgentConfig(id as string, params)
|
||||
.then((res) => {
|
||||
if (flag) {
|
||||
message.success(t('common.saveSuccess'))
|
||||
message.success({ content: t('common.saveSuccess'), duration: 1 })
|
||||
}
|
||||
resolve(res)
|
||||
})
|
||||
@@ -197,33 +197,34 @@ const Cluster = forwardRef<ClusterRef, { onFeaturesLoad?: (features: FeaturesCon
|
||||
return (
|
||||
<>
|
||||
{loading && <Spin fullscreen></Spin>}
|
||||
<Row className="rb:h-[calc(100vh-89px)]" gutter={12}>
|
||||
<Col span={12} className="rb:h-full rb:overflow-x-auto rb:border-r rb:border-[#DFE4ED]">
|
||||
<Row className="rb:h-full!" gutter={12}>
|
||||
<Col span={12}>
|
||||
<Form form={form} layout="vertical">
|
||||
<Flex gap={16} vertical>
|
||||
<Flex gap={12} vertical>
|
||||
<Flex align="center" justify="end" className="rb:p-3! rb:bg-white rb:rounded-xl">
|
||||
{/* <FeaturesConfig value={values?.features as FeaturesConfigForm} refresh={handleSaveFeaturesConfig} /> */}
|
||||
<Button type="primary" onClick={() => handleSave()}>
|
||||
{t('common.save')}
|
||||
</Button>
|
||||
</Flex>
|
||||
<Form.Item name="features" hidden noStyle></Form.Item>
|
||||
<Card title={t('application.collaboration')}>
|
||||
<Form.Item
|
||||
name="orchestration_mode"
|
||||
noStyle
|
||||
>
|
||||
<RadioGroupCard
|
||||
options={['supervisor', 'collaboration'].map((type) => ({
|
||||
value: type,
|
||||
label: t(`application.${type}`),
|
||||
labelDesc: t(`application.${type}Desc`),
|
||||
}))}
|
||||
allowClear={false}
|
||||
block={true}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Card>
|
||||
<Flex gap={12} vertical className="rb:h-[calc(100vh-158px)]! rb:overflow-y-auto!">
|
||||
<Form.Item name="features" hidden noStyle></Form.Item>
|
||||
<Card title={t('application.collaboration')}>
|
||||
<Form.Item
|
||||
name="orchestration_mode"
|
||||
noStyle
|
||||
>
|
||||
<RadioGroupCard
|
||||
options={['supervisor', 'collaboration'].map((type) => ({
|
||||
value: type,
|
||||
label: t(`application.${type}`),
|
||||
labelDesc: t(`application.${type}Desc`),
|
||||
}))}
|
||||
allowClear={false}
|
||||
block={true}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title={<>
|
||||
@@ -289,45 +290,46 @@ const Cluster = forwardRef<ClusterRef, { onFeaturesLoad?: (features: FeaturesCon
|
||||
>{t('application.modelConfig')}</Button>
|
||||
</Form.Item>
|
||||
</Flex>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name={['execution_config', "sub_agent_execution_mode"]}
|
||||
label={<span className="rb:text-[#5B6167]">{t('application.orchestrationMode')}</span>}
|
||||
className="rb:mb-4!"
|
||||
>
|
||||
<Select
|
||||
options={['sequential', 'parallel'].map((type) => ({
|
||||
value: type,
|
||||
label: t(`application.${type}`),
|
||||
}))}
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="aggregation_strategy"
|
||||
label={<span className="rb:text-[#5B6167]">{t('application.aggregationStrategy')}</span>}
|
||||
className="rb:mb-0!"
|
||||
>
|
||||
<Select
|
||||
options={['merge', 'vote', 'priority'].map((type) => ({
|
||||
value: type,
|
||||
label: t(`application.${type}`),
|
||||
}))}
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Card>}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name={['execution_config', "sub_agent_execution_mode"]}
|
||||
label={<span className="rb:text-[#5B6167]">{t('application.orchestrationMode')}</span>}
|
||||
className="rb:mb-4!"
|
||||
>
|
||||
<Select
|
||||
options={['sequential', 'parallel'].map((type) => ({
|
||||
value: type,
|
||||
label: t(`application.${type}`),
|
||||
}))}
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="aggregation_strategy"
|
||||
label={<span className="rb:text-[#5B6167]">{t('application.aggregationStrategy')}</span>}
|
||||
className="rb:mb-0!"
|
||||
>
|
||||
<Select
|
||||
options={['merge', 'vote', 'priority'].map((type) => ({
|
||||
value: type,
|
||||
label: t(`application.${type}`),
|
||||
}))}
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Card>}
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Form>
|
||||
</Col>
|
||||
<Col span={12} className="rb:h-full rb:overflow-y-hidden">
|
||||
<Col span={12} className="rb:h-full! rb:overflow-y-hidden">
|
||||
<RbCard
|
||||
title={t('application.debuggingAndPreview')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:h-[56px]! rb:leading-[22px]!"
|
||||
titleClassName="rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-4! rb:pt-0!"
|
||||
className="rb:h-full"
|
||||
bodyClassName="rb:p-4! rb:pt-0! rb:h-[calc(100%-56px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
<Chat
|
||||
data={data as Config}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:29:41
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 16:43:10
|
||||
* @Last Modified time: 2026-03-26 15:24:41
|
||||
*/
|
||||
import { type FC, useState, useEffect, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -30,7 +30,7 @@ const tagColors: Record<Release['tagKey'], TagProps['color']> = {
|
||||
history: 'default',
|
||||
}
|
||||
|
||||
const heightClass = 'rb:h-[calc(100vh-88px)]'
|
||||
const heightClass = 'rb:max-h-[calc(100vh-140px)]'
|
||||
/**
|
||||
* Release page component
|
||||
* Manages application version releases, rollbacks, and version history
|
||||
@@ -77,51 +77,55 @@ const ReleasePage: FC<{data: Application; refresh: () => void}> = ({data, refres
|
||||
}
|
||||
return (
|
||||
<Flex gap={12}>
|
||||
<div className={`rb:overflow-y-auto rb:w-101 rb:flex-[0_0_auto] ${heightClass}`}>
|
||||
<div className="rb:w-101 rb:h-full">
|
||||
<Flex gap={12} vertical>
|
||||
<div className="rb:px-1">
|
||||
<div className="rb:text-[16px] rb:leading-5.5 rb:font-medium">{t('application.versionList')}</div>
|
||||
<div className="rb:text-[12px] rb:text-[#5B6167] rb:leading-4.5">{t('application.versionListDesc')}</div>
|
||||
</div>
|
||||
{releaseList.length === 0
|
||||
? <Empty />
|
||||
: selectedVersion && releaseList.map((version, index) => {
|
||||
const tagKey = version.id === data.current_release_id && index === 0
|
||||
? 'current'
|
||||
: version.id === data.current_release_id
|
||||
? 'rolledBack' : 'history'
|
||||
return (
|
||||
<RbCard
|
||||
key={version.version}
|
||||
title={<>
|
||||
{version.version_name && version.version_name[0].toLocaleLowerCase() === 'v' ? version.version_name : version.version_name ? `v${version.version_name}` : `v${version.version}`}
|
||||
{tagKey && <Tag color={tagColors[tagKey]} className="rb:ml-2">
|
||||
{tagKey}
|
||||
</Tag>}
|
||||
</>}
|
||||
className={clsx("rb:hover:shadow-[0px_2px_8px_0px_rgba(0,0,0,0.2)]! rb:cursor-pointer rb:bg-white", {
|
||||
'rb:border-[#171719]!': version.id === selectedVersion.id,
|
||||
'rb:border-[#DFE4ED] ': version.id !== selectedVersion.id
|
||||
})}
|
||||
headerType="borderless"
|
||||
onClick={() => setSelectedVersion(version)}
|
||||
>
|
||||
<div className="rb:leading-5 rb:line-clamp-2 rb:overflow-hidden rb:text-ellipsis rb:whitespace-nowrap">
|
||||
<Markdown content={version.release_notes} />
|
||||
</div>
|
||||
<div className="rb:mt-4 rb:text-[12px] rb:text-[#5B6167] rb:leading-4.5">
|
||||
{t('application.publishedOn')} {formatDateTime(version.published_at, 'YYYY-MM-DD HH:mm:ss')}
|
||||
</div>
|
||||
<div className="rb:text-[12px] rb:text-[#5B6167] rb:leading-4.5">
|
||||
{t('application.publisher')}: {version.publisher_name}
|
||||
</div>
|
||||
</RbCard>
|
||||
)
|
||||
})
|
||||
}
|
||||
<div className={`${heightClass} rb:overflow-y-auto`}>
|
||||
{releaseList.length === 0
|
||||
? <Empty />
|
||||
: <Flex gap={12} vertical>
|
||||
{selectedVersion && releaseList.map((version, index) => {
|
||||
const tagKey = version.id === data.current_release_id && index === 0
|
||||
? 'current'
|
||||
: version.id === data.current_release_id
|
||||
? 'rolledBack' : 'history'
|
||||
return (
|
||||
<RbCard
|
||||
key={version.version}
|
||||
title={<>
|
||||
{version.version_name && version.version_name[0].toLocaleLowerCase() === 'v' ? version.version_name : version.version_name ? `v${version.version_name}` : `v${version.version}`}
|
||||
{tagKey && <Tag color={tagColors[tagKey]} className="rb:ml-2">
|
||||
{tagKey}
|
||||
</Tag>}
|
||||
</>}
|
||||
className={clsx("rb:hover:shadow-[0px_2px_8px_0px_rgba(0,0,0,0.2)]! rb:cursor-pointer rb:bg-white", {
|
||||
'rb:border-[#171719]!': version.id === selectedVersion.id,
|
||||
'rb:border-[#DFE4ED] ': version.id !== selectedVersion.id
|
||||
})}
|
||||
headerType="borderless"
|
||||
onClick={() => setSelectedVersion(version)}
|
||||
>
|
||||
<div className="rb:leading-5 rb:line-clamp-2 rb:overflow-hidden rb:text-ellipsis rb:whitespace-nowrap">
|
||||
<Markdown content={version.release_notes} />
|
||||
</div>
|
||||
<div className="rb:mt-4 rb:text-[12px] rb:text-[#5B6167] rb:leading-4.5">
|
||||
{t('application.publishedOn')} {formatDateTime(version.published_at, 'YYYY-MM-DD HH:mm:ss')}
|
||||
</div>
|
||||
<div className="rb:text-[12px] rb:text-[#5B6167] rb:leading-4.5">
|
||||
{t('application.publisher')}: {version.publisher_name}
|
||||
</div>
|
||||
</RbCard>
|
||||
)
|
||||
})}
|
||||
</Flex>
|
||||
}
|
||||
</div>
|
||||
</Flex>
|
||||
</div>
|
||||
<div className={`rb:overflow-y-auto rb:flex-[1_1_auto] ${heightClass}`}>
|
||||
<div className="rb:overflow-y-auto rb:flex-1">
|
||||
<Form layout="vertical">
|
||||
<Flex align="center" className={clsx("rb:leading-6.5! rb:text-[18px] rb:font-medium rb:mb-4.75!", {
|
||||
'rb:justify-between': selectedVersion,
|
||||
@@ -140,7 +144,7 @@ const ReleasePage: FC<{data: Application; refresh: () => void}> = ({data, refres
|
||||
</Space>
|
||||
</Flex>
|
||||
{selectedVersion &&
|
||||
<Flex gap={16} vertical>
|
||||
<Flex gap={16} vertical className={`${heightClass} rb:overflow-y-auto`}>
|
||||
<RbCard
|
||||
title={t('application.VersionInformation')}
|
||||
headerType="borderless"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-03-13 17:27:52
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 13:43:02
|
||||
* @Last Modified time: 2026-03-26 15:35:13
|
||||
*/
|
||||
import { type FC, useState, useRef, useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -531,11 +531,11 @@ const TestChat: FC<TestChatProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="rb:w-250 rb:p-3 rb:mx-auto">
|
||||
<div className="rb:w-250 rb:mx-auto rb:h-full">
|
||||
<RbCard
|
||||
title={t('application.test')}
|
||||
headerClassName="rb:min-h-[56px]!"
|
||||
className="rb:h-[calc(100vh-88px)]!"
|
||||
className="rb:h-full!"
|
||||
bodyClassName="rb:h-[calc(100%-56px)]! rb:overflow-y-auto rb:px-3! rb:py-0!"
|
||||
>
|
||||
<Chat
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:27:39
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 13:41:44
|
||||
* @Last Modified time: 2026-03-27 17:59:07
|
||||
*/
|
||||
/**
|
||||
* Chat debugging component for application testing
|
||||
@@ -224,11 +224,11 @@ const Chat: FC<ChatProps> = ({
|
||||
if (loading || !id) return
|
||||
setLoading(true)
|
||||
setCompareLoading(true)
|
||||
const files = (fileList || []).filter(item => !['uploading', 'error'].includes(item.status))
|
||||
handleSave(false)
|
||||
.then(() => {
|
||||
const message = msg
|
||||
if (!message?.trim()) return
|
||||
const files = (toolbarRef.current?.getFiles() || []).filter(item => !['uploading', 'error'].includes(item.status))
|
||||
// Validate required variables before sending
|
||||
let isCanSend = true
|
||||
const params: Record<string, any> = {}
|
||||
@@ -427,11 +427,11 @@ const Chat: FC<ChatProps> = ({
|
||||
if (loading || !id) return
|
||||
setLoading(true)
|
||||
setCompareLoading(true)
|
||||
const files = (fileList || []).filter(item => !['uploading', 'error'].includes(item.status))
|
||||
handleSave(false)
|
||||
.then(() => {
|
||||
const message = msg
|
||||
if (!message || message.trim() === '') return
|
||||
const files = (toolbarRef.current?.getFiles() || []).filter(item => !['uploading', 'error'].includes(item.status))
|
||||
addUserMessage(message, files)
|
||||
setMessage(undefined)
|
||||
toolbarRef.current?.setFiles([])
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:27:52
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 15:58:23
|
||||
* @Last Modified time: 2026-03-27 19:07:24
|
||||
*/
|
||||
import { type FC, useRef, useMemo, useCallback } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { Tabs, Dropdown, Button, Flex } from 'antd';
|
||||
import { Tabs, Dropdown, Flex, Popover } from 'antd';
|
||||
import type { MenuProps } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import clsx from 'clsx';
|
||||
@@ -212,15 +212,42 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({
|
||||
</Flex>}
|
||||
extra={application?.type === 'workflow' && source !== 'sharing' && activeTab === 'arrangement'
|
||||
? <Flex align="center" justify="end" gap={10} className="rb:h-8">
|
||||
<FeaturesConfig source={application?.type} value={features as FeaturesConfigForm} refresh={handleSaveFeaturesConfig} />
|
||||
<Button onClick={clear}>{t('workflow.clear')}</Button>
|
||||
<Button onClick={addvariable}>{t('workflow.addvariable')}</Button>
|
||||
<Button onClick={run}>{t('workflow.run')}</Button>
|
||||
<Button type="primary" onClick={save}>{t('workflow.save')}</Button>
|
||||
<div
|
||||
className="rb:size-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/logout.svg')]"
|
||||
onClick={goToApplication}
|
||||
></div>
|
||||
<FeaturesConfig
|
||||
source={application?.type}
|
||||
value={features as FeaturesConfigForm}
|
||||
refresh={handleSaveFeaturesConfig}
|
||||
chatVariables={(workflowRef.current?.chatVariables || []).map(v => ({ ...v, display_name: v.name }))}
|
||||
/>
|
||||
<Popover content={t('workflow.clear')} classNames={{ body: 'rb:py-0.5! rb:px-1! rb:rounded-[6px]! rb:text-[12px]!' }}>
|
||||
<div
|
||||
className="rb:cursor-pointer rb:size-7.5 rb:border rb:border-[#EBEBEB] rb:hover:bg-[#F6F6F6] rb:rounded-[10px] rb:bg-[url('src/assets/images/workflow/clear.svg')] rb:bg-size-[16px_16px] rb:bg-center rb:bg-no-repeat"
|
||||
onClick={clear}
|
||||
></div>
|
||||
</Popover>
|
||||
<Popover content={t('workflow.addvariable')} classNames={{ body: 'rb:py-0.5! rb:px-1! rb:rounded-[6px]! rb:text-[12px]!' }}>
|
||||
<div
|
||||
className="rb:cursor-pointer rb:size-7.5 rb:border rb:border-[#EBEBEB] rb:hover:bg-[#F6F6F6] rb:rounded-[10px] rb:bg-[url('src/assets/images/workflow/variable.svg')] rb:bg-size-[16px_16px] rb:bg-center rb:bg-no-repeat"
|
||||
onClick={addvariable}
|
||||
></div>
|
||||
</Popover>
|
||||
<Popover content={t('workflow.run')} classNames={{ body: 'rb:py-0.5! rb:px-1! rb:rounded-[6px]! rb:text-[12px]!' }}>
|
||||
<div
|
||||
className="rb:cursor-pointer rb:size-7.5 rb:border rb:border-[#EBEBEB] rb:hover:bg-[#F6F6F6] rb:rounded-[10px] rb:bg-[url('src/assets/images/workflow/run.svg')] rb:bg-size-[16px_16px] rb:bg-center rb:bg-no-repeat"
|
||||
onClick={run}
|
||||
></div>
|
||||
</Popover>
|
||||
<Popover content={t('workflow.save')} classNames={{ body: 'rb:py-0.5! rb:px-1! rb:rounded-[6px]! rb:text-[12px]!' }}>
|
||||
<div
|
||||
className="rb:cursor-pointer rb:size-7.5 rb:border rb:border-[#EBEBEB] rb:hover:bg-[#F6F6F6] rb:rounded-[10px] rb:bg-[url('src/assets/images/workflow/save.svg')] rb:bg-size-[16px_16px] rb:bg-center rb:bg-no-repeat"
|
||||
onClick={save}
|
||||
></div>
|
||||
</Popover>
|
||||
<Popover content={t('common.return')} classNames={{ body: 'rb:py-0.5! rb:px-1! rb:rounded-[6px]! rb:text-[12px]!' }}>
|
||||
<div
|
||||
className="rb:cursor-pointer rb:size-7.5 rb:border rb:border-[#EBEBEB] rb:hover:bg-[#F6F6F6] rb:rounded-[10px] rb:bg-[url('src/assets/images/workflow/return.svg')] rb:bg-size-[16px_16px] rb:bg-center rb:bg-no-repeat"
|
||||
onClick={goToApplication}
|
||||
></div>
|
||||
</Popover>
|
||||
</Flex>
|
||||
: <Flex justify="flex-end">
|
||||
<Flex align="center" className="rb:leading-5 rb:text-[14px] rb:text-[#5B6167] rb:font-regular rb:cursor-pointer" onClick={goToApplication}>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:27:56
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 14:03:01
|
||||
* @Last Modified time: 2026-03-27 17:32:10
|
||||
*/
|
||||
/**
|
||||
* Copy Application Modal
|
||||
@@ -74,16 +74,16 @@ const FeaturesConfigModal = forwardRef<FeaturesConfigModalRef, FeaturesConfigMod
|
||||
}
|
||||
|
||||
const formatFileTypeOptions = (fu: FeaturesConfigForm['file_upload']) => {
|
||||
let options = [{ type: 'document', enabled: fu.document_enabled, maxSize: fu.document_max_size_mb }]
|
||||
if (!capability) return options
|
||||
let options = fu.document_enabled ? [{ type: 'document', enabled: fu.document_enabled, maxSize: fu.document_max_size_mb }] : []
|
||||
if (!capability && source !== 'workflow') return options
|
||||
|
||||
if (capability.includes('vision')) {
|
||||
if ((capability?.includes('vision') || source === 'workflow') && fu.image_enabled) {
|
||||
options.push({ type: 'image', enabled: fu.image_enabled, maxSize: fu.image_max_size_mb })
|
||||
}
|
||||
if (capability.includes('audio')) {
|
||||
if ((capability?.includes('audio') || source === 'workflow') && fu.audio_enabled) {
|
||||
options.push({ type: 'audio', enabled: fu.audio_enabled, maxSize: fu.audio_max_size_mb })
|
||||
}
|
||||
if (capability.includes('video')) {
|
||||
if ((capability?.includes('video') || source === 'workflow') && fu.video_enabled) {
|
||||
options.push({ type: 'video', enabled: fu.video_enabled, maxSize: fu.video_max_size_mb })
|
||||
}
|
||||
return options.filter(item => item.enabled)
|
||||
@@ -201,6 +201,7 @@ const FeaturesConfigModal = forwardRef<FeaturesConfigModalRef, FeaturesConfigMod
|
||||
ref={fileUploadSettingModalRef}
|
||||
onSave={handleSaveSettings}
|
||||
capability={capability}
|
||||
source={source}
|
||||
/>
|
||||
<OpenStatementSettingModal
|
||||
ref={openStatementSettingModalRef}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-03-05
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 11:00:14
|
||||
* @Last Modified time: 2026-03-27 14:02:40
|
||||
*/
|
||||
import { forwardRef, useImperativeHandle, useState, useMemo } from 'react';
|
||||
import { Form, InputNumber, Flex, Switch, Row, Col, Radio } from 'antd';
|
||||
@@ -12,6 +12,7 @@ import clsx from 'clsx';
|
||||
import RbModal from '@/components/RbModal';
|
||||
import type { FeaturesConfigForm } from '../../types'
|
||||
import type { Capability } from '@/views/ModelManagement/types'
|
||||
import type { Application } from '@/views/ApplicationManagement/types';
|
||||
|
||||
type FileUpload = Omit<FeaturesConfigForm['file_upload'], 'settings'>
|
||||
|
||||
@@ -23,6 +24,7 @@ interface FileUploadSettingModalRef {
|
||||
interface FileUploadSettingModalProps {
|
||||
onSave: (values: FileUpload) => void;
|
||||
capability?: Capability[];
|
||||
source?: Application['type']
|
||||
}
|
||||
const documentType = {
|
||||
type: 'document',
|
||||
@@ -108,6 +110,7 @@ const defaultValues: FileUpload = {
|
||||
const FileUploadSettingModal = forwardRef<FileUploadSettingModalRef, FileUploadSettingModalProps>(({
|
||||
onSave,
|
||||
capability,
|
||||
source,
|
||||
}, ref) => {
|
||||
const { t } = useTranslation();
|
||||
const [visible, setVisible] = useState(false);
|
||||
@@ -149,6 +152,14 @@ const FileUploadSettingModal = forwardRef<FileUploadSettingModalRef, FileUploadS
|
||||
}));
|
||||
|
||||
const fileTypeOptions = useMemo(() => {
|
||||
if (source === 'workflow') {
|
||||
return [
|
||||
documentType,
|
||||
imageType,
|
||||
audioType,
|
||||
videoType,
|
||||
]
|
||||
}
|
||||
let options = [documentType]
|
||||
if (!capability) return options
|
||||
if (capability.includes('vision')) options = [...options, imageType]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-03-05
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 14:12:11
|
||||
* @Last Modified time: 2026-03-27 14:38:28
|
||||
*/
|
||||
import { forwardRef, useImperativeHandle, useState } from 'react';
|
||||
import { Button, Form, Input, Flex, App } from 'antd';
|
||||
@@ -44,12 +44,13 @@ const OpenStatementSettingModal = forwardRef<OpenStatementSettingModalRef, OpenS
|
||||
|
||||
const handleSave = async () => {
|
||||
form.validateFields().then(values => {
|
||||
const { suggested_questions, ...rest } = values
|
||||
const filterSuggestedQuestions = suggested_questions.filter(vo => vo && vo.trim() !== '' && vo !== null)
|
||||
if (values?.enabled && values?.statement && values?.statement?.trim() !== '') {
|
||||
const usedVars = [...new Set([...values.statement?.matchAll(/\{\{(\w+)\}\}/g)].map(m => m[1]))]
|
||||
|
||||
const validNames = new Set(chatVariables.map(v => v.name))
|
||||
const invalid = usedVars.filter(v => !validNames.has(v))
|
||||
console.log('invalid', invalid)
|
||||
if (invalid.length > 0) {
|
||||
modal.confirm({
|
||||
title: t('application.invalidVariablesTitle'),
|
||||
@@ -57,14 +58,26 @@ const OpenStatementSettingModal = forwardRef<OpenStatementSettingModalRef, OpenS
|
||||
okText: t('common.confirm'),
|
||||
cancelText: t('common.cancel'),
|
||||
onOk: () => {
|
||||
onSave(values);
|
||||
onSave({
|
||||
...rest,
|
||||
suggested_questions: filterSuggestedQuestions
|
||||
});
|
||||
handleClose();
|
||||
},
|
||||
})
|
||||
} else {
|
||||
onSave(values);
|
||||
onSave({
|
||||
...rest,
|
||||
suggested_questions: filterSuggestedQuestions
|
||||
});
|
||||
handleClose();
|
||||
}
|
||||
} else {
|
||||
onSave({
|
||||
...rest,
|
||||
suggested_questions: filterSuggestedQuestions
|
||||
});
|
||||
handleClose();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-03-13 17:20:21
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 11:00:25
|
||||
* @Last Modified time: 2026-03-27 19:07:35
|
||||
*/
|
||||
import { type FC, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button } from 'antd';
|
||||
import { Button, Popover } from 'antd';
|
||||
|
||||
import FeaturesConfigModal from './FeaturesConfigModal'
|
||||
import type { FeaturesConfigModalRef, FeaturesConfigForm } from '../../types'
|
||||
@@ -45,7 +45,16 @@ const FeaturesConfig: FC<FeaturesConfigProps> = ({
|
||||
return (
|
||||
<>
|
||||
{/* Button that triggers the feature configuration modal */}
|
||||
<Button onClick={handleFeaturesConfig}>{t('application.features')}</Button>
|
||||
{source === 'workflow'
|
||||
?
|
||||
<Popover content={t('application.features')} classNames={{ body: 'rb:py-0.5! rb:px-1! rb:rounded-[6px]! rb:text-[12px]!' }}>
|
||||
<div
|
||||
className="rb:cursor-pointer rb:size-7.5 rb:border rb:border-[#EBEBEB] rb:hover:bg-[#F6F6F6] rb:rounded-[10px] rb:bg-[url('src/assets/images/workflow/features.svg')] rb:bg-size-[16px_16px] rb:bg-center rb:bg-no-repeat"
|
||||
onClick={handleFeaturesConfig}
|
||||
></div>
|
||||
</Popover>
|
||||
: <Button onClick={handleFeaturesConfig}>{t('application.features')}</Button>
|
||||
}
|
||||
|
||||
{/* Modal for editing feature settings; calls refresh on save */}
|
||||
<FeaturesConfigModal
|
||||
|
||||
@@ -139,6 +139,7 @@ const ModelConfigModal = forwardRef<ModelConfigModalRef, ModelConfigModalProps>(
|
||||
>
|
||||
{source !== 'multi_agent' &&
|
||||
<ModelSelect
|
||||
params={{type: 'llm,chat'}}
|
||||
placeholder={t('common.pleaseSelect')}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:29:37
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 15:59:47
|
||||
* @Last Modified time: 2026-03-26 15:37:18
|
||||
*/
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Flex } from 'antd'
|
||||
|
||||
import ConfigHeader from './components/ConfigHeader'
|
||||
import type { AgentRef, ClusterRef, WorkflowRef, Config } from './types'
|
||||
@@ -108,7 +109,7 @@ const ApplicationConfig: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex vertical className="rb:h-screen!">
|
||||
<ConfigHeader
|
||||
activeTab={activeTab}
|
||||
handleChangeTab={handleChangeTab}
|
||||
@@ -119,7 +120,7 @@ const ApplicationConfig: React.FC = () => {
|
||||
features={features}
|
||||
onFeaturesChange={setFeatures}
|
||||
/>
|
||||
<div className="rb:p-3 rb:max-h-[calc(100vh-65px)] rb:overflow-auto">
|
||||
<div className="rb:p-3 rb:flex-1 rb:overflow-auto">
|
||||
{activeTab === 'arrangement' && application?.type === 'agent' && <Agent ref={agentRef} onFeaturesLoad={setFeatures} />}
|
||||
{activeTab === 'arrangement' && application?.type === 'multi_agent' && <Cluster ref={clusterRef} onFeaturesLoad={setFeatures} />}
|
||||
{activeTab === 'arrangement' && application?.type === 'workflow' && <Workflow ref={workflowRef} onFeaturesLoad={setFeatures} />}
|
||||
@@ -129,7 +130,7 @@ const ApplicationConfig: React.FC = () => {
|
||||
{activeTab === 'test' && <TestChat application={application} config={config} />}
|
||||
{activeTab === 'log' && <Logs />}
|
||||
</div>
|
||||
</>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import type { KnowledgeConfig } from './components/Knowledge/types'
|
||||
import type { Variable } from './components/VariableList/types'
|
||||
import type { ToolOption } from './components/ToolList/types'
|
||||
import type { ChatItem } from '@/components/Chat/types'
|
||||
import type { GraphRef, WorkflowConfig } from '@/views/Workflow/types';
|
||||
import type { ChatVariable, GraphRef, WorkflowConfig } from '@/views/Workflow/types';
|
||||
import type { ApiKey } from '@/views/ApiKeyManagement/types'
|
||||
import type { SkillConfigForm } from './components/Skill/types'
|
||||
import type { Capability } from '@/views/ModelManagement/types'
|
||||
@@ -164,6 +164,7 @@ export interface WorkflowRef {
|
||||
graphRef: GraphRef;
|
||||
/** Add variable */
|
||||
addVariable: () => void;
|
||||
chatVariables: ChatVariable[];
|
||||
config: WorkflowConfig | null;
|
||||
features: WorkflowConfig['features'];
|
||||
handleSaveFeaturesConfig?: (value: FeaturesConfigForm) => void;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:34:12
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:37:51
|
||||
* @Last Modified time: 2026-03-26 14:39:18
|
||||
*/
|
||||
import React, { useState, useEffect, useMemo, type MouseEvent } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -81,7 +81,7 @@ const MySharing: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex vertical gap={12} className="rb:h-[calc(100vh-148px)]! rb:overflow-y-auto!">
|
||||
<Flex vertical gap={12} className="rb:max-h-[calc(100%-48px)]! rb:overflow-y-auto!">
|
||||
<BodyWrapper loading={false} empty={data.length === 0}>
|
||||
{grouped.map(({ workspace, items }) => (
|
||||
<Collapse
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-06 21:09:42
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-23 17:19:58
|
||||
* @Last Modified time: 2026-03-27 18:23:04
|
||||
*/
|
||||
/**
|
||||
* File Upload Component
|
||||
@@ -59,7 +59,7 @@ interface UploadFilesProps extends Omit<UploadProps, 'onChange'> {
|
||||
featureConfig: FeaturesConfigForm['file_upload']
|
||||
}
|
||||
|
||||
const transform_file_type = {
|
||||
export const transform_file_type: Record<string, string> = {
|
||||
'text/plain': 'document/text',
|
||||
'text/markdown': 'document/markdown',
|
||||
'text/x-markdown': 'document/x-markdown',
|
||||
@@ -313,7 +313,7 @@ const UploadFiles = forwardRef<UploadFilesRef, UploadFilesProps>(({
|
||||
</div>
|
||||
);
|
||||
},
|
||||
className: 'rb:-mb-1.5!',
|
||||
className: 'rb:-mb-1.5! upload-block',
|
||||
...props,
|
||||
};
|
||||
|
||||
@@ -327,7 +327,7 @@ const UploadFiles = forwardRef<UploadFilesRef, UploadFilesProps>(({
|
||||
<Upload
|
||||
{...uploadProps}
|
||||
>
|
||||
{t('memoryConversation.uploadFile')}
|
||||
<div>{t('memoryConversation.uploadFile')}</div>
|
||||
</Upload>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:58:03
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 13:35:42
|
||||
* @Last Modified time: 2026-03-27 14:28:19
|
||||
*/
|
||||
/**
|
||||
* Conversation Page
|
||||
@@ -30,8 +30,10 @@ import { type SSEMessage } from '@/utils/stream'
|
||||
import { shareFileUploadUrlWithoutApiPrefix } from '@/api/fileStorage'
|
||||
import ChatToolbar, { type ChatToolbarRef } from '@/components/Chat/ChatToolbar'
|
||||
import type { Variable } from '@/views/Workflow/components/Properties/VariableList/types'
|
||||
import type { Variable as AppVariable } from '@/views/ApplicationConfig/components/VariableList/types'
|
||||
import type { FeaturesConfigForm } from '@/views/ApplicationConfig/types';
|
||||
import { getFileStatusById } from '@/api/fileStorage';
|
||||
import { replaceVariables } from '@/views/ApplicationConfig/Agent'
|
||||
|
||||
const Conversation: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
@@ -84,11 +86,11 @@ const Conversation: FC = () => {
|
||||
if (shareToken && token) {
|
||||
getExperienceConfig(token)
|
||||
.then(res => {
|
||||
const response = res as { variables: Variable[]; features: FeaturesConfigForm; app_type: string; memory?: boolean; }
|
||||
const response = res as { variables: Variable[]; features: FeaturesConfigForm; app_type: string; memory: boolean; }
|
||||
toolbarRef.current?.setVariables(response.variables || [])
|
||||
setConfig(response)
|
||||
setFeatures(response.features)
|
||||
setIsHasMemory((response.app_type === 'workflow' && response.memory) || (response.app_type !== 'workflow'))
|
||||
setIsHasMemory((response.app_type === 'workflow' && response.memory) || response.memory)
|
||||
})
|
||||
} else {
|
||||
setChatList([])
|
||||
@@ -375,6 +377,17 @@ const Conversation: FC = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleChangeVariables = (variables: Variable[]) => {
|
||||
setChatList(prev => {
|
||||
const firstMsg = prev[0]
|
||||
console.log('firstMsg', firstMsg)
|
||||
if (firstMsg && firstMsg.role === 'assistant' && firstMsg.content && features?.opening_statement.enabled && features?.opening_statement.statement && variables.length > 0) {
|
||||
firstMsg.content = replaceVariables(features?.opening_statement.statement, variables as unknown as AppVariable[])
|
||||
}
|
||||
return [firstMsg, ...prev.slice(1)]
|
||||
})
|
||||
}
|
||||
|
||||
console.log('chatList', chatList)
|
||||
|
||||
return (
|
||||
@@ -460,7 +473,8 @@ const Conversation: FC = () => {
|
||||
}
|
||||
}}
|
||||
rightExtra={
|
||||
<Flex align="center" justify="end" gap={8}>
|
||||
(features?.web_search?.enabled || isHasMemory)
|
||||
? <Flex align="center" justify="end" gap={8}>
|
||||
{features?.web_search?.enabled &&
|
||||
<Tooltip title={t('memoryConversation.web_search')}>
|
||||
<Flex justify="center" align="center"
|
||||
@@ -496,7 +510,9 @@ const Conversation: FC = () => {
|
||||
</Tooltip>
|
||||
}
|
||||
</Flex>
|
||||
: undefined
|
||||
}
|
||||
onVariablesChange={handleChangeVariables}
|
||||
/>
|
||||
</Chat>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:56:54
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 18:28:18
|
||||
* @Last Modified time: 2026-03-26 15:43:29
|
||||
*/
|
||||
/**
|
||||
* Emotion Engine Configuration Page
|
||||
@@ -118,8 +118,8 @@ const EmotionEngine: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={12}>
|
||||
<Row gutter={[16, 16]} className="rb:h-full!">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('emotionEngine.emotionEngineConfig')}
|
||||
headerType="borderless"
|
||||
@@ -128,7 +128,7 @@ const EmotionEngine: React.FC = () => {
|
||||
<Button block onClick={handleReset}>{t('common.reset')}</Button>
|
||||
<Button type="primary" loading={loading} block onClick={handleSave}>{t('common.save')}</Button>
|
||||
</Space>}
|
||||
className="rb:h-[calc(100vh-76px)]!"
|
||||
className="rb:h-full!"
|
||||
bodyClassName="rb:h-[calc(100%-54px)] rb:overflow-y-auto! rb:p-3! rb:pt-0!"
|
||||
>
|
||||
<Form
|
||||
@@ -207,12 +207,12 @@ const EmotionEngine: React.FC = () => {
|
||||
</Form>
|
||||
</RbCard>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('emotionEngine.emotionEngineConfig')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
className="rb:h-[calc(100vh-76px)]!"
|
||||
className="rb:h-full!"
|
||||
bodyClassName="rb:h-[calc(100%-54px)] rb:overflow-y-auto! rb:p-3! rb:pt-0!"
|
||||
>
|
||||
<Flex vertical gap={24} className="rb:text-[#212332]">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:00:12
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 18:29:00
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-26 15:47:37
|
||||
*/
|
||||
/**
|
||||
* Forgetting Engine Configuration Page
|
||||
@@ -155,8 +155,8 @@ const ForgettingEngine: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Row gutter={12}>
|
||||
<Col span={12}>
|
||||
<Row gutter={12} className="rb:h-full!">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('forgettingEngine.forgettingEngineConfigParams')}
|
||||
extra={<Space>
|
||||
@@ -165,7 +165,7 @@ const ForgettingEngine: React.FC = () => {
|
||||
</Space>}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
className="rb:h-[calc(100vh-76px)]!"
|
||||
className="rb:h-full!"
|
||||
bodyClassName="rb:h-[calc(100%-54px)] rb:overflow-y-auto! rb:p-3! rb:pt-0!"
|
||||
>
|
||||
<Form
|
||||
@@ -226,7 +226,7 @@ const ForgettingEngine: React.FC = () => {
|
||||
</Form>
|
||||
</RbCard>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('forgettingEngine.forgettingCurve')}
|
||||
headerType="borderless"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:16:45
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-10 11:57:35
|
||||
* @Last Modified time: 2026-03-26 14:30:27
|
||||
*/
|
||||
/**
|
||||
* Pie Chart Card Component
|
||||
@@ -33,7 +33,7 @@ const PieCard: FC<PieCardProps> = ({ chartData, loading }) => {
|
||||
>
|
||||
{loading
|
||||
? <Loading size={249} />
|
||||
: <PieChart chartData={chartData} />
|
||||
: <PieChart chartData={chartData} itemGap={24} />
|
||||
}
|
||||
</Card>
|
||||
)
|
||||
|
||||
@@ -75,7 +75,7 @@ const GuideCard: React.FC = () => {
|
||||
<div className="rb:mt-2 rb:pl-3 rb:pr-4">
|
||||
<Button ref={startButtonRef} block className='rb:gap-1 rb:flex rb:items-center' onClick={handleStartGuide}>
|
||||
<span className='rb:text-xs'>{t('index.viewGuide')}</span>
|
||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('src/assets/images/common/arrow_right_dark.svg')]"></div>
|
||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/arrow_right_dark.svg')]"></div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @LastEditTime: 2025-12-19 20:19:59
|
||||
*/
|
||||
import { useEffect, useState, useRef, type FC } from 'react';
|
||||
import { useNavigate, useParams, useLocation } from 'react-router-dom';
|
||||
import { useNavigate, useParams, useLocation, useSearchParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useBreadcrumbManager, type BreadcrumbPath } from '@/hooks/useBreadcrumbManager';
|
||||
import { Button, Spin, message, Switch } from 'antd';
|
||||
@@ -29,11 +29,16 @@ const DocumentDetails: FC = () => {
|
||||
const { updateBreadcrumbs } = useBreadcrumbManager({
|
||||
breadcrumbType: 'detail'
|
||||
});
|
||||
const [searchParams] = useSearchParams();
|
||||
const {
|
||||
documentId,
|
||||
parentId: locationParentId,
|
||||
breadcrumbPath
|
||||
} = (location.state || {}) as {
|
||||
} = ({
|
||||
documentId: searchParams.get('documentId') ?? undefined,
|
||||
parentId: searchParams.get('parentId') ?? undefined,
|
||||
...(location.state || {})
|
||||
}) as {
|
||||
documentId?: string;
|
||||
parentId?: string;
|
||||
breadcrumbPath?: BreadcrumbPath;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState, useRef, useMemo, useCallback, type FC } from 'react';
|
||||
import { Row, Col, Button, Dropdown, Tooltip, App } from 'antd'
|
||||
import { Button, Dropdown, Tooltip, App, Flex } from 'antd'
|
||||
import type { MenuProps } from 'antd';
|
||||
import { EllipsisOutlined, RightOutlined, DownOutlined } from '@ant-design/icons';
|
||||
import { RightOutlined, DownOutlined } from '@ant-design/icons';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -78,6 +78,7 @@ const KnowledgeBaseManagement: FC = () => {
|
||||
if (permissionId !== 'share') {
|
||||
items.push({
|
||||
key: '1',
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:cursor-pointer rb:bg-[url('@/assets/images/common/edit_bold.svg')]" />,
|
||||
label: t('knowledgeBase.edit'),
|
||||
onClick: () => {
|
||||
handleEdit(item);
|
||||
@@ -87,6 +88,7 @@ const KnowledgeBaseManagement: FC = () => {
|
||||
|
||||
items.push({
|
||||
key: '2',
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:cursor-pointer rb:bg-[url('@/assets/images/common/delete_red_big.svg')]" />,
|
||||
label: t('knowledgeBase.delete'),
|
||||
onClick: () => {
|
||||
handleDelete(item);
|
||||
@@ -560,21 +562,23 @@ const KnowledgeBaseManagement: FC = () => {
|
||||
{data.length === 0 && !loading ? (
|
||||
<Empty size={200} />
|
||||
) : (
|
||||
<Row gutter={[16, 16]} className="rb:mb-2" style={{ margin: 0 }}>
|
||||
<div style={{ columns: '3 280px', columnGap: 12, marginBottom: 8 }}>
|
||||
{data.map((item) => {
|
||||
const modelInfo = modelMenus[item.id];
|
||||
const hasModelInfo = modelInfo && modelInfo.menu.length > 1;
|
||||
return (
|
||||
<Col xs={12} sm={12} md={12} lg={8} xl={8} key={item.id} >
|
||||
<div key={item.id} className="rb:break-inside-avoid rb:mb-3">
|
||||
<RbCard
|
||||
title={item.name}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:py-3!"
|
||||
className='rb:min-h-[200px]'
|
||||
extra={
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<Dropdown menu={{ items: getOptMenuItems(item) }} >
|
||||
<EllipsisOutlined className="rb:cursor-pointer" />
|
||||
<Dropdown
|
||||
menu={{ items: getOptMenuItems(item) }}
|
||||
placement="bottomRight"
|
||||
>
|
||||
<div onClick={(e) => e.stopPropagation()} className="rb:cursor-pointer rb:size-5.5 rb:bg-[url('@/assets/images/common/more.svg')] rb:hover:bg-[url('@/assets/images/common/more_hover.svg')]"></div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
}
|
||||
@@ -583,24 +587,23 @@ const KnowledgeBaseManagement: FC = () => {
|
||||
<div className="rb:flex rb:text-[#5B6167] rb:h-5 rb:line-clamp-1 rb:text-sm rb:leading-5 rb:mb-3">
|
||||
{/* <div className="rb:font-medium rb:w-20">{t('knowledgeBase.description')} </div> */}
|
||||
<Tooltip title={item.description}>
|
||||
<div className='rb:flex-1 rb:text-left rb:leading-5 rb:text-gray-800 rb:break-words rb:line-clamp-2'>{(item.description && item.description != '') ? item.description : t('knowledgeBase.noDescription')}</div>
|
||||
<div className='rb:flex-1 rb:text-left rb:leading-5 rb:text-gray-800 rb:wrap-break-word rb:line-clamp-2'>{(item.description && item.description != '') ? item.description : t('knowledgeBase.noDescription')}</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className='rb:min-h-[60px] rb:py-2.5 rb:px-3 rb:bg-[#F6F6F6] rb:rounded-lg rb:mb-3'>
|
||||
{item.descriptionItems?.map((description: Record<string, unknown>) => (
|
||||
<Flex vertical gap={4} className='rb:min-h-15 rb:py-2.5! rb:px-3! rb:bg-[#F6F6F6] rb:rounded-lg rb:mb-3'>
|
||||
{item.descriptionItems?.map((description: Record<string, unknown>) => (
|
||||
<div
|
||||
key={description.key as string}
|
||||
className="rb:flex rb:gap-4 rb:justify-start rb:text-[#5B6167] rb:text-[14px] rb:leading-[20px]"
|
||||
key={description.key as string}
|
||||
className="rb:grid rb:grid-cols-2 rb:text-[#5B6167] rb:text-[14px] rb:leading-5"
|
||||
>
|
||||
<div className={clsx('rb:whitespace-nowrap rb:w-20',{"rb:text-gray-800 rb:font-medium" : (description.key as string) === 'permission_id'})}>{(description.label as string)}</div>
|
||||
<div className={clsx('rb:flex-inline rb:text-left rb:py-[1px] rb:rounded rb:font-medium',{
|
||||
"rb:text-[#155eef] rb:font-medium": (description.key as string) === 'permission_id' && (description.children as string) === t('knowledgeBase.private'),
|
||||
"rb:text-[#FF8A4C] rb:font-medium": (description.key as string) === 'permission_id' && (description.children as string) === t('knowledgeBase.share'),
|
||||
})}>{(description.children as string)}</div>
|
||||
<div className={clsx('rb:whitespace-nowrap rb:w-20', {"rb:text-gray-800 rb:font-medium" : (description.key as string) === 'permission_id'})}>{(description.label as string)}</div>
|
||||
<div className={clsx('rb:flex-inline rb:text-left rb:py-px rb:rounded',{
|
||||
"rb:text-[#155eef] rb:font-medium": (description.key as string) === 'permission_id' && (description.children as string) === t('knowledgeBase.private'),
|
||||
"rb:text-[#FF8A4C] rb:font-medium": (description.key as string) === 'permission_id' && (description.children as string) === t('knowledgeBase.share'),
|
||||
})}>{(description.children as string)}</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
</div>
|
||||
))}
|
||||
</Flex>
|
||||
{hasModelInfo && (
|
||||
<div onClick={(e) => e.stopPropagation()}>
|
||||
<div
|
||||
@@ -633,9 +636,9 @@ const KnowledgeBaseManagement: FC = () => {
|
||||
)}
|
||||
</div>
|
||||
</RbCard>
|
||||
</Col>
|
||||
</div>
|
||||
)})}
|
||||
</Row>
|
||||
</div>
|
||||
)}
|
||||
</InfiniteScroll>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:42:12
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 16:25:23
|
||||
* @Last Modified time: 2026-03-30 11:38:42
|
||||
*/
|
||||
/**
|
||||
* Member Management Page
|
||||
@@ -105,10 +105,11 @@ const MemberManagement: React.FC = () => {
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="rb:h-[calc(100vh-80px)] rb:overflow-hidden rb:bg-white rb:rounded-lg rb:pt-3 rb:px-3">
|
||||
<Flex justify="end" className="rb:px-1! rb:mb-3!">
|
||||
<div className="rb:h-full rb:overflow-hidden rb:bg-white rb:rounded-lg rb:pt-3 rb:px-3">
|
||||
<Flex justify="space-between" align="center" className="rb:px-1! rb:mb-3!">
|
||||
<div className="rb:font-[MiSans-Bold] rb:font-bold rb:text-[#212332] rb:leading-5">{t('member.memberList')}</div>
|
||||
<Button type="primary" onClick={() => handleEdit()}>
|
||||
{t('member.createMember')}
|
||||
+ {t('member.createMember')}
|
||||
</Button>
|
||||
</Flex>
|
||||
<Table<Member>
|
||||
@@ -117,6 +118,7 @@ const MemberManagement: React.FC = () => {
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
pagination={false}
|
||||
scrollY="calc(100vh - 248px)"
|
||||
/>
|
||||
|
||||
<MemberModal
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/**
|
||||
* Card Component
|
||||
* Styled wrapper for conversation and analysis panels
|
||||
* Provides consistent layout and styling
|
||||
*/
|
||||
|
||||
import { Card } from 'antd'
|
||||
import { type FC, type ReactNode } from 'react'
|
||||
|
||||
/**
|
||||
* Component props
|
||||
*/
|
||||
interface RbCardProps {
|
||||
children: ReactNode;
|
||||
title: string;
|
||||
bodyClassName?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
const RbCard: FC<RbCardProps> = ({ children, title, bodyClassName, style, ...props }) => {
|
||||
return (
|
||||
<Card
|
||||
title={title}
|
||||
classNames={{
|
||||
header: "rb:min-h-[40px]! rb:p-[0_16px]! rb:rounded-[12px_12px_0_0]! rb:text-[14px]! rb:leading-[20px]! rb:font-medium! rb:border-b-[#DFE4ED]",
|
||||
body: `rb:h-[calc(100%-40px)] rb:p-[16px]! ${bodyClassName || ''}`,
|
||||
}}
|
||||
style={{
|
||||
borderRadius: '12px',
|
||||
borderColor: '#DFE4ED',
|
||||
background: '#FBFDFF',
|
||||
height: 'calc(100vh - 152px)',
|
||||
...style
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
export default RbCard
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:09:03
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-20 10:22:08
|
||||
* @Last Modified time: 2026-03-31 12:21:56
|
||||
*/
|
||||
/**
|
||||
* Memory Conversation Page
|
||||
@@ -12,16 +12,18 @@
|
||||
|
||||
import { type FC, type ReactNode, useState, useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Col, Row, App, Skeleton, Select, Segmented, Tooltip, Flex } from 'antd'
|
||||
import { Col, Row, App, Skeleton, Segmented, Tooltip, Flex } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import type { AnyObject } from 'antd/es/_util/type';
|
||||
|
||||
import ConversationEmptyIcon from '@/assets/images/conversation/conversationEmpty.svg'
|
||||
import AnalysisEmptyIcon from '@/assets/images/conversation/analysisEmpty.png'
|
||||
import { readService, getUserMemoryList } from '@/api/memory'
|
||||
import { readService, userMemoryListUrl } from '@/api/memory'
|
||||
import Empty from '@/components/Empty'
|
||||
import DebounceSelect from '@/components/DebounceSelect'
|
||||
import Markdown from '@/components/Markdown'
|
||||
import type { Data } from '@/views/UserMemory/types'
|
||||
import type { DefaultOptionType } from 'antd/es/select'
|
||||
import Chat from '@/components/Chat'
|
||||
import type { ChatItem } from '@/components/Chat/types'
|
||||
import RbCard from '@/components/RbCard/Card';
|
||||
@@ -60,7 +62,7 @@ export interface TestParams {
|
||||
search_switch: string;
|
||||
/** Conversation history */
|
||||
history: { role: string; content: string }[];
|
||||
/** Enable web search */
|
||||
/** Enable web keyword */
|
||||
web_search?: boolean;
|
||||
/** Enable memory function */
|
||||
memory?: boolean;
|
||||
@@ -108,21 +110,10 @@ const MemoryConversation: FC = () => {
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const [chatData, setChatData] = useState<ChatItem[]>([])
|
||||
const [logs, setLogs] = useState<LogItem[]>([])
|
||||
const [userList, setUserList] = useState<Data[]>([])
|
||||
const [search_switch, setSearchSwitch] = useState('0')
|
||||
const [msg, setMsg] = useState<string>('')
|
||||
const [expandedLogs, setExpandedLogs] = useState<Record<number, boolean>>({})
|
||||
|
||||
/** Load user list on mount */
|
||||
useEffect(() => {
|
||||
getUserMemoryList().then(res => {
|
||||
setUserList((res as Data[] || []).map(item => ({
|
||||
...item,
|
||||
name: item.end_user?.other_name && item.end_user?.other_name !== '' ? item.end_user?.other_name : item.end_user?.id
|
||||
})))
|
||||
})
|
||||
}, [])
|
||||
|
||||
/** Handle message send */
|
||||
const handleSend = () => {
|
||||
if(!userId) {
|
||||
@@ -149,7 +140,7 @@ const MemoryConversation: FC = () => {
|
||||
})
|
||||
}
|
||||
|
||||
/** Handle search mode change */
|
||||
/** Handle keyword mode change */
|
||||
const handleChange = (value: string) => {
|
||||
setSearchSwitch(value)
|
||||
}
|
||||
@@ -158,30 +149,32 @@ const MemoryConversation: FC = () => {
|
||||
<>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Select
|
||||
options={userList.map(item => ({
|
||||
<DebounceSelect
|
||||
url={userMemoryListUrl}
|
||||
searchKey="keyword"
|
||||
format={(items) => (items as Data[]).map(item => ({
|
||||
...item,
|
||||
'end_user.id': item.end_user?.id,
|
||||
label: item.end_user?.other_name || item.end_user?.id,
|
||||
value: item.end_user?.id,
|
||||
label: item?.name,
|
||||
}))}
|
||||
filterOption={(inputValue, option) => option?.label?.toLowerCase().indexOf(inputValue.toLowerCase()) !== -1}
|
||||
showSearch={true}
|
||||
// filterOption={(inputValue, option) => option.label?.toLowerCase().indexOf(inputValue.toLowerCase()) !== -1}
|
||||
placeholder={t('memoryConversation.searchPlaceholder')}
|
||||
style={{ width: '100%', marginBottom: '16px' }}
|
||||
onChange={setUserId}
|
||||
onChange={(opt: DefaultOptionType) => setUserId(opt?.value as string)}
|
||||
variant="borderless"
|
||||
className="rb:bg-white rb:rounded-lg"
|
||||
showSearch
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={16}>
|
||||
<Row gutter={16} className="rb:h-[calc(100%-48px)]!">
|
||||
<Col span={12}>
|
||||
<RbCard
|
||||
title={t('memoryConversation.conversationContent')}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[52px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:px-3! rb:py-0! rb:h-[calc(100%-52px)]!"
|
||||
className="rb:h-[calc(100vh-124px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
<Chat
|
||||
empty={
|
||||
@@ -213,7 +206,7 @@ const MemoryConversation: FC = () => {
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[52px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
bodyClassName="rb:p-3! rb:pt-0! rb:h-[calc(100%-52px)]! rb:overflow-y-auto!"
|
||||
className="rb:h-[calc(100vh-124px)]!"
|
||||
className="rb:h-full!"
|
||||
>
|
||||
{loading ?
|
||||
<Skeleton active />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:30:11
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:40:38
|
||||
* @Last Modified time: 2026-03-26 15:46:30
|
||||
*/
|
||||
/**
|
||||
* Result Component
|
||||
@@ -267,7 +267,7 @@ const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
||||
title={t('memoryExtractionEngine.exampleMemoryExtractionResults')}
|
||||
subTitle={t('memoryExtractionEngine.exampleMemoryExtractionResultsSubTitle')}
|
||||
headerClassName="rb:pb-0! rb:pt-4!"
|
||||
bodyClassName="rb:h-[calc(100vh-163px)]! rb:overflow-y-auto rb:p-[16px_20px]!"
|
||||
bodyClassName="rb:h-[calc(100%-50px)]! rb:overflow-y-auto rb:p-[16px_20px]!"
|
||||
extra={<Space size={8}>
|
||||
<Button
|
||||
icon={<div className="rb:size-3.5 rb:bg-cover rb:bg-[url('@/assets/images/common/save.svg')]"></div>}
|
||||
@@ -281,6 +281,7 @@ const Result: FC<ResultProps> = ({ loading, handleSave }) => {
|
||||
onClick={handleRun}
|
||||
>{t('memoryExtractionEngine.debug')}</Button>
|
||||
</Space>}
|
||||
className="rb:h-full!"
|
||||
>
|
||||
{/* <RbAlert color="orange" icon={<ExclamationCircleFilled />} className="rb:mb-3!">
|
||||
{t('memoryExtractionEngine.warning')}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:30:02
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 14:07:35
|
||||
* @Last Modified time: 2026-03-26 15:45:42
|
||||
*/
|
||||
/**
|
||||
* Memory Extraction Engine Configuration Page
|
||||
@@ -123,10 +123,10 @@ const MemoryExtractionEngine: FC = () => {
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
|
||||
<Row gutter={12}>
|
||||
<Col span={12}>
|
||||
<Form form={form}>
|
||||
<Flex vertical gap={12} className="rb:h-[calc(100vh-114px)]! rb:overflow-y-auto">
|
||||
<Row gutter={12} className="rb:h-[calc(100%-38px)]!">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<Form form={form} className="rb:h-full!">
|
||||
<Flex vertical gap={12} className="rb:h-full! rb:overflow-y-auto">
|
||||
<div className="rb:bg-white rb:rounded-xl rb:py-2.5 rb:px-4">
|
||||
<Flex
|
||||
align="center"
|
||||
@@ -259,7 +259,7 @@ const MemoryExtractionEngine: FC = () => {
|
||||
</Flex>
|
||||
</Form>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<Result
|
||||
loading={loading}
|
||||
handleSave={handleSave}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:33:15
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-12 15:44:32
|
||||
* @Last Modified time: 2026-03-26 14:56:00
|
||||
*/
|
||||
/**
|
||||
* Memory Management Page
|
||||
@@ -100,7 +100,10 @@ const MemoryManagement: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<BodyWrapper loading={loading} empty={data.length === 0}>
|
||||
<Row gutter={[12, 12]}>
|
||||
<Row
|
||||
gutter={[12, 12]}
|
||||
className="rb:max-h-[calc(100%-48px)] rb:overflow-y-auto"
|
||||
>
|
||||
{data.map((item) => (
|
||||
<Col key={item.config_id} span={12}>
|
||||
<RbCard
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:50:10
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 14:21:01
|
||||
* @Last Modified time: 2026-03-27 19:18:55
|
||||
*/
|
||||
/**
|
||||
* Model List View
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
import { useRef, useState, useEffect, forwardRef, useImperativeHandle } from 'react';
|
||||
import { Button, Flex, Row, Col, Tooltip } from 'antd'
|
||||
import { Button, Flex, Row, Col, Tooltip, Popover } from 'antd'
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import type { ProviderModelItem, KeyConfigModalRef, ModelListDetailRef, ModelListItem, BaseRef } from './types'
|
||||
@@ -75,7 +75,14 @@ const ModelList = forwardRef<BaseRef, { query: any; handleEdit: (vo?: ModelListI
|
||||
<Tooltip title={String(item.provider).charAt(0).toUpperCase() + String(item.provider).slice(1)}>
|
||||
<div className="rb:wrap-break-word rb:line-clamp-1">{String(item.provider).charAt(0).toUpperCase() + String(item.provider).slice(1)}</div>
|
||||
</Tooltip>
|
||||
<Flex gap={8} className="rb:overflow-hidden rb:flex-nowrap rb:w-auto!">{item.tags.map(tag => <Tag key={tag} className="rb:shrink-0">{t(`modelNew.${tag}`)}</Tag>)}</Flex>
|
||||
|
||||
<Popover content={
|
||||
<Flex gap={8} className="rb:overflow-hidden rb:flex-nowrap rb:w-auto!">{item.tags.map(tag => <Tag key={tag} className="rb:shrink-0">{t(`modelNew.${tag}`)}</Tag>)}</Flex>
|
||||
}>
|
||||
<Flex gap={8} className="rb:overflow-hidden rb:flex-nowrap rb:w-auto!">
|
||||
{item.tags.map(tag => <Tag key={tag} className="rb:shrink-0">{t(`modelNew.${tag}`)}</Tag>)}
|
||||
</Flex>
|
||||
</Popover>
|
||||
</Flex>}
|
||||
isNeedTooltip={false}
|
||||
footer={<Row gutter={9} className="rb:pt-2!">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:49:45
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 12:28:07
|
||||
* @Last Modified time: 2026-03-27 18:06:23
|
||||
*/
|
||||
/**
|
||||
* Model List Detail Drawer
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
import { useState, useImperativeHandle, forwardRef, useRef, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Switch, Row, Col, Space, Tooltip } from 'antd'
|
||||
import { Button, Switch, Row, Col, Space, Tooltip, Popover } from 'antd'
|
||||
|
||||
import type { ProviderModelItem, ModelListItem, ModelListDetailRef, MultiKeyConfigModalRef } from '../types';
|
||||
import RbDrawer from '@/components/RbDrawer';
|
||||
@@ -136,11 +136,19 @@ const ModelListDetail = forwardRef<ModelListDetailRef, ModelListDetailProps>(({
|
||||
<RbCard
|
||||
key={item.id}
|
||||
title={item.name}
|
||||
subTitle={<Space size={8} className="rb:mt-1!">
|
||||
<Tag>{t(`modelNew.${item.type}`)}</Tag>
|
||||
<Tag color="warning">{item.api_keys.length}{t('modelNew.apiKeyNum')}</Tag>
|
||||
{item.capability?.filter(item => item !=='video').map(vo => <Tag key={vo}>{t(`modelNew.${vo}`)}</Tag>)}
|
||||
</Space>}
|
||||
subTitle={
|
||||
<Popover content={
|
||||
<Space size={8} className="rb:mt-1!">
|
||||
<Tag>{t(`modelNew.${item.type}`)}</Tag>
|
||||
<Tag color="warning">{item.api_keys.length}{t('modelNew.apiKeyNum')}</Tag>
|
||||
{item.capability?.map(vo => <Tag key={vo}>{t(`modelNew.${vo}`)}</Tag>)}
|
||||
</Space>}>
|
||||
<Space size={8} className="rb:mt-1!">
|
||||
<Tag>{t(`modelNew.${item.type}`)}</Tag>
|
||||
<Tag color="warning">{item.api_keys.length}{t('modelNew.apiKeyNum')}</Tag>
|
||||
{item.capability?.map(vo => <Tag key={vo}>{t(`modelNew.${vo}`)}</Tag>)}
|
||||
</Space>
|
||||
</Popover>}
|
||||
avatarUrl={getLogoUrl(item.logo)}
|
||||
avatar={
|
||||
<div className="rb:w-12 rb:h-12 rb:rounded-lg rb:mr-3.25 rb:bg-[#155eef] rb:flex rb:items-center rb:justify-center rb:text-[28px] rb:text-[#ffffff]">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:50:05
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 12:28:07
|
||||
* @Last Modified time: 2026-03-26 15:51:08
|
||||
*/
|
||||
/**
|
||||
* Model Management Main Page
|
||||
@@ -84,8 +84,8 @@ const tabKeys = ['group', 'list', 'square']
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex vertical gap={16}>
|
||||
<Flex justify="space-between" align="center">
|
||||
<>
|
||||
<Flex justify="space-between" align="center" className="rb:mb-3!">
|
||||
<PageTabs
|
||||
value={activeTab}
|
||||
options={formatTabItems()}
|
||||
@@ -132,7 +132,7 @@ const tabKeys = ['group', 'list', 'square']
|
||||
</Form>
|
||||
</Flex>
|
||||
|
||||
<div className="rb:w-full rb:h-[calc(100vh-125px)] rb:overflow-y-auto">
|
||||
<div className="rb:w-full rb:h-[calc(100%-44px)] rb:overflow-y-auto">
|
||||
{activeTab === 'group' && <GroupModel ref={groupRef} query={query} handleEdit={handleEdit} />}
|
||||
{activeTab === 'list' && <ModelList ref={modelListRef} query={query} handleEdit={handleEdit} handleCloseModel={() => customModelModalRef.current?.handleClose() } />}
|
||||
{activeTab === 'square' && <ModelSquare query={query} />}
|
||||
@@ -145,7 +145,7 @@ const tabKeys = ['group', 'list', 'square']
|
||||
ref={customModelModalRef}
|
||||
refresh={handleRefresh}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 16:50:22
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 14:03:13
|
||||
* @Last Modified time: 2026-03-25 18:35:13
|
||||
*/
|
||||
/**
|
||||
* Utility functions for Model Management
|
||||
*/
|
||||
|
||||
import bedrockIcon from '@/assets/images/model/bedrock.svg'
|
||||
import bedrockIcon from '@/assets/images/model/bedrock.png'
|
||||
import dashscopeIcon from '@/assets/images/model/dashscope.png'
|
||||
import gpustackIcon from '@/assets/images/model/gpustack.png'
|
||||
import ollamaIcon from '@/assets/images/model/ollama.svg'
|
||||
import openaiIcon from '@/assets/images/model/openai.svg'
|
||||
import xinferenceIcon from '@/assets/images/model/xinference.svg'
|
||||
import ollamaIcon from '@/assets/images/model/ollama.png'
|
||||
import openaiIcon from '@/assets/images/model/openai.png'
|
||||
import xinferenceIcon from '@/assets/images/model/xinference.png'
|
||||
import volcanoIcon from '@/assets/images/model/volcano.png'
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 14:10:15
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 13:38:59
|
||||
* @Last Modified time: 2026-03-27 15:03:09
|
||||
*/
|
||||
import { type FC, useState, useRef } from 'react';
|
||||
import type { MenuInfo } from 'rc-menu/lib/interface';
|
||||
@@ -150,13 +150,13 @@ const Ontology: FC = () => {
|
||||
items: [
|
||||
{
|
||||
key: 'edit',
|
||||
icon: <div className="rb:size-6 rb:bg-cover rb:cursor-pointer rb:bg-[url('@/assets/images/common/edit.svg')]" />,
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:cursor-pointer rb:bg-[url('@/assets/images/common/edit_bold.svg')]" />,
|
||||
label: t('common.edit'),
|
||||
onClick: (e: MenuInfo) => handleEdit(item, e),
|
||||
},
|
||||
{
|
||||
key: 'delete',
|
||||
icon: <div className="rb:size-6 rb:bg-cover rb:cursor-pointer rb:bg-[url('@/assets/images/common/delete.svg')]" />,
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:cursor-pointer rb:bg-[url('@/assets/images/common/delete_red_big.svg')]" />,
|
||||
label: t('common.delete'),
|
||||
onClick: (e: MenuInfo) => handleDelete(item, e),
|
||||
},
|
||||
@@ -164,7 +164,7 @@ const Ontology: FC = () => {
|
||||
}}
|
||||
placement="bottomRight"
|
||||
>
|
||||
<div onClick={(e) => e.stopPropagation()} className="rb:cursor-pointer rb:size-6 rb:bg-[url('@/assets/images/common/more.svg')] rb:hover:bg-[url('@/assets/images/common/more_hover.svg')]"></div>
|
||||
<div onClick={(e) => e.stopPropagation()} className="rb:cursor-pointer rb:size-5.5 rb:bg-[url('@/assets/images/common/more.svg')] rb:hover:bg-[url('@/assets/images/common/more_hover.svg')]"></div>
|
||||
</Dropdown>
|
||||
</Flex>
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 14:10:20
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 12:16:23
|
||||
* @Last Modified time: 2026-03-26 18:55:37
|
||||
*/
|
||||
import { type FC, useEffect, useState, useRef } from 'react'
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
@@ -100,58 +100,60 @@ const Detail: FC = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader
|
||||
title={<Space>
|
||||
{data.scene_name}
|
||||
{data.is_system_default ? <Tag color="warning">{t('common.default')}</Tag> : undefined}
|
||||
<Tooltip title={data.scene_description}>
|
||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/question.svg')]"></div>
|
||||
</Tooltip>
|
||||
</Space>}
|
||||
extra={<Space size={12}>
|
||||
{data.is_system_default ? undefined : (<Space>
|
||||
<Button type="primary" ghost className="rb:h-6! rb:px-2! rb:leading-5.5!" onClick={handleAdd}>+ {t('ontology.addClass')}</Button>
|
||||
<Button className="rb:h-6! rb:px-2! rb:leading-5.5!" type="primary" onClick={handleExtract}>+ {t('ontology.extract')}</Button>
|
||||
</Space>)}
|
||||
<Flex align="center" className="rb:leading-5 rb:text-[14px] rb:text-[#5B6167] rb:font-regular rb:cursor-pointer" onClick={() => navigate(-1)}>
|
||||
<div
|
||||
className="rb:mr-2 rb:size-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/logout.svg')]"
|
||||
></div>
|
||||
{t('common.return')}
|
||||
</Flex>
|
||||
</Space>}
|
||||
/>
|
||||
<Flex vertical className="rb:h-screen!">
|
||||
<PageHeader
|
||||
title={<Space>
|
||||
{data.scene_name}
|
||||
{data.is_system_default ? <Tag color="warning">{t('common.default')}</Tag> : undefined}
|
||||
<Tooltip title={data.scene_description}>
|
||||
<div className="rb:size-4 rb:bg-cover rb:bg-[url('@/assets/images/common/question.svg')]"></div>
|
||||
</Tooltip>
|
||||
</Space>}
|
||||
extra={<Space size={12}>
|
||||
{data.is_system_default ? undefined : (<Space>
|
||||
<Button type="primary" ghost className="rb:h-6! rb:px-2! rb:leading-5.5!" onClick={handleAdd}>+ {t('ontology.addClass')}</Button>
|
||||
<Button className="rb:h-6! rb:px-2! rb:leading-5.5!" type="primary" onClick={handleExtract}>+ {t('ontology.extract')}</Button>
|
||||
</Space>)}
|
||||
<Flex align="center" className="rb:leading-5 rb:text-[14px] rb:text-[#5B6167] rb:font-regular rb:cursor-pointer" onClick={() => navigate(-1)}>
|
||||
<div
|
||||
className="rb:mr-2 rb:size-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/logout.svg')]"
|
||||
></div>
|
||||
{t('common.return')}
|
||||
</Flex>
|
||||
</Space>}
|
||||
/>
|
||||
|
||||
<div className="rb:h-[calc(100vh-64px)] rb:overflow-y-auto rb:p-3">
|
||||
<Row gutter={12} className="rb:mb-4">
|
||||
<Col span={6} offset={18}>
|
||||
<SearchInput
|
||||
placeholder={t('ontology.classSearchPlaceholder')}
|
||||
onSearch={(value) => setQuery({ class_name: value })}
|
||||
className="rb:w-full!"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<BodyWrapper loading={loading} empty={!data.items?.length}>
|
||||
<Row gutter={[16, 16]}>
|
||||
{data.items?.map(item => (
|
||||
<Col key={item.class_id} span={6}>
|
||||
<RbCard
|
||||
title={item.class_name}
|
||||
extra={data.is_system_default ? undefined : (<div
|
||||
className="rb:size-5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/common/delete.svg')] rb:hover:bg-[url('@/assets/images/common/delete_hover.svg')]"
|
||||
onClick={() => handleDelete(item)}
|
||||
></div>)}
|
||||
>
|
||||
<Tooltip title={item.class_description}>
|
||||
<div className="rb:h-10 rb:text-[#5B6167] rb:leading-5 rb:font-regular rb:wrap-break-word rb:line-clamp-2">{item.class_description}</div>
|
||||
</Tooltip>
|
||||
</RbCard>
|
||||
</Col>
|
||||
))}
|
||||
<div className="rb:flex-1 rb:p-3 rb:overflow-hidden">
|
||||
<Row gutter={12} className="rb:mb-4">
|
||||
<Col span={6} offset={18}>
|
||||
<SearchInput
|
||||
placeholder={t('ontology.classSearchPlaceholder')}
|
||||
onSearch={(value) => setQuery({ class_name: value })}
|
||||
className="rb:w-full!"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</BodyWrapper>
|
||||
</div>
|
||||
<BodyWrapper loading={loading} empty={!data.items?.length}>
|
||||
<Row gutter={[16, 16]} className="rb:max-h-[calc(100%-48px)] rb:overflow-y-auto">
|
||||
{data.items?.map(item => (
|
||||
<Col key={item.class_id} span={6}>
|
||||
<RbCard
|
||||
title={item.class_name}
|
||||
extra={data.is_system_default ? undefined : (<div
|
||||
className="rb:size-5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/common/delete.svg')] rb:hover:bg-[url('@/assets/images/common/delete_hover.svg')]"
|
||||
onClick={() => handleDelete(item)}
|
||||
></div>)}
|
||||
>
|
||||
<Tooltip title={item.class_description}>
|
||||
<div className="rb:h-10 rb:text-[#5B6167] rb:leading-5 rb:font-regular rb:wrap-break-word rb:line-clamp-2">{item.class_description}</div>
|
||||
</Tooltip>
|
||||
</RbCard>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</BodyWrapper>
|
||||
</div>
|
||||
</Flex>
|
||||
|
||||
<OntologyClassModal
|
||||
ref={ontologyClassModalRef}
|
||||
|
||||
@@ -8,7 +8,7 @@ const Header:FC<{ title: string; desc: string; className?: string; }> = ({
|
||||
return (
|
||||
<div className={`rb:pl-2 ${className}`}>
|
||||
<div className="rb:text-[#212332] rb:font-[MiSans-Bold] rb:font-bold rb:text-[16px] rb:leading-5.5">{title}</div>
|
||||
<div className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4 rb:mt-2 rb:pb-1">{desc}</div>
|
||||
<div className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4 rb:mt-2">{desc}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:44:15
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-20 13:52:09
|
||||
* @Last Modified time: 2026-03-27 15:14:58
|
||||
*/
|
||||
/**
|
||||
* Prompt Editor Component
|
||||
@@ -188,12 +188,12 @@ const Prompt: FC = () => {
|
||||
|
||||
<RbCard
|
||||
title={t('prompt.chatTitle')}
|
||||
headerClassName="rb:min-h-[52px]! rb:font-[MiSans-Bold] rb:gont-bold"
|
||||
headerClassName="rb:min-h-[52px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
headerType="borderless"
|
||||
bodyClassName="rb:px-4! rb:pt-0! rb:pb-3!"
|
||||
>
|
||||
<ChatContent
|
||||
classNames="rb:h-[calc(100vh-265px)] rb:mb-[12px]!"
|
||||
classNames="rb:h-[calc(100vh-257px)] rb:mb-[12px]!"
|
||||
contentClassNames="rb:max-w-75!"
|
||||
empty={<Empty url={ConversationEmptyIcon} title={t(`prompt.promptChatEmpty`)} isNeedSubTitle={false} size={[140, 100]} className="rb:h-full" />}
|
||||
data={chatList || []}
|
||||
@@ -249,7 +249,7 @@ const Prompt: FC = () => {
|
||||
</Flex>
|
||||
<RbCard
|
||||
title={t('prompt.conversationOptimizationPrompt')}
|
||||
headerClassName="rb:min-h-[52px]! rb:font-[MiSans-Bold] rb:gont-bold"
|
||||
headerClassName="rb:min-h-[52px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
headerType="borderless"
|
||||
bodyClassName="rb:px-4! rb:pt-0! rb:pb-3!"
|
||||
extra={
|
||||
@@ -275,10 +275,10 @@ const Prompt: FC = () => {
|
||||
{values?.current_prompt
|
||||
? <Editor
|
||||
ref={editorRef}
|
||||
className="rb:h-[calc(100vh-201px)] rb:bg-white! rb:border-none! rb:p-0! rb:text-[#212332] rb:leading-5"
|
||||
className="rb:h-[calc(100vh-193px)] rb:bg-white! rb:border-none! rb:p-0! rb:text-[#212332] rb:leading-5"
|
||||
onChange={(value) => form.setFieldValue('current_prompt', value)}
|
||||
/>
|
||||
: <Empty url={analysisEmptyIcon} title={t(`prompt.promptPlaceholder`)} isNeedSubTitle={false} size={[270, 170]} className="rb:h-[calc(100vh-201px)] rb:w-70 rb:mx-auto! rb:text-center! rb:text-[12px]! rb:leading-4!" />
|
||||
: <Empty url={analysisEmptyIcon} title={t(`prompt.promptPlaceholder`)} isNeedSubTitle={false} size={[270, 170]} className="rb:h-[calc(100vh-193px)] rb:mx-auto! rb:text-center! rb:text-[12px]! rb:leading-4!" />
|
||||
}
|
||||
</Form.Item>
|
||||
</RbCard>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:44:04
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-02-09 12:18:09
|
||||
* @Last Modified time: 2026-03-27 15:52:44
|
||||
*/
|
||||
/**
|
||||
* Prompt History Component
|
||||
@@ -12,8 +12,7 @@
|
||||
import React, { useRef, type MouseEvent } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Tooltip, App, Flex, Form, Dropdown } from 'antd';
|
||||
import { DashOutlined } from '@ant-design/icons';
|
||||
import { Space, App, Flex, Form } from 'antd';
|
||||
|
||||
import type { HistoryQuery, HistoryItem, PromptDetailRef } from '../types';
|
||||
import RbCard from '@/components/RbCard/Card'
|
||||
@@ -104,28 +103,33 @@ const History: React.FC = () => {
|
||||
renderItem={(item) => (
|
||||
<RbCard
|
||||
className="rb:cursor-pointer rb:relative"
|
||||
title={<Tooltip title={item.title}>{item.title}</Tooltip>}
|
||||
headerClassName='rb:h-[38px]! rb:pt-3!'
|
||||
title={item.title}
|
||||
headerClassName='rb:min-h-[46px]!'
|
||||
headerType="borderless"
|
||||
bodyClassName="rb:px-3! rb:py-0!"
|
||||
>
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{ key: 'detail', label: t('common.viewDetail') },
|
||||
{ key: 'edit', label: t('common.edit') },
|
||||
{ key: 'delete', label: t('common.delete') },
|
||||
],
|
||||
onClick: ({key}) => handleClick(key, item)
|
||||
}}
|
||||
>
|
||||
<DashOutlined className="rb:absolute rb:right-6 rb:top-3.25 rb:hover:bg-[#F6F6F6] rb:p-1 rb:rounded-md" />
|
||||
</Dropdown>
|
||||
<div className="rb:text-[12px] rb:text-[#5B6167] rb:leading-4.5 rb:mb-2">{formatDateTime(item.created_at, 'YYYY/MM/DD HH:mm')}</div>
|
||||
<div className="rb:h-35.5 rb:leading-5 rb:overflow-hidden rb:px-3 rb:py-2.5 rb:bg-[#F6F6F6] rb:rounded-lg rb:hover:shadow-[0px_2px_8px_0px_rgba(23,23,25,0.16)]">
|
||||
<div className="rb:h-35.5 rb:leading-5 rb:overflow-hidden rb:px-3 rb:py-2.5 rb:bg-[#F6F6F6] rb:rounded-lg">
|
||||
<Markdown content={item.prompt} className="rb:h-31! rb:overflow-hidden! rb:line-clamp-6! rb:break-word! rb:text-ellipsis!" />
|
||||
</div>
|
||||
|
||||
<Flex align="center" justify="space-between" className="rb:py-3!">
|
||||
<div className="rb:text-[12px] rb:text-[#5B6167] rb:leading-4.5">{formatDateTime(item.created_at, 'YYYY/MM/DD HH:mm')}</div>
|
||||
|
||||
<Space size={8}>
|
||||
<div className="rb:size-4.5 rb:bg-cover rb:bg-[url('src/assets/images/prompt/eye.svg')] rb:hover:bg-[url('src/assets/images/prompt/eye_bg.svg')]"
|
||||
onClick={() => handleClick('detail', item)}
|
||||
></div>
|
||||
<div className="rb:size-4.5 rb:bg-cover rb:bg-[url('src/assets/images/prompt/edit.svg')] rb:hover:bg-[url('src/assets/images/prompt/edit_bg.svg')]"
|
||||
onClick={() => handleClick('edit', item)}
|
||||
></div>
|
||||
<div className="rb:size-4.5 rb:bg-cover rb:bg-[url('src/assets/images/prompt/delete.svg')] rb:hover:bg-[url('src/assets/images/prompt/delete_hover.svg')]"
|
||||
onClick={() => handleClick('delete', item)}
|
||||
></div>
|
||||
</Space>
|
||||
</Flex>
|
||||
</RbCard>
|
||||
)}
|
||||
heightClass="rb:h-[calc(100vh-126px)]!"
|
||||
/>
|
||||
|
||||
<PromptDetail
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:46:47
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 11:44:16
|
||||
* @Last Modified time: 2026-03-26 18:57:08
|
||||
*/
|
||||
/**
|
||||
* Self Reflection Engine Configuration Page
|
||||
@@ -169,8 +169,8 @@ const SelfReflectionEngine: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={12}>
|
||||
<Row gutter={[16, 16]} className="rb:h-full!">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('reflectionEngine.reflectionEngineConfig')}
|
||||
extra={<Space>
|
||||
@@ -179,7 +179,7 @@ const SelfReflectionEngine: React.FC = () => {
|
||||
</Space>}
|
||||
headerType="borderless"
|
||||
headerClassName="rb:min-h-[54px]! rb:font-[MiSans-Bold] rb:font-bold"
|
||||
className="rb:h-[calc(100vh-76px)]!"
|
||||
className="rb:h-full!"
|
||||
bodyClassName="rb:h-[calc(100%-54px)] rb:overflow-y-auto! rb:p-4! rb:pt-0!"
|
||||
>
|
||||
<Form
|
||||
@@ -252,8 +252,8 @@ const SelfReflectionEngine: React.FC = () => {
|
||||
</Form>
|
||||
</RbCard>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Space size={16} direction="vertical" className="rb:w-full">
|
||||
<Col span={12} className="rb:h-full!">
|
||||
<Flex gap={16} vertical className="rb:h-full!">
|
||||
<RbCard
|
||||
title={t('memoryExtractionEngine.example')}
|
||||
>
|
||||
@@ -346,7 +346,7 @@ const SelfReflectionEngine: React.FC = () => {
|
||||
</RbCard>
|
||||
)}
|
||||
</>}
|
||||
</Space>
|
||||
</Flex>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:48:03
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-24 17:01:59
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-30 11:36:24
|
||||
*/
|
||||
/**
|
||||
* Space Configuration Page
|
||||
@@ -15,9 +15,7 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
import type { SpaceConfigData } from './types'
|
||||
import { getWorkspaceModels, updateWorkspaceModels } from '@/api/workspaces'
|
||||
import { getModelListUrl } from '@/api/models'
|
||||
import CustomSelect from '@/components/CustomSelect'
|
||||
import RbAlert from '@/components/RbAlert';
|
||||
import ModelSelect from '@/components/ModelSelect';
|
||||
|
||||
const SpaceConfig: FC = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -63,7 +61,9 @@ const SpaceConfig: FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="rb:w-250 rb:bg-white rb:rounded-lg rb:py-3 rb:px-3">
|
||||
<div className="rb:bg-white rb:rounded-lg rb:p-6 rb:pb-8">
|
||||
<div className="rb:font-[MiSans-Bold] rb:font-bold rb:text-[#212332] rb:leading-5">{t('menu.spaceConfig')}</div>
|
||||
<div className="rb:text-[#5B6167] rb:text-[12px] rb:leading-4 rb:mt-2 rb:mb-6">{t('space.configAlert')}</div>
|
||||
{pageLoading
|
||||
? <Skeleton active />
|
||||
: <Form
|
||||
@@ -71,55 +71,42 @@ const SpaceConfig: FC = () => {
|
||||
layout="vertical"
|
||||
>
|
||||
<Form.Item
|
||||
label={t('space.llmModel')}
|
||||
label={t('space.llmModel')}
|
||||
className="rb:font-medium rb:text-[#212332] rb:mb-6!"
|
||||
name="llm"
|
||||
rules={[{ required: true, message: t('common.pleaseSelect') }]}
|
||||
>
|
||||
<CustomSelect
|
||||
url={getModelListUrl}
|
||||
params={{ type: 'llm', pagesize: 100, is_active: true }}
|
||||
valueKey="id"
|
||||
labelKey="name"
|
||||
hasAll={false}
|
||||
style={{width: '100%'}}
|
||||
<ModelSelect
|
||||
params={{ type: 'llm' }}
|
||||
className="rb:w-137.5!"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('space.embeddingModel')}
|
||||
label={t('space.embeddingModel')}
|
||||
className="rb:font-medium rb:text-[#212332] rb:mb-6!"
|
||||
name="embedding"
|
||||
rules={[{ required: true, message: t('common.pleaseSelect') }]}
|
||||
>
|
||||
<CustomSelect
|
||||
url={getModelListUrl}
|
||||
params={{ type: 'embedding', pagesize: 100, is_active: true }}
|
||||
valueKey="id"
|
||||
labelKey="name"
|
||||
hasAll={false}
|
||||
style={{width: '100%'}}
|
||||
<ModelSelect
|
||||
params={{ type: 'embedding' }}
|
||||
className="rb:w-137.5!"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('space.rerankModel')}
|
||||
label={t('space.rerankModel')}
|
||||
className="rb:font-medium rb:text-[#212332] rb:mb-6!"
|
||||
name="rerank"
|
||||
rules={[{ required: true, message: t('common.pleaseSelect') }]}
|
||||
>
|
||||
<CustomSelect
|
||||
url={getModelListUrl}
|
||||
params={{ type: 'rerank', pagesize: 100, is_active: true }}
|
||||
valueKey="id"
|
||||
labelKey="name"
|
||||
hasAll={false}
|
||||
style={{width: '100%'}}
|
||||
<ModelSelect
|
||||
params={{ type: 'rerank' }}
|
||||
className="rb:w-137.5!"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<RbAlert>{t('space.configAlert')}</RbAlert>
|
||||
|
||||
<Form.Item className="rb:text-right">
|
||||
<Button type="primary" className="rb:mt-6" onClick={handleSave} loading={loading}>
|
||||
{t('common.save')}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
<Button type="primary" className="rb:mt-1" onClick={handleSave} loading={loading}>
|
||||
{t('common.save')}
|
||||
</Button>
|
||||
</Form>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @Author: ZhaoYing
|
||||
* @Date: 2026-02-03 17:48:59
|
||||
* @Last Modified by: ZhaoYing
|
||||
* @Last Modified time: 2026-03-25 15:33:38
|
||||
* @Last Modified time: 2026-03-26 14:43:20
|
||||
*/
|
||||
/**
|
||||
* Space Management Page
|
||||
@@ -12,7 +12,7 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { List, Button, Flex, Space as AntSpace, Tooltip } from 'antd';
|
||||
import { Button, Flex, Space as AntSpace, Tooltip, Row, Col } from 'antd';
|
||||
|
||||
import type { Space, SpaceModalRef } from './types';
|
||||
import SpaceModal from './components/SpaceModal';
|
||||
@@ -68,11 +68,12 @@ const SpaceManagement: React.FC = () => {
|
||||
{t('space.createSpace')}
|
||||
</Button>
|
||||
<BodyWrapper loading={loading} empty={data.length === 0}>
|
||||
<List
|
||||
grid={{ gutter: 16, column: 4 }}
|
||||
dataSource={data}
|
||||
renderItem={(item) => (
|
||||
<List.Item key={item.id}>
|
||||
<Row
|
||||
gutter={[16, 16]}
|
||||
className="rb:max-h-[calc(100%-48px)] rb:overflow-y-auto"
|
||||
>
|
||||
{data.map(item => (
|
||||
<Col key={item.id} span={6}>
|
||||
<RbCard
|
||||
avatarUrl={item.icon}
|
||||
avatarText={item.name[0]}
|
||||
@@ -91,10 +92,9 @@ const SpaceManagement: React.FC = () => {
|
||||
</Button>}
|
||||
>
|
||||
</RbCard>
|
||||
</List.Item>
|
||||
)}
|
||||
className="rb:h-[calc(100vh-124px)] rb:overflow-y-auto rb:overflow-x-hidden"
|
||||
/>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</BodyWrapper>
|
||||
|
||||
<SpaceModal
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
Row,
|
||||
Col,
|
||||
App,
|
||||
List,
|
||||
Space,
|
||||
Flex,
|
||||
Tooltip,
|
||||
@@ -69,11 +68,12 @@ const Custom = forwardRef<CustomRef, { getStatusTag: (status: string) => ReactNo
|
||||
return (
|
||||
<>
|
||||
<BodyWrapper loading={loading} empty={data.length === 0}>
|
||||
<List
|
||||
grid={{ gutter: 16, column: 3 }}
|
||||
dataSource={data}
|
||||
renderItem={(item) => (
|
||||
<List.Item key={item.id}>
|
||||
<Row
|
||||
gutter={[16, 16]}
|
||||
className="rb:max-h-[calc(100%-48px)] rb:overflow-y-auto"
|
||||
>
|
||||
{data.map((item) => (
|
||||
<Col span={8} key={item.id}>
|
||||
<RbCard
|
||||
title={
|
||||
<Flex justify="space-between" gap={16}>
|
||||
@@ -88,14 +88,14 @@ const Custom = forwardRef<CustomRef, { getStatusTag: (status: string) => ReactNo
|
||||
items: [
|
||||
{
|
||||
key: 'edit',
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:cursor-pointer rb:bg-[url('@/assets/images/common/edit.svg')]" />,
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:cursor-pointer rb:bg-[url('@/assets/images/common/edit_bold.svg')]" />,
|
||||
label: t('common.edit'),
|
||||
onClick: () => handleEdit(item),
|
||||
},
|
||||
{
|
||||
key: 'delete',
|
||||
className: 'rb:text-[#FF5D34]!',
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:cursor-pointer rb:bg-[url('@/assets/images/common/delete_red.svg')]" />,
|
||||
icon: <div className="rb:size-4 rb:bg-cover rb:cursor-pointer rb:bg-[url('@/assets/images/common/delete_red_big.svg')]" />,
|
||||
label: t('common.delete'),
|
||||
onClick: () => handleDeleteService(item),
|
||||
},
|
||||
@@ -103,13 +103,12 @@ const Custom = forwardRef<CustomRef, { getStatusTag: (status: string) => ReactNo
|
||||
}}
|
||||
placement="bottomRight"
|
||||
>
|
||||
<div className="rb:cursor-pointer rb:size-6 rb:bg-[url('@/assets/images/common/more.svg')] rb:hover:bg-[url('@/assets/images/common/more_hover.svg')]"></div>
|
||||
<div className="rb:cursor-pointer rb:size-5.5 rb:bg-[url('@/assets/images/common/more.svg')] rb:hover:bg-[url('@/assets/images/common/more_hover.svg')]"></div>
|
||||
</Dropdown>
|
||||
</Flex>
|
||||
}
|
||||
isNeedTooltip={false}
|
||||
>
|
||||
|
||||
{item.tags?.length > 0
|
||||
? <Flex gap={8} wrap align="center">
|
||||
<Flex gap={6}>
|
||||
@@ -142,10 +141,9 @@ const Custom = forwardRef<CustomRef, { getStatusTag: (status: string) => ReactNo
|
||||
</Col>
|
||||
</Row>
|
||||
</RbCard>
|
||||
</List.Item>
|
||||
)}
|
||||
className="rb:h-[calc(100vh-178px)] rb:overflow-y-auto rb:overflow-x-hidden"
|
||||
/>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
</BodyWrapper>
|
||||
|
||||
{/* 添加服务弹窗组件 */}
|
||||
|
||||