Compare commits
2 Commits
de3d196e11
...
91eaa37283
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91eaa37283 | ||
|
|
3f85b0ff78 |
98
.dockerignore
Normal file
98
.dockerignore
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
# Git
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
Dockerfile*
|
||||||
|
docker-compose*
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
# Environment files (keep only production)
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# Storybook build outputs
|
||||||
|
.out
|
||||||
|
.storybook-out
|
||||||
|
|
||||||
|
# Temporary folders
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
6
.env.production
Normal file
6
.env.production
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# VITE_API_BASE_URL = http://150.158.121.95
|
||||||
|
VITE_API_BASE_URL = http://154.9.253.114:9380
|
||||||
|
|
||||||
|
VITE_RSA_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArq9XTUSeYr2+N1h3Afl/z8Dse/2yD0ZGrKwx+EEEcdsBLca9Ynmx3nIB5obmLlSfmskLpBo0UACBmB5rEjBp2Q2f3AG3Hjd4B+gNCG6BDaawuDlgANIhGnaTLrIqWrrcm4EMzJOnAOI1fgzJRsOOUEfaS318Eq9OVO3apEyCCt0lOQK6PuksduOjVxtltDav+guVAA068NrPYmRNabVKRNLJpL8w4D44sfth5RvZ3q9t+6RTArpEtc5sh5ChzvqPOzKGMXW83C95TxmXqpbK6olN4RevSfVjEAgCydH6HN6OhtOQEcnrU97r9H0iZOWwbw3pVrZiUkuRD1R56Wzs2wIDAQAB
|
||||||
|
-----END PUBLIC KEY-----"
|
||||||
52
Dockerfile
52
Dockerfile
@@ -1,12 +1,60 @@
|
|||||||
FROM node:20-alpine
|
# 多阶段构建 - 构建阶段
|
||||||
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 复制包管理文件
|
||||||
COPY package.json pnpm-lock.yaml ./
|
COPY package.json pnpm-lock.yaml ./
|
||||||
|
|
||||||
|
# 安装 pnpm 和依赖
|
||||||
RUN npm install -g pnpm && pnpm install
|
RUN npm install -g pnpm && pnpm install
|
||||||
|
|
||||||
|
# 复制源代码
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
|
# 构建生产版本
|
||||||
|
RUN pnpm build
|
||||||
|
|
||||||
|
# 生产阶段 - nginx
|
||||||
|
FROM nginx:alpine AS production
|
||||||
|
|
||||||
|
# 复制自定义 nginx 配置
|
||||||
|
COPY <<EOF /etc/nginx/conf.d/default.conf
|
||||||
|
server {
|
||||||
|
listen 5173;
|
||||||
|
server_name localhost;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# 处理 SPA 路由
|
||||||
|
location / {
|
||||||
|
try_files \$uri \$uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 静态资源缓存
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# 安全头
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
|
||||||
|
# Gzip 压缩
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 从构建阶段复制构建产物
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
|
||||||
|
# 暴露端口
|
||||||
EXPOSE 5173
|
EXPOSE 5173
|
||||||
|
|
||||||
CMD ["pnpm", "dev"]
|
# 启动 nginx
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
28
docker-compose.yml
Normal file
28
docker-compose.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
teres-frontend:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
target: production
|
||||||
|
ports:
|
||||||
|
- "3000:80"
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# 开发环境服务(可选)
|
||||||
|
teres-frontend-dev:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.dev
|
||||||
|
ports:
|
||||||
|
- "5173:5173"
|
||||||
|
volumes:
|
||||||
|
- .:/app
|
||||||
|
- /app/node_modules
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=development
|
||||||
|
profiles:
|
||||||
|
- dev
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
"@mui/material": "^7.3.4",
|
"@mui/material": "^7.3.4",
|
||||||
"@mui/x-data-grid": "^8.14.0",
|
"@mui/x-data-grid": "^8.14.0",
|
||||||
"@mui/x-date-pickers": "^8.14.0",
|
"@mui/x-date-pickers": "^8.14.0",
|
||||||
|
"@xyflow/react": "^12.8.6",
|
||||||
"ahooks": "^3.9.5",
|
"ahooks": "^3.9.5",
|
||||||
"axios": "^1.12.2",
|
"axios": "^1.12.2",
|
||||||
"dayjs": "^1.11.18",
|
"dayjs": "^1.11.18",
|
||||||
|
|||||||
236
pnpm-lock.yaml
generated
236
pnpm-lock.yaml
generated
@@ -26,6 +26,9 @@ importers:
|
|||||||
'@mui/x-date-pickers':
|
'@mui/x-date-pickers':
|
||||||
specifier: ^8.14.0
|
specifier: ^8.14.0
|
||||||
version: 8.14.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react@18.3.1))(@mui/material@7.3.4(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/system@7.3.3(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(dayjs@1.11.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 8.14.0(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react@18.3.1))(@mui/material@7.3.4(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/system@7.3.3(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(react@18.3.1))(@types/react@19.2.2)(dayjs@1.11.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
'@xyflow/react':
|
||||||
|
specifier: ^12.8.6
|
||||||
|
version: 12.8.6(@types/react@19.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
ahooks:
|
ahooks:
|
||||||
specifier: ^3.9.5
|
specifier: ^3.9.5
|
||||||
version: 3.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 3.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
@@ -92,7 +95,7 @@ importers:
|
|||||||
version: 19.2.1(@types/react@19.2.2)
|
version: 19.2.1(@types/react@19.2.2)
|
||||||
'@vitejs/plugin-react':
|
'@vitejs/plugin-react':
|
||||||
specifier: ^5.0.4
|
specifier: ^5.0.4
|
||||||
version: 5.0.4(vite@7.1.9(@types/node@24.7.1))
|
version: 5.0.4(vite@7.1.9(@types/node@24.7.1)(terser@5.44.0))
|
||||||
eslint:
|
eslint:
|
||||||
specifier: ^9.36.0
|
specifier: ^9.36.0
|
||||||
version: 9.37.0
|
version: 9.37.0
|
||||||
@@ -113,7 +116,7 @@ importers:
|
|||||||
version: 8.46.0(eslint@9.37.0)(typescript@5.9.3)
|
version: 8.46.0(eslint@9.37.0)(typescript@5.9.3)
|
||||||
vite:
|
vite:
|
||||||
specifier: ^7.1.7
|
specifier: ^7.1.7
|
||||||
version: 7.1.9(@types/node@24.7.1)
|
version: 7.1.9(@types/node@24.7.1)(terser@5.44.0)
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
@@ -478,6 +481,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
||||||
|
'@jridgewell/source-map@0.3.11':
|
||||||
|
resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==}
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.5.5':
|
'@jridgewell/sourcemap-codec@1.5.5':
|
||||||
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
|
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
|
||||||
|
|
||||||
@@ -792,6 +798,24 @@ packages:
|
|||||||
'@types/babel__traverse@7.28.0':
|
'@types/babel__traverse@7.28.0':
|
||||||
resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
|
resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
|
||||||
|
|
||||||
|
'@types/d3-color@3.1.3':
|
||||||
|
resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==}
|
||||||
|
|
||||||
|
'@types/d3-drag@3.0.7':
|
||||||
|
resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==}
|
||||||
|
|
||||||
|
'@types/d3-interpolate@3.0.4':
|
||||||
|
resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==}
|
||||||
|
|
||||||
|
'@types/d3-selection@3.0.11':
|
||||||
|
resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==}
|
||||||
|
|
||||||
|
'@types/d3-transition@3.0.9':
|
||||||
|
resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==}
|
||||||
|
|
||||||
|
'@types/d3-zoom@3.0.8':
|
||||||
|
resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==}
|
||||||
|
|
||||||
'@types/estree@1.0.8':
|
'@types/estree@1.0.8':
|
||||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
||||||
|
|
||||||
@@ -891,6 +915,15 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
|
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
|
||||||
|
|
||||||
|
'@xyflow/react@12.8.6':
|
||||||
|
resolution: {integrity: sha512-SksAm2m4ySupjChphMmzvm55djtgMDPr+eovPDdTnyGvShf73cvydfoBfWDFllooIQ4IaiUL5yfxHRwU0c37EA==}
|
||||||
|
peerDependencies:
|
||||||
|
react: '>=17'
|
||||||
|
react-dom: '>=17'
|
||||||
|
|
||||||
|
'@xyflow/system@0.0.70':
|
||||||
|
resolution: {integrity: sha512-PpC//u9zxdjj0tfTSmZrg3+sRbTz6kop/Amky44U2Dl51sxzDTIUfXMwETOYpmr2dqICWXBIJwXL2a9QWtX2XA==}
|
||||||
|
|
||||||
acorn-jsx@5.3.2:
|
acorn-jsx@5.3.2:
|
||||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -950,6 +983,9 @@ packages:
|
|||||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
buffer-from@1.1.2:
|
||||||
|
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||||
|
|
||||||
call-bind-apply-helpers@1.0.2:
|
call-bind-apply-helpers@1.0.2:
|
||||||
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -965,6 +1001,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
classcat@5.0.5:
|
||||||
|
resolution: {integrity: sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==}
|
||||||
|
|
||||||
clsx@2.1.1:
|
clsx@2.1.1:
|
||||||
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
|
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -980,6 +1019,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
|
commander@2.20.3:
|
||||||
|
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
||||||
|
|
||||||
concat-map@0.0.1:
|
concat-map@0.0.1:
|
||||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||||
|
|
||||||
@@ -1004,6 +1046,44 @@ packages:
|
|||||||
csstype@3.1.3:
|
csstype@3.1.3:
|
||||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||||
|
|
||||||
|
d3-color@3.1.0:
|
||||||
|
resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
d3-dispatch@3.0.1:
|
||||||
|
resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
d3-drag@3.0.0:
|
||||||
|
resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
d3-ease@3.0.1:
|
||||||
|
resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
d3-interpolate@3.0.1:
|
||||||
|
resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
d3-selection@3.0.0:
|
||||||
|
resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
d3-timer@3.0.1:
|
||||||
|
resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
d3-transition@3.0.1:
|
||||||
|
resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
peerDependencies:
|
||||||
|
d3-selection: 2 - 3
|
||||||
|
|
||||||
|
d3-zoom@3.0.0:
|
||||||
|
resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
dayjs@1.11.18:
|
dayjs@1.11.18:
|
||||||
resolution: {integrity: sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==}
|
resolution: {integrity: sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==}
|
||||||
|
|
||||||
@@ -1601,10 +1681,17 @@ packages:
|
|||||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
source-map-support@0.5.21:
|
||||||
|
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
|
||||||
|
|
||||||
source-map@0.5.7:
|
source-map@0.5.7:
|
||||||
resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
|
resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
source-map@0.6.1:
|
||||||
|
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
strip-json-comments@3.1.1:
|
strip-json-comments@3.1.1:
|
||||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -1620,6 +1707,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
terser@5.44.0:
|
||||||
|
resolution: {integrity: sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
tinyglobby@0.2.15:
|
tinyglobby@0.2.15:
|
||||||
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
|
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
|
||||||
engines: {node: '>=12.0.0'}
|
engines: {node: '>=12.0.0'}
|
||||||
@@ -1738,6 +1830,21 @@ packages:
|
|||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
zustand@4.5.7:
|
||||||
|
resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==}
|
||||||
|
engines: {node: '>=12.7.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@types/react': '>=16.8'
|
||||||
|
immer: '>=9.0.6'
|
||||||
|
react: '>=16.8'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@types/react':
|
||||||
|
optional: true
|
||||||
|
immer:
|
||||||
|
optional: true
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
|
||||||
zustand@5.0.8:
|
zustand@5.0.8:
|
||||||
resolution: {integrity: sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw==}
|
resolution: {integrity: sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw==}
|
||||||
engines: {node: '>=12.20.0'}
|
engines: {node: '>=12.20.0'}
|
||||||
@@ -2102,6 +2209,12 @@ snapshots:
|
|||||||
|
|
||||||
'@jridgewell/resolve-uri@3.1.2': {}
|
'@jridgewell/resolve-uri@3.1.2': {}
|
||||||
|
|
||||||
|
'@jridgewell/source-map@0.3.11':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/gen-mapping': 0.3.13
|
||||||
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.5.5': {}
|
'@jridgewell/sourcemap-codec@1.5.5': {}
|
||||||
|
|
||||||
'@jridgewell/trace-mapping@0.3.31':
|
'@jridgewell/trace-mapping@0.3.31':
|
||||||
@@ -2358,6 +2471,27 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.28.4
|
'@babel/types': 7.28.4
|
||||||
|
|
||||||
|
'@types/d3-color@3.1.3': {}
|
||||||
|
|
||||||
|
'@types/d3-drag@3.0.7':
|
||||||
|
dependencies:
|
||||||
|
'@types/d3-selection': 3.0.11
|
||||||
|
|
||||||
|
'@types/d3-interpolate@3.0.4':
|
||||||
|
dependencies:
|
||||||
|
'@types/d3-color': 3.1.3
|
||||||
|
|
||||||
|
'@types/d3-selection@3.0.11': {}
|
||||||
|
|
||||||
|
'@types/d3-transition@3.0.9':
|
||||||
|
dependencies:
|
||||||
|
'@types/d3-selection': 3.0.11
|
||||||
|
|
||||||
|
'@types/d3-zoom@3.0.8':
|
||||||
|
dependencies:
|
||||||
|
'@types/d3-interpolate': 3.0.4
|
||||||
|
'@types/d3-selection': 3.0.11
|
||||||
|
|
||||||
'@types/estree@1.0.8': {}
|
'@types/estree@1.0.8': {}
|
||||||
|
|
||||||
'@types/js-cookie@3.0.6': {}
|
'@types/js-cookie@3.0.6': {}
|
||||||
@@ -2479,7 +2613,7 @@ snapshots:
|
|||||||
'@typescript-eslint/types': 8.46.0
|
'@typescript-eslint/types': 8.46.0
|
||||||
eslint-visitor-keys: 4.2.1
|
eslint-visitor-keys: 4.2.1
|
||||||
|
|
||||||
'@vitejs/plugin-react@5.0.4(vite@7.1.9(@types/node@24.7.1))':
|
'@vitejs/plugin-react@5.0.4(vite@7.1.9(@types/node@24.7.1)(terser@5.44.0))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.28.4
|
'@babel/core': 7.28.4
|
||||||
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4)
|
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4)
|
||||||
@@ -2487,10 +2621,33 @@ snapshots:
|
|||||||
'@rolldown/pluginutils': 1.0.0-beta.38
|
'@rolldown/pluginutils': 1.0.0-beta.38
|
||||||
'@types/babel__core': 7.20.5
|
'@types/babel__core': 7.20.5
|
||||||
react-refresh: 0.17.0
|
react-refresh: 0.17.0
|
||||||
vite: 7.1.9(@types/node@24.7.1)
|
vite: 7.1.9(@types/node@24.7.1)(terser@5.44.0)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
'@xyflow/react@12.8.6(@types/react@19.2.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
|
dependencies:
|
||||||
|
'@xyflow/system': 0.0.70
|
||||||
|
classcat: 5.0.5
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
zustand: 4.5.7(@types/react@19.2.2)(react@18.3.1)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@types/react'
|
||||||
|
- immer
|
||||||
|
|
||||||
|
'@xyflow/system@0.0.70':
|
||||||
|
dependencies:
|
||||||
|
'@types/d3-drag': 3.0.7
|
||||||
|
'@types/d3-interpolate': 3.0.4
|
||||||
|
'@types/d3-selection': 3.0.11
|
||||||
|
'@types/d3-transition': 3.0.9
|
||||||
|
'@types/d3-zoom': 3.0.8
|
||||||
|
d3-drag: 3.0.0
|
||||||
|
d3-interpolate: 3.0.1
|
||||||
|
d3-selection: 3.0.0
|
||||||
|
d3-zoom: 3.0.0
|
||||||
|
|
||||||
acorn-jsx@5.3.2(acorn@8.15.0):
|
acorn-jsx@5.3.2(acorn@8.15.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.15.0
|
acorn: 8.15.0
|
||||||
@@ -2566,6 +2723,9 @@ snapshots:
|
|||||||
node-releases: 2.0.23
|
node-releases: 2.0.23
|
||||||
update-browserslist-db: 1.1.3(browserslist@4.26.3)
|
update-browserslist-db: 1.1.3(browserslist@4.26.3)
|
||||||
|
|
||||||
|
buffer-from@1.1.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
call-bind-apply-helpers@1.0.2:
|
call-bind-apply-helpers@1.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
@@ -2580,6 +2740,8 @@ snapshots:
|
|||||||
ansi-styles: 4.3.0
|
ansi-styles: 4.3.0
|
||||||
supports-color: 7.2.0
|
supports-color: 7.2.0
|
||||||
|
|
||||||
|
classcat@5.0.5: {}
|
||||||
|
|
||||||
clsx@2.1.1: {}
|
clsx@2.1.1: {}
|
||||||
|
|
||||||
color-convert@2.0.1:
|
color-convert@2.0.1:
|
||||||
@@ -2592,6 +2754,9 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
delayed-stream: 1.0.0
|
delayed-stream: 1.0.0
|
||||||
|
|
||||||
|
commander@2.20.3:
|
||||||
|
optional: true
|
||||||
|
|
||||||
concat-map@0.0.1: {}
|
concat-map@0.0.1: {}
|
||||||
|
|
||||||
convert-source-map@1.9.0: {}
|
convert-source-map@1.9.0: {}
|
||||||
@@ -2616,6 +2781,42 @@ snapshots:
|
|||||||
|
|
||||||
csstype@3.1.3: {}
|
csstype@3.1.3: {}
|
||||||
|
|
||||||
|
d3-color@3.1.0: {}
|
||||||
|
|
||||||
|
d3-dispatch@3.0.1: {}
|
||||||
|
|
||||||
|
d3-drag@3.0.0:
|
||||||
|
dependencies:
|
||||||
|
d3-dispatch: 3.0.1
|
||||||
|
d3-selection: 3.0.0
|
||||||
|
|
||||||
|
d3-ease@3.0.1: {}
|
||||||
|
|
||||||
|
d3-interpolate@3.0.1:
|
||||||
|
dependencies:
|
||||||
|
d3-color: 3.1.0
|
||||||
|
|
||||||
|
d3-selection@3.0.0: {}
|
||||||
|
|
||||||
|
d3-timer@3.0.1: {}
|
||||||
|
|
||||||
|
d3-transition@3.0.1(d3-selection@3.0.0):
|
||||||
|
dependencies:
|
||||||
|
d3-color: 3.1.0
|
||||||
|
d3-dispatch: 3.0.1
|
||||||
|
d3-ease: 3.0.1
|
||||||
|
d3-interpolate: 3.0.1
|
||||||
|
d3-selection: 3.0.0
|
||||||
|
d3-timer: 3.0.1
|
||||||
|
|
||||||
|
d3-zoom@3.0.0:
|
||||||
|
dependencies:
|
||||||
|
d3-dispatch: 3.0.1
|
||||||
|
d3-drag: 3.0.0
|
||||||
|
d3-interpolate: 3.0.1
|
||||||
|
d3-selection: 3.0.0
|
||||||
|
d3-transition: 3.0.1(d3-selection@3.0.0)
|
||||||
|
|
||||||
dayjs@1.11.18: {}
|
dayjs@1.11.18: {}
|
||||||
|
|
||||||
debug@4.4.3:
|
debug@4.4.3:
|
||||||
@@ -3189,8 +3390,17 @@ snapshots:
|
|||||||
|
|
||||||
source-map-js@1.2.1: {}
|
source-map-js@1.2.1: {}
|
||||||
|
|
||||||
|
source-map-support@0.5.21:
|
||||||
|
dependencies:
|
||||||
|
buffer-from: 1.1.2
|
||||||
|
source-map: 0.6.1
|
||||||
|
optional: true
|
||||||
|
|
||||||
source-map@0.5.7: {}
|
source-map@0.5.7: {}
|
||||||
|
|
||||||
|
source-map@0.6.1:
|
||||||
|
optional: true
|
||||||
|
|
||||||
strip-json-comments@3.1.1: {}
|
strip-json-comments@3.1.1: {}
|
||||||
|
|
||||||
stylis@4.2.0: {}
|
stylis@4.2.0: {}
|
||||||
@@ -3201,6 +3411,14 @@ snapshots:
|
|||||||
|
|
||||||
supports-preserve-symlinks-flag@1.0.0: {}
|
supports-preserve-symlinks-flag@1.0.0: {}
|
||||||
|
|
||||||
|
terser@5.44.0:
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/source-map': 0.3.11
|
||||||
|
acorn: 8.15.0
|
||||||
|
commander: 2.20.3
|
||||||
|
source-map-support: 0.5.21
|
||||||
|
optional: true
|
||||||
|
|
||||||
tinyglobby@0.2.15:
|
tinyglobby@0.2.15:
|
||||||
dependencies:
|
dependencies:
|
||||||
fdir: 6.5.0(picomatch@4.0.3)
|
fdir: 6.5.0(picomatch@4.0.3)
|
||||||
@@ -3251,7 +3469,7 @@ snapshots:
|
|||||||
|
|
||||||
uuid@13.0.0: {}
|
uuid@13.0.0: {}
|
||||||
|
|
||||||
vite@7.1.9(@types/node@24.7.1):
|
vite@7.1.9(@types/node@24.7.1)(terser@5.44.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.25.10
|
esbuild: 0.25.10
|
||||||
fdir: 6.5.0(picomatch@4.0.3)
|
fdir: 6.5.0(picomatch@4.0.3)
|
||||||
@@ -3262,6 +3480,7 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 24.7.1
|
'@types/node': 24.7.1
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
terser: 5.44.0
|
||||||
|
|
||||||
void-elements@3.1.0: {}
|
void-elements@3.1.0: {}
|
||||||
|
|
||||||
@@ -3277,6 +3496,13 @@ snapshots:
|
|||||||
|
|
||||||
yocto-queue@0.1.0: {}
|
yocto-queue@0.1.0: {}
|
||||||
|
|
||||||
|
zustand@4.5.7(@types/react@19.2.2)(react@18.3.1):
|
||||||
|
dependencies:
|
||||||
|
use-sync-external-store: 1.6.0(react@18.3.1)
|
||||||
|
optionalDependencies:
|
||||||
|
'@types/react': 19.2.2
|
||||||
|
react: 18.3.1
|
||||||
|
|
||||||
zustand@5.0.8(@types/react@19.2.2)(react@18.3.1)(use-sync-external-store@1.6.0(react@18.3.1)):
|
zustand@5.0.8(@types/react@19.2.2)(react@18.3.1)(use-sync-external-store@1.6.0(react@18.3.1)):
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.2
|
'@types/react': 19.2.2
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect, useCallback } from 'react';
|
import { useState, useEffect, useCallback, useMemo } from 'react';
|
||||||
import knowledgeService from '@/services/knowledge_service';
|
import knowledgeService from '@/services/knowledge_service';
|
||||||
import type { IKnowledge, IKnowledgeResult, IParserConfig } from '@/interfaces/database/knowledge';
|
import type { IKnowledge, IKnowledgeGraph, IKnowledgeResult } from '@/interfaces/database/knowledge';
|
||||||
import type { IFetchKnowledgeListRequestParams } from '@/interfaces/request/knowledge';
|
import type { IFetchKnowledgeListRequestParams } from '@/interfaces/request/knowledge';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -200,6 +200,12 @@ export const useKnowledgeDetail = (kbId: string) => {
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const [knowledgeGraph, setKnowledgeGraph] = useState<IKnowledgeGraph | null>(null);
|
||||||
|
|
||||||
|
const showKnowledgeGraph = useMemo(() => {
|
||||||
|
return knowledgeGraph !== null && Object.keys(knowledgeGraph?.graph || {}).length > 0;
|
||||||
|
}, [knowledgeGraph]);
|
||||||
|
|
||||||
const fetchKnowledgeDetail = useCallback(async () => {
|
const fetchKnowledgeDetail = useCallback(async () => {
|
||||||
if (!kbId) return;
|
if (!kbId) return;
|
||||||
|
|
||||||
@@ -223,15 +229,41 @@ export const useKnowledgeDetail = (kbId: string) => {
|
|||||||
}
|
}
|
||||||
}, [kbId]);
|
}, [kbId]);
|
||||||
|
|
||||||
|
const fetchKnowledgeGraph = useCallback(async () => {
|
||||||
|
if (!kbId) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
setError(null);
|
||||||
|
|
||||||
|
const response = await knowledgeService.getKnowledgeGraph(kbId);
|
||||||
|
|
||||||
|
if (response.data.code === 0) {
|
||||||
|
setKnowledgeGraph(response.data.data);
|
||||||
|
} else {
|
||||||
|
throw new Error(response.data.message || '获取知识库图失败');
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
const errorMessage = err.response?.data?.message || err.message || '获取知识库图失败';
|
||||||
|
setError(errorMessage);
|
||||||
|
console.error('Failed to fetch knowledge graph:', err);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}, [kbId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchKnowledgeDetail();
|
fetchKnowledgeDetail();
|
||||||
}, [fetchKnowledgeDetail]);
|
fetchKnowledgeGraph();
|
||||||
|
}, [fetchKnowledgeDetail, fetchKnowledgeGraph]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
knowledge,
|
knowledge,
|
||||||
|
knowledgeGraph,
|
||||||
loading,
|
loading,
|
||||||
error,
|
error,
|
||||||
refresh: fetchKnowledgeDetail,
|
refresh: fetchKnowledgeDetail,
|
||||||
|
showKnowledgeGraph,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// import type { AgentCategory } from '@/constants/agent';
|
||||||
|
import type { Edge, Node } from '@xyflow/react';
|
||||||
|
import type { IReference, Message } from './chat';
|
||||||
|
|
||||||
export interface ICategorizeItem {
|
export interface ICategorizeItem {
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
@@ -30,11 +34,6 @@ export interface ISwitchForm {
|
|||||||
no: string;
|
no: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
import type { AgentCategory } from '@/constants/agent';
|
|
||||||
import type { Edge, Node } from '@xyflow/react';
|
|
||||||
import type { IReference, Message } from './chat';
|
|
||||||
|
|
||||||
export type DSLComponents = Record<string, IOperator>;
|
export type DSLComponents = Record<string, IOperator>;
|
||||||
|
|
||||||
export interface DSL {
|
export interface DSL {
|
||||||
@@ -157,7 +156,7 @@ export interface IAgentForm {
|
|||||||
delay_after_error: number;
|
delay_after_error: number;
|
||||||
visual_files_var: string;
|
visual_files_var: string;
|
||||||
max_rounds: number;
|
max_rounds: number;
|
||||||
exception_method: Nullable<'comment' | 'go'>;
|
// exception_method: Nullable<'comment' | 'go'>;
|
||||||
exception_comment: any;
|
exception_comment: any;
|
||||||
exception_goto: any;
|
exception_goto: any;
|
||||||
tools: Array<{
|
tools: Array<{
|
||||||
@@ -275,5 +274,5 @@ export interface IPipeLineListRequest {
|
|||||||
keywords?: string;
|
keywords?: string;
|
||||||
orderby?: string;
|
orderby?: string;
|
||||||
desc?: boolean;
|
desc?: boolean;
|
||||||
canvas_category?: AgentCategory;
|
// canvas_category?: AgentCategory;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { MessageType } from '@/constants/chat';
|
// import { MessageType } from '@/constants/chat';
|
||||||
|
|
||||||
export interface PromptConfig {
|
export interface PromptConfig {
|
||||||
empty_response: string;
|
empty_response: string;
|
||||||
@@ -89,7 +89,7 @@ export interface IConversation {
|
|||||||
|
|
||||||
export interface Message {
|
export interface Message {
|
||||||
content: string;
|
content: string;
|
||||||
role: MessageType;
|
// role: MessageType;
|
||||||
doc_ids?: string[];
|
doc_ids?: string[];
|
||||||
prompt?: string;
|
prompt?: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Edge, Node } from '@xyflow/react';
|
import type { Edge, Node } from '@xyflow/react';
|
||||||
import type { IReference, Message } from './chat';
|
import type { IReference, Message } from './chat';
|
||||||
|
|
||||||
export type DSLComponents = Record<string, IOperator>;
|
export type DSLComponents = Record<string, IOperator>;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export enum McpServerType {
|
// export enum McpServerType {
|
||||||
Sse = 'sse',
|
// Sse = 'sse',
|
||||||
StreamableHttp = 'streamable-http',
|
// StreamableHttp = 'streamable-http',
|
||||||
}
|
// }
|
||||||
|
|
||||||
export interface IMcpServerVariable {
|
export interface IMcpServerVariable {
|
||||||
key: string;
|
key: string;
|
||||||
@@ -12,7 +12,7 @@ export interface IMcpServerInfo {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
url: string;
|
url: string;
|
||||||
server_type: McpServerType;
|
// server_type: McpServerType;
|
||||||
description?: string;
|
description?: string;
|
||||||
variables?: IMcpServerVariable[];
|
variables?: IMcpServerVariable[];
|
||||||
headers: Map<string, string>;
|
headers: Map<string, string>;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { IExportedMcpServer } from '@/interfaces/database/mcp';
|
// import { IExportedMcpServer } from '@/interfaces/database/mcp';
|
||||||
|
|
||||||
export interface ITestMcpRequestBody {
|
export interface ITestMcpRequestBody {
|
||||||
server_type: string;
|
server_type: string;
|
||||||
@@ -9,8 +9,8 @@ export interface ITestMcpRequestBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IImportMcpServersRequestBody {
|
export interface IImportMcpServersRequestBody {
|
||||||
mcpServers: Record<
|
// mcpServers: Record<
|
||||||
string,
|
// string,
|
||||||
Pick<IExportedMcpServer, 'type' | 'url' | 'authorization_token'>
|
// Pick<IExportedMcpServer, 'type' | 'url' | 'authorization_token'>
|
||||||
>;
|
// >;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ const MetricValue = styled(Typography)(({ theme }) => ({
|
|||||||
lineHeight: 1.2,
|
lineHeight: 1.2,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const TrendIndicator = styled(Box)<{ trend: 'up' | 'down' }>(({ trend, theme }) => ({
|
const TrendIndicator = styled(Box)<{ trend: string }>(({ trend, theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: '0.25rem',
|
gap: '0.25rem',
|
||||||
@@ -245,7 +245,7 @@ const Dashboard: React.FC = () => {
|
|||||||
|
|
||||||
{/* 关键指标卡片 */}
|
{/* 关键指标卡片 */}
|
||||||
<Grid container spacing={3} sx={{ mb: 3 }}>
|
<Grid container spacing={3} sx={{ mb: 3 }}>
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<MetricCard>
|
<MetricCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -270,7 +270,7 @@ const Dashboard: React.FC = () => {
|
|||||||
</MetricCard>
|
</MetricCard>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<MetricCard>
|
<MetricCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -295,7 +295,7 @@ const Dashboard: React.FC = () => {
|
|||||||
</MetricCard>
|
</MetricCard>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<MetricCard>
|
<MetricCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -320,7 +320,7 @@ const Dashboard: React.FC = () => {
|
|||||||
</MetricCard>
|
</MetricCard>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<MetricCard>
|
<MetricCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -362,7 +362,7 @@ const Dashboard: React.FC = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
<KnowledgeGridView
|
<KnowledgeGridView
|
||||||
knowledgeBases={mockKnowledgeBases}
|
knowledgeBases={mockKnowledgeBases as any}
|
||||||
maxItems={3}
|
maxItems={3}
|
||||||
showSeeAll={true}
|
showSeeAll={true}
|
||||||
onSeeAll={handleSeeAllKnowledgeBases}
|
onSeeAll={handleSeeAllKnowledgeBases}
|
||||||
@@ -372,7 +372,7 @@ const Dashboard: React.FC = () => {
|
|||||||
|
|
||||||
{/* 系统状态 */}
|
{/* 系统状态 */}
|
||||||
<Grid container spacing={3} sx={{ mb: 3 }}>
|
<Grid container spacing={3} sx={{ mb: 3 }}>
|
||||||
<Grid item xs={12} md={6}>
|
<Grid size={{xs:12,md:6}}>
|
||||||
<Card sx={{ border: '1px solid #E5E5E5' }}>
|
<Card sx={{ border: '1px solid #E5E5E5' }}>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="h6" fontWeight={600} mb={2}>
|
<Typography variant="h6" fontWeight={600} mb={2}>
|
||||||
@@ -403,7 +403,7 @@ const Dashboard: React.FC = () => {
|
|||||||
</Card>
|
</Card>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} md={6}>
|
<Grid size={{xs:12,md:6}}>
|
||||||
<Card sx={{ border: '1px solid #E5E5E5' }}>
|
<Card sx={{ border: '1px solid #E5E5E5' }}>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="h6" fontWeight={600} mb={2}>
|
<Typography variant="h6" fontWeight={600} mb={2}>
|
||||||
@@ -479,15 +479,6 @@ const Dashboard: React.FC = () => {
|
|||||||
</TableContainer>
|
</TableContainer>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* 用户数据调试组件 - 仅在开发环境显示 */}
|
|
||||||
{process.env.NODE_ENV === 'development' && (
|
|
||||||
<Card sx={{ border: '1px solid #E5E5E5', mt: 3 }}>
|
|
||||||
<CardContent>
|
|
||||||
<UserDataDebug />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ const MCP: React.FC = () => {
|
|||||||
<>
|
<>
|
||||||
{/* 状态概览 */}
|
{/* 状态概览 */}
|
||||||
<Grid container spacing={3} sx={{ mb: 3 }}>
|
<Grid container spacing={3} sx={{ mb: 3 }}>
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<StatusCard>
|
<StatusCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -211,7 +211,7 @@ const MCP: React.FC = () => {
|
|||||||
</StatusCard>
|
</StatusCard>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<StatusCard>
|
<StatusCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -229,7 +229,7 @@ const MCP: React.FC = () => {
|
|||||||
</StatusCard>
|
</StatusCard>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<StatusCard>
|
<StatusCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -247,7 +247,7 @@ const MCP: React.FC = () => {
|
|||||||
</StatusCard>
|
</StatusCard>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<StatusCard>
|
<StatusCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -359,7 +359,7 @@ const MCP: React.FC = () => {
|
|||||||
</Alert>
|
</Alert>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
{mockMCPServers.map((server) => (
|
{mockMCPServers.map((server) => (
|
||||||
<Grid item xs={12} md={6} key={server.id}>
|
<Grid size={{xs:12,md:6}} key={server.id}>
|
||||||
<Card variant="outlined">
|
<Card variant="outlined">
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="subtitle1" fontWeight={600} mb={1}>
|
<Typography variant="subtitle1" fontWeight={600} mb={1}>
|
||||||
@@ -389,7 +389,7 @@ const MCP: React.FC = () => {
|
|||||||
|
|
||||||
{tabValue === 2 && (
|
{tabValue === 2 && (
|
||||||
<Grid container spacing={3}>
|
<Grid container spacing={3}>
|
||||||
<Grid item xs={12} md={6}>
|
<Grid size={{xs:12,md:6}}>
|
||||||
<Card sx={{ border: '1px solid #E5E5E5' }}>
|
<Card sx={{ border: '1px solid #E5E5E5' }}>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="h6" fontWeight={600} mb={2}>
|
<Typography variant="h6" fontWeight={600} mb={2}>
|
||||||
@@ -418,7 +418,7 @@ const MCP: React.FC = () => {
|
|||||||
</Card>
|
</Card>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} md={6}>
|
<Grid size={{xs:12,md:6}}>
|
||||||
<Card sx={{ border: '1px solid #E5E5E5' }}>
|
<Card sx={{ border: '1px solid #E5E5E5' }}>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="h6" fontWeight={600} mb={2}>
|
<Typography variant="h6" fontWeight={600} mb={2}>
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ const ModelsResources: React.FC = () => {
|
|||||||
<>
|
<>
|
||||||
{/* 模型概览卡片 */}
|
{/* 模型概览卡片 */}
|
||||||
<Grid container spacing={3} sx={{ mb: 3 }}>
|
<Grid container spacing={3} sx={{ mb: 3 }}>
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<ResourceCard>
|
<ResourceCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -244,7 +244,7 @@ const ModelsResources: React.FC = () => {
|
|||||||
</ResourceCard>
|
</ResourceCard>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<ResourceCard>
|
<ResourceCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -262,7 +262,7 @@ const ModelsResources: React.FC = () => {
|
|||||||
</ResourceCard>
|
</ResourceCard>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<ResourceCard>
|
<ResourceCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -280,7 +280,7 @@ const ModelsResources: React.FC = () => {
|
|||||||
</ResourceCard>
|
</ResourceCard>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<ResourceCard>
|
<ResourceCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -385,7 +385,7 @@ const ModelsResources: React.FC = () => {
|
|||||||
<>
|
<>
|
||||||
{/* 资源概览卡片 */}
|
{/* 资源概览卡片 */}
|
||||||
<Grid container spacing={3} sx={{ mb: 3 }}>
|
<Grid container spacing={3} sx={{ mb: 3 }}>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid size={{xs:12,sm:6,md:4}}>
|
||||||
<ResourceCard>
|
<ResourceCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -403,7 +403,7 @@ const ModelsResources: React.FC = () => {
|
|||||||
</ResourceCard>
|
</ResourceCard>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid size={{xs:12,sm:6,md:4}}>
|
||||||
<ResourceCard>
|
<ResourceCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
@@ -421,7 +421,7 @@ const ModelsResources: React.FC = () => {
|
|||||||
</ResourceCard>
|
</ResourceCard>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid size={{xs:12,sm:6,md:4}}>
|
||||||
<ResourceCard>
|
<ResourceCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ const PipelineConfig: React.FC = () => {
|
|||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
<Grid container spacing={3}>
|
<Grid container spacing={3}>
|
||||||
<Grid item xs={12} md={6}>
|
<Grid size={{xs:12,md:6}}>
|
||||||
<ConfigCard>
|
<ConfigCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="h6" fontWeight={600} mb={2}>
|
<Typography variant="h6" fontWeight={600} mb={2}>
|
||||||
@@ -223,7 +223,7 @@ const PipelineConfig: React.FC = () => {
|
|||||||
</ConfigCard>
|
</ConfigCard>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} md={6}>
|
<Grid size={{xs:12,md:6}}>
|
||||||
<ConfigCard>
|
<ConfigCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="h6" fontWeight={600} mb={2}>
|
<Typography variant="h6" fontWeight={600} mb={2}>
|
||||||
@@ -283,7 +283,7 @@ const PipelineConfig: React.FC = () => {
|
|||||||
</ConfigCard>
|
</ConfigCard>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12}>
|
<Grid size={{xs:12,md:6}}>
|
||||||
<ConfigCard>
|
<ConfigCard>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="h6" fontWeight={600} mb={2}>
|
<Typography variant="h6" fontWeight={600} mb={2}>
|
||||||
@@ -291,7 +291,7 @@ const PipelineConfig: React.FC = () => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<Box textAlign="center" p={2} bgcolor="#F8F9FA" borderRadius="6px">
|
<Box textAlign="center" p={2} bgcolor="#F8F9FA" borderRadius="6px">
|
||||||
<Typography variant="h4" color="primary" fontWeight={600}>
|
<Typography variant="h4" color="primary" fontWeight={600}>
|
||||||
1,234
|
1,234
|
||||||
@@ -301,7 +301,7 @@ const PipelineConfig: React.FC = () => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<Box textAlign="center" p={2} bgcolor="#F8F9FA" borderRadius="6px">
|
<Box textAlign="center" p={2} bgcolor="#F8F9FA" borderRadius="6px">
|
||||||
<Typography variant="h4" color="success.main" fontWeight={600}>
|
<Typography variant="h4" color="success.main" fontWeight={600}>
|
||||||
98.5%
|
98.5%
|
||||||
@@ -311,7 +311,7 @@ const PipelineConfig: React.FC = () => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<Box textAlign="center" p={2} bgcolor="#F8F9FA" borderRadius="6px">
|
<Box textAlign="center" p={2} bgcolor="#F8F9FA" borderRadius="6px">
|
||||||
<Typography variant="h4" color="warning.main" fontWeight={600}>
|
<Typography variant="h4" color="warning.main" fontWeight={600}>
|
||||||
2.3s
|
2.3s
|
||||||
@@ -321,7 +321,7 @@ const PipelineConfig: React.FC = () => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={3}>
|
<Grid size={{xs:12,sm:6,md:3}}>
|
||||||
<Box textAlign="center" p={2} bgcolor="#F8F9FA" borderRadius="6px">
|
<Box textAlign="center" p={2} bgcolor="#F8F9FA" borderRadius="6px">
|
||||||
<Typography variant="h4" color="info.main" fontWeight={600}>
|
<Typography variant="h4" color="info.main" fontWeight={600}>
|
||||||
156
|
156
|
||||||
|
|||||||
351
src/pages/knowledge/components/KnowledgeGraphView.tsx
Normal file
351
src/pages/knowledge/components/KnowledgeGraphView.tsx
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
import React, { useMemo, useCallback } from 'react';
|
||||||
|
import {
|
||||||
|
ReactFlow,
|
||||||
|
type Node,
|
||||||
|
type Edge,
|
||||||
|
Controls,
|
||||||
|
Background,
|
||||||
|
useNodesState,
|
||||||
|
useEdgesState,
|
||||||
|
ConnectionMode,
|
||||||
|
Panel,
|
||||||
|
Handle,
|
||||||
|
Position,
|
||||||
|
} from '@xyflow/react';
|
||||||
|
import '@xyflow/react/dist/style.css';
|
||||||
|
import { Box, Typography, Alert, Chip, Card, CardContent, Tooltip, Avatar } from '@mui/material';
|
||||||
|
import type { IKnowledgeGraph } from '@/interfaces/database/knowledge';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
interface KnowledgeGraphProps {
|
||||||
|
knowledgeGraph?: IKnowledgeGraph | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据实体类型获取节点颜色
|
||||||
|
const getNodeColor = (entityType?: string): string => {
|
||||||
|
const colorMap: Record<string, string> = {
|
||||||
|
PERSON: '#FF6B6B', // 红色 - 人物
|
||||||
|
ORGANIZATION: '#4ECDC4', // 青色 - 组织
|
||||||
|
LOCATION: '#45B7D1', // 蓝色 - 地点
|
||||||
|
EVENT: '#96CEB4', // 绿色 - 事件
|
||||||
|
CONCEPT: '#FFEAA7', // 黄色 - 概念
|
||||||
|
CATEGORY: '#DDA0DD', // 紫色 - 分类
|
||||||
|
TECHNOLOGY: '#98D8C8', // 薄荷绿 - 技术
|
||||||
|
PRODUCT: '#F7DC6F', // 金黄色 - 产品
|
||||||
|
SERVICE: '#BB8FCE', // 淡紫色 - 服务
|
||||||
|
};
|
||||||
|
return colorMap[entityType || 'CONCEPT'] || '#74B9FF';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 自定义节点组件
|
||||||
|
const CustomNode = ({ data }: { data: any }) => {
|
||||||
|
const nodeColor = getNodeColor(data.entity_type);
|
||||||
|
const nodeSize = Math.max(80, Math.min(140, (data.pagerank || 0.1) * 500));
|
||||||
|
|
||||||
|
// 获取节点首字母作为Avatar显示
|
||||||
|
const getInitials = (name: string) => {
|
||||||
|
if (!name) return '?';
|
||||||
|
const words = name.trim().split(/\s+/);
|
||||||
|
if (words.length === 1) {
|
||||||
|
return words[0].charAt(0).toUpperCase();
|
||||||
|
}
|
||||||
|
return words.slice(0, 2).map(word => word.charAt(0).toUpperCase()).join('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const tooltipContent = (
|
||||||
|
<Box sx={{ p: 1, maxWidth: 300 }}>
|
||||||
|
<Typography variant="subtitle2" sx={{ fontWeight: 'bold', mb: 1 }}>
|
||||||
|
{data.label || data.name || 'Unknown'}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" sx={{ mb: 0.5 }}>
|
||||||
|
<strong>类型:</strong> {data.entity_type || 'Unknown'}
|
||||||
|
</Typography>
|
||||||
|
{data.description && (
|
||||||
|
<Typography variant="body2">
|
||||||
|
<strong>描述:</strong> {data.description}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
{data.pagerank && (
|
||||||
|
<Typography variant="caption" sx={{ display: 'block', mt: 1 }}>
|
||||||
|
PageRank: {data.pagerank.toFixed(4)}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip
|
||||||
|
title={tooltipContent}
|
||||||
|
placement="top"
|
||||||
|
arrow
|
||||||
|
enterDelay={500}
|
||||||
|
leaveDelay={200}
|
||||||
|
>
|
||||||
|
<Card
|
||||||
|
sx={{
|
||||||
|
width: nodeSize,
|
||||||
|
height: nodeSize,
|
||||||
|
borderRadius: '50%',
|
||||||
|
border: '3px solid #fff',
|
||||||
|
boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
|
||||||
|
cursor: 'pointer',
|
||||||
|
position: 'relative',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor: nodeColor,
|
||||||
|
transition: 'all 0.2s ease-in-out',
|
||||||
|
'&:hover': {
|
||||||
|
transform: 'scale(1.1)',
|
||||||
|
boxShadow: '0 6px 20px rgba(0,0,0,0.25)',
|
||||||
|
zIndex: 10,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* React Flow Handle 组件 */}
|
||||||
|
<Handle
|
||||||
|
type="target"
|
||||||
|
position={Position.Top}
|
||||||
|
style={{ background: '#555', opacity: 0 }}
|
||||||
|
/>
|
||||||
|
<Handle
|
||||||
|
type="source"
|
||||||
|
position={Position.Bottom}
|
||||||
|
style={{ background: '#555', opacity: 0 }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CardContent
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
p: 1,
|
||||||
|
'&:last-child': { pb: 1 },
|
||||||
|
height: '100%',
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
variant="caption"
|
||||||
|
sx={{
|
||||||
|
color: '#fff',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: Math.max(10, nodeSize * 0.08),
|
||||||
|
textAlign: 'center',
|
||||||
|
lineHeight: 1.1,
|
||||||
|
wordBreak: 'break-word',
|
||||||
|
textShadow: '1px 1px 2px rgba(0,0,0,0.7)',
|
||||||
|
maxWidth: '90%',
|
||||||
|
overflow: 'hidden',
|
||||||
|
display: '-webkit-box',
|
||||||
|
WebkitLineClamp: 2,
|
||||||
|
WebkitBoxOrient: 'vertical',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{data.label || data.name || 'Unknown'}
|
||||||
|
</Typography>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const nodeTypes = {
|
||||||
|
custom: CustomNode,
|
||||||
|
};
|
||||||
|
|
||||||
|
const KnowledgeGraphView: React.FC<KnowledgeGraphProps> = ({ knowledgeGraph }) => {
|
||||||
|
// 转换数据格式为 React Flow 所需的格式
|
||||||
|
const { nodes: initialNodes, edges: initialEdges } = useMemo(() => {
|
||||||
|
const graphData = knowledgeGraph?.graph || {};
|
||||||
|
if (!graphData?.nodes || !graphData?.edges) {
|
||||||
|
return { nodes: [], edges: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换节点数据
|
||||||
|
// @ts-ignore
|
||||||
|
const nodes: Node[] = graphData.nodes.map((node, index) => {
|
||||||
|
console.log(`节点 ${index}:`, node);
|
||||||
|
console.log(`节点ID: ${node.id}`);
|
||||||
|
|
||||||
|
const encodeId = encodeURIComponent(String(node.id));
|
||||||
|
|
||||||
|
const n: Node = {
|
||||||
|
id: encodeId,
|
||||||
|
type: 'custom',
|
||||||
|
position: {
|
||||||
|
x: Math.random() * 800,
|
||||||
|
y: Math.random() * 600,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
label: node.entity_name || node.id,
|
||||||
|
entity_type: node.entity_type,
|
||||||
|
pagerank: node.pagerank,
|
||||||
|
description: node.description,
|
||||||
|
...node,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return n
|
||||||
|
});
|
||||||
|
|
||||||
|
// 转换边数据
|
||||||
|
// @ts-ignore
|
||||||
|
const edges: Edge[] = graphData.edges.map((edge, index) => {
|
||||||
|
console.log(`边 ${index}:`, edge);
|
||||||
|
console.log(`src_id: ${edge.src_id}, tgt_id: ${edge.tgt_id}`);
|
||||||
|
// 检查source和target是否存在
|
||||||
|
if (!edge.src_id || !edge.tgt_id) {
|
||||||
|
console.warn(`边 ${index} 缺少src_id或tgt_id:`, edge);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查对应的节点是否存在
|
||||||
|
const sourceExists = nodes.some(node => node.id === encodeURIComponent(edge.src_id));
|
||||||
|
const targetExists = nodes.some(node => node.id === encodeURIComponent(edge.tgt_id));
|
||||||
|
|
||||||
|
if (!sourceExists || !targetExists) {
|
||||||
|
console.warn(`边 ${index} 的节点不存在: source=${sourceExists}, target=${targetExists}`, edge);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const weight = Number(edge.weight) || 1;
|
||||||
|
const strokeWidth = Math.max(1, Math.min(3, weight));
|
||||||
|
|
||||||
|
const sourceId = encodeURIComponent(String(edge.src_id));
|
||||||
|
const targetId = encodeURIComponent(String(edge.tgt_id));
|
||||||
|
|
||||||
|
const edgeObj: Edge = {
|
||||||
|
id: `${sourceId}-${targetId}`,
|
||||||
|
source: sourceId,
|
||||||
|
target: targetId,
|
||||||
|
type: 'simplebezier',
|
||||||
|
// animated: weight > 5,
|
||||||
|
style: {
|
||||||
|
strokeWidth,
|
||||||
|
stroke: '#99ADD1',
|
||||||
|
},
|
||||||
|
// label: edge.description ? edge.description.substring(0, 50) + '...' : '',
|
||||||
|
labelStyle: {
|
||||||
|
fontSize: '10px',
|
||||||
|
fill: '#666',
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
weight: edge.weight,
|
||||||
|
description: edge.description,
|
||||||
|
keywords: edge.keywords,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return edgeObj;
|
||||||
|
})
|
||||||
|
// @ts-ignore
|
||||||
|
.filter(edge => edge != null); // 过滤掉null值
|
||||||
|
return { nodes, edges };
|
||||||
|
}, [knowledgeGraph]);
|
||||||
|
|
||||||
|
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
||||||
|
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
||||||
|
|
||||||
|
console.log('转换后的节点:', nodes);
|
||||||
|
console.log('转换后的边:', edges);
|
||||||
|
// 节点点击事件
|
||||||
|
const onNodeClick = useCallback((event: React.MouseEvent, node: Node) => {
|
||||||
|
console.log('节点点击:', node.data);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 边点击事件
|
||||||
|
const onEdgeClick = useCallback((event: React.MouseEvent, edge: Edge) => {
|
||||||
|
console.log('边点击:', edge.data);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!knowledgeGraph || initialNodes.length === 0) {
|
||||||
|
return (
|
||||||
|
<Box sx={{ p: 2, display: 'flex', justifyContent: 'center', alignItems: 'center', height: 400 }}>
|
||||||
|
<Alert severity="info">暂无知识图谱数据</Alert>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ width: '100%', height: '600px', border: '1px solid #e0e0e0', borderRadius: 1 }}>
|
||||||
|
<ReactFlow
|
||||||
|
nodes={nodes}
|
||||||
|
edges={edges}
|
||||||
|
onNodesChange={onNodesChange}
|
||||||
|
onEdgesChange={onEdgesChange}
|
||||||
|
onNodeClick={onNodeClick}
|
||||||
|
onEdgeClick={onEdgeClick}
|
||||||
|
nodeTypes={nodeTypes}
|
||||||
|
connectionMode={ConnectionMode.Loose}
|
||||||
|
fitView
|
||||||
|
fitViewOptions={{ padding: 0.2 }}
|
||||||
|
minZoom={0.1}
|
||||||
|
maxZoom={2}
|
||||||
|
>
|
||||||
|
<Background />
|
||||||
|
<Controls />
|
||||||
|
|
||||||
|
{/* 图例面板 */}
|
||||||
|
<Panel position="top-right">
|
||||||
|
<Box sx={{
|
||||||
|
backgroundColor: 'rgba(255,255,255,0.9)',
|
||||||
|
p: 2,
|
||||||
|
borderRadius: 1,
|
||||||
|
minWidth: 200,
|
||||||
|
boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
|
||||||
|
}}>
|
||||||
|
<Typography variant="subtitle2" sx={{ mb: 1, fontWeight: 'bold' }}>
|
||||||
|
图例
|
||||||
|
</Typography>
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
|
||||||
|
{['PERSON', 'ORGANIZATION', 'CATEGORY', 'TECHNOLOGY'].map((type) => (
|
||||||
|
<Box key={type} sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
borderRadius: '50%',
|
||||||
|
backgroundColor: getNodeColor(type),
|
||||||
|
border: '1px solid #fff',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Typography variant="caption">{type}</Typography>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Panel>
|
||||||
|
|
||||||
|
{/* 统计信息面板 */}
|
||||||
|
<Panel position="top-left">
|
||||||
|
<Box sx={{
|
||||||
|
backgroundColor: 'rgba(255,255,255,0.9)',
|
||||||
|
p: 2,
|
||||||
|
borderRadius: 1,
|
||||||
|
boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
|
||||||
|
}}>
|
||||||
|
<Typography variant="subtitle2" sx={{ mb: 1, fontWeight: 'bold' }}>
|
||||||
|
图谱统计
|
||||||
|
</Typography>
|
||||||
|
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
|
||||||
|
<Chip
|
||||||
|
label={`节点: ${nodes.length}`}
|
||||||
|
size="small"
|
||||||
|
color="primary"
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
|
<Chip
|
||||||
|
label={`边: ${edges.length}`}
|
||||||
|
size="small"
|
||||||
|
color="secondary"
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Panel>
|
||||||
|
</ReactFlow>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KnowledgeGraphView;
|
||||||
@@ -18,9 +18,10 @@ import {
|
|||||||
CardContent,
|
CardContent,
|
||||||
Divider,
|
Divider,
|
||||||
Chip,
|
Chip,
|
||||||
|
Tabs,
|
||||||
|
Tab,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { type GridRowSelectionModel } from '@mui/x-data-grid';
|
import { type GridRowSelectionModel } from '@mui/x-data-grid';
|
||||||
import knowledgeService from '@/services/knowledge_service';
|
|
||||||
import type { IKnowledge, IKnowledgeFile } from '@/interfaces/database/knowledge';
|
import type { IKnowledge, IKnowledgeFile } from '@/interfaces/database/knowledge';
|
||||||
import type { IDocumentInfoFilter } from '@/interfaces/database/document';
|
import type { IDocumentInfoFilter } from '@/interfaces/database/document';
|
||||||
import FileUploadDialog from '@/components/FileUploadDialog';
|
import FileUploadDialog from '@/components/FileUploadDialog';
|
||||||
@@ -28,16 +29,16 @@ import KnowledgeInfoCard from './components/KnowledgeInfoCard';
|
|||||||
import DocumentListComponent from './components/DocumentListComponent';
|
import DocumentListComponent from './components/DocumentListComponent';
|
||||||
import FloatingActionButtons from './components/FloatingActionButtons';
|
import FloatingActionButtons from './components/FloatingActionButtons';
|
||||||
import KnowledgeBreadcrumbs from './components/KnowledgeBreadcrumbs';
|
import KnowledgeBreadcrumbs from './components/KnowledgeBreadcrumbs';
|
||||||
|
import KnowledgeGraphView from './components/KnowledgeGraphView';
|
||||||
import { useDocumentList, useDocumentOperations } from '@/hooks/document-hooks';
|
import { useDocumentList, useDocumentOperations } from '@/hooks/document-hooks';
|
||||||
import { RUNNING_STATUS_KEYS } from '@/constants/knowledge';
|
import { RUNNING_STATUS_KEYS } from '@/constants/knowledge';
|
||||||
|
import { useKnowledgeDetail } from '@/hooks/knowledge-hooks';
|
||||||
|
|
||||||
function KnowledgeBaseDetail() {
|
function KnowledgeBaseDetail() {
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
// 状态管理
|
// 状态管理
|
||||||
const [knowledgeBase, setKnowledgeBase] = useState<IKnowledge | null>(null);
|
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [searchKeyword, setSearchKeyword] = useState('');
|
const [searchKeyword, setSearchKeyword] = useState('');
|
||||||
const [rowSelectionModel, setRowSelectionModel] = useState<GridRowSelectionModel>({
|
const [rowSelectionModel, setRowSelectionModel] = useState<GridRowSelectionModel>({
|
||||||
@@ -46,11 +47,13 @@ function KnowledgeBaseDetail() {
|
|||||||
});
|
});
|
||||||
const [uploadDialogOpen, setUploadDialogOpen] = useState(false);
|
const [uploadDialogOpen, setUploadDialogOpen] = useState(false);
|
||||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||||
const [testingDialogOpen, setTestingDialogOpen] = useState(false);
|
|
||||||
const [configDialogOpen, setConfigDialogOpen] = useState(false);
|
|
||||||
const [processDetailsDialogOpen, setProcessDetailsDialogOpen] = useState(false);
|
const [processDetailsDialogOpen, setProcessDetailsDialogOpen] = useState(false);
|
||||||
const [selectedFileDetails, setSelectedFileDetails] = useState<IKnowledgeFile | null>(null);
|
const [selectedFileDetails, setSelectedFileDetails] = useState<IKnowledgeFile | null>(null);
|
||||||
|
|
||||||
|
// 标签页状态
|
||||||
|
const [currentTab, setCurrentTab] = useState(0);
|
||||||
|
|
||||||
// 轮询相关状态
|
// 轮询相关状态
|
||||||
const pollingIntervalRef = useRef<any>(null);
|
const pollingIntervalRef = useRef<any>(null);
|
||||||
const [isPolling, setIsPolling] = useState(false);
|
const [isPolling, setIsPolling] = useState(false);
|
||||||
@@ -80,25 +83,9 @@ function KnowledgeBaseDetail() {
|
|||||||
error: operationError,
|
error: operationError,
|
||||||
} = useDocumentOperations();
|
} = useDocumentOperations();
|
||||||
|
|
||||||
// 获取知识库详情
|
const { knowledge: knowledgeBase, refresh: fetchKnowledgeDetail, loading, showKnowledgeGraph, knowledgeGraph } = useKnowledgeDetail(id || '');
|
||||||
const fetchKnowledgeDetail = async () => {
|
|
||||||
if (!id) return;
|
|
||||||
|
|
||||||
try {
|
console.log('showKnowledgeGraph:', showKnowledgeGraph, knowledgeGraph);
|
||||||
setLoading(true);
|
|
||||||
const response = await knowledgeService.getKnowledgeDetail({ kb_id: id });
|
|
||||||
|
|
||||||
if (response.data.code === 0) {
|
|
||||||
setKnowledgeBase(response.data.data);
|
|
||||||
} else {
|
|
||||||
setError(response.data.message || '获取知识库详情失败');
|
|
||||||
}
|
|
||||||
} catch (err: any) {
|
|
||||||
setError(err.response?.data?.message || err.message || '获取知识库详情失败');
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 删除文件
|
// 删除文件
|
||||||
const handleDeleteFiles = async () => {
|
const handleDeleteFiles = async () => {
|
||||||
@@ -291,7 +278,21 @@ function KnowledgeBaseDetail() {
|
|||||||
{/* 知识库信息卡片 */}
|
{/* 知识库信息卡片 */}
|
||||||
<KnowledgeInfoCard knowledgeBase={knowledgeBase} />
|
<KnowledgeInfoCard knowledgeBase={knowledgeBase} />
|
||||||
|
|
||||||
{/* 文件列表组件 */}
|
{/* 标签页组件 - 仅在showKnowledgeGraph为true时显示 */}
|
||||||
|
{showKnowledgeGraph ? (
|
||||||
|
<Box sx={{ mt: 3 }}>
|
||||||
|
<Tabs
|
||||||
|
value={currentTab}
|
||||||
|
onChange={(event, newValue) => setCurrentTab(newValue)}
|
||||||
|
sx={{ borderBottom: 1, borderColor: 'divider' }}
|
||||||
|
>
|
||||||
|
<Tab label="Documents" />
|
||||||
|
<Tab label="Graph" />
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
{/* Document List 标签页内容 */}
|
||||||
|
{currentTab === 0 && (
|
||||||
|
<Box sx={{ mt: 2 }}>
|
||||||
<DocumentListComponent
|
<DocumentListComponent
|
||||||
files={files}
|
files={files}
|
||||||
loading={filesLoading}
|
loading={filesLoading}
|
||||||
@@ -327,6 +328,54 @@ function KnowledgeBaseDetail() {
|
|||||||
onViewDetails={handleViewDetails}
|
onViewDetails={handleViewDetails}
|
||||||
onViewProcessDetails={handleViewProcessDetails}
|
onViewProcessDetails={handleViewProcessDetails}
|
||||||
/>
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Graph 标签页内容 */}
|
||||||
|
{currentTab === 1 && (
|
||||||
|
<Box sx={{ mt: 2 }}>
|
||||||
|
<KnowledgeGraphView knowledgeGraph={knowledgeGraph} />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
/* 原有的文件列表组件 - 当showKnowledgeGraph为false时显示 */
|
||||||
|
<DocumentListComponent
|
||||||
|
files={files}
|
||||||
|
loading={filesLoading}
|
||||||
|
searchKeyword={searchKeyword}
|
||||||
|
onSearchChange={setSearchKeyword}
|
||||||
|
onReparse={(fileIds) => handleReparse(fileIds)}
|
||||||
|
onDelete={(fileIds) => {
|
||||||
|
console.log('删除文件:', fileIds);
|
||||||
|
setRowSelectionModel({
|
||||||
|
type: 'include',
|
||||||
|
ids: new Set(fileIds)
|
||||||
|
});
|
||||||
|
setDeleteDialogOpen(true);
|
||||||
|
}}
|
||||||
|
onUpload={() => setUploadDialogOpen(true)}
|
||||||
|
onRefresh={() => {
|
||||||
|
refreshFiles();
|
||||||
|
fetchKnowledgeDetail();
|
||||||
|
}}
|
||||||
|
rowSelectionModel={rowSelectionModel}
|
||||||
|
onRowSelectionModelChange={(newModel) => {
|
||||||
|
console.log('新的选择模型:', newModel);
|
||||||
|
setRowSelectionModel(newModel);
|
||||||
|
}}
|
||||||
|
total={total}
|
||||||
|
page={currentPage}
|
||||||
|
pageSize={pageSize}
|
||||||
|
onPageChange={setCurrentPage}
|
||||||
|
onPageSizeChange={setPageSize}
|
||||||
|
onRename={handleRename}
|
||||||
|
onChangeStatus={handleChangeStatus}
|
||||||
|
onCancelRun={handleCancelRun}
|
||||||
|
onViewDetails={handleViewDetails}
|
||||||
|
onViewProcessDetails={handleViewProcessDetails}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* 浮动操作按钮 */}
|
{/* 浮动操作按钮 */}
|
||||||
<FloatingActionButtons
|
<FloatingActionButtons
|
||||||
@@ -359,88 +408,6 @@ function KnowledgeBaseDetail() {
|
|||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
{/* 检索测试对话框 */}
|
|
||||||
<Dialog open={testingDialogOpen} onClose={() => setTestingDialogOpen(false)} maxWidth="md" fullWidth>
|
|
||||||
<DialogTitle>检索测试</DialogTitle>
|
|
||||||
<DialogContent>
|
|
||||||
<Stack spacing={3} sx={{ mt: 1 }}>
|
|
||||||
<TextField
|
|
||||||
fullWidth
|
|
||||||
label="测试查询"
|
|
||||||
placeholder="输入要测试的查询内容..."
|
|
||||||
multiline
|
|
||||||
rows={3}
|
|
||||||
/>
|
|
||||||
<Stack direction="row" spacing={2}>
|
|
||||||
<TextField
|
|
||||||
label="返回结果数量"
|
|
||||||
type="number"
|
|
||||||
defaultValue={5}
|
|
||||||
sx={{ width: 150 }}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
label="相似度阈值"
|
|
||||||
type="number"
|
|
||||||
defaultValue={0.7}
|
|
||||||
inputProps={{ min: 0, max: 1, step: 0.1 }}
|
|
||||||
sx={{ width: 150 }}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
<Box sx={{ minHeight: 200, border: '1px solid #e0e0e0', borderRadius: 1, p: 2 }}>
|
|
||||||
<Typography variant="body2" color="text.secondary">
|
|
||||||
测试结果将在这里显示...
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</Stack>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<Button onClick={() => setTestingDialogOpen(false)}>关闭</Button>
|
|
||||||
<Button variant="contained">开始测试</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
|
|
||||||
{/* 配置设置对话框 */}
|
|
||||||
<Dialog open={configDialogOpen} onClose={() => setConfigDialogOpen(false)} maxWidth="sm" fullWidth>
|
|
||||||
<DialogTitle>配置设置</DialogTitle>
|
|
||||||
<DialogContent>
|
|
||||||
<Stack spacing={3} sx={{ mt: 1 }}>
|
|
||||||
<TextField
|
|
||||||
fullWidth
|
|
||||||
label="知识库名称"
|
|
||||||
defaultValue={knowledgeBase?.name}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
fullWidth
|
|
||||||
label="描述"
|
|
||||||
multiline
|
|
||||||
rows={3}
|
|
||||||
defaultValue={knowledgeBase?.description}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
fullWidth
|
|
||||||
label="语言"
|
|
||||||
defaultValue={knowledgeBase?.language}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
fullWidth
|
|
||||||
label="嵌入模型"
|
|
||||||
defaultValue={knowledgeBase?.embd_id}
|
|
||||||
disabled
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
fullWidth
|
|
||||||
label="解析器"
|
|
||||||
defaultValue={knowledgeBase?.parser_id}
|
|
||||||
disabled
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<Button onClick={() => setConfigDialogOpen(false)}>取消</Button>
|
|
||||||
<Button variant="contained">保存</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
|
|
||||||
{/* 文档详情对话框 */}
|
{/* 文档详情对话框 */}
|
||||||
<Dialog
|
<Dialog
|
||||||
open={processDetailsDialogOpen}
|
open={processDetailsDialogOpen}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
/* Linting */
|
/* Linting */
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": false,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": false,
|
||||||
"erasableSyntaxOnly": true,
|
"erasableSyntaxOnly": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noUncheckedSideEffectImports": true,
|
"noUncheckedSideEffectImports": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user