diff --git a/frontend/.editorconfig b/frontend/.editorconfig index 3ba168a59..54955d935 100644 --- a/frontend/.editorconfig +++ b/frontend/.editorconfig @@ -1,13 +1,13 @@ -root = true - -[*] -charset = utf-8 -end_of_line = lf -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.{md}] -trim_trailing_whitespace = false - +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{md}] +trim_trailing_whitespace = false + diff --git a/frontend/.gitignore b/frontend/.gitignore index 7a14a7a70..2e8f378eb 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -1,28 +1,28 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -src/mock/sessions/* - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? - +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +src/mock/sessions/* + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + .vite \ No newline at end of file diff --git a/frontend/README.md b/frontend/README.md index 8bea5e6fc..b4fcd04d0 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,96 +1,96 @@ -🚀 快速开始 - -``` -npm install # 安装依赖 -npm run dev # 启动项目 -npm run mock # 启动后台Mock服务(可选) -``` - -📁 项目结构 - -``` -frontend/ -├── public/ # 📖 文档中心 -│ ├── huawei-logo.webp/ # logo -│ └── xxx/ # 标注工作台(可分离部署) -│ -├── src/ # 🎨 前端应用 -│ ├── apps/ # 多前端应用 -│ │ ├── console/ # 数据工作台&运营控制台 -│ │ │ ├── next.config.js -│ │ │ ├── package.json -│ │ │ └── src/ -│ │ └── annotation-studio/ # 标注工作台(可分离部署) -│ │ -│ ├── assets/ # 共享UI组件/SDK -│ │ ├── xxx/ # 数据工作台&运营控制台 -│ │ │ ├── next.config.js -│ │ │ └── src/ -│ │ │ -│ │ │ -│ │ └── xxx/ # 数据工作台&运营控制台 -│ │ ├── package.json -│ │ └── src/ -│ │ -│ ├── components/ # 构建与环境配置 -│ │ ├── CardView.tsx # 数据工作台&运营控制台 -│ │ ├── DetailHeader.tsx # 数据工作台&运营控制台 -│ │ ├── RadioCard.tsx # 数据工作台&运营控制台 -│ │ ├── SearchControls # 数据工作台&运营控制台 -│ │ ├── TagList # 标注工作台(可分离部署) -│ │ └── TaskPopover # 标注工作台(可分离部署) -│ │ -│ ├── hooks/ # 构建与环境配置 -│ │ ├── console/ # 数据工作台&运营控制台 -│ │ ├── next.config.js -│ │ ├── next.config.js -│ │ ├── next.config.js -│ │ ├── next.config.js -│ │ ├── next.config.js -│ │ └── annotation-studio/ # 标注工作台(可分离部署) -│ │ -│ ├── mock/ # 构建与环境配置 -│ │ ├── console/ # 数据工作台&运营控制台 -│ │ ├── next.config.js -│ │ ├── next.config.js -│ │ ├── next.config.js -│ │ ├── next.config.js -│ │ └── annotation-studio/ # 标注工作台(可分离部署) -│ │ -│ ├── pages/ # 构建与环境配置 -│ │ ├── console/ # 数据工作台&运营控制台 -│ │ │ ├── next.config.js -│ │ │ ├── package.json -│ │ │ └── src/ -│ │ └── annotation-studio/ # 标注工作台(可分离部署) -│ │ -│ ├── providers/ # 构建与环境配置 -│ │ ├── console/ # 数据工作台&运营控制台 -│ │ │ ├── next.config.js -│ │ │ ├── package.json -│ │ │ └── src/ -│ │ └── annotation-studio/ # 标注工作台(可分离部署) -│ │ -│ ├── routes/ # 构建与环境配置 -│ │ └── next.config.js -│ │ -│ ├── types/ # 构建与环境配置 -│ │ ├── next.config.js -│ │ ├── next.config.js -│ │ ├── next.config.js -│ │ ├── next.config.js -│ │ └── next.config.js -│ │ -│ └── utils/ # 构建与环境配置 -│ ├── next.config.js -│ ├── next.config.js -│ └── next.config.js -│ -├── eslint.config.js/ # 🔧 后端服务架构 -├── index.html/ # 🔧 后端服务架构 -├── package.json/ # 🔧 后端服务架构 -├── README.md # 项目说明 -├── tailwind.config.ts # 更新日志 -├── vite.config.ts # 开源协议 -└── pom.xml # Maven根配置 -``` +🚀 快速开始 + +``` +npm install # 安装依赖 +npm run dev # 启动项目 +npm run mock # 启动后台Mock服务(可选) +``` + +📁 项目结构 + +``` +frontend/ +├── public/ # 📖 文档中心 +│ ├── huawei-logo.webp/ # logo +│ └── xxx/ # 标注工作台(可分离部署) +│ +├── src/ # 🎨 前端应用 +│ ├── apps/ # 多前端应用 +│ │ ├── console/ # 数据工作台&运营控制台 +│ │ │ ├── next.config.js +│ │ │ ├── package.json +│ │ │ └── src/ +│ │ └── annotation-studio/ # 标注工作台(可分离部署) +│ │ +│ ├── assets/ # 共享UI组件/SDK +│ │ ├── xxx/ # 数据工作台&运营控制台 +│ │ │ ├── next.config.js +│ │ │ └── src/ +│ │ │ +│ │ │ +│ │ └── xxx/ # 数据工作台&运营控制台 +│ │ ├── package.json +│ │ └── src/ +│ │ +│ ├── components/ # 构建与环境配置 +│ │ ├── CardView.tsx # 数据工作台&运营控制台 +│ │ ├── DetailHeader.tsx # 数据工作台&运营控制台 +│ │ ├── RadioCard.tsx # 数据工作台&运营控制台 +│ │ ├── SearchControls # 数据工作台&运营控制台 +│ │ ├── TagList # 标注工作台(可分离部署) +│ │ └── TaskPopover # 标注工作台(可分离部署) +│ │ +│ ├── hooks/ # 构建与环境配置 +│ │ ├── console/ # 数据工作台&运营控制台 +│ │ ├── next.config.js +│ │ ├── next.config.js +│ │ ├── next.config.js +│ │ ├── next.config.js +│ │ ├── next.config.js +│ │ └── annotation-studio/ # 标注工作台(可分离部署) +│ │ +│ ├── mock/ # 构建与环境配置 +│ │ ├── console/ # 数据工作台&运营控制台 +│ │ ├── next.config.js +│ │ ├── next.config.js +│ │ ├── next.config.js +│ │ ├── next.config.js +│ │ └── annotation-studio/ # 标注工作台(可分离部署) +│ │ +│ ├── pages/ # 构建与环境配置 +│ │ ├── console/ # 数据工作台&运营控制台 +│ │ │ ├── next.config.js +│ │ │ ├── package.json +│ │ │ └── src/ +│ │ └── annotation-studio/ # 标注工作台(可分离部署) +│ │ +│ ├── providers/ # 构建与环境配置 +│ │ ├── console/ # 数据工作台&运营控制台 +│ │ │ ├── next.config.js +│ │ │ ├── package.json +│ │ │ └── src/ +│ │ └── annotation-studio/ # 标注工作台(可分离部署) +│ │ +│ ├── routes/ # 构建与环境配置 +│ │ └── next.config.js +│ │ +│ ├── types/ # 构建与环境配置 +│ │ ├── next.config.js +│ │ ├── next.config.js +│ │ ├── next.config.js +│ │ ├── next.config.js +│ │ └── next.config.js +│ │ +│ └── utils/ # 构建与环境配置 +│ ├── next.config.js +│ ├── next.config.js +│ └── next.config.js +│ +├── eslint.config.js/ # 🔧 后端服务架构 +├── index.html/ # 🔧 后端服务架构 +├── package.json/ # 🔧 后端服务架构 +├── README.md # 项目说明 +├── tailwind.config.ts # 更新日志 +├── vite.config.ts # 开源协议 +└── pom.xml # Maven根配置 +``` diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js index 63d950bd5..d94e7deb7 100644 --- a/frontend/eslint.config.js +++ b/frontend/eslint.config.js @@ -1,23 +1,23 @@ -import js from '@eslint/js' -import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' -import tseslint from 'typescript-eslint' -import { globalIgnores } from 'eslint/config' - -export default tseslint.config([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - js.configs.recommended, - tseslint.configs.recommended, - reactHooks.configs['recommended-latest'], - reactRefresh.configs.vite, - ], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - }, - }, -]) +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { globalIgnores } from 'eslint/config' + +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs['recommended-latest'], + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + }, +]) diff --git a/frontend/index.html b/frontend/index.html index 5337f9cfb..278d49b30 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,13 +1,13 @@ - - - - - - - DataMate - - -
- - - + + + + + + + DataMate + + +
+ + + diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 3b341b98b..f48ffc742 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,7225 +1,7225 @@ -{ - "name": "edatamate", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "edatamate", - "version": "0.0.0", - "dependencies": { - "@reduxjs/toolkit": "^2.11.0", - "@xyflow/react": "^12.8.3", - "antd": "^5.27.0", - "jssha": "^3.3.1", - "lucide-react": "^0.539.0", - "react": "^18.1.1", - "react-dom": "^18.1.1", - "react-redux": "^9.2.0", - "react-router": "^7.8.0", - "recharts": "2.15.0" - }, - "devDependencies": { - "@eslint/js": "^9.33.0", - "@tailwindcss/vite": "^4.1.12", - "@types/node": "^24.2.1", - "@types/react": "^18.1.10", - "@types/react-dom": "^18.1.7", - "@vitejs/plugin-react": "^5.0.0", - "body-parser": "^2.2.0", - "eslint": "^9.33.0", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.20", - "express": "^5.1.0", - "express-session": "^1.18.2", - "fs-extra": "^11.3.1", - "globals": "^16.3.0", - "lodash": "^4.17.21", - "minimist": "^1.2.8", - "mockjs": "^1.1.0", - "nodemon": "^3.1.10", - "postcss": "^8.5.6", - "session-file-store": "^1.5.0", - "tailwindcss": "^4.1.12", - "typescript": "~5.8.3", - "typescript-eslint": "^8.39.1", - "vite": "^7.1.2" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@ant-design/colors": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.2.1.tgz", - "integrity": "sha512-lCHDcEzieu4GA3n8ELeZ5VQ8pKQAWcGGLRTQ50aQM2iqPpq2evTxER84jfdPvsPAtEcZ7m44NI45edFMo8oOYQ==", - "license": "MIT", - "dependencies": { - "@ant-design/fast-color": "^2.0.6" - } - }, - "node_modules/@ant-design/cssinjs": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.24.0.tgz", - "integrity": "sha512-K4cYrJBsgvL+IoozUXYjbT6LHHNt+19a9zkvpBPxLjFHas1UpPM2A5MlhROb0BT8N8WoavM5VsP9MeSeNK/3mg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.11.1", - "@emotion/hash": "^0.8.0", - "@emotion/unitless": "^0.7.5", - "classnames": "^2.3.1", - "csstype": "^3.1.3", - "rc-util": "^5.35.0", - "stylis": "^4.3.4" - }, - "peerDependencies": { - "react": ">=16.0.0", - "react-dom": ">=16.0.0" - } - }, - "node_modules/@ant-design/cssinjs-utils": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-1.1.3.tgz", - "integrity": "sha512-nOoQMLW1l+xR1Co8NFVYiP8pZp3VjIIzqV6D6ShYF2ljtdwWJn5WSsH+7kvCktXL/yhEtWURKOfH5Xz/gzlwsg==", - "license": "MIT", - "dependencies": { - "@ant-design/cssinjs": "^1.21.0", - "@babel/runtime": "^7.23.2", - "rc-util": "^5.38.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@ant-design/fast-color": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz", - "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.24.7" - }, - "engines": { - "node": ">=8.x" - } - }, - "node_modules/@ant-design/icons": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz", - "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", - "license": "MIT", - "dependencies": { - "@ant-design/colors": "^7.0.0", - "@ant-design/icons-svg": "^4.4.0", - "@babel/runtime": "^7.24.8", - "classnames": "^2.2.6", - "rc-util": "^5.31.1" - }, - "engines": { - "node": ">=8" - }, - "peerDependencies": { - "react": ">=16.0.0", - "react-dom": ">=16.0.0" - } - }, - "node_modules/@ant-design/icons-svg": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", - "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==", - "license": "MIT" - }, - "node_modules/@ant-design/react-slick": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz", - "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.4", - "classnames": "^2.2.5", - "json2mq": "^0.2.0", - "resize-observer-polyfill": "^1.5.1", - "throttle-debounce": "^5.0.0" - }, - "peerDependencies": { - "react": ">=16.9.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", - "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", - "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", - "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.0", - "@babel/types": "^7.28.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.2.tgz", - "integrity": "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", - "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz", - "integrity": "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", - "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", - "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", - "license": "MIT" - }, - "node_modules/@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", - "license": "MIT" - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", - "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", - "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", - "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", - "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", - "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", - "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", - "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", - "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", - "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", - "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", - "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", - "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", - "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", - "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", - "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", - "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", - "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", - "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", - "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", - "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", - "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", - "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", - "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", - "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", - "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", - "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", - "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", - "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "9.33.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.33.0.tgz", - "integrity": "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", - "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.15.2", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.30", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", - "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rc-component/async-validator": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz", - "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.24.4" - }, - "engines": { - "node": ">=14.x" - } - }, - "node_modules/@rc-component/color-picker": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz", - "integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==", - "license": "MIT", - "dependencies": { - "@ant-design/fast-color": "^2.0.6", - "@babel/runtime": "^7.23.6", - "classnames": "^2.2.6", - "rc-util": "^5.38.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/context": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", - "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "rc-util": "^5.27.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/mini-decimal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", - "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.0" - }, - "engines": { - "node": ">=8.x" - } - }, - "node_modules/@rc-component/mutate-observer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", - "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.0", - "classnames": "^2.3.2", - "rc-util": "^5.24.4" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/portal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", - "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.0", - "classnames": "^2.3.2", - "rc-util": "^5.24.4" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/qrcode": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.0.0.tgz", - "integrity": "sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.24.7", - "classnames": "^2.3.2", - "rc-util": "^5.38.0" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/tour": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.1.tgz", - "integrity": "sha512-Tr2t7J1DKZUpfJuDZWHxyxWpfmj8EZrqSgyMZ+BCdvKZ6r1UDsfU46M/iWAAFBy961Ssfom2kv5f3UcjIL2CmQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.0", - "@rc-component/portal": "^1.0.0-9", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.3.2", - "rc-util": "^5.24.4" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@rc-component/trigger": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.3.0.tgz", - "integrity": "sha512-iwaxZyzOuK0D7lS+0AQEtW52zUWxoGqTGkke3dRyb8pYiShmRpCjB/8TzPI4R6YySCH7Vm9BZj/31VPiiQTLBg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.23.2", - "@rc-component/portal": "^1.1.0", - "classnames": "^2.3.2", - "rc-motion": "^2.0.0", - "rc-resize-observer": "^1.3.1", - "rc-util": "^5.44.0" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/@reduxjs/toolkit": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.0.tgz", - "integrity": "sha512-hBjYg0aaRL1O2Z0IqWhnTLytnjDIxekmRxm1snsHjHaKVmIF1HiImWqsq+PuEbn6zdMlkIj9WofK1vR8jjx+Xw==", - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@standard-schema/utils": "^0.3.0", - "immer": "^11.0.0", - "redux": "^5.0.1", - "redux-thunk": "^3.1.0", - "reselect": "^5.1.0" - }, - "peerDependencies": { - "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", - "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-redux": { - "optional": true - } - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.30.tgz", - "integrity": "sha512-whXaSoNUFiyDAjkUF8OBpOm77Szdbk5lGNqFe6CbVbJFrhCCPinCbRA3NjawwlNHla1No7xvXXh+CpSxnPfUEw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.2.tgz", - "integrity": "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.2.tgz", - "integrity": "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.2.tgz", - "integrity": "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.2.tgz", - "integrity": "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.2.tgz", - "integrity": "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.2.tgz", - "integrity": "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.2.tgz", - "integrity": "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.2.tgz", - "integrity": "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.2.tgz", - "integrity": "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.2.tgz", - "integrity": "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.2.tgz", - "integrity": "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.2.tgz", - "integrity": "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.2.tgz", - "integrity": "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.2.tgz", - "integrity": "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.2.tgz", - "integrity": "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.2.tgz", - "integrity": "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.2.tgz", - "integrity": "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.2.tgz", - "integrity": "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.2.tgz", - "integrity": "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.2.tgz", - "integrity": "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", - "license": "MIT" - }, - "node_modules/@standard-schema/utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", - "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", - "license": "MIT" - }, - "node_modules/@tailwindcss/node": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.12.tgz", - "integrity": "sha512-3hm9brwvQkZFe++SBt+oLjo4OLDtkvlE8q2WalaD/7QWaeM7KEJbAiY/LJZUaCs7Xa8aUu4xy3uoyX4q54UVdQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.4", - "enhanced-resolve": "^5.18.3", - "jiti": "^2.5.1", - "lightningcss": "1.30.1", - "magic-string": "^0.30.17", - "source-map-js": "^1.2.1", - "tailwindcss": "4.1.12" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.12.tgz", - "integrity": "sha512-gM5EoKHW/ukmlEtphNwaGx45fGoEmP10v51t9unv55voWh6WrOL19hfuIdo2FjxIaZzw776/BUQg7Pck++cIVw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.4", - "tar": "^7.4.3" - }, - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.12", - "@tailwindcss/oxide-darwin-arm64": "4.1.12", - "@tailwindcss/oxide-darwin-x64": "4.1.12", - "@tailwindcss/oxide-freebsd-x64": "4.1.12", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.12", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.12", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.12", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.12", - "@tailwindcss/oxide-linux-x64-musl": "4.1.12", - "@tailwindcss/oxide-wasm32-wasi": "4.1.12", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.12", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.12" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.12.tgz", - "integrity": "sha512-oNY5pq+1gc4T6QVTsZKwZaGpBb2N1H1fsc1GD4o7yinFySqIuRZ2E4NvGasWc6PhYJwGK2+5YT1f9Tp80zUQZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.12.tgz", - "integrity": "sha512-cq1qmq2HEtDV9HvZlTtrj671mCdGB93bVY6J29mwCyaMYCP/JaUBXxrQQQm7Qn33AXXASPUb2HFZlWiiHWFytw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.12.tgz", - "integrity": "sha512-6UCsIeFUcBfpangqlXay9Ffty9XhFH1QuUFn0WV83W8lGdX8cD5/+2ONLluALJD5+yJ7k8mVtwy3zMZmzEfbLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.12.tgz", - "integrity": "sha512-JOH/f7j6+nYXIrHobRYCtoArJdMJh5zy5lr0FV0Qu47MID/vqJAY3r/OElPzx1C/wdT1uS7cPq+xdYYelny1ww==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.12.tgz", - "integrity": "sha512-v4Ghvi9AU1SYgGr3/j38PD8PEe6bRfTnNSUE3YCMIRrrNigCFtHZ2TCm8142X8fcSqHBZBceDx+JlFJEfNg5zQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.12.tgz", - "integrity": "sha512-YP5s1LmetL9UsvVAKusHSyPlzSRqYyRB0f+Kl/xcYQSPLEw/BvGfxzbH+ihUciePDjiXwHh+p+qbSP3SlJw+6g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.12.tgz", - "integrity": "sha512-V8pAM3s8gsrXcCv6kCHSuwyb/gPsd863iT+v1PGXC4fSL/OJqsKhfK//v8P+w9ThKIoqNbEnsZqNy+WDnwQqCA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.12.tgz", - "integrity": "sha512-xYfqYLjvm2UQ3TZggTGrwxjYaLB62b1Wiysw/YE3Yqbh86sOMoTn0feF98PonP7LtjsWOWcXEbGqDL7zv0uW8Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.12.tgz", - "integrity": "sha512-ha0pHPamN+fWZY7GCzz5rKunlv9L5R8kdh+YNvP5awe3LtuXb5nRi/H27GeL2U+TdhDOptU7T6Is7mdwh5Ar3A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.12.tgz", - "integrity": "sha512-4tSyu3dW+ktzdEpuk6g49KdEangu3eCYoqPhWNsZgUhyegEda3M9rG0/j1GV/JjVVsj+lG7jWAyrTlLzd/WEBg==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.5", - "@emnapi/runtime": "^1.4.5", - "@emnapi/wasi-threads": "^1.0.4", - "@napi-rs/wasm-runtime": "^0.2.12", - "@tybys/wasm-util": "^0.10.0", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.12.tgz", - "integrity": "sha512-iGLyD/cVP724+FGtMWslhcFyg4xyYyM+5F4hGvKA7eifPkXHRAUDFaimu53fpNg9X8dfP75pXx/zFt/jlNF+lg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.12.tgz", - "integrity": "sha512-NKIh5rzw6CpEodv/++r0hGLlfgT/gFN+5WNdZtvh6wpU2BpGNgdjvj6H2oFc8nCM839QM1YOhjpgbAONUb4IxA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/vite": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.12.tgz", - "integrity": "sha512-4pt0AMFDx7gzIrAOIYgYP0KCBuKWqyW8ayrdiLEjoJTT4pKTjrzG/e4uzWtTLDziC+66R9wbUqZBccJalSE5vQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tailwindcss/node": "4.1.12", - "@tailwindcss/oxide": "4.1.12", - "tailwindcss": "4.1.12" - }, - "peerDependencies": { - "vite": "^5.2.0 || ^6 || ^7" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "node_modules/@types/d3-array": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", - "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", - "license": "MIT" - }, - "node_modules/@types/d3-color": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", - "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", - "license": "MIT" - }, - "node_modules/@types/d3-drag": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", - "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", - "license": "MIT", - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-ease": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", - "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", - "license": "MIT" - }, - "node_modules/@types/d3-interpolate": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", - "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", - "license": "MIT", - "dependencies": { - "@types/d3-color": "*" - } - }, - "node_modules/@types/d3-path": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", - "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", - "license": "MIT" - }, - "node_modules/@types/d3-scale": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", - "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", - "license": "MIT", - "dependencies": { - "@types/d3-time": "*" - } - }, - "node_modules/@types/d3-selection": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", - "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", - "license": "MIT" - }, - "node_modules/@types/d3-shape": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", - "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", - "license": "MIT", - "dependencies": { - "@types/d3-path": "*" - } - }, - "node_modules/@types/d3-time": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", - "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", - "license": "MIT" - }, - "node_modules/@types/d3-timer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", - "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", - "license": "MIT" - }, - "node_modules/@types/d3-transition": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", - "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", - "license": "MIT", - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-zoom": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", - "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", - "license": "MIT", - "dependencies": { - "@types/d3-interpolate": "*", - "@types/d3-selection": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "24.2.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.2.1.tgz", - "integrity": "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.10.0" - } - }, - "node_modules/@types/prop-types": { - "version": "15.7.15", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", - "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "18.3.23", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", - "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", - "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^18.0.0" - } - }, - "node_modules/@types/use-sync-external-store": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", - "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.1.tgz", - "integrity": "sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.39.1", - "@typescript-eslint/type-utils": "8.39.1", - "@typescript-eslint/utils": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.39.1", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.39.1.tgz", - "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/typescript-estree": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", - "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.39.1", - "@typescript-eslint/types": "^8.39.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", - "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", - "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.39.1.tgz", - "integrity": "sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/typescript-estree": "8.39.1", - "@typescript-eslint/utils": "8.39.1", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", - "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", - "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.39.1", - "@typescript-eslint/tsconfig-utils": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/visitor-keys": "8.39.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", - "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.39.1", - "@typescript-eslint/types": "8.39.1", - "@typescript-eslint/typescript-estree": "8.39.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", - "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.39.1", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.0.0.tgz", - "integrity": "sha512-Jx9JfsTa05bYkS9xo0hkofp2dCmp1blrKjw9JONs5BTHOvJCgLbaPSuZLGSVJW6u2qe0tc4eevY0+gSNNi0YCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.28.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.30", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, - "node_modules/@xyflow/react": { - "version": "12.8.3", - "resolved": "https://registry.npmjs.org/@xyflow/react/-/react-12.8.3.tgz", - "integrity": "sha512-8sdRZPMCzfhauF96krlUMPCKmi9cX64HsYG8qoVAAvTKDAqxXg7RSp/IhoXlzbI/lsRD1vAxeDBxvI/XqACa6g==", - "license": "MIT", - "dependencies": { - "@xyflow/system": "0.0.67", - "classcat": "^5.0.3", - "zustand": "^4.4.0" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/@xyflow/system": { - "version": "0.0.67", - "resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.67.tgz", - "integrity": "sha512-hYsmbj+8JDei0jmupBmxNLaeJEcf9kKmMl6IziGe02i0TOCsHwjIdP+qz+f4rI1/FR2CQiCZJrw4dkHOLC6tEQ==", - "license": "MIT", - "dependencies": { - "@types/d3-drag": "^3.0.7", - "@types/d3-interpolate": "^3.0.4", - "@types/d3-selection": "^3.0.10", - "@types/d3-transition": "^3.0.8", - "@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" - } - }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/antd": { - "version": "5.27.0", - "resolved": "https://registry.npmjs.org/antd/-/antd-5.27.0.tgz", - "integrity": "sha512-o54dmpooLOc08RSGCkeEQBYAGPxUSmnhmYJKCNTHH46vzjOVxdteu+wPTRVkRbAkDTbs2VcNr5VL7Lu67rPIiA==", - "license": "MIT", - "dependencies": { - "@ant-design/colors": "^7.2.1", - "@ant-design/cssinjs": "^1.23.0", - "@ant-design/cssinjs-utils": "^1.1.3", - "@ant-design/fast-color": "^2.0.6", - "@ant-design/icons": "^5.6.1", - "@ant-design/react-slick": "~1.1.2", - "@babel/runtime": "^7.26.0", - "@rc-component/color-picker": "~2.0.1", - "@rc-component/mutate-observer": "^1.1.0", - "@rc-component/qrcode": "~1.0.0", - "@rc-component/tour": "~1.15.1", - "@rc-component/trigger": "^2.3.0", - "classnames": "^2.5.1", - "copy-to-clipboard": "^3.3.3", - "dayjs": "^1.11.11", - "rc-cascader": "~3.34.0", - "rc-checkbox": "~3.5.0", - "rc-collapse": "~3.9.0", - "rc-dialog": "~9.6.0", - "rc-drawer": "~7.3.0", - "rc-dropdown": "~4.2.1", - "rc-field-form": "~2.7.0", - "rc-image": "~7.12.0", - "rc-input": "~1.8.0", - "rc-input-number": "~9.5.0", - "rc-mentions": "~2.20.0", - "rc-menu": "~9.16.1", - "rc-motion": "^2.9.5", - "rc-notification": "~5.6.4", - "rc-pagination": "~5.1.0", - "rc-picker": "~4.11.3", - "rc-progress": "~4.0.0", - "rc-rate": "~2.13.1", - "rc-resize-observer": "^1.4.3", - "rc-segmented": "~2.7.0", - "rc-select": "~14.16.8", - "rc-slider": "~11.1.8", - "rc-steps": "~6.0.1", - "rc-switch": "~4.1.0", - "rc-table": "~7.51.1", - "rc-tabs": "~15.7.0", - "rc-textarea": "~1.10.2", - "rc-tooltip": "~6.4.0", - "rc-tree": "~5.13.1", - "rc-tree-select": "~5.27.0", - "rc-upload": "~4.9.2", - "rc-util": "^5.44.4", - "scroll-into-view-if-needed": "^3.1.0", - "throttle-debounce": "^5.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ant-design" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/bagpipe": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/bagpipe/-/bagpipe-0.3.5.tgz", - "integrity": "sha512-42sAlmPDKes1nLm/aly+0VdaopSU9br+jkRELedhQxI5uXHgtk47I83Mpmf4zoNTRMASdLFtUkimlu/Z9zQ8+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.0", - "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", - "on-finished": "^2.4.1", - "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.25.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz", - "integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001733", - "electron-to-chromium": "^1.5.199", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001735", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001735.tgz", - "integrity": "sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/classcat": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.5.tgz", - "integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==", - "license": "MIT" - }, - "node_modules/classnames": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", - "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", - "license": "MIT" - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", - "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20" - } - }, - "node_modules/compute-scroll-into-view": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", - "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cookie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/copy-to-clipboard": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", - "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", - "license": "MIT", - "dependencies": { - "toggle-selection": "^1.0.6" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "license": "MIT" - }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "license": "ISC", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-drag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-selection": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "license": "ISC", - "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-shape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", - "license": "ISC", - "dependencies": { - "d3-path": "^3.1.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "license": "ISC", - "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "d3-selection": "2 - 3" - } - }, - "node_modules/d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decimal.js-light": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", - "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", - "license": "MIT" - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true, - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.200", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.200.tgz", - "integrity": "sha512-rFCxROw7aOe4uPTfIAx+rXv9cEcGx+buAF4npnhtTqCJk5KDFRnh3+KYj7rdVh6lsFt5/aPs+Irj9rZ33WMA7w==", - "dev": true, - "license": "ISC" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", - "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", - "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.9", - "@esbuild/android-arm": "0.25.9", - "@esbuild/android-arm64": "0.25.9", - "@esbuild/android-x64": "0.25.9", - "@esbuild/darwin-arm64": "0.25.9", - "@esbuild/darwin-x64": "0.25.9", - "@esbuild/freebsd-arm64": "0.25.9", - "@esbuild/freebsd-x64": "0.25.9", - "@esbuild/linux-arm": "0.25.9", - "@esbuild/linux-arm64": "0.25.9", - "@esbuild/linux-ia32": "0.25.9", - "@esbuild/linux-loong64": "0.25.9", - "@esbuild/linux-mips64el": "0.25.9", - "@esbuild/linux-ppc64": "0.25.9", - "@esbuild/linux-riscv64": "0.25.9", - "@esbuild/linux-s390x": "0.25.9", - "@esbuild/linux-x64": "0.25.9", - "@esbuild/netbsd-arm64": "0.25.9", - "@esbuild/netbsd-x64": "0.25.9", - "@esbuild/openbsd-arm64": "0.25.9", - "@esbuild/openbsd-x64": "0.25.9", - "@esbuild/openharmony-arm64": "0.25.9", - "@esbuild/sunos-x64": "0.25.9", - "@esbuild/win32-arm64": "0.25.9", - "@esbuild/win32-ia32": "0.25.9", - "@esbuild/win32-x64": "0.25.9" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true, - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.33.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.33.0.tgz", - "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.1", - "@eslint/core": "^0.15.2", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.33.0", - "@eslint/plugin-kit": "^0.3.5", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.20", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", - "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": ">=8.40" - } - }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "license": "MIT" - }, - "node_modules/express": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.0", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express-session": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.2.tgz", - "integrity": "sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "cookie": "0.7.2", - "cookie-signature": "1.0.7", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.1.0", - "parseurl": "~1.3.3", - "safe-buffer": "5.2.1", - "uid-safe": "~2.1.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/express-session/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express-session/node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "dev": true, - "license": "MIT" - }, - "node_modules/express-session/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express-session/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/express/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-equals": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz", - "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/fs-extra": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz", - "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", - "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true, - "license": "ISC" - }, - "node_modules/immer": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/immer/-/immer-11.0.1.tgz", - "integrity": "sha512-naDCyggtcBWANtIrjQEajhhBEuL9b0Zg4zmlWK2CzS6xCWSE39/vvf4LqnMjUAWHBhot4m9MHCM/Z+mfWhUkiA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/jiti": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", - "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json2mq": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", - "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", - "license": "MIT", - "dependencies": { - "string-convert": "^0.2.0" - } - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jssha": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jssha/-/jssha-3.3.1.tgz", - "integrity": "sha512-VCMZj12FCFMQYcFLPRm/0lOBbLi8uM2BhXPTqw3U4YAfs4AZfiApOoBLoN8cQE60Z50m1MYMTQVCfgF/KaCVhQ==", - "license": "BSD-3-Clause", - "engines": { - "node": "*" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kruptein": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/kruptein/-/kruptein-2.2.3.tgz", - "integrity": "sha512-BTwprBPTzkFT9oTugxKd3WnWrX630MqUDsnmBuoa98eQs12oD4n4TeI0GbpdGcYn/73Xueg2rfnw+oK4dovnJg==", - "dev": true, - "license": "MIT", - "dependencies": { - "asn1.js": "^5.4.1" - }, - "engines": { - "node": ">6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lightningcss": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", - "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-darwin-arm64": "1.30.1", - "lightningcss-darwin-x64": "1.30.1", - "lightningcss-freebsd-x64": "1.30.1", - "lightningcss-linux-arm-gnueabihf": "1.30.1", - "lightningcss-linux-arm64-gnu": "1.30.1", - "lightningcss-linux-arm64-musl": "1.30.1", - "lightningcss-linux-x64-gnu": "1.30.1", - "lightningcss-linux-x64-musl": "1.30.1", - "lightningcss-win32-arm64-msvc": "1.30.1", - "lightningcss-win32-x64-msvc": "1.30.1" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", - "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", - "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", - "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", - "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", - "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", - "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", - "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", - "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", - "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", - "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lucide-react": { - "version": "0.539.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.539.0.tgz", - "integrity": "sha512-VVISr+VF2krO91FeuCrm1rSOLACQUYVy7NQkzrOty52Y8TlTPcXcMdQFj9bYzBgXbWCiywlwSZ3Z8u6a+6bMlg==", - "license": "ISC", - "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mockjs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mockjs/-/mockjs-1.1.0.tgz", - "integrity": "sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==", - "dev": true, - "dependencies": { - "commander": "*" - }, - "bin": { - "random": "bin/random" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, - "license": "MIT" - }, - "node_modules/nodemon": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz", - "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^3.5.2", - "debug": "^4", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^7.5.3", - "simple-update-notifier": "^2.0.0", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nodemon/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/nodemon/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/nodemon/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", - "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-to-regexp": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true, - "license": "MIT" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", - "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.7.0", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", - "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/rc-cascader": { - "version": "3.34.0", - "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.34.0.tgz", - "integrity": "sha512-KpXypcvju9ptjW9FaN2NFcA2QH9E9LHKq169Y0eWtH4e/wHQ5Wh5qZakAgvb8EKZ736WZ3B0zLLOBsrsja5Dag==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.25.7", - "classnames": "^2.3.1", - "rc-select": "~14.16.2", - "rc-tree": "~5.13.0", - "rc-util": "^5.43.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-checkbox": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.5.0.tgz", - "integrity": "sha512-aOAQc3E98HteIIsSqm6Xk2FPKIER6+5vyEFMZfo73TqM+VVAIqOkHoPjgKLqSNtVLWScoaM7vY2ZrGEheI79yg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.3.2", - "rc-util": "^5.25.2" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-collapse": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.9.0.tgz", - "integrity": "sha512-swDdz4QZ4dFTo4RAUMLL50qP0EY62N2kvmk2We5xYdRwcRn8WcYtuetCJpwpaCbUfUt5+huLpVxhvmnK+PHrkA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "rc-motion": "^2.3.4", - "rc-util": "^5.27.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-dialog": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.6.0.tgz", - "integrity": "sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "@rc-component/portal": "^1.0.0-8", - "classnames": "^2.2.6", - "rc-motion": "^2.3.0", - "rc-util": "^5.21.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-drawer": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.3.0.tgz", - "integrity": "sha512-DX6CIgiBWNpJIMGFO8BAISFkxiuKitoizooj4BDyee8/SnBn0zwO2FHrNDpqqepj0E/TFTDpmEBCyFuTgC7MOg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.23.9", - "@rc-component/portal": "^1.1.1", - "classnames": "^2.2.6", - "rc-motion": "^2.6.1", - "rc-util": "^5.38.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-dropdown": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.1.tgz", - "integrity": "sha512-YDAlXsPv3I1n42dv1JpdM7wJ+gSUBfeyPK59ZpBD9jQhK9jVuxpjj3NmWQHOBceA1zEPVX84T2wbdb2SD0UjmA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.3", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.2.6", - "rc-util": "^5.44.1" - }, - "peerDependencies": { - "react": ">=16.11.0", - "react-dom": ">=16.11.0" - } - }, - "node_modules/rc-field-form": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.7.0.tgz", - "integrity": "sha512-hgKsCay2taxzVnBPZl+1n4ZondsV78G++XVsMIJCAoioMjlMQR9YwAp7JZDIECzIu2Z66R+f4SFIRrO2DjDNAA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.0", - "@rc-component/async-validator": "^5.0.3", - "rc-util": "^5.32.2" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-image": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.12.0.tgz", - "integrity": "sha512-cZ3HTyyckPnNnUb9/DRqduqzLfrQRyi+CdHjdqgsyDpI3Ln5UX1kXnAhPBSJj9pVRzwRFgqkN7p9b6HBDjmu/Q==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.11.2", - "@rc-component/portal": "^1.0.2", - "classnames": "^2.2.6", - "rc-dialog": "~9.6.0", - "rc-motion": "^2.6.2", - "rc-util": "^5.34.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-input": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.8.0.tgz", - "integrity": "sha512-KXvaTbX+7ha8a/k+eg6SYRVERK0NddX8QX7a7AnRvUa/rEH0CNMlpcBzBkhI0wp2C8C4HlMoYl8TImSN+fuHKA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.11.1", - "classnames": "^2.2.1", - "rc-util": "^5.18.1" - }, - "peerDependencies": { - "react": ">=16.0.0", - "react-dom": ">=16.0.0" - } - }, - "node_modules/rc-input-number": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.5.0.tgz", - "integrity": "sha512-bKaEvB5tHebUURAEXw35LDcnRZLq3x1k7GxfAqBMzmpHkDGzjAtnUL8y4y5N15rIFIg5IJgwr211jInl3cipag==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "@rc-component/mini-decimal": "^1.0.1", - "classnames": "^2.2.5", - "rc-input": "~1.8.0", - "rc-util": "^5.40.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-mentions": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.20.0.tgz", - "integrity": "sha512-w8HCMZEh3f0nR8ZEd466ATqmXFCMGMN5UFCzEUL0bM/nGw/wOS2GgRzKBcm19K++jDyuWCOJOdgcKGXU3fXfbQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.22.5", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.2.6", - "rc-input": "~1.8.0", - "rc-menu": "~9.16.0", - "rc-textarea": "~1.10.0", - "rc-util": "^5.34.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-menu": { - "version": "9.16.1", - "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.16.1.tgz", - "integrity": "sha512-ghHx6/6Dvp+fw8CJhDUHFHDJ84hJE3BXNCzSgLdmNiFErWSOaZNsihDAsKq9ByTALo/xkNIwtDFGIl6r+RPXBg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "@rc-component/trigger": "^2.0.0", - "classnames": "2.x", - "rc-motion": "^2.4.3", - "rc-overflow": "^1.3.1", - "rc-util": "^5.27.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-motion": { - "version": "2.9.5", - "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.5.tgz", - "integrity": "sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.11.1", - "classnames": "^2.2.1", - "rc-util": "^5.44.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-notification": { - "version": "5.6.4", - "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.4.tgz", - "integrity": "sha512-KcS4O6B4qzM3KH7lkwOB7ooLPZ4b6J+VMmQgT51VZCeEcmghdeR4IrMcFq0LG+RPdnbe/ArT086tGM8Snimgiw==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "rc-motion": "^2.9.0", - "rc-util": "^5.20.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-overflow": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.4.1.tgz", - "integrity": "sha512-3MoPQQPV1uKyOMVNd6SZfONi+f3st0r8PksexIdBTeIYbMX0Jr+k7pHEDvsXtR4BpCv90/Pv2MovVNhktKrwvw==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.11.1", - "classnames": "^2.2.1", - "rc-resize-observer": "^1.0.0", - "rc-util": "^5.37.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-pagination": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-5.1.0.tgz", - "integrity": "sha512-8416Yip/+eclTFdHXLKTxZvn70duYVGTvUUWbckCCZoIl3jagqke3GLsFrMs0bsQBikiYpZLD9206Ej4SOdOXQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.3.2", - "rc-util": "^5.38.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-picker": { - "version": "4.11.3", - "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.11.3.tgz", - "integrity": "sha512-MJ5teb7FlNE0NFHTncxXQ62Y5lytq6sh5nUw0iH8OkHL/TjARSEvSHpr940pWgjGANpjCwyMdvsEV55l5tYNSg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.24.7", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.2.1", - "rc-overflow": "^1.3.2", - "rc-resize-observer": "^1.4.0", - "rc-util": "^5.43.0" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "date-fns": ">= 2.x", - "dayjs": ">= 1.x", - "luxon": ">= 3.x", - "moment": ">= 2.x", - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - }, - "peerDependenciesMeta": { - "date-fns": { - "optional": true - }, - "dayjs": { - "optional": true - }, - "luxon": { - "optional": true - }, - "moment": { - "optional": true - } - } - }, - "node_modules/rc-progress": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz", - "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.2.6", - "rc-util": "^5.16.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-rate": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.1.tgz", - "integrity": "sha512-QUhQ9ivQ8Gy7mtMZPAjLbxBt5y9GRp65VcUyGUMF3N3fhiftivPHdpuDIaWIMOTEprAjZPC08bls1dQB+I1F2Q==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.2.5", - "rc-util": "^5.0.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-resize-observer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.3.tgz", - "integrity": "sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.20.7", - "classnames": "^2.2.1", - "rc-util": "^5.44.1", - "resize-observer-polyfill": "^1.5.1" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-segmented": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.7.0.tgz", - "integrity": "sha512-liijAjXz+KnTRVnxxXG2sYDGd6iLL7VpGGdR8gwoxAXy2KglviKCxLWZdjKYJzYzGSUwKDSTdYk8brj54Bn5BA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.11.1", - "classnames": "^2.2.1", - "rc-motion": "^2.4.4", - "rc-util": "^5.17.0" - }, - "peerDependencies": { - "react": ">=16.0.0", - "react-dom": ">=16.0.0" - } - }, - "node_modules/rc-select": { - "version": "14.16.8", - "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.16.8.tgz", - "integrity": "sha512-NOV5BZa1wZrsdkKaiK7LHRuo5ZjZYMDxPP6/1+09+FB4KoNi8jcG1ZqLE3AVCxEsYMBe65OBx71wFoHRTP3LRg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "@rc-component/trigger": "^2.1.1", - "classnames": "2.x", - "rc-motion": "^2.0.1", - "rc-overflow": "^1.3.1", - "rc-util": "^5.16.1", - "rc-virtual-list": "^3.5.2" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/rc-slider": { - "version": "11.1.8", - "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.8.tgz", - "integrity": "sha512-2gg/72YFSpKP+Ja5AjC5DPL1YnV8DEITDQrcc1eASrUYjl0esptaBVJBh5nLTXCCp15eD8EuGjwezVGSHhs9tQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.2.5", - "rc-util": "^5.36.0" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-steps": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz", - "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.16.7", - "classnames": "^2.2.3", - "rc-util": "^5.16.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-switch": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz", - "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.21.0", - "classnames": "^2.2.1", - "rc-util": "^5.30.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-table": { - "version": "7.51.1", - "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.51.1.tgz", - "integrity": "sha512-5iq15mTHhvC42TlBLRCoCBLoCmGlbRZAlyF21FonFnS/DIC8DeRqnmdyVREwt2CFbPceM0zSNdEeVfiGaqYsKw==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "@rc-component/context": "^1.4.0", - "classnames": "^2.2.5", - "rc-resize-observer": "^1.1.0", - "rc-util": "^5.44.3", - "rc-virtual-list": "^3.14.2" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-tabs": { - "version": "15.7.0", - "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.7.0.tgz", - "integrity": "sha512-ZepiE+6fmozYdWf/9gVp7k56PKHB1YYoDsKeQA1CBlJ/POIhjkcYiv0AGP0w2Jhzftd3AVvZP/K+V+Lpi2ankA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.11.2", - "classnames": "2.x", - "rc-dropdown": "~4.2.0", - "rc-menu": "~9.16.0", - "rc-motion": "^2.6.2", - "rc-resize-observer": "^1.0.0", - "rc-util": "^5.34.1" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-textarea": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.10.2.tgz", - "integrity": "sha512-HfaeXiaSlpiSp0I/pvWpecFEHpVysZ9tpDLNkxQbMvMz6gsr7aVZ7FpWP9kt4t7DB+jJXesYS0us1uPZnlRnwQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "^2.2.1", - "rc-input": "~1.8.0", - "rc-resize-observer": "^1.0.0", - "rc-util": "^5.27.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-tooltip": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.4.0.tgz", - "integrity": "sha512-kqyivim5cp8I5RkHmpsp1Nn/Wk+1oeloMv9c7LXNgDxUpGm+RbXJGL+OPvDlcRnx9DBeOe4wyOIl4OKUERyH1g==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.11.2", - "@rc-component/trigger": "^2.0.0", - "classnames": "^2.3.1", - "rc-util": "^5.44.3" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-tree": { - "version": "5.13.1", - "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.13.1.tgz", - "integrity": "sha512-FNhIefhftobCdUJshO7M8uZTA9F4OPGVXqGfZkkD/5soDeOhwO06T/aKTrg0WD8gRg/pyfq+ql3aMymLHCTC4A==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "rc-motion": "^2.0.1", - "rc-util": "^5.16.1", - "rc-virtual-list": "^3.5.1" - }, - "engines": { - "node": ">=10.x" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/rc-tree-select": { - "version": "5.27.0", - "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.27.0.tgz", - "integrity": "sha512-2qTBTzwIT7LRI1o7zLyrCzmo5tQanmyGbSaGTIf7sYimCklAToVVfpMC6OAldSKolcnjorBYPNSKQqJmN3TCww==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.25.7", - "classnames": "2.x", - "rc-select": "~14.16.2", - "rc-tree": "~5.13.0", - "rc-util": "^5.43.0" - }, - "peerDependencies": { - "react": "*", - "react-dom": "*" - } - }, - "node_modules/rc-upload": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.9.2.tgz", - "integrity": "sha512-nHx+9rbd1FKMiMRYsqQ3NkXUv7COHPBo3X1Obwq9SWS6/diF/A0aJ5OHubvwUAIDs+4RMleljV0pcrNUc823GQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.3", - "classnames": "^2.2.5", - "rc-util": "^5.2.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-util": { - "version": "5.44.4", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.44.4.tgz", - "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.3", - "react-is": "^18.2.0" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/rc-virtual-list": { - "version": "3.19.1", - "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.19.1.tgz", - "integrity": "sha512-DCapO2oyPqmooGhxBuXHM4lFuX+sshQwWqqkuyFA+4rShLe//+GEPVwiDgO+jKtKHtbeYwZoNvetwfHdOf+iUQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.20.0", - "classnames": "^2.2.6", - "rc-resize-observer": "^1.0.0", - "rc-util": "^5.36.0" - }, - "engines": { - "node": ">=8.x" - }, - "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" - } - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "license": "MIT" - }, - "node_modules/react-redux": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", - "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", - "license": "MIT", - "dependencies": { - "@types/use-sync-external-store": "^0.0.6", - "use-sync-external-store": "^1.4.0" - }, - "peerDependencies": { - "@types/react": "^18.2.25 || ^19", - "react": "^18.0 || ^19", - "redux": "^5.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "redux": { - "optional": true - } - } - }, - "node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-router": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.0.tgz", - "integrity": "sha512-r15M3+LHKgM4SOapNmsH3smAizWds1vJ0Z9C4mWaKnT9/wD7+d/0jYcj6LmOvonkrO4Rgdyp4KQ/29gWN2i1eg==", - "license": "MIT", - "dependencies": { - "cookie": "^1.0.1", - "set-cookie-parser": "^2.6.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - } - } - }, - "node_modules/react-smooth": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", - "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==", - "license": "MIT", - "dependencies": { - "fast-equals": "^5.0.1", - "prop-types": "^15.8.1", - "react-transition-group": "^4.4.5" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "license": "BSD-3-Clause", - "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/recharts": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.0.tgz", - "integrity": "sha512-cIvMxDfpAmqAmVgc4yb7pgm/O1tmmkl/CjrvXuW+62/+7jj/iF9Ykm+hb/UJt42TREHMyd3gb+pkgoa2MxgDIw==", - "license": "MIT", - "dependencies": { - "clsx": "^2.0.0", - "eventemitter3": "^4.0.1", - "lodash": "^4.17.21", - "react-is": "^18.3.1", - "react-smooth": "^4.0.0", - "recharts-scale": "^0.4.4", - "tiny-invariant": "^1.3.1", - "victory-vendor": "^36.6.8" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/recharts-scale": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", - "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", - "license": "MIT", - "dependencies": { - "decimal.js-light": "^2.4.1" - } - }, - "node_modules/redux": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", - "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT" - }, - "node_modules/redux-thunk": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", - "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", - "license": "MIT", - "peerDependencies": { - "redux": "^5.0.0" - } - }, - "node_modules/reselect": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", - "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", - "license": "MIT" - }, - "node_modules/resize-observer-polyfill": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", - "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", - "license": "MIT" - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz", - "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.46.2", - "@rollup/rollup-android-arm64": "4.46.2", - "@rollup/rollup-darwin-arm64": "4.46.2", - "@rollup/rollup-darwin-x64": "4.46.2", - "@rollup/rollup-freebsd-arm64": "4.46.2", - "@rollup/rollup-freebsd-x64": "4.46.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.46.2", - "@rollup/rollup-linux-arm-musleabihf": "4.46.2", - "@rollup/rollup-linux-arm64-gnu": "4.46.2", - "@rollup/rollup-linux-arm64-musl": "4.46.2", - "@rollup/rollup-linux-loongarch64-gnu": "4.46.2", - "@rollup/rollup-linux-ppc64-gnu": "4.46.2", - "@rollup/rollup-linux-riscv64-gnu": "4.46.2", - "@rollup/rollup-linux-riscv64-musl": "4.46.2", - "@rollup/rollup-linux-s390x-gnu": "4.46.2", - "@rollup/rollup-linux-x64-gnu": "4.46.2", - "@rollup/rollup-linux-x64-musl": "4.46.2", - "@rollup/rollup-win32-arm64-msvc": "4.46.2", - "@rollup/rollup-win32-ia32-msvc": "4.46.2", - "@rollup/rollup-win32-x64-msvc": "4.46.2", - "fsevents": "~2.3.2" - } - }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT" - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/scroll-into-view-if-needed": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", - "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", - "license": "MIT", - "dependencies": { - "compute-scroll-into-view": "^3.0.2" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "mime-types": "^3.0.1", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/session-file-store": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/session-file-store/-/session-file-store-1.5.0.tgz", - "integrity": "sha512-60IZaJNzyu2tIeHutkYE8RiXVx3KRvacOxfLr2Mj92SIsRIroDsH0IlUUR6fJAjoTW4RQISbaOApa2IZpIwFdQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bagpipe": "^0.3.5", - "fs-extra": "^8.0.1", - "kruptein": "^2.0.4", - "object-assign": "^4.1.1", - "retry": "^0.12.0", - "write-file-atomic": "3.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/session-file-store/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/session-file-store/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/session-file-store/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", - "license": "MIT" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true, - "license": "ISC" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/simple-update-notifier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string-convert": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", - "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==", - "license": "MIT" - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stylis": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", - "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", - "license": "MIT" - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tailwindcss": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.12.tgz", - "integrity": "sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==", - "dev": true, - "license": "MIT" - }, - "node_modules/tapable": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", - "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/throttle-debounce": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", - "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", - "license": "MIT", - "engines": { - "node": ">=12.22" - } - }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", - "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toggle-selection": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", - "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", - "license": "MIT" - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/touch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", - "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", - "dev": true, - "license": "ISC", - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "dev": true, - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "8.39.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.39.1.tgz", - "integrity": "sha512-GDUv6/NDYngUlNvwaHM1RamYftxf782IyEDbdj3SeaIHHv8fNQVRC++fITT7kUJV/5rIA/tkoRSSskt6osEfqg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.39.1", - "@typescript-eslint/parser": "8.39.1", - "@typescript-eslint/typescript-estree": "8.39.1", - "@typescript-eslint/utils": "8.39.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "dev": true, - "license": "MIT", - "dependencies": { - "random-bytes": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true, - "license": "MIT" - }, - "node_modules/undici-types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/use-sync-external-store": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", - "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/victory-vendor": { - "version": "36.9.2", - "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", - "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", - "license": "MIT AND ISC", - "dependencies": { - "@types/d3-array": "^3.0.3", - "@types/d3-ease": "^3.0.0", - "@types/d3-interpolate": "^3.0.1", - "@types/d3-scale": "^4.0.2", - "@types/d3-shape": "^3.1.0", - "@types/d3-time": "^3.0.0", - "@types/d3-timer": "^3.0.0", - "d3-array": "^3.1.6", - "d3-ease": "^3.0.1", - "d3-interpolate": "^3.0.1", - "d3-scale": "^4.0.2", - "d3-shape": "^3.1.0", - "d3-time": "^3.0.0", - "d3-timer": "^3.0.1" - } - }, - "node_modules/vite": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.2.tgz", - "integrity": "sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.6", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.14" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/fdir": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", - "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zustand": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", - "integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==", - "license": "MIT", - "dependencies": { - "use-sync-external-store": "^1.2.2" - }, - "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 - } - } - } - } -} +{ + "name": "edatamate", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "edatamate", + "version": "0.0.0", + "dependencies": { + "@reduxjs/toolkit": "^2.11.0", + "@xyflow/react": "^12.8.3", + "antd": "^5.27.0", + "jssha": "^3.3.1", + "lucide-react": "^0.539.0", + "react": "^18.1.1", + "react-dom": "^18.1.1", + "react-redux": "^9.2.0", + "react-router": "^7.8.0", + "recharts": "2.15.0" + }, + "devDependencies": { + "@eslint/js": "^9.33.0", + "@tailwindcss/vite": "^4.1.12", + "@types/node": "^24.2.1", + "@types/react": "^18.1.10", + "@types/react-dom": "^18.1.7", + "@vitejs/plugin-react": "^5.0.0", + "body-parser": "^2.2.0", + "eslint": "^9.33.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "express": "^5.1.0", + "express-session": "^1.18.2", + "fs-extra": "^11.3.1", + "globals": "^16.3.0", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "mockjs": "^1.1.0", + "nodemon": "^3.1.10", + "postcss": "^8.5.6", + "session-file-store": "^1.5.0", + "tailwindcss": "^4.1.12", + "typescript": "~5.8.3", + "typescript-eslint": "^8.39.1", + "vite": "^7.1.2" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ant-design/colors": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.2.1.tgz", + "integrity": "sha512-lCHDcEzieu4GA3n8ELeZ5VQ8pKQAWcGGLRTQ50aQM2iqPpq2evTxER84jfdPvsPAtEcZ7m44NI45edFMo8oOYQ==", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6" + } + }, + "node_modules/@ant-design/cssinjs": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.24.0.tgz", + "integrity": "sha512-K4cYrJBsgvL+IoozUXYjbT6LHHNt+19a9zkvpBPxLjFHas1UpPM2A5MlhROb0BT8N8WoavM5VsP9MeSeNK/3mg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@emotion/hash": "^0.8.0", + "@emotion/unitless": "^0.7.5", + "classnames": "^2.3.1", + "csstype": "^3.1.3", + "rc-util": "^5.35.0", + "stylis": "^4.3.4" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/cssinjs-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-1.1.3.tgz", + "integrity": "sha512-nOoQMLW1l+xR1Co8NFVYiP8pZp3VjIIzqV6D6ShYF2ljtdwWJn5WSsH+7kvCktXL/yhEtWURKOfH5Xz/gzlwsg==", + "license": "MIT", + "dependencies": { + "@ant-design/cssinjs": "^1.21.0", + "@babel/runtime": "^7.23.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@ant-design/fast-color": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz", + "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", + "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==", + "license": "MIT" + }, + "node_modules/@ant-design/react-slick": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz", + "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "resize-observer-polyfill": "^1.5.1", + "throttle-debounce": "^5.0.0" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", + "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.6", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", + "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.0", + "@babel/types": "^7.28.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.2.tgz", + "integrity": "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz", + "integrity": "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", + "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.33.0.tgz", + "integrity": "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rc-component/async-validator": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz", + "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.4" + }, + "engines": { + "node": ">=14.x" + } + }, + "node_modules/@rc-component/color-picker": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz", + "integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6", + "@babel/runtime": "^7.23.6", + "classnames": "^2.2.6", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/context": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", + "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", + "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@rc-component/mutate-observer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", + "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", + "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/qrcode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.0.0.tgz", + "integrity": "sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "classnames": "^2.3.2", + "rc-util": "^5.38.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tour": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.1.tgz", + "integrity": "sha512-Tr2t7J1DKZUpfJuDZWHxyxWpfmj8EZrqSgyMZ+BCdvKZ6r1UDsfU46M/iWAAFBy961Ssfom2kv5f3UcjIL2CmQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/portal": "^1.0.0-9", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/trigger": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.3.0.tgz", + "integrity": "sha512-iwaxZyzOuK0D7lS+0AQEtW52zUWxoGqTGkke3dRyb8pYiShmRpCjB/8TzPI4R6YySCH7Vm9BZj/31VPiiQTLBg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@rc-component/portal": "^1.1.0", + "classnames": "^2.3.2", + "rc-motion": "^2.0.0", + "rc-resize-observer": "^1.3.1", + "rc-util": "^5.44.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@reduxjs/toolkit": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.0.tgz", + "integrity": "sha512-hBjYg0aaRL1O2Z0IqWhnTLytnjDIxekmRxm1snsHjHaKVmIF1HiImWqsq+PuEbn6zdMlkIj9WofK1vR8jjx+Xw==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^11.0.0", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.30", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.30.tgz", + "integrity": "sha512-whXaSoNUFiyDAjkUF8OBpOm77Szdbk5lGNqFe6CbVbJFrhCCPinCbRA3NjawwlNHla1No7xvXXh+CpSxnPfUEw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.2.tgz", + "integrity": "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.2.tgz", + "integrity": "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.2.tgz", + "integrity": "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.2.tgz", + "integrity": "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.2.tgz", + "integrity": "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.2.tgz", + "integrity": "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.2.tgz", + "integrity": "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.2.tgz", + "integrity": "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.2.tgz", + "integrity": "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.2.tgz", + "integrity": "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.2.tgz", + "integrity": "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.2.tgz", + "integrity": "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.2.tgz", + "integrity": "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.2.tgz", + "integrity": "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.2.tgz", + "integrity": "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.2.tgz", + "integrity": "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.2.tgz", + "integrity": "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.2.tgz", + "integrity": "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.2.tgz", + "integrity": "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.2.tgz", + "integrity": "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.12.tgz", + "integrity": "sha512-3hm9brwvQkZFe++SBt+oLjo4OLDtkvlE8q2WalaD/7QWaeM7KEJbAiY/LJZUaCs7Xa8aUu4xy3uoyX4q54UVdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.4", + "enhanced-resolve": "^5.18.3", + "jiti": "^2.5.1", + "lightningcss": "1.30.1", + "magic-string": "^0.30.17", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.12" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.12.tgz", + "integrity": "sha512-gM5EoKHW/ukmlEtphNwaGx45fGoEmP10v51t9unv55voWh6WrOL19hfuIdo2FjxIaZzw776/BUQg7Pck++cIVw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.4.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.12", + "@tailwindcss/oxide-darwin-arm64": "4.1.12", + "@tailwindcss/oxide-darwin-x64": "4.1.12", + "@tailwindcss/oxide-freebsd-x64": "4.1.12", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.12", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.12", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.12", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.12", + "@tailwindcss/oxide-linux-x64-musl": "4.1.12", + "@tailwindcss/oxide-wasm32-wasi": "4.1.12", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.12", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.12" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.12.tgz", + "integrity": "sha512-oNY5pq+1gc4T6QVTsZKwZaGpBb2N1H1fsc1GD4o7yinFySqIuRZ2E4NvGasWc6PhYJwGK2+5YT1f9Tp80zUQZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.12.tgz", + "integrity": "sha512-cq1qmq2HEtDV9HvZlTtrj671mCdGB93bVY6J29mwCyaMYCP/JaUBXxrQQQm7Qn33AXXASPUb2HFZlWiiHWFytw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.12.tgz", + "integrity": "sha512-6UCsIeFUcBfpangqlXay9Ffty9XhFH1QuUFn0WV83W8lGdX8cD5/+2ONLluALJD5+yJ7k8mVtwy3zMZmzEfbLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.12.tgz", + "integrity": "sha512-JOH/f7j6+nYXIrHobRYCtoArJdMJh5zy5lr0FV0Qu47MID/vqJAY3r/OElPzx1C/wdT1uS7cPq+xdYYelny1ww==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.12.tgz", + "integrity": "sha512-v4Ghvi9AU1SYgGr3/j38PD8PEe6bRfTnNSUE3YCMIRrrNigCFtHZ2TCm8142X8fcSqHBZBceDx+JlFJEfNg5zQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.12.tgz", + "integrity": "sha512-YP5s1LmetL9UsvVAKusHSyPlzSRqYyRB0f+Kl/xcYQSPLEw/BvGfxzbH+ihUciePDjiXwHh+p+qbSP3SlJw+6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.12.tgz", + "integrity": "sha512-V8pAM3s8gsrXcCv6kCHSuwyb/gPsd863iT+v1PGXC4fSL/OJqsKhfK//v8P+w9ThKIoqNbEnsZqNy+WDnwQqCA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.12.tgz", + "integrity": "sha512-xYfqYLjvm2UQ3TZggTGrwxjYaLB62b1Wiysw/YE3Yqbh86sOMoTn0feF98PonP7LtjsWOWcXEbGqDL7zv0uW8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.12.tgz", + "integrity": "sha512-ha0pHPamN+fWZY7GCzz5rKunlv9L5R8kdh+YNvP5awe3LtuXb5nRi/H27GeL2U+TdhDOptU7T6Is7mdwh5Ar3A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.12.tgz", + "integrity": "sha512-4tSyu3dW+ktzdEpuk6g49KdEangu3eCYoqPhWNsZgUhyegEda3M9rG0/j1GV/JjVVsj+lG7jWAyrTlLzd/WEBg==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.5", + "@emnapi/runtime": "^1.4.5", + "@emnapi/wasi-threads": "^1.0.4", + "@napi-rs/wasm-runtime": "^0.2.12", + "@tybys/wasm-util": "^0.10.0", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.12.tgz", + "integrity": "sha512-iGLyD/cVP724+FGtMWslhcFyg4xyYyM+5F4hGvKA7eifPkXHRAUDFaimu53fpNg9X8dfP75pXx/zFt/jlNF+lg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.12.tgz", + "integrity": "sha512-NKIh5rzw6CpEodv/++r0hGLlfgT/gFN+5WNdZtvh6wpU2BpGNgdjvj6H2oFc8nCM839QM1YOhjpgbAONUb4IxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.12.tgz", + "integrity": "sha512-4pt0AMFDx7gzIrAOIYgYP0KCBuKWqyW8ayrdiLEjoJTT4pKTjrzG/e4uzWtTLDziC+66R9wbUqZBccJalSE5vQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.1.12", + "@tailwindcss/oxide": "4.1.12", + "tailwindcss": "4.1.12" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.2.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.2.1.tgz", + "integrity": "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.10.0" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.23", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", + "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.1.tgz", + "integrity": "sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/type-utils": "8.39.1", + "@typescript-eslint/utils": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.39.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.39.1.tgz", + "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", + "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.39.1", + "@typescript-eslint/types": "^8.39.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", + "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", + "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.39.1.tgz", + "integrity": "sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/utils": "8.39.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", + "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", + "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.39.1", + "@typescript-eslint/tsconfig-utils": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", + "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", + "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.39.1", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.0.0.tgz", + "integrity": "sha512-Jx9JfsTa05bYkS9xo0hkofp2dCmp1blrKjw9JONs5BTHOvJCgLbaPSuZLGSVJW6u2qe0tc4eevY0+gSNNi0YCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.30", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/@xyflow/react": { + "version": "12.8.3", + "resolved": "https://registry.npmjs.org/@xyflow/react/-/react-12.8.3.tgz", + "integrity": "sha512-8sdRZPMCzfhauF96krlUMPCKmi9cX64HsYG8qoVAAvTKDAqxXg7RSp/IhoXlzbI/lsRD1vAxeDBxvI/XqACa6g==", + "license": "MIT", + "dependencies": { + "@xyflow/system": "0.0.67", + "classcat": "^5.0.3", + "zustand": "^4.4.0" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@xyflow/system": { + "version": "0.0.67", + "resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.67.tgz", + "integrity": "sha512-hYsmbj+8JDei0jmupBmxNLaeJEcf9kKmMl6IziGe02i0TOCsHwjIdP+qz+f4rI1/FR2CQiCZJrw4dkHOLC6tEQ==", + "license": "MIT", + "dependencies": { + "@types/d3-drag": "^3.0.7", + "@types/d3-interpolate": "^3.0.4", + "@types/d3-selection": "^3.0.10", + "@types/d3-transition": "^3.0.8", + "@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" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/antd": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.27.0.tgz", + "integrity": "sha512-o54dmpooLOc08RSGCkeEQBYAGPxUSmnhmYJKCNTHH46vzjOVxdteu+wPTRVkRbAkDTbs2VcNr5VL7Lu67rPIiA==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.2.1", + "@ant-design/cssinjs": "^1.23.0", + "@ant-design/cssinjs-utils": "^1.1.3", + "@ant-design/fast-color": "^2.0.6", + "@ant-design/icons": "^5.6.1", + "@ant-design/react-slick": "~1.1.2", + "@babel/runtime": "^7.26.0", + "@rc-component/color-picker": "~2.0.1", + "@rc-component/mutate-observer": "^1.1.0", + "@rc-component/qrcode": "~1.0.0", + "@rc-component/tour": "~1.15.1", + "@rc-component/trigger": "^2.3.0", + "classnames": "^2.5.1", + "copy-to-clipboard": "^3.3.3", + "dayjs": "^1.11.11", + "rc-cascader": "~3.34.0", + "rc-checkbox": "~3.5.0", + "rc-collapse": "~3.9.0", + "rc-dialog": "~9.6.0", + "rc-drawer": "~7.3.0", + "rc-dropdown": "~4.2.1", + "rc-field-form": "~2.7.0", + "rc-image": "~7.12.0", + "rc-input": "~1.8.0", + "rc-input-number": "~9.5.0", + "rc-mentions": "~2.20.0", + "rc-menu": "~9.16.1", + "rc-motion": "^2.9.5", + "rc-notification": "~5.6.4", + "rc-pagination": "~5.1.0", + "rc-picker": "~4.11.3", + "rc-progress": "~4.0.0", + "rc-rate": "~2.13.1", + "rc-resize-observer": "^1.4.3", + "rc-segmented": "~2.7.0", + "rc-select": "~14.16.8", + "rc-slider": "~11.1.8", + "rc-steps": "~6.0.1", + "rc-switch": "~4.1.0", + "rc-table": "~7.51.1", + "rc-tabs": "~15.7.0", + "rc-textarea": "~1.10.2", + "rc-tooltip": "~6.4.0", + "rc-tree": "~5.13.1", + "rc-tree-select": "~5.27.0", + "rc-upload": "~4.9.2", + "rc-util": "^5.44.4", + "scroll-into-view-if-needed": "^3.1.0", + "throttle-debounce": "^5.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/bagpipe": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/bagpipe/-/bagpipe-0.3.5.tgz", + "integrity": "sha512-42sAlmPDKes1nLm/aly+0VdaopSU9br+jkRELedhQxI5uXHgtk47I83Mpmf4zoNTRMASdLFtUkimlu/Z9zQ8+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bn.js": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.25.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz", + "integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001733", + "electron-to-chromium": "^1.5.199", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001735", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001735.tgz", + "integrity": "sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/classcat": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.5.tgz", + "integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==", + "license": "MIT" + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", + "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "license": "MIT", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.200", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.200.tgz", + "integrity": "sha512-rFCxROw7aOe4uPTfIAx+rXv9cEcGx+buAF4npnhtTqCJk5KDFRnh3+KYj7rdVh6lsFt5/aPs+Irj9rZ33WMA7w==", + "dev": true, + "license": "ISC" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.33.0.tgz", + "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.33.0", + "@eslint/plugin-kit": "^0.3.5", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.20", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", + "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-session": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.2.tgz", + "integrity": "sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.7", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.1.0", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express-session/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/express/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-equals": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz", + "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs-extra": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz", + "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", + "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, + "license": "ISC" + }, + "node_modules/immer": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-11.0.1.tgz", + "integrity": "sha512-naDCyggtcBWANtIrjQEajhhBEuL9b0Zg4zmlWK2CzS6xCWSE39/vvf4LqnMjUAWHBhot4m9MHCM/Z+mfWhUkiA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", + "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "license": "MIT", + "dependencies": { + "string-convert": "^0.2.0" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jssha": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jssha/-/jssha-3.3.1.tgz", + "integrity": "sha512-VCMZj12FCFMQYcFLPRm/0lOBbLi8uM2BhXPTqw3U4YAfs4AZfiApOoBLoN8cQE60Z50m1MYMTQVCfgF/KaCVhQ==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kruptein": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/kruptein/-/kruptein-2.2.3.tgz", + "integrity": "sha512-BTwprBPTzkFT9oTugxKd3WnWrX630MqUDsnmBuoa98eQs12oD4n4TeI0GbpdGcYn/73Xueg2rfnw+oK4dovnJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "asn1.js": "^5.4.1" + }, + "engines": { + "node": ">6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.539.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.539.0.tgz", + "integrity": "sha512-VVISr+VF2krO91FeuCrm1rSOLACQUYVy7NQkzrOty52Y8TlTPcXcMdQFj9bYzBgXbWCiywlwSZ3Z8u6a+6bMlg==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mockjs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mockjs/-/mockjs-1.1.0.tgz", + "integrity": "sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==", + "dev": true, + "dependencies": { + "commander": "*" + }, + "bin": { + "random": "bin/random" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nodemon": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz", + "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", + "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.7.0", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/rc-cascader": { + "version": "3.34.0", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.34.0.tgz", + "integrity": "sha512-KpXypcvju9ptjW9FaN2NFcA2QH9E9LHKq169Y0eWtH4e/wHQ5Wh5qZakAgvb8EKZ736WZ3B0zLLOBsrsja5Dag==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "classnames": "^2.3.1", + "rc-select": "~14.16.2", + "rc-tree": "~5.13.0", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-checkbox": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.5.0.tgz", + "integrity": "sha512-aOAQc3E98HteIIsSqm6Xk2FPKIER6+5vyEFMZfo73TqM+VVAIqOkHoPjgKLqSNtVLWScoaM7vY2ZrGEheI79yg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.25.2" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-collapse": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.9.0.tgz", + "integrity": "sha512-swDdz4QZ4dFTo4RAUMLL50qP0EY62N2kvmk2We5xYdRwcRn8WcYtuetCJpwpaCbUfUt5+huLpVxhvmnK+PHrkA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.3.4", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dialog": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.6.0.tgz", + "integrity": "sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/portal": "^1.0.0-8", + "classnames": "^2.2.6", + "rc-motion": "^2.3.0", + "rc-util": "^5.21.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-drawer": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.3.0.tgz", + "integrity": "sha512-DX6CIgiBWNpJIMGFO8BAISFkxiuKitoizooj4BDyee8/SnBn0zwO2FHrNDpqqepj0E/TFTDpmEBCyFuTgC7MOg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@rc-component/portal": "^1.1.1", + "classnames": "^2.2.6", + "rc-motion": "^2.6.1", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dropdown": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.1.tgz", + "integrity": "sha512-YDAlXsPv3I1n42dv1JpdM7wJ+gSUBfeyPK59ZpBD9jQhK9jVuxpjj3NmWQHOBceA1zEPVX84T2wbdb2SD0UjmA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-util": "^5.44.1" + }, + "peerDependencies": { + "react": ">=16.11.0", + "react-dom": ">=16.11.0" + } + }, + "node_modules/rc-field-form": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.7.0.tgz", + "integrity": "sha512-hgKsCay2taxzVnBPZl+1n4ZondsV78G++XVsMIJCAoioMjlMQR9YwAp7JZDIECzIu2Z66R+f4SFIRrO2DjDNAA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/async-validator": "^5.0.3", + "rc-util": "^5.32.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-image": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.12.0.tgz", + "integrity": "sha512-cZ3HTyyckPnNnUb9/DRqduqzLfrQRyi+CdHjdqgsyDpI3Ln5UX1kXnAhPBSJj9pVRzwRFgqkN7p9b6HBDjmu/Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/portal": "^1.0.2", + "classnames": "^2.2.6", + "rc-dialog": "~9.6.0", + "rc-motion": "^2.6.2", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-input": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.8.0.tgz", + "integrity": "sha512-KXvaTbX+7ha8a/k+eg6SYRVERK0NddX8QX7a7AnRvUa/rEH0CNMlpcBzBkhI0wp2C8C4HlMoYl8TImSN+fuHKA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-input-number": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.5.0.tgz", + "integrity": "sha512-bKaEvB5tHebUURAEXw35LDcnRZLq3x1k7GxfAqBMzmpHkDGzjAtnUL8y4y5N15rIFIg5IJgwr211jInl3cipag==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/mini-decimal": "^1.0.1", + "classnames": "^2.2.5", + "rc-input": "~1.8.0", + "rc-util": "^5.40.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-mentions": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.20.0.tgz", + "integrity": "sha512-w8HCMZEh3f0nR8ZEd466ATqmXFCMGMN5UFCzEUL0bM/nGw/wOS2GgRzKBcm19K++jDyuWCOJOdgcKGXU3fXfbQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.22.5", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-input": "~1.8.0", + "rc-menu": "~9.16.0", + "rc-textarea": "~1.10.0", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-menu": { + "version": "9.16.1", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.16.1.tgz", + "integrity": "sha512-ghHx6/6Dvp+fw8CJhDUHFHDJ84hJE3BXNCzSgLdmNiFErWSOaZNsihDAsKq9ByTALo/xkNIwtDFGIl6r+RPXBg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.0.0", + "classnames": "2.x", + "rc-motion": "^2.4.3", + "rc-overflow": "^1.3.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-motion": { + "version": "2.9.5", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.5.tgz", + "integrity": "sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.44.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-notification": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.4.tgz", + "integrity": "sha512-KcS4O6B4qzM3KH7lkwOB7ooLPZ4b6J+VMmQgT51VZCeEcmghdeR4IrMcFq0LG+RPdnbe/ArT086tGM8Snimgiw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.9.0", + "rc-util": "^5.20.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-overflow": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.4.1.tgz", + "integrity": "sha512-3MoPQQPV1uKyOMVNd6SZfONi+f3st0r8PksexIdBTeIYbMX0Jr+k7pHEDvsXtR4BpCv90/Pv2MovVNhktKrwvw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.37.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-pagination": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-5.1.0.tgz", + "integrity": "sha512-8416Yip/+eclTFdHXLKTxZvn70duYVGTvUUWbckCCZoIl3jagqke3GLsFrMs0bsQBikiYpZLD9206Ej4SOdOXQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-picker": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.11.3.tgz", + "integrity": "sha512-MJ5teb7FlNE0NFHTncxXQ62Y5lytq6sh5nUw0iH8OkHL/TjARSEvSHpr940pWgjGANpjCwyMdvsEV55l5tYNSg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.1", + "rc-overflow": "^1.3.2", + "rc-resize-observer": "^1.4.0", + "rc-util": "^5.43.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "date-fns": ">= 2.x", + "dayjs": ">= 1.x", + "luxon": ">= 3.x", + "moment": ">= 2.x", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + }, + "peerDependenciesMeta": { + "date-fns": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + } + } + }, + "node_modules/rc-progress": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz", + "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.16.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-rate": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.1.tgz", + "integrity": "sha512-QUhQ9ivQ8Gy7mtMZPAjLbxBt5y9GRp65VcUyGUMF3N3fhiftivPHdpuDIaWIMOTEprAjZPC08bls1dQB+I1F2Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-resize-observer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.3.tgz", + "integrity": "sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.7", + "classnames": "^2.2.1", + "rc-util": "^5.44.1", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-segmented": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.7.0.tgz", + "integrity": "sha512-liijAjXz+KnTRVnxxXG2sYDGd6iLL7VpGGdR8gwoxAXy2KglviKCxLWZdjKYJzYzGSUwKDSTdYk8brj54Bn5BA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-motion": "^2.4.4", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-select": { + "version": "14.16.8", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.16.8.tgz", + "integrity": "sha512-NOV5BZa1wZrsdkKaiK7LHRuo5ZjZYMDxPP6/1+09+FB4KoNi8jcG1ZqLE3AVCxEsYMBe65OBx71wFoHRTP3LRg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.1.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-overflow": "^1.3.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-slider": { + "version": "11.1.8", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.8.tgz", + "integrity": "sha512-2gg/72YFSpKP+Ja5AjC5DPL1YnV8DEITDQrcc1eASrUYjl0esptaBVJBh5nLTXCCp15eD8EuGjwezVGSHhs9tQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-steps": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz", + "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.16.7", + "classnames": "^2.2.3", + "rc-util": "^5.16.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-switch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz", + "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0", + "classnames": "^2.2.1", + "rc-util": "^5.30.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-table": { + "version": "7.51.1", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.51.1.tgz", + "integrity": "sha512-5iq15mTHhvC42TlBLRCoCBLoCmGlbRZAlyF21FonFnS/DIC8DeRqnmdyVREwt2CFbPceM0zSNdEeVfiGaqYsKw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/context": "^1.4.0", + "classnames": "^2.2.5", + "rc-resize-observer": "^1.1.0", + "rc-util": "^5.44.3", + "rc-virtual-list": "^3.14.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tabs": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.7.0.tgz", + "integrity": "sha512-ZepiE+6fmozYdWf/9gVp7k56PKHB1YYoDsKeQA1CBlJ/POIhjkcYiv0AGP0w2Jhzftd3AVvZP/K+V+Lpi2ankA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "classnames": "2.x", + "rc-dropdown": "~4.2.0", + "rc-menu": "~9.16.0", + "rc-motion": "^2.6.2", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.34.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-textarea": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.10.2.tgz", + "integrity": "sha512-HfaeXiaSlpiSp0I/pvWpecFEHpVysZ9tpDLNkxQbMvMz6gsr7aVZ7FpWP9kt4t7DB+jJXesYS0us1uPZnlRnwQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-input": "~1.8.0", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tooltip": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.4.0.tgz", + "integrity": "sha512-kqyivim5cp8I5RkHmpsp1Nn/Wk+1oeloMv9c7LXNgDxUpGm+RbXJGL+OPvDlcRnx9DBeOe4wyOIl4OKUERyH1g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.1", + "rc-util": "^5.44.3" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tree": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.13.1.tgz", + "integrity": "sha512-FNhIefhftobCdUJshO7M8uZTA9F4OPGVXqGfZkkD/5soDeOhwO06T/aKTrg0WD8gRg/pyfq+ql3aMymLHCTC4A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.1" + }, + "engines": { + "node": ">=10.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-tree-select": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.27.0.tgz", + "integrity": "sha512-2qTBTzwIT7LRI1o7zLyrCzmo5tQanmyGbSaGTIf7sYimCklAToVVfpMC6OAldSKolcnjorBYPNSKQqJmN3TCww==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "classnames": "2.x", + "rc-select": "~14.16.2", + "rc-tree": "~5.13.0", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-upload": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.9.2.tgz", + "integrity": "sha512-nHx+9rbd1FKMiMRYsqQ3NkXUv7COHPBo3X1Obwq9SWS6/diF/A0aJ5OHubvwUAIDs+4RMleljV0pcrNUc823GQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.44.4", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.44.4.tgz", + "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-virtual-list": { + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.19.1.tgz", + "integrity": "sha512-DCapO2oyPqmooGhxBuXHM4lFuX+sshQwWqqkuyFA+4rShLe//+GEPVwiDgO+jKtKHtbeYwZoNvetwfHdOf+iUQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.0", + "classnames": "^2.2.6", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.0.tgz", + "integrity": "sha512-r15M3+LHKgM4SOapNmsH3smAizWds1vJ0Z9C4mWaKnT9/wD7+d/0jYcj6LmOvonkrO4Rgdyp4KQ/29gWN2i1eg==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-smooth": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", + "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==", + "license": "MIT", + "dependencies": { + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recharts": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.0.tgz", + "integrity": "sha512-cIvMxDfpAmqAmVgc4yb7pgm/O1tmmkl/CjrvXuW+62/+7jj/iF9Ykm+hb/UJt42TREHMyd3gb+pkgoa2MxgDIw==", + "license": "MIT", + "dependencies": { + "clsx": "^2.0.0", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.21", + "react-is": "^18.3.1", + "react-smooth": "^4.0.0", + "recharts-scale": "^0.4.4", + "tiny-invariant": "^1.3.1", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "license": "MIT", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.46.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz", + "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.46.2", + "@rollup/rollup-android-arm64": "4.46.2", + "@rollup/rollup-darwin-arm64": "4.46.2", + "@rollup/rollup-darwin-x64": "4.46.2", + "@rollup/rollup-freebsd-arm64": "4.46.2", + "@rollup/rollup-freebsd-x64": "4.46.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.46.2", + "@rollup/rollup-linux-arm-musleabihf": "4.46.2", + "@rollup/rollup-linux-arm64-gnu": "4.46.2", + "@rollup/rollup-linux-arm64-musl": "4.46.2", + "@rollup/rollup-linux-loongarch64-gnu": "4.46.2", + "@rollup/rollup-linux-ppc64-gnu": "4.46.2", + "@rollup/rollup-linux-riscv64-gnu": "4.46.2", + "@rollup/rollup-linux-riscv64-musl": "4.46.2", + "@rollup/rollup-linux-s390x-gnu": "4.46.2", + "@rollup/rollup-linux-x64-gnu": "4.46.2", + "@rollup/rollup-linux-x64-musl": "4.46.2", + "@rollup/rollup-win32-arm64-msvc": "4.46.2", + "@rollup/rollup-win32-ia32-msvc": "4.46.2", + "@rollup/rollup-win32-x64-msvc": "4.46.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/session-file-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/session-file-store/-/session-file-store-1.5.0.tgz", + "integrity": "sha512-60IZaJNzyu2tIeHutkYE8RiXVx3KRvacOxfLr2Mj92SIsRIroDsH0IlUUR6fJAjoTW4RQISbaOApa2IZpIwFdQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bagpipe": "^0.3.5", + "fs-extra": "^8.0.1", + "kruptein": "^2.0.4", + "object-assign": "^4.1.1", + "retry": "^0.12.0", + "write-file-atomic": "3.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/session-file-store/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/session-file-store/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/session-file-store/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==", + "license": "MIT" + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tailwindcss": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.12.tgz", + "integrity": "sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/throttle-debounce": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", + "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", + "license": "MIT", + "engines": { + "node": ">=12.22" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", + "license": "MIT" + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.39.1.tgz", + "integrity": "sha512-GDUv6/NDYngUlNvwaHM1RamYftxf782IyEDbdj3SeaIHHv8fNQVRC++fITT7kUJV/5rIA/tkoRSSskt6osEfqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.39.1", + "@typescript-eslint/parser": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/utils": "8.39.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dev": true, + "license": "MIT", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/victory-vendor": { + "version": "36.9.2", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", + "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, + "node_modules/vite": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.2.tgz", + "integrity": "sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.6", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.14" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zustand": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", + "integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.2.2" + }, + "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 + } + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json index 99f07ac33..5d44f3bae 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,51 +1,51 @@ -{ - "name": "edatamate", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "mock": "cd src/mock && nodemon --config nodemon.json --inspect=0.0.0.0:9229 mock.cjs --env=development --port=8002", - "build": "vite build", - "lint": "eslint .", - "preview": "vite preview" - }, - "dependencies": { - "@reduxjs/toolkit": "^2.11.0", - "@xyflow/react": "^12.8.3", - "antd": "^5.27.0", - "jssha": "^3.3.1", - "lucide-react": "^0.539.0", - "react": "^18.1.1", - "react-dom": "^18.1.1", - "react-redux": "^9.2.0", - "react-router": "^7.8.0", - "recharts": "2.15.0" - }, - "devDependencies": { - "@eslint/js": "^9.33.0", - "@tailwindcss/vite": "^4.1.12", - "@types/node": "^24.2.1", - "@types/react": "^18.1.10", - "@types/react-dom": "^18.1.7", - "@vitejs/plugin-react": "^5.0.0", - "body-parser": "^2.2.0", - "eslint": "^9.33.0", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.20", - "express": "^5.1.0", - "express-session": "^1.18.2", - "fs-extra": "^11.3.1", - "globals": "^16.3.0", - "lodash": "^4.17.21", - "minimist": "^1.2.8", - "mockjs": "^1.1.0", - "nodemon": "^3.1.10", - "postcss": "^8.5.6", - "session-file-store": "^1.5.0", - "tailwindcss": "^4.1.12", - "typescript": "~5.8.3", - "typescript-eslint": "^8.39.1", - "vite": "^7.1.2" - } -} +{ + "name": "edatamate", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "mock": "cd src/mock && nodemon --config nodemon.json --inspect=0.0.0.0:9229 mock.cjs --env=development --port=8002", + "build": "vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@reduxjs/toolkit": "^2.11.0", + "@xyflow/react": "^12.8.3", + "antd": "^5.27.0", + "jssha": "^3.3.1", + "lucide-react": "^0.539.0", + "react": "^18.1.1", + "react-dom": "^18.1.1", + "react-redux": "^9.2.0", + "react-router": "^7.8.0", + "recharts": "2.15.0" + }, + "devDependencies": { + "@eslint/js": "^9.33.0", + "@tailwindcss/vite": "^4.1.12", + "@types/node": "^24.2.1", + "@types/react": "^18.1.10", + "@types/react-dom": "^18.1.7", + "@vitejs/plugin-react": "^5.0.0", + "body-parser": "^2.2.0", + "eslint": "^9.33.0", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "express": "^5.1.0", + "express-session": "^1.18.2", + "fs-extra": "^11.3.1", + "globals": "^16.3.0", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "mockjs": "^1.1.0", + "nodemon": "^3.1.10", + "postcss": "^8.5.6", + "session-file-store": "^1.5.0", + "tailwindcss": "^4.1.12", + "typescript": "~5.8.3", + "typescript-eslint": "^8.39.1", + "vite": "^7.1.2" + } +} diff --git a/frontend/src/components/ActionDropdown.tsx b/frontend/src/components/ActionDropdown.tsx index d6d7ab48e..9fe696bf4 100644 --- a/frontend/src/components/ActionDropdown.tsx +++ b/frontend/src/components/ActionDropdown.tsx @@ -1,117 +1,117 @@ -import { Dropdown, Popconfirm, Button, Space } from "antd"; -import { EllipsisOutlined } from "@ant-design/icons"; -import { useState } from "react"; - -interface ActionItem { - key: string; - label: string; - icon?: React.ReactNode; - danger?: boolean; - confirm?: { - title: string; - description?: string; - okText?: string; - cancelText?: string; - }; -} - -interface ActionDropdownProps { - actions?: ActionItem[]; - onAction?: (key: string, action: ActionItem) => void; - placement?: - | "bottomRight" - | "topLeft" - | "topCenter" - | "topRight" - | "bottomLeft" - | "bottomCenter" - | "top" - | "bottom"; -} - -const ActionDropdown = ({ - actions = [], - onAction, - placement = "bottomRight", -}: ActionDropdownProps) => { - const [open, setOpen] = useState(false); - const handleActionClick = (action: ActionItem) => { - if (action.confirm) { - // 如果有确认框,不立即执行,等待确认 - return; - } - // 执行操作 - onAction?.(action.key, action); - // 如果没有确认框,则立即关闭 Dropdown - setOpen(false); - }; - - const dropdownContent = ( -
- - {actions.map((action) => { - if (action.confirm) { - return ( - { - onAction?.(action.key, action); - setOpen(false); - }} - okText={action.confirm.okText || "确定"} - cancelText={action.confirm.cancelText || "取消"} - okType={action.danger ? "danger" : "primary"} - styles={{ root: { zIndex: 9999 } }} - > - - - ); - } - - return ( - - ); - })} - -
- ); - - return ( - - + + ); + } + + return ( + + ); + })} + + + ); + + return ( + + - - - - - - } - > - } - className="cursor-pointer" - onClick={() => setShowPopover(true)} - > - 添加标签 - - - - ); -} +import { Button, Input, Popover, theme, Tag, Empty } from "antd"; +import { PlusOutlined } from "@ant-design/icons"; +import { useEffect, useMemo, useState } from "react"; + +interface Tag { + id: number; + name: string; + color: string; +} + +interface AddTagPopoverProps { + tags: Tag[]; + onFetchTags?: () => Promise; + onAddTag?: (tag: Tag) => void; + onCreateAndTag?: (tagName: string) => void; +} + +export default function AddTagPopover({ + tags, + onFetchTags, + onAddTag, + onCreateAndTag, +}: AddTagPopoverProps) { + const { token } = theme.useToken(); + const [showPopover, setShowPopover] = useState(false); + + const [newTag, setNewTag] = useState(""); + const [allTags, setAllTags] = useState([]); + + const tagsSet = useMemo(() => new Set(tags.map((tag) => tag.id)), [tags]); + + const fetchTags = async () => { + if (onFetchTags && showPopover) { + const data = await onFetchTags?.(); + setAllTags(data || []); + } + }; + useEffect(() => { + fetchTags(); + }, [showPopover]); + + const availableTags = useMemo(() => { + return allTags.filter((tag) => !tagsSet.has(tag.id)); + }, [allTags, tagsSet]); + + const handleCreateAndAddTag = () => { + if (newTag.trim()) { + onCreateAndTag?.(newTag.trim()); + setNewTag(""); + } + + setShowPopover(false); + }; + + const tagPlusStyle: React.CSSProperties = { + height: 22, + background: token.colorBgContainer, + borderStyle: "dashed", + }; + + return ( + <> + +

+ 添加标签 +

+ {/* Available Tags */} + {availableTags?.length ? ( +
+
选择现有标签
+
+ {availableTags.map((tag) => ( + { + onAddTag?.(tag.name); + setShowPopover(false); + }} + > + + {tag.name} + + ))} +
+
+ ) : ( + + )} + + {/* Create New Tag */} +
+
创建新标签
+
+ setNewTag(e.target.value)} + className="h-8 text-sm" + /> + +
+
+ + + + } + > + } + className="cursor-pointer" + onClick={() => setShowPopover(true)} + > + 添加标签 + +
+ + ); +} diff --git a/frontend/src/components/AdvancedCronScheduler.tsx b/frontend/src/components/AdvancedCronScheduler.tsx index b700615f2..8c331d335 100644 --- a/frontend/src/components/AdvancedCronScheduler.tsx +++ b/frontend/src/components/AdvancedCronScheduler.tsx @@ -1,556 +1,556 @@ -import React, { useState, useCallback, useEffect } from "react"; -import { - Card, - Select, - Input, - Space, - Typography, - Row, - Col, - Divider, - Button, - Tooltip, -} from "antd"; -import { InfoCircleOutlined } from "@ant-design/icons"; - -const { Title, Text } = Typography; -const { Option } = Select; - -export interface AdvancedCronConfig { - second: string; - minute: string; - hour: string; - day: string; - month: string; - weekday: string; - year?: string; - cronExpression: string; -} - -interface AdvancedCronSchedulerProps { - value?: AdvancedCronConfig; - onChange?: (config: AdvancedCronConfig) => void; - showYear?: boolean; // 是否显示年份字段 - className?: string; -} - -// Cron字段的选项配置 -const CRON_OPTIONS = { - second: { - label: "秒", - range: [0, 59], - examples: ["0", "*/5", "10,20,30", "0-30"], - description: "秒钟 (0-59)", - }, - minute: { - label: "分钟", - range: [0, 59], - examples: ["0", "*/15", "5,10,15", "0-30"], - description: "分钟 (0-59)", - }, - hour: { - label: "小时", - range: [0, 23], - examples: ["0", "*/2", "8,14,20", "9-17"], - description: "小时 (0-23)", - }, - day: { - label: "日", - range: [1, 31], - examples: ["*", "1", "1,15", "1-15", "*/2"], - description: "日期 (1-31)", - }, - month: { - label: "月", - range: [1, 12], - examples: ["*", "1", "1,6,12", "3-9", "*/3"], - description: "月份 (1-12)", - }, - year: { - label: "年", - range: [1970, 2099], - examples: ["*", "2024", "2024-2026", "*/2"], - description: "年份 (1970-2099)", - }, - weekday: { - label: "周", - range: [0, 7], // 0和7都表示周日 - examples: ["*", "1", "1-5", "1,3,5", "0,6"], - description: "星期 (0-7, 0和7都表示周日)", - weekNames: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"], - }, -}; - -// 生成常用的cron表达式选项 -const generateCommonOptions = (field: keyof typeof CRON_OPTIONS) => { - const options = [ - { label: "* (任意)", value: "*" }, - { label: "? (不指定)", value: "?" }, // 仅用于日和周字段 - ]; - - const config = CRON_OPTIONS[field]; - const [start, end] = config.range; - - // 添加具体数值选项 - if (field === "weekday") { - const weekdayConfig = config as { weekNames?: string[] }; - weekdayConfig.weekNames?.forEach((name: string, index: number) => { - options.push({ label: `${index} (${name})`, value: index.toString() }); - }); - // 添加7作为周日的别名 - options.push({ label: "7 (周日)", value: "7" }); - } else { - // 添加部分具体数值 - const step = - field === "year" ? 5 : field === "day" || field === "month" ? 3 : 5; - for (let i = start; i <= end; i += step) { - if (i <= end) { - options.push({ label: i.toString(), value: i.toString() }); - } - } - } - - // 添加间隔选项 - if (field !== "year") { - options.push( - { label: "*/2 (每2个)", value: "*/2" }, - { label: "*/5 (每5个)", value: "*/5" }, - { label: "*/10 (每10个)", value: "*/10" } - ); - } - - // 添加范围选项 - if (field === "hour") { - options.push( - { label: "9-17 (工作时间)", value: "9-17" }, - { label: "0-6 (凌晨)", value: "0-6" } - ); - } else if (field === "weekday") { - options.push( - { label: "1-5 (工作日)", value: "1-5" }, - { label: "0,6 (周末)", value: "0,6" } - ); - } else if (field === "day") { - options.push( - { label: "1-15 (上半月)", value: "1-15" }, - { label: "16-31 (下半月)", value: "16-31" } - ); - } - - return options; -}; - -// 验证cron字段值 -const validateCronField = ( - value: string, - field: keyof typeof CRON_OPTIONS -): boolean => { - if (!value || value === "*" || value === "?") return true; - - const config = CRON_OPTIONS[field]; - const [min, max] = config.range; - - // 验证基本格式 - const patterns = [ - /^\d+$/, // 单个数字 - /^\d+-\d+$/, // 范围 - /^\*\/\d+$/, // 间隔 - /^(\d+,)*\d+$/, // 列表 - /^(\d+-\d+,)*(\d+-\d+|\d+)$/, // 复合表达式 - ]; - - if (!patterns.some((pattern) => pattern.test(value))) { - return false; - } - - // 验证数值范围 - const numbers = value.match(/\d+/g); - if (numbers) { - return numbers.every((num) => { - const n = parseInt(num); - return n >= min && n <= max; - }); - } - - return true; -}; - -// 生成cron表达式 -const generateCronExpression = ( - config: Omit -): string => { - const { second, minute, hour, day, month, weekday, year } = config; - - const parts = [second, minute, hour, day, month, weekday]; - if (year && year !== "*") { - parts.push(year); - } - - return parts.join(" "); -}; - -// 解析cron表达式为人类可读的描述 -const parseCronDescription = (cronExpression: string): string => { - const parts = cronExpression.split(" "); - if (parts.length < 6) return cronExpression; - - const [second, minute, hour, day, month, weekday, year] = parts; - - const descriptions = []; - - // 时间描述 - if (second === "0" && minute !== "*" && hour !== "*") { - descriptions.push(`${hour.padStart(2, "0")}:${minute.padStart(2, "0")}`); - } else { - if (hour !== "*") descriptions.push(`${hour}时`); - if (minute !== "*") descriptions.push(`${minute}分`); - if (second !== "*" && second !== "0") descriptions.push(`${second}秒`); - } - - // 日期描述 - if (day !== "*" && day !== "?") { - descriptions.push(`${day}日`); - } - - // 月份描述 - if (month !== "*") { - descriptions.push(`${month}月`); - } - - // 星期描述 - if (weekday !== "*" && weekday !== "?") { - const weekNames = [ - "周日", - "周一", - "周二", - "周三", - "周四", - "周五", - "周六", - "周日", - ]; - if (weekday === "1-5") { - descriptions.push("工作日"); - } else if (weekday === "0,6") { - descriptions.push("周末"); - } else if (/^\d$/.test(weekday)) { - descriptions.push(weekNames[parseInt(weekday)]); - } else { - descriptions.push(`周${weekday}`); - } - } - - // 年份描述 - if (year && year !== "*") { - descriptions.push(`${year}年`); - } - - return descriptions.length > 0 ? descriptions.join(" ") : "每秒执行"; -}; - -const AdvancedCronScheduler: React.FC = ({ - value = { - second: "0", - minute: "0", - hour: "0", - day: "*", - month: "*", - weekday: "?", - year: "*", - cronExpression: "0 0 0 * * ?", - }, - onChange, - showYear = false, - className, -}) => { - const [config, setConfig] = useState(value); - const [customMode, setCustomMode] = useState(false); - - // 更新配置 - const updateConfig = useCallback( - (updates: Partial) => { - const newConfig = { ...config, ...updates }; - newConfig.cronExpression = generateCronExpression(newConfig); - setConfig(newConfig); - onChange?.(newConfig); - }, - [config, onChange] - ); - - // 同步外部值 - useEffect(() => { - setConfig(value); - }, [value]); - - // 处理字段变化 - const handleFieldChange = ( - field: keyof AdvancedCronConfig, - fieldValue: string - ) => { - if (field === "cronExpression") { - // 直接编辑cron表达式 - const parts = fieldValue.split(" "); - if (parts.length >= 6) { - const newConfig = { - second: parts[0] || "0", - minute: parts[1] || "0", - hour: parts[2] || "0", - day: parts[3] || "*", - month: parts[4] || "*", - weekday: parts[5] || "?", - year: parts[6] || "*", - cronExpression: fieldValue, - }; - setConfig(newConfig); - onChange?.(newConfig); - } - } else { - updateConfig({ [field]: fieldValue }); - } - }; - - // 快速设置预设 - const setPreset = (preset: Partial) => { - updateConfig(preset); - }; - - // 常用预设 - const commonPresets = [ - { - label: "每秒", - config: { - second: "*", - minute: "*", - hour: "*", - day: "*", - month: "*", - weekday: "?", - }, - }, - { - label: "每分钟", - config: { - second: "0", - minute: "*", - hour: "*", - day: "*", - month: "*", - weekday: "?", - }, - }, - { - label: "每小时", - config: { - second: "0", - minute: "0", - hour: "*", - day: "*", - month: "*", - weekday: "?", - }, - }, - { - label: "每天午夜", - config: { - second: "0", - minute: "0", - hour: "0", - day: "*", - month: "*", - weekday: "?", - }, - }, - { - label: "每周一9点", - config: { - second: "0", - minute: "0", - hour: "9", - day: "?", - month: "*", - weekday: "1", - }, - }, - { - label: "每月1日0点", - config: { - second: "0", - minute: "0", - hour: "0", - day: "1", - month: "*", - weekday: "?", - }, - }, - { - label: "工作日9点", - config: { - second: "0", - minute: "0", - hour: "9", - day: "?", - month: "*", - weekday: "1-5", - }, - }, - { - label: "每15分钟", - config: { - second: "0", - minute: "*/15", - hour: "*", - day: "*", - month: "*", - weekday: "?", - }, - }, - ]; - - const fields: Array = [ - "second", - "minute", - "hour", - "day", - "month", - "weekday", - ]; - if (showYear) fields.push("year"); - - return ( - - - {/* 标题和切换模式 */} -
- - 高级 Cron 表达式配置 - - -
- - {/* 快速预设 */} -
- 快速预设: -
- {commonPresets.map((preset, index) => ( - - ))} -
-
- - {customMode ? ( - /* 手动编辑模式 */ -
- Cron 表达式: - - handleFieldChange("cronExpression", e.target.value) - } - placeholder="秒 分 时 日 月 周 [年]" - /> - - 格式:秒(0-59) 分(0-59) 时(0-23) 日(1-31) 月(1-12) 周(0-7) - [年(1970-2099)] - -
- ) : ( - /* 向导模式 */ - - {fields.map((field) => { - const fieldConfig = CRON_OPTIONS[field]; - const options = generateCommonOptions(field); - return ( - -
-
- {fieldConfig.label} - - - -
- - {/* 自定义输入 */} - handleFieldChange(field, e.target.value)} - status={ - validateCronField(config[field] || "", field) ? "" : "error" - } - /> -
- - ); - })} -
- )} - - - - {/* 结果预览 */} -
- 生成的 Cron 表达式: - - - 描述:{parseCronDescription(config.cronExpression)} - -
- - {/* 字段说明 */} -
- 字段说明: -
- - • * 表示任意值 - • ? 表示不指定值(仅日、周字段) - • */5 表示每5个单位 - • 1-5 表示范围 - • 1,3,5 表示列表 - • 日和周字段不能同时指定具体值 - -
-
-
-
- ); -}; - -export default AdvancedCronScheduler; +import React, { useState, useCallback, useEffect } from "react"; +import { + Card, + Select, + Input, + Space, + Typography, + Row, + Col, + Divider, + Button, + Tooltip, +} from "antd"; +import { InfoCircleOutlined } from "@ant-design/icons"; + +const { Title, Text } = Typography; +const { Option } = Select; + +export interface AdvancedCronConfig { + second: string; + minute: string; + hour: string; + day: string; + month: string; + weekday: string; + year?: string; + cronExpression: string; +} + +interface AdvancedCronSchedulerProps { + value?: AdvancedCronConfig; + onChange?: (config: AdvancedCronConfig) => void; + showYear?: boolean; // 是否显示年份字段 + className?: string; +} + +// Cron字段的选项配置 +const CRON_OPTIONS = { + second: { + label: "秒", + range: [0, 59], + examples: ["0", "*/5", "10,20,30", "0-30"], + description: "秒钟 (0-59)", + }, + minute: { + label: "分钟", + range: [0, 59], + examples: ["0", "*/15", "5,10,15", "0-30"], + description: "分钟 (0-59)", + }, + hour: { + label: "小时", + range: [0, 23], + examples: ["0", "*/2", "8,14,20", "9-17"], + description: "小时 (0-23)", + }, + day: { + label: "日", + range: [1, 31], + examples: ["*", "1", "1,15", "1-15", "*/2"], + description: "日期 (1-31)", + }, + month: { + label: "月", + range: [1, 12], + examples: ["*", "1", "1,6,12", "3-9", "*/3"], + description: "月份 (1-12)", + }, + year: { + label: "年", + range: [1970, 2099], + examples: ["*", "2024", "2024-2026", "*/2"], + description: "年份 (1970-2099)", + }, + weekday: { + label: "周", + range: [0, 7], // 0和7都表示周日 + examples: ["*", "1", "1-5", "1,3,5", "0,6"], + description: "星期 (0-7, 0和7都表示周日)", + weekNames: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"], + }, +}; + +// 生成常用的cron表达式选项 +const generateCommonOptions = (field: keyof typeof CRON_OPTIONS) => { + const options = [ + { label: "* (任意)", value: "*" }, + { label: "? (不指定)", value: "?" }, // 仅用于日和周字段 + ]; + + const config = CRON_OPTIONS[field]; + const [start, end] = config.range; + + // 添加具体数值选项 + if (field === "weekday") { + const weekdayConfig = config as { weekNames?: string[] }; + weekdayConfig.weekNames?.forEach((name: string, index: number) => { + options.push({ label: `${index} (${name})`, value: index.toString() }); + }); + // 添加7作为周日的别名 + options.push({ label: "7 (周日)", value: "7" }); + } else { + // 添加部分具体数值 + const step = + field === "year" ? 5 : field === "day" || field === "month" ? 3 : 5; + for (let i = start; i <= end; i += step) { + if (i <= end) { + options.push({ label: i.toString(), value: i.toString() }); + } + } + } + + // 添加间隔选项 + if (field !== "year") { + options.push( + { label: "*/2 (每2个)", value: "*/2" }, + { label: "*/5 (每5个)", value: "*/5" }, + { label: "*/10 (每10个)", value: "*/10" } + ); + } + + // 添加范围选项 + if (field === "hour") { + options.push( + { label: "9-17 (工作时间)", value: "9-17" }, + { label: "0-6 (凌晨)", value: "0-6" } + ); + } else if (field === "weekday") { + options.push( + { label: "1-5 (工作日)", value: "1-5" }, + { label: "0,6 (周末)", value: "0,6" } + ); + } else if (field === "day") { + options.push( + { label: "1-15 (上半月)", value: "1-15" }, + { label: "16-31 (下半月)", value: "16-31" } + ); + } + + return options; +}; + +// 验证cron字段值 +const validateCronField = ( + value: string, + field: keyof typeof CRON_OPTIONS +): boolean => { + if (!value || value === "*" || value === "?") return true; + + const config = CRON_OPTIONS[field]; + const [min, max] = config.range; + + // 验证基本格式 + const patterns = [ + /^\d+$/, // 单个数字 + /^\d+-\d+$/, // 范围 + /^\*\/\d+$/, // 间隔 + /^(\d+,)*\d+$/, // 列表 + /^(\d+-\d+,)*(\d+-\d+|\d+)$/, // 复合表达式 + ]; + + if (!patterns.some((pattern) => pattern.test(value))) { + return false; + } + + // 验证数值范围 + const numbers = value.match(/\d+/g); + if (numbers) { + return numbers.every((num) => { + const n = parseInt(num); + return n >= min && n <= max; + }); + } + + return true; +}; + +// 生成cron表达式 +const generateCronExpression = ( + config: Omit +): string => { + const { second, minute, hour, day, month, weekday, year } = config; + + const parts = [second, minute, hour, day, month, weekday]; + if (year && year !== "*") { + parts.push(year); + } + + return parts.join(" "); +}; + +// 解析cron表达式为人类可读的描述 +const parseCronDescription = (cronExpression: string): string => { + const parts = cronExpression.split(" "); + if (parts.length < 6) return cronExpression; + + const [second, minute, hour, day, month, weekday, year] = parts; + + const descriptions = []; + + // 时间描述 + if (second === "0" && minute !== "*" && hour !== "*") { + descriptions.push(`${hour.padStart(2, "0")}:${minute.padStart(2, "0")}`); + } else { + if (hour !== "*") descriptions.push(`${hour}时`); + if (minute !== "*") descriptions.push(`${minute}分`); + if (second !== "*" && second !== "0") descriptions.push(`${second}秒`); + } + + // 日期描述 + if (day !== "*" && day !== "?") { + descriptions.push(`${day}日`); + } + + // 月份描述 + if (month !== "*") { + descriptions.push(`${month}月`); + } + + // 星期描述 + if (weekday !== "*" && weekday !== "?") { + const weekNames = [ + "周日", + "周一", + "周二", + "周三", + "周四", + "周五", + "周六", + "周日", + ]; + if (weekday === "1-5") { + descriptions.push("工作日"); + } else if (weekday === "0,6") { + descriptions.push("周末"); + } else if (/^\d$/.test(weekday)) { + descriptions.push(weekNames[parseInt(weekday)]); + } else { + descriptions.push(`周${weekday}`); + } + } + + // 年份描述 + if (year && year !== "*") { + descriptions.push(`${year}年`); + } + + return descriptions.length > 0 ? descriptions.join(" ") : "每秒执行"; +}; + +const AdvancedCronScheduler: React.FC = ({ + value = { + second: "0", + minute: "0", + hour: "0", + day: "*", + month: "*", + weekday: "?", + year: "*", + cronExpression: "0 0 0 * * ?", + }, + onChange, + showYear = false, + className, +}) => { + const [config, setConfig] = useState(value); + const [customMode, setCustomMode] = useState(false); + + // 更新配置 + const updateConfig = useCallback( + (updates: Partial) => { + const newConfig = { ...config, ...updates }; + newConfig.cronExpression = generateCronExpression(newConfig); + setConfig(newConfig); + onChange?.(newConfig); + }, + [config, onChange] + ); + + // 同步外部值 + useEffect(() => { + setConfig(value); + }, [value]); + + // 处理字段变化 + const handleFieldChange = ( + field: keyof AdvancedCronConfig, + fieldValue: string + ) => { + if (field === "cronExpression") { + // 直接编辑cron表达式 + const parts = fieldValue.split(" "); + if (parts.length >= 6) { + const newConfig = { + second: parts[0] || "0", + minute: parts[1] || "0", + hour: parts[2] || "0", + day: parts[3] || "*", + month: parts[4] || "*", + weekday: parts[5] || "?", + year: parts[6] || "*", + cronExpression: fieldValue, + }; + setConfig(newConfig); + onChange?.(newConfig); + } + } else { + updateConfig({ [field]: fieldValue }); + } + }; + + // 快速设置预设 + const setPreset = (preset: Partial) => { + updateConfig(preset); + }; + + // 常用预设 + const commonPresets = [ + { + label: "每秒", + config: { + second: "*", + minute: "*", + hour: "*", + day: "*", + month: "*", + weekday: "?", + }, + }, + { + label: "每分钟", + config: { + second: "0", + minute: "*", + hour: "*", + day: "*", + month: "*", + weekday: "?", + }, + }, + { + label: "每小时", + config: { + second: "0", + minute: "0", + hour: "*", + day: "*", + month: "*", + weekday: "?", + }, + }, + { + label: "每天午夜", + config: { + second: "0", + minute: "0", + hour: "0", + day: "*", + month: "*", + weekday: "?", + }, + }, + { + label: "每周一9点", + config: { + second: "0", + minute: "0", + hour: "9", + day: "?", + month: "*", + weekday: "1", + }, + }, + { + label: "每月1日0点", + config: { + second: "0", + minute: "0", + hour: "0", + day: "1", + month: "*", + weekday: "?", + }, + }, + { + label: "工作日9点", + config: { + second: "0", + minute: "0", + hour: "9", + day: "?", + month: "*", + weekday: "1-5", + }, + }, + { + label: "每15分钟", + config: { + second: "0", + minute: "*/15", + hour: "*", + day: "*", + month: "*", + weekday: "?", + }, + }, + ]; + + const fields: Array = [ + "second", + "minute", + "hour", + "day", + "month", + "weekday", + ]; + if (showYear) fields.push("year"); + + return ( + + + {/* 标题和切换模式 */} +
+ + 高级 Cron 表达式配置 + + +
+ + {/* 快速预设 */} +
+ 快速预设: +
+ {commonPresets.map((preset, index) => ( + + ))} +
+
+ + {customMode ? ( + /* 手动编辑模式 */ +
+ Cron 表达式: + + handleFieldChange("cronExpression", e.target.value) + } + placeholder="秒 分 时 日 月 周 [年]" + /> + + 格式:秒(0-59) 分(0-59) 时(0-23) 日(1-31) 月(1-12) 周(0-7) + [年(1970-2099)] + +
+ ) : ( + /* 向导模式 */ + + {fields.map((field) => { + const fieldConfig = CRON_OPTIONS[field]; + const options = generateCommonOptions(field); + return ( + +
+
+ {fieldConfig.label} + + + +
+ + {/* 自定义输入 */} + handleFieldChange(field, e.target.value)} + status={ + validateCronField(config[field] || "", field) ? "" : "error" + } + /> +
+ + ); + })} +
+ )} + + + + {/* 结果预览 */} +
+ 生成的 Cron 表达式: + + + 描述:{parseCronDescription(config.cronExpression)} + +
+ + {/* 字段说明 */} +
+ 字段说明: +
+ + • * 表示任意值 + • ? 表示不指定值(仅日、周字段) + • */5 表示每5个单位 + • 1-5 表示范围 + • 1,3,5 表示列表 + • 日和周字段不能同时指定具体值 + +
+
+
+
+ ); +}; + +export default AdvancedCronScheduler; diff --git a/frontend/src/components/CardView.tsx b/frontend/src/components/CardView.tsx index 0219c6eee..04301cb70 100644 --- a/frontend/src/components/CardView.tsx +++ b/frontend/src/components/CardView.tsx @@ -1,292 +1,292 @@ -import React, { useState, useEffect, useRef } from "react"; -import { Tag, Pagination, Tooltip, Empty, Popover, Spin } from "antd"; -import { ClockCircleOutlined, StarFilled } from "@ant-design/icons"; -import type { ItemType } from "antd/es/menu/interface"; -import { formatDateTime } from "@/utils/unit"; -import ActionDropdown from "./ActionDropdown"; -import { Database } from "lucide-react"; - -interface BaseCardDataType { - id: string | number; - name: string; - type: string; - icon?: React.JSX.Element; - iconColor?: string; - status: { - label: string; - icon?: React.JSX.Element; - color?: string; - } | null; - description: string; - tags?: string[]; - statistics?: { label: string; value: string | number }[]; - updatedAt?: string; -} - -interface CardViewProps { - data: T[]; - pagination: { - [key: string]: any; - current: number; - pageSize: number; - total: number; - }; - operations: - | { - key: string; - label: string; - danger?: boolean; - icon?: React.JSX.Element; - onClick?: (item: T) => void; - }[] - | ((item: T) => ItemType[]); - loading?: boolean; - onView?: (item: T) => void; - onFavorite?: (item: T) => void; - isFavorite?: (item: T) => boolean; -} - -// 标签渲染组件 -const TagsRenderer = ({ tags }: { tags?: any[] }) => { - const [visibleTags, setVisibleTags] = useState([]); - const [hiddenTags, setHiddenTags] = useState([]); - const containerRef = useRef(null); - - useEffect(() => { - if (!tags || tags.length === 0) return; - - const calculateVisibleTags = () => { - if (!containerRef.current) return; - - const containerWidth = containerRef.current.offsetWidth; - const tempDiv = document.createElement("div"); - tempDiv.style.visibility = "hidden"; - tempDiv.style.position = "absolute"; - tempDiv.style.top = "-9999px"; - tempDiv.className = "flex flex-wrap gap-1"; - document.body.appendChild(tempDiv); - - let totalWidth = 0; - let visibleCount = 0; - const tagElements: HTMLElement[] = []; - - // 为每个tag创建临时元素来测量宽度 - tags.forEach((tag, index) => { - const tagElement = document.createElement("span"); - tagElement.className = "ant-tag ant-tag-default"; - tagElement.style.margin = "2px"; - tagElement.textContent = typeof tag === "string" ? tag : tag.name; - tempDiv.appendChild(tagElement); - tagElements.push(tagElement); - - const tagWidth = tagElement.offsetWidth + 4; // 加上gap的宽度 - - // 如果不是最后一个标签,需要预留+n标签的空间 - const plusTagWidth = index < tags.length - 1 ? 35 : 0; // +n标签大约35px宽度 - - if (totalWidth + tagWidth + plusTagWidth <= containerWidth) { - totalWidth += tagWidth; - visibleCount++; - } else { - // 如果当前标签放不下,且已经有可见标签,则停止 - if (visibleCount > 0) return; - // 如果是第一个标签就放不下,至少显示一个 - if (index === 0) { - totalWidth += tagWidth; - visibleCount = 1; - } - } - }); - - document.body.removeChild(tempDiv); - - setVisibleTags(tags.slice(0, visibleCount)); - setHiddenTags(tags.slice(visibleCount)); - }; - - // 延迟执行以确保DOM已渲染 - const timer = setTimeout(calculateVisibleTags, 0); - - // 监听窗口大小变化 - const handleResize = () => { - calculateVisibleTags(); - }; - - window.addEventListener("resize", handleResize); - - return () => { - clearTimeout(timer); - window.removeEventListener("resize", handleResize); - }; - }, [tags]); - - if (!tags || tags.length === 0) return null; - - const popoverContent = ( -
-
- {hiddenTags.map((tag, index) => ( - {typeof tag === "string" ? tag : tag.name} - ))} -
-
- ); - - return ( -
- {visibleTags.map((tag, index) => ( - {typeof tag === "string" ? tag : tag.name} - ))} - {hiddenTags.length > 0 && ( - - - +{hiddenTags.length} - - - )} -
- ); -}; - -function CardView(props: CardViewProps) { - const { - data, - pagination, - operations, - loading, - onView, - onFavorite, - isFavorite, - } = props; - - if (data.length === 0) { - return ( -
- -
- ); - } - - const ops = (item) => - typeof operations === "function" ? operations(item) : operations; - - return ( -
-
- {data.map((item) => ( -
-
-
onView?.(item)} - style={{ cursor: onView ? "pointer" : "default" }} - > - {/* Header */} -
-
- {item?.icon && ( -
-
{item?.icon}
-
- )} -
-
-

- {item?.name} -

- {item?.status && ( - -
- {item?.status?.icon && ( - {item?.status?.icon} - )} - {item?.status?.label} -
-
- )} -
-
-
- {onFavorite && ( - onFavorite?.(item)} - /> - )} -
- -
- {/* Tags */} - - - {/* Description */} -

- - {item?.description} - -

- - {/* Statistics */} -
- {item?.statistics?.map((stat, idx) => ( -
-
- {stat?.label}: -
-
- {stat?.value} -
-
- ))} -
-
-
- - {/* Actions */} -
-
-
- {" "} - {formatDateTime(item?.updatedAt)} -
-
- {operations && ( - { - const operation = ops(item).find((op) => op.key === key); - if (operation?.onClick) { - operation.onClick(item); - } - }} - /> - )} -
-
-
- ))} -
-
- -
-
- ); -} - -export default CardView; +import React, { useState, useEffect, useRef } from "react"; +import { Tag, Pagination, Tooltip, Empty, Popover, Spin } from "antd"; +import { ClockCircleOutlined, StarFilled } from "@ant-design/icons"; +import type { ItemType } from "antd/es/menu/interface"; +import { formatDateTime } from "@/utils/unit"; +import ActionDropdown from "./ActionDropdown"; +import { Database } from "lucide-react"; + +interface BaseCardDataType { + id: string | number; + name: string; + type: string; + icon?: React.JSX.Element; + iconColor?: string; + status: { + label: string; + icon?: React.JSX.Element; + color?: string; + } | null; + description: string; + tags?: string[]; + statistics?: { label: string; value: string | number }[]; + updatedAt?: string; +} + +interface CardViewProps { + data: T[]; + pagination: { + [key: string]: any; + current: number; + pageSize: number; + total: number; + }; + operations: + | { + key: string; + label: string; + danger?: boolean; + icon?: React.JSX.Element; + onClick?: (item: T) => void; + }[] + | ((item: T) => ItemType[]); + loading?: boolean; + onView?: (item: T) => void; + onFavorite?: (item: T) => void; + isFavorite?: (item: T) => boolean; +} + +// 标签渲染组件 +const TagsRenderer = ({ tags }: { tags?: any[] }) => { + const [visibleTags, setVisibleTags] = useState([]); + const [hiddenTags, setHiddenTags] = useState([]); + const containerRef = useRef(null); + + useEffect(() => { + if (!tags || tags.length === 0) return; + + const calculateVisibleTags = () => { + if (!containerRef.current) return; + + const containerWidth = containerRef.current.offsetWidth; + const tempDiv = document.createElement("div"); + tempDiv.style.visibility = "hidden"; + tempDiv.style.position = "absolute"; + tempDiv.style.top = "-9999px"; + tempDiv.className = "flex flex-wrap gap-1"; + document.body.appendChild(tempDiv); + + let totalWidth = 0; + let visibleCount = 0; + const tagElements: HTMLElement[] = []; + + // 为每个tag创建临时元素来测量宽度 + tags.forEach((tag, index) => { + const tagElement = document.createElement("span"); + tagElement.className = "ant-tag ant-tag-default"; + tagElement.style.margin = "2px"; + tagElement.textContent = typeof tag === "string" ? tag : tag.name; + tempDiv.appendChild(tagElement); + tagElements.push(tagElement); + + const tagWidth = tagElement.offsetWidth + 4; // 加上gap的宽度 + + // 如果不是最后一个标签,需要预留+n标签的空间 + const plusTagWidth = index < tags.length - 1 ? 35 : 0; // +n标签大约35px宽度 + + if (totalWidth + tagWidth + plusTagWidth <= containerWidth) { + totalWidth += tagWidth; + visibleCount++; + } else { + // 如果当前标签放不下,且已经有可见标签,则停止 + if (visibleCount > 0) return; + // 如果是第一个标签就放不下,至少显示一个 + if (index === 0) { + totalWidth += tagWidth; + visibleCount = 1; + } + } + }); + + document.body.removeChild(tempDiv); + + setVisibleTags(tags.slice(0, visibleCount)); + setHiddenTags(tags.slice(visibleCount)); + }; + + // 延迟执行以确保DOM已渲染 + const timer = setTimeout(calculateVisibleTags, 0); + + // 监听窗口大小变化 + const handleResize = () => { + calculateVisibleTags(); + }; + + window.addEventListener("resize", handleResize); + + return () => { + clearTimeout(timer); + window.removeEventListener("resize", handleResize); + }; + }, [tags]); + + if (!tags || tags.length === 0) return null; + + const popoverContent = ( +
+
+ {hiddenTags.map((tag, index) => ( + {typeof tag === "string" ? tag : tag.name} + ))} +
+
+ ); + + return ( +
+ {visibleTags.map((tag, index) => ( + {typeof tag === "string" ? tag : tag.name} + ))} + {hiddenTags.length > 0 && ( + + + +{hiddenTags.length} + + + )} +
+ ); +}; + +function CardView(props: CardViewProps) { + const { + data, + pagination, + operations, + loading, + onView, + onFavorite, + isFavorite, + } = props; + + if (data.length === 0) { + return ( +
+ +
+ ); + } + + const ops = (item) => + typeof operations === "function" ? operations(item) : operations; + + return ( +
+
+ {data.map((item) => ( +
+
+
onView?.(item)} + style={{ cursor: onView ? "pointer" : "default" }} + > + {/* Header */} +
+
+ {item?.icon && ( +
+
{item?.icon}
+
+ )} +
+
+

+ {item?.name} +

+ {item?.status && ( + +
+ {item?.status?.icon && ( + {item?.status?.icon} + )} + {item?.status?.label} +
+
+ )} +
+
+
+ {onFavorite && ( + onFavorite?.(item)} + /> + )} +
+ +
+ {/* Tags */} + + + {/* Description */} +

+ + {item?.description} + +

+ + {/* Statistics */} +
+ {item?.statistics?.map((stat, idx) => ( +
+
+ {stat?.label}: +
+
+ {stat?.value} +
+
+ ))} +
+
+
+ + {/* Actions */} +
+
+
+ {" "} + {formatDateTime(item?.updatedAt)} +
+
+ {operations && ( + { + const operation = ops(item).find((op) => op.key === key); + if (operation?.onClick) { + operation.onClick(item); + } + }} + /> + )} +
+
+
+ ))} +
+
+ +
+
+ ); +} + +export default CardView; diff --git a/frontend/src/components/DetailHeader.tsx b/frontend/src/components/DetailHeader.tsx index a95dc10f6..27b59659d 100644 --- a/frontend/src/components/DetailHeader.tsx +++ b/frontend/src/components/DetailHeader.tsx @@ -1,145 +1,145 @@ -import React from "react"; -import { Database } from "lucide-react"; -import { Card, Button, Tag, Tooltip, Popconfirm } from "antd"; -import type { ItemType } from "antd/es/menu/interface"; -import AddTagPopover from "./AddTagPopover"; -import ActionDropdown from "./ActionDropdown"; - -interface StatisticItem { - icon: React.ReactNode; - label: string; - value: string | number; -} - -interface OperationItem { - key: string; - label: string; - icon?: React.ReactNode; - isDropdown?: boolean; - items?: ItemType[]; - onMenuClick?: (key: string) => void; - onClick?: () => void; - danger?: boolean; -} - -interface TagConfig { - showAdd: boolean; - tags: { id: number; name: string; color: string }[]; - onFetchTags?: () => Promise<{ - data: { id: number; name: string; color: string }[]; - }>; - onAddTag?: (tag: { id: number; name: string; color: string }) => void; - onCreateAndTag?: (tagName: string) => void; -} -interface DetailHeaderProps { - data: T; - statistics: StatisticItem[]; - operations: OperationItem[]; - tagConfig?: TagConfig; -} - -function DetailHeader({ - data = {} as T, - statistics, - operations, - tagConfig, -}: DetailHeaderProps): React.ReactNode { - return ( - -
-
-
- {
{data?.icon}
|| ( - - )} -
-
-
-

{data?.name}

- {data?.status && ( - -
- {data.status?.icon && {data.status?.icon}} - {data.status?.label} -
-
- )} -
- {data?.tags && ( -
- {data?.tags?.map((tag) => ( - - {tag.name} - - ))} - {tagConfig?.showAdd && ( - - )} -
- )} -

{data?.description}

-
- {statistics.map((stat) => ( -
- {stat.icon} - {stat.value} -
- ))} -
-
-
-
- {operations.map((op) => { - if (op.isDropdown) { - return ( - - ); - } - if (op.confirm) { - return ( - - { - if (op.onClick) { - op.onClick() - } else { - op?.confirm?.onConfirm?.(); - } - }} - okType={op.danger ? "danger" : "primary"} - overlayStyle={{ zIndex: 9999 }} - > -
-
-
- ); -} - -export default DetailHeader; +import React from "react"; +import { Database } from "lucide-react"; +import { Card, Button, Tag, Tooltip, Popconfirm } from "antd"; +import type { ItemType } from "antd/es/menu/interface"; +import AddTagPopover from "./AddTagPopover"; +import ActionDropdown from "./ActionDropdown"; + +interface StatisticItem { + icon: React.ReactNode; + label: string; + value: string | number; +} + +interface OperationItem { + key: string; + label: string; + icon?: React.ReactNode; + isDropdown?: boolean; + items?: ItemType[]; + onMenuClick?: (key: string) => void; + onClick?: () => void; + danger?: boolean; +} + +interface TagConfig { + showAdd: boolean; + tags: { id: number; name: string; color: string }[]; + onFetchTags?: () => Promise<{ + data: { id: number; name: string; color: string }[]; + }>; + onAddTag?: (tag: { id: number; name: string; color: string }) => void; + onCreateAndTag?: (tagName: string) => void; +} +interface DetailHeaderProps { + data: T; + statistics: StatisticItem[]; + operations: OperationItem[]; + tagConfig?: TagConfig; +} + +function DetailHeader({ + data = {} as T, + statistics, + operations, + tagConfig, +}: DetailHeaderProps): React.ReactNode { + return ( + +
+
+
+ {
{data?.icon}
|| ( + + )} +
+
+
+

{data?.name}

+ {data?.status && ( + +
+ {data.status?.icon && {data.status?.icon}} + {data.status?.label} +
+
+ )} +
+ {data?.tags && ( +
+ {data?.tags?.map((tag) => ( + + {tag.name} + + ))} + {tagConfig?.showAdd && ( + + )} +
+ )} +

{data?.description}

+
+ {statistics.map((stat) => ( +
+ {stat.icon} + {stat.value} +
+ ))} +
+
+
+
+ {operations.map((op) => { + if (op.isDropdown) { + return ( + + ); + } + if (op.confirm) { + return ( + + { + if (op.onClick) { + op.onClick() + } else { + op?.confirm?.onConfirm?.(); + } + }} + okType={op.danger ? "danger" : "primary"} + overlayStyle={{ zIndex: 9999 }} + > +
+
+
+ ); +} + +export default DetailHeader; diff --git a/frontend/src/components/DevelopmentInProgress.tsx b/frontend/src/components/DevelopmentInProgress.tsx index 81303b7f7..a0a01d8b5 100644 --- a/frontend/src/components/DevelopmentInProgress.tsx +++ b/frontend/src/components/DevelopmentInProgress.tsx @@ -1,28 +1,28 @@ -import { Button } from "antd"; -const DevelopmentInProgress = ({ showHome = true, showTime = "" }) => { - return ( -
-
🚧
-

功能开发中

- {showTime && ( -

- 为了给您带来更好的体验,我们计划{showTime} - 开放此功能 -

- )} - {showHome && ( - - )} -
- ); -}; - -export default DevelopmentInProgress; +import { Button } from "antd"; +const DevelopmentInProgress = ({ showHome = true, showTime = "" }) => { + return ( +
+
🚧
+

功能开发中

+ {showTime && ( +

+ 为了给您带来更好的体验,我们计划{showTime} + 开放此功能 +

+ )} + {showHome && ( + + )} +
+ ); +}; + +export default DevelopmentInProgress; diff --git a/frontend/src/components/ErrorBoundary.tsx b/frontend/src/components/ErrorBoundary.tsx index 7538c195f..6c7e2f9f8 100644 --- a/frontend/src/components/ErrorBoundary.tsx +++ b/frontend/src/components/ErrorBoundary.tsx @@ -1,191 +1,191 @@ -import React, { Component } from "react"; -import { Button, Modal } from "antd"; - -interface ErrorContextType { - hasError: boolean; - error: Error | null; - errorInfo: { componentStack: string } | null; -} - -const ErrorContext = React.createContext({ - hasError: false, - error: null, - errorInfo: null, -}); - -interface ErrorBoundaryState { - hasError: boolean; - error: Error | null; - errorInfo: { componentStack: string } | null; - errorTimestamp: string | null; -} - -interface ErrorBoundaryProps { - children?: React.ReactNode; - onReset?: () => void; - showDetails?: boolean; -} - -export default class ErrorBoundary extends Component< - ErrorBoundaryProps, - ErrorBoundaryState -> { - constructor(props: ErrorBoundaryProps) { - super(props); - this.state = { - hasError: false, - error: null, - errorInfo: null, - errorTimestamp: null, - }; - } - - static getDerivedStateFromError(error: any) { - // 更新 state 使下一次渲染能够显示降级 UI - return { - hasError: true, - error: error, - errorTimestamp: new Date().toISOString(), - }; - } - - componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { - // 错误统计 - this.setState({ - error, - errorInfo, - hasError: true, - }); - - // 在实际应用中,这里可以集成错误报告服务 - this.logErrorToService(error, errorInfo); - - // 开发环境下在控制台显示详细错误 - if (process.env.NODE_ENV === "development") { - console.error("ErrorBoundary 捕获到错误:", error); - console.error("错误详情:", errorInfo); - } - } - - logErrorToService = (error: Error, errorInfo: React.ErrorInfo) => { - // 这里可以集成 Sentry、LogRocket 等错误监控服务 - const errorData = { - error: error.toString(), - errorInfo: errorInfo.componentStack, - timestamp: this.state.errorTimestamp, - url: window.location.href, - userAgent: navigator.userAgent, - }; - - // 模拟发送错误日志 - console.log("发送错误日志到监控服务:", errorData); - - // 实际使用时取消注释并配置您的错误监控服务 - /* - if (window.Sentry) { - window.Sentry.captureException(error, { extra: errorInfo }); - } - */ - }; - - handleReset = () => { - this.setState({ - hasError: false, - error: null, - errorInfo: null, - errorTimestamp: null, - }); - - // 可选:重新加载页面或执行其他恢复操作 - if (this.props.onReset) { - this.props.onReset(); - } - }; - - handleReload = () => { - window.location.reload(); - }; - - handleGoHome = () => { - window.location.href = "/"; - }; - - renderErrorDetails = () => { - const { error, errorInfo } = this.state; - - if (!this.props.showDetails) return null; - - return ( -
-
- 错误信息: -
-            {error?.toString()}
-          
-
- {errorInfo && ( -
- 组件堆栈: -
-              {errorInfo.componentStack}
-            
-
- )} -
- ); - }; - - render() { - if (this.state.hasError) { - return ( - -
-
⚠️
-

出了点问题

-

应用程序遇到了意外错误。

- -
- - -
- - {this.renderErrorDetails()} - -
-

- 如果问题持续存在,请联系技术支持 -

- - 错误 ID: {this.state.errorTimestamp} - -
-
-
- ); - } - - return ( - - {this.props.children} - - ); - } -} - -export function withErrorBoundary( - Component: React.ComponentType -): React.ComponentType { - return (props) => ( - - - - ); -} +import React, { Component } from "react"; +import { Button, Modal } from "antd"; + +interface ErrorContextType { + hasError: boolean; + error: Error | null; + errorInfo: { componentStack: string } | null; +} + +const ErrorContext = React.createContext({ + hasError: false, + error: null, + errorInfo: null, +}); + +interface ErrorBoundaryState { + hasError: boolean; + error: Error | null; + errorInfo: { componentStack: string } | null; + errorTimestamp: string | null; +} + +interface ErrorBoundaryProps { + children?: React.ReactNode; + onReset?: () => void; + showDetails?: boolean; +} + +export default class ErrorBoundary extends Component< + ErrorBoundaryProps, + ErrorBoundaryState +> { + constructor(props: ErrorBoundaryProps) { + super(props); + this.state = { + hasError: false, + error: null, + errorInfo: null, + errorTimestamp: null, + }; + } + + static getDerivedStateFromError(error: any) { + // 更新 state 使下一次渲染能够显示降级 UI + return { + hasError: true, + error: error, + errorTimestamp: new Date().toISOString(), + }; + } + + componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { + // 错误统计 + this.setState({ + error, + errorInfo, + hasError: true, + }); + + // 在实际应用中,这里可以集成错误报告服务 + this.logErrorToService(error, errorInfo); + + // 开发环境下在控制台显示详细错误 + if (process.env.NODE_ENV === "development") { + console.error("ErrorBoundary 捕获到错误:", error); + console.error("错误详情:", errorInfo); + } + } + + logErrorToService = (error: Error, errorInfo: React.ErrorInfo) => { + // 这里可以集成 Sentry、LogRocket 等错误监控服务 + const errorData = { + error: error.toString(), + errorInfo: errorInfo.componentStack, + timestamp: this.state.errorTimestamp, + url: window.location.href, + userAgent: navigator.userAgent, + }; + + // 模拟发送错误日志 + console.log("发送错误日志到监控服务:", errorData); + + // 实际使用时取消注释并配置您的错误监控服务 + /* + if (window.Sentry) { + window.Sentry.captureException(error, { extra: errorInfo }); + } + */ + }; + + handleReset = () => { + this.setState({ + hasError: false, + error: null, + errorInfo: null, + errorTimestamp: null, + }); + + // 可选:重新加载页面或执行其他恢复操作 + if (this.props.onReset) { + this.props.onReset(); + } + }; + + handleReload = () => { + window.location.reload(); + }; + + handleGoHome = () => { + window.location.href = "/"; + }; + + renderErrorDetails = () => { + const { error, errorInfo } = this.state; + + if (!this.props.showDetails) return null; + + return ( +
+
+ 错误信息: +
+            {error?.toString()}
+          
+
+ {errorInfo && ( +
+ 组件堆栈: +
+              {errorInfo.componentStack}
+            
+
+ )} +
+ ); + }; + + render() { + if (this.state.hasError) { + return ( + +
+
⚠️
+

出了点问题

+

应用程序遇到了意外错误。

+ +
+ + +
+ + {this.renderErrorDetails()} + +
+

+ 如果问题持续存在,请联系技术支持 +

+ + 错误 ID: {this.state.errorTimestamp} + +
+
+
+ ); + } + + return ( + + {this.props.children} + + ); + } +} + +export function withErrorBoundary( + Component: React.ComponentType +): React.ComponentType { + return (props) => ( + + + + ); +} diff --git a/frontend/src/components/RadioCard.tsx b/frontend/src/components/RadioCard.tsx index f4a441446..ad9f8d806 100644 --- a/frontend/src/components/RadioCard.tsx +++ b/frontend/src/components/RadioCard.tsx @@ -1,70 +1,70 @@ -import React from "react"; -import { Card } from "antd"; - -interface RadioCardOption { - value: string; - label: string; - description?: string; - icon?: SVGAElement | React.FC>; - color?: string; -} - -interface RadioCardProps { - options: RadioCardOption[]; - value: string; - onChange: (value: string) => void; - className?: string; -} - -const RadioCard: React.FC = ({ - options, - value, - onChange, - className, -}) => { - return ( -
- {options.map((option) => ( -
onChange(option.value)} - > - -

- {option.label} -

- {option.description && ( -
- {option.description} -
- )} -
- ))} -
- ); -}; - -export default RadioCard; +import React from "react"; +import { Card } from "antd"; + +interface RadioCardOption { + value: string; + label: string; + description?: string; + icon?: SVGAElement | React.FC>; + color?: string; +} + +interface RadioCardProps { + options: RadioCardOption[]; + value: string; + onChange: (value: string) => void; + className?: string; +} + +const RadioCard: React.FC = ({ + options, + value, + onChange, + className, +}) => { + return ( +
+ {options.map((option) => ( +
onChange(option.value)} + > + +

+ {option.label} +

+ {option.description && ( +
+ {option.description} +
+ )} +
+ ))} +
+ ); +}; + +export default RadioCard; diff --git a/frontend/src/components/SearchControls.tsx b/frontend/src/components/SearchControls.tsx index ff8e92be2..3e2c4d7f6 100644 --- a/frontend/src/components/SearchControls.tsx +++ b/frontend/src/components/SearchControls.tsx @@ -1,239 +1,239 @@ -import { Input, Button, Select, Tag, Segmented, DatePicker } from "antd"; -import { - BarsOutlined, - AppstoreOutlined, - SearchOutlined, - ReloadOutlined, -} from "@ant-design/icons"; -import { useEffect, useState } from "react"; - -interface FilterOption { - key: string; - label: string; - mode?: "tags" | "multiple"; - options: { label: string; value: string }[]; -} - -interface SearchControlsProps { - searchTerm: string; - onSearchChange: (value: string) => void; - searchPlaceholder?: string; - - // Filter props - filters?: FilterOption[]; - selectedFilters?: Record; - onFiltersChange?: (filters: Record) => void; - onClearFilters?: () => void; - - // Date range props - dateRange?: [Date | null, Date | null] | null; - onDateChange?: (dates: [Date | null, Date | null] | null) => void; - - // Reload props - onReload?: () => void; - - // View props - viewMode?: "card" | "list"; - onViewModeChange?: (mode: "card" | "list") => void; - - // Control visibility - showFilters?: boolean; - showSort?: boolean; - showViewToggle?: boolean; - showReload?: boolean; - showDatePicker?: boolean; - - // Styling - className?: string; -} - -export function SearchControls({ - viewMode, - className, - searchTerm, - showFilters = true, - showViewToggle = true, - searchPlaceholder = "搜索...", - filters = [], - dateRange, - showDatePicker = false, - showReload = true, - onReload, - onDateChange, - onSearchChange, - onFiltersChange, - onViewModeChange, - onClearFilters, -}: SearchControlsProps) { - const [selectedFilters, setSelectedFilters] = useState<{ - [key: string]: string[]; - }>({}); - - const filtersMap: Record = filters.reduce( - (prev, cur) => ({ ...prev, [cur.key]: cur }), - {} - ); - - // select change - const handleFilterChange = (filterKey: string, value: string) => { - const filteredValues = { - ...selectedFilters, - [filterKey]: !value ? [] : [value], - }; - setSelectedFilters(filteredValues); - }; - - // 清除已选筛选 - const handleClearFilter = (filterKey: string, value: string | string[]) => { - const isMultiple = filtersMap[filterKey]?.mode === "multiple"; - if (!isMultiple) { - setSelectedFilters({ - ...selectedFilters, - [filterKey]: [], - }); - } else { - const currentValues = selectedFilters[filterKey]?.[0] || []; - const newValues = currentValues.filter((v) => v !== value); - setSelectedFilters({ - ...selectedFilters, - [filterKey]: [newValues], - }); - } - }; - - const handleClearAllFilters = () => { - setSelectedFilters({}); - onClearFilters?.(); - }; - - const hasActiveFilters = Object.values(selectedFilters).some( - (values) => values?.[0]?.length > 0 - ); - - useEffect(() => { - if (Object.keys(selectedFilters).length === 0) return; - onFiltersChange?.(selectedFilters); - }, [selectedFilters]); - - return ( -
-
- {/* Left side - Search and Filters */} -
- {/* Search */} -
- onSearchChange(e.target.value)} - prefix={} - /> -
- - {/* Filters */} - {showFilters && filters.length > 0 && ( -
- {filters.map((filter: FilterOption) => ( - - ))} -
- )} -
- - {showDatePicker && ( - - )} - - {/* Right side */} -
- {showViewToggle && onViewModeChange && ( - }, - { value: "card", icon: }, - ]} - value={viewMode} - onChange={(value) => onViewModeChange(value as "list" | "card")} - /> - )} - - {showReload && ( - - )} -
-
- - {/* Active Filters Display */} - {hasActiveFilters && ( -
-
-
- - 已选筛选: - - {Object.entries(selectedFilters).map(([filterKey, values]) => - values.map((value) => { - const filter = filtersMap[filterKey]; - - const getLabeledValue = (item: string) => { - const option = filter?.options.find( - (o) => o.value === item - ); - return ( - handleClearFilter(filterKey, item)} - color="blue" - > - {filter?.label}: {option?.label || item} - - ); - }; - return Array.isArray(value) - ? value.map((item) => getLabeledValue(item)) - : getLabeledValue(value); - }) - )} -
- - {/* Clear all filters button on the right */} - -
-
- )} -
- ); -} +import { Input, Button, Select, Tag, Segmented, DatePicker } from "antd"; +import { + BarsOutlined, + AppstoreOutlined, + SearchOutlined, + ReloadOutlined, +} from "@ant-design/icons"; +import { useEffect, useState } from "react"; + +interface FilterOption { + key: string; + label: string; + mode?: "tags" | "multiple"; + options: { label: string; value: string }[]; +} + +interface SearchControlsProps { + searchTerm: string; + onSearchChange: (value: string) => void; + searchPlaceholder?: string; + + // Filter props + filters?: FilterOption[]; + selectedFilters?: Record; + onFiltersChange?: (filters: Record) => void; + onClearFilters?: () => void; + + // Date range props + dateRange?: [Date | null, Date | null] | null; + onDateChange?: (dates: [Date | null, Date | null] | null) => void; + + // Reload props + onReload?: () => void; + + // View props + viewMode?: "card" | "list"; + onViewModeChange?: (mode: "card" | "list") => void; + + // Control visibility + showFilters?: boolean; + showSort?: boolean; + showViewToggle?: boolean; + showReload?: boolean; + showDatePicker?: boolean; + + // Styling + className?: string; +} + +export function SearchControls({ + viewMode, + className, + searchTerm, + showFilters = true, + showViewToggle = true, + searchPlaceholder = "搜索...", + filters = [], + dateRange, + showDatePicker = false, + showReload = true, + onReload, + onDateChange, + onSearchChange, + onFiltersChange, + onViewModeChange, + onClearFilters, +}: SearchControlsProps) { + const [selectedFilters, setSelectedFilters] = useState<{ + [key: string]: string[]; + }>({}); + + const filtersMap: Record = filters.reduce( + (prev, cur) => ({ ...prev, [cur.key]: cur }), + {} + ); + + // select change + const handleFilterChange = (filterKey: string, value: string) => { + const filteredValues = { + ...selectedFilters, + [filterKey]: !value ? [] : [value], + }; + setSelectedFilters(filteredValues); + }; + + // 清除已选筛选 + const handleClearFilter = (filterKey: string, value: string | string[]) => { + const isMultiple = filtersMap[filterKey]?.mode === "multiple"; + if (!isMultiple) { + setSelectedFilters({ + ...selectedFilters, + [filterKey]: [], + }); + } else { + const currentValues = selectedFilters[filterKey]?.[0] || []; + const newValues = currentValues.filter((v) => v !== value); + setSelectedFilters({ + ...selectedFilters, + [filterKey]: [newValues], + }); + } + }; + + const handleClearAllFilters = () => { + setSelectedFilters({}); + onClearFilters?.(); + }; + + const hasActiveFilters = Object.values(selectedFilters).some( + (values) => values?.[0]?.length > 0 + ); + + useEffect(() => { + if (Object.keys(selectedFilters).length === 0) return; + onFiltersChange?.(selectedFilters); + }, [selectedFilters]); + + return ( +
+
+ {/* Left side - Search and Filters */} +
+ {/* Search */} +
+ onSearchChange(e.target.value)} + prefix={} + /> +
+ + {/* Filters */} + {showFilters && filters.length > 0 && ( +
+ {filters.map((filter: FilterOption) => ( + + ))} +
+ )} +
+ + {showDatePicker && ( + + )} + + {/* Right side */} +
+ {showViewToggle && onViewModeChange && ( + }, + { value: "card", icon: }, + ]} + value={viewMode} + onChange={(value) => onViewModeChange(value as "list" | "card")} + /> + )} + + {showReload && ( + + )} +
+
+ + {/* Active Filters Display */} + {hasActiveFilters && ( +
+
+
+ + 已选筛选: + + {Object.entries(selectedFilters).map(([filterKey, values]) => + values.map((value) => { + const filter = filtersMap[filterKey]; + + const getLabeledValue = (item: string) => { + const option = filter?.options.find( + (o) => o.value === item + ); + return ( + handleClearFilter(filterKey, item)} + color="blue" + > + {filter?.label}: {option?.label || item} + + ); + }; + return Array.isArray(value) + ? value.map((item) => getLabeledValue(item)) + : getLabeledValue(value); + }) + )} +
+ + {/* Clear all filters button on the right */} + +
+
+ )} +
+ ); +} diff --git a/frontend/src/components/TagList.tsx b/frontend/src/components/TagList.tsx index 9688c776f..75fa14076 100644 --- a/frontend/src/components/TagList.tsx +++ b/frontend/src/components/TagList.tsx @@ -1,149 +1,149 @@ -import React, { useEffect, useRef, useState } from "react"; -import { PlusOutlined } from "@ant-design/icons"; -import type { InputRef } from "antd"; -import { Flex, Input, Tag, theme, Tooltip } from "antd"; - -const tagInputStyle: React.CSSProperties = { - width: 64, - height: 22, - marginInlineEnd: 8, - verticalAlign: "top", -}; - -interface TagListProps { - tags: string[]; - setTags: (tags: string[]) => void; - onDelete?: (tag: string) => void; - onAdd?: (tag: string) => void; - onEdit?: (oldTag: string, newTag: string) => void; -} - -const TagList: React.FC = ({ - tags, - setTags, - onDelete, - onAdd, - onEdit, -}) => { - const { token } = theme.useToken(); - const [inputVisible, setInputVisible] = useState(false); - const [inputValue, setInputValue] = useState(""); - const [editInputIndex, setEditInputIndex] = useState(-1); - const [editInputValue, setEditInputValue] = useState(""); - const inputRef = useRef(null); - const editInputRef = useRef(null); - - useEffect(() => { - if (inputVisible) { - inputRef.current?.focus(); - } - }, [inputVisible]); - - useEffect(() => { - editInputRef.current?.focus(); - }, [editInputValue]); - - const handleClose = (removedTag: string) => { - const newTags = tags.filter((tag) => tag !== removedTag); - setTags(newTags); - onDelete?.(removedTag); - }; - - const showInput = () => { - setInputVisible(true); - }; - - const handleInputChange = (e: React.ChangeEvent) => { - setInputValue(e.target.value); - }; - - const handleInputConfirm = () => { - if (inputValue && !tags.includes(inputValue)) { - setTags([...tags, inputValue]); - onAdd?.(inputValue); - } - setInputVisible(false); - setInputValue(""); - }; - - const handleEditInputChange = (e: React.ChangeEvent) => { - setEditInputValue(e.target.value); - }; - - const handleEditInputConfirm = () => { - const newTags = [...tags]; - newTags[editInputIndex] = editInputValue; - setTags(newTags); - onEdit?.(tags[editInputIndex], editInputValue); - setEditInputIndex(-1); - setEditInputValue(""); - }; - - const tagPlusStyle: React.CSSProperties = { - height: 22, - background: token.colorBgContainer, - borderStyle: "dashed", - }; - - return ( - - {tags.map((tag, index) => { - if (editInputIndex === index) { - return ( - - ); - } - const isLongTag = tag.length > 20; - const tagElem = ( - handleClose(tag)} closable> - { - if (index !== 0) { - setEditInputIndex(index); - setEditInputValue(tag); - e.preventDefault(); - } - }} - > - {isLongTag ? `${tag.slice(0, 20)}...` : tag} - - - ); - return isLongTag ? ( - - {tagElem} - - ) : ( - tagElem - ); - })} - {inputVisible ? ( - - ) : ( - } onClick={showInput}> - 新增标签 - - )} - - ); -}; - -export default TagList; +import React, { useEffect, useRef, useState } from "react"; +import { PlusOutlined } from "@ant-design/icons"; +import type { InputRef } from "antd"; +import { Flex, Input, Tag, theme, Tooltip } from "antd"; + +const tagInputStyle: React.CSSProperties = { + width: 64, + height: 22, + marginInlineEnd: 8, + verticalAlign: "top", +}; + +interface TagListProps { + tags: string[]; + setTags: (tags: string[]) => void; + onDelete?: (tag: string) => void; + onAdd?: (tag: string) => void; + onEdit?: (oldTag: string, newTag: string) => void; +} + +const TagList: React.FC = ({ + tags, + setTags, + onDelete, + onAdd, + onEdit, +}) => { + const { token } = theme.useToken(); + const [inputVisible, setInputVisible] = useState(false); + const [inputValue, setInputValue] = useState(""); + const [editInputIndex, setEditInputIndex] = useState(-1); + const [editInputValue, setEditInputValue] = useState(""); + const inputRef = useRef(null); + const editInputRef = useRef(null); + + useEffect(() => { + if (inputVisible) { + inputRef.current?.focus(); + } + }, [inputVisible]); + + useEffect(() => { + editInputRef.current?.focus(); + }, [editInputValue]); + + const handleClose = (removedTag: string) => { + const newTags = tags.filter((tag) => tag !== removedTag); + setTags(newTags); + onDelete?.(removedTag); + }; + + const showInput = () => { + setInputVisible(true); + }; + + const handleInputChange = (e: React.ChangeEvent) => { + setInputValue(e.target.value); + }; + + const handleInputConfirm = () => { + if (inputValue && !tags.includes(inputValue)) { + setTags([...tags, inputValue]); + onAdd?.(inputValue); + } + setInputVisible(false); + setInputValue(""); + }; + + const handleEditInputChange = (e: React.ChangeEvent) => { + setEditInputValue(e.target.value); + }; + + const handleEditInputConfirm = () => { + const newTags = [...tags]; + newTags[editInputIndex] = editInputValue; + setTags(newTags); + onEdit?.(tags[editInputIndex], editInputValue); + setEditInputIndex(-1); + setEditInputValue(""); + }; + + const tagPlusStyle: React.CSSProperties = { + height: 22, + background: token.colorBgContainer, + borderStyle: "dashed", + }; + + return ( + + {tags.map((tag, index) => { + if (editInputIndex === index) { + return ( + + ); + } + const isLongTag = tag.length > 20; + const tagElem = ( + handleClose(tag)} closable> + { + if (index !== 0) { + setEditInputIndex(index); + setEditInputValue(tag); + e.preventDefault(); + } + }} + > + {isLongTag ? `${tag.slice(0, 20)}...` : tag} + + + ); + return isLongTag ? ( + + {tagElem} + + ) : ( + tagElem + ); + })} + {inputVisible ? ( + + ) : ( + } onClick={showInput}> + 新增标签 + + )} + + ); +}; + +export default TagList; diff --git a/frontend/src/components/TopLoadingBar.tsx b/frontend/src/components/TopLoadingBar.tsx index a921e210d..ec95fd16f 100644 --- a/frontend/src/components/TopLoadingBar.tsx +++ b/frontend/src/components/TopLoadingBar.tsx @@ -1,69 +1,69 @@ -import { useEffect, useRef, useState } from "react"; - -const TopLoadingBar = () => { - const [isVisible, setIsVisible] = useState(false); - const [progress, setProgress] = useState(0); - const intervalRef = useRef(null); - - useEffect(() => { - // 监听全局事件 - const handleShow = () => { - setIsVisible(true); - setProgress(0); - - // 清除可能存在的旧interval - if (intervalRef.current) { - clearInterval(intervalRef.current); - } - - // 模拟进度 - let currentProgress = 0; - intervalRef.current = setInterval(() => { - currentProgress += Math.random() * 10; - if (currentProgress >= 90) { - clearInterval(intervalRef.current); - } - setProgress(currentProgress); - }, 200); - }; - - const handleHide = () => { - // 清除进度interval - if (intervalRef.current) { - clearInterval(intervalRef.current); - intervalRef.current = null; - } - setProgress(100); - setTimeout(() => { - setIsVisible(false); - setProgress(0); - }, 300); - }; - - // 添加全局事件监听器 - window.addEventListener("loading:show", handleShow); - window.addEventListener("loading:hide", handleHide); - - return () => { - // 组件卸载时清理 - if (intervalRef.current) { - clearInterval(intervalRef.current); - } - window.removeEventListener("loading:show", handleShow); - window.removeEventListener("loading:hide", handleHide); - }; - }, []); - - if (!isVisible) return null; - - return ( -
-
-
- ); -}; - -export default TopLoadingBar; +import { useEffect, useRef, useState } from "react"; + +const TopLoadingBar = () => { + const [isVisible, setIsVisible] = useState(false); + const [progress, setProgress] = useState(0); + const intervalRef = useRef(null); + + useEffect(() => { + // 监听全局事件 + const handleShow = () => { + setIsVisible(true); + setProgress(0); + + // 清除可能存在的旧interval + if (intervalRef.current) { + clearInterval(intervalRef.current); + } + + // 模拟进度 + let currentProgress = 0; + intervalRef.current = setInterval(() => { + currentProgress += Math.random() * 10; + if (currentProgress >= 90) { + clearInterval(intervalRef.current); + } + setProgress(currentProgress); + }, 200); + }; + + const handleHide = () => { + // 清除进度interval + if (intervalRef.current) { + clearInterval(intervalRef.current); + intervalRef.current = null; + } + setProgress(100); + setTimeout(() => { + setIsVisible(false); + setProgress(0); + }, 300); + }; + + // 添加全局事件监听器 + window.addEventListener("loading:show", handleShow); + window.addEventListener("loading:hide", handleHide); + + return () => { + // 组件卸载时清理 + if (intervalRef.current) { + clearInterval(intervalRef.current); + } + window.removeEventListener("loading:show", handleShow); + window.removeEventListener("loading:hide", handleHide); + }; + }, []); + + if (!isVisible) return null; + + return ( +
+
+
+ ); +}; + +export default TopLoadingBar; diff --git a/frontend/src/components/business/DatasetFileTransfer.tsx b/frontend/src/components/business/DatasetFileTransfer.tsx index 0d222fe96..92284cb1f 100644 --- a/frontend/src/components/business/DatasetFileTransfer.tsx +++ b/frontend/src/components/business/DatasetFileTransfer.tsx @@ -1,331 +1,331 @@ -import React, { useCallback, useEffect } from "react"; -import { Button, Input, Table } from "antd"; -import { RightOutlined } from "@ant-design/icons"; -import { mapDataset } from "@/pages/DataManagement/dataset.const"; -import { - Dataset, - DatasetFile, - DatasetType, -} from "@/pages/DataManagement/dataset.model"; -import { - queryDatasetFilesUsingGet, - queryDatasetsUsingGet, -} from "@/pages/DataManagement/dataset.api"; -import { formatBytes } from "@/utils/unit"; -import { useDebouncedEffect } from "@/hooks/useDebouncedEffect"; - -interface DatasetFileTransferProps - extends React.HTMLAttributes { - open: boolean; - selectedFilesMap: { [key: string]: DatasetFile }; - onSelectedFilesChange: (filesMap: { [key: string]: DatasetFile }) => void; - onDatasetSelect?: (dataset: Dataset | null) => void; -} - -const fileCols = [ - { - title: "所属数据集", - dataIndex: "datasetName", - key: "datasetName", - ellipsis: true, - }, - { - title: "文件名", - dataIndex: "fileName", - key: "fileName", - ellipsis: true, - }, - { - title: "大小", - dataIndex: "fileSize", - key: "fileSize", - ellipsis: true, - render: formatBytes, - }, -]; - -// Customize Table Transfer -const DatasetFileTransfer: React.FC = ({ - open, - selectedFilesMap, - onSelectedFilesChange, - onDatasetSelect, - ...props -}) => { - const [datasets, setDatasets] = React.useState([]); - const [datasetSearch, setDatasetSearch] = React.useState(""); - const [datasetPagination, setDatasetPagination] = React.useState<{ - current: number; - pageSize: number; - total: number; - }>({ current: 1, pageSize: 10, total: 0 }); - - const [files, setFiles] = React.useState([]); - const [filesSearch, setFilesSearch] = React.useState(""); - const [filesPagination, setFilesPagination] = React.useState<{ - current: number; - pageSize: number; - total: number; - }>({ current: 1, pageSize: 10, total: 0 }); - - const [showFiles, setShowFiles] = React.useState(false); - const [selectedDataset, setSelectedDataset] = React.useState( - null - ); - const [datasetSelections, setDatasetSelections] = React.useState( - [] - ); - - const fetchDatasets = async () => { - const { data } = await queryDatasetsUsingGet({ - // Ant Design Table pagination.current is 1-based; ensure backend also receives 1-based value - page: datasetPagination.current, - size: datasetPagination.pageSize, - keyword: datasetSearch, - type: DatasetType.TEXT, - }); - setDatasets(data.content.map(mapDataset) || []); - setDatasetPagination((prev) => ({ - ...prev, - total: data.totalElements, - })); - }; - - useDebouncedEffect( - () => { - fetchDatasets(); - }, - [datasetSearch, datasetPagination.pageSize, datasetPagination.current], - 300 - ); - - const fetchFiles = useCallback( - async ( - options?: Partial<{ page: number; pageSize: number; keyword: string }> - ) => { - if (!selectedDataset) return; - const page = options?.page ?? filesPagination.current; - const pageSize = options?.pageSize ?? filesPagination.pageSize; - const keyword = options?.keyword ?? filesSearch; - - const { data } = await queryDatasetFilesUsingGet(selectedDataset.id, { - page, - size: pageSize, - keyword, - }); - setFiles( - (data.content || []).map((item: DatasetFile) => ({ - ...item, - key: item.id, - datasetName: selectedDataset.name, - })) - ); - setFilesPagination((prev) => ({ - ...prev, - current: page, - pageSize, - total: data.totalElements, - })); - }, - [selectedDataset, filesPagination.current, filesPagination.pageSize, filesSearch] - ); - - useEffect(() => { - // 当数据集变化时,重置文件分页并拉取第一页文件,避免额外的循环请求 - if (selectedDataset) { - setFilesPagination({ current: 1, pageSize: 10, total: 0 }); - fetchFiles({ page: 1, pageSize: 10 }).catch(() => {}); - } else { - setFiles([]); - setFilesPagination({ current: 1, pageSize: 10, total: 0 }); - } - // 只在 selectedDataset 变化时触发 - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedDataset]); - - useEffect(() => { - onDatasetSelect?.(selectedDataset); - }, [selectedDataset, onDatasetSelect]); - - const toggleSelectFile = (record: DatasetFile) => { - if (!selectedFilesMap[record.id]) { - onSelectedFilesChange({ - ...selectedFilesMap, - [record.id]: record, - }); - } else { - const newSelectedFiles = { ...selectedFilesMap }; - delete newSelectedFiles[record.id]; - onSelectedFilesChange(newSelectedFiles); - } - }; - - useEffect(() => { - if (!open) { - // 重置状态 - setDatasets([]); - setDatasetSearch(""); - setDatasetPagination({ current: 1, pageSize: 10, total: 0 }); - setFiles([]); - setFilesSearch(""); - setFilesPagination({ current: 1, pageSize: 10, total: 0 }); - setShowFiles(false); - setSelectedDataset(null); - setDatasetSelections([]); - onDatasetSelect?.(null); - } - }, [open, onDatasetSelect]); - - const datasetCols = [ - { - title: "数据集名称", - dataIndex: "name", - key: "name", - ellipsis: true, - }, - { - title: "文件数", - dataIndex: "fileCount", - key: "fileCount", - ellipsis: true, - }, - { - title: "大小", - dataIndex: "totalSize", - key: "totalSize", - ellipsis: true, - render: formatBytes, - }, - ]; - - return ( -
-
-
-
选择数据集
-
- setDatasetSearch(e.target.value)} - /> -
- - selectedDataset?.id === record.id ? "bg-blue-100" : "" - } - onRow={(record: Dataset) => ({ - onClick: () => { - setSelectedDataset(record); - if (!datasetSelections.find((d) => d.id === record.id)) { - setDatasetSelections([...datasetSelections, record]); - } else { - setDatasetSelections( - datasetSelections.filter((d) => d.id !== record.id) - ); - } - }, - })} - dataSource={datasets} - columns={datasetCols} - pagination={{ - ...datasetPagination, - onChange: (page, pageSize) => - setDatasetPagination({ - current: page, - pageSize: pageSize || datasetPagination.pageSize, - total: datasetPagination.total, - }), - }} - /> - - -
-
选择文件
-
- setFilesSearch(e.target.value)} - /> -
-
{ - const nextPageSize = pageSize || filesPagination.pageSize; - setFilesPagination((prev) => ({ - ...prev, - current: page, - pageSize: nextPageSize, - })); - fetchFiles({ page, pageSize: nextPageSize }).catch(() => {}); - }, - }} - onRow={(record: DatasetFile) => ({ - onClick: () => toggleSelectFile(record), - })} - rowSelection={{ - type: "checkbox", - selectedRowKeys: Object.keys(selectedFilesMap), - - // 单选 - onSelect: (record: DatasetFile) => { - toggleSelectFile(record); - }, - - // 全选 - onSelectAll: (selected, selectedRows: DatasetFile[]) => { - if (selected) { - // ✔ 全选 -> 将 files 列表全部加入 selectedFilesMap - const newMap: Record = { ...selectedFilesMap }; - selectedRows.forEach((f) => { - newMap[f.id] = f; - }); - onSelectedFilesChange(newMap); - } else { - // ✘ 取消全选 -> 清空 map - const newMap = { ...selectedFilesMap }; - Object.keys(newMap).forEach((id) => { - if (files.some((f) => String(f.id) === id)) { - // 仅移除当前页对应文件 - delete newMap[id]; - } - }); - onSelectedFilesChange(newMap); - } - }, - - getCheckboxProps: (record: DatasetFile) => ({ - name: record.fileName, - }), - }} - /> - - - -
- - - ); -}; - -export default DatasetFileTransfer; +import React, { useCallback, useEffect } from "react"; +import { Button, Input, Table } from "antd"; +import { RightOutlined } from "@ant-design/icons"; +import { mapDataset } from "@/pages/DataManagement/dataset.const"; +import { + Dataset, + DatasetFile, + DatasetType, +} from "@/pages/DataManagement/dataset.model"; +import { + queryDatasetFilesUsingGet, + queryDatasetsUsingGet, +} from "@/pages/DataManagement/dataset.api"; +import { formatBytes } from "@/utils/unit"; +import { useDebouncedEffect } from "@/hooks/useDebouncedEffect"; + +interface DatasetFileTransferProps + extends React.HTMLAttributes { + open: boolean; + selectedFilesMap: { [key: string]: DatasetFile }; + onSelectedFilesChange: (filesMap: { [key: string]: DatasetFile }) => void; + onDatasetSelect?: (dataset: Dataset | null) => void; +} + +const fileCols = [ + { + title: "所属数据集", + dataIndex: "datasetName", + key: "datasetName", + ellipsis: true, + }, + { + title: "文件名", + dataIndex: "fileName", + key: "fileName", + ellipsis: true, + }, + { + title: "大小", + dataIndex: "fileSize", + key: "fileSize", + ellipsis: true, + render: formatBytes, + }, +]; + +// Customize Table Transfer +const DatasetFileTransfer: React.FC = ({ + open, + selectedFilesMap, + onSelectedFilesChange, + onDatasetSelect, + ...props +}) => { + const [datasets, setDatasets] = React.useState([]); + const [datasetSearch, setDatasetSearch] = React.useState(""); + const [datasetPagination, setDatasetPagination] = React.useState<{ + current: number; + pageSize: number; + total: number; + }>({ current: 1, pageSize: 10, total: 0 }); + + const [files, setFiles] = React.useState([]); + const [filesSearch, setFilesSearch] = React.useState(""); + const [filesPagination, setFilesPagination] = React.useState<{ + current: number; + pageSize: number; + total: number; + }>({ current: 1, pageSize: 10, total: 0 }); + + const [showFiles, setShowFiles] = React.useState(false); + const [selectedDataset, setSelectedDataset] = React.useState( + null + ); + const [datasetSelections, setDatasetSelections] = React.useState( + [] + ); + + const fetchDatasets = async () => { + const { data } = await queryDatasetsUsingGet({ + // Ant Design Table pagination.current is 1-based; ensure backend also receives 1-based value + page: datasetPagination.current, + size: datasetPagination.pageSize, + keyword: datasetSearch, + type: DatasetType.TEXT, + }); + setDatasets(data.content.map(mapDataset) || []); + setDatasetPagination((prev) => ({ + ...prev, + total: data.totalElements, + })); + }; + + useDebouncedEffect( + () => { + fetchDatasets(); + }, + [datasetSearch, datasetPagination.pageSize, datasetPagination.current], + 300 + ); + + const fetchFiles = useCallback( + async ( + options?: Partial<{ page: number; pageSize: number; keyword: string }> + ) => { + if (!selectedDataset) return; + const page = options?.page ?? filesPagination.current; + const pageSize = options?.pageSize ?? filesPagination.pageSize; + const keyword = options?.keyword ?? filesSearch; + + const { data } = await queryDatasetFilesUsingGet(selectedDataset.id, { + page, + size: pageSize, + keyword, + }); + setFiles( + (data.content || []).map((item: DatasetFile) => ({ + ...item, + key: item.id, + datasetName: selectedDataset.name, + })) + ); + setFilesPagination((prev) => ({ + ...prev, + current: page, + pageSize, + total: data.totalElements, + })); + }, + [selectedDataset, filesPagination.current, filesPagination.pageSize, filesSearch] + ); + + useEffect(() => { + // 当数据集变化时,重置文件分页并拉取第一页文件,避免额外的循环请求 + if (selectedDataset) { + setFilesPagination({ current: 1, pageSize: 10, total: 0 }); + fetchFiles({ page: 1, pageSize: 10 }).catch(() => {}); + } else { + setFiles([]); + setFilesPagination({ current: 1, pageSize: 10, total: 0 }); + } + // 只在 selectedDataset 变化时触发 + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedDataset]); + + useEffect(() => { + onDatasetSelect?.(selectedDataset); + }, [selectedDataset, onDatasetSelect]); + + const toggleSelectFile = (record: DatasetFile) => { + if (!selectedFilesMap[record.id]) { + onSelectedFilesChange({ + ...selectedFilesMap, + [record.id]: record, + }); + } else { + const newSelectedFiles = { ...selectedFilesMap }; + delete newSelectedFiles[record.id]; + onSelectedFilesChange(newSelectedFiles); + } + }; + + useEffect(() => { + if (!open) { + // 重置状态 + setDatasets([]); + setDatasetSearch(""); + setDatasetPagination({ current: 1, pageSize: 10, total: 0 }); + setFiles([]); + setFilesSearch(""); + setFilesPagination({ current: 1, pageSize: 10, total: 0 }); + setShowFiles(false); + setSelectedDataset(null); + setDatasetSelections([]); + onDatasetSelect?.(null); + } + }, [open, onDatasetSelect]); + + const datasetCols = [ + { + title: "数据集名称", + dataIndex: "name", + key: "name", + ellipsis: true, + }, + { + title: "文件数", + dataIndex: "fileCount", + key: "fileCount", + ellipsis: true, + }, + { + title: "大小", + dataIndex: "totalSize", + key: "totalSize", + ellipsis: true, + render: formatBytes, + }, + ]; + + return ( +
+
+
+
选择数据集
+
+ setDatasetSearch(e.target.value)} + /> +
+
+ selectedDataset?.id === record.id ? "bg-blue-100" : "" + } + onRow={(record: Dataset) => ({ + onClick: () => { + setSelectedDataset(record); + if (!datasetSelections.find((d) => d.id === record.id)) { + setDatasetSelections([...datasetSelections, record]); + } else { + setDatasetSelections( + datasetSelections.filter((d) => d.id !== record.id) + ); + } + }, + })} + dataSource={datasets} + columns={datasetCols} + pagination={{ + ...datasetPagination, + onChange: (page, pageSize) => + setDatasetPagination({ + current: page, + pageSize: pageSize || datasetPagination.pageSize, + total: datasetPagination.total, + }), + }} + /> + + +
+
选择文件
+
+ setFilesSearch(e.target.value)} + /> +
+
{ + const nextPageSize = pageSize || filesPagination.pageSize; + setFilesPagination((prev) => ({ + ...prev, + current: page, + pageSize: nextPageSize, + })); + fetchFiles({ page, pageSize: nextPageSize }).catch(() => {}); + }, + }} + onRow={(record: DatasetFile) => ({ + onClick: () => toggleSelectFile(record), + })} + rowSelection={{ + type: "checkbox", + selectedRowKeys: Object.keys(selectedFilesMap), + + // 单选 + onSelect: (record: DatasetFile) => { + toggleSelectFile(record); + }, + + // 全选 + onSelectAll: (selected, selectedRows: DatasetFile[]) => { + if (selected) { + // ✔ 全选 -> 将 files 列表全部加入 selectedFilesMap + const newMap: Record = { ...selectedFilesMap }; + selectedRows.forEach((f) => { + newMap[f.id] = f; + }); + onSelectedFilesChange(newMap); + } else { + // ✘ 取消全选 -> 清空 map + const newMap = { ...selectedFilesMap }; + Object.keys(newMap).forEach((id) => { + if (files.some((f) => String(f.id) === id)) { + // 仅移除当前页对应文件 + delete newMap[id]; + } + }); + onSelectedFilesChange(newMap); + } + }, + + getCheckboxProps: (record: DatasetFile) => ({ + name: record.fileName, + }), + }} + /> + + + +
+ + + ); +}; + +export default DatasetFileTransfer; diff --git a/frontend/src/components/business/TagManagement.tsx b/frontend/src/components/business/TagManagement.tsx index bf3c45786..42913b372 100644 --- a/frontend/src/components/business/TagManagement.tsx +++ b/frontend/src/components/business/TagManagement.tsx @@ -1,251 +1,251 @@ -import React, { useEffect, useState } from "react"; -import { Drawer, Input, Button, App } from "antd"; -import { PlusOutlined } from "@ant-design/icons"; -import { Edit, Save, TagIcon, X, Trash } from "lucide-react"; -import { TagItem } from "@/pages/DataManagement/dataset.model"; - -interface CustomTagProps { - isEditable?: boolean; - tag: { id: number; name: string }; - editingTag?: string | null; - editingTagValue?: string; - setEditingTag?: React.Dispatch>; - setEditingTagValue?: React.Dispatch>; - handleEditTag?: (tag: { id: number; name: string }, value: string) => void; - handleCancelEdit?: (tag: { id: number; name: string }) => void; - handleDeleteTag?: (tag: { id: number; name: string }) => void; -} - -function CustomTag({ - isEditable = false, - tag, - editingTag, - editingTagValue, - setEditingTag, - setEditingTagValue, - handleEditTag, - handleCancelEdit, - handleDeleteTag, -}: CustomTagProps) { - return ( -
- {editingTag?.id === tag.id ? ( -
- setEditingTagValue?.(e.target.value)} - onKeyPress={(e) => { - if (e.key === "Enter") { - handleEditTag?.(tag, editingTagValue); - } - if (e.key === "Escape") { - setEditingTag?.(null); - setEditingTagValue?.(""); - } - }} - className="h-6 text-sm" - autoFocus - /> -
- ) : ( - <> - {tag.name} - {isEditable && ( -
-
- )} - - )} -
- ); -} - -const TagManager: React.FC = ({ - onFetch, - onCreate, - onDelete, - onUpdate, -}: { - onFetch: () => Promise; - onCreate: (tag: Pick) => Promise<{ ok: boolean }>; - onDelete: (tagId: number) => Promise<{ ok: boolean }>; - onUpdate: (tag: TagItem) => Promise<{ ok: boolean }>; -}) => { - const [showTagManager, setShowTagManager] = useState(false); - const { message } = App.useApp(); - const [tags, setTags] = useState<{ id: number; name: string }[]>([]); - const [newTag, setNewTag] = useState(""); - const [editingTag, setEditingTag] = useState(null); - const [editingTagValue, setEditingTagValue] = useState(""); - - // 获取标签列表 - const fetchTags = async () => { - if (!onFetch) return; - try { - const { data } = await onFetch?.(); - setTags(data || []); - } catch (e) { - message.error("获取标签失败"); - } - }; - - // 添加标签 - const addTag = async (tag: string) => { - try { - await onCreate?.({ - name: tag, - }); - fetchTags(); - setNewTag(""); - message.success("标签添加成功"); - } catch (error) { - message.error("添加标签失败"); - } - }; - - // 删除标签 - const deleteTag = async (tag: TagItem) => { - try { - await onDelete?.(tag.id); - fetchTags(); - message.success("标签删除成功"); - } catch (error) { - message.error("删除标签失败"); - } - }; - - const updateTag = async (oldTag: TagItem, newTag: string) => { - try { - await onUpdate?.({ ...oldTag, name: newTag }); - fetchTags(); - message.success("标签更新成功"); - } catch (error) { - message.error("更新标签失败"); - } - }; - - const handleCreateNewTag = () => { - if (newTag.trim()) { - addTag(newTag.trim()); - setNewTag(""); - } - }; - - const handleEditTag = (tag: TagItem, value: string) => { - if (value.trim()) { - updateTag(tag, value.trim()); - setEditingTag(null); - setEditingTagValue(""); - } - }; - - const handleCancelEdit = (tag: string) => { - setEditingTag(null); - setEditingTagValue(""); - }; - - const handleDeleteTag = (tag: TagItem) => { - deleteTag(tag); - setEditingTag(null); - setEditingTagValue(""); - }; - - useEffect(() => { - if (showTagManager) fetchTags(); - }, [showTagManager]); - - return ( - <> - - setShowTagManager(false)} - title="标签管理" - width={500} - > -
- {/* Add New Tag */} -
- setNewTag(e.target.value)} - onKeyPress={(e) => { - if (e.key === "Enter") { - addTag(e.target.value); - } - }} - /> - -
- -
-
- {tags.map((tag) => ( - - ))} -
-
-
-
- - ); -}; - -export default TagManager; +import React, { useEffect, useState } from "react"; +import { Drawer, Input, Button, App } from "antd"; +import { PlusOutlined } from "@ant-design/icons"; +import { Edit, Save, TagIcon, X, Trash } from "lucide-react"; +import { TagItem } from "@/pages/DataManagement/dataset.model"; + +interface CustomTagProps { + isEditable?: boolean; + tag: { id: number; name: string }; + editingTag?: string | null; + editingTagValue?: string; + setEditingTag?: React.Dispatch>; + setEditingTagValue?: React.Dispatch>; + handleEditTag?: (tag: { id: number; name: string }, value: string) => void; + handleCancelEdit?: (tag: { id: number; name: string }) => void; + handleDeleteTag?: (tag: { id: number; name: string }) => void; +} + +function CustomTag({ + isEditable = false, + tag, + editingTag, + editingTagValue, + setEditingTag, + setEditingTagValue, + handleEditTag, + handleCancelEdit, + handleDeleteTag, +}: CustomTagProps) { + return ( +
+ {editingTag?.id === tag.id ? ( +
+ setEditingTagValue?.(e.target.value)} + onKeyPress={(e) => { + if (e.key === "Enter") { + handleEditTag?.(tag, editingTagValue); + } + if (e.key === "Escape") { + setEditingTag?.(null); + setEditingTagValue?.(""); + } + }} + className="h-6 text-sm" + autoFocus + /> +
+ ) : ( + <> + {tag.name} + {isEditable && ( +
+
+ )} + + )} +
+ ); +} + +const TagManager: React.FC = ({ + onFetch, + onCreate, + onDelete, + onUpdate, +}: { + onFetch: () => Promise; + onCreate: (tag: Pick) => Promise<{ ok: boolean }>; + onDelete: (tagId: number) => Promise<{ ok: boolean }>; + onUpdate: (tag: TagItem) => Promise<{ ok: boolean }>; +}) => { + const [showTagManager, setShowTagManager] = useState(false); + const { message } = App.useApp(); + const [tags, setTags] = useState<{ id: number; name: string }[]>([]); + const [newTag, setNewTag] = useState(""); + const [editingTag, setEditingTag] = useState(null); + const [editingTagValue, setEditingTagValue] = useState(""); + + // 获取标签列表 + const fetchTags = async () => { + if (!onFetch) return; + try { + const { data } = await onFetch?.(); + setTags(data || []); + } catch (e) { + message.error("获取标签失败"); + } + }; + + // 添加标签 + const addTag = async (tag: string) => { + try { + await onCreate?.({ + name: tag, + }); + fetchTags(); + setNewTag(""); + message.success("标签添加成功"); + } catch (error) { + message.error("添加标签失败"); + } + }; + + // 删除标签 + const deleteTag = async (tag: TagItem) => { + try { + await onDelete?.(tag.id); + fetchTags(); + message.success("标签删除成功"); + } catch (error) { + message.error("删除标签失败"); + } + }; + + const updateTag = async (oldTag: TagItem, newTag: string) => { + try { + await onUpdate?.({ ...oldTag, name: newTag }); + fetchTags(); + message.success("标签更新成功"); + } catch (error) { + message.error("更新标签失败"); + } + }; + + const handleCreateNewTag = () => { + if (newTag.trim()) { + addTag(newTag.trim()); + setNewTag(""); + } + }; + + const handleEditTag = (tag: TagItem, value: string) => { + if (value.trim()) { + updateTag(tag, value.trim()); + setEditingTag(null); + setEditingTagValue(""); + } + }; + + const handleCancelEdit = (tag: string) => { + setEditingTag(null); + setEditingTagValue(""); + }; + + const handleDeleteTag = (tag: TagItem) => { + deleteTag(tag); + setEditingTag(null); + setEditingTagValue(""); + }; + + useEffect(() => { + if (showTagManager) fetchTags(); + }, [showTagManager]); + + return ( + <> + + setShowTagManager(false)} + title="标签管理" + width={500} + > +
+ {/* Add New Tag */} +
+ setNewTag(e.target.value)} + onKeyPress={(e) => { + if (e.key === "Enter") { + addTag(e.target.value); + } + }} + /> + +
+ +
+
+ {tags.map((tag) => ( + + ))} +
+
+
+
+ + ); +}; + +export default TagManager; diff --git a/frontend/src/components/business/TaskPopover.tsx b/frontend/src/components/business/TaskPopover.tsx index e1b838abd..2a0e7467e 100644 --- a/frontend/src/components/business/TaskPopover.tsx +++ b/frontend/src/components/business/TaskPopover.tsx @@ -1,162 +1,162 @@ -import { Button, Popover, Progress } from "antd"; -import { Calendar, Clock, Play, Trash2, X } from "lucide-react"; - -interface TaskItem { - id: string; - name: string; - status: string; - progress: number; - scheduleConfig: { - type: string; - cronExpression?: string; - executionCount?: number; - maxExecutions?: number; - }; - nextExecution?: string; - importConfig: { - source?: string; - }; - createdAt: string; -} - -export default function TaskPopover() { - const tasks: TaskItem[] = [ - { - id: "1", - name: "导入客户数据", - status: "importing", - progress: 65, - scheduleConfig: { - type: "manual", - }, - importConfig: { - source: "local", - }, - createdAt: "2025-07-29 14:23", - }, - { - id: "2", - name: "定时同步订单", - status: "waiting", - progress: 0, - scheduleConfig: { - type: "scheduled", - cronExpression: "0 0 * * *", - executionCount: 3, - maxExecutions: 10, - }, - nextExecution: "2025-07-31 00:00", - importConfig: { - source: "api", - }, - createdAt: "2025-07-28 09:10", - }, - { - id: "3", - name: "清理历史日志", - status: "finished", - progress: 100, - scheduleConfig: { - type: "manual", - }, - importConfig: { - source: "system", - }, - createdAt: "2025-07-27 17:45", - }, - ]; - - return ( - -
-

近期任务

- -
- -
- {tasks.length === 0 ? ( -
- -

暂无创建任务

-
- ) : ( -
- {tasks.map((task) => ( -
-
-
-

- {task.name} -

-
- {task.status === "waiting" && ( - - )} - -
-
- - {task.status === "importing" && ( -
-
- 导入进度 - {Math.round(task.progress)}% -
- -
- )} - - {/* Schedule Information */} - {task.scheduleConfig.type === "scheduled" && ( -
-
- - 定时任务 -
-
Cron: {task.scheduleConfig.cronExpression}
- {task.nextExecution && ( -
下次执行: {task.nextExecution}
- )} -
- 执行次数: {task.scheduleConfig.executionCount || 0}/ - {task.scheduleConfig.maxExecutions || 10} -
-
- )} - -
- - {task.importConfig.source === "local" - ? "本地上传" - : task.importConfig.source || "未知来源"} - - {task.createdAt} -
-
-
- ))} -
- )} -
- - } - > - -
- ); -} +import { Button, Popover, Progress } from "antd"; +import { Calendar, Clock, Play, Trash2, X } from "lucide-react"; + +interface TaskItem { + id: string; + name: string; + status: string; + progress: number; + scheduleConfig: { + type: string; + cronExpression?: string; + executionCount?: number; + maxExecutions?: number; + }; + nextExecution?: string; + importConfig: { + source?: string; + }; + createdAt: string; +} + +export default function TaskPopover() { + const tasks: TaskItem[] = [ + { + id: "1", + name: "导入客户数据", + status: "importing", + progress: 65, + scheduleConfig: { + type: "manual", + }, + importConfig: { + source: "local", + }, + createdAt: "2025-07-29 14:23", + }, + { + id: "2", + name: "定时同步订单", + status: "waiting", + progress: 0, + scheduleConfig: { + type: "scheduled", + cronExpression: "0 0 * * *", + executionCount: 3, + maxExecutions: 10, + }, + nextExecution: "2025-07-31 00:00", + importConfig: { + source: "api", + }, + createdAt: "2025-07-28 09:10", + }, + { + id: "3", + name: "清理历史日志", + status: "finished", + progress: 100, + scheduleConfig: { + type: "manual", + }, + importConfig: { + source: "system", + }, + createdAt: "2025-07-27 17:45", + }, + ]; + + return ( + +
+

近期任务

+ +
+ +
+ {tasks.length === 0 ? ( +
+ +

暂无创建任务

+
+ ) : ( +
+ {tasks.map((task) => ( +
+
+
+

+ {task.name} +

+
+ {task.status === "waiting" && ( + + )} + +
+
+ + {task.status === "importing" && ( +
+
+ 导入进度 + {Math.round(task.progress)}% +
+ +
+ )} + + {/* Schedule Information */} + {task.scheduleConfig.type === "scheduled" && ( +
+
+ + 定时任务 +
+
Cron: {task.scheduleConfig.cronExpression}
+ {task.nextExecution && ( +
下次执行: {task.nextExecution}
+ )} +
+ 执行次数: {task.scheduleConfig.executionCount || 0}/ + {task.scheduleConfig.maxExecutions || 10} +
+
+ )} + +
+ + {task.importConfig.source === "local" + ? "本地上传" + : task.importConfig.source || "未知来源"} + + {task.createdAt} +
+
+
+ ))} +
+ )} +
+ + } + > + +
+ ); +} diff --git a/frontend/src/hooks/useDebouncedEffect.ts b/frontend/src/hooks/useDebouncedEffect.ts index 152128560..dfd56aac3 100644 --- a/frontend/src/hooks/useDebouncedEffect.ts +++ b/frontend/src/hooks/useDebouncedEffect.ts @@ -1,17 +1,17 @@ -import { useEffect } from "react"; - -export function useDebouncedEffect( - cb: () => void, - deps: any[] = [], - delay: number = 300 -) { - useEffect(() => { - const handler = setTimeout(() => { - cb(); - }, delay); - - return () => { - clearTimeout(handler); - }; - }, [...(deps || []), delay]); -} +import { useEffect } from "react"; + +export function useDebouncedEffect( + cb: () => void, + deps: any[] = [], + delay: number = 300 +) { + useEffect(() => { + const handler = setTimeout(() => { + cb(); + }, delay); + + return () => { + clearTimeout(handler); + }; + }, [...(deps || []), delay]); +} diff --git a/frontend/src/hooks/useFetchData.ts b/frontend/src/hooks/useFetchData.ts index c3319c9e2..7df77384a 100644 --- a/frontend/src/hooks/useFetchData.ts +++ b/frontend/src/hooks/useFetchData.ts @@ -1,238 +1,236 @@ -// 首页数据获取 -// 支持轮询功能,使用示例: -// const { fetchData, startPolling, stopPolling, isPolling } = useFetchData( -// fetchFunction, -// mapFunction, -// 5000, // 5秒轮询一次,默认30秒 -// true, // 是否自动开始轮询,默认 true -// [fetchStatistics, fetchOtherData] // 额外的轮询函数数组 -// ); -// -// startPolling(); // 开始轮询 -// stopPolling(); // 停止轮询 -// 手动调用 fetchData() 时,如果正在轮询,会重新开始轮询计时 -// 轮询时会同时执行主要的 fetchFunction 和所有额外的轮询函数 -import { useState, useRef, useEffect, useCallback } from "react"; -import { useDebouncedEffect } from "./useDebouncedEffect"; -import Loading from "@/utils/loading"; -import { App } from "antd"; - -export default function useFetchData( - fetchFunc: (params?: any) => Promise, - mapDataFunc: (data: Partial) => T = (data) => data as T, - pollingInterval: number = 30000, // 默认30秒轮询一次 - autoRefresh: boolean = false, // 是否自动开始轮询,默认 false - additionalPollingFuncs: (() => Promise)[] = [], // 额外的轮询函数 - pageOffset: number = 1 -) { - const { message } = App.useApp(); - - // 轮询相关状态 - const [isPolling, setIsPolling] = useState(false); - const pollingTimerRef = useRef(null); - - // 表格数据 - const [tableData, setTableData] = useState([]); - // 设置加载状态 - const [loading, setLoading] = useState(false); - - // 搜索参数 - const [searchParams, setSearchParams] = useState({ - keyword: "", - filter: { - type: [] as string[], - status: [] as string[], - tags: [] as string[], - // 通用分类筛选(如算子市场的分类 ID 列表) - categories: [] as string[], - }, - current: 1, - pageSize: 12, - }); - - // 分页配置 - const [pagination, setPagination] = useState({ - total: 0, - showSizeChanger: true, - pageSizeOptions: ["12", "24", "48"], - showTotal: (total: number) => `共 ${total} 条`, - onChange: (current: number, pageSize?: number) => { - setSearchParams((prev) => ({ - ...prev, - current, - pageSize: pageSize || prev.pageSize, - })); - }, - }); - - const handleFiltersChange = (searchFilters: { [key: string]: string[] }) => { - setSearchParams({ - ...searchParams, - current: 1, - filter: { ...searchParams.filter, ...searchFilters }, - }); - }; - - const handleKeywordChange = (keyword: string) => { - setSearchParams({ - ...searchParams, - current: 1, - keyword: keyword, - }); - }; - - function getFirstOfArray(arr: string[]) { - if (!arr || arr.length === 0 || !Array.isArray(arr)) return undefined; - if (arr[0] === "all") return undefined; - return arr[0]; - } - - // 清除轮询定时器 - const clearPollingTimer = useCallback(() => { - if (pollingTimerRef.current) { - clearTimeout(pollingTimerRef.current); - pollingTimerRef.current = null; - } - }, []); - - const fetchData = useCallback( - async (extraParams = {}, skipPollingRestart = false) => { - const { keyword, filter, current, pageSize } = searchParams; - if (!skipPollingRestart) { - Loading.show(); - setLoading(true); - } - - // 如果正在轮询且不是轮询触发的调用,先停止当前轮询 - const wasPolling = isPolling && !skipPollingRestart; - if (wasPolling) { - clearPollingTimer(); - } - - try { - // 同时执行主要数据获取和额外的轮询函数 - const promises = [ - fetchFunc({ - ...Object.fromEntries( - Object.entries(filter).filter(([_, value]) => value != null && value.length > 0) - ), - ...extraParams, - keyword, - type: getFirstOfArray(filter?.type) || undefined, - status: getFirstOfArray(filter?.status) || undefined, - tags: filter?.tags?.length ? filter.tags.join(",") : undefined, - page: current - pageOffset, - size: pageSize, // Use camelCase for HTTP query params - }), - ...additionalPollingFuncs.map((func) => func()), - ]; - - const results = await Promise.all(promises); - const { data } = results[0]; // 主要数据结果 - - setPagination((prev) => ({ - ...prev, - total: data?.totalElements || 0, - })); - let result = []; - if (mapDataFunc) { - result = data?.content.map(mapDataFunc) ?? []; - } - setTableData(result); - - // 如果之前正在轮询且不是轮询触发的调用,重新开始轮询 - if (wasPolling) { - const poll = () => { - pollingTimerRef.current = setTimeout(() => { - fetchData({}, true).then(() => { - if (pollingTimerRef.current) { - poll(); - } - }); - }, pollingInterval); - }; - poll(); - } - } catch (error) { - console.error(error); - message.error("数据获取失败,请稍后重试"); - } finally { - Loading.hide(); - setLoading(false); - } - }, - [ - searchParams, - fetchFunc, - mapDataFunc, - isPolling, - clearPollingTimer, - pollingInterval, - message, - additionalPollingFuncs, - ] - ); - - // 开始轮询 - const startPolling = useCallback(() => { - clearPollingTimer(); - setIsPolling(true); - - const poll = () => { - pollingTimerRef.current = setTimeout(() => { - fetchData({}, true).then(() => { - if (pollingTimerRef.current) { - poll(); - } - }); - }, pollingInterval); - }; - - poll(); - }, [pollingInterval, clearPollingTimer, fetchData]); - - // 停止轮询 - const stopPolling = useCallback(() => { - clearPollingTimer(); - setIsPolling(false); - }, [clearPollingTimer]); - - // 搜索参数变化时,自动刷新数据 - // keyword 变化时,防抖500ms后刷新 - useDebouncedEffect( - () => { - fetchData(); - }, - [searchParams], - searchParams?.keyword ? 500 : 0 - ); - - // 组件卸载时清理轮询 - useEffect(() => { - if (autoRefresh) { - startPolling(); - } - return () => { - clearPollingTimer(); - }; - }, [clearPollingTimer]); - - return { - loading, - tableData, - pagination: { - ...pagination, - current: searchParams.current, - pageSize: searchParams.pageSize, - }, - searchParams, - setSearchParams, - setPagination, - handleFiltersChange, - handleKeywordChange, - fetchData, - isPolling, - startPolling, - stopPolling, - }; -} +// 首页数据获取 +// 支持轮询功能,使用示例: +// const { fetchData, startPolling, stopPolling, isPolling } = useFetchData( +// fetchFunction, +// mapFunction, +// 5000, // 5秒轮询一次,默认30秒 +// true, // 是否自动开始轮询,默认 true +// [fetchStatistics, fetchOtherData] // 额外的轮询函数数组 +// ); +// +// startPolling(); // 开始轮询 +// stopPolling(); // 停止轮询 +// 手动调用 fetchData() 时,如果正在轮询,会重新开始轮询计时 +// 轮询时会同时执行主要的 fetchFunction 和所有额外的轮询函数 +import { useState, useRef, useEffect, useCallback } from "react"; +import { useDebouncedEffect } from "./useDebouncedEffect"; +import Loading from "@/utils/loading"; +import { App } from "antd"; + +export default function useFetchData( + fetchFunc: (params?: any) => Promise, + mapDataFunc: (data: Partial) => T = (data) => data as T, + pollingInterval: number = 30000, // 默认30秒轮询一次 + autoRefresh: boolean = false, // 是否自动开始轮询,默认 false + additionalPollingFuncs: (() => Promise)[] = [], // 额外的轮询函数 + pageOffset: number = 1 +) { + const { message } = App.useApp(); + + // 轮询相关状态 + const [isPolling, setIsPolling] = useState(false); + const pollingTimerRef = useRef(null); + + // 表格数据 + const [tableData, setTableData] = useState([]); + // 设置加载状态 + const [loading, setLoading] = useState(false); + + // 搜索参数 + const [searchParams, setSearchParams] = useState({ + keyword: "", + filter: { + type: [] as string[], + status: [] as string[], + tags: [] as string[], + }, + current: 1, + pageSize: 12, + }); + + // 分页配置 + const [pagination, setPagination] = useState({ + total: 0, + showSizeChanger: true, + pageSizeOptions: ["12", "24", "48"], + showTotal: (total: number) => `共 ${total} 条`, + onChange: (current: number, pageSize?: number) => { + setSearchParams((prev) => ({ + ...prev, + current, + pageSize: pageSize || prev.pageSize, + })); + }, + }); + + const handleFiltersChange = (searchFilters: { [key: string]: string[] }) => { + setSearchParams({ + ...searchParams, + current: 1, + filter: { ...searchParams.filter, ...searchFilters }, + }); + }; + + const handleKeywordChange = (keyword: string) => { + setSearchParams({ + ...searchParams, + current: 1, + keyword: keyword, + }); + }; + + function getFirstOfArray(arr: string[]) { + if (!arr || arr.length === 0 || !Array.isArray(arr)) return undefined; + if (arr[0] === "all") return undefined; + return arr[0]; + } + + // 清除轮询定时器 + const clearPollingTimer = useCallback(() => { + if (pollingTimerRef.current) { + clearTimeout(pollingTimerRef.current); + pollingTimerRef.current = null; + } + }, []); + + const fetchData = useCallback( + async (extraParams = {}, skipPollingRestart = false) => { + const { keyword, filter, current, pageSize } = searchParams; + if (!skipPollingRestart) { + Loading.show(); + setLoading(true); + } + + // 如果正在轮询且不是轮询触发的调用,先停止当前轮询 + const wasPolling = isPolling && !skipPollingRestart; + if (wasPolling) { + clearPollingTimer(); + } + + try { + // 同时执行主要数据获取和额外的轮询函数 + const promises = [ + fetchFunc({ + ...Object.fromEntries( + Object.entries(filter).filter(([_, value]) => value != null && value.length > 0) + ), + ...extraParams, + keyword, + type: getFirstOfArray(filter?.type) || undefined, + status: getFirstOfArray(filter?.status) || undefined, + tags: filter?.tags?.length ? filter.tags.join(",") : undefined, + page: current - pageOffset, + size: pageSize, // Use camelCase for HTTP query params + }), + ...additionalPollingFuncs.map((func) => func()), + ]; + + const results = await Promise.all(promises); + const { data } = results[0]; // 主要数据结果 + + setPagination((prev) => ({ + ...prev, + total: data?.totalElements || 0, + })); + let result = []; + if (mapDataFunc) { + result = data?.content.map(mapDataFunc) ?? []; + } + setTableData(result); + + // 如果之前正在轮询且不是轮询触发的调用,重新开始轮询 + if (wasPolling) { + const poll = () => { + pollingTimerRef.current = setTimeout(() => { + fetchData({}, true).then(() => { + if (pollingTimerRef.current) { + poll(); + } + }); + }, pollingInterval); + }; + poll(); + } + } catch (error) { + console.error(error); + message.error("数据获取失败,请稍后重试"); + } finally { + Loading.hide(); + setLoading(false); + } + }, + [ + searchParams, + fetchFunc, + mapDataFunc, + isPolling, + clearPollingTimer, + pollingInterval, + message, + additionalPollingFuncs, + ] + ); + + // 开始轮询 + const startPolling = useCallback(() => { + clearPollingTimer(); + setIsPolling(true); + + const poll = () => { + pollingTimerRef.current = setTimeout(() => { + fetchData({}, true).then(() => { + if (pollingTimerRef.current) { + poll(); + } + }); + }, pollingInterval); + }; + + poll(); + }, [pollingInterval, clearPollingTimer, fetchData]); + + // 停止轮询 + const stopPolling = useCallback(() => { + clearPollingTimer(); + setIsPolling(false); + }, [clearPollingTimer]); + + // 搜索参数变化时,自动刷新数据 + // keyword 变化时,防抖500ms后刷新 + useDebouncedEffect( + () => { + fetchData(); + }, + [searchParams], + searchParams?.keyword ? 500 : 0 + ); + + // 组件卸载时清理轮询 + useEffect(() => { + if (autoRefresh) { + startPolling(); + } + return () => { + clearPollingTimer(); + }; + }, [clearPollingTimer]); + + return { + loading, + tableData, + pagination: { + ...pagination, + current: searchParams.current, + pageSize: searchParams.pageSize, + }, + searchParams, + setSearchParams, + setPagination, + handleFiltersChange, + handleKeywordChange, + fetchData, + isPolling, + startPolling, + stopPolling, + }; +} diff --git a/frontend/src/hooks/useLeavePrompt.ts b/frontend/src/hooks/useLeavePrompt.ts index 57bbbf569..b7d083160 100644 --- a/frontend/src/hooks/useLeavePrompt.ts +++ b/frontend/src/hooks/useLeavePrompt.ts @@ -1,52 +1,52 @@ -import { useCallback, useEffect, useState } from "react"; -import { useNavigate } from "react-router"; - -// 自定义hook:页面离开前提示 -export function useLeavePrompt(shouldPrompt: boolean) { - const navigate = useNavigate(); - const [showPrompt, setShowPrompt] = useState(false); - const [nextPath, setNextPath] = useState(null); - - // 浏览器刷新/关闭 - useEffect(() => { - const handler = (e: BeforeUnloadEvent) => { - if (shouldPrompt) { - e.preventDefault(); - e.returnValue = ""; - return ""; - } - }; - window.addEventListener("beforeunload", handler); - return () => window.removeEventListener("beforeunload", handler); - }, [shouldPrompt]); - - // 路由切换拦截 - useEffect(() => { - const unblock = (window as any).__REACT_ROUTER_DOM_HISTORY__?.block?.( - (tx: any) => { - if (shouldPrompt) { - setShowPrompt(true); - setNextPath(tx.location.pathname); - return false; - } - return true; - } - ); - return () => { - if (unblock) unblock(); - }; - }, [shouldPrompt]); - - const confirmLeave = useCallback(() => { - setShowPrompt(false); - if (nextPath) { - navigate(nextPath, { replace: true }); - } - }, [nextPath, navigate]); - - return { - showPrompt, - setShowPrompt, - confirmLeave, - }; -} +import { useCallback, useEffect, useState } from "react"; +import { useNavigate } from "react-router"; + +// 自定义hook:页面离开前提示 +export function useLeavePrompt(shouldPrompt: boolean) { + const navigate = useNavigate(); + const [showPrompt, setShowPrompt] = useState(false); + const [nextPath, setNextPath] = useState(null); + + // 浏览器刷新/关闭 + useEffect(() => { + const handler = (e: BeforeUnloadEvent) => { + if (shouldPrompt) { + e.preventDefault(); + e.returnValue = ""; + return ""; + } + }; + window.addEventListener("beforeunload", handler); + return () => window.removeEventListener("beforeunload", handler); + }, [shouldPrompt]); + + // 路由切换拦截 + useEffect(() => { + const unblock = (window as any).__REACT_ROUTER_DOM_HISTORY__?.block?.( + (tx: any) => { + if (shouldPrompt) { + setShowPrompt(true); + setNextPath(tx.location.pathname); + return false; + } + return true; + } + ); + return () => { + if (unblock) unblock(); + }; + }, [shouldPrompt]); + + const confirmLeave = useCallback(() => { + setShowPrompt(false); + if (nextPath) { + navigate(nextPath, { replace: true }); + } + }, [nextPath, navigate]); + + return { + showPrompt, + setShowPrompt, + confirmLeave, + }; +} diff --git a/frontend/src/hooks/useSearchParams.tsx b/frontend/src/hooks/useSearchParams.tsx index e02f8c64b..3514d0a94 100644 --- a/frontend/src/hooks/useSearchParams.tsx +++ b/frontend/src/hooks/useSearchParams.tsx @@ -1,18 +1,18 @@ -import { useMemo } from "react"; -import { useLocation } from "react-router"; - -interface AnyObject { - [key: string]: any; -} - -export function useSearchParams(): AnyObject { - const { search } = useLocation(); - return useMemo(() => { - const urlParams = new URLSearchParams(search); - const params: AnyObject = {}; - for (const [key, value] of urlParams.entries()) { - params[key] = value; - } - return params; - }, [search]); -} +import { useMemo } from "react"; +import { useLocation } from "react-router"; + +interface AnyObject { + [key: string]: any; +} + +export function useSearchParams(): AnyObject { + const { search } = useLocation(); + return useMemo(() => { + const urlParams = new URLSearchParams(search); + const params: AnyObject = {}; + for (const [key, value] of urlParams.entries()) { + params[key] = value; + } + return params; + }, [search]); +} diff --git a/frontend/src/hooks/useSliceUpload.tsx b/frontend/src/hooks/useSliceUpload.tsx index 3301529bc..44a3dca6f 100644 --- a/frontend/src/hooks/useSliceUpload.tsx +++ b/frontend/src/hooks/useSliceUpload.tsx @@ -1,187 +1,187 @@ -import { TaskItem } from "@/pages/DataManagement/dataset.model"; -import { calculateSHA256, checkIsFilesExist } from "@/utils/file.util"; -import { App } from "antd"; -import { useRef, useState } from "react"; - -export function useFileSliceUpload( - { - preUpload, - uploadChunk, - cancelUpload, - }: { - preUpload: (id: string, params: any) => Promise<{ data: number }>; - uploadChunk: (id: string, formData: FormData, config: any) => Promise; - cancelUpload: ((reqId: number) => Promise) | null; - }, - showTaskCenter = true // 上传时是否显示任务中心 -) { - const { message } = App.useApp(); - const [taskList, setTaskList] = useState([]); - const taskListRef = useRef([]); // 用于固定任务顺序 - - const createTask = (detail: any = {}) => { - const { dataset } = detail; - const title = `上传数据集: ${dataset.name} `; - const controller = new AbortController(); - const task: TaskItem = { - key: dataset.id, - title, - percent: 0, - reqId: -1, - controller, - size: 0, - updateEvent: detail.updateEvent, - hasArchive: detail.hasArchive, - }; - taskListRef.current = [task, ...taskListRef.current]; - - setTaskList(taskListRef.current); - return task; - }; - - const updateTaskList = (task: TaskItem) => { - taskListRef.current = taskListRef.current.map((item) => - item.key === task.key ? task : item - ); - setTaskList(taskListRef.current); - }; - - const removeTask = (task: TaskItem) => { - const { key } = task; - taskListRef.current = taskListRef.current.filter( - (item) => item.key !== key - ); - setTaskList(taskListRef.current); - if (task.isCancel && task.cancelFn) { - task.cancelFn(); - } - if (task.updateEvent) window.dispatchEvent(new Event(task.updateEvent)); - if (showTaskCenter) { - window.dispatchEvent( - new CustomEvent("show:task-popover", { detail: { show: false } }) - ); - } - }; - - async function buildFormData({ file, reqId, i, j }) { - const formData = new FormData(); - const { slices, name, size } = file; - const checkSum = await calculateSHA256(slices[j]); - formData.append("file", slices[j]); - formData.append("reqId", reqId.toString()); - formData.append("fileNo", (i + 1).toString()); - formData.append("chunkNo", (j + 1).toString()); - formData.append("fileName", name); - formData.append("fileSize", size.toString()); - formData.append("totalChunkNum", slices.length.toString()); - formData.append("checkSumHex", checkSum); - return formData; - } - - async function uploadSlice(task: TaskItem, fileInfo) { - if (!task) { - return; - } - const { reqId, key } = task; - const { loaded, i, j, files, totalSize } = fileInfo; - const formData = await buildFormData({ - file: files[i], - i, - j, - reqId, - }); - - let newTask = { ...task }; - await uploadChunk(key, formData, { - onUploadProgress: (e) => { - const loadedSize = loaded + e.loaded; - const curPercent = Number((loadedSize / totalSize) * 100).toFixed(2); - - newTask = { - ...newTask, - ...taskListRef.current.find((item) => item.key === key), - size: loadedSize, - percent: curPercent >= 100 ? 99.99 : curPercent, - }; - updateTaskList(newTask); - }, - }); - } - - async function uploadFile({ task, files, totalSize }) { - const { data: reqId } = await preUpload(task.key, { - totalFileNum: files.length, - totalSize, - datasetId: task.key, - hasArchive: task.hasArchive, - }); - - const newTask: TaskItem = { - ...task, - reqId, - isCancel: false, - cancelFn: () => { - task.controller.abort(); - cancelUpload?.(reqId); - if (task.updateEvent) window.dispatchEvent(new Event(task.updateEvent)); - }, - }; - updateTaskList(newTask); - if (showTaskCenter) { - window.dispatchEvent( - new CustomEvent("show:task-popover", { detail: { show: true } }) - ); - } - // // 更新数据状态 - if (task.updateEvent) window.dispatchEvent(new Event(task.updateEvent)); - - let loaded = 0; - for (let i = 0; i < files.length; i++) { - const { slices } = files[i]; - for (let j = 0; j < slices.length; j++) { - await uploadSlice(newTask, { - loaded, - i, - j, - files, - totalSize, - }); - loaded += slices[j].size; - } - } - removeTask(newTask); - } - - const handleUpload = async ({ task, files }) => { - const isErrorFile = await checkIsFilesExist(files); - if (isErrorFile) { - message.error("文件被修改或删除,请重新选择文件上传"); - removeTask({ - ...task, - isCancel: false, - ...taskListRef.current.find((item) => item.key === task.key), - }); - return; - } - - try { - const totalSize = files.reduce((acc, file) => acc + file.size, 0); - await uploadFile({ task, files, totalSize }); - } catch (err) { - console.error(err); - message.error("文件上传失败,请稍后重试"); - removeTask({ - ...task, - isCancel: true, - ...taskListRef.current.find((item) => item.key === task.key), - }); - } - }; - - return { - taskList, - createTask, - removeTask, - handleUpload, - }; -} +import { TaskItem } from "@/pages/DataManagement/dataset.model"; +import { calculateSHA256, checkIsFilesExist } from "@/utils/file.util"; +import { App } from "antd"; +import { useRef, useState } from "react"; + +export function useFileSliceUpload( + { + preUpload, + uploadChunk, + cancelUpload, + }: { + preUpload: (id: string, params: any) => Promise<{ data: number }>; + uploadChunk: (id: string, formData: FormData, config: any) => Promise; + cancelUpload: ((reqId: number) => Promise) | null; + }, + showTaskCenter = true // 上传时是否显示任务中心 +) { + const { message } = App.useApp(); + const [taskList, setTaskList] = useState([]); + const taskListRef = useRef([]); // 用于固定任务顺序 + + const createTask = (detail: any = {}) => { + const { dataset } = detail; + const title = `上传数据集: ${dataset.name} `; + const controller = new AbortController(); + const task: TaskItem = { + key: dataset.id, + title, + percent: 0, + reqId: -1, + controller, + size: 0, + updateEvent: detail.updateEvent, + hasArchive: detail.hasArchive, + }; + taskListRef.current = [task, ...taskListRef.current]; + + setTaskList(taskListRef.current); + return task; + }; + + const updateTaskList = (task: TaskItem) => { + taskListRef.current = taskListRef.current.map((item) => + item.key === task.key ? task : item + ); + setTaskList(taskListRef.current); + }; + + const removeTask = (task: TaskItem) => { + const { key } = task; + taskListRef.current = taskListRef.current.filter( + (item) => item.key !== key + ); + setTaskList(taskListRef.current); + if (task.isCancel && task.cancelFn) { + task.cancelFn(); + } + if (task.updateEvent) window.dispatchEvent(new Event(task.updateEvent)); + if (showTaskCenter) { + window.dispatchEvent( + new CustomEvent("show:task-popover", { detail: { show: false } }) + ); + } + }; + + async function buildFormData({ file, reqId, i, j }) { + const formData = new FormData(); + const { slices, name, size } = file; + const checkSum = await calculateSHA256(slices[j]); + formData.append("file", slices[j]); + formData.append("reqId", reqId.toString()); + formData.append("fileNo", (i + 1).toString()); + formData.append("chunkNo", (j + 1).toString()); + formData.append("fileName", name); + formData.append("fileSize", size.toString()); + formData.append("totalChunkNum", slices.length.toString()); + formData.append("checkSumHex", checkSum); + return formData; + } + + async function uploadSlice(task: TaskItem, fileInfo) { + if (!task) { + return; + } + const { reqId, key } = task; + const { loaded, i, j, files, totalSize } = fileInfo; + const formData = await buildFormData({ + file: files[i], + i, + j, + reqId, + }); + + let newTask = { ...task }; + await uploadChunk(key, formData, { + onUploadProgress: (e) => { + const loadedSize = loaded + e.loaded; + const curPercent = Number((loadedSize / totalSize) * 100).toFixed(2); + + newTask = { + ...newTask, + ...taskListRef.current.find((item) => item.key === key), + size: loadedSize, + percent: curPercent >= 100 ? 99.99 : curPercent, + }; + updateTaskList(newTask); + }, + }); + } + + async function uploadFile({ task, files, totalSize }) { + const { data: reqId } = await preUpload(task.key, { + totalFileNum: files.length, + totalSize, + datasetId: task.key, + hasArchive: task.hasArchive, + }); + + const newTask: TaskItem = { + ...task, + reqId, + isCancel: false, + cancelFn: () => { + task.controller.abort(); + cancelUpload?.(reqId); + if (task.updateEvent) window.dispatchEvent(new Event(task.updateEvent)); + }, + }; + updateTaskList(newTask); + if (showTaskCenter) { + window.dispatchEvent( + new CustomEvent("show:task-popover", { detail: { show: true } }) + ); + } + // // 更新数据状态 + if (task.updateEvent) window.dispatchEvent(new Event(task.updateEvent)); + + let loaded = 0; + for (let i = 0; i < files.length; i++) { + const { slices } = files[i]; + for (let j = 0; j < slices.length; j++) { + await uploadSlice(newTask, { + loaded, + i, + j, + files, + totalSize, + }); + loaded += slices[j].size; + } + } + removeTask(newTask); + } + + const handleUpload = async ({ task, files }) => { + const isErrorFile = await checkIsFilesExist(files); + if (isErrorFile) { + message.error("文件被修改或删除,请重新选择文件上传"); + removeTask({ + ...task, + isCancel: false, + ...taskListRef.current.find((item) => item.key === task.key), + }); + return; + } + + try { + const totalSize = files.reduce((acc, file) => acc + file.size, 0); + await uploadFile({ task, files, totalSize }); + } catch (err) { + console.error(err); + message.error("文件上传失败,请稍后重试"); + removeTask({ + ...task, + isCancel: true, + ...taskListRef.current.find((item) => item.key === task.key), + }); + } + }; + + return { + taskList, + createTask, + removeTask, + handleUpload, + }; +} diff --git a/frontend/src/hooks/useStyle.ts b/frontend/src/hooks/useStyle.ts index ba694baa1..5139240e7 100644 --- a/frontend/src/hooks/useStyle.ts +++ b/frontend/src/hooks/useStyle.ts @@ -1,20 +1,20 @@ -import { createStyles } from "antd-style"; - -const useStyle = createStyles(({ css, token }) => { - const { antCls } = token; - return { - customTable: css` - ${antCls}-table { - ${antCls}-table-container { - ${antCls}-table-body, ${antCls}-table-content { - scrollbar-width: thin; - scrollbar-color: ${token.colorBorder} transparent; - scrollbar-gutter: stable; - } - } - } - `, - }; -}); - -export default useStyle; +import { createStyles } from "antd-style"; + +const useStyle = createStyles(({ css, token }) => { + const { antCls } = token; + return { + customTable: css` + ${antCls}-table { + ${antCls}-table-container { + ${antCls}-table-body, ${antCls}-table-content { + scrollbar-width: thin; + scrollbar-color: ${token.colorBorder} transparent; + scrollbar-gutter: stable; + } + } + } + `, + }; +}); + +export default useStyle; diff --git a/frontend/src/hooks/useTagConfig.ts b/frontend/src/hooks/useTagConfig.ts index ec39524f7..d547c54ac 100644 --- a/frontend/src/hooks/useTagConfig.ts +++ b/frontend/src/hooks/useTagConfig.ts @@ -1,67 +1,67 @@ -import { useState, useEffect } from "react"; -import { message } from "antd"; -import { getTagConfigUsingGet } from "../pages/DataAnnotation/annotation.api"; -import type { LabelStudioTagConfig } from "../pages/DataAnnotation/annotation.tagconfig"; -import { parseTagConfig, type TagOption } from "../pages/DataAnnotation/annotation.tagconfig"; - -interface UseTagConfigReturn { - config: LabelStudioTagConfig | null; - objectOptions: TagOption[]; - controlOptions: TagOption[]; - loading: boolean; - error: string | null; - refetch: () => Promise; -} - -/** - * Hook to fetch and manage Label Studio tag configuration - * @param includeLabelingOnly - If true, only include controls with category="labeling" (default: true) - */ -export function useTagConfig(includeLabelingOnly: boolean = true): UseTagConfigReturn { - const [config, setConfig] = useState(null); - const [objectOptions, setObjectOptions] = useState([]); - const [controlOptions, setControlOptions] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - - const fetchConfig = async () => { - setLoading(true); - setError(null); - try { - const response = await getTagConfigUsingGet(); - if (response.code === 200 && response.data) { - const tagConfig: LabelStudioTagConfig = response.data; - setConfig(tagConfig); - - const { objectOptions: objects, controlOptions: controls } = - parseTagConfig(tagConfig, includeLabelingOnly); - setObjectOptions(objects); - setControlOptions(controls); - } else { - const errorMsg = response.message || "获取标签配置失败"; - setError(errorMsg); - message.error(errorMsg); - } - } catch (err: any) { - const errorMsg = err.message || "加载标签配置时出错"; - setError(errorMsg); - console.error("Failed to fetch tag config:", err); - message.error(errorMsg); - } finally { - setLoading(false); - } - }; - - useEffect(() => { - fetchConfig(); - }, []); - - return { - config, - objectOptions, - controlOptions, - loading, - error, - refetch: fetchConfig, - }; -} +import { useState, useEffect } from "react"; +import { message } from "antd"; +import { getTagConfigUsingGet } from "../pages/DataAnnotation/annotation.api"; +import type { LabelStudioTagConfig } from "../pages/DataAnnotation/annotation.tagconfig"; +import { parseTagConfig, type TagOption } from "../pages/DataAnnotation/annotation.tagconfig"; + +interface UseTagConfigReturn { + config: LabelStudioTagConfig | null; + objectOptions: TagOption[]; + controlOptions: TagOption[]; + loading: boolean; + error: string | null; + refetch: () => Promise; +} + +/** + * Hook to fetch and manage Label Studio tag configuration + * @param includeLabelingOnly - If true, only include controls with category="labeling" (default: true) + */ +export function useTagConfig(includeLabelingOnly: boolean = true): UseTagConfigReturn { + const [config, setConfig] = useState(null); + const [objectOptions, setObjectOptions] = useState([]); + const [controlOptions, setControlOptions] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + const fetchConfig = async () => { + setLoading(true); + setError(null); + try { + const response = await getTagConfigUsingGet(); + if (response.code === 200 && response.data) { + const tagConfig: LabelStudioTagConfig = response.data; + setConfig(tagConfig); + + const { objectOptions: objects, controlOptions: controls } = + parseTagConfig(tagConfig, includeLabelingOnly); + setObjectOptions(objects); + setControlOptions(controls); + } else { + const errorMsg = response.message || "获取标签配置失败"; + setError(errorMsg); + message.error(errorMsg); + } + } catch (err: any) { + const errorMsg = err.message || "加载标签配置时出错"; + setError(errorMsg); + console.error("Failed to fetch tag config:", err); + message.error(errorMsg); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchConfig(); + }, []); + + return { + config, + objectOptions, + controlOptions, + loading, + error, + refetch: fetchConfig, + }; +} diff --git a/frontend/src/index.css b/frontend/src/index.css index d08ea97e1..172fcbb1a 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -1,75 +1,75 @@ -@import "tailwindcss"; - -/* components/TopLoadingBar.css */ -.top-loading-bar { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 3px; - background-color: transparent; - z-index: 9999; - overflow: hidden; -} - -.loading-bar-progress { - height: 100%; - background: linear-gradient(90deg, #3498db, #2ecc71, #3498db); - background-size: 200% 100%; - animation: gradient-animation 2s linear infinite, width-animation 0.3s ease; - transition: width 0.3s ease; -} - -@keyframes gradient-animation { - 0% { - background-position: 200% 0; - } - 100% { - background-position: -200% 0; - } -} - -@keyframes width-animation { - from { - transform: translateX(-100%); - } - to { - transform: translateX(0); - } -} - -.show-task-popover { - opacity: 100%; - visibility: visible; - transform: translateX(0); -} - -@layer components { - .flex-center { - @apply flex items-center justify-center; - } - .flex-overflow-auto { - @apply flex-1 flex flex-col overflow-auto h-full; - } - .flex-overflow-hidden { - @apply flex flex-col h-full overflow-hidden; - } - .border-card { - @apply border border-[#f0f0f0] rounded-lg bg-white; - } - .border { - @apply border border-[#f0f0f0]; - } - .border-bottom { - @apply border-b border-[#f0f0f0]; - } - .border-top { - @apply border-t border-[#f0f0f0]; - } - .border-right { - @apply border-r border-[#f0f0f0]; - } - .border-left { - @apply border-l border-[#f0f0f0]; - } -} +@import "tailwindcss"; + +/* components/TopLoadingBar.css */ +.top-loading-bar { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 3px; + background-color: transparent; + z-index: 9999; + overflow: hidden; +} + +.loading-bar-progress { + height: 100%; + background: linear-gradient(90deg, #3498db, #2ecc71, #3498db); + background-size: 200% 100%; + animation: gradient-animation 2s linear infinite, width-animation 0.3s ease; + transition: width 0.3s ease; +} + +@keyframes gradient-animation { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -200% 0; + } +} + +@keyframes width-animation { + from { + transform: translateX(-100%); + } + to { + transform: translateX(0); + } +} + +.show-task-popover { + opacity: 100%; + visibility: visible; + transform: translateX(0); +} + +@layer components { + .flex-center { + @apply flex items-center justify-center; + } + .flex-overflow-auto { + @apply flex-1 flex flex-col overflow-auto h-full; + } + .flex-overflow-hidden { + @apply flex flex-col h-full overflow-hidden; + } + .border-card { + @apply border border-[#f0f0f0] rounded-lg bg-white; + } + .border { + @apply border border-[#f0f0f0]; + } + .border-bottom { + @apply border-b border-[#f0f0f0]; + } + .border-top { + @apply border-t border-[#f0f0f0]; + } + .border-right { + @apply border-r border-[#f0f0f0]; + } + .border-left { + @apply border-l border-[#f0f0f0]; + } +} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index a3f0f01bb..4537c90ef 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,22 +1,22 @@ -import { StrictMode, Suspense } from "react"; -import { createRoot } from "react-dom/client"; -import { RouterProvider } from "react-router"; -import router from "./routes/routes"; -import { App as AntdApp, Spin } from "antd"; -import "./index.css"; -import TopLoadingBar from "./components/TopLoadingBar"; -import { store } from "./store"; -import { Provider } from "react-redux"; - -createRoot(document.getElementById("root")!).render( - - - - }> - - - - - - -); +import { StrictMode, Suspense } from "react"; +import { createRoot } from "react-dom/client"; +import { RouterProvider } from "react-router"; +import router from "./routes/routes"; +import { App as AntdApp, Spin } from "antd"; +import "./index.css"; +import TopLoadingBar from "./components/TopLoadingBar"; +import { store } from "./store"; +import { Provider } from "react-redux"; + +createRoot(document.getElementById("root")!).render( + + + + }> + + + + + + +); diff --git a/frontend/src/mock/annotation.tsx b/frontend/src/mock/annotation.tsx index 8b5ccccf2..280815dbf 100644 --- a/frontend/src/mock/annotation.tsx +++ b/frontend/src/mock/annotation.tsx @@ -1,330 +1,330 @@ -import { BarChart, Circle, Grid, ImageIcon, Layers, Maximize, MousePointer, Move, Square, Target, Crop, RotateCcw, FileText, Tag, Heart, HelpCircle, BookOpen, MessageSquare, Users, Zap, Globe, Scissors } from "lucide-react"; - -// Define the AnnotationTask type if not imported from elsewhere -interface AnnotationTask { - id: string - name: string - completed: string - completedCount: number - skippedCount: number - totalCount: number - annotators: Array<{ - id: string - name: string - avatar?: string - }> - text: string - status: "completed" | "in_progress" | "pending" | "skipped" - project: string - type: "图像分类" | "文本分类" | "目标检测" | "NER" | "语音识别" | "视频分析" - datasetType: "text" | "image" | "video" | "audio" - progress: number -} - - -export const mockTasks: AnnotationTask[] = [ - { - id: "12345678", - name: "图像分类标注任务", - completed: "2024年1月20日 20:40", - completedCount: 1, - skippedCount: 0, - totalCount: 2, - annotators: [ - { id: "1", name: "张三", avatar: "/placeholder-user.jpg" }, - { id: "2", name: "李四", avatar: "/placeholder-user.jpg" }, - ], - text: "对产品图像进行分类标注,包含10个类别", - status: "completed", - project: "图像分类", - type: "图像分类", - datasetType: "image", - progress: 100, - }, - { - id: "12345679", - name: "文本情感分析标注", - completed: "2024年1月20日 20:40", - completedCount: 2, - skippedCount: 0, - totalCount: 2, - annotators: [ - { id: "1", name: "王五", avatar: "/placeholder-user.jpg" }, - { id: "2", name: "赵六", avatar: "/placeholder-user.jpg" }, - ], - text: "对用户评论进行情感倾向标注", - status: "completed", - project: "文本分类", - type: "文本分类", - datasetType: "text", - progress: 100, - }, - { - id: "12345680", - name: "目标检测标注任务", - completed: "2024年1月20日 20:40", - completedCount: 1, - skippedCount: 0, - totalCount: 2, - annotators: [{ id: "1", name: "孙七", avatar: "/placeholder-user.jpg" }], - text: "对交通场景图像进行目标检测标注", - status: "in_progress", - project: "目标检测", - type: "目标检测", - datasetType: "image", - progress: 50, - }, - { - id: "12345681", - name: "命名实体识别标注", - completed: "2024年1月20日 20:40", - completedCount: 1, - skippedCount: 0, - totalCount: 2, - annotators: [{ id: "1", name: "周八", avatar: "/placeholder-user.jpg" }], - text: "对新闻文本进行命名实体识别标注", - status: "in_progress", - project: "NER", - type: "NER", - datasetType: "text", - progress: 75, - }, - { - id: "12345682", - name: "语音识别标注任务", - completed: "2024年1月20日 20:40", - completedCount: 1, - skippedCount: 0, - totalCount: 2, - annotators: [{ id: "1", name: "吴九", avatar: "/placeholder-user.jpg" }], - text: "对语音数据进行转录和标注", - status: "in_progress", - project: "语音识别", - type: "语音识别", - datasetType: "audio", - progress: 25, - }, - { - id: "12345683", - name: "视频动作识别标注", - completed: "2024年1月20日 20:40", - completedCount: 0, - skippedCount: 2, - totalCount: 2, - annotators: [ - { id: "1", name: "陈十", avatar: "/placeholder-user.jpg" }, - { id: "2", name: "林十一", avatar: "/placeholder-user.jpg" }, - ], - text: "对视频中的人体动作进行识别和标注", - status: "skipped", - project: "视频分析", - type: "视频分析", - datasetType: "video", - progress: 0, - }, -] - -// Define the Template type -type Template = { - id: string; - name: string; - category: string; - description: string; - type: string; - preview?: string; - icon: React.ReactNode; -}; - -// 扩展的预制模板数据 -export const mockTemplates: Template[] = [ - // 计算机视觉模板 - { - id: "cv-1", - name: "目标检测", - category: "Computer Vision", - description: "使用边界框标注图像中的目标对象", - type: "image", - preview: "/placeholder.svg?height=120&width=180&text=Object+Detection", - icon: , - }, - { - id: "cv-2", - name: "语义分割(多边形)", - category: "Computer Vision", - description: "使用多边形精确标注图像中的区域", - type: "image", - preview: "/placeholder.svg?height=120&width=180&text=Polygon+Segmentation", - icon: , - }, - { - id: "cv-3", - name: "语义分割(掩码)", - category: "Computer Vision", - description: "使用像素级掩码标注图像区域", - type: "image", - preview: "/placeholder.svg?height=120&width=180&text=Mask+Segmentation", - icon: , - }, - { - id: "cv-4", - name: "关键点标注", - category: "Computer Vision", - description: "标注图像中的关键点位置", - type: "image", - preview: "/placeholder.svg?height=120&width=180&text=Keypoint+Labeling", - icon: , - }, - { - id: "cv-5", - name: "图像分类", - category: "Computer Vision", - description: "为整个图像分配类别标签", - type: "image", - preview: "/placeholder.svg?height=120&width=180&text=Image+Classification", - icon: , - }, - { - id: "cv-6", - name: "实例分割", - category: "Computer Vision", - description: "区分同类别的不同实例对象", - type: "image", - preview: "/placeholder.svg?height=120&width=180&text=Instance+Segmentation", - icon: , - }, - { - id: "cv-7", - name: "全景分割", - category: "Computer Vision", - description: "结合语义分割和实例分割的全景标注", - type: "image", - preview: "/placeholder.svg?height=120&width=180&text=Panoptic+Segmentation", - icon: , - }, - { - id: "cv-8", - name: "3D目标检测", - category: "Computer Vision", - description: "在3D空间中标注目标对象的位置和方向", - type: "image", - preview: "/placeholder.svg?height=120&width=180&text=3D+Object+Detection", - icon: , - }, - { - id: "cv-9", - name: "图像配对", - category: "Computer Vision", - description: "标注图像之间的对应关系", - type: "image", - preview: "/placeholder.svg?height=120&width=180&text=Image+Matching", - icon: , - }, - { - id: "cv-10", - name: "图像质量评估", - category: "Computer Vision", - description: "评估和标注图像质量等级", - type: "image", - preview: "/placeholder.svg?height=120&width=180&text=Quality+Assessment", - icon: , - }, - { - id: "cv-11", - name: "图像裁剪标注", - category: "Computer Vision", - description: "标注图像中需要裁剪的区域", - type: "image", - preview: "/placeholder.svg?height=120&width=180&text=Image+Cropping", - icon: , - }, - { - id: "cv-12", - name: "图像旋转标注", - category: "Computer Vision", - description: "标注图像的正确方向角度", - type: "image", - preview: "/placeholder.svg?height=120&width=180&text=Image+Rotation", - icon: , - }, - // 自然语言处理模板 - { - id: "nlp-1", - name: "文本分类", - category: "Natural Language Processing", - description: "为文本分配类别标签", - type: "text", - icon: , - }, - { - id: "nlp-2", - name: "命名实体识别", - category: "Natural Language Processing", - description: "识别和标注文本中的实体", - type: "text", - icon: , - }, - { - id: "nlp-3", - name: "情感分析", - category: "Natural Language Processing", - description: "标注文本的情感倾向", - type: "text", - icon: , - }, - { - id: "nlp-4", - name: "问答标注", - category: "Natural Language Processing", - description: "标注问题和答案对", - type: "text", - icon: , - }, - { - id: "nlp-5", - name: "文本摘要", - category: "Natural Language Processing", - description: "为长文本创建摘要标注", - type: "text", - icon: , - }, - { - id: "nlp-6", - name: "对话标注", - category: "Natural Language Processing", - description: "标注对话中的意图和实体", - type: "text", - icon: , - }, - { - id: "nlp-7", - name: "关系抽取", - category: "Natural Language Processing", - description: "标注实体之间的关系", - type: "text", - icon: , - }, - { - id: "nlp-8", - name: "文本相似度", - category: "Natural Language Processing", - description: "标注文本之间的相似度", - type: "text", - icon: , - }, - { - id: "nlp-9", - name: "语言检测", - category: "Natural Language Processing", - description: "识别和标注文本的语言类型", - type: "text", - icon: , - }, - { - id: "nlp-10", - name: "文本纠错", - category: "Natural Language Processing", - description: "标注文本中的错误并提供修正", - type: "text", - icon: , - }, +import { BarChart, Circle, Grid, ImageIcon, Layers, Maximize, MousePointer, Move, Square, Target, Crop, RotateCcw, FileText, Tag, Heart, HelpCircle, BookOpen, MessageSquare, Users, Zap, Globe, Scissors } from "lucide-react"; + +// Define the AnnotationTask type if not imported from elsewhere +interface AnnotationTask { + id: string + name: string + completed: string + completedCount: number + skippedCount: number + totalCount: number + annotators: Array<{ + id: string + name: string + avatar?: string + }> + text: string + status: "completed" | "in_progress" | "pending" | "skipped" + project: string + type: "图像分类" | "文本分类" | "目标检测" | "NER" | "语音识别" | "视频分析" + datasetType: "text" | "image" | "video" | "audio" + progress: number +} + + +export const mockTasks: AnnotationTask[] = [ + { + id: "12345678", + name: "图像分类标注任务", + completed: "2024年1月20日 20:40", + completedCount: 1, + skippedCount: 0, + totalCount: 2, + annotators: [ + { id: "1", name: "张三", avatar: "/placeholder-user.jpg" }, + { id: "2", name: "李四", avatar: "/placeholder-user.jpg" }, + ], + text: "对产品图像进行分类标注,包含10个类别", + status: "completed", + project: "图像分类", + type: "图像分类", + datasetType: "image", + progress: 100, + }, + { + id: "12345679", + name: "文本情感分析标注", + completed: "2024年1月20日 20:40", + completedCount: 2, + skippedCount: 0, + totalCount: 2, + annotators: [ + { id: "1", name: "王五", avatar: "/placeholder-user.jpg" }, + { id: "2", name: "赵六", avatar: "/placeholder-user.jpg" }, + ], + text: "对用户评论进行情感倾向标注", + status: "completed", + project: "文本分类", + type: "文本分类", + datasetType: "text", + progress: 100, + }, + { + id: "12345680", + name: "目标检测标注任务", + completed: "2024年1月20日 20:40", + completedCount: 1, + skippedCount: 0, + totalCount: 2, + annotators: [{ id: "1", name: "孙七", avatar: "/placeholder-user.jpg" }], + text: "对交通场景图像进行目标检测标注", + status: "in_progress", + project: "目标检测", + type: "目标检测", + datasetType: "image", + progress: 50, + }, + { + id: "12345681", + name: "命名实体识别标注", + completed: "2024年1月20日 20:40", + completedCount: 1, + skippedCount: 0, + totalCount: 2, + annotators: [{ id: "1", name: "周八", avatar: "/placeholder-user.jpg" }], + text: "对新闻文本进行命名实体识别标注", + status: "in_progress", + project: "NER", + type: "NER", + datasetType: "text", + progress: 75, + }, + { + id: "12345682", + name: "语音识别标注任务", + completed: "2024年1月20日 20:40", + completedCount: 1, + skippedCount: 0, + totalCount: 2, + annotators: [{ id: "1", name: "吴九", avatar: "/placeholder-user.jpg" }], + text: "对语音数据进行转录和标注", + status: "in_progress", + project: "语音识别", + type: "语音识别", + datasetType: "audio", + progress: 25, + }, + { + id: "12345683", + name: "视频动作识别标注", + completed: "2024年1月20日 20:40", + completedCount: 0, + skippedCount: 2, + totalCount: 2, + annotators: [ + { id: "1", name: "陈十", avatar: "/placeholder-user.jpg" }, + { id: "2", name: "林十一", avatar: "/placeholder-user.jpg" }, + ], + text: "对视频中的人体动作进行识别和标注", + status: "skipped", + project: "视频分析", + type: "视频分析", + datasetType: "video", + progress: 0, + }, +] + +// Define the Template type +type Template = { + id: string; + name: string; + category: string; + description: string; + type: string; + preview?: string; + icon: React.ReactNode; +}; + +// 扩展的预制模板数据 +export const mockTemplates: Template[] = [ + // 计算机视觉模板 + { + id: "cv-1", + name: "目标检测", + category: "Computer Vision", + description: "使用边界框标注图像中的目标对象", + type: "image", + preview: "/placeholder.svg?height=120&width=180&text=Object+Detection", + icon: , + }, + { + id: "cv-2", + name: "语义分割(多边形)", + category: "Computer Vision", + description: "使用多边形精确标注图像中的区域", + type: "image", + preview: "/placeholder.svg?height=120&width=180&text=Polygon+Segmentation", + icon: , + }, + { + id: "cv-3", + name: "语义分割(掩码)", + category: "Computer Vision", + description: "使用像素级掩码标注图像区域", + type: "image", + preview: "/placeholder.svg?height=120&width=180&text=Mask+Segmentation", + icon: , + }, + { + id: "cv-4", + name: "关键点标注", + category: "Computer Vision", + description: "标注图像中的关键点位置", + type: "image", + preview: "/placeholder.svg?height=120&width=180&text=Keypoint+Labeling", + icon: , + }, + { + id: "cv-5", + name: "图像分类", + category: "Computer Vision", + description: "为整个图像分配类别标签", + type: "image", + preview: "/placeholder.svg?height=120&width=180&text=Image+Classification", + icon: , + }, + { + id: "cv-6", + name: "实例分割", + category: "Computer Vision", + description: "区分同类别的不同实例对象", + type: "image", + preview: "/placeholder.svg?height=120&width=180&text=Instance+Segmentation", + icon: , + }, + { + id: "cv-7", + name: "全景分割", + category: "Computer Vision", + description: "结合语义分割和实例分割的全景标注", + type: "image", + preview: "/placeholder.svg?height=120&width=180&text=Panoptic+Segmentation", + icon: , + }, + { + id: "cv-8", + name: "3D目标检测", + category: "Computer Vision", + description: "在3D空间中标注目标对象的位置和方向", + type: "image", + preview: "/placeholder.svg?height=120&width=180&text=3D+Object+Detection", + icon: , + }, + { + id: "cv-9", + name: "图像配对", + category: "Computer Vision", + description: "标注图像之间的对应关系", + type: "image", + preview: "/placeholder.svg?height=120&width=180&text=Image+Matching", + icon: , + }, + { + id: "cv-10", + name: "图像质量评估", + category: "Computer Vision", + description: "评估和标注图像质量等级", + type: "image", + preview: "/placeholder.svg?height=120&width=180&text=Quality+Assessment", + icon: , + }, + { + id: "cv-11", + name: "图像裁剪标注", + category: "Computer Vision", + description: "标注图像中需要裁剪的区域", + type: "image", + preview: "/placeholder.svg?height=120&width=180&text=Image+Cropping", + icon: , + }, + { + id: "cv-12", + name: "图像旋转标注", + category: "Computer Vision", + description: "标注图像的正确方向角度", + type: "image", + preview: "/placeholder.svg?height=120&width=180&text=Image+Rotation", + icon: , + }, + // 自然语言处理模板 + { + id: "nlp-1", + name: "文本分类", + category: "Natural Language Processing", + description: "为文本分配类别标签", + type: "text", + icon: , + }, + { + id: "nlp-2", + name: "命名实体识别", + category: "Natural Language Processing", + description: "识别和标注文本中的实体", + type: "text", + icon: , + }, + { + id: "nlp-3", + name: "情感分析", + category: "Natural Language Processing", + description: "标注文本的情感倾向", + type: "text", + icon: , + }, + { + id: "nlp-4", + name: "问答标注", + category: "Natural Language Processing", + description: "标注问题和答案对", + type: "text", + icon: , + }, + { + id: "nlp-5", + name: "文本摘要", + category: "Natural Language Processing", + description: "为长文本创建摘要标注", + type: "text", + icon: , + }, + { + id: "nlp-6", + name: "对话标注", + category: "Natural Language Processing", + description: "标注对话中的意图和实体", + type: "text", + icon: , + }, + { + id: "nlp-7", + name: "关系抽取", + category: "Natural Language Processing", + description: "标注实体之间的关系", + type: "text", + icon: , + }, + { + id: "nlp-8", + name: "文本相似度", + category: "Natural Language Processing", + description: "标注文本之间的相似度", + type: "text", + icon: , + }, + { + id: "nlp-9", + name: "语言检测", + category: "Natural Language Processing", + description: "识别和标注文本的语言类型", + type: "text", + icon: , + }, + { + id: "nlp-10", + name: "文本纠错", + category: "Natural Language Processing", + description: "标注文本中的错误并提供修正", + type: "text", + icon: , + }, ] \ No newline at end of file diff --git a/frontend/src/mock/evaluation.tsx b/frontend/src/mock/evaluation.tsx index 41bb0ba9c..5caad2da5 100644 --- a/frontend/src/mock/evaluation.tsx +++ b/frontend/src/mock/evaluation.tsx @@ -1,290 +1,290 @@ -// 预设评估维度配置 -export const presetEvaluationDimensions: EvaluationDimension[] = [ - { - id: "answer_relevance", - name: "回答相关性", - description: "评估回答内容是否针对问题,是否切中要点", - category: "accuracy", - isEnabled: true, - }, - { - id: "content_quality", - name: "内容质量", - description: "评估内容的准确性、完整性和可读性", - category: "quality", - isEnabled: true, - }, - { - id: "information_completeness", - name: "信息完整性", - description: "评估信息是否完整,无缺失关键内容", - category: "completeness", - isEnabled: true, - }, - { - id: "language_fluency", - name: "语言流畅性", - description: "评估语言表达是否流畅自然", - category: "quality", - isEnabled: true, - }, - { - id: "factual_accuracy", - name: "事实准确性", - description: "评估内容中事实信息的准确性", - category: "accuracy", - isEnabled: true, - }, -] - - -export const sliceOperators: SliceOperator[] = [ - { - id: "paragraph-split", - name: "段落分割", - description: "按段落自然分割文档", - type: "text", - icon: "📄", - params: { minLength: 50, maxLength: 1000 }, - }, - { - id: "sentence-split", - name: "句子分割", - description: "按句子边界分割文档", - type: "text", - icon: "📝", - params: { maxSentences: 5, overlap: 1 }, - }, - { - id: "semantic-split", - name: "语义分割", - description: "基于语义相似度智能分割", - type: "semantic", - icon: "🧠", - params: { threshold: 0.7, windowSize: 3 }, - }, - { - id: "length-split", - name: "长度分割", - description: "按固定字符长度分割", - type: "text", - icon: "📏", - params: { chunkSize: 512, overlap: 50 }, - }, - { - id: "structure-split", - name: "结构化分割", - description: "按文档结构(标题、章节)分割", - type: "structure", - icon: "🏗️", - params: { preserveHeaders: true, minSectionLength: 100 }, - }, - { - id: "table-extract", - name: "表格提取", - description: "提取并单独处理表格内容", - type: "structure", - icon: "📊", - params: { includeHeaders: true, mergeRows: false }, - }, - { - id: "code-extract", - name: "代码提取", - description: "识别并提取代码块", - type: "custom", - icon: "💻", - params: { languages: ["python", "javascript", "sql"], preserveIndentation: true }, - }, - { - id: "qa-extract", - name: "问答提取", - description: "自动识别问答格式内容", - type: "semantic", - icon: "❓", - params: { confidenceThreshold: 0.8, generateAnswers: true }, - }, -] - - -export const mockTasks: EvaluationTask[] = [ - { - id: "1", - name: "客服对话数据质量评估", - datasetId: "1", - datasetName: "客服对话数据集", - evaluationType: "model", - status: "completed", - score: 85, - progress: 100, - createdAt: "2024-01-15 14:30", - completedAt: "2024-01-15 14:45", - description: "评估客服对话数据的质量,包括对话完整性、回复准确性等维度", - dimensions: ["answer_relevance", "content_quality", "information_completeness"], - customDimensions: [], - sliceConfig: { - threshold: 0.8, - sampleCount: 100, - method: "语义分割", - }, - modelConfig: { - url: "https://api.openai.com/v1/chat/completions", - apiKey: "sk-***", - prompt: "请从数据质量、标签准确性、标注一致性三个维度评估这个客服对话数据集...", - temperature: 0.3, - maxTokens: 2000, - }, - metrics: { - accuracy: 88, - completeness: 92, - consistency: 78, - relevance: 85, - }, - issues: [ - { type: "重复数据", count: 23, severity: "medium" }, - { type: "格式错误", count: 5, severity: "high" }, - { type: "内容不完整", count: 12, severity: "low" }, - ], - }, - { - id: "2", - name: "产品评论人工评估", - datasetId: "2", - datasetName: "产品评论数据集", - evaluationType: "manual", - status: "pending", - progress: 0, - createdAt: "2024-01-15 15:20", - description: "人工评估产品评论数据的情感标注准确性", - dimensions: ["content_quality", "factual_accuracy"], - customDimensions: [ - { - id: "custom_1", - name: "情感极性准确性", - description: "评估情感标注的极性(正面/负面/中性)准确性", - category: "custom", - isCustom: true, - isEnabled: true, - }, - ], - sliceConfig: { - threshold: 0.7, - sampleCount: 50, - method: "段落分割", - }, - metrics: { - accuracy: 0, - completeness: 0, - consistency: 0, - relevance: 0, - }, - issues: [], - }, - { - id: "3", - name: "新闻分类数据评估", - datasetId: "4", - datasetName: "新闻分类数据集", - evaluationType: "manual", - status: "running", - progress: 65, - createdAt: "2024-01-15 16:10", - description: "人工评估新闻分类数据集的标注质量", - dimensions: ["content_quality", "information_completeness", "factual_accuracy"], - customDimensions: [], - sliceConfig: { - threshold: 0.9, - sampleCount: 80, - method: "句子分割", - }, - metrics: { - accuracy: 82, - completeness: 78, - consistency: 85, - relevance: 80, - }, - issues: [{ type: "标注不一致", count: 15, severity: "medium" }], - }, -] - -// 模拟QA对数据 -export const mockQAPairs: QAPair[] = [ - { - id: "qa_1", - question: "这个产品的退货政策是什么?", - answer: "我们提供7天无理由退货服务,商品需要保持原包装完整。", - sliceId: "slice_1", - score: 4.5, - feedback: "回答准确且完整", - }, - { - id: "qa_2", - question: "如何联系客服?", - answer: "您可以通过在线客服、电话400-123-4567或邮箱service@company.com联系我们。", - sliceId: "slice_2", - score: 5.0, - feedback: "提供了多种联系方式,非常全面", - }, - { - id: "qa_3", - question: "配送时间需要多久?", - answer: "一般情况下,我们会在1-3个工作日内发货,配送时间根据地区不同为2-7天。", - sliceId: "slice_3", - score: 4.0, - feedback: "时间范围说明清楚", - }, -] -// 评估维度模板配置 -export const evaluationTemplates = { - dialogue_text: { - name: "对话文本评估", - dimensions: [ - { - id: "answer_relevance", - name: "回答是否有针对性", - description: "评估回答内容是否针对问题,是否切中要点", - category: "accuracy" as const, - isEnabled: true, - }, - { - id: "question_correctness", - name: "问题是否正确", - description: "评估问题表述是否清晰、准确、合理", - category: "quality" as const, - isEnabled: true, - }, - { - id: "answer_independence", - name: "回答是否独立", - description: "评估回答是否独立完整,不依赖外部信息", - category: "completeness" as const, - isEnabled: true, - }, - ], - }, - data_quality: { - name: "数据质量评估", - dimensions: [ - { - id: "data_quality", - name: "数据质量", - description: "评估数据的整体质量,包括格式规范性、完整性等", - category: "quality" as const, - isEnabled: true, - }, - { - id: "label_accuracy", - name: "标签准确性", - description: "评估数据标签的准确性和一致性", - category: "accuracy" as const, - isEnabled: true, - }, - { - id: "data_completeness", - name: "数据完整性", - description: "评估数据集的完整性,是否存在缺失数据", - category: "completeness" as const, - isEnabled: true, - }, - ], - }, +// 预设评估维度配置 +export const presetEvaluationDimensions: EvaluationDimension[] = [ + { + id: "answer_relevance", + name: "回答相关性", + description: "评估回答内容是否针对问题,是否切中要点", + category: "accuracy", + isEnabled: true, + }, + { + id: "content_quality", + name: "内容质量", + description: "评估内容的准确性、完整性和可读性", + category: "quality", + isEnabled: true, + }, + { + id: "information_completeness", + name: "信息完整性", + description: "评估信息是否完整,无缺失关键内容", + category: "completeness", + isEnabled: true, + }, + { + id: "language_fluency", + name: "语言流畅性", + description: "评估语言表达是否流畅自然", + category: "quality", + isEnabled: true, + }, + { + id: "factual_accuracy", + name: "事实准确性", + description: "评估内容中事实信息的准确性", + category: "accuracy", + isEnabled: true, + }, +] + + +export const sliceOperators: SliceOperator[] = [ + { + id: "paragraph-split", + name: "段落分割", + description: "按段落自然分割文档", + type: "text", + icon: "📄", + params: { minLength: 50, maxLength: 1000 }, + }, + { + id: "sentence-split", + name: "句子分割", + description: "按句子边界分割文档", + type: "text", + icon: "📝", + params: { maxSentences: 5, overlap: 1 }, + }, + { + id: "semantic-split", + name: "语义分割", + description: "基于语义相似度智能分割", + type: "semantic", + icon: "🧠", + params: { threshold: 0.7, windowSize: 3 }, + }, + { + id: "length-split", + name: "长度分割", + description: "按固定字符长度分割", + type: "text", + icon: "📏", + params: { chunkSize: 512, overlap: 50 }, + }, + { + id: "structure-split", + name: "结构化分割", + description: "按文档结构(标题、章节)分割", + type: "structure", + icon: "🏗️", + params: { preserveHeaders: true, minSectionLength: 100 }, + }, + { + id: "table-extract", + name: "表格提取", + description: "提取并单独处理表格内容", + type: "structure", + icon: "📊", + params: { includeHeaders: true, mergeRows: false }, + }, + { + id: "code-extract", + name: "代码提取", + description: "识别并提取代码块", + type: "custom", + icon: "💻", + params: { languages: ["python", "javascript", "sql"], preserveIndentation: true }, + }, + { + id: "qa-extract", + name: "问答提取", + description: "自动识别问答格式内容", + type: "semantic", + icon: "❓", + params: { confidenceThreshold: 0.8, generateAnswers: true }, + }, +] + + +export const mockTasks: EvaluationTask[] = [ + { + id: "1", + name: "客服对话数据质量评估", + datasetId: "1", + datasetName: "客服对话数据集", + evaluationType: "model", + status: "completed", + score: 85, + progress: 100, + createdAt: "2024-01-15 14:30", + completedAt: "2024-01-15 14:45", + description: "评估客服对话数据的质量,包括对话完整性、回复准确性等维度", + dimensions: ["answer_relevance", "content_quality", "information_completeness"], + customDimensions: [], + sliceConfig: { + threshold: 0.8, + sampleCount: 100, + method: "语义分割", + }, + modelConfig: { + url: "https://api.openai.com/v1/chat/completions", + apiKey: "sk-***", + prompt: "请从数据质量、标签准确性、标注一致性三个维度评估这个客服对话数据集...", + temperature: 0.3, + maxTokens: 2000, + }, + metrics: { + accuracy: 88, + completeness: 92, + consistency: 78, + relevance: 85, + }, + issues: [ + { type: "重复数据", count: 23, severity: "medium" }, + { type: "格式错误", count: 5, severity: "high" }, + { type: "内容不完整", count: 12, severity: "low" }, + ], + }, + { + id: "2", + name: "产品评论人工评估", + datasetId: "2", + datasetName: "产品评论数据集", + evaluationType: "manual", + status: "pending", + progress: 0, + createdAt: "2024-01-15 15:20", + description: "人工评估产品评论数据的情感标注准确性", + dimensions: ["content_quality", "factual_accuracy"], + customDimensions: [ + { + id: "custom_1", + name: "情感极性准确性", + description: "评估情感标注的极性(正面/负面/中性)准确性", + category: "custom", + isCustom: true, + isEnabled: true, + }, + ], + sliceConfig: { + threshold: 0.7, + sampleCount: 50, + method: "段落分割", + }, + metrics: { + accuracy: 0, + completeness: 0, + consistency: 0, + relevance: 0, + }, + issues: [], + }, + { + id: "3", + name: "新闻分类数据评估", + datasetId: "4", + datasetName: "新闻分类数据集", + evaluationType: "manual", + status: "running", + progress: 65, + createdAt: "2024-01-15 16:10", + description: "人工评估新闻分类数据集的标注质量", + dimensions: ["content_quality", "information_completeness", "factual_accuracy"], + customDimensions: [], + sliceConfig: { + threshold: 0.9, + sampleCount: 80, + method: "句子分割", + }, + metrics: { + accuracy: 82, + completeness: 78, + consistency: 85, + relevance: 80, + }, + issues: [{ type: "标注不一致", count: 15, severity: "medium" }], + }, +] + +// 模拟QA对数据 +export const mockQAPairs: QAPair[] = [ + { + id: "qa_1", + question: "这个产品的退货政策是什么?", + answer: "我们提供7天无理由退货服务,商品需要保持原包装完整。", + sliceId: "slice_1", + score: 4.5, + feedback: "回答准确且完整", + }, + { + id: "qa_2", + question: "如何联系客服?", + answer: "您可以通过在线客服、电话400-123-4567或邮箱service@company.com联系我们。", + sliceId: "slice_2", + score: 5.0, + feedback: "提供了多种联系方式,非常全面", + }, + { + id: "qa_3", + question: "配送时间需要多久?", + answer: "一般情况下,我们会在1-3个工作日内发货,配送时间根据地区不同为2-7天。", + sliceId: "slice_3", + score: 4.0, + feedback: "时间范围说明清楚", + }, +] +// 评估维度模板配置 +export const evaluationTemplates = { + dialogue_text: { + name: "对话文本评估", + dimensions: [ + { + id: "answer_relevance", + name: "回答是否有针对性", + description: "评估回答内容是否针对问题,是否切中要点", + category: "accuracy" as const, + isEnabled: true, + }, + { + id: "question_correctness", + name: "问题是否正确", + description: "评估问题表述是否清晰、准确、合理", + category: "quality" as const, + isEnabled: true, + }, + { + id: "answer_independence", + name: "回答是否独立", + description: "评估回答是否独立完整,不依赖外部信息", + category: "completeness" as const, + isEnabled: true, + }, + ], + }, + data_quality: { + name: "数据质量评估", + dimensions: [ + { + id: "data_quality", + name: "数据质量", + description: "评估数据的整体质量,包括格式规范性、完整性等", + category: "quality" as const, + isEnabled: true, + }, + { + id: "label_accuracy", + name: "标签准确性", + description: "评估数据标签的准确性和一致性", + category: "accuracy" as const, + isEnabled: true, + }, + { + id: "data_completeness", + name: "数据完整性", + description: "评估数据集的完整性,是否存在缺失数据", + category: "completeness" as const, + isEnabled: true, + }, + ], + }, } \ No newline at end of file diff --git a/frontend/src/mock/knowledgeBase.tsx b/frontend/src/mock/knowledgeBase.tsx index dbfc968d0..b2b9fb59f 100644 --- a/frontend/src/mock/knowledgeBase.tsx +++ b/frontend/src/mock/knowledgeBase.tsx @@ -1,254 +1,254 @@ -export const mockChunks = Array.from({ length: 23 }, (_, i) => ({ - id: i + 1, - content: `这是第 ${ - i + 1 - } 个文档分块的内容示例。在实际应用中,这里会显示从原始文档中提取和分割的具体文本内容。用户可以在这里查看和编辑分块的内容,确保知识库的质量和准确性。这个分块包含了重要的业务信息和技术细节,需要仔细维护以确保检索的准确性。`, - position: i + 1, - tokens: Math.floor(Math.random() * 200) + 100, - embedding: Array.from({ length: 1536 }, () => Math.random() - 0.5), - similarity: (Math.random() * 0.3 + 0.7).toFixed(3), - createdAt: "2024-01-22 10:35", - updatedAt: "2024-01-22 10:35", - vectorId: `vec_${i + 1}_${Math.random().toString(36).substr(2, 9)}`, - sliceOperator: ["semantic-split", "paragraph-split", "table-extract"][ - Math.floor(Math.random() * 3) - ], - parentChunkId: i > 0 ? Math.floor(Math.random() * i) + 1 : undefined, - metadata: { - source: "API文档.pdf", - page: Math.floor(i / 5) + 1, - section: `第${Math.floor(i / 3) + 1}章`, - }, -})); - -export const mockQAPairs = [ - { - id: 1, - question: "什么是API文档的主要用途?", - answer: - "API文档的主要用途是为开发者提供详细的接口说明,包括请求参数、响应格式和使用示例.", - }, - { - id: 2, - question: "如何正确使用这个API?", - answer: - "使用API时需要先获取访问令牌,然后按照文档中的格式发送请求,注意处理错误响应.", - }, -]; - -export const sliceOperators: SliceOperator[] = [ - { - id: "paragraph-split", - name: "段落分割", - description: "按段落自然分割文档", - type: "text", - icon: "📄", - params: { minLength: 50, maxLength: 1000 }, - }, - { - id: "sentence-split", - name: "句子分割", - description: "按句子边界分割文档", - type: "text", - icon: "📝", - params: { maxSentences: 5, overlap: 1 }, - }, - { - id: "semantic-split", - name: "语义分割", - description: "基于语义相似度智能分割", - type: "semantic", - icon: "🧠", - params: { threshold: 0.7, windowSize: 3 }, - }, - { - id: "length-split", - name: "长度分割", - description: "按固定字符长度分割", - type: "text", - icon: "📏", - params: { chunkSize: 512, overlap: 50 }, - }, - { - id: "structure-split", - name: "结构化分割", - description: "按文档结构(标题、章节)分割", - type: "structure", - icon: "🏗️", - params: { preserveHeaders: true, minSectionLength: 100 }, - }, - { - id: "table-extract", - name: "表格提取", - description: "提取并单独处理表格内容", - type: "structure", - icon: "📊", - params: { includeHeaders: true, mergeRows: false }, - }, - { - id: "code-extract", - name: "代码提取", - description: "识别并提取代码块", - type: "custom", - icon: "💻", - params: { - languages: ["python", "javascript", "sql"], - preserveIndentation: true, - }, - }, - { - id: "qa-extract", - name: "问答提取", - description: "自动识别问答格式内容", - type: "semantic", - icon: "❓", - params: { confidenceThreshold: 0.8, generateAnswers: true }, - }, -]; - -export const vectorDatabases = [ - { - id: "pinecone", - name: "Pinecone", - description: "云端向量数据库,高性能检索", - }, - { - id: "weaviate", - name: "Weaviate", - description: "开源向量数据库,支持多模态", - }, - { id: "qdrant", name: "Qdrant", description: "高性能向量搜索引擎" }, - { id: "chroma", name: "ChromaDB", description: "轻量级向量数据库" }, - { id: "milvus", name: "Milvus", description: "分布式向量数据库" }, - { id: "faiss", name: "FAISS", description: "Facebook AI 相似性搜索库" }, -]; - -export const mockKnowledgeBases: KnowledgeBase[] = [ - { - id: 1, - name: "产品技术文档库", - description: - "包含所有产品相关的技术文档和API说明,支持多种格式文档的智能解析和向量化处理", - type: "unstructured", - status: "ready", - fileCount: 45, - chunkCount: 1250, - vectorCount: 1250, - size: "2.3 GB", - progress: 100, - createdAt: "2024-01-15", - lastUpdated: "2024-01-22", - vectorDatabase: "pinecone", - config: { - embeddingModel: "text-embedding-3-large", - llmModel: "gpt-4o", - chunkSize: 512, - overlap: 50, - sliceMethod: "semantic", - enableQA: true, - vectorDimension: 1536, - sliceOperators: ["semantic-split", "paragraph-split", "table-extract"], - }, - files: [ - { - id: 1, - name: "API文档.pdf", - type: "pdf", - size: "2.5 MB", - status: "completed", - chunkCount: 156, - progress: 100, - uploadedAt: "2024-01-15", - source: "upload", - vectorizationStatus: "completed", - }, - { - id: 2, - name: "用户手册.docx", - type: "docx", - size: "1.8 MB", - status: "disabled", - chunkCount: 89, - progress: 65, - uploadedAt: "2024-01-22", - source: "dataset", - datasetId: "dataset-1", - vectorizationStatus: "failed", - }, - ], - vectorizationHistory: [ - { - id: 1, - timestamp: "2024-01-22 14:30:00", - operation: "create", - fileId: 1, - fileName: "API文档.pdf", - chunksProcessed: 156, - vectorsGenerated: 156, - status: "success", - duration: "2m 15s", - config: { - embeddingModel: "text-embedding-3-large", - chunkSize: 512, - sliceMethod: "semantic", - }, - }, - { - id: 2, - timestamp: "2024-01-22 15:45:00", - operation: "update", - fileId: 2, - fileName: "用户手册.docx", - chunksProcessed: 89, - vectorsGenerated: 0, - status: "failed", - duration: "0m 45s", - config: { - embeddingModel: "text-embedding-3-large", - chunkSize: 512, - sliceMethod: "semantic", - }, - error: "向量化服务连接超时", - }, - ], - }, - { - id: 2, - name: "FAQ结构化知识库", - description: "客服常见问题的结构化问答对,支持快速检索和智能匹配", - type: "structured", - status: "vectorizing", - fileCount: 12, - chunkCount: 890, - vectorCount: 750, - size: "156 MB", - progress: 75, - createdAt: "2024-01-20", - lastUpdated: "2024-01-23", - vectorDatabase: "weaviate", - config: { - embeddingModel: "text-embedding-ada-002", - chunkSize: 256, - overlap: 0, - sliceMethod: "paragraph", - enableQA: false, - vectorDimension: 1536, - sliceOperators: ["qa-extract", "paragraph-split"], - }, - files: [ - { - id: 3, - name: "FAQ模板.xlsx", - type: "xlsx", - size: "450 KB", - status: "vectorizing", - chunkCount: 234, - progress: 75, - uploadedAt: "2024-01-20", - source: "upload", - vectorizationStatus: "processing", - }, - ], - vectorizationHistory: [], - }, -]; +export const mockChunks = Array.from({ length: 23 }, (_, i) => ({ + id: i + 1, + content: `这是第 ${ + i + 1 + } 个文档分块的内容示例。在实际应用中,这里会显示从原始文档中提取和分割的具体文本内容。用户可以在这里查看和编辑分块的内容,确保知识库的质量和准确性。这个分块包含了重要的业务信息和技术细节,需要仔细维护以确保检索的准确性。`, + position: i + 1, + tokens: Math.floor(Math.random() * 200) + 100, + embedding: Array.from({ length: 1536 }, () => Math.random() - 0.5), + similarity: (Math.random() * 0.3 + 0.7).toFixed(3), + createdAt: "2024-01-22 10:35", + updatedAt: "2024-01-22 10:35", + vectorId: `vec_${i + 1}_${Math.random().toString(36).substr(2, 9)}`, + sliceOperator: ["semantic-split", "paragraph-split", "table-extract"][ + Math.floor(Math.random() * 3) + ], + parentChunkId: i > 0 ? Math.floor(Math.random() * i) + 1 : undefined, + metadata: { + source: "API文档.pdf", + page: Math.floor(i / 5) + 1, + section: `第${Math.floor(i / 3) + 1}章`, + }, +})); + +export const mockQAPairs = [ + { + id: 1, + question: "什么是API文档的主要用途?", + answer: + "API文档的主要用途是为开发者提供详细的接口说明,包括请求参数、响应格式和使用示例.", + }, + { + id: 2, + question: "如何正确使用这个API?", + answer: + "使用API时需要先获取访问令牌,然后按照文档中的格式发送请求,注意处理错误响应.", + }, +]; + +export const sliceOperators: SliceOperator[] = [ + { + id: "paragraph-split", + name: "段落分割", + description: "按段落自然分割文档", + type: "text", + icon: "📄", + params: { minLength: 50, maxLength: 1000 }, + }, + { + id: "sentence-split", + name: "句子分割", + description: "按句子边界分割文档", + type: "text", + icon: "📝", + params: { maxSentences: 5, overlap: 1 }, + }, + { + id: "semantic-split", + name: "语义分割", + description: "基于语义相似度智能分割", + type: "semantic", + icon: "🧠", + params: { threshold: 0.7, windowSize: 3 }, + }, + { + id: "length-split", + name: "长度分割", + description: "按固定字符长度分割", + type: "text", + icon: "📏", + params: { chunkSize: 512, overlap: 50 }, + }, + { + id: "structure-split", + name: "结构化分割", + description: "按文档结构(标题、章节)分割", + type: "structure", + icon: "🏗️", + params: { preserveHeaders: true, minSectionLength: 100 }, + }, + { + id: "table-extract", + name: "表格提取", + description: "提取并单独处理表格内容", + type: "structure", + icon: "📊", + params: { includeHeaders: true, mergeRows: false }, + }, + { + id: "code-extract", + name: "代码提取", + description: "识别并提取代码块", + type: "custom", + icon: "💻", + params: { + languages: ["python", "javascript", "sql"], + preserveIndentation: true, + }, + }, + { + id: "qa-extract", + name: "问答提取", + description: "自动识别问答格式内容", + type: "semantic", + icon: "❓", + params: { confidenceThreshold: 0.8, generateAnswers: true }, + }, +]; + +export const vectorDatabases = [ + { + id: "pinecone", + name: "Pinecone", + description: "云端向量数据库,高性能检索", + }, + { + id: "weaviate", + name: "Weaviate", + description: "开源向量数据库,支持多模态", + }, + { id: "qdrant", name: "Qdrant", description: "高性能向量搜索引擎" }, + { id: "chroma", name: "ChromaDB", description: "轻量级向量数据库" }, + { id: "milvus", name: "Milvus", description: "分布式向量数据库" }, + { id: "faiss", name: "FAISS", description: "Facebook AI 相似性搜索库" }, +]; + +export const mockKnowledgeBases: KnowledgeBase[] = [ + { + id: 1, + name: "产品技术文档库", + description: + "包含所有产品相关的技术文档和API说明,支持多种格式文档的智能解析和向量化处理", + type: "unstructured", + status: "ready", + fileCount: 45, + chunkCount: 1250, + vectorCount: 1250, + size: "2.3 GB", + progress: 100, + createdAt: "2024-01-15", + lastUpdated: "2024-01-22", + vectorDatabase: "pinecone", + config: { + embeddingModel: "text-embedding-3-large", + llmModel: "gpt-4o", + chunkSize: 512, + overlap: 50, + sliceMethod: "semantic", + enableQA: true, + vectorDimension: 1536, + sliceOperators: ["semantic-split", "paragraph-split", "table-extract"], + }, + files: [ + { + id: 1, + name: "API文档.pdf", + type: "pdf", + size: "2.5 MB", + status: "completed", + chunkCount: 156, + progress: 100, + uploadedAt: "2024-01-15", + source: "upload", + vectorizationStatus: "completed", + }, + { + id: 2, + name: "用户手册.docx", + type: "docx", + size: "1.8 MB", + status: "disabled", + chunkCount: 89, + progress: 65, + uploadedAt: "2024-01-22", + source: "dataset", + datasetId: "dataset-1", + vectorizationStatus: "failed", + }, + ], + vectorizationHistory: [ + { + id: 1, + timestamp: "2024-01-22 14:30:00", + operation: "create", + fileId: 1, + fileName: "API文档.pdf", + chunksProcessed: 156, + vectorsGenerated: 156, + status: "success", + duration: "2m 15s", + config: { + embeddingModel: "text-embedding-3-large", + chunkSize: 512, + sliceMethod: "semantic", + }, + }, + { + id: 2, + timestamp: "2024-01-22 15:45:00", + operation: "update", + fileId: 2, + fileName: "用户手册.docx", + chunksProcessed: 89, + vectorsGenerated: 0, + status: "failed", + duration: "0m 45s", + config: { + embeddingModel: "text-embedding-3-large", + chunkSize: 512, + sliceMethod: "semantic", + }, + error: "向量化服务连接超时", + }, + ], + }, + { + id: 2, + name: "FAQ结构化知识库", + description: "客服常见问题的结构化问答对,支持快速检索和智能匹配", + type: "structured", + status: "vectorizing", + fileCount: 12, + chunkCount: 890, + vectorCount: 750, + size: "156 MB", + progress: 75, + createdAt: "2024-01-20", + lastUpdated: "2024-01-23", + vectorDatabase: "weaviate", + config: { + embeddingModel: "text-embedding-ada-002", + chunkSize: 256, + overlap: 0, + sliceMethod: "paragraph", + enableQA: false, + vectorDimension: 1536, + sliceOperators: ["qa-extract", "paragraph-split"], + }, + files: [ + { + id: 3, + name: "FAQ模板.xlsx", + type: "xlsx", + size: "450 KB", + status: "vectorizing", + chunkCount: 234, + progress: 75, + uploadedAt: "2024-01-20", + source: "upload", + vectorizationStatus: "processing", + }, + ], + vectorizationHistory: [], + }, +]; diff --git a/frontend/src/mock/mock-apis.cjs b/frontend/src/mock/mock-apis.cjs index 8b1a02bfa..c219608aa 100644 --- a/frontend/src/mock/mock-apis.cjs +++ b/frontend/src/mock/mock-apis.cjs @@ -1,167 +1,167 @@ -const { addMockPrefix } = require("./mock-core/util.cjs"); - -const MockAPI = { - // 数据归集接口 - queryTasksUsingGet: "/data-collection/tasks", // 获取数据源任务列表 - createTaskUsingPost: "/data-collection/tasks", // 创建数据源任务 - queryTaskByIdUsingGet: "/data-collection/tasks/:id", // 根据ID获取数据源任务详情 - updateTaskByIdUsingPut: "/data-collection/tasks/:id", // 更新数据源任务 - queryDataXTemplatesUsingGet: "/data-collection/templates", // 获取DataX数据源模板列表 - deleteTaskByIdUsingDelete: "/data-collection/tasks/:id", // 删除数据源任务 - executeTaskByIdUsingPost: "/data-collection/tasks/:id/execute", // 执行数据源任务 - stopTaskByIdUsingPost: "/data-collection/tasks/:id/stop", // 停止数据源任务 - queryExecutionLogUsingPost: "/data-collection/executions", // 获取任务执行日志 - queryExecutionLogByIdUsingGet: "/data-collection/executions/:id", // 获取任务执行日志详情 - queryCollectionStatisticsUsingGet: "/data-collection/monitor/statistics", // 获取数据归集统计信息 - - // 数据管理接口 - queryDatasetsUsingGet: "/data-management/datasets", // 获取数据集列表 - createDatasetUsingPost: "/data-management/datasets", // 创建数据集 - queryDatasetByIdUsingGet: "/data-management/datasets/:id", // 根据ID获取数据集详情 - updateDatasetByIdUsingPut: "/data-management/datasets/:id", // 更新数据集 - deleteDatasetByIdUsingDelete: "/data-management/datasets/:id", // 删除数据集 - queryFilesUsingGet: "/data-management/datasets/:id/files", // 获取数据集文件列表 - uploadFileUsingPost: "/data-management/datasets/:id/files", // 添加数据集文件 - queryFileByIdUsingGet: "/data-management/datasets/:id/files/:fileId", // 获取数据集文件详情 - deleteFileByIdUsingDelete: "/data-management/datasets/:id/files/:fileId", // 删除数据集文件 - downloadFileByIdUsingGet: - "/data-management/datasets/:id/files/:fileId/download", // 下载文件 - queryDatasetTypesUsingGet: "/data-management/dataset-types", // 获取数据集类型列表 - queryTagsUsingGet: "/data-management/tags", // 获取数据集标签列表 - createTagUsingPost: "/data-management/tags", // 创建数据集标签 - updateTagUsingPost: "/data-management/tags", // 更新数据集标签 - deleteTagUsingPost: "/data-management/tags", // 删除数据集标签 - queryDatasetStatisticsUsingGet: "/data-management/datasets/statistics", // 获取数据集统计信息 - preUploadFileUsingPost: "/data-management/datasets/:id/upload/pre-upload", // 预上传文件 - cancelUploadUsingPut: "/data-management/datasets/upload/cancel-upload/:id", // 取消上传 - uploadFileChunkUsingPost: "/data-management/datasets/:id/upload/chunk", // 上传切片 - - // 数据清洗接口 - queryCleaningTasksUsingGet: "/cleaning/tasks", // 获取清洗任务列表 - createCleaningTaskUsingPost: "/cleaning/tasks", // 创建清洗任务 - queryCleaningTaskByIdUsingGet: "/cleaning/tasks/:taskId", // 根据ID获取清洗任务详情 - deleteCleaningTaskByIdUsingDelete: "/cleaning/tasks/:taskId", // 删除清洗任务 - executeCleaningTaskUsingPost: "/cleaning/tasks/:taskId/execute", // 执行清洗任务 - stopCleaningTaskUsingPost: "/cleaning/tasks/:taskId/stop", // 停止清洗任务 - queryCleaningTemplatesUsingGet: "/cleaning/templates", // 获取清洗模板列表 - createCleaningTemplateUsingPost: "/cleaning/templates", // 创建清洗模板 - queryCleaningTemplateByIdUsingGet: "/cleaning/templates/:templateId", // 根据ID获取清洗模板详情 - updateCleaningTemplateByIdUsingPut: "/cleaning/templates/:templateId", // 根据ID更新清洗模板详情 - deleteCleaningTemplateByIdUsingDelete: "/cleaning/templates/:templateId", // 删除清洗模板 - - // 数据标注接口 - queryAnnotationTasksUsingGet: "/project/mappings/list", // 获取标注任务列表 - createAnnotationTaskUsingPost: "/project/create", // 创建标注任务 - syncAnnotationTaskByIdUsingPost: "/project/sync", // 同步标注任务 - deleteAnnotationTaskByIdUsingDelete: "/project/mappings", // 删除标注任务 - queryAnnotationTaskByIdUsingGet: "/annotation/tasks/:taskId", // 根据ID获取标注任务详情 - executeAnnotationTaskByIdUsingPost: "/annotation/tasks/:taskId/execute", // 执行标注任务 - stopAnnotationTaskByIdUsingPost: "/annotation/tasks/:taskId/stop", // 停止标注任务 - queryAnnotationDataUsingGet: "/annotation/data", // 获取标注数据列表 - submitAnnotationUsingPost: "/annotation/submit/:id", // 提交标注 - updateAnnotationUsingPut: "/annotation/update/:id", // 根据ID更新标注 - deleteAnnotationUsingDelete: "/annotation/delete/:id", // 根据ID删除标注 - startAnnotationTaskUsingPost: "/annotation/start/:taskId", // 开始标注任务 - pauseAnnotationTaskUsingPost: "/annotation/pause/:taskId", // 暂停标注任务 - resumeAnnotationTaskUsingPost: "/annotation/resume/:taskId", // 恢复标注任务 - completeAnnotationTaskUsingPost: "/annotation/complete/:taskId", // 完成标注任务 - getAnnotationTaskStatisticsUsingGet: "/annotation/statistics/:taskId", // 获取标注任务统计信息 - getAnnotationStatisticsUsingGet: "/annotation/statistics", // 获取标注统计信息 - queryAnnotationTemplatesUsingGet: "/annotation/templates", // 获取标注模板列表 - createAnnotationTemplateUsingPost: "/annotation/templates", // 创建标注模板 - queryAnnotationTemplateByIdUsingGet: "/annotation/templates/:templateId", // 根据ID获取标注模板详情 - queryAnnotatorsUsingGet: "/annotation/annotators", // 获取标注者列表 - assignAnnotatorUsingPost: "/annotation/annotators/:annotatorId", // 分配标注者 - - // 数据合成接口 - querySynthesisJobsUsingGet: "/synthesis/jobs", // 获取合成任务列表 - createSynthesisJobUsingPost: "/synthesis/jobs/create", // 创建合成任务 - querySynthesisJobByIdUsingGet: "/synthesis/jobs/:jobId", // 根据ID获取合成任务详情 - updateSynthesisJobByIdUsingPut: "/synthesis/jobs/:jobId", // 更新合成任务 - deleteSynthesisJobByIdUsingDelete: "/synthesis/jobs/:jobId", // 删除合成任务 - executeSynthesisJobUsingPost: "/synthesis/jobs/execute/:jobId", // 执行合成任务 - stopSynthesisJobByIdUsingPost: "/synthesis/jobs/stop/:jobId", // 停止合成任务 - querySynthesisTemplatesUsingGet: "/synthesis/templates", // 获取合成模板列表 - createSynthesisTemplateUsingPost: "/synthesis/templates/create", // 创建合成模板 - querySynthesisTemplateByIdUsingGet: "/synthesis/templates/:templateId", // 根据ID获取合成模板详情 - updateSynthesisTemplateByIdUsingPut: "/synthesis/templates/:templateId", // 更新合成模板 - deleteSynthesisTemplateByIdUsingDelete: "/synthesis/templates/:templateId", // 删除合成模板 - queryInstructionTemplatesUsingPost: "/synthesis/templates", // 获取指令模板列表 - createInstructionTemplateUsingPost: "/synthesis/templates/create", // 创建指令模板 - queryInstructionTemplateByIdUsingGet: "/synthesis/templates/:templateId", // 根据ID获取指令模板详情 - deleteInstructionTemplateByIdUsingDelete: "/synthesis/templates/:templateId", // 删除指令模板 - instructionTuningUsingPost: "/synthesis/instruction-tuning", // 指令微调 - cotDistillationUsingPost: "/synthesis/cot-distillation", // Cot蒸馏 - - // 数据配比接口 - createRatioTaskUsingPost: "/synthesis/ratio-task", // 创建配比任务 - queryRatioTasksUsingGet: "/synthesis/ratio-task", // 获取配比任务列表 - queryRatioTaskByIdUsingGet: "/synthesis/ratio-task/:taskId", // 根据ID获取配比任务详情 - deleteRatioTaskByIdUsingDelete: "/synthesis/ratio-task/:taskId", // 删除配比任务 - updateRatioTaskByIdUsingPut: "/synthesis/ratio-task/:taskId", // 更新配比任务 - executeRatioTaskByIdUsingPost: "/synthesis/ratio-task/:taskId/execute", // 执行配比任务 - stopRatioTaskByIdUsingPost: "/synthesis/ratio-task/:taskId/stop", // 停止配比任务 - queryRatioJobStatusUsingGet: "/synthesis/ratio-task/:taskId/status", // 获取配比任务状态 - queryRatioModelsUsingGet: "/synthesis/ratio-models", // 获取配比模型列表 - - // 数据评测接口 - queryEvaluationTasksUsingPost: "/evaluation/tasks", // 获取评测任务列表 - createEvaluationTaskUsingPost: "/evaluation/tasks/create", // 创建评测任务 - queryEvaluationTaskByIdUsingGet: "/evaluation/tasks/:taskId", // 根据ID获取评测任务详情 - updateEvaluationTaskByIdUsingPut: "/evaluation/tasks/:taskId", // 更新评测任务 - deleteEvaluationTaskByIdUsingDelete: "/evaluation/tasks/:taskId", // 删除评测任务 - executeEvaluationTaskByIdUsingPost: "/evaluation/tasks/:taskId/execute", // 执行评测任务 - stopEvaluationTaskByIdUsingPost: "/evaluation/tasks/:taskId/stop", // 停止评测任务 - queryEvaluationReportsUsingPost: "/evaluation/reports", // 获取评测报告列表 - queryEvaluationReportByIdUsingGet: "/evaluation/reports/:reportId", // 根据ID获取评测报告详情 - manualEvaluateUsingPost: "/evaluation/manual-evaluate", // 人工评测 - queryEvaluationStatisticsUsingGet: "/evaluation/statistics", // 获取评测统计信息 - evaluateDataQualityUsingPost: "/evaluation/data-quality", // 数据质量评测 - getQualityEvaluationByIdUsingGet: "/evaluation/data-quality/:id", // 根据ID获取数据质量评测详情 - evaluateCompatibilityUsingPost: "/evaluation/compatibility", // 兼容性评测 - evaluateValueUsingPost: "/evaluation/value", // 价值评测 - queryEvaluationReportsUsingGet: "/evaluation/reports", // 获取评测报告列表(简化版) - getEvaluationReportByIdUsingGet: "/evaluation/reports/:reportId", // 根据ID获取评测报告详情(简化版) - exportEvaluationReportUsingGet: "/evaluation/reports/:reportId/export", // 导出评测报告 - batchEvaluationUsingPost: "/evaluation/batch-evaluate", // 批量评测 - - // 知识生成接口 - queryKnowledgeBasesUsingPost: "/knowledge-base/list", // 获取知识库列表 - createKnowledgeBaseUsingPost: "/knowledge-base/create", // 创建知识库 - queryKnowledgeBaseByIdUsingGet: "/knowledge-base/:baseId", // 根据ID获取知识库详情 - updateKnowledgeBaseByIdUsingPut: "/knowledge-base/:baseId", // 更新知识库 - deleteKnowledgeBaseByIdUsingDelete: "/knowledge-base/:baseId", // 删除知识库 - addKnowledgeBaseFilesUsingPost: "/knowledge-base/:baseId/files", // 添加文件到知识库 - queryKnowledgeBaseFilesGet: "/knowledge-base/:baseId/files", // 根据ID获取知识生成文件列表 - queryKnowledgeBaseFilesByIdUsingGet: - "/knowledge-base/:baseId/files/:fileId", // 根据ID获取知识生成文件详情 - deleteKnowledgeBaseTaskByIdUsingDelete: "/knowledge-base/:baseId/files/:id", // 删除知识生成文件 - - // 算子市场 - queryOperatorsUsingPost: "/operators/list", // 获取算子列表 - queryCategoryTreeUsingGet: "/categories/tree", // 获取算子分类树 - queryOperatorByIdUsingGet: "/operators/:id", // 根据ID获取算子详情 - createOperatorUsingPost: "/operators/create", // 创建算子 - updateOperatorByIdUsingPut: "/operators/:id", // 更新算子 - uploadOperatorUsingPost: "/operators/upload", // 上传算子 - uploadFileChunkUsingPost: "/operators/upload/chunk", // 上传切片 - preUploadOperatorUsingPost: "/operators/upload/pre-upload", // 预上传文件 - cancelUploadOperatorUsingPut: "/operators/upload/cancel-upload", // 取消上传 - - createLabelUsingPost: "/operators/labels", // 创建算子标签 - queryLabelsUsingGet: "/labels", // 获取算子标签列表 - deleteLabelsUsingDelete: "/labels", // 删除算子标签 - updateLabelByIdUsingPut: "/labels/:labelId", // 更新算子标签 - deleteOperatorByIdUsingDelete: "/operators/:operatorId", // 删除算子 - publishOperatorUsingPost: "/operators/:operatorId/publish", // 发布算子 - unpublishOperatorUsingPost: "/operators/:operatorId/unpublish", // 下架算子 - - // 设置接口 - queryModelsUsingGet: "/models/list", // 获取模型列表 - queryProvidersUsingGet: "/models/providers", // 获取模型提供商列表 - createModelUsingPost: "/models/create", // 创建模型 - updateModelUsingPut: "/models/:id", // 更新模型 - deleteModelUsingDelete: "/models/:id", // 删除模型 -}; - -module.exports = addMockPrefix("/api", MockAPI); +const { addMockPrefix } = require("./mock-core/util.cjs"); + +const MockAPI = { + // 数据归集接口 + queryTasksUsingGet: "/data-collection/tasks", // 获取数据源任务列表 + createTaskUsingPost: "/data-collection/tasks", // 创建数据源任务 + queryTaskByIdUsingGet: "/data-collection/tasks/:id", // 根据ID获取数据源任务详情 + updateTaskByIdUsingPut: "/data-collection/tasks/:id", // 更新数据源任务 + queryDataXTemplatesUsingGet: "/data-collection/templates", // 获取DataX数据源模板列表 + deleteTaskByIdUsingDelete: "/data-collection/tasks/:id", // 删除数据源任务 + executeTaskByIdUsingPost: "/data-collection/tasks/:id/execute", // 执行数据源任务 + stopTaskByIdUsingPost: "/data-collection/tasks/:id/stop", // 停止数据源任务 + queryExecutionLogUsingPost: "/data-collection/executions", // 获取任务执行日志 + queryExecutionLogByIdUsingGet: "/data-collection/executions/:id", // 获取任务执行日志详情 + queryCollectionStatisticsUsingGet: "/data-collection/monitor/statistics", // 获取数据归集统计信息 + + // 数据管理接口 + queryDatasetsUsingGet: "/data-management/datasets", // 获取数据集列表 + createDatasetUsingPost: "/data-management/datasets", // 创建数据集 + queryDatasetByIdUsingGet: "/data-management/datasets/:id", // 根据ID获取数据集详情 + updateDatasetByIdUsingPut: "/data-management/datasets/:id", // 更新数据集 + deleteDatasetByIdUsingDelete: "/data-management/datasets/:id", // 删除数据集 + queryFilesUsingGet: "/data-management/datasets/:id/files", // 获取数据集文件列表 + uploadFileUsingPost: "/data-management/datasets/:id/files", // 添加数据集文件 + queryFileByIdUsingGet: "/data-management/datasets/:id/files/:fileId", // 获取数据集文件详情 + deleteFileByIdUsingDelete: "/data-management/datasets/:id/files/:fileId", // 删除数据集文件 + downloadFileByIdUsingGet: + "/data-management/datasets/:id/files/:fileId/download", // 下载文件 + queryDatasetTypesUsingGet: "/data-management/dataset-types", // 获取数据集类型列表 + queryTagsUsingGet: "/data-management/tags", // 获取数据集标签列表 + createTagUsingPost: "/data-management/tags", // 创建数据集标签 + updateTagUsingPost: "/data-management/tags", // 更新数据集标签 + deleteTagUsingPost: "/data-management/tags", // 删除数据集标签 + queryDatasetStatisticsUsingGet: "/data-management/datasets/statistics", // 获取数据集统计信息 + preUploadFileUsingPost: "/data-management/datasets/:id/upload/pre-upload", // 预上传文件 + cancelUploadUsingPut: "/data-management/datasets/upload/cancel-upload/:id", // 取消上传 + uploadFileChunkUsingPost: "/data-management/datasets/:id/upload/chunk", // 上传切片 + + // 数据清洗接口 + queryCleaningTasksUsingGet: "/cleaning/tasks", // 获取清洗任务列表 + createCleaningTaskUsingPost: "/cleaning/tasks", // 创建清洗任务 + queryCleaningTaskByIdUsingGet: "/cleaning/tasks/:taskId", // 根据ID获取清洗任务详情 + deleteCleaningTaskByIdUsingDelete: "/cleaning/tasks/:taskId", // 删除清洗任务 + executeCleaningTaskUsingPost: "/cleaning/tasks/:taskId/execute", // 执行清洗任务 + stopCleaningTaskUsingPost: "/cleaning/tasks/:taskId/stop", // 停止清洗任务 + queryCleaningTemplatesUsingGet: "/cleaning/templates", // 获取清洗模板列表 + createCleaningTemplateUsingPost: "/cleaning/templates", // 创建清洗模板 + queryCleaningTemplateByIdUsingGet: "/cleaning/templates/:templateId", // 根据ID获取清洗模板详情 + updateCleaningTemplateByIdUsingPut: "/cleaning/templates/:templateId", // 根据ID更新清洗模板详情 + deleteCleaningTemplateByIdUsingDelete: "/cleaning/templates/:templateId", // 删除清洗模板 + + // 数据标注接口 + queryAnnotationTasksUsingGet: "/project/mappings/list", // 获取标注任务列表 + createAnnotationTaskUsingPost: "/project/create", // 创建标注任务 + syncAnnotationTaskByIdUsingPost: "/project/sync", // 同步标注任务 + deleteAnnotationTaskByIdUsingDelete: "/project/mappings", // 删除标注任务 + queryAnnotationTaskByIdUsingGet: "/annotation/tasks/:taskId", // 根据ID获取标注任务详情 + executeAnnotationTaskByIdUsingPost: "/annotation/tasks/:taskId/execute", // 执行标注任务 + stopAnnotationTaskByIdUsingPost: "/annotation/tasks/:taskId/stop", // 停止标注任务 + queryAnnotationDataUsingGet: "/annotation/data", // 获取标注数据列表 + submitAnnotationUsingPost: "/annotation/submit/:id", // 提交标注 + updateAnnotationUsingPut: "/annotation/update/:id", // 根据ID更新标注 + deleteAnnotationUsingDelete: "/annotation/delete/:id", // 根据ID删除标注 + startAnnotationTaskUsingPost: "/annotation/start/:taskId", // 开始标注任务 + pauseAnnotationTaskUsingPost: "/annotation/pause/:taskId", // 暂停标注任务 + resumeAnnotationTaskUsingPost: "/annotation/resume/:taskId", // 恢复标注任务 + completeAnnotationTaskUsingPost: "/annotation/complete/:taskId", // 完成标注任务 + getAnnotationTaskStatisticsUsingGet: "/annotation/statistics/:taskId", // 获取标注任务统计信息 + getAnnotationStatisticsUsingGet: "/annotation/statistics", // 获取标注统计信息 + queryAnnotationTemplatesUsingGet: "/annotation/templates", // 获取标注模板列表 + createAnnotationTemplateUsingPost: "/annotation/templates", // 创建标注模板 + queryAnnotationTemplateByIdUsingGet: "/annotation/templates/:templateId", // 根据ID获取标注模板详情 + queryAnnotatorsUsingGet: "/annotation/annotators", // 获取标注者列表 + assignAnnotatorUsingPost: "/annotation/annotators/:annotatorId", // 分配标注者 + + // 数据合成接口 + querySynthesisJobsUsingGet: "/synthesis/jobs", // 获取合成任务列表 + createSynthesisJobUsingPost: "/synthesis/jobs/create", // 创建合成任务 + querySynthesisJobByIdUsingGet: "/synthesis/jobs/:jobId", // 根据ID获取合成任务详情 + updateSynthesisJobByIdUsingPut: "/synthesis/jobs/:jobId", // 更新合成任务 + deleteSynthesisJobByIdUsingDelete: "/synthesis/jobs/:jobId", // 删除合成任务 + executeSynthesisJobUsingPost: "/synthesis/jobs/execute/:jobId", // 执行合成任务 + stopSynthesisJobByIdUsingPost: "/synthesis/jobs/stop/:jobId", // 停止合成任务 + querySynthesisTemplatesUsingGet: "/synthesis/templates", // 获取合成模板列表 + createSynthesisTemplateUsingPost: "/synthesis/templates/create", // 创建合成模板 + querySynthesisTemplateByIdUsingGet: "/synthesis/templates/:templateId", // 根据ID获取合成模板详情 + updateSynthesisTemplateByIdUsingPut: "/synthesis/templates/:templateId", // 更新合成模板 + deleteSynthesisTemplateByIdUsingDelete: "/synthesis/templates/:templateId", // 删除合成模板 + queryInstructionTemplatesUsingPost: "/synthesis/templates", // 获取指令模板列表 + createInstructionTemplateUsingPost: "/synthesis/templates/create", // 创建指令模板 + queryInstructionTemplateByIdUsingGet: "/synthesis/templates/:templateId", // 根据ID获取指令模板详情 + deleteInstructionTemplateByIdUsingDelete: "/synthesis/templates/:templateId", // 删除指令模板 + instructionTuningUsingPost: "/synthesis/instruction-tuning", // 指令微调 + cotDistillationUsingPost: "/synthesis/cot-distillation", // Cot蒸馏 + + // 数据配比接口 + createRatioTaskUsingPost: "/synthesis/ratio-task", // 创建配比任务 + queryRatioTasksUsingGet: "/synthesis/ratio-task", // 获取配比任务列表 + queryRatioTaskByIdUsingGet: "/synthesis/ratio-task/:taskId", // 根据ID获取配比任务详情 + deleteRatioTaskByIdUsingDelete: "/synthesis/ratio-task/:taskId", // 删除配比任务 + updateRatioTaskByIdUsingPut: "/synthesis/ratio-task/:taskId", // 更新配比任务 + executeRatioTaskByIdUsingPost: "/synthesis/ratio-task/:taskId/execute", // 执行配比任务 + stopRatioTaskByIdUsingPost: "/synthesis/ratio-task/:taskId/stop", // 停止配比任务 + queryRatioJobStatusUsingGet: "/synthesis/ratio-task/:taskId/status", // 获取配比任务状态 + queryRatioModelsUsingGet: "/synthesis/ratio-models", // 获取配比模型列表 + + // 数据评测接口 + queryEvaluationTasksUsingPost: "/evaluation/tasks", // 获取评测任务列表 + createEvaluationTaskUsingPost: "/evaluation/tasks/create", // 创建评测任务 + queryEvaluationTaskByIdUsingGet: "/evaluation/tasks/:taskId", // 根据ID获取评测任务详情 + updateEvaluationTaskByIdUsingPut: "/evaluation/tasks/:taskId", // 更新评测任务 + deleteEvaluationTaskByIdUsingDelete: "/evaluation/tasks/:taskId", // 删除评测任务 + executeEvaluationTaskByIdUsingPost: "/evaluation/tasks/:taskId/execute", // 执行评测任务 + stopEvaluationTaskByIdUsingPost: "/evaluation/tasks/:taskId/stop", // 停止评测任务 + queryEvaluationReportsUsingPost: "/evaluation/reports", // 获取评测报告列表 + queryEvaluationReportByIdUsingGet: "/evaluation/reports/:reportId", // 根据ID获取评测报告详情 + manualEvaluateUsingPost: "/evaluation/manual-evaluate", // 人工评测 + queryEvaluationStatisticsUsingGet: "/evaluation/statistics", // 获取评测统计信息 + evaluateDataQualityUsingPost: "/evaluation/data-quality", // 数据质量评测 + getQualityEvaluationByIdUsingGet: "/evaluation/data-quality/:id", // 根据ID获取数据质量评测详情 + evaluateCompatibilityUsingPost: "/evaluation/compatibility", // 兼容性评测 + evaluateValueUsingPost: "/evaluation/value", // 价值评测 + queryEvaluationReportsUsingGet: "/evaluation/reports", // 获取评测报告列表(简化版) + getEvaluationReportByIdUsingGet: "/evaluation/reports/:reportId", // 根据ID获取评测报告详情(简化版) + exportEvaluationReportUsingGet: "/evaluation/reports/:reportId/export", // 导出评测报告 + batchEvaluationUsingPost: "/evaluation/batch-evaluate", // 批量评测 + + // 知识生成接口 + queryKnowledgeBasesUsingPost: "/knowledge-base/list", // 获取知识库列表 + createKnowledgeBaseUsingPost: "/knowledge-base/create", // 创建知识库 + queryKnowledgeBaseByIdUsingGet: "/knowledge-base/:baseId", // 根据ID获取知识库详情 + updateKnowledgeBaseByIdUsingPut: "/knowledge-base/:baseId", // 更新知识库 + deleteKnowledgeBaseByIdUsingDelete: "/knowledge-base/:baseId", // 删除知识库 + addKnowledgeBaseFilesUsingPost: "/knowledge-base/:baseId/files", // 添加文件到知识库 + queryKnowledgeBaseFilesGet: "/knowledge-base/:baseId/files", // 根据ID获取知识生成文件列表 + queryKnowledgeBaseFilesByIdUsingGet: + "/knowledge-base/:baseId/files/:fileId", // 根据ID获取知识生成文件详情 + deleteKnowledgeBaseTaskByIdUsingDelete: "/knowledge-base/:baseId/files/:id", // 删除知识生成文件 + + // 算子市场 + queryOperatorsUsingPost: "/operators/list", // 获取算子列表 + queryCategoryTreeUsingGet: "/categories/tree", // 获取算子分类树 + queryOperatorByIdUsingGet: "/operators/:id", // 根据ID获取算子详情 + createOperatorUsingPost: "/operators/create", // 创建算子 + updateOperatorByIdUsingPut: "/operators/:id", // 更新算子 + uploadOperatorUsingPost: "/operators/upload", // 上传算子 + uploadFileChunkUsingPost: "/operators/upload/chunk", // 上传切片 + preUploadOperatorUsingPost: "/operators/upload/pre-upload", // 预上传文件 + cancelUploadOperatorUsingPut: "/operators/upload/cancel-upload", // 取消上传 + + createLabelUsingPost: "/operators/labels", // 创建算子标签 + queryLabelsUsingGet: "/labels", // 获取算子标签列表 + deleteLabelsUsingDelete: "/labels", // 删除算子标签 + updateLabelByIdUsingPut: "/labels/:labelId", // 更新算子标签 + deleteOperatorByIdUsingDelete: "/operators/:operatorId", // 删除算子 + publishOperatorUsingPost: "/operators/:operatorId/publish", // 发布算子 + unpublishOperatorUsingPost: "/operators/:operatorId/unpublish", // 下架算子 + + // 设置接口 + queryModelsUsingGet: "/models/list", // 获取模型列表 + queryProvidersUsingGet: "/models/providers", // 获取模型提供商列表 + createModelUsingPost: "/models/create", // 创建模型 + updateModelUsingPut: "/models/:id", // 更新模型 + deleteModelUsingDelete: "/models/:id", // 删除模型 +}; + +module.exports = addMockPrefix("/api", MockAPI); diff --git a/frontend/src/mock/mock-core/module-loader.cjs b/frontend/src/mock/mock-core/module-loader.cjs index 32cc778f0..4084fc1ed 100644 --- a/frontend/src/mock/mock-core/module-loader.cjs +++ b/frontend/src/mock/mock-core/module-loader.cjs @@ -1,25 +1,25 @@ -const fs = require('fs'); - -function loadAllMockModules(router, pathDir) { - if (!fs.existsSync(pathDir)) { - throw new Error(`Mock directory ${pathDir} does not exist.`); - } - - const files = fs.readdirSync(pathDir); - files.forEach(file => { - const filePath = `${pathDir}/${file}`; - if(fs.lstatSync(filePath).isDirectory()) { - loadAllMockModules(router, filePath); - } else { - let fileNameModule = file.replace('/\.js\b$/', ''); - let module = require(`${pathDir}/${fileNameModule}`); - if(typeof module === 'function' && module.length === 1) { - module(router); - } - } - }); -} - -module.exports = { - loadAllMockModules, +const fs = require('fs'); + +function loadAllMockModules(router, pathDir) { + if (!fs.existsSync(pathDir)) { + throw new Error(`Mock directory ${pathDir} does not exist.`); + } + + const files = fs.readdirSync(pathDir); + files.forEach(file => { + const filePath = `${pathDir}/${file}`; + if(fs.lstatSync(filePath).isDirectory()) { + loadAllMockModules(router, filePath); + } else { + let fileNameModule = file.replace('/\.js\b$/', ''); + let module = require(`${pathDir}/${fileNameModule}`); + if(typeof module === 'function' && module.length === 1) { + module(router); + } + } + }); +} + +module.exports = { + loadAllMockModules, }; \ No newline at end of file diff --git a/frontend/src/mock/mock-core/session-helper.cjs b/frontend/src/mock/mock-core/session-helper.cjs index b01ea237b..d92f382c9 100644 --- a/frontend/src/mock/mock-core/session-helper.cjs +++ b/frontend/src/mock/mock-core/session-helper.cjs @@ -1,63 +1,63 @@ -const path = require("path"); -const Mock = require("mockjs"); -const session = require("express-session"); -const FileStore = require("session-file-store")(session); - -const { isFunction } = require("lodash"); - -const argv = require("minimist")(process.argv.slice(2)); -const isDev = (argv.env || "development") === "development"; -const TOKEN_KEY = isDev ? "X-Auth-Token" : "X-Csrf-Token"; - -const setSessionUser = (req, getLoginInfo) => { - if (!isFunction(getLoginInfo)) { - throw new Error("getLoginInfo must be a function"); - } - - if (!req.session?.users) { - req.session.users = {}; - } - - let token = req.get(TOKEN_KEY); - const { users } = req.session; - if (!token || !users[token]) { - token = Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""); - const userInfo = getLoginInfo(req) || {}; - users[token] = user; - } - return token; -}; - -const getSessionUser = (req) => { - const token = req.get(TOKEN_KEY); - if (token && req.session?.users) { - return req.session.users[token]; - } - return null; -}; - -const genExpressSession = () => { - return session({ - name: "demo.name", - secret: "demo.secret", - resave: true, - saveUninitialized: true, - cookie: { - maxAge: 60 * 60 * 1e3, - expires: new Date(Date.now() + 60 * 60 * 1e3), - }, // 1 hour - store: new FileStore({ - path: path.join(__dirname, "../sessions"), - retries: 0, - keyFunction: (secret, sessionId) => { - return secret + sessionId; - }, - }), - }); -}; - -module.exports = { - setSessionUser, - getSessionUser, - genExpressSession, -}; +const path = require("path"); +const Mock = require("mockjs"); +const session = require("express-session"); +const FileStore = require("session-file-store")(session); + +const { isFunction } = require("lodash"); + +const argv = require("minimist")(process.argv.slice(2)); +const isDev = (argv.env || "development") === "development"; +const TOKEN_KEY = isDev ? "X-Auth-Token" : "X-Csrf-Token"; + +const setSessionUser = (req, getLoginInfo) => { + if (!isFunction(getLoginInfo)) { + throw new Error("getLoginInfo must be a function"); + } + + if (!req.session?.users) { + req.session.users = {}; + } + + let token = req.get(TOKEN_KEY); + const { users } = req.session; + if (!token || !users[token]) { + token = Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""); + const userInfo = getLoginInfo(req) || {}; + users[token] = user; + } + return token; +}; + +const getSessionUser = (req) => { + const token = req.get(TOKEN_KEY); + if (token && req.session?.users) { + return req.session.users[token]; + } + return null; +}; + +const genExpressSession = () => { + return session({ + name: "demo.name", + secret: "demo.secret", + resave: true, + saveUninitialized: true, + cookie: { + maxAge: 60 * 60 * 1e3, + expires: new Date(Date.now() + 60 * 60 * 1e3), + }, // 1 hour + store: new FileStore({ + path: path.join(__dirname, "../sessions"), + retries: 0, + keyFunction: (secret, sessionId) => { + return secret + sessionId; + }, + }), + }); +}; + +module.exports = { + setSessionUser, + getSessionUser, + genExpressSession, +}; diff --git a/frontend/src/mock/mock-core/util.cjs b/frontend/src/mock/mock-core/util.cjs index 327f7c224..ef4a065f9 100644 --- a/frontend/src/mock/mock-core/util.cjs +++ b/frontend/src/mock/mock-core/util.cjs @@ -1,30 +1,30 @@ - -function log(message, type = "log", provided = 'console') { - const providedFn = globalThis[provided] || console; - if (providedFn && typeof providedFn[type] === 'function') { - const invokeMethod = providedFn[type ?? 'log']; - invokeMethod.call(providedFn, message); - } -} - -function addMockPrefix(urlPrefix, api) { - const newMockApi = {}; - Object.keys(api).map(apiKey=>{ - newMockApi[apiKey] = urlPrefix + api[apiKey]; - }); - - return new Proxy(newMockApi, { - get(target, prop) { - if (prop in target) { - return target[prop]; - } else { - throw new Error(`API ${String(prop)} is not defined.`); - } - } - }) -} - -module.exports = { - log, - addMockPrefix, + +function log(message, type = "log", provided = 'console') { + const providedFn = globalThis[provided] || console; + if (providedFn && typeof providedFn[type] === 'function') { + const invokeMethod = providedFn[type ?? 'log']; + invokeMethod.call(providedFn, message); + } +} + +function addMockPrefix(urlPrefix, api) { + const newMockApi = {}; + Object.keys(api).map(apiKey=>{ + newMockApi[apiKey] = urlPrefix + api[apiKey]; + }); + + return new Proxy(newMockApi, { + get(target, prop) { + if (prop in target) { + return target[prop]; + } else { + throw new Error(`API ${String(prop)} is not defined.`); + } + } + }) +} + +module.exports = { + log, + addMockPrefix, }; \ No newline at end of file diff --git a/frontend/src/mock/mock-middleware/error-handle-middleware.cjs b/frontend/src/mock/mock-middleware/error-handle-middleware.cjs index 272c0ae88..d1e50c89f 100644 --- a/frontend/src/mock/mock-middleware/error-handle-middleware.cjs +++ b/frontend/src/mock/mock-middleware/error-handle-middleware.cjs @@ -1,13 +1,13 @@ -const errorHandle = (err, req, res, next) => { - if(res.headersSent) { - return next(err); - } - console.error('Server Error:', err.message); - res.status(500).json({ - code: '500', - msg: 'Internal Server Error', - data: null, - }); -}; - -module.exports = errorHandle; +const errorHandle = (err, req, res, next) => { + if(res.headersSent) { + return next(err); + } + console.error('Server Error:', err.message); + res.status(500).json({ + code: '500', + msg: 'Internal Server Error', + data: null, + }); +}; + +module.exports = errorHandle; diff --git a/frontend/src/mock/mock-middleware/index.cjs b/frontend/src/mock/mock-middleware/index.cjs index e9f2ff0f0..01c9e567a 100644 --- a/frontend/src/mock/mock-middleware/index.cjs +++ b/frontend/src/mock/mock-middleware/index.cjs @@ -1,11 +1,11 @@ -const setHeader = require('./set-header-middleware.cjs'); -const strongMatch = require('./strong-match-middleware.cjs'); -const sendJSON = require('./send-json-middleawre.cjs'); -const errorHandle = require('./error-handle-middleware.cjs'); - -module.exports = { - setHeader, - strongMatch, - sendJSON, - errorHandle, +const setHeader = require('./set-header-middleware.cjs'); +const strongMatch = require('./strong-match-middleware.cjs'); +const sendJSON = require('./send-json-middleawre.cjs'); +const errorHandle = require('./error-handle-middleware.cjs'); + +module.exports = { + setHeader, + strongMatch, + sendJSON, + errorHandle, }; \ No newline at end of file diff --git a/frontend/src/mock/mock-middleware/send-json-middleawre.cjs b/frontend/src/mock/mock-middleware/send-json-middleawre.cjs index a7a493f6f..b6a1a47b4 100644 --- a/frontend/src/mock/mock-middleware/send-json-middleawre.cjs +++ b/frontend/src/mock/mock-middleware/send-json-middleawre.cjs @@ -1,18 +1,18 @@ -const sendJSON = (req, res, next) => { - res.sendJSON = ( - data = null, - { code = '0', msg = 'success', statusCode = 200, timeout = 0 } = {} - ) => { - const timer = setTimeout(() => { - res.status(statusCode).json({ - code, - msg, - data, - }); - clearTimeout(timer); - }, timeout); - }; - next(); -}; - +const sendJSON = (req, res, next) => { + res.sendJSON = ( + data = null, + { code = '0', msg = 'success', statusCode = 200, timeout = 0 } = {} + ) => { + const timer = setTimeout(() => { + res.status(statusCode).json({ + code, + msg, + data, + }); + clearTimeout(timer); + }, timeout); + }; + next(); +}; + module.exports = sendJSON; \ No newline at end of file diff --git a/frontend/src/mock/mock-middleware/set-header-middleware.cjs b/frontend/src/mock/mock-middleware/set-header-middleware.cjs index 49694e470..821c6c3bb 100644 --- a/frontend/src/mock/mock-middleware/set-header-middleware.cjs +++ b/frontend/src/mock/mock-middleware/set-header-middleware.cjs @@ -1,14 +1,14 @@ -const setHeader = (req, res, next) => { - res.set({ - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE,OPTIONS', - 'Access-Control-Allow-Headers': 'Content-Type, Authorization', - 'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src *; font-src 'self';", - 'X-Content-Type-Options': 'nosniff', - 'X-Frame-Options': 'SAMEORIGIN', - 'X-XSS-Protection': '1; mode=block', - }); - next(); -}; - +const setHeader = (req, res, next) => { + res.set({ + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE,OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization', + 'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src *; font-src 'self';", + 'X-Content-Type-Options': 'nosniff', + 'X-Frame-Options': 'SAMEORIGIN', + 'X-XSS-Protection': '1; mode=block', + }); + next(); +}; + module.exports = setHeader; \ No newline at end of file diff --git a/frontend/src/mock/mock-middleware/strong-match-middleware.cjs b/frontend/src/mock/mock-middleware/strong-match-middleware.cjs index 8d0a1be8e..a11813e3f 100644 --- a/frontend/src/mock/mock-middleware/strong-match-middleware.cjs +++ b/frontend/src/mock/mock-middleware/strong-match-middleware.cjs @@ -1,13 +1,13 @@ -const API = require('../mock-apis.cjs'); - -const strongMatch = (req, res, next) => { - res.strongMatch = () => { - const { url } = req; - const index = url.indexOf('?'); - const targetUrl = index !== -1 ? url.substring(0, index) : url; - const isExistedUrl = Object.values(API).includes(targetUrl); - return isExistedUrl; - }; - next(); -}; +const API = require('../mock-apis.cjs'); + +const strongMatch = (req, res, next) => { + res.strongMatch = () => { + const { url } = req; + const index = url.indexOf('?'); + const targetUrl = index !== -1 ? url.substring(0, index) : url; + const isExistedUrl = Object.values(API).includes(targetUrl); + return isExistedUrl; + }; + next(); +}; module.exports = strongMatch; \ No newline at end of file diff --git a/frontend/src/mock/mock-seed/data-annotation.cjs b/frontend/src/mock/mock-seed/data-annotation.cjs index be8fe88a8..6ba179916 100644 --- a/frontend/src/mock/mock-seed/data-annotation.cjs +++ b/frontend/src/mock/mock-seed/data-annotation.cjs @@ -1,618 +1,618 @@ -const Mock = require("mockjs"); -const API = require("../mock-apis.cjs"); - -// 标注任务数据 -function annotationTaskItem() { - return { - source_dataset_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - mapping_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - labelling_project_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - labelling_project_name: Mock.Random.ctitle(5, 20), - created_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - last_updated_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - deleted_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - // id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - // name: Mock.Random.ctitle(5, 20), - // description: Mock.Random.csentence(5, 30), - // type: Mock.Random.pick([ - // "TEXT_CLASSIFICATION", - // "NAMED_ENTITY_RECOGNITION", - // "OBJECT_DETECTION", - // "SEMANTIC_SEGMENTATION", - // ]), - // status: Mock.Random.pick(["PENDING", "IN_PROGRESS", "COMPLETED", "PAUSED"]), - // datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - // progress: Mock.Random.float(0, 100, 2, 2), - // createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - // updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - // createdBy: Mock.Random.cname(), - // assignedTo: Mock.Random.cname(), - // totalDataCount: Mock.Random.integer(100, 10000), - // annotatedCount: Mock.Random.integer(10, 500), - // configuration: { - // labels: Mock.Random.shuffle([ - // "正面", - // "负面", - // "中性", - // "人物", - // "地点", - // "组织", - // "时间", - // ]).slice(0, Mock.Random.integer(3, 5)), - // guidelines: Mock.Random.csentence(10, 50), - // qualityThreshold: Mock.Random.float(0.8, 1.0, 2, 2), - // }, - // statistics: { - // accuracy: Mock.Random.float(0.85, 0.99, 2, 2), - // averageTime: Mock.Random.integer(30, 300), // seconds - // reviewCount: Mock.Random.integer(0, 50), - // }, - }; -} - -const annotationTaskList = new Array(25).fill(null).map(annotationTaskItem); - -// 标注数据项 -function annotationDataItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - taskId: Mock.Random.pick(annotationTaskList).id, - content: Mock.Random.cparagraph(1, 3), - originalData: { - text: Mock.Random.cparagraph(1, 3), - source: Mock.Random.url(), - metadata: { - author: Mock.Random.cname(), - timestamp: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - }, - }, - annotations: [ - { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - label: Mock.Random.pick(["正面", "负面", "中性"]), - confidence: Mock.Random.float(0.7, 1.0, 2, 2), - annotator: Mock.Random.cname(), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - isPreAnnotation: Mock.Random.boolean(), - }, - ], - status: Mock.Random.pick(["PENDING", "ANNOTATED", "REVIEWED", "REJECTED"]), - priority: Mock.Random.integer(1, 5), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - }; -} - -const annotationDataList = new Array(200).fill(null).map(annotationDataItem); - -// 标注模板数据 -function annotationTemplateItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.ctitle(5, 15), - description: Mock.Random.csentence(5, 25), - type: Mock.Random.pick([ - "TEXT_CLASSIFICATION", - "NAMED_ENTITY_RECOGNITION", - "OBJECT_DETECTION", - "SEMANTIC_SEGMENTATION", - ]), - category: Mock.Random.ctitle(3, 8), - labels: Mock.Random.shuffle([ - "正面", - "负面", - "中性", - "人物", - "地点", - "组织", - "时间", - "产品", - "服务", - ]).slice(0, Mock.Random.integer(3, 6)), - guidelines: Mock.Random.csentence(10, 50), - usageCount: Mock.Random.integer(0, 100), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - createdBy: Mock.Random.cname(), - }; -} - -const annotationTemplateList = new Array(15) - .fill(null) - .map(annotationTemplateItem); - -// 标注者数据 -function annotatorItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.cname(), - email: Mock.Random.email(), - role: Mock.Random.pick(["ANNOTATOR", "REVIEWER", "ADMIN"]), - skillLevel: Mock.Random.pick(["BEGINNER", "INTERMEDIATE", "EXPERT"]), - specialties: Mock.Random.shuffle([ - "文本分类", - "命名实体识别", - "目标检测", - "语义分割", - ]).slice(0, Mock.Random.integer(1, 3)), - statistics: { - totalAnnotations: Mock.Random.integer(100, 5000), - accuracy: Mock.Random.float(0.85, 0.99, 2, 2), - averageSpeed: Mock.Random.integer(50, 200), // annotations per hour - totalWorkTime: Mock.Random.integer(10, 500), // hours - }, - status: Mock.Random.pick(["ACTIVE", "INACTIVE", "SUSPENDED"]), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - }; -} - -const annotatorList = new Array(20).fill(null).map(annotatorItem); - -module.exports = function (router) { - // 获取标注任务列表 - router.get(API.queryAnnotationTasksUsingGet, (req, res) => { - const { page = 0, size = 20, status, type } = req.query; - let filteredTasks = annotationTaskList; - - if (status) { - filteredTasks = filteredTasks.filter((task) => task.status === status); - } - - if (type) { - filteredTasks = filteredTasks.filter((task) => task.type === type); - } - - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = filteredTasks.slice(startIndex, endIndex); - - res.send({ - code: "0", - msg: "Success", - data: { - content: pageData, - totalElements: filteredTasks.length, - totalPages: Math.ceil(filteredTasks.length / size), - size: parseInt(size), - number: parseInt(page), - first: page == 0, - last: page >= Math.ceil(filteredTasks.length / size) - 1, - }, - }); - }); - - // 创建标注任务 - router.post(API.createAnnotationTaskUsingPost, (req, res) => { - const newTask = { - ...annotationTaskItem(), - ...req.body, - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - status: "PENDING", - progress: 0, - annotatedCount: 0, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - annotationTaskList.push(newTask); - - res.status(201).send({ - code: "0", - msg: "Annotation task created successfully", - data: newTask, - }); - }); - - // 获取标注任务详情 - router.get(API.queryAnnotationTaskByIdUsingGet, (req, res) => { - const { taskId } = req.params; - const task = annotationTaskList.find((t) => t.id === taskId); - - if (task) { - res.send({ - code: "0", - msg: "Success", - data: task, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Annotation task not found", - data: null, - }); - } - }); - - // 更新标注任务 - router.put(API.syncAnnotationTaskByIdUsingPost, (req, res) => { - const { taskId } = req.params; - const index = annotationTaskList.findIndex((t) => t.id === taskId); - - if (index !== -1) { - annotationTaskList[index] = { - ...annotationTaskList[index], - ...req.body, - updatedAt: new Date().toISOString(), - }; - res.send({ - code: "0", - msg: "Annotation task updated successfully", - data: annotationTaskList[index], - }); - } else { - res.status(404).send({ - code: "1", - msg: "Annotation task not found", - data: null, - }); - } - }); - - // 删除标注任务 - router.delete(API.deleteAnnotationTaskByIdUsingDelete, (req, res) => { - const { taskId } = req.params; - const index = annotationTaskList.findIndex((t) => t.id === taskId); - - if (index !== -1) { - annotationTaskList.splice(index, 1); - res.send({ - code: "0", - msg: "Annotation task deleted successfully", - data: null, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Annotation task not found", - data: null, - }); - } - }); - - // 获取标注数据列表 - router.get(API.queryAnnotationDataUsingGet, (req, res) => { - const { taskId } = req.params; - const { page = 0, size = 20, status } = req.query; - - let filteredData = annotationDataList.filter( - (data) => data.taskId === taskId - ); - - if (status) { - filteredData = filteredData.filter((data) => data.status === status); - } - - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = filteredData.slice(startIndex, endIndex); - - res.send({ - code: "0", - msg: "Success", - data: { - content: pageData, - totalElements: filteredData.length, - totalPages: Math.ceil(filteredData.length / size), - size: parseInt(size), - number: parseInt(page), - }, - }); - }); - - // 提交标注 - router.post(API.submitAnnotationUsingPost, (req, res) => { - const { taskId } = req.params; - const newAnnotation = { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - taskId, - ...req.body, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - - res.status(201).send({ - code: "0", - msg: "Annotation submitted successfully", - data: newAnnotation, - }); - }); - - // 更新标注 - router.put(API.updateAnnotationUsingPut, (req, res) => { - const { taskId, annotationId } = req.params; - - res.send({ - code: "0", - msg: "Annotation updated successfully", - data: { - id: annotationId, - taskId, - ...req.body, - updatedAt: new Date().toISOString(), - }, - }); - }); - - // 删除标注 - router.delete(API.deleteAnnotationUsingDelete, (req, res) => { - const { taskId, annotationId } = req.params; - - res.send({ - code: "0", - msg: "Annotation deleted successfully", - data: null, - }); - }); - - // 开始标注任务 - router.post(API.startAnnotationTaskUsingPost, (req, res) => { - const { taskId } = req.params; - const task = annotationTaskList.find((t) => t.id === taskId); - - if (task) { - task.status = "IN_PROGRESS"; - task.updatedAt = new Date().toISOString(); - - res.send({ - code: "0", - msg: "Annotation task started successfully", - data: task, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Annotation task not found", - data: null, - }); - } - }); - - // 暂停标注任务 - router.post(API.pauseAnnotationTaskUsingPost, (req, res) => { - const { taskId } = req.params; - const task = annotationTaskList.find((t) => t.id === taskId); - - if (task) { - task.status = "PAUSED"; - task.updatedAt = new Date().toISOString(); - - res.send({ - code: "0", - msg: "Annotation task paused successfully", - data: task, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Annotation task not found", - data: null, - }); - } - }); - - // 恢复标注任务 - router.post(API.resumeAnnotationTaskUsingPost, (req, res) => { - const { taskId } = req.params; - const task = annotationTaskList.find((t) => t.id === taskId); - - if (task) { - task.status = "IN_PROGRESS"; - task.updatedAt = new Date().toISOString(); - - res.send({ - code: "0", - msg: "Annotation task resumed successfully", - data: task, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Annotation task not found", - data: null, - }); - } - }); - - // 完成标注任务 - router.post(API.completeAnnotationTaskUsingPost, (req, res) => { - const { taskId } = req.params; - const task = annotationTaskList.find((t) => t.id === taskId); - - if (task) { - task.status = "COMPLETED"; - task.progress = 100; - task.updatedAt = new Date().toISOString(); - - res.send({ - code: "0", - msg: "Annotation task completed successfully", - data: task, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Annotation task not found", - data: null, - }); - } - }); - - // 获取标注任务统计信息 - router.get(API.getAnnotationTaskStatisticsUsingGet, (req, res) => { - const { taskId } = req.params; - const task = annotationTaskList.find((t) => t.id === taskId); - - if (task) { - const statistics = { - taskId, - totalDataCount: task.totalDataCount, - annotatedCount: task.annotatedCount, - progress: task.progress, - accuracy: task.statistics.accuracy, - averageAnnotationTime: task.statistics.averageTime, - reviewCount: task.statistics.reviewCount, - qualityScore: Mock.Random.float(0.8, 0.99, 2, 2), - annotatorDistribution: { - [Mock.Random.cname()]: Mock.Random.integer(10, 100), - [Mock.Random.cname()]: Mock.Random.integer(10, 100), - [Mock.Random.cname()]: Mock.Random.integer(10, 100), - }, - }; - - res.send({ - code: "0", - msg: "Success", - data: statistics, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Annotation task not found", - data: null, - }); - } - }); - - // 获取整体标注统计信息 - router.get(API.getAnnotationStatisticsUsingGet, (req, res) => { - const statistics = { - totalTasks: annotationTaskList.length, - completedTasks: annotationTaskList.filter((t) => t.status === "COMPLETED") - .length, - inProgressTasks: annotationTaskList.filter( - (t) => t.status === "IN_PROGRESS" - ).length, - pendingTasks: annotationTaskList.filter((t) => t.status === "PENDING") - .length, - totalAnnotations: annotationDataList.length, - totalAnnotators: annotatorList.length, - averageAccuracy: Mock.Random.float(0.85, 0.95, 2, 2), - taskTypeDistribution: { - TEXT_CLASSIFICATION: Mock.Random.integer(5, 15), - NAMED_ENTITY_RECOGNITION: Mock.Random.integer(3, 10), - OBJECT_DETECTION: Mock.Random.integer(2, 8), - SEMANTIC_SEGMENTATION: Mock.Random.integer(1, 5), - }, - }; - - res.send({ - code: "0", - msg: "Success", - data: statistics, - }); - }); - - // 获取标注模板列表 - router.get(API.queryAnnotationTemplatesUsingGet, (req, res) => { - const { page = 0, size = 20, type } = req.query; - let filteredTemplates = annotationTemplateList; - - if (type) { - filteredTemplates = filteredTemplates.filter( - (template) => template.type === type - ); - } - - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = filteredTemplates.slice(startIndex, endIndex); - - res.send({ - code: "0", - msg: "Success", - data: { - content: pageData, - totalElements: filteredTemplates.length, - totalPages: Math.ceil(filteredTemplates.length / size), - size: parseInt(size), - number: parseInt(page), - }, - }); - }); - - // 创建标注模板 - router.post(API.createAnnotationTemplateUsingPost, (req, res) => { - const newTemplate = { - ...annotationTemplateItem(), - ...req.body, - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - usageCount: 0, - createdAt: new Date().toISOString(), - }; - annotationTemplateList.push(newTemplate); - - res.status(201).send({ - code: "0", - msg: "Annotation template created successfully", - data: newTemplate, - }); - }); - - // 获取标注模板详情 - router.get(API.queryAnnotationTemplateByIdUsingGet, (req, res) => { - const { templateId } = req.params; - const template = annotationTemplateList.find((t) => t.id === templateId); - - if (template) { - res.send({ - code: "0", - msg: "Success", - data: template, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Annotation template not found", - data: null, - }); - } - }); - - // 获取标注者列表 - router.get(API.queryAnnotatorsUsingGet, (req, res) => { - const { page = 0, size = 20, status, skillLevel } = req.query; - let filteredAnnotators = annotatorList; - - if (status) { - filteredAnnotators = filteredAnnotators.filter( - (annotator) => annotator.status === status - ); - } - - if (skillLevel) { - filteredAnnotators = filteredAnnotators.filter( - (annotator) => annotator.skillLevel === skillLevel - ); - } - - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = filteredAnnotators.slice(startIndex, endIndex); - - res.send({ - code: "0", - msg: "Success", - data: { - content: pageData, - totalElements: filteredAnnotators.length, - totalPages: Math.ceil(filteredAnnotators.length / size), - size: parseInt(size), - number: parseInt(page), - }, - }); - }); - - // 分配标注者 - router.post(API.assignAnnotatorUsingPost, (req, res) => { - const { taskId } = req.params; - const { annotatorIds } = req.body; - - res.send({ - code: "0", - msg: "Annotators assigned successfully", - data: { - taskId, - assignedAnnotators: annotatorIds, - assignedAt: new Date().toISOString(), - }, - }); - }); -}; +const Mock = require("mockjs"); +const API = require("../mock-apis.cjs"); + +// 标注任务数据 +function annotationTaskItem() { + return { + source_dataset_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + mapping_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + labelling_project_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + labelling_project_name: Mock.Random.ctitle(5, 20), + created_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + last_updated_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + deleted_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + // id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + // name: Mock.Random.ctitle(5, 20), + // description: Mock.Random.csentence(5, 30), + // type: Mock.Random.pick([ + // "TEXT_CLASSIFICATION", + // "NAMED_ENTITY_RECOGNITION", + // "OBJECT_DETECTION", + // "SEMANTIC_SEGMENTATION", + // ]), + // status: Mock.Random.pick(["PENDING", "IN_PROGRESS", "COMPLETED", "PAUSED"]), + // datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + // progress: Mock.Random.float(0, 100, 2, 2), + // createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + // updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + // createdBy: Mock.Random.cname(), + // assignedTo: Mock.Random.cname(), + // totalDataCount: Mock.Random.integer(100, 10000), + // annotatedCount: Mock.Random.integer(10, 500), + // configuration: { + // labels: Mock.Random.shuffle([ + // "正面", + // "负面", + // "中性", + // "人物", + // "地点", + // "组织", + // "时间", + // ]).slice(0, Mock.Random.integer(3, 5)), + // guidelines: Mock.Random.csentence(10, 50), + // qualityThreshold: Mock.Random.float(0.8, 1.0, 2, 2), + // }, + // statistics: { + // accuracy: Mock.Random.float(0.85, 0.99, 2, 2), + // averageTime: Mock.Random.integer(30, 300), // seconds + // reviewCount: Mock.Random.integer(0, 50), + // }, + }; +} + +const annotationTaskList = new Array(25).fill(null).map(annotationTaskItem); + +// 标注数据项 +function annotationDataItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + taskId: Mock.Random.pick(annotationTaskList).id, + content: Mock.Random.cparagraph(1, 3), + originalData: { + text: Mock.Random.cparagraph(1, 3), + source: Mock.Random.url(), + metadata: { + author: Mock.Random.cname(), + timestamp: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + }, + }, + annotations: [ + { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + label: Mock.Random.pick(["正面", "负面", "中性"]), + confidence: Mock.Random.float(0.7, 1.0, 2, 2), + annotator: Mock.Random.cname(), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + isPreAnnotation: Mock.Random.boolean(), + }, + ], + status: Mock.Random.pick(["PENDING", "ANNOTATED", "REVIEWED", "REJECTED"]), + priority: Mock.Random.integer(1, 5), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + }; +} + +const annotationDataList = new Array(200).fill(null).map(annotationDataItem); + +// 标注模板数据 +function annotationTemplateItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.ctitle(5, 15), + description: Mock.Random.csentence(5, 25), + type: Mock.Random.pick([ + "TEXT_CLASSIFICATION", + "NAMED_ENTITY_RECOGNITION", + "OBJECT_DETECTION", + "SEMANTIC_SEGMENTATION", + ]), + category: Mock.Random.ctitle(3, 8), + labels: Mock.Random.shuffle([ + "正面", + "负面", + "中性", + "人物", + "地点", + "组织", + "时间", + "产品", + "服务", + ]).slice(0, Mock.Random.integer(3, 6)), + guidelines: Mock.Random.csentence(10, 50), + usageCount: Mock.Random.integer(0, 100), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + createdBy: Mock.Random.cname(), + }; +} + +const annotationTemplateList = new Array(15) + .fill(null) + .map(annotationTemplateItem); + +// 标注者数据 +function annotatorItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.cname(), + email: Mock.Random.email(), + role: Mock.Random.pick(["ANNOTATOR", "REVIEWER", "ADMIN"]), + skillLevel: Mock.Random.pick(["BEGINNER", "INTERMEDIATE", "EXPERT"]), + specialties: Mock.Random.shuffle([ + "文本分类", + "命名实体识别", + "目标检测", + "语义分割", + ]).slice(0, Mock.Random.integer(1, 3)), + statistics: { + totalAnnotations: Mock.Random.integer(100, 5000), + accuracy: Mock.Random.float(0.85, 0.99, 2, 2), + averageSpeed: Mock.Random.integer(50, 200), // annotations per hour + totalWorkTime: Mock.Random.integer(10, 500), // hours + }, + status: Mock.Random.pick(["ACTIVE", "INACTIVE", "SUSPENDED"]), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + }; +} + +const annotatorList = new Array(20).fill(null).map(annotatorItem); + +module.exports = function (router) { + // 获取标注任务列表 + router.get(API.queryAnnotationTasksUsingGet, (req, res) => { + const { page = 0, size = 20, status, type } = req.query; + let filteredTasks = annotationTaskList; + + if (status) { + filteredTasks = filteredTasks.filter((task) => task.status === status); + } + + if (type) { + filteredTasks = filteredTasks.filter((task) => task.type === type); + } + + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = filteredTasks.slice(startIndex, endIndex); + + res.send({ + code: "0", + msg: "Success", + data: { + content: pageData, + totalElements: filteredTasks.length, + totalPages: Math.ceil(filteredTasks.length / size), + size: parseInt(size), + number: parseInt(page), + first: page == 0, + last: page >= Math.ceil(filteredTasks.length / size) - 1, + }, + }); + }); + + // 创建标注任务 + router.post(API.createAnnotationTaskUsingPost, (req, res) => { + const newTask = { + ...annotationTaskItem(), + ...req.body, + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + status: "PENDING", + progress: 0, + annotatedCount: 0, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + annotationTaskList.push(newTask); + + res.status(201).send({ + code: "0", + msg: "Annotation task created successfully", + data: newTask, + }); + }); + + // 获取标注任务详情 + router.get(API.queryAnnotationTaskByIdUsingGet, (req, res) => { + const { taskId } = req.params; + const task = annotationTaskList.find((t) => t.id === taskId); + + if (task) { + res.send({ + code: "0", + msg: "Success", + data: task, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Annotation task not found", + data: null, + }); + } + }); + + // 更新标注任务 + router.put(API.syncAnnotationTaskByIdUsingPost, (req, res) => { + const { taskId } = req.params; + const index = annotationTaskList.findIndex((t) => t.id === taskId); + + if (index !== -1) { + annotationTaskList[index] = { + ...annotationTaskList[index], + ...req.body, + updatedAt: new Date().toISOString(), + }; + res.send({ + code: "0", + msg: "Annotation task updated successfully", + data: annotationTaskList[index], + }); + } else { + res.status(404).send({ + code: "1", + msg: "Annotation task not found", + data: null, + }); + } + }); + + // 删除标注任务 + router.delete(API.deleteAnnotationTaskByIdUsingDelete, (req, res) => { + const { taskId } = req.params; + const index = annotationTaskList.findIndex((t) => t.id === taskId); + + if (index !== -1) { + annotationTaskList.splice(index, 1); + res.send({ + code: "0", + msg: "Annotation task deleted successfully", + data: null, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Annotation task not found", + data: null, + }); + } + }); + + // 获取标注数据列表 + router.get(API.queryAnnotationDataUsingGet, (req, res) => { + const { taskId } = req.params; + const { page = 0, size = 20, status } = req.query; + + let filteredData = annotationDataList.filter( + (data) => data.taskId === taskId + ); + + if (status) { + filteredData = filteredData.filter((data) => data.status === status); + } + + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = filteredData.slice(startIndex, endIndex); + + res.send({ + code: "0", + msg: "Success", + data: { + content: pageData, + totalElements: filteredData.length, + totalPages: Math.ceil(filteredData.length / size), + size: parseInt(size), + number: parseInt(page), + }, + }); + }); + + // 提交标注 + router.post(API.submitAnnotationUsingPost, (req, res) => { + const { taskId } = req.params; + const newAnnotation = { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + taskId, + ...req.body, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + + res.status(201).send({ + code: "0", + msg: "Annotation submitted successfully", + data: newAnnotation, + }); + }); + + // 更新标注 + router.put(API.updateAnnotationUsingPut, (req, res) => { + const { taskId, annotationId } = req.params; + + res.send({ + code: "0", + msg: "Annotation updated successfully", + data: { + id: annotationId, + taskId, + ...req.body, + updatedAt: new Date().toISOString(), + }, + }); + }); + + // 删除标注 + router.delete(API.deleteAnnotationUsingDelete, (req, res) => { + const { taskId, annotationId } = req.params; + + res.send({ + code: "0", + msg: "Annotation deleted successfully", + data: null, + }); + }); + + // 开始标注任务 + router.post(API.startAnnotationTaskUsingPost, (req, res) => { + const { taskId } = req.params; + const task = annotationTaskList.find((t) => t.id === taskId); + + if (task) { + task.status = "IN_PROGRESS"; + task.updatedAt = new Date().toISOString(); + + res.send({ + code: "0", + msg: "Annotation task started successfully", + data: task, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Annotation task not found", + data: null, + }); + } + }); + + // 暂停标注任务 + router.post(API.pauseAnnotationTaskUsingPost, (req, res) => { + const { taskId } = req.params; + const task = annotationTaskList.find((t) => t.id === taskId); + + if (task) { + task.status = "PAUSED"; + task.updatedAt = new Date().toISOString(); + + res.send({ + code: "0", + msg: "Annotation task paused successfully", + data: task, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Annotation task not found", + data: null, + }); + } + }); + + // 恢复标注任务 + router.post(API.resumeAnnotationTaskUsingPost, (req, res) => { + const { taskId } = req.params; + const task = annotationTaskList.find((t) => t.id === taskId); + + if (task) { + task.status = "IN_PROGRESS"; + task.updatedAt = new Date().toISOString(); + + res.send({ + code: "0", + msg: "Annotation task resumed successfully", + data: task, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Annotation task not found", + data: null, + }); + } + }); + + // 完成标注任务 + router.post(API.completeAnnotationTaskUsingPost, (req, res) => { + const { taskId } = req.params; + const task = annotationTaskList.find((t) => t.id === taskId); + + if (task) { + task.status = "COMPLETED"; + task.progress = 100; + task.updatedAt = new Date().toISOString(); + + res.send({ + code: "0", + msg: "Annotation task completed successfully", + data: task, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Annotation task not found", + data: null, + }); + } + }); + + // 获取标注任务统计信息 + router.get(API.getAnnotationTaskStatisticsUsingGet, (req, res) => { + const { taskId } = req.params; + const task = annotationTaskList.find((t) => t.id === taskId); + + if (task) { + const statistics = { + taskId, + totalDataCount: task.totalDataCount, + annotatedCount: task.annotatedCount, + progress: task.progress, + accuracy: task.statistics.accuracy, + averageAnnotationTime: task.statistics.averageTime, + reviewCount: task.statistics.reviewCount, + qualityScore: Mock.Random.float(0.8, 0.99, 2, 2), + annotatorDistribution: { + [Mock.Random.cname()]: Mock.Random.integer(10, 100), + [Mock.Random.cname()]: Mock.Random.integer(10, 100), + [Mock.Random.cname()]: Mock.Random.integer(10, 100), + }, + }; + + res.send({ + code: "0", + msg: "Success", + data: statistics, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Annotation task not found", + data: null, + }); + } + }); + + // 获取整体标注统计信息 + router.get(API.getAnnotationStatisticsUsingGet, (req, res) => { + const statistics = { + totalTasks: annotationTaskList.length, + completedTasks: annotationTaskList.filter((t) => t.status === "COMPLETED") + .length, + inProgressTasks: annotationTaskList.filter( + (t) => t.status === "IN_PROGRESS" + ).length, + pendingTasks: annotationTaskList.filter((t) => t.status === "PENDING") + .length, + totalAnnotations: annotationDataList.length, + totalAnnotators: annotatorList.length, + averageAccuracy: Mock.Random.float(0.85, 0.95, 2, 2), + taskTypeDistribution: { + TEXT_CLASSIFICATION: Mock.Random.integer(5, 15), + NAMED_ENTITY_RECOGNITION: Mock.Random.integer(3, 10), + OBJECT_DETECTION: Mock.Random.integer(2, 8), + SEMANTIC_SEGMENTATION: Mock.Random.integer(1, 5), + }, + }; + + res.send({ + code: "0", + msg: "Success", + data: statistics, + }); + }); + + // 获取标注模板列表 + router.get(API.queryAnnotationTemplatesUsingGet, (req, res) => { + const { page = 0, size = 20, type } = req.query; + let filteredTemplates = annotationTemplateList; + + if (type) { + filteredTemplates = filteredTemplates.filter( + (template) => template.type === type + ); + } + + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = filteredTemplates.slice(startIndex, endIndex); + + res.send({ + code: "0", + msg: "Success", + data: { + content: pageData, + totalElements: filteredTemplates.length, + totalPages: Math.ceil(filteredTemplates.length / size), + size: parseInt(size), + number: parseInt(page), + }, + }); + }); + + // 创建标注模板 + router.post(API.createAnnotationTemplateUsingPost, (req, res) => { + const newTemplate = { + ...annotationTemplateItem(), + ...req.body, + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + usageCount: 0, + createdAt: new Date().toISOString(), + }; + annotationTemplateList.push(newTemplate); + + res.status(201).send({ + code: "0", + msg: "Annotation template created successfully", + data: newTemplate, + }); + }); + + // 获取标注模板详情 + router.get(API.queryAnnotationTemplateByIdUsingGet, (req, res) => { + const { templateId } = req.params; + const template = annotationTemplateList.find((t) => t.id === templateId); + + if (template) { + res.send({ + code: "0", + msg: "Success", + data: template, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Annotation template not found", + data: null, + }); + } + }); + + // 获取标注者列表 + router.get(API.queryAnnotatorsUsingGet, (req, res) => { + const { page = 0, size = 20, status, skillLevel } = req.query; + let filteredAnnotators = annotatorList; + + if (status) { + filteredAnnotators = filteredAnnotators.filter( + (annotator) => annotator.status === status + ); + } + + if (skillLevel) { + filteredAnnotators = filteredAnnotators.filter( + (annotator) => annotator.skillLevel === skillLevel + ); + } + + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = filteredAnnotators.slice(startIndex, endIndex); + + res.send({ + code: "0", + msg: "Success", + data: { + content: pageData, + totalElements: filteredAnnotators.length, + totalPages: Math.ceil(filteredAnnotators.length / size), + size: parseInt(size), + number: parseInt(page), + }, + }); + }); + + // 分配标注者 + router.post(API.assignAnnotatorUsingPost, (req, res) => { + const { taskId } = req.params; + const { annotatorIds } = req.body; + + res.send({ + code: "0", + msg: "Annotators assigned successfully", + data: { + taskId, + assignedAnnotators: annotatorIds, + assignedAt: new Date().toISOString(), + }, + }); + }); +}; diff --git a/frontend/src/mock/mock-seed/data-cleansing.cjs b/frontend/src/mock/mock-seed/data-cleansing.cjs index 7f4542a10..6a1784975 100644 --- a/frontend/src/mock/mock-seed/data-cleansing.cjs +++ b/frontend/src/mock/mock-seed/data-cleansing.cjs @@ -1,563 +1,563 @@ -const Mock = require("mockjs"); -const API = require("../mock-apis.cjs"); - -function operatorItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.ctitle(3, 10), - description: Mock.Random.csentence(5, 20), - version: "1.0.0", - inputs: Mock.Random.integer(1, 5), - outputs: Mock.Random.integer(1, 5), - settings: JSON.stringify({ - host: { type: "input", name: "主机地址", defaultVal: "localhost" }, - fileLength: { - name: "文档字数", - description: - "过滤字数不在指定范围内的文档,如[10,10000000]。若输入为空,则不对字数上/下限做限制。", - type: "range", - defaultVal: [10, 10000000], - min: 0, - max: 10000000000000000, - step: 1, - }, - range: { - type: "range", - name: "读取行数", - description: "某个词的统计数/文档总词数 > 设定值,该文档被去除。", - properties: [ - { - name: "起始行", - type: "inputNumber", - defaultVal: 1000, - min: 100, - max: 10000, - step: 1, - }, - { - name: "结束行", - type: "inputNumber", - defaultVal: 2000, - min: 100, - max: 10000, - step: 1, - }, - ], - }, - filepath: { type: "input", name: "文件路径", defaultVal: "/path" }, - encoding: { - type: "select", - name: "编码", - defaultVal: "utf-8", - options: ["utf-8", "gbk", "ascii"], - }, - radio: { - type: "radio", - name: "radio", - defaultVal: "utf-8", - options: ["utf-8", "gbk", "ascii"], - }, - features: { - type: "checkbox", - name: "特征列", - defaultVal: ["feature1", "feature3"], - options: ["feature1", "feature2", "feature3"], - }, - repeatPhraseRatio: { - name: "文档词重复率", - description: "某个词的统计数/文档总词数 > 设定值,该文档被去除。", - type: "slider", - defaultVal: 0.5, - min: 0, - max: 1, - step: 0.1, - }, - hitStopwords: { - name: "去除停用词", - description: "统计重复词时,选择是否要去除停用词。", - type: "switch", - defaultVal: false, - required: true, - checkedLabel: "去除", - unCheckedLabel: "不去除", - }, - }), - categories: [Mock.Random.pick([3, 4, 5, 6, 7, 8, 9])], - isStar: Mock.Random.boolean(), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - }; -} - -const operatorList = new Array(50).fill(null).map(operatorItem); - -// 清洗任务数据 -function cleaningTaskItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.ctitle(5, 20), - description: Mock.Random.csentence(5, 30), - status: Mock.Random.pick([ - "PENDING", - "RUNNING", - "COMPLETED", - "FAILED", - "STOPPED", - ]), - srcDatasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - srcDatasetName: Mock.Random.ctitle(5, 15), - destDatasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - destDatasetName: Mock.Random.ctitle(5, 15), - progress: { - finishedFileNum: Mock.Random.integer(0, 100), - process: Mock.Random.integer(0, 100), - totalFileNum: 100, - }, - startedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - finishedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - instance: operatorList, - }; -} - -const cleaningTaskList = new Array(20).fill(null).map(cleaningTaskItem); - -// 清洗模板数据 -function cleaningTemplateItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.ctitle(5, 15), - description: Mock.Random.csentence(5, 25), - instance: operatorList.slice( - Mock.Random.integer(0, 5), - Mock.Random.integer(6, 50) - ), - category: Mock.Random.ctitle(3, 8), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - }; -} - -const cleaningTemplateList = new Array(15).fill(null).map(cleaningTemplateItem); - -const categoryTree = [ - { - id: 1, - name: "modal", - count: 7, - categories: [ - { id: 3, name: "text", count: 3, type: null, parentId: null }, - { id: 4, name: "image", count: 0, type: null, parentId: null }, - { id: 5, name: "audio", count: 0, type: null, parentId: null }, - { id: 6, name: "video", count: 0, type: null, parentId: null }, - { - id: 7, - name: "multimodal", - count: 0, - type: null, - parentId: null, - }, - ], - }, - { - id: 2, - name: "language", - count: 3, - categories: [ - { id: 8, name: "python", count: 2, type: null, parentId: null }, - { id: 9, name: "java", count: 1, type: null, parentId: null }, - ], - }, -]; - -module.exports = function (router) { - // 获取清洗任务列表 - router.get(API.queryCleaningTasksUsingGet, (req, res) => { - const { page = 0, size = 10, status } = req.query; - let filteredTasks = cleaningTaskList; - - if (status) { - filteredTasks = cleaningTaskList.filter((task) => task.status === status); - } - - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = filteredTasks.slice(startIndex, endIndex); - - res.send({ - code: "0", - msg: "Success", - data: { - content: pageData, - totalElements: filteredTasks.length, - totalPages: Math.ceil(filteredTasks.length / size), - size: parseInt(size), - number: parseInt(page), - }, - }); - }); - - // 创建清洗任务 - router.post(API.createCleaningTaskUsingPost, (req, res) => { - const newTask = { - ...cleaningTaskItem(), - ...req.body, - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - status: "PENDING", - createdAt: new Date().toISOString(), - }; - cleaningTaskList.push(newTask); - - res.status(201).send({ - code: "0", - msg: "Cleaning task created successfully", - data: newTask, - }); - }); - - // 获取清洗任务详情 - router.get(API.queryCleaningTaskByIdUsingGet, (req, res) => { - const { taskId } = req.params; - const task = cleaningTaskList.find((j) => j.id === taskId); - - if (task) { - res.send({ - code: "0", - msg: "Success", - data: task, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Cleaning task not found", - data: null, - }); - } - }); - - // 删除清洗任务 - router.delete(API.deleteCleaningTaskByIdUsingDelete, (req, res) => { - const { taskId } = req.params; - const index = cleaningTaskList.findIndex((j) => j.id === taskId); - - if (index !== -1) { - cleaningTaskList.splice(index, 1); - res.send({ - code: "0", - msg: "Cleaning task deleted successfully", - data: null, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Cleaning task not found", - data: null, - }); - } - }); - - // 执行清洗任务 - router.post(API.executeCleaningTaskUsingPost, (req, res) => { - const { taskId } = req.params; - const task = cleaningTaskList.find((j) => j.id === taskId); - - if (task) { - task.status = "RUNNING"; - task.startTime = new Date().toISOString(); - - res.send({ - code: "0", - msg: "Cleaning task execution started", - data: { - executionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - status: "RUNNING", - message: "Task execution started successfully", - }, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Cleaning task not found", - data: null, - }); - } - }); - - // 停止清洗任务 - router.post(API.stopCleaningTaskUsingPost, (req, res) => { - const { taskId } = req.params; - const task = cleaningTaskList.find((j) => j.id === taskId); - - if (task) { - task.status = "PENDING"; - task.endTime = new Date().toISOString(); - - res.send({ - code: "0", - msg: "Cleaning task stopped successfully", - data: null, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Cleaning task not found", - data: null, - }); - } - }); - - // 获取清洗模板列表 - router.get(API.queryCleaningTemplatesUsingGet, (req, res) => { - const { page = 0, size = 20 } = req.query; - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = cleaningTemplateList.slice(startIndex, endIndex); - res.send({ - code: "0", - msg: "Success", - data: { content: pageData, totalElements: cleaningTemplateList.length }, - }); - }); - - // 创建清洗模板 - router.post(API.createCleaningTemplateUsingPost, (req, res) => { - const newTemplate = { - ...cleaningTemplateItem(), - ...req.body, - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - createdAt: new Date().toISOString(), - }; - cleaningTemplateList.push(newTemplate); - - res.status(201).send({ - code: "0", - msg: "Cleaning template created successfully", - data: newTemplate, - }); - }); - - // 获取清洗模板详情 - router.get(API.queryCleaningTemplateByIdUsingGet, (req, res) => { - const { templateId } = req.params; - const template = cleaningTemplateList.find((t) => t.id === templateId); - - if (template) { - res.send({ - code: "0", - msg: "Success", - data: template, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Cleaning template not found", - data: null, - }); - } - }); - - // 删除清洗模板 - router.delete(API.deleteCleaningTemplateByIdUsingDelete, (req, res) => { - const { templateId } = req.params; - const index = cleaningTemplateList.findIndex((t) => t.id === templateId); - - if (index !== -1) { - cleaningTemplateList.splice(index, 1); - res.send({ - code: "0", - msg: "Cleaning template deleted successfully", - data: null, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Cleaning template not found", - data: null, - }); - } - }); - - // 获取算子列表 - router.post(API.queryOperatorsUsingPost, (req, res) => { - const { - page = 0, - size = 20, - categories = [], - operatorName = "", - labelName = "", - isStar, - } = req.body; - - let filteredOperators = operatorList; - - // 按分类筛选 - if (categories && categories.length > 0) { - filteredOperators = filteredOperators.filter((op) => - categories.includes(op.category.id) - ); - } - - // 按名称搜索 - if (operatorName) { - filteredOperators = filteredOperators.filter((op) => - op.name.toLowerCase().includes(operatorName.toLowerCase()) - ); - } - - // 按标签筛选 - if (labelName) { - filteredOperators = filteredOperators.filter((op) => - op.labels.some((label) => label.name.includes(labelName)) - ); - } - - // 按收藏状态筛选 - if (typeof isStar === "boolean") { - filteredOperators = filteredOperators.filter( - (op) => op.isStar === isStar - ); - } - - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = filteredOperators.slice(startIndex, endIndex); - - res.send({ - code: "0", - msg: "Success", - data: { - content: pageData, - totalElements: filteredOperators.length, - totalPages: Math.ceil(filteredOperators.length / size), - size: parseInt(size), - number: parseInt(page), - first: page === 0, - last: page >= Math.ceil(filteredOperators.length / size) - 1, - }, - }); - }); - - // 获取算子详情 - router.get(API.queryOperatorByIdUsingGet, (req, res) => { - const { id } = req.params; - const operator = operatorList.find((op) => op.id === id); - console.log("获取算子详情:", id, operator); - if (operator) { - // 增加浏览次数模拟 - operator.viewCount = (operator.viewCount || 0) + 1; - - res.send({ - code: "0", - msg: "Success", - data: operator, - }); - } else { - res.status(404).send({ - error: "OPERATOR_NOT_FOUND", - message: "算子不存在", - timestamp: new Date().toISOString(), - }); - } - }); - - // 更新算子信息 - router.put(API.updateOperatorByIdUsingPut, (req, res) => { - const { id } = req.params; - const index = operatorList.findIndex((op) => op.id === id); - - if (index !== -1) { - operatorList[index] = { - ...operatorList[index], - ...req.body, - updatedAt: new Date().toISOString(), - }; - - res.send({ - code: "0", - msg: "Operator updated successfully", - data: operatorList[index], - }); - } else { - res.status(404).send({ - error: "OPERATOR_NOT_FOUND", - message: "算子不存在", - timestamp: new Date().toISOString(), - }); - } - }); - - // 创建算子 - router.post(API.createOperatorUsingPost, (req, res) => { - const { name, description, version, category, documentation } = req.body; - - const newOperator = { - ...operatorItem(), - ...req.body, - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name, - description, - version, - category: - typeof category === "string" - ? { id: category, name: category } - : category, - documentation, - status: "REVIEWING", - downloadCount: 0, - rating: 0, - ratingCount: 0, - isStar: false, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - - operatorList.push(newOperator); - - res.status(201).send({ - code: "0", - msg: "Operator created successfully", - data: newOperator, - }); - }); - - // 上传算子 - router.post(API.uploadOperatorUsingPost, (req, res) => { - const { description } = req.body; - - const newOperator = { - ...operatorItem(), - description: description || "通过文件上传创建的算子", - status: "REVIEWING", - downloadCount: 0, - rating: 0, - ratingCount: 0, - isStar: false, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - - operatorList.push(newOperator); - - res.status(201).send({ - code: "0", - msg: "Operator uploaded successfully", - data: newOperator, - }); - }); - - // 获取算子分类树 - router.get(API.queryCategoryTreeUsingGet, (req, res) => { - res.send({ - code: "0", - msg: "Success", - data: { - page: 0, - size: categoryTree.length, - totalElements: categoryTree.length, - totalPages: 1, - content: categoryTree, - }, - }); - }); -}; +const Mock = require("mockjs"); +const API = require("../mock-apis.cjs"); + +function operatorItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.ctitle(3, 10), + description: Mock.Random.csentence(5, 20), + version: "1.0.0", + inputs: Mock.Random.integer(1, 5), + outputs: Mock.Random.integer(1, 5), + settings: JSON.stringify({ + host: { type: "input", name: "主机地址", defaultVal: "localhost" }, + fileLength: { + name: "文档字数", + description: + "过滤字数不在指定范围内的文档,如[10,10000000]。若输入为空,则不对字数上/下限做限制。", + type: "range", + defaultVal: [10, 10000000], + min: 0, + max: 10000000000000000, + step: 1, + }, + range: { + type: "range", + name: "读取行数", + description: "某个词的统计数/文档总词数 > 设定值,该文档被去除。", + properties: [ + { + name: "起始行", + type: "inputNumber", + defaultVal: 1000, + min: 100, + max: 10000, + step: 1, + }, + { + name: "结束行", + type: "inputNumber", + defaultVal: 2000, + min: 100, + max: 10000, + step: 1, + }, + ], + }, + filepath: { type: "input", name: "文件路径", defaultVal: "/path" }, + encoding: { + type: "select", + name: "编码", + defaultVal: "utf-8", + options: ["utf-8", "gbk", "ascii"], + }, + radio: { + type: "radio", + name: "radio", + defaultVal: "utf-8", + options: ["utf-8", "gbk", "ascii"], + }, + features: { + type: "checkbox", + name: "特征列", + defaultVal: ["feature1", "feature3"], + options: ["feature1", "feature2", "feature3"], + }, + repeatPhraseRatio: { + name: "文档词重复率", + description: "某个词的统计数/文档总词数 > 设定值,该文档被去除。", + type: "slider", + defaultVal: 0.5, + min: 0, + max: 1, + step: 0.1, + }, + hitStopwords: { + name: "去除停用词", + description: "统计重复词时,选择是否要去除停用词。", + type: "switch", + defaultVal: false, + required: true, + checkedLabel: "去除", + unCheckedLabel: "不去除", + }, + }), + categories: [Mock.Random.pick([3, 4, 5, 6, 7, 8, 9])], + isStar: Mock.Random.boolean(), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + }; +} + +const operatorList = new Array(50).fill(null).map(operatorItem); + +// 清洗任务数据 +function cleaningTaskItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.ctitle(5, 20), + description: Mock.Random.csentence(5, 30), + status: Mock.Random.pick([ + "PENDING", + "RUNNING", + "COMPLETED", + "FAILED", + "STOPPED", + ]), + srcDatasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + srcDatasetName: Mock.Random.ctitle(5, 15), + destDatasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + destDatasetName: Mock.Random.ctitle(5, 15), + progress: { + finishedFileNum: Mock.Random.integer(0, 100), + process: Mock.Random.integer(0, 100), + totalFileNum: 100, + }, + startedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + finishedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + instance: operatorList, + }; +} + +const cleaningTaskList = new Array(20).fill(null).map(cleaningTaskItem); + +// 清洗模板数据 +function cleaningTemplateItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.ctitle(5, 15), + description: Mock.Random.csentence(5, 25), + instance: operatorList.slice( + Mock.Random.integer(0, 5), + Mock.Random.integer(6, 50) + ), + category: Mock.Random.ctitle(3, 8), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + }; +} + +const cleaningTemplateList = new Array(15).fill(null).map(cleaningTemplateItem); + +const categoryTree = [ + { + id: 1, + name: "modal", + count: 7, + categories: [ + { id: 3, name: "text", count: 3, type: null, parentId: null }, + { id: 4, name: "image", count: 0, type: null, parentId: null }, + { id: 5, name: "audio", count: 0, type: null, parentId: null }, + { id: 6, name: "video", count: 0, type: null, parentId: null }, + { + id: 7, + name: "multimodal", + count: 0, + type: null, + parentId: null, + }, + ], + }, + { + id: 2, + name: "language", + count: 3, + categories: [ + { id: 8, name: "python", count: 2, type: null, parentId: null }, + { id: 9, name: "java", count: 1, type: null, parentId: null }, + ], + }, +]; + +module.exports = function (router) { + // 获取清洗任务列表 + router.get(API.queryCleaningTasksUsingGet, (req, res) => { + const { page = 0, size = 10, status } = req.query; + let filteredTasks = cleaningTaskList; + + if (status) { + filteredTasks = cleaningTaskList.filter((task) => task.status === status); + } + + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = filteredTasks.slice(startIndex, endIndex); + + res.send({ + code: "0", + msg: "Success", + data: { + content: pageData, + totalElements: filteredTasks.length, + totalPages: Math.ceil(filteredTasks.length / size), + size: parseInt(size), + number: parseInt(page), + }, + }); + }); + + // 创建清洗任务 + router.post(API.createCleaningTaskUsingPost, (req, res) => { + const newTask = { + ...cleaningTaskItem(), + ...req.body, + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + status: "PENDING", + createdAt: new Date().toISOString(), + }; + cleaningTaskList.push(newTask); + + res.status(201).send({ + code: "0", + msg: "Cleaning task created successfully", + data: newTask, + }); + }); + + // 获取清洗任务详情 + router.get(API.queryCleaningTaskByIdUsingGet, (req, res) => { + const { taskId } = req.params; + const task = cleaningTaskList.find((j) => j.id === taskId); + + if (task) { + res.send({ + code: "0", + msg: "Success", + data: task, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Cleaning task not found", + data: null, + }); + } + }); + + // 删除清洗任务 + router.delete(API.deleteCleaningTaskByIdUsingDelete, (req, res) => { + const { taskId } = req.params; + const index = cleaningTaskList.findIndex((j) => j.id === taskId); + + if (index !== -1) { + cleaningTaskList.splice(index, 1); + res.send({ + code: "0", + msg: "Cleaning task deleted successfully", + data: null, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Cleaning task not found", + data: null, + }); + } + }); + + // 执行清洗任务 + router.post(API.executeCleaningTaskUsingPost, (req, res) => { + const { taskId } = req.params; + const task = cleaningTaskList.find((j) => j.id === taskId); + + if (task) { + task.status = "RUNNING"; + task.startTime = new Date().toISOString(); + + res.send({ + code: "0", + msg: "Cleaning task execution started", + data: { + executionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + status: "RUNNING", + message: "Task execution started successfully", + }, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Cleaning task not found", + data: null, + }); + } + }); + + // 停止清洗任务 + router.post(API.stopCleaningTaskUsingPost, (req, res) => { + const { taskId } = req.params; + const task = cleaningTaskList.find((j) => j.id === taskId); + + if (task) { + task.status = "PENDING"; + task.endTime = new Date().toISOString(); + + res.send({ + code: "0", + msg: "Cleaning task stopped successfully", + data: null, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Cleaning task not found", + data: null, + }); + } + }); + + // 获取清洗模板列表 + router.get(API.queryCleaningTemplatesUsingGet, (req, res) => { + const { page = 0, size = 20 } = req.query; + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = cleaningTemplateList.slice(startIndex, endIndex); + res.send({ + code: "0", + msg: "Success", + data: { content: pageData, totalElements: cleaningTemplateList.length }, + }); + }); + + // 创建清洗模板 + router.post(API.createCleaningTemplateUsingPost, (req, res) => { + const newTemplate = { + ...cleaningTemplateItem(), + ...req.body, + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + createdAt: new Date().toISOString(), + }; + cleaningTemplateList.push(newTemplate); + + res.status(201).send({ + code: "0", + msg: "Cleaning template created successfully", + data: newTemplate, + }); + }); + + // 获取清洗模板详情 + router.get(API.queryCleaningTemplateByIdUsingGet, (req, res) => { + const { templateId } = req.params; + const template = cleaningTemplateList.find((t) => t.id === templateId); + + if (template) { + res.send({ + code: "0", + msg: "Success", + data: template, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Cleaning template not found", + data: null, + }); + } + }); + + // 删除清洗模板 + router.delete(API.deleteCleaningTemplateByIdUsingDelete, (req, res) => { + const { templateId } = req.params; + const index = cleaningTemplateList.findIndex((t) => t.id === templateId); + + if (index !== -1) { + cleaningTemplateList.splice(index, 1); + res.send({ + code: "0", + msg: "Cleaning template deleted successfully", + data: null, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Cleaning template not found", + data: null, + }); + } + }); + + // 获取算子列表 + router.post(API.queryOperatorsUsingPost, (req, res) => { + const { + page = 0, + size = 20, + categories = [], + operatorName = "", + labelName = "", + isStar, + } = req.body; + + let filteredOperators = operatorList; + + // 按分类筛选 + if (categories && categories.length > 0) { + filteredOperators = filteredOperators.filter((op) => + categories.includes(op.category.id) + ); + } + + // 按名称搜索 + if (operatorName) { + filteredOperators = filteredOperators.filter((op) => + op.name.toLowerCase().includes(operatorName.toLowerCase()) + ); + } + + // 按标签筛选 + if (labelName) { + filteredOperators = filteredOperators.filter((op) => + op.labels.some((label) => label.name.includes(labelName)) + ); + } + + // 按收藏状态筛选 + if (typeof isStar === "boolean") { + filteredOperators = filteredOperators.filter( + (op) => op.isStar === isStar + ); + } + + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = filteredOperators.slice(startIndex, endIndex); + + res.send({ + code: "0", + msg: "Success", + data: { + content: pageData, + totalElements: filteredOperators.length, + totalPages: Math.ceil(filteredOperators.length / size), + size: parseInt(size), + number: parseInt(page), + first: page === 0, + last: page >= Math.ceil(filteredOperators.length / size) - 1, + }, + }); + }); + + // 获取算子详情 + router.get(API.queryOperatorByIdUsingGet, (req, res) => { + const { id } = req.params; + const operator = operatorList.find((op) => op.id === id); + console.log("获取算子详情:", id, operator); + if (operator) { + // 增加浏览次数模拟 + operator.viewCount = (operator.viewCount || 0) + 1; + + res.send({ + code: "0", + msg: "Success", + data: operator, + }); + } else { + res.status(404).send({ + error: "OPERATOR_NOT_FOUND", + message: "算子不存在", + timestamp: new Date().toISOString(), + }); + } + }); + + // 更新算子信息 + router.put(API.updateOperatorByIdUsingPut, (req, res) => { + const { id } = req.params; + const index = operatorList.findIndex((op) => op.id === id); + + if (index !== -1) { + operatorList[index] = { + ...operatorList[index], + ...req.body, + updatedAt: new Date().toISOString(), + }; + + res.send({ + code: "0", + msg: "Operator updated successfully", + data: operatorList[index], + }); + } else { + res.status(404).send({ + error: "OPERATOR_NOT_FOUND", + message: "算子不存在", + timestamp: new Date().toISOString(), + }); + } + }); + + // 创建算子 + router.post(API.createOperatorUsingPost, (req, res) => { + const { name, description, version, category, documentation } = req.body; + + const newOperator = { + ...operatorItem(), + ...req.body, + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name, + description, + version, + category: + typeof category === "string" + ? { id: category, name: category } + : category, + documentation, + status: "REVIEWING", + downloadCount: 0, + rating: 0, + ratingCount: 0, + isStar: false, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + + operatorList.push(newOperator); + + res.status(201).send({ + code: "0", + msg: "Operator created successfully", + data: newOperator, + }); + }); + + // 上传算子 + router.post(API.uploadOperatorUsingPost, (req, res) => { + const { description } = req.body; + + const newOperator = { + ...operatorItem(), + description: description || "通过文件上传创建的算子", + status: "REVIEWING", + downloadCount: 0, + rating: 0, + ratingCount: 0, + isStar: false, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + + operatorList.push(newOperator); + + res.status(201).send({ + code: "0", + msg: "Operator uploaded successfully", + data: newOperator, + }); + }); + + // 获取算子分类树 + router.get(API.queryCategoryTreeUsingGet, (req, res) => { + res.send({ + code: "0", + msg: "Success", + data: { + page: 0, + size: categoryTree.length, + totalElements: categoryTree.length, + totalPages: 1, + content: categoryTree, + }, + }); + }); +}; diff --git a/frontend/src/mock/mock-seed/data-collection.cjs b/frontend/src/mock/mock-seed/data-collection.cjs index f7670ba86..8998b0b6b 100644 --- a/frontend/src/mock/mock-seed/data-collection.cjs +++ b/frontend/src/mock/mock-seed/data-collection.cjs @@ -1,232 +1,232 @@ -const Mock = require("mockjs"); -const API = require("../mock-apis.cjs"); -const { Random } = Mock; - -// 生成模拟数据归集统计信息 -function dataXTemplate() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.ctitle(5, 15), - sourceType: Mock.Random.csentence(3, 10), - targetType: Mock.Random.csentence(3, 10), - description: Mock.Random.csentence(5, 20), - version: `v${Mock.Random.integer(1, 5)}.${Mock.Random.integer( - 0, - 9 - )}.${Mock.Random.integer(0, 9)}`, - isSystem: Mock.Random.boolean(), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - }; -} - -const templateList = new Array(20).fill(null).map(dataXTemplate); - -// 生成模拟任务数据 -function taskItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.ctitle(5, 20), - description: Mock.Random.csentence(5, 20), - syncMode: Mock.Random.pick(["ONCE", "SCHEDULED"]), - config: { - query: "SELECT * FROM table WHERE condition", - batchSize: Mock.Random.integer(100, 1000), - frequency: Mock.Random.integer(1, 60), // in minutes - }, - scheduleExpression: "0 0 * * *", // cron expression - lastExecutionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - status: Mock.Random.pick([ - "DRAFT", - "READY", - "RUNNING", - "FAILED", - "STOPPED", - "SUCCESS", - ]), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - sourceDataSourceId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - sourceDataSourceName: Mock.Random.ctitle(5, 20), - targetDataSourceId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - targetDataSourceName: Mock.Random.ctitle(5, 20), - }; -} - -const taskList = new Array(50).fill(null).map(taskItem); - -// 生成模拟任务执行日志数据 -function executionLogItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - taskName: Mock.Random.ctitle(5, 20), - dataSource: Mock.Random.ctitle(5, 15), - startTime: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - endTime: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - status: Mock.Random.pick(["SUCCESS", "FAILED", "RUNNING"]), - triggerType: Mock.Random.pick(["MANUAL", "SCHEDULED", "API"]), - duration: Mock.Random.integer(1, 120), - retryCount: Mock.Random.integer(0, 5), - recordsProcessed: Mock.Random.integer(100, 10000), - processId: Mock.Random.integer(1000, 9999), - errorMessage: Mock.Random.boolean() ? "" : Mock.Random.csentence(5, 20), - }; -} - -const executionLogList = new Array(100).fill(null).map(executionLogItem); - -module.exports = function (router) { - // 获取任务列表 - router.get(API.queryTasksUsingGet, (req, res) => { - const { keyword, status, page = 0, size = 10 } = req.query; - let filteredTasks = taskList; - if (keyword) { - filteredTasks = filteredTasks.filter((task) => - task.name.includes(keyword) - ); - } - if (status && status.length > 0) { - filteredTasks = filteredTasks.filter((task) => - status.includes(task.status) - ); - } - const startIndex = page * size; - const endIndex = startIndex + size; - const paginatedTasks = filteredTasks.slice(startIndex, endIndex); - - res.send({ - code: "0", - msg: "Success", - data: { - totalElements: filteredTasks.length, - page, - size, - content: paginatedTasks, - }, - }); - }); - - router.get(API.queryDataXTemplatesUsingGet, (req, res) => { - const { keyword, page = 0, size = 10 } = req.query; - let filteredTemplates = templateList; - if (keyword) { - filteredTemplates = filteredTemplates.filter((template) => - template.name.includes(keyword) - ); - } - const startIndex = page * size; - const endIndex = startIndex + size; - const paginatedTemplates = filteredTemplates.slice(startIndex, endIndex); - res.send({ - code: "0", - msg: "Success", - data: { - content: paginatedTemplates, - totalElements: filteredTemplates.length, - page, - size, - }, - }); - }); - - // 创建任务 - router.post(API.createTaskUsingPost, (req, res) => { - taskList.unshift(taskItem()); // 添加一个新的任务到列表开头 - res.send({ - code: "0", - msg: "任务创建成功", - data: { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - }, - }); - }); - - // 更新任务 - router.post(API.updateTaskByIdUsingPut, (req, res) => { - const { id } = req.body; - res.send({ - code: "0", - msg: "Data source task updated successfully", - data: taskList.find((task) => task.id === id), - }); - }); - - // 删除任务 - router.post(API.deleteTaskByIdUsingDelete, (req, res) => { - const { id } = req.body; - const index = taskList.findIndex((task) => task.id === id); - if (index !== -1) { - taskList.splice(index, 1); - } - res.send({ - code: "0", - msg: "Data source task deleted successfully", - data: null, - }); - }); - - // 执行任务 - router.post(API.executeTaskByIdUsingPost, (req, res) => { - console.log("Received request to execute task", req.body); - const { id } = req.body; - console.log("Executing task with ID:", id); - taskList.find((task) => task.id === id).status = "RUNNING"; - res.send({ - code: "0", - msg: "Data source task execution started", - data: null, - }); - }); - - // 停止任务 - router.post(API.stopTaskByIdUsingPost, (req, res) => { - const { id } = req.body; - const task = taskList.find((task) => task.id === id); - if (task) { - task.status = "STOPPED"; - } - res.send({ - code: "0", - msg: "Data source task stopped successfully", - data: null, - }); - }); - - // 获取任务执行日志 - router.post(API.queryExecutionLogUsingPost, (req, res) => { - const { keyword, page = 1, size = 10, status } = req.body; - let filteredLogs = executionLogList; - if (keyword) { - filteredLogs = filteredLogs.filter((log) => - log.taskName.includes(keyword) - ); - } - if (status && status.length > 0) { - filteredLogs = filteredLogs.filter((log) => status.includes(log.status)); - } - const startIndex = (page - 1) * size; - const endIndex = startIndex + size; - const paginatedLogs = filteredLogs.slice(startIndex, endIndex); - res.send({ - code: "0", - msg: "Success", - data: { - totalElements: filteredLogs.length, - page, - size, - results: paginatedLogs, - }, - }); - }); - - // 获取任务执行日志详情 - router.post(API.queryExecutionLogByIdUsingGet, (req, res) => { - const { id } = req.body; - const log = executionLogList.find((log) => log.id === id); - res.send({ - code: "0", - msg: "Success", - data: log, - }); - }); -}; +const Mock = require("mockjs"); +const API = require("../mock-apis.cjs"); +const { Random } = Mock; + +// 生成模拟数据归集统计信息 +function dataXTemplate() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.ctitle(5, 15), + sourceType: Mock.Random.csentence(3, 10), + targetType: Mock.Random.csentence(3, 10), + description: Mock.Random.csentence(5, 20), + version: `v${Mock.Random.integer(1, 5)}.${Mock.Random.integer( + 0, + 9 + )}.${Mock.Random.integer(0, 9)}`, + isSystem: Mock.Random.boolean(), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + }; +} + +const templateList = new Array(20).fill(null).map(dataXTemplate); + +// 生成模拟任务数据 +function taskItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.ctitle(5, 20), + description: Mock.Random.csentence(5, 20), + syncMode: Mock.Random.pick(["ONCE", "SCHEDULED"]), + config: { + query: "SELECT * FROM table WHERE condition", + batchSize: Mock.Random.integer(100, 1000), + frequency: Mock.Random.integer(1, 60), // in minutes + }, + scheduleExpression: "0 0 * * *", // cron expression + lastExecutionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + status: Mock.Random.pick([ + "DRAFT", + "READY", + "RUNNING", + "FAILED", + "STOPPED", + "SUCCESS", + ]), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + sourceDataSourceId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + sourceDataSourceName: Mock.Random.ctitle(5, 20), + targetDataSourceId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + targetDataSourceName: Mock.Random.ctitle(5, 20), + }; +} + +const taskList = new Array(50).fill(null).map(taskItem); + +// 生成模拟任务执行日志数据 +function executionLogItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + taskName: Mock.Random.ctitle(5, 20), + dataSource: Mock.Random.ctitle(5, 15), + startTime: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + endTime: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + status: Mock.Random.pick(["SUCCESS", "FAILED", "RUNNING"]), + triggerType: Mock.Random.pick(["MANUAL", "SCHEDULED", "API"]), + duration: Mock.Random.integer(1, 120), + retryCount: Mock.Random.integer(0, 5), + recordsProcessed: Mock.Random.integer(100, 10000), + processId: Mock.Random.integer(1000, 9999), + errorMessage: Mock.Random.boolean() ? "" : Mock.Random.csentence(5, 20), + }; +} + +const executionLogList = new Array(100).fill(null).map(executionLogItem); + +module.exports = function (router) { + // 获取任务列表 + router.get(API.queryTasksUsingGet, (req, res) => { + const { keyword, status, page = 0, size = 10 } = req.query; + let filteredTasks = taskList; + if (keyword) { + filteredTasks = filteredTasks.filter((task) => + task.name.includes(keyword) + ); + } + if (status && status.length > 0) { + filteredTasks = filteredTasks.filter((task) => + status.includes(task.status) + ); + } + const startIndex = page * size; + const endIndex = startIndex + size; + const paginatedTasks = filteredTasks.slice(startIndex, endIndex); + + res.send({ + code: "0", + msg: "Success", + data: { + totalElements: filteredTasks.length, + page, + size, + content: paginatedTasks, + }, + }); + }); + + router.get(API.queryDataXTemplatesUsingGet, (req, res) => { + const { keyword, page = 0, size = 10 } = req.query; + let filteredTemplates = templateList; + if (keyword) { + filteredTemplates = filteredTemplates.filter((template) => + template.name.includes(keyword) + ); + } + const startIndex = page * size; + const endIndex = startIndex + size; + const paginatedTemplates = filteredTemplates.slice(startIndex, endIndex); + res.send({ + code: "0", + msg: "Success", + data: { + content: paginatedTemplates, + totalElements: filteredTemplates.length, + page, + size, + }, + }); + }); + + // 创建任务 + router.post(API.createTaskUsingPost, (req, res) => { + taskList.unshift(taskItem()); // 添加一个新的任务到列表开头 + res.send({ + code: "0", + msg: "任务创建成功", + data: { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + }, + }); + }); + + // 更新任务 + router.post(API.updateTaskByIdUsingPut, (req, res) => { + const { id } = req.body; + res.send({ + code: "0", + msg: "Data source task updated successfully", + data: taskList.find((task) => task.id === id), + }); + }); + + // 删除任务 + router.post(API.deleteTaskByIdUsingDelete, (req, res) => { + const { id } = req.body; + const index = taskList.findIndex((task) => task.id === id); + if (index !== -1) { + taskList.splice(index, 1); + } + res.send({ + code: "0", + msg: "Data source task deleted successfully", + data: null, + }); + }); + + // 执行任务 + router.post(API.executeTaskByIdUsingPost, (req, res) => { + console.log("Received request to execute task", req.body); + const { id } = req.body; + console.log("Executing task with ID:", id); + taskList.find((task) => task.id === id).status = "RUNNING"; + res.send({ + code: "0", + msg: "Data source task execution started", + data: null, + }); + }); + + // 停止任务 + router.post(API.stopTaskByIdUsingPost, (req, res) => { + const { id } = req.body; + const task = taskList.find((task) => task.id === id); + if (task) { + task.status = "STOPPED"; + } + res.send({ + code: "0", + msg: "Data source task stopped successfully", + data: null, + }); + }); + + // 获取任务执行日志 + router.post(API.queryExecutionLogUsingPost, (req, res) => { + const { keyword, page = 1, size = 10, status } = req.body; + let filteredLogs = executionLogList; + if (keyword) { + filteredLogs = filteredLogs.filter((log) => + log.taskName.includes(keyword) + ); + } + if (status && status.length > 0) { + filteredLogs = filteredLogs.filter((log) => status.includes(log.status)); + } + const startIndex = (page - 1) * size; + const endIndex = startIndex + size; + const paginatedLogs = filteredLogs.slice(startIndex, endIndex); + res.send({ + code: "0", + msg: "Success", + data: { + totalElements: filteredLogs.length, + page, + size, + results: paginatedLogs, + }, + }); + }); + + // 获取任务执行日志详情 + router.post(API.queryExecutionLogByIdUsingGet, (req, res) => { + const { id } = req.body; + const log = executionLogList.find((log) => log.id === id); + res.send({ + code: "0", + msg: "Success", + data: log, + }); + }); +}; diff --git a/frontend/src/mock/mock-seed/data-evaluation.cjs b/frontend/src/mock/mock-seed/data-evaluation.cjs index c241de70e..0c96a4ca3 100644 --- a/frontend/src/mock/mock-seed/data-evaluation.cjs +++ b/frontend/src/mock/mock-seed/data-evaluation.cjs @@ -1,501 +1,501 @@ -const Mock = require("mockjs"); -const API = require("../mock-apis.cjs"); - -// 质量指标枚举 -const QualityMetrics = [ - "COMPLETENESS", - "ACCURACY", - "CONSISTENCY", - "VALIDITY", - "UNIQUENESS", - "TIMELINESS" -]; - -// 适配性标准枚举 -const CompatibilityCriteria = [ - "FORMAT_COMPATIBILITY", - "SCHEMA_COMPATIBILITY", - "SIZE_ADEQUACY", - "DISTRIBUTION_MATCH", - "FEATURE_COVERAGE" -]; - -// 价值标准枚举 -const ValueCriteria = [ - "RARITY", - "DEMAND", - "QUALITY", - "COMPLETENESS", - "TIMELINESS", - "STRATEGIC_IMPORTANCE" -]; - -// 评估类型枚举 -const EvaluationTypes = ["QUALITY", "COMPATIBILITY", "VALUE", "COMPREHENSIVE"]; - -// 评估状态枚举 -const EvaluationStatuses = ["PENDING", "RUNNING", "COMPLETED", "FAILED"]; - -// 生成质量评估结果 -function qualityEvaluationItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - status: Mock.Random.pick(EvaluationStatuses), - overallScore: Mock.Random.float(0.6, 1.0, 2, 2), - metrics: Mock.Random.shuffle(QualityMetrics).slice(0, Mock.Random.integer(3, 5)).map(metric => ({ - metric, - score: Mock.Random.float(0.5, 1.0, 2, 2), - details: { - totalRecords: Mock.Random.integer(1000, 100000), - validRecords: Mock.Random.integer(800, 95000), - issues: Mock.Random.integer(0, 50) - }, - issues: new Array(Mock.Random.integer(0, 3)).fill(null).map(() => ({ - type: Mock.Random.pick(["MISSING_VALUE", "INVALID_FORMAT", "DUPLICATE", "OUTLIER"]), - severity: Mock.Random.pick(["LOW", "MEDIUM", "HIGH", "CRITICAL"]), - description: Mock.Random.csentence(5, 15), - affectedRecords: Mock.Random.integer(1, 1000), - suggestions: [Mock.Random.csentence(5, 20)] - })) - })), - recommendations: new Array(Mock.Random.integer(2, 5)).fill(null).map(() => - Mock.Random.csentence(10, 30) - ), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - detailedResults: { - fieldAnalysis: new Array(Mock.Random.integer(3, 8)).fill(null).map(() => ({ - fieldName: Mock.Random.word(5, 10), - dataType: Mock.Random.pick(["STRING", "INTEGER", "FLOAT", "BOOLEAN", "DATE"]), - nullCount: Mock.Random.integer(0, 100), - uniqueCount: Mock.Random.integer(100, 1000), - statistics: { - mean: Mock.Random.float(0, 100, 2, 2), - median: Mock.Random.float(0, 100, 2, 2), - stdDev: Mock.Random.float(0, 50, 2, 2) - } - })), - distributionAnalysis: { - distributions: new Array(3).fill(null).map(() => ({ - field: Mock.Random.word(5, 10), - type: Mock.Random.pick(["NORMAL", "UNIFORM", "SKEWED"]), - parameters: {} - })), - outliers: new Array(Mock.Random.integer(0, 5)).fill(null).map(() => ({ - field: Mock.Random.word(5, 10), - value: Mock.Random.float(-100, 100, 2, 2), - zScore: Mock.Random.float(-3, 3, 2, 2) - })), - patterns: [ - "数据分布较为均匀", - "存在少量异常值", - "部分字段相关性较强" - ] - }, - correlationAnalysis: { - correlationMatrix: new Array(5).fill(null).map(() => - new Array(5).fill(null).map(() => Mock.Random.float(-1, 1, 2, 2)) - ), - significantCorrelations: new Array(Mock.Random.integer(1, 3)).fill(null).map(() => ({ - field1: Mock.Random.word(5, 10), - field2: Mock.Random.word(5, 10), - correlation: Mock.Random.float(0.5, 1, 2, 2), - pValue: Mock.Random.float(0, 0.05, 3, 3) - })) - } - }, - visualizations: new Array(Mock.Random.integer(2, 4)).fill(null).map(() => ({ - type: Mock.Random.pick(["CHART", "GRAPH", "HISTOGRAM", "HEATMAP"]), - title: Mock.Random.ctitle(5, 15), - data: { - labels: new Array(5).fill(null).map(() => Mock.Random.word(3, 8)), - values: new Array(5).fill(null).map(() => Mock.Random.integer(0, 100)) - }, - config: { - width: 400, - height: 300, - color: Mock.Random.color() - } - })) - }; -} - -// 生成适配性评估结果 -function compatibilityEvaluationItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - targetType: Mock.Random.pick(["LANGUAGE_MODEL", "CLASSIFICATION_MODEL", "RECOMMENDATION_SYSTEM", "CUSTOM_TASK"]), - compatibilityScore: Mock.Random.float(0.6, 1.0, 2, 2), - results: Mock.Random.shuffle(CompatibilityCriteria).slice(0, Mock.Random.integer(3, 5)).map(criterion => ({ - criterion, - score: Mock.Random.float(0.5, 1.0, 2, 2), - status: Mock.Random.pick(["PASS", "WARN", "FAIL"]), - details: Mock.Random.csentence(10, 30) - })), - suggestions: new Array(Mock.Random.integer(2, 4)).fill(null).map(() => - Mock.Random.csentence(10, 25) - ), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss") - }; -} - -// 生成价值评估结果 -function valueEvaluationItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - valueScore: Mock.Random.float(0.6, 1.0, 2, 2), - monetaryValue: Mock.Random.float(10000, 1000000, 2, 2), - strategicValue: Mock.Random.float(0.6, 1.0, 2, 2), - results: Mock.Random.shuffle(ValueCriteria).slice(0, Mock.Random.integer(3, 5)).map(criterion => ({ - criterion, - score: Mock.Random.float(0.5, 1.0, 2, 2), - impact: Mock.Random.pick(["LOW", "MEDIUM", "HIGH"]), - explanation: Mock.Random.csentence(10, 30) - })), - insights: new Array(Mock.Random.integer(3, 6)).fill(null).map(() => - Mock.Random.csentence(15, 40) - ), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss") - }; -} - -// 生成评估报告 -function evaluationReportItem() { - const type = Mock.Random.pick(EvaluationTypes); - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - datasetName: Mock.Random.ctitle(5, 15), - type, - status: Mock.Random.pick(EvaluationStatuses), - overallScore: Mock.Random.float(0.6, 1.0, 2, 2), - summary: Mock.Random.csentence(20, 50), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - completedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - qualityResults: type === "QUALITY" || type === "COMPREHENSIVE" ? qualityEvaluationItem() : null, - compatibilityResults: type === "COMPATIBILITY" || type === "COMPREHENSIVE" ? compatibilityEvaluationItem() : null, - valueResults: type === "VALUE" || type === "COMPREHENSIVE" ? valueEvaluationItem() : null, - attachments: new Array(Mock.Random.integer(1, 3)).fill(null).map(() => ({ - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.word(5, 10) + "." + Mock.Random.pick(["pdf", "xlsx", "json"]), - type: Mock.Random.pick(["PDF", "EXCEL", "JSON"]), - size: Mock.Random.integer(1024, 1024 * 1024), - downloadUrl: "/api/v1/evaluation/attachments/" + Mock.Random.guid() - })) - }; -} - -const qualityEvaluationList = new Array(30).fill(null).map(qualityEvaluationItem); -const compatibilityEvaluationList = new Array(20).fill(null).map(compatibilityEvaluationItem); -const valueEvaluationList = new Array(25).fill(null).map(valueEvaluationItem); -const evaluationReportList = new Array(50).fill(null).map(evaluationReportItem); - -module.exports = function (router) { - // 数据质量评估 - router.post(API.evaluateDataQualityUsingPost, (req, res) => { - const { datasetId, metrics, sampleSize, parameters } = req.body; - - const newEvaluation = { - ...qualityEvaluationItem(), - datasetId, - status: "RUNNING", - metrics: metrics.map(metric => ({ - metric, - score: Mock.Random.float(0.5, 1.0, 2, 2), - details: { - totalRecords: sampleSize || Mock.Random.integer(1000, 100000), - validRecords: Mock.Random.integer(800, 95000), - issues: Mock.Random.integer(0, 50) - }, - issues: [] - })), - createdAt: new Date().toISOString() - }; - - qualityEvaluationList.push(newEvaluation); - - // 模拟异步处理,2秒后完成 - setTimeout(() => { - newEvaluation.status = "COMPLETED"; - }, 2000); - - res.send({ - code: "0", - msg: "Quality evaluation started successfully", - data: newEvaluation - }); - }); - - // 获取质量评估结果 - router.get(API.getQualityEvaluationByIdUsingGet, (req, res) => { - const { evaluationId } = req.params; - const evaluation = qualityEvaluationList.find(e => e.id === evaluationId); - - if (evaluation) { - res.send({ - code: "0", - msg: "Success", - data: evaluation - }); - } else { - res.status(404).send({ - code: "1", - msg: "Quality evaluation not found", - data: null - }); - } - }); - - // 适配性评估 - router.post(API.evaluateCompatibilityUsingPost, (req, res) => { - const { datasetId, targetType, targetConfig, evaluationCriteria } = req.body; - - const newEvaluation = { - ...compatibilityEvaluationItem(), - datasetId, - targetType, - results: evaluationCriteria.map(criterion => ({ - criterion, - score: Mock.Random.float(0.5, 1.0, 2, 2), - status: Mock.Random.pick(["PASS", "WARN", "FAIL"]), - details: Mock.Random.csentence(10, 30) - })), - createdAt: new Date().toISOString() - }; - - compatibilityEvaluationList.push(newEvaluation); - - res.send({ - code: "0", - msg: "Compatibility evaluation completed successfully", - data: newEvaluation - }); - }); - - // 价值评估 - router.post(API.evaluateValueUsingPost, (req, res) => { - const { datasetId, valueCriteria, marketContext, businessContext } = req.body; - - const newEvaluation = { - ...valueEvaluationItem(), - datasetId, - results: valueCriteria.map(criterion => ({ - criterion, - score: Mock.Random.float(0.5, 1.0, 2, 2), - impact: Mock.Random.pick(["LOW", "MEDIUM", "HIGH"]), - explanation: Mock.Random.csentence(10, 30) - })), - createdAt: new Date().toISOString() - }; - - valueEvaluationList.push(newEvaluation); - - res.send({ - code: "0", - msg: "Value evaluation completed successfully", - data: newEvaluation - }); - }); - - // 获取评估报告列表 - router.get(API.queryEvaluationReportsUsingGet, (req, res) => { - const { page = 0, size = 20, type, datasetId } = req.query; - let filteredReports = evaluationReportList; - - if (type) { - filteredReports = filteredReports.filter(report => report.type === type); - } - - if (datasetId) { - filteredReports = filteredReports.filter(report => report.datasetId === datasetId); - } - - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = filteredReports.slice(startIndex, endIndex); - - res.send({ - code: "0", - msg: "Success", - data: { - content: pageData, - totalElements: filteredReports.length, - totalPages: Math.ceil(filteredReports.length / size), - size: parseInt(size), - number: parseInt(page) - } - }); - }); - - // 获取评估报告详情 - router.get(API.getEvaluationReportByIdUsingGet, (req, res) => { - const { reportId } = req.params; - const report = evaluationReportList.find(r => r.id === reportId); - - if (report) { - res.send({ - code: "0", - msg: "Success", - data: report - }); - } else { - res.status(404).send({ - code: "1", - msg: "Evaluation report not found", - data: null - }); - } - }); - - // 导出评估报告 - router.get(API.exportEvaluationReportUsingGet, (req, res) => { - const { reportId } = req.params; - const { format = "PDF" } = req.query; - const report = evaluationReportList.find(r => r.id === reportId); - - if (report) { - const fileName = `evaluation_report_${reportId}.${format.toLowerCase()}`; - - res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`); - res.setHeader('Content-Type', 'application/octet-stream'); - res.send(`Mock ${format} content for evaluation report ${reportId}`); - } else { - res.status(404).send({ - code: "1", - msg: "Evaluation report not found", - data: null - }); - } - }); - - // 批量评估 - router.post(API.batchEvaluationUsingPost, (req, res) => { - const { datasetIds, evaluationTypes, parameters } = req.body; - - const batchId = Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""); - const totalTasks = datasetIds.length * evaluationTypes.length; - - // 为每个数据集和评估类型组合创建任务 - datasetIds.forEach(datasetId => { - evaluationTypes.forEach(type => { - const report = { - ...evaluationReportItem(), - datasetId, - type, - status: "PENDING", - batchId - }; - evaluationReportList.push(report); - - // 模拟异步处理 - setTimeout(() => { - report.status = "COMPLETED"; - }, Mock.Random.integer(3000, 10000)); - }); - }); - - res.status(202).send({ - code: "0", - msg: "Batch evaluation submitted successfully", - data: { - batchId, - status: "SUBMITTED", - totalTasks, - submittedAt: new Date().toISOString() - } - }); - }); - - // 获取批量评估状态 - router.get("/api/v1/evaluation/batch/:batchId", (req, res) => { - const { batchId } = req.params; - const batchReports = evaluationReportList.filter(r => r.batchId === batchId); - - const completedTasks = batchReports.filter(r => r.status === "COMPLETED").length; - const runningTasks = batchReports.filter(r => r.status === "RUNNING").length; - const pendingTasks = batchReports.filter(r => r.status === "PENDING").length; - const failedTasks = batchReports.filter(r => r.status === "FAILED").length; - - let overallStatus = "COMPLETED"; - if (runningTasks > 0 || pendingTasks > 0) { - overallStatus = "RUNNING"; - } else if (failedTasks > 0) { - overallStatus = "PARTIAL_FAILED"; - } - - res.send({ - code: "0", - msg: "Success", - data: { - batchId, - status: overallStatus, - totalTasks: batchReports.length, - completedTasks, - runningTasks, - pendingTasks, - failedTasks, - progress: batchReports.length > 0 ? Math.round((completedTasks / batchReports.length) * 100) : 0, - reports: batchReports - } - }); - }); - - // 获取评估统计信息 - router.get("/api/v1/evaluation/statistics", (req, res) => { - const { timeRange = "LAST_30_DAYS" } = req.query; - - const statistics = { - totalEvaluations: evaluationReportList.length, - completedEvaluations: evaluationReportList.filter(r => r.status === "COMPLETED").length, - runningEvaluations: evaluationReportList.filter(r => r.status === "RUNNING").length, - failedEvaluations: evaluationReportList.filter(r => r.status === "FAILED").length, - averageScore: Mock.Random.float(0.75, 0.95, 2, 2), - evaluationTypeDistribution: { - QUALITY: evaluationReportList.filter(r => r.type === "QUALITY").length, - COMPATIBILITY: evaluationReportList.filter(r => r.type === "COMPATIBILITY").length, - VALUE: evaluationReportList.filter(r => r.type === "VALUE").length, - COMPREHENSIVE: evaluationReportList.filter(r => r.type === "COMPREHENSIVE").length - }, - scoreDistribution: { - excellent: evaluationReportList.filter(r => r.overallScore >= 0.9).length, - good: evaluationReportList.filter(r => r.overallScore >= 0.8 && r.overallScore < 0.9).length, - fair: evaluationReportList.filter(r => r.overallScore >= 0.6 && r.overallScore < 0.8).length, - poor: evaluationReportList.filter(r => r.overallScore < 0.6).length - }, - trends: new Array(30).fill(null).map((_, index) => ({ - date: Mock.Random.date("yyyy-MM-dd"), - evaluations: Mock.Random.integer(5, 50), - averageScore: Mock.Random.float(0.7, 0.95, 2, 2) - })) - }; - - res.send({ - code: "0", - msg: "Success", - data: statistics - }); - }); - - // 删除评估报告 - router.delete("/api/v1/evaluation/reports/:reportId", (req, res) => { - const { reportId } = req.params; - const index = evaluationReportList.findIndex(r => r.id === reportId); - - if (index !== -1) { - evaluationReportList.splice(index, 1); - res.send({ - code: "0", - msg: "Evaluation report deleted successfully", - data: null - }); - } else { - res.status(404).send({ - code: "1", - msg: "Evaluation report not found", - data: null - }); - } - }); +const Mock = require("mockjs"); +const API = require("../mock-apis.cjs"); + +// 质量指标枚举 +const QualityMetrics = [ + "COMPLETENESS", + "ACCURACY", + "CONSISTENCY", + "VALIDITY", + "UNIQUENESS", + "TIMELINESS" +]; + +// 适配性标准枚举 +const CompatibilityCriteria = [ + "FORMAT_COMPATIBILITY", + "SCHEMA_COMPATIBILITY", + "SIZE_ADEQUACY", + "DISTRIBUTION_MATCH", + "FEATURE_COVERAGE" +]; + +// 价值标准枚举 +const ValueCriteria = [ + "RARITY", + "DEMAND", + "QUALITY", + "COMPLETENESS", + "TIMELINESS", + "STRATEGIC_IMPORTANCE" +]; + +// 评估类型枚举 +const EvaluationTypes = ["QUALITY", "COMPATIBILITY", "VALUE", "COMPREHENSIVE"]; + +// 评估状态枚举 +const EvaluationStatuses = ["PENDING", "RUNNING", "COMPLETED", "FAILED"]; + +// 生成质量评估结果 +function qualityEvaluationItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + status: Mock.Random.pick(EvaluationStatuses), + overallScore: Mock.Random.float(0.6, 1.0, 2, 2), + metrics: Mock.Random.shuffle(QualityMetrics).slice(0, Mock.Random.integer(3, 5)).map(metric => ({ + metric, + score: Mock.Random.float(0.5, 1.0, 2, 2), + details: { + totalRecords: Mock.Random.integer(1000, 100000), + validRecords: Mock.Random.integer(800, 95000), + issues: Mock.Random.integer(0, 50) + }, + issues: new Array(Mock.Random.integer(0, 3)).fill(null).map(() => ({ + type: Mock.Random.pick(["MISSING_VALUE", "INVALID_FORMAT", "DUPLICATE", "OUTLIER"]), + severity: Mock.Random.pick(["LOW", "MEDIUM", "HIGH", "CRITICAL"]), + description: Mock.Random.csentence(5, 15), + affectedRecords: Mock.Random.integer(1, 1000), + suggestions: [Mock.Random.csentence(5, 20)] + })) + })), + recommendations: new Array(Mock.Random.integer(2, 5)).fill(null).map(() => + Mock.Random.csentence(10, 30) + ), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + detailedResults: { + fieldAnalysis: new Array(Mock.Random.integer(3, 8)).fill(null).map(() => ({ + fieldName: Mock.Random.word(5, 10), + dataType: Mock.Random.pick(["STRING", "INTEGER", "FLOAT", "BOOLEAN", "DATE"]), + nullCount: Mock.Random.integer(0, 100), + uniqueCount: Mock.Random.integer(100, 1000), + statistics: { + mean: Mock.Random.float(0, 100, 2, 2), + median: Mock.Random.float(0, 100, 2, 2), + stdDev: Mock.Random.float(0, 50, 2, 2) + } + })), + distributionAnalysis: { + distributions: new Array(3).fill(null).map(() => ({ + field: Mock.Random.word(5, 10), + type: Mock.Random.pick(["NORMAL", "UNIFORM", "SKEWED"]), + parameters: {} + })), + outliers: new Array(Mock.Random.integer(0, 5)).fill(null).map(() => ({ + field: Mock.Random.word(5, 10), + value: Mock.Random.float(-100, 100, 2, 2), + zScore: Mock.Random.float(-3, 3, 2, 2) + })), + patterns: [ + "数据分布较为均匀", + "存在少量异常值", + "部分字段相关性较强" + ] + }, + correlationAnalysis: { + correlationMatrix: new Array(5).fill(null).map(() => + new Array(5).fill(null).map(() => Mock.Random.float(-1, 1, 2, 2)) + ), + significantCorrelations: new Array(Mock.Random.integer(1, 3)).fill(null).map(() => ({ + field1: Mock.Random.word(5, 10), + field2: Mock.Random.word(5, 10), + correlation: Mock.Random.float(0.5, 1, 2, 2), + pValue: Mock.Random.float(0, 0.05, 3, 3) + })) + } + }, + visualizations: new Array(Mock.Random.integer(2, 4)).fill(null).map(() => ({ + type: Mock.Random.pick(["CHART", "GRAPH", "HISTOGRAM", "HEATMAP"]), + title: Mock.Random.ctitle(5, 15), + data: { + labels: new Array(5).fill(null).map(() => Mock.Random.word(3, 8)), + values: new Array(5).fill(null).map(() => Mock.Random.integer(0, 100)) + }, + config: { + width: 400, + height: 300, + color: Mock.Random.color() + } + })) + }; +} + +// 生成适配性评估结果 +function compatibilityEvaluationItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + targetType: Mock.Random.pick(["LANGUAGE_MODEL", "CLASSIFICATION_MODEL", "RECOMMENDATION_SYSTEM", "CUSTOM_TASK"]), + compatibilityScore: Mock.Random.float(0.6, 1.0, 2, 2), + results: Mock.Random.shuffle(CompatibilityCriteria).slice(0, Mock.Random.integer(3, 5)).map(criterion => ({ + criterion, + score: Mock.Random.float(0.5, 1.0, 2, 2), + status: Mock.Random.pick(["PASS", "WARN", "FAIL"]), + details: Mock.Random.csentence(10, 30) + })), + suggestions: new Array(Mock.Random.integer(2, 4)).fill(null).map(() => + Mock.Random.csentence(10, 25) + ), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss") + }; +} + +// 生成价值评估结果 +function valueEvaluationItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + valueScore: Mock.Random.float(0.6, 1.0, 2, 2), + monetaryValue: Mock.Random.float(10000, 1000000, 2, 2), + strategicValue: Mock.Random.float(0.6, 1.0, 2, 2), + results: Mock.Random.shuffle(ValueCriteria).slice(0, Mock.Random.integer(3, 5)).map(criterion => ({ + criterion, + score: Mock.Random.float(0.5, 1.0, 2, 2), + impact: Mock.Random.pick(["LOW", "MEDIUM", "HIGH"]), + explanation: Mock.Random.csentence(10, 30) + })), + insights: new Array(Mock.Random.integer(3, 6)).fill(null).map(() => + Mock.Random.csentence(15, 40) + ), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss") + }; +} + +// 生成评估报告 +function evaluationReportItem() { + const type = Mock.Random.pick(EvaluationTypes); + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + datasetName: Mock.Random.ctitle(5, 15), + type, + status: Mock.Random.pick(EvaluationStatuses), + overallScore: Mock.Random.float(0.6, 1.0, 2, 2), + summary: Mock.Random.csentence(20, 50), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + completedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + qualityResults: type === "QUALITY" || type === "COMPREHENSIVE" ? qualityEvaluationItem() : null, + compatibilityResults: type === "COMPATIBILITY" || type === "COMPREHENSIVE" ? compatibilityEvaluationItem() : null, + valueResults: type === "VALUE" || type === "COMPREHENSIVE" ? valueEvaluationItem() : null, + attachments: new Array(Mock.Random.integer(1, 3)).fill(null).map(() => ({ + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.word(5, 10) + "." + Mock.Random.pick(["pdf", "xlsx", "json"]), + type: Mock.Random.pick(["PDF", "EXCEL", "JSON"]), + size: Mock.Random.integer(1024, 1024 * 1024), + downloadUrl: "/api/v1/evaluation/attachments/" + Mock.Random.guid() + })) + }; +} + +const qualityEvaluationList = new Array(30).fill(null).map(qualityEvaluationItem); +const compatibilityEvaluationList = new Array(20).fill(null).map(compatibilityEvaluationItem); +const valueEvaluationList = new Array(25).fill(null).map(valueEvaluationItem); +const evaluationReportList = new Array(50).fill(null).map(evaluationReportItem); + +module.exports = function (router) { + // 数据质量评估 + router.post(API.evaluateDataQualityUsingPost, (req, res) => { + const { datasetId, metrics, sampleSize, parameters } = req.body; + + const newEvaluation = { + ...qualityEvaluationItem(), + datasetId, + status: "RUNNING", + metrics: metrics.map(metric => ({ + metric, + score: Mock.Random.float(0.5, 1.0, 2, 2), + details: { + totalRecords: sampleSize || Mock.Random.integer(1000, 100000), + validRecords: Mock.Random.integer(800, 95000), + issues: Mock.Random.integer(0, 50) + }, + issues: [] + })), + createdAt: new Date().toISOString() + }; + + qualityEvaluationList.push(newEvaluation); + + // 模拟异步处理,2秒后完成 + setTimeout(() => { + newEvaluation.status = "COMPLETED"; + }, 2000); + + res.send({ + code: "0", + msg: "Quality evaluation started successfully", + data: newEvaluation + }); + }); + + // 获取质量评估结果 + router.get(API.getQualityEvaluationByIdUsingGet, (req, res) => { + const { evaluationId } = req.params; + const evaluation = qualityEvaluationList.find(e => e.id === evaluationId); + + if (evaluation) { + res.send({ + code: "0", + msg: "Success", + data: evaluation + }); + } else { + res.status(404).send({ + code: "1", + msg: "Quality evaluation not found", + data: null + }); + } + }); + + // 适配性评估 + router.post(API.evaluateCompatibilityUsingPost, (req, res) => { + const { datasetId, targetType, targetConfig, evaluationCriteria } = req.body; + + const newEvaluation = { + ...compatibilityEvaluationItem(), + datasetId, + targetType, + results: evaluationCriteria.map(criterion => ({ + criterion, + score: Mock.Random.float(0.5, 1.0, 2, 2), + status: Mock.Random.pick(["PASS", "WARN", "FAIL"]), + details: Mock.Random.csentence(10, 30) + })), + createdAt: new Date().toISOString() + }; + + compatibilityEvaluationList.push(newEvaluation); + + res.send({ + code: "0", + msg: "Compatibility evaluation completed successfully", + data: newEvaluation + }); + }); + + // 价值评估 + router.post(API.evaluateValueUsingPost, (req, res) => { + const { datasetId, valueCriteria, marketContext, businessContext } = req.body; + + const newEvaluation = { + ...valueEvaluationItem(), + datasetId, + results: valueCriteria.map(criterion => ({ + criterion, + score: Mock.Random.float(0.5, 1.0, 2, 2), + impact: Mock.Random.pick(["LOW", "MEDIUM", "HIGH"]), + explanation: Mock.Random.csentence(10, 30) + })), + createdAt: new Date().toISOString() + }; + + valueEvaluationList.push(newEvaluation); + + res.send({ + code: "0", + msg: "Value evaluation completed successfully", + data: newEvaluation + }); + }); + + // 获取评估报告列表 + router.get(API.queryEvaluationReportsUsingGet, (req, res) => { + const { page = 0, size = 20, type, datasetId } = req.query; + let filteredReports = evaluationReportList; + + if (type) { + filteredReports = filteredReports.filter(report => report.type === type); + } + + if (datasetId) { + filteredReports = filteredReports.filter(report => report.datasetId === datasetId); + } + + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = filteredReports.slice(startIndex, endIndex); + + res.send({ + code: "0", + msg: "Success", + data: { + content: pageData, + totalElements: filteredReports.length, + totalPages: Math.ceil(filteredReports.length / size), + size: parseInt(size), + number: parseInt(page) + } + }); + }); + + // 获取评估报告详情 + router.get(API.getEvaluationReportByIdUsingGet, (req, res) => { + const { reportId } = req.params; + const report = evaluationReportList.find(r => r.id === reportId); + + if (report) { + res.send({ + code: "0", + msg: "Success", + data: report + }); + } else { + res.status(404).send({ + code: "1", + msg: "Evaluation report not found", + data: null + }); + } + }); + + // 导出评估报告 + router.get(API.exportEvaluationReportUsingGet, (req, res) => { + const { reportId } = req.params; + const { format = "PDF" } = req.query; + const report = evaluationReportList.find(r => r.id === reportId); + + if (report) { + const fileName = `evaluation_report_${reportId}.${format.toLowerCase()}`; + + res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`); + res.setHeader('Content-Type', 'application/octet-stream'); + res.send(`Mock ${format} content for evaluation report ${reportId}`); + } else { + res.status(404).send({ + code: "1", + msg: "Evaluation report not found", + data: null + }); + } + }); + + // 批量评估 + router.post(API.batchEvaluationUsingPost, (req, res) => { + const { datasetIds, evaluationTypes, parameters } = req.body; + + const batchId = Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""); + const totalTasks = datasetIds.length * evaluationTypes.length; + + // 为每个数据集和评估类型组合创建任务 + datasetIds.forEach(datasetId => { + evaluationTypes.forEach(type => { + const report = { + ...evaluationReportItem(), + datasetId, + type, + status: "PENDING", + batchId + }; + evaluationReportList.push(report); + + // 模拟异步处理 + setTimeout(() => { + report.status = "COMPLETED"; + }, Mock.Random.integer(3000, 10000)); + }); + }); + + res.status(202).send({ + code: "0", + msg: "Batch evaluation submitted successfully", + data: { + batchId, + status: "SUBMITTED", + totalTasks, + submittedAt: new Date().toISOString() + } + }); + }); + + // 获取批量评估状态 + router.get("/api/v1/evaluation/batch/:batchId", (req, res) => { + const { batchId } = req.params; + const batchReports = evaluationReportList.filter(r => r.batchId === batchId); + + const completedTasks = batchReports.filter(r => r.status === "COMPLETED").length; + const runningTasks = batchReports.filter(r => r.status === "RUNNING").length; + const pendingTasks = batchReports.filter(r => r.status === "PENDING").length; + const failedTasks = batchReports.filter(r => r.status === "FAILED").length; + + let overallStatus = "COMPLETED"; + if (runningTasks > 0 || pendingTasks > 0) { + overallStatus = "RUNNING"; + } else if (failedTasks > 0) { + overallStatus = "PARTIAL_FAILED"; + } + + res.send({ + code: "0", + msg: "Success", + data: { + batchId, + status: overallStatus, + totalTasks: batchReports.length, + completedTasks, + runningTasks, + pendingTasks, + failedTasks, + progress: batchReports.length > 0 ? Math.round((completedTasks / batchReports.length) * 100) : 0, + reports: batchReports + } + }); + }); + + // 获取评估统计信息 + router.get("/api/v1/evaluation/statistics", (req, res) => { + const { timeRange = "LAST_30_DAYS" } = req.query; + + const statistics = { + totalEvaluations: evaluationReportList.length, + completedEvaluations: evaluationReportList.filter(r => r.status === "COMPLETED").length, + runningEvaluations: evaluationReportList.filter(r => r.status === "RUNNING").length, + failedEvaluations: evaluationReportList.filter(r => r.status === "FAILED").length, + averageScore: Mock.Random.float(0.75, 0.95, 2, 2), + evaluationTypeDistribution: { + QUALITY: evaluationReportList.filter(r => r.type === "QUALITY").length, + COMPATIBILITY: evaluationReportList.filter(r => r.type === "COMPATIBILITY").length, + VALUE: evaluationReportList.filter(r => r.type === "VALUE").length, + COMPREHENSIVE: evaluationReportList.filter(r => r.type === "COMPREHENSIVE").length + }, + scoreDistribution: { + excellent: evaluationReportList.filter(r => r.overallScore >= 0.9).length, + good: evaluationReportList.filter(r => r.overallScore >= 0.8 && r.overallScore < 0.9).length, + fair: evaluationReportList.filter(r => r.overallScore >= 0.6 && r.overallScore < 0.8).length, + poor: evaluationReportList.filter(r => r.overallScore < 0.6).length + }, + trends: new Array(30).fill(null).map((_, index) => ({ + date: Mock.Random.date("yyyy-MM-dd"), + evaluations: Mock.Random.integer(5, 50), + averageScore: Mock.Random.float(0.7, 0.95, 2, 2) + })) + }; + + res.send({ + code: "0", + msg: "Success", + data: statistics + }); + }); + + // 删除评估报告 + router.delete("/api/v1/evaluation/reports/:reportId", (req, res) => { + const { reportId } = req.params; + const index = evaluationReportList.findIndex(r => r.id === reportId); + + if (index !== -1) { + evaluationReportList.splice(index, 1); + res.send({ + code: "0", + msg: "Evaluation report deleted successfully", + data: null + }); + } else { + res.status(404).send({ + code: "1", + msg: "Evaluation report not found", + data: null + }); + } + }); }; \ No newline at end of file diff --git a/frontend/src/mock/mock-seed/data-management.cjs b/frontend/src/mock/mock-seed/data-management.cjs index b1702cef3..aa9f9531b 100644 --- a/frontend/src/mock/mock-seed/data-management.cjs +++ b/frontend/src/mock/mock-seed/data-management.cjs @@ -1,435 +1,435 @@ -const Mock = require("mockjs"); -const API = require("../mock-apis.cjs"); - -function tagItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.word(3, 10), - description: Mock.Random.csentence(5, 20), - color: Mock.Random.color(), - usageCount: Mock.Random.integer(0, 100), - }; -} -const tagList = new Array(20).fill(null).map((_, index) => tagItem(index)); - -function datasetItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.ctitle(5, 20), - datasetType: Mock.Random.pick(["TEXT", "IMAGE", "AUDIO", "VIDEO"]), - status: Mock.Random.pick(["DRAFT","ACTIVE", "INACTIVE", "PROCESSING"]), - tags: Mock.Random.shuffle(tagList).slice(0, Mock.Random.integer(1, 3)), - totalSize: Mock.Random.integer(1024, 1024 * 1024 * 1024), // in bytes - description: Mock.Random.cparagraph(1, 3), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - createdBy: Mock.Random.cname(), - updatedBy: Mock.Random.cname(), - }; -} - -const datasetList = new Array(50) - .fill(null) - .map((_, index) => datasetItem(index)); - -function datasetFileItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - fileName: - Mock.Random.word(5, 15) + - "." + - Mock.Random.pick(["csv", "json", "xml", "parquet", "avro"]), - originName: - Mock.Random.word(5, 15) + - "." + - Mock.Random.pick(["csv", "json", "xml", "parquet", "avro"]), - fileType: Mock.Random.pick(["CSV", "JSON", "XML", "Parquet", "Avro"]), - size: Mock.Random.integer(1024, 1024 * 1024 * 1024), // in bytes - type: Mock.Random.pick(["CSV", "JSON", "XML", "Parquet", "Avro"]), - status: Mock.Random.pick(["UPLOADED", "PROCESSING", "COMPLETED", "ERROR"]), - description: Mock.Random.csentence(5, 20), - filePath: "/path/to/file/" + Mock.Random.word(5, 10), - uploadedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - uploadedBy: Mock.Random.cname(), - }; -} - -const datasetFileList = new Array(200) - .fill(null) - .map((_, index) => datasetFileItem(index)); - -const datasetStatistics = { - count: { - text: 10, - image: 34, - audio: 23, - video: 5, - }, - size: { - text: "120 MB", - image: "3.4 GB", - audio: "2.3 GB", - video: "15 GB", - }, - totalDatasets: datasetList.length, - totalFiles: datasetFileList.length, - completedFiles: datasetFileList.filter((file) => file.status === "COMPLETED") - .length, - totalSize: datasetFileList.reduce((acc, file) => acc + file.size, 0), // in bytes - completionRate: - datasetFileList.length === 0 - ? 0 - : Math.round( - (datasetFileList.filter((file) => file.status === "COMPLETED") - .length / - datasetFileList.length) * - 100 - ), // percentage -}; - -const datasetTypes = [ - { - code: "PRETRAIN", - name: "预训练数据集", - description: "用于模型预训练的大规模数据集", - supportedFormats: ["txt", "json", "csv", "parquet"], - icon: "brain", - }, - { - code: "FINE_TUNE", - name: "微调数据集", - description: "用于模型微调的专业数据集", - supportedFormats: ["json", "csv", "xlsx"], - icon: "tune", - }, - { - code: "EVAL", - name: "评估数据集", - description: "用于模型评估的标准数据集", - supportedFormats: ["json", "csv", "xml"], - icon: "assessment", - }, -]; - -module.exports = { datasetList }; -module.exports = function (router) { - // 获取数据统计信息 - router.get(API.queryDatasetStatisticsUsingGet, (req, res) => { - res.send({ - code: "0", - msg: "Success", - data: datasetStatistics, - }); - }); - - // 创建数据 - router.post(API.createDatasetUsingPost, (req, res) => { - const newDataset = { - ...req.body, - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - status: "ACTIVE", - fileCount: 0, - totalSize: 0, - completionRate: 0, - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - createdBy: "Admin", - updatedBy: "Admin", - tags: tagList.filter((tag) => req.body?.tagIds?.includes?.(tag.id)), - }; - datasetList.unshift(newDataset); // Add to the beginning of the list - res.send({ - code: "0", - msg: "Dataset created successfully", - data: newDataset, - }); - }); - - // 获取数据集列表 - router.get(API.queryDatasetsUsingGet, (req, res) => { - const { page = 0, size = 10, keyword, type, status, tags } = req.query; - console.log("Received query params:", req.query); - - let filteredDatasets = datasetList; - if (keyword) { - console.log("filter keyword:", keyword); - - filteredDatasets = filteredDatasets.filter( - (dataset) => - dataset.name.includes(keyword) || - dataset.description.includes(keyword) - ); - } - if (type) { - filteredDatasets = filteredDatasets.filter( - (dataset) => dataset.datasetType === type - ); - } - if (status) { - console.log("filter status:", status); - filteredDatasets = filteredDatasets.filter( - (dataset) => dataset.status === status - ); - } - if (tags && tags.length > 0) { - console.log("filter tags:", tags); - filteredDatasets = filteredDatasets.filter((dataset) => - tags.every((tag) => dataset.tags.some((t) => t.name === tag)) - ); - } - - const totalElements = filteredDatasets.length; - const paginatedDatasets = filteredDatasets.slice( - page * size, - (page + 1) * size - ); - - res.send({ - code: "0", - msg: "Success", - data: { - totalElements, - page, - size, - content: paginatedDatasets, - }, - }); - }); - - // 根据ID获取数据集详情 - router.get(API.queryDatasetByIdUsingGet, (req, res) => { - const { id } = req.params; - - const dataset = datasetList.find((d) => d.id === id); - if (dataset) { - res.send({ - code: "0", - msg: "Success", - data: dataset, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Dataset not found", - data: null, - }); - } - }); - - // 更新数据集 - router.put(API.updateDatasetByIdUsingPut, (req, res) => { - const { id } = req.params; - let { tags } = req.body; - - const index = datasetList.findIndex((d) => d.id === id); - tags = [...datasetList[index].tags.map((tag) => tag.name), ...tags]; - if (index !== -1) { - datasetList[index] = { - ...datasetList[index], - ...req.body, - tags: tagList.filter((tag) => tags?.includes?.(tag.name)), - updatedAt: new Date().toISOString(), - updatedBy: "Admin", - }; - res.send({ - code: "0", - msg: "Dataset updated successfully", - data: datasetList[index], - }); - } else { - res.status(404).send({ - code: "1", - msg: "Dataset not found", - data: null, - }); - } - }); - - // 删除数据集 - router.delete(API.deleteDatasetByIdUsingDelete, (req, res) => { - const { datasetId } = req.params; - const index = datasetList.findIndex((d) => d.id === datasetId); - - if (index !== -1) { - datasetList.splice(index, 1); - res.status(204).send(); - } else { - res.status(404).send({ - code: "1", - msg: "Dataset not found", - data: null, - }); - } - }); - - // 获取数据集文件列表 - router.get(API.queryFilesUsingGet, (req, res) => { - const { datasetId } = req.params; - const { page = 0, size = 20, fileType, status } = req.query; - - let filteredFiles = datasetFileList; - - if (fileType) { - filteredFiles = filteredFiles.filter( - (file) => file.fileType === fileType - ); - } - - if (status) { - filteredFiles = filteredFiles.filter((file) => file.status === status); - } - - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = filteredFiles.slice(startIndex, endIndex); - - res.send({ - code: "0", - msg: "Success", - data: { - content: pageData, - page: parseInt(page), - size: parseInt(size), - totalElements: filteredFiles.length, - }, - }); - }); - - // 上传文件到数据集 - router.post(API.uploadFileUsingPost, (req, res) => { - const { datasetId } = req.params; - const newFile = { - ...datasetFileItem(), - ...req.body, - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - uploadedAt: new Date().toISOString(), - uploadedBy: "Admin", - }; - - datasetFileList.push(newFile); - - res.status(201).send({ - code: "0", - msg: "File uploaded successfully", - data: newFile, - }); - }); - - // 获取文件详情 - router.get(API.queryFileByIdUsingGet, (req, res) => { - const { datasetId, fileId } = req.params; - const file = datasetFileList.find((f) => f.id === fileId); - - if (file) { - res.send({ - code: "0", - msg: "Success", - data: file, - }); - } else { - res.status(404).send({ - code: "1", - msg: "File not found", - data: null, - }); - } - }); - - // 删除文件 - router.delete(API.deleteFileByIdUsingDelete, (req, res) => { - const { datasetId, fileId } = req.params; - const index = datasetFileList.findIndex((f) => f.id === fileId); - - if (index !== -1) { - datasetFileList.splice(index, 1); - res.status(204).send(); - } else { - res.status(404).send({ - code: "1", - msg: "File not found", - data: null, - }); - } - }); - - // 下载文件 - router.get(API.downloadFileByIdUsingGet, (req, res) => { - const { datasetId, fileId } = req.params; - const file = datasetFileList.find((f) => f.id === fileId); - - if (file) { - res.setHeader( - "Content-Disposition", - `attachment; filename="${file.fileName}"` - ); - res.setHeader("Content-Type", "application/octet-stream"); - res.send(`Mock file content for ${file.fileName}`); - } else { - res.status(404).send({ - code: "1", - msg: "File not found", - data: null, - }); - } - }); - - // 获取数据集类型列表 - router.get(API.queryDatasetTypesUsingGet, (req, res) => { - res.send({ - code: "0", - msg: "Success", - data: datasetTypes, - }); - }); - - // 获取标签列表 - router.get(API.queryTagsUsingGet, (req, res) => { - const { keyword } = req.query; - let filteredTags = tagList; - - if (keyword) { - filteredTags = tagList.filter((tag) => - tag.name.toLowerCase().includes(keyword.toLowerCase()) - ); - } - - res.send({ - code: "0", - msg: "Success", - data: filteredTags, - }); - }); - - // 创建标签 - router.post(API.createTagUsingPost, (req, res) => { - const newTag = { - ...tagItem(), - ...req.body, - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - usageCount: 0, - }; - - tagList.push(newTag); - - res.status(201).send({ - code: "0", - msg: "Tag created successfully", - data: newTag, - }); - }); - - router.post(API.preUploadFileUsingPost, (req, res) => { - res.status(201).send(Mock.Random.guid()); - }); - - // 上传 - router.post(API.uploadFileChunkUsingPost, (req, res) => { - res.status(500).send({ message: "Simulated upload failure" }); - // res.status(201).send({ data: "success" }); - }); - - // 取消上传 - router.put(API.cancelUploadUsingPut, (req, res) => { - res.status(201).send({ data: "success" }); - }); -}; +const Mock = require("mockjs"); +const API = require("../mock-apis.cjs"); + +function tagItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.word(3, 10), + description: Mock.Random.csentence(5, 20), + color: Mock.Random.color(), + usageCount: Mock.Random.integer(0, 100), + }; +} +const tagList = new Array(20).fill(null).map((_, index) => tagItem(index)); + +function datasetItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.ctitle(5, 20), + datasetType: Mock.Random.pick(["TEXT", "IMAGE", "AUDIO", "VIDEO"]), + status: Mock.Random.pick(["DRAFT","ACTIVE", "INACTIVE", "PROCESSING"]), + tags: Mock.Random.shuffle(tagList).slice(0, Mock.Random.integer(1, 3)), + totalSize: Mock.Random.integer(1024, 1024 * 1024 * 1024), // in bytes + description: Mock.Random.cparagraph(1, 3), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + createdBy: Mock.Random.cname(), + updatedBy: Mock.Random.cname(), + }; +} + +const datasetList = new Array(50) + .fill(null) + .map((_, index) => datasetItem(index)); + +function datasetFileItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + fileName: + Mock.Random.word(5, 15) + + "." + + Mock.Random.pick(["csv", "json", "xml", "parquet", "avro"]), + originName: + Mock.Random.word(5, 15) + + "." + + Mock.Random.pick(["csv", "json", "xml", "parquet", "avro"]), + fileType: Mock.Random.pick(["CSV", "JSON", "XML", "Parquet", "Avro"]), + size: Mock.Random.integer(1024, 1024 * 1024 * 1024), // in bytes + type: Mock.Random.pick(["CSV", "JSON", "XML", "Parquet", "Avro"]), + status: Mock.Random.pick(["UPLOADED", "PROCESSING", "COMPLETED", "ERROR"]), + description: Mock.Random.csentence(5, 20), + filePath: "/path/to/file/" + Mock.Random.word(5, 10), + uploadedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + uploadedBy: Mock.Random.cname(), + }; +} + +const datasetFileList = new Array(200) + .fill(null) + .map((_, index) => datasetFileItem(index)); + +const datasetStatistics = { + count: { + text: 10, + image: 34, + audio: 23, + video: 5, + }, + size: { + text: "120 MB", + image: "3.4 GB", + audio: "2.3 GB", + video: "15 GB", + }, + totalDatasets: datasetList.length, + totalFiles: datasetFileList.length, + completedFiles: datasetFileList.filter((file) => file.status === "COMPLETED") + .length, + totalSize: datasetFileList.reduce((acc, file) => acc + file.size, 0), // in bytes + completionRate: + datasetFileList.length === 0 + ? 0 + : Math.round( + (datasetFileList.filter((file) => file.status === "COMPLETED") + .length / + datasetFileList.length) * + 100 + ), // percentage +}; + +const datasetTypes = [ + { + code: "PRETRAIN", + name: "预训练数据集", + description: "用于模型预训练的大规模数据集", + supportedFormats: ["txt", "json", "csv", "parquet"], + icon: "brain", + }, + { + code: "FINE_TUNE", + name: "微调数据集", + description: "用于模型微调的专业数据集", + supportedFormats: ["json", "csv", "xlsx"], + icon: "tune", + }, + { + code: "EVAL", + name: "评估数据集", + description: "用于模型评估的标准数据集", + supportedFormats: ["json", "csv", "xml"], + icon: "assessment", + }, +]; + +module.exports = { datasetList }; +module.exports = function (router) { + // 获取数据统计信息 + router.get(API.queryDatasetStatisticsUsingGet, (req, res) => { + res.send({ + code: "0", + msg: "Success", + data: datasetStatistics, + }); + }); + + // 创建数据 + router.post(API.createDatasetUsingPost, (req, res) => { + const newDataset = { + ...req.body, + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + status: "ACTIVE", + fileCount: 0, + totalSize: 0, + completionRate: 0, + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + createdBy: "Admin", + updatedBy: "Admin", + tags: tagList.filter((tag) => req.body?.tagIds?.includes?.(tag.id)), + }; + datasetList.unshift(newDataset); // Add to the beginning of the list + res.send({ + code: "0", + msg: "Dataset created successfully", + data: newDataset, + }); + }); + + // 获取数据集列表 + router.get(API.queryDatasetsUsingGet, (req, res) => { + const { page = 0, size = 10, keyword, type, status, tags } = req.query; + console.log("Received query params:", req.query); + + let filteredDatasets = datasetList; + if (keyword) { + console.log("filter keyword:", keyword); + + filteredDatasets = filteredDatasets.filter( + (dataset) => + dataset.name.includes(keyword) || + dataset.description.includes(keyword) + ); + } + if (type) { + filteredDatasets = filteredDatasets.filter( + (dataset) => dataset.datasetType === type + ); + } + if (status) { + console.log("filter status:", status); + filteredDatasets = filteredDatasets.filter( + (dataset) => dataset.status === status + ); + } + if (tags && tags.length > 0) { + console.log("filter tags:", tags); + filteredDatasets = filteredDatasets.filter((dataset) => + tags.every((tag) => dataset.tags.some((t) => t.name === tag)) + ); + } + + const totalElements = filteredDatasets.length; + const paginatedDatasets = filteredDatasets.slice( + page * size, + (page + 1) * size + ); + + res.send({ + code: "0", + msg: "Success", + data: { + totalElements, + page, + size, + content: paginatedDatasets, + }, + }); + }); + + // 根据ID获取数据集详情 + router.get(API.queryDatasetByIdUsingGet, (req, res) => { + const { id } = req.params; + + const dataset = datasetList.find((d) => d.id === id); + if (dataset) { + res.send({ + code: "0", + msg: "Success", + data: dataset, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Dataset not found", + data: null, + }); + } + }); + + // 更新数据集 + router.put(API.updateDatasetByIdUsingPut, (req, res) => { + const { id } = req.params; + let { tags } = req.body; + + const index = datasetList.findIndex((d) => d.id === id); + tags = [...datasetList[index].tags.map((tag) => tag.name), ...tags]; + if (index !== -1) { + datasetList[index] = { + ...datasetList[index], + ...req.body, + tags: tagList.filter((tag) => tags?.includes?.(tag.name)), + updatedAt: new Date().toISOString(), + updatedBy: "Admin", + }; + res.send({ + code: "0", + msg: "Dataset updated successfully", + data: datasetList[index], + }); + } else { + res.status(404).send({ + code: "1", + msg: "Dataset not found", + data: null, + }); + } + }); + + // 删除数据集 + router.delete(API.deleteDatasetByIdUsingDelete, (req, res) => { + const { datasetId } = req.params; + const index = datasetList.findIndex((d) => d.id === datasetId); + + if (index !== -1) { + datasetList.splice(index, 1); + res.status(204).send(); + } else { + res.status(404).send({ + code: "1", + msg: "Dataset not found", + data: null, + }); + } + }); + + // 获取数据集文件列表 + router.get(API.queryFilesUsingGet, (req, res) => { + const { datasetId } = req.params; + const { page = 0, size = 20, fileType, status } = req.query; + + let filteredFiles = datasetFileList; + + if (fileType) { + filteredFiles = filteredFiles.filter( + (file) => file.fileType === fileType + ); + } + + if (status) { + filteredFiles = filteredFiles.filter((file) => file.status === status); + } + + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = filteredFiles.slice(startIndex, endIndex); + + res.send({ + code: "0", + msg: "Success", + data: { + content: pageData, + page: parseInt(page), + size: parseInt(size), + totalElements: filteredFiles.length, + }, + }); + }); + + // 上传文件到数据集 + router.post(API.uploadFileUsingPost, (req, res) => { + const { datasetId } = req.params; + const newFile = { + ...datasetFileItem(), + ...req.body, + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + uploadedAt: new Date().toISOString(), + uploadedBy: "Admin", + }; + + datasetFileList.push(newFile); + + res.status(201).send({ + code: "0", + msg: "File uploaded successfully", + data: newFile, + }); + }); + + // 获取文件详情 + router.get(API.queryFileByIdUsingGet, (req, res) => { + const { datasetId, fileId } = req.params; + const file = datasetFileList.find((f) => f.id === fileId); + + if (file) { + res.send({ + code: "0", + msg: "Success", + data: file, + }); + } else { + res.status(404).send({ + code: "1", + msg: "File not found", + data: null, + }); + } + }); + + // 删除文件 + router.delete(API.deleteFileByIdUsingDelete, (req, res) => { + const { datasetId, fileId } = req.params; + const index = datasetFileList.findIndex((f) => f.id === fileId); + + if (index !== -1) { + datasetFileList.splice(index, 1); + res.status(204).send(); + } else { + res.status(404).send({ + code: "1", + msg: "File not found", + data: null, + }); + } + }); + + // 下载文件 + router.get(API.downloadFileByIdUsingGet, (req, res) => { + const { datasetId, fileId } = req.params; + const file = datasetFileList.find((f) => f.id === fileId); + + if (file) { + res.setHeader( + "Content-Disposition", + `attachment; filename="${file.fileName}"` + ); + res.setHeader("Content-Type", "application/octet-stream"); + res.send(`Mock file content for ${file.fileName}`); + } else { + res.status(404).send({ + code: "1", + msg: "File not found", + data: null, + }); + } + }); + + // 获取数据集类型列表 + router.get(API.queryDatasetTypesUsingGet, (req, res) => { + res.send({ + code: "0", + msg: "Success", + data: datasetTypes, + }); + }); + + // 获取标签列表 + router.get(API.queryTagsUsingGet, (req, res) => { + const { keyword } = req.query; + let filteredTags = tagList; + + if (keyword) { + filteredTags = tagList.filter((tag) => + tag.name.toLowerCase().includes(keyword.toLowerCase()) + ); + } + + res.send({ + code: "0", + msg: "Success", + data: filteredTags, + }); + }); + + // 创建标签 + router.post(API.createTagUsingPost, (req, res) => { + const newTag = { + ...tagItem(), + ...req.body, + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + usageCount: 0, + }; + + tagList.push(newTag); + + res.status(201).send({ + code: "0", + msg: "Tag created successfully", + data: newTag, + }); + }); + + router.post(API.preUploadFileUsingPost, (req, res) => { + res.status(201).send(Mock.Random.guid()); + }); + + // 上传 + router.post(API.uploadFileChunkUsingPost, (req, res) => { + res.status(500).send({ message: "Simulated upload failure" }); + // res.status(201).send({ data: "success" }); + }); + + // 取消上传 + router.put(API.cancelUploadUsingPut, (req, res) => { + res.status(201).send({ data: "success" }); + }); +}; diff --git a/frontend/src/mock/mock-seed/data-ratio.cjs b/frontend/src/mock/mock-seed/data-ratio.cjs index 7592f8a76..9ca4b3aec 100644 --- a/frontend/src/mock/mock-seed/data-ratio.cjs +++ b/frontend/src/mock/mock-seed/data-ratio.cjs @@ -1,220 +1,220 @@ - -const Mock = require("mockjs"); -const API = require("../mock-apis.cjs"); - -function ratioJobItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.ctitle(5, 15), - description: Mock.Random.csentence(10, 30), - status: Mock.Random.pick(["PENDING", "RUNNING", "COMPLETED", "FAILED", "PAUSED"]), - totals: Mock.Random.integer(1000, 10000), - ratio_method: Mock.Random.pick(["DATASET", "TAG"]), - target_dataset_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - target_dataset_name: Mock.Random.ctitle(3, 8), - config: [ - { - datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - counts: Mock.Random.integer(100, 1000).toString(), - filter_conditions: "", - }, - { - datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - counts: Mock.Random.integer(100, 1000).toString(), - filter_conditions: "", - }, - ], - created_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updated_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - }; -} - -const ratioJobList = new Array(20).fill(null).map(ratioJobItem); - - -module.exports = function (router) { - // 获取配比任务列表 - router.get(API.queryRatioTasksUsingGet, (req, res) => { - const { page = 0, size = 10, status } = req.query; - let filteredJobs = ratioJobList; - if (status) { - filteredJobs = ratioJobList.filter((job) => job.status === status); - } - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = filteredJobs.slice(startIndex, endIndex); - res.send({ - code: "0", - msg: "Success", - data: { - content: pageData, - totalElements: filteredJobs.length, - totalPages: Math.ceil(filteredJobs.length / size), - size: parseInt(size), - number: parseInt(page), - }, - }); - }); - - // 创建配比任务 - router.post(API.createRatioTaskUsingPost, (req, res) => { - const newJob = { - ...ratioJobItem(), - ...req.body, - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - status: "PENDING", - createdAt: new Date().toISOString(), - }; - ratioJobList.push(newJob); - res.status(201).send({ - code: "0", - msg: "Ratio job created successfully", - data: newJob, - }); - }); - - // 获取配比任务详情 - router.get(API.queryRatioTaskByIdUsingGet, (req, res) => { - const { taskId } = req.params; - const job = ratioJobList.find((j) => j.id === taskId); - if (job) { - res.send({ - code: "0", - msg: "Success", - data: job, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Ratio job not found", - data: null, - }); - } - }); - - // 删除配比任务 - router.delete(API.deleteRatioTaskByIdUsingDelete, (req, res) => { - const { taskId } = req.params; - const index = ratioJobList.findIndex((j) => j.id === taskId); - if (index !== -1) { - ratioJobList.splice(index, 1); - res.send({ - code: "0", - msg: "Ratio job deleted successfully", - data: null, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Ratio job not found", - data: null, - }); - } - }); - - // 更新配比任务 - router.put(API.updateRatioTaskByIdUsingPut, (req, res) => { - const { taskId } = req.params; - const index = ratioJobList.findIndex((j) => j.id === taskId); - if (index !== -1) { - ratioJobList[index] = { - ...ratioJobList[index], - ...req.body, - updatedAt: new Date().toISOString(), - }; - res.send({ - code: "0", - msg: "Ratio job updated successfully", - data: ratioJobList[index], - }); - } else { - res.status(404).send({ - code: "1", - msg: "Ratio job not found", - data: null, - }); - } - }); - - // 执行配比任务 - router.post(API.executeRatioTaskByIdUsingPost, (req, res) => { - const { taskId } = req.params; - const job = ratioJobList.find((j) => j.id === taskId); - if (job) { - job.status = "RUNNING"; - job.startedAt = new Date().toISOString(); - res.send({ - code: "0", - msg: "Ratio job execution started", - data: { - executionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - status: "RUNNING", - message: "Job execution started successfully", - }, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Ratio job not found", - data: null, - }); - } - }); - - // 停止配比任务 - router.post(API.stopRatioTaskByIdUsingPost, (req, res) => { - const { taskId } = req.params; - const job = ratioJobList.find((j) => j.id === taskId); - if (job) { - job.status = "STOPPED"; - job.finishedAt = new Date().toISOString(); - res.send({ - code: "0", - msg: "Ratio job stopped successfully", - data: null, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Ratio job not found", - data: null, - }); - } - }); - - // 获取配比任务状态 - router.get(API.queryRatioJobStatusUsingGet, (req, res) => { - const { taskId } = req.params; - const job = ratioJobList.find((j) => j.id === taskId); - if (job) { - res.send({ - code: "0", - msg: "Success", - data: { - status: job.status, - progress: job.progress, - }, - }); - } else { - res.status(404).send({ - code: "1", - msg: "Ratio job not found", - data: null, - }); - } - }); - - // 获取配比模型列表 - router.get(API.queryRatioModelsUsingGet, (req, res) => { - const models = [ - { id: "model1", name: "均匀分配模型", description: "将目标数量均匀分配到各数据集。" }, - { id: "model2", name: "标签优先模型", description: "优先满足标签配比需求。" }, - { id: "model3", name: "自定义模型", description: "支持自定义分配逻辑。" }, - ]; - res.send({ - code: "0", - msg: "Success", - data: models, - }); - }); -}; + +const Mock = require("mockjs"); +const API = require("../mock-apis.cjs"); + +function ratioJobItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.ctitle(5, 15), + description: Mock.Random.csentence(10, 30), + status: Mock.Random.pick(["PENDING", "RUNNING", "COMPLETED", "FAILED", "PAUSED"]), + totals: Mock.Random.integer(1000, 10000), + ratio_method: Mock.Random.pick(["DATASET", "TAG"]), + target_dataset_id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + target_dataset_name: Mock.Random.ctitle(3, 8), + config: [ + { + datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + counts: Mock.Random.integer(100, 1000).toString(), + filter_conditions: "", + }, + { + datasetId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + counts: Mock.Random.integer(100, 1000).toString(), + filter_conditions: "", + }, + ], + created_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updated_at: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + }; +} + +const ratioJobList = new Array(20).fill(null).map(ratioJobItem); + + +module.exports = function (router) { + // 获取配比任务列表 + router.get(API.queryRatioTasksUsingGet, (req, res) => { + const { page = 0, size = 10, status } = req.query; + let filteredJobs = ratioJobList; + if (status) { + filteredJobs = ratioJobList.filter((job) => job.status === status); + } + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = filteredJobs.slice(startIndex, endIndex); + res.send({ + code: "0", + msg: "Success", + data: { + content: pageData, + totalElements: filteredJobs.length, + totalPages: Math.ceil(filteredJobs.length / size), + size: parseInt(size), + number: parseInt(page), + }, + }); + }); + + // 创建配比任务 + router.post(API.createRatioTaskUsingPost, (req, res) => { + const newJob = { + ...ratioJobItem(), + ...req.body, + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + status: "PENDING", + createdAt: new Date().toISOString(), + }; + ratioJobList.push(newJob); + res.status(201).send({ + code: "0", + msg: "Ratio job created successfully", + data: newJob, + }); + }); + + // 获取配比任务详情 + router.get(API.queryRatioTaskByIdUsingGet, (req, res) => { + const { taskId } = req.params; + const job = ratioJobList.find((j) => j.id === taskId); + if (job) { + res.send({ + code: "0", + msg: "Success", + data: job, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Ratio job not found", + data: null, + }); + } + }); + + // 删除配比任务 + router.delete(API.deleteRatioTaskByIdUsingDelete, (req, res) => { + const { taskId } = req.params; + const index = ratioJobList.findIndex((j) => j.id === taskId); + if (index !== -1) { + ratioJobList.splice(index, 1); + res.send({ + code: "0", + msg: "Ratio job deleted successfully", + data: null, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Ratio job not found", + data: null, + }); + } + }); + + // 更新配比任务 + router.put(API.updateRatioTaskByIdUsingPut, (req, res) => { + const { taskId } = req.params; + const index = ratioJobList.findIndex((j) => j.id === taskId); + if (index !== -1) { + ratioJobList[index] = { + ...ratioJobList[index], + ...req.body, + updatedAt: new Date().toISOString(), + }; + res.send({ + code: "0", + msg: "Ratio job updated successfully", + data: ratioJobList[index], + }); + } else { + res.status(404).send({ + code: "1", + msg: "Ratio job not found", + data: null, + }); + } + }); + + // 执行配比任务 + router.post(API.executeRatioTaskByIdUsingPost, (req, res) => { + const { taskId } = req.params; + const job = ratioJobList.find((j) => j.id === taskId); + if (job) { + job.status = "RUNNING"; + job.startedAt = new Date().toISOString(); + res.send({ + code: "0", + msg: "Ratio job execution started", + data: { + executionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + status: "RUNNING", + message: "Job execution started successfully", + }, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Ratio job not found", + data: null, + }); + } + }); + + // 停止配比任务 + router.post(API.stopRatioTaskByIdUsingPost, (req, res) => { + const { taskId } = req.params; + const job = ratioJobList.find((j) => j.id === taskId); + if (job) { + job.status = "STOPPED"; + job.finishedAt = new Date().toISOString(); + res.send({ + code: "0", + msg: "Ratio job stopped successfully", + data: null, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Ratio job not found", + data: null, + }); + } + }); + + // 获取配比任务状态 + router.get(API.queryRatioJobStatusUsingGet, (req, res) => { + const { taskId } = req.params; + const job = ratioJobList.find((j) => j.id === taskId); + if (job) { + res.send({ + code: "0", + msg: "Success", + data: { + status: job.status, + progress: job.progress, + }, + }); + } else { + res.status(404).send({ + code: "1", + msg: "Ratio job not found", + data: null, + }); + } + }); + + // 获取配比模型列表 + router.get(API.queryRatioModelsUsingGet, (req, res) => { + const models = [ + { id: "model1", name: "均匀分配模型", description: "将目标数量均匀分配到各数据集。" }, + { id: "model2", name: "标签优先模型", description: "优先满足标签配比需求。" }, + { id: "model3", name: "自定义模型", description: "支持自定义分配逻辑。" }, + ]; + res.send({ + code: "0", + msg: "Success", + data: models, + }); + }); +}; diff --git a/frontend/src/mock/mock-seed/data-synthesis.cjs b/frontend/src/mock/mock-seed/data-synthesis.cjs index 831758831..826acfc7d 100644 --- a/frontend/src/mock/mock-seed/data-synthesis.cjs +++ b/frontend/src/mock/mock-seed/data-synthesis.cjs @@ -1,522 +1,522 @@ -const Mock = require("mockjs"); -const API = require("../mock-apis.cjs"); - -// 合成类型枚举 -const SynthesisTypes = [ - "INSTRUCTION_TUNING", - "COT_DISTILLATION", - "DIALOGUE_GENERATION", - "TEXT_AUGMENTATION", - "MULTIMODAL_SYNTHESIS", - "CUSTOM" -]; - -// 任务状态枚举 -const JobStatuses = ["PENDING", "RUNNING", "COMPLETED", "FAILED", "CANCELLED"]; - -// 模型配置 -function modelConfigItem() { - return { - modelName: Mock.Random.pick([ - "gpt-3.5-turbo", - "gpt-4", - "claude-3", - "llama-2-70b", - "qwen-max" - ]), - temperature: Mock.Random.float(0.1, 1.0, 2, 2), - maxTokens: Mock.Random.pick([512, 1024, 2048, 4096]), - topP: Mock.Random.float(0.1, 1.0, 2, 2), - frequencyPenalty: Mock.Random.float(0, 2.0, 2, 2) - }; -} - -// 合成模板数据 -function synthesisTemplateItem() { - const type = Mock.Random.pick(SynthesisTypes); - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.ctitle(5, 20), - description: Mock.Random.csentence(5, 30), - type, - category: Mock.Random.pick([ - "教育培训", "对话系统", "内容生成", "代码生成", "多模态", "自定义" - ]), - modelConfig: modelConfigItem(), - enabled: Mock.Random.boolean(), - promptTemplate: type === "INSTRUCTION_TUNING" - ? "请根据以下主题生成一个指令:{topic}\n指令应该包含:\n1. 明确的任务描述\n2. 具体的输入要求\n3. 期望的输出格式" - : type === "COT_DISTILLATION" - ? "问题:{question}\n请提供详细的推理步骤,然后给出最终答案。\n推理过程:\n1. 分析问题的关键信息\n2. 应用相关知识和规则\n3. 逐步推导出结论" - : "请根据以下模板生成内容:{template}", - parameters: { - maxLength: Mock.Random.integer(100, 2000), - diversity: Mock.Random.float(0.1, 1.0, 2, 2), - quality: Mock.Random.float(0.7, 1.0, 2, 2) - }, - examples: new Array(Mock.Random.integer(2, 5)).fill(null).map(() => ({ - input: Mock.Random.csentence(10, 30), - output: Mock.Random.csentence(20, 50), - explanation: Mock.Random.csentence(5, 20) - })), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss") - }; -} - -const synthesisTemplateList = new Array(25).fill(null).map(synthesisTemplateItem); - -// 合成任务数据 -function synthesisJobItem() { - const template = Mock.Random.pick(synthesisTemplateList); - const targetCount = Mock.Random.integer(100, 10000); - const generatedCount = Mock.Random.integer(0, targetCount); - const progress = targetCount > 0 ? (generatedCount / targetCount) * 100 : 0; - - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.ctitle(5, 20), - description: Mock.Random.csentence(5, 30), - templateId: template.id, - template: { - id: template.id, - name: template.name, - type: template.type - }, - status: Mock.Random.pick(JobStatuses), - progress: Math.round(progress * 100) / 100, - targetCount, - generatedCount, - startTime: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - endTime: progress >= 100 ? Mock.Random.datetime("yyyy-MM-dd HH:mm:ss") : null, - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - statistics: { - totalGenerated: generatedCount, - successfulGenerated: Math.floor(generatedCount * Mock.Random.float(0.85, 0.98, 2, 2)), - failedGenerated: Math.floor(generatedCount * Mock.Random.float(0.02, 0.15, 2, 2)), - averageLength: Mock.Random.integer(50, 500), - uniqueCount: Math.floor(generatedCount * Mock.Random.float(0.8, 0.95, 2, 2)) - }, - samples: new Array(Math.min(10, generatedCount)).fill(null).map(() => ({ - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - content: Mock.Random.cparagraph(1, 3), - score: Mock.Random.float(0.6, 1.0, 2, 2), - metadata: { - length: Mock.Random.integer(50, 500), - model: template.modelConfig.modelName, - timestamp: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss") - }, - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss") - })) - }; -} - -const synthesisJobList = new Array(30).fill(null).map(synthesisJobItem); - -// 生成指令数据 -function generatedInstructionItem() { - return { - instruction: Mock.Random.csentence(10, 30), - input: Mock.Random.csentence(5, 20), - output: Mock.Random.csentence(10, 40), - quality: Mock.Random.float(0.7, 1.0, 2, 2) - }; -} - -// COT 示例数据 -function cotExampleItem() { - return { - question: Mock.Random.csentence(10, 25) + "?", - reasoning: Mock.Random.cparagraph(2, 4), - answer: Mock.Random.csentence(5, 15) - }; -} - -// 蒸馏COT数据 -function distilledCOTDataItem() { - return { - question: Mock.Random.csentence(10, 25) + "?", - reasoning: Mock.Random.cparagraph(2, 4), - answer: Mock.Random.csentence(5, 15), - confidence: Mock.Random.float(0.7, 1.0, 2, 2) - }; -} - -module.exports = function (router) { - // 获取合成模板列表 - router.get(API.querySynthesisTemplatesUsingGet, (req, res) => { - const { page = 0, size = 20, type } = req.query; - let filteredTemplates = synthesisTemplateList; - - if (type) { - filteredTemplates = synthesisTemplateList.filter( - (template) => template.type === type - ); - } - - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = filteredTemplates.slice(startIndex, endIndex); - - res.send({ - code: "0", - msg: "Success", - data: { - content: pageData, - totalElements: filteredTemplates.length, - totalPages: Math.ceil(filteredTemplates.length / size), - size: parseInt(size), - number: parseInt(page) - } - }); - }); - - // 创建合成模板 - router.post(API.createSynthesisTemplateUsingPost, (req, res) => { - const newTemplate = { - ...synthesisTemplateItem(), - ...req.body, - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - enabled: true, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString() - }; - synthesisTemplateList.push(newTemplate); - - res.status(201).send({ - code: "0", - msg: "Synthesis template created successfully", - data: newTemplate - }); - }); - - // 获取合成模板详情 - router.get(API.querySynthesisTemplateByIdUsingGet, (req, res) => { - const { templateId } = req.params; - const template = synthesisTemplateList.find((t) => t.id === templateId); - - if (template) { - res.send({ - code: "0", - msg: "Success", - data: template - }); - } else { - res.status(404).send({ - code: "1", - msg: "Synthesis template not found", - data: null - }); - } - }); - - // 更新合成模板 - router.put(API.updateSynthesisTemplateByIdUsingPut, (req, res) => { - const { templateId } = req.params; - const index = synthesisTemplateList.findIndex((t) => t.id === templateId); - - if (index !== -1) { - synthesisTemplateList[index] = { - ...synthesisTemplateList[index], - ...req.body, - updatedAt: new Date().toISOString() - }; - res.send({ - code: "0", - msg: "Synthesis template updated successfully", - data: synthesisTemplateList[index] - }); - } else { - res.status(404).send({ - code: "1", - msg: "Synthesis template not found", - data: null - }); - } - }); - - // 删除合成模板 - router.delete(API.deleteSynthesisTemplateByIdUsingDelete, (req, res) => { - const { templateId } = req.params; - const index = synthesisTemplateList.findIndex((t) => t.id === templateId); - - if (index !== -1) { - synthesisTemplateList.splice(index, 1); - res.send({ - code: "0", - msg: "Synthesis template deleted successfully", - data: null - }); - } else { - res.status(404).send({ - code: "1", - msg: "Synthesis template not found", - data: null - }); - } - }); - - // 获取合成任务列表 - router.get(API.querySynthesisJobsUsingGet, (req, res) => { - const { page = 0, size = 20, status } = req.query; - let filteredJobs = synthesisJobList; - - if (status) { - filteredJobs = synthesisJobList.filter((job) => job.status === status); - } - - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = filteredJobs.slice(startIndex, endIndex); - - res.send({ - code: "0", - msg: "Success", - data: { - content: pageData, - totalElements: filteredJobs.length, - totalPages: Math.ceil(filteredJobs.length / size), - size: parseInt(size), - number: parseInt(page) - } - }); - }); - - // 创建合成任务 - router.post(API.createSynthesisJobUsingPost, (req, res) => { - const { templateId } = req.body; - const template = synthesisTemplateList.find(t => t.id === templateId); - - const newJob = { - ...synthesisJobItem(), - ...req.body, - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - templateId, - template: template ? { - id: template.id, - name: template.name, - type: template.type - } : null, - status: "PENDING", - progress: 0, - generatedCount: 0, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString() - }; - synthesisJobList.push(newJob); - - res.status(201).send({ - code: "0", - msg: "Synthesis job created successfully", - data: newJob - }); - }); - - // 获取合成任务详情 - router.get(API.querySynthesisJobByIdUsingGet, (req, res) => { - const { jobId } = req.params; - const job = synthesisJobList.find((j) => j.id === jobId); - - if (job) { - const template = synthesisTemplateList.find(t => t.id === job.templateId); - const jobDetail = { - ...job, - template: template || null - }; - - res.send({ - code: "0", - msg: "Success", - data: jobDetail - }); - } else { - res.status(404).send({ - code: "1", - msg: "Synthesis job not found", - data: null - }); - } - }); - - // 删除合成任务 - router.delete(API.deleteSynthesisJobByIdUsingDelete, (req, res) => { - const { jobId } = req.params; - const index = synthesisJobList.findIndex((j) => j.id === jobId); - - if (index !== -1) { - synthesisJobList.splice(index, 1); - res.send({ - code: "0", - msg: "Synthesis job deleted successfully", - data: null - }); - } else { - res.status(404).send({ - code: "1", - msg: "Synthesis job not found", - data: null - }); - } - }); - - // 执行合成任务 - router.post(API.executeSynthesisJobUsingPost, (req, res) => { - const { jobId } = req.params; - const job = synthesisJobList.find((j) => j.id === jobId); - - if (job) { - job.status = "RUNNING"; - job.startTime = new Date().toISOString(); - job.updatedAt = new Date().toISOString(); - - // 模拟异步执行 - setTimeout(() => { - job.status = Mock.Random.pick(["COMPLETED", "FAILED"]); - job.progress = job.status === "COMPLETED" ? 100 : Mock.Random.float(10, 90, 2, 2); - job.generatedCount = Math.floor((job.progress / 100) * job.targetCount); - job.endTime = new Date().toISOString(); - }, Mock.Random.integer(2000, 5000)); - - res.send({ - code: "0", - msg: "Synthesis job execution started", - data: { - executionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - status: "RUNNING", - message: "Job execution started successfully" - } - }); - } else { - res.status(404).send({ - code: "1", - msg: "Synthesis job not found", - data: null - }); - } - }); - - // 指令调优数据合成 - router.post(API.instructionTuningUsingPost, (req, res) => { - const { baseInstructions, targetDomain, count, modelConfig, parameters } = req.body; - - const jobId = Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""); - const generatedInstructions = new Array(count).fill(null).map(() => generatedInstructionItem()); - - const statistics = { - totalGenerated: count, - averageQuality: Mock.Random.float(0.8, 0.95, 2, 2), - diversityScore: Mock.Random.float(0.7, 0.9, 2, 2) - }; - - res.send({ - code: "0", - msg: "Instruction tuning completed successfully", - data: { - jobId, - generatedInstructions, - statistics - } - }); - }); - - // COT蒸馏数据合成 - router.post(API.cotDistillationUsingPost, (req, res) => { - const { sourceModel, targetFormat, examples, parameters } = req.body; - - const jobId = Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""); - const processedCount = examples.length; - const successfulCount = Math.floor(processedCount * Mock.Random.float(0.85, 0.98, 2, 2)); - - const distilledData = new Array(successfulCount).fill(null).map(() => distilledCOTDataItem()); - - const statistics = { - totalProcessed: processedCount, - successfulDistilled: successfulCount, - averageConfidence: Mock.Random.float(0.8, 0.95, 2, 2) - }; - - res.send({ - code: "0", - msg: "COT distillation completed successfully", - data: { - jobId, - distilledData, - statistics - } - }); - }); - - // 获取合成任务统计信息 - router.get("/api/v1/synthesis/statistics", (req, res) => { - const statistics = { - totalJobs: synthesisJobList.length, - completedJobs: synthesisJobList.filter(j => j.status === "COMPLETED").length, - runningJobs: synthesisJobList.filter(j => j.status === "RUNNING").length, - failedJobs: synthesisJobList.filter(j => j.status === "FAILED").length, - totalGenerated: synthesisJobList.reduce((sum, job) => sum + job.generatedCount, 0), - averageQuality: Mock.Random.float(0.8, 0.95, 2, 2), - templateTypeDistribution: { - "INSTRUCTION_TUNING": synthesisTemplateList.filter(t => t.type === "INSTRUCTION_TUNING").length, - "COT_DISTILLATION": synthesisTemplateList.filter(t => t.type === "COT_DISTILLATION").length, - "DIALOGUE_GENERATION": synthesisTemplateList.filter(t => t.type === "DIALOGUE_GENERATION").length, - "TEXT_AUGMENTATION": synthesisTemplateList.filter(t => t.type === "TEXT_AUGMENTATION").length, - "MULTIMODAL_SYNTHESIS": synthesisTemplateList.filter(t => t.type === "MULTIMODAL_SYNTHESIS").length, - "CUSTOM": synthesisTemplateList.filter(t => t.type === "CUSTOM").length - }, - dailyGeneration: new Array(7).fill(null).map((_, index) => ({ - date: Mock.Random.date("yyyy-MM-dd"), - count: Mock.Random.integer(100, 5000) - })) - }; - - res.send({ - code: "0", - msg: "Success", - data: statistics - }); - }); - - // 批量操作 - router.post("/api/v1/synthesis/jobs/batch", (req, res) => { - const { action, jobIds } = req.body; - - let successCount = 0; - let failedCount = 0; - - jobIds.forEach(jobId => { - const job = synthesisJobList.find(j => j.id === jobId); - if (job) { - switch(action) { - case "DELETE": - const index = synthesisJobList.findIndex(j => j.id === jobId); - synthesisJobList.splice(index, 1); - successCount++; - break; - case "START": - job.status = "RUNNING"; - job.startTime = new Date().toISOString(); - successCount++; - break; - case "STOP": - job.status = "CANCELLED"; - job.endTime = new Date().toISOString(); - successCount++; - break; - } - } else { - failedCount++; - } - }); - - res.send({ - code: "0", - msg: `Batch ${action.toLowerCase()} completed`, - data: { - total: jobIds.length, - success: successCount, - failed: failedCount - } - }); - }); +const Mock = require("mockjs"); +const API = require("../mock-apis.cjs"); + +// 合成类型枚举 +const SynthesisTypes = [ + "INSTRUCTION_TUNING", + "COT_DISTILLATION", + "DIALOGUE_GENERATION", + "TEXT_AUGMENTATION", + "MULTIMODAL_SYNTHESIS", + "CUSTOM" +]; + +// 任务状态枚举 +const JobStatuses = ["PENDING", "RUNNING", "COMPLETED", "FAILED", "CANCELLED"]; + +// 模型配置 +function modelConfigItem() { + return { + modelName: Mock.Random.pick([ + "gpt-3.5-turbo", + "gpt-4", + "claude-3", + "llama-2-70b", + "qwen-max" + ]), + temperature: Mock.Random.float(0.1, 1.0, 2, 2), + maxTokens: Mock.Random.pick([512, 1024, 2048, 4096]), + topP: Mock.Random.float(0.1, 1.0, 2, 2), + frequencyPenalty: Mock.Random.float(0, 2.0, 2, 2) + }; +} + +// 合成模板数据 +function synthesisTemplateItem() { + const type = Mock.Random.pick(SynthesisTypes); + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.ctitle(5, 20), + description: Mock.Random.csentence(5, 30), + type, + category: Mock.Random.pick([ + "教育培训", "对话系统", "内容生成", "代码生成", "多模态", "自定义" + ]), + modelConfig: modelConfigItem(), + enabled: Mock.Random.boolean(), + promptTemplate: type === "INSTRUCTION_TUNING" + ? "请根据以下主题生成一个指令:{topic}\n指令应该包含:\n1. 明确的任务描述\n2. 具体的输入要求\n3. 期望的输出格式" + : type === "COT_DISTILLATION" + ? "问题:{question}\n请提供详细的推理步骤,然后给出最终答案。\n推理过程:\n1. 分析问题的关键信息\n2. 应用相关知识和规则\n3. 逐步推导出结论" + : "请根据以下模板生成内容:{template}", + parameters: { + maxLength: Mock.Random.integer(100, 2000), + diversity: Mock.Random.float(0.1, 1.0, 2, 2), + quality: Mock.Random.float(0.7, 1.0, 2, 2) + }, + examples: new Array(Mock.Random.integer(2, 5)).fill(null).map(() => ({ + input: Mock.Random.csentence(10, 30), + output: Mock.Random.csentence(20, 50), + explanation: Mock.Random.csentence(5, 20) + })), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss") + }; +} + +const synthesisTemplateList = new Array(25).fill(null).map(synthesisTemplateItem); + +// 合成任务数据 +function synthesisJobItem() { + const template = Mock.Random.pick(synthesisTemplateList); + const targetCount = Mock.Random.integer(100, 10000); + const generatedCount = Mock.Random.integer(0, targetCount); + const progress = targetCount > 0 ? (generatedCount / targetCount) * 100 : 0; + + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.ctitle(5, 20), + description: Mock.Random.csentence(5, 30), + templateId: template.id, + template: { + id: template.id, + name: template.name, + type: template.type + }, + status: Mock.Random.pick(JobStatuses), + progress: Math.round(progress * 100) / 100, + targetCount, + generatedCount, + startTime: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + endTime: progress >= 100 ? Mock.Random.datetime("yyyy-MM-dd HH:mm:ss") : null, + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + statistics: { + totalGenerated: generatedCount, + successfulGenerated: Math.floor(generatedCount * Mock.Random.float(0.85, 0.98, 2, 2)), + failedGenerated: Math.floor(generatedCount * Mock.Random.float(0.02, 0.15, 2, 2)), + averageLength: Mock.Random.integer(50, 500), + uniqueCount: Math.floor(generatedCount * Mock.Random.float(0.8, 0.95, 2, 2)) + }, + samples: new Array(Math.min(10, generatedCount)).fill(null).map(() => ({ + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + content: Mock.Random.cparagraph(1, 3), + score: Mock.Random.float(0.6, 1.0, 2, 2), + metadata: { + length: Mock.Random.integer(50, 500), + model: template.modelConfig.modelName, + timestamp: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss") + }, + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss") + })) + }; +} + +const synthesisJobList = new Array(30).fill(null).map(synthesisJobItem); + +// 生成指令数据 +function generatedInstructionItem() { + return { + instruction: Mock.Random.csentence(10, 30), + input: Mock.Random.csentence(5, 20), + output: Mock.Random.csentence(10, 40), + quality: Mock.Random.float(0.7, 1.0, 2, 2) + }; +} + +// COT 示例数据 +function cotExampleItem() { + return { + question: Mock.Random.csentence(10, 25) + "?", + reasoning: Mock.Random.cparagraph(2, 4), + answer: Mock.Random.csentence(5, 15) + }; +} + +// 蒸馏COT数据 +function distilledCOTDataItem() { + return { + question: Mock.Random.csentence(10, 25) + "?", + reasoning: Mock.Random.cparagraph(2, 4), + answer: Mock.Random.csentence(5, 15), + confidence: Mock.Random.float(0.7, 1.0, 2, 2) + }; +} + +module.exports = function (router) { + // 获取合成模板列表 + router.get(API.querySynthesisTemplatesUsingGet, (req, res) => { + const { page = 0, size = 20, type } = req.query; + let filteredTemplates = synthesisTemplateList; + + if (type) { + filteredTemplates = synthesisTemplateList.filter( + (template) => template.type === type + ); + } + + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = filteredTemplates.slice(startIndex, endIndex); + + res.send({ + code: "0", + msg: "Success", + data: { + content: pageData, + totalElements: filteredTemplates.length, + totalPages: Math.ceil(filteredTemplates.length / size), + size: parseInt(size), + number: parseInt(page) + } + }); + }); + + // 创建合成模板 + router.post(API.createSynthesisTemplateUsingPost, (req, res) => { + const newTemplate = { + ...synthesisTemplateItem(), + ...req.body, + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + enabled: true, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString() + }; + synthesisTemplateList.push(newTemplate); + + res.status(201).send({ + code: "0", + msg: "Synthesis template created successfully", + data: newTemplate + }); + }); + + // 获取合成模板详情 + router.get(API.querySynthesisTemplateByIdUsingGet, (req, res) => { + const { templateId } = req.params; + const template = synthesisTemplateList.find((t) => t.id === templateId); + + if (template) { + res.send({ + code: "0", + msg: "Success", + data: template + }); + } else { + res.status(404).send({ + code: "1", + msg: "Synthesis template not found", + data: null + }); + } + }); + + // 更新合成模板 + router.put(API.updateSynthesisTemplateByIdUsingPut, (req, res) => { + const { templateId } = req.params; + const index = synthesisTemplateList.findIndex((t) => t.id === templateId); + + if (index !== -1) { + synthesisTemplateList[index] = { + ...synthesisTemplateList[index], + ...req.body, + updatedAt: new Date().toISOString() + }; + res.send({ + code: "0", + msg: "Synthesis template updated successfully", + data: synthesisTemplateList[index] + }); + } else { + res.status(404).send({ + code: "1", + msg: "Synthesis template not found", + data: null + }); + } + }); + + // 删除合成模板 + router.delete(API.deleteSynthesisTemplateByIdUsingDelete, (req, res) => { + const { templateId } = req.params; + const index = synthesisTemplateList.findIndex((t) => t.id === templateId); + + if (index !== -1) { + synthesisTemplateList.splice(index, 1); + res.send({ + code: "0", + msg: "Synthesis template deleted successfully", + data: null + }); + } else { + res.status(404).send({ + code: "1", + msg: "Synthesis template not found", + data: null + }); + } + }); + + // 获取合成任务列表 + router.get(API.querySynthesisJobsUsingGet, (req, res) => { + const { page = 0, size = 20, status } = req.query; + let filteredJobs = synthesisJobList; + + if (status) { + filteredJobs = synthesisJobList.filter((job) => job.status === status); + } + + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = filteredJobs.slice(startIndex, endIndex); + + res.send({ + code: "0", + msg: "Success", + data: { + content: pageData, + totalElements: filteredJobs.length, + totalPages: Math.ceil(filteredJobs.length / size), + size: parseInt(size), + number: parseInt(page) + } + }); + }); + + // 创建合成任务 + router.post(API.createSynthesisJobUsingPost, (req, res) => { + const { templateId } = req.body; + const template = synthesisTemplateList.find(t => t.id === templateId); + + const newJob = { + ...synthesisJobItem(), + ...req.body, + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + templateId, + template: template ? { + id: template.id, + name: template.name, + type: template.type + } : null, + status: "PENDING", + progress: 0, + generatedCount: 0, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString() + }; + synthesisJobList.push(newJob); + + res.status(201).send({ + code: "0", + msg: "Synthesis job created successfully", + data: newJob + }); + }); + + // 获取合成任务详情 + router.get(API.querySynthesisJobByIdUsingGet, (req, res) => { + const { jobId } = req.params; + const job = synthesisJobList.find((j) => j.id === jobId); + + if (job) { + const template = synthesisTemplateList.find(t => t.id === job.templateId); + const jobDetail = { + ...job, + template: template || null + }; + + res.send({ + code: "0", + msg: "Success", + data: jobDetail + }); + } else { + res.status(404).send({ + code: "1", + msg: "Synthesis job not found", + data: null + }); + } + }); + + // 删除合成任务 + router.delete(API.deleteSynthesisJobByIdUsingDelete, (req, res) => { + const { jobId } = req.params; + const index = synthesisJobList.findIndex((j) => j.id === jobId); + + if (index !== -1) { + synthesisJobList.splice(index, 1); + res.send({ + code: "0", + msg: "Synthesis job deleted successfully", + data: null + }); + } else { + res.status(404).send({ + code: "1", + msg: "Synthesis job not found", + data: null + }); + } + }); + + // 执行合成任务 + router.post(API.executeSynthesisJobUsingPost, (req, res) => { + const { jobId } = req.params; + const job = synthesisJobList.find((j) => j.id === jobId); + + if (job) { + job.status = "RUNNING"; + job.startTime = new Date().toISOString(); + job.updatedAt = new Date().toISOString(); + + // 模拟异步执行 + setTimeout(() => { + job.status = Mock.Random.pick(["COMPLETED", "FAILED"]); + job.progress = job.status === "COMPLETED" ? 100 : Mock.Random.float(10, 90, 2, 2); + job.generatedCount = Math.floor((job.progress / 100) * job.targetCount); + job.endTime = new Date().toISOString(); + }, Mock.Random.integer(2000, 5000)); + + res.send({ + code: "0", + msg: "Synthesis job execution started", + data: { + executionId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + status: "RUNNING", + message: "Job execution started successfully" + } + }); + } else { + res.status(404).send({ + code: "1", + msg: "Synthesis job not found", + data: null + }); + } + }); + + // 指令调优数据合成 + router.post(API.instructionTuningUsingPost, (req, res) => { + const { baseInstructions, targetDomain, count, modelConfig, parameters } = req.body; + + const jobId = Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""); + const generatedInstructions = new Array(count).fill(null).map(() => generatedInstructionItem()); + + const statistics = { + totalGenerated: count, + averageQuality: Mock.Random.float(0.8, 0.95, 2, 2), + diversityScore: Mock.Random.float(0.7, 0.9, 2, 2) + }; + + res.send({ + code: "0", + msg: "Instruction tuning completed successfully", + data: { + jobId, + generatedInstructions, + statistics + } + }); + }); + + // COT蒸馏数据合成 + router.post(API.cotDistillationUsingPost, (req, res) => { + const { sourceModel, targetFormat, examples, parameters } = req.body; + + const jobId = Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""); + const processedCount = examples.length; + const successfulCount = Math.floor(processedCount * Mock.Random.float(0.85, 0.98, 2, 2)); + + const distilledData = new Array(successfulCount).fill(null).map(() => distilledCOTDataItem()); + + const statistics = { + totalProcessed: processedCount, + successfulDistilled: successfulCount, + averageConfidence: Mock.Random.float(0.8, 0.95, 2, 2) + }; + + res.send({ + code: "0", + msg: "COT distillation completed successfully", + data: { + jobId, + distilledData, + statistics + } + }); + }); + + // 获取合成任务统计信息 + router.get("/api/v1/synthesis/statistics", (req, res) => { + const statistics = { + totalJobs: synthesisJobList.length, + completedJobs: synthesisJobList.filter(j => j.status === "COMPLETED").length, + runningJobs: synthesisJobList.filter(j => j.status === "RUNNING").length, + failedJobs: synthesisJobList.filter(j => j.status === "FAILED").length, + totalGenerated: synthesisJobList.reduce((sum, job) => sum + job.generatedCount, 0), + averageQuality: Mock.Random.float(0.8, 0.95, 2, 2), + templateTypeDistribution: { + "INSTRUCTION_TUNING": synthesisTemplateList.filter(t => t.type === "INSTRUCTION_TUNING").length, + "COT_DISTILLATION": synthesisTemplateList.filter(t => t.type === "COT_DISTILLATION").length, + "DIALOGUE_GENERATION": synthesisTemplateList.filter(t => t.type === "DIALOGUE_GENERATION").length, + "TEXT_AUGMENTATION": synthesisTemplateList.filter(t => t.type === "TEXT_AUGMENTATION").length, + "MULTIMODAL_SYNTHESIS": synthesisTemplateList.filter(t => t.type === "MULTIMODAL_SYNTHESIS").length, + "CUSTOM": synthesisTemplateList.filter(t => t.type === "CUSTOM").length + }, + dailyGeneration: new Array(7).fill(null).map((_, index) => ({ + date: Mock.Random.date("yyyy-MM-dd"), + count: Mock.Random.integer(100, 5000) + })) + }; + + res.send({ + code: "0", + msg: "Success", + data: statistics + }); + }); + + // 批量操作 + router.post("/api/v1/synthesis/jobs/batch", (req, res) => { + const { action, jobIds } = req.body; + + let successCount = 0; + let failedCount = 0; + + jobIds.forEach(jobId => { + const job = synthesisJobList.find(j => j.id === jobId); + if (job) { + switch(action) { + case "DELETE": + const index = synthesisJobList.findIndex(j => j.id === jobId); + synthesisJobList.splice(index, 1); + successCount++; + break; + case "START": + job.status = "RUNNING"; + job.startTime = new Date().toISOString(); + successCount++; + break; + case "STOP": + job.status = "CANCELLED"; + job.endTime = new Date().toISOString(); + successCount++; + break; + } + } else { + failedCount++; + } + }); + + res.send({ + code: "0", + msg: `Batch ${action.toLowerCase()} completed`, + data: { + total: jobIds.length, + success: successCount, + failed: failedCount + } + }); + }); }; \ No newline at end of file diff --git a/frontend/src/mock/mock-seed/knowledge-base.cjs b/frontend/src/mock/mock-seed/knowledge-base.cjs index 9323ce7d4..28f9164eb 100644 --- a/frontend/src/mock/mock-seed/knowledge-base.cjs +++ b/frontend/src/mock/mock-seed/knowledge-base.cjs @@ -1,176 +1,176 @@ -const Mock = require("mockjs"); -const API = require("../mock-apis.cjs"); - -// 知识库数据 -function KnowledgeBaseItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.ctitle(5, 15), - description: Mock.Random.csentence(10, 30), - createdBy: Mock.Random.cname(), - updatedBy: Mock.Random.cname(), - embeddingModel: Mock.Random.pick([ - "text-embedding-ada-002", - "text-embedding-3-small", - "text-embedding-3-large", - ]), - chatModel: Mock.Random.pick(["gpt-3.5-turbo", "gpt-4", "gpt-4-32k"]), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - }; -} - -const knowledgeBaseList = new Array(50).fill(null).map(KnowledgeBaseItem); - -function fileItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - createdBy: Mock.Random.cname(), - updatedBy: Mock.Random.cname(), - knowledgeBaseId: Mock.Random.pick(knowledgeBaseList).id, - fileId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - fileName: Mock.Random.ctitle(5, 15), - chunkCount: Mock.Random.integer(1, 100), - metadata: {}, - status: Mock.Random.pick([ - "UNPROCESSED", - "PROCESSING", - "PROCESSED", - "PROCESS_FAILED", - ]), - }; -} - -const fileList = new Array(20).fill(null).map(fileItem); - -module.exports = function (router) { - // 获取知识库列表 - router.post(API.queryKnowledgeBasesUsingPost, (req, res) => { - const { page = 0, size, keyword } = req.body; - let filteredList = knowledgeBaseList; - if (keyword) { - filteredList = knowledgeBaseList.filter( - (kb) => kb.name.includes(keyword) || kb.description.includes(keyword) - ); - } - const start = page * size; - const end = start + size; - const totalElements = filteredList.length; - const paginatedList = filteredList.slice(start, end); - res.send({ - code: "0", - msg: "Success", - data: { - totalElements, - page, - size, - content: paginatedList, - }, - }); - }); - - // 创建知识库 - router.post(API.createKnowledgeBaseUsingPost, (req, res) => { - const item = KnowledgeBaseItem(); - knowledgeBaseList.unshift(item); - res.status(201).send(item); - }); - - // 获取知识库详情 - router.get(API.queryKnowledgeBaseByIdUsingGet, (req, res) => { - const id = req.params.baseId; - const item = - knowledgeBaseList.find((kb) => kb.id === id) || KnowledgeBaseItem(); - res.send({ - code: "0", - msg: "Success", - data: item, - }); - }); - - // 更新知识库 - router.put(API.updateKnowledgeBaseByIdUsingPut, (req, res) => { - const id = req.params.baseId; - const idx = knowledgeBaseList.findIndex((kb) => kb.id === id); - if (idx >= 0) { - knowledgeBaseList[idx] = { ...knowledgeBaseList[idx], ...req.body }; - res.status(201).send(knowledgeBaseList[idx]); - } else { - res.status(404).send({ message: "Not found" }); - } - }); - - // 删除知识库 - router.delete(API.deleteKnowledgeBaseByIdUsingDelete, (req, res) => { - const id = req.params.baseId; - const idx = knowledgeBaseList.findIndex((kb) => kb.id === id); - if (idx >= 0) { - knowledgeBaseList.splice(idx, 1); - res.status(201).send({ success: true }); - } else { - res.status(404).send({ message: "Not found" }); - } - }); - - // 添加文件到知识库 - router.post(API.addKnowledgeBaseFilesUsingPost, (req, res) => { - const file = Mock.mock({ - id: "@guid", - name: "@ctitle(5,15)", - size: "@integer(1000,1000000)", - status: "uploaded", - createdAt: "@datetime", - }); - res.status(201).send(file); - }); - - // 获取知识生成文件详情 - router.get(API.queryKnowledgeBaseFilesGet, (req, res) => { - const { keyword, page, size } = req.query; - let filteredList = fileList; - if (keyword) { - filteredList = fileList.filter((file) => file.fileName.includes(keyword)); - } - const start = page * size; - const end = start + size; - const totalElements = filteredList.length; - const paginatedList = filteredList.slice(start, end); - res.send({ - code: "0", - msg: "Success", - data: { - totalElements, - page, - size, - content: paginatedList, - }, - }); - }); - - router.get(API.queryKnowledgeBaseFilesByIdUsingGet, (req, res) => { - const { baseId, fileId } = req.params; - const item = - fileList.find( - (file) => file.knowledgeBaseId === baseId && file.id === fileId - ) || fileItem(); - res.send({ - code: "0", - msg: "Success", - data: item, - }); - }); - - // 删除知识生成文件 - router.delete(API.deleteKnowledgeBaseTaskByIdUsingDelete, (req, res) => { - const { id } = req.params; - const idx = fileList.findIndex((file) => file.id === id); - if (idx >= 0) { - fileList.splice(idx, 1); - res.status(200).send({ success: true }); - return; - } - res.status(404).send({ message: "Not found" }); - }); -}; +const Mock = require("mockjs"); +const API = require("../mock-apis.cjs"); + +// 知识库数据 +function KnowledgeBaseItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.ctitle(5, 15), + description: Mock.Random.csentence(10, 30), + createdBy: Mock.Random.cname(), + updatedBy: Mock.Random.cname(), + embeddingModel: Mock.Random.pick([ + "text-embedding-ada-002", + "text-embedding-3-small", + "text-embedding-3-large", + ]), + chatModel: Mock.Random.pick(["gpt-3.5-turbo", "gpt-4", "gpt-4-32k"]), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + }; +} + +const knowledgeBaseList = new Array(50).fill(null).map(KnowledgeBaseItem); + +function fileItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + createdBy: Mock.Random.cname(), + updatedBy: Mock.Random.cname(), + knowledgeBaseId: Mock.Random.pick(knowledgeBaseList).id, + fileId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + fileName: Mock.Random.ctitle(5, 15), + chunkCount: Mock.Random.integer(1, 100), + metadata: {}, + status: Mock.Random.pick([ + "UNPROCESSED", + "PROCESSING", + "PROCESSED", + "PROCESS_FAILED", + ]), + }; +} + +const fileList = new Array(20).fill(null).map(fileItem); + +module.exports = function (router) { + // 获取知识库列表 + router.post(API.queryKnowledgeBasesUsingPost, (req, res) => { + const { page = 0, size, keyword } = req.body; + let filteredList = knowledgeBaseList; + if (keyword) { + filteredList = knowledgeBaseList.filter( + (kb) => kb.name.includes(keyword) || kb.description.includes(keyword) + ); + } + const start = page * size; + const end = start + size; + const totalElements = filteredList.length; + const paginatedList = filteredList.slice(start, end); + res.send({ + code: "0", + msg: "Success", + data: { + totalElements, + page, + size, + content: paginatedList, + }, + }); + }); + + // 创建知识库 + router.post(API.createKnowledgeBaseUsingPost, (req, res) => { + const item = KnowledgeBaseItem(); + knowledgeBaseList.unshift(item); + res.status(201).send(item); + }); + + // 获取知识库详情 + router.get(API.queryKnowledgeBaseByIdUsingGet, (req, res) => { + const id = req.params.baseId; + const item = + knowledgeBaseList.find((kb) => kb.id === id) || KnowledgeBaseItem(); + res.send({ + code: "0", + msg: "Success", + data: item, + }); + }); + + // 更新知识库 + router.put(API.updateKnowledgeBaseByIdUsingPut, (req, res) => { + const id = req.params.baseId; + const idx = knowledgeBaseList.findIndex((kb) => kb.id === id); + if (idx >= 0) { + knowledgeBaseList[idx] = { ...knowledgeBaseList[idx], ...req.body }; + res.status(201).send(knowledgeBaseList[idx]); + } else { + res.status(404).send({ message: "Not found" }); + } + }); + + // 删除知识库 + router.delete(API.deleteKnowledgeBaseByIdUsingDelete, (req, res) => { + const id = req.params.baseId; + const idx = knowledgeBaseList.findIndex((kb) => kb.id === id); + if (idx >= 0) { + knowledgeBaseList.splice(idx, 1); + res.status(201).send({ success: true }); + } else { + res.status(404).send({ message: "Not found" }); + } + }); + + // 添加文件到知识库 + router.post(API.addKnowledgeBaseFilesUsingPost, (req, res) => { + const file = Mock.mock({ + id: "@guid", + name: "@ctitle(5,15)", + size: "@integer(1000,1000000)", + status: "uploaded", + createdAt: "@datetime", + }); + res.status(201).send(file); + }); + + // 获取知识生成文件详情 + router.get(API.queryKnowledgeBaseFilesGet, (req, res) => { + const { keyword, page, size } = req.query; + let filteredList = fileList; + if (keyword) { + filteredList = fileList.filter((file) => file.fileName.includes(keyword)); + } + const start = page * size; + const end = start + size; + const totalElements = filteredList.length; + const paginatedList = filteredList.slice(start, end); + res.send({ + code: "0", + msg: "Success", + data: { + totalElements, + page, + size, + content: paginatedList, + }, + }); + }); + + router.get(API.queryKnowledgeBaseFilesByIdUsingGet, (req, res) => { + const { baseId, fileId } = req.params; + const item = + fileList.find( + (file) => file.knowledgeBaseId === baseId && file.id === fileId + ) || fileItem(); + res.send({ + code: "0", + msg: "Success", + data: item, + }); + }); + + // 删除知识生成文件 + router.delete(API.deleteKnowledgeBaseTaskByIdUsingDelete, (req, res) => { + const { id } = req.params; + const idx = fileList.findIndex((file) => file.id === id); + if (idx >= 0) { + fileList.splice(idx, 1); + res.status(200).send({ success: true }); + return; + } + res.status(404).send({ message: "Not found" }); + }); +}; diff --git a/frontend/src/mock/mock-seed/operator-market.cjs b/frontend/src/mock/mock-seed/operator-market.cjs index fb6560a26..97c93cb4d 100644 --- a/frontend/src/mock/mock-seed/operator-market.cjs +++ b/frontend/src/mock/mock-seed/operator-market.cjs @@ -1,150 +1,150 @@ -const Mock = require("mockjs"); -const API = require("../mock-apis.cjs"); - -// 算子标签数据 -function labelItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name: Mock.Random.pick([ - "数据清洗", - "特征选择", - "分类算法", - "聚类算法", - "回归分析", - "深度神经网络", - "卷积神经网络", - "循环神经网络", - "注意力机制", - "文本分析", - "图像处理", - "语音识别", - "推荐算法", - "异常检测", - "优化算法", - "集成学习", - "迁移学习", - "强化学习", - "联邦学习", - ]), - usageCount: Mock.Random.integer(1, 500), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - }; -} - -const labelList = new Array(50).fill(null).map(labelItem); - -module.exports = function (router) { - router.post(API.preUploadOperatorUsingPost, (req, res) => { - res.status(201).send(Mock.Random.guid()); - }); - - // 上传切片 - router.post(API.uploadFileChunkUsingPost, (req, res) => { - // res.status(500).send({ message: "Simulated upload failure" }); - res.status(201).send({ data: "success" }); - }); - - // 取消上传 - router.put(API.cancelUploadOperatorUsingPut, (req, res) => { - res.status(201).send({ data: "success" }); - }); - - router.post(API.uploadOperatorUsingPost, (req, res) => { - res.status(201).send({ - code: "0", - msg: "Upload successful", - data: { - operatorId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - // 其他返回数据 - }, - }); - }); - - // 获取算子标签列表 - router.get(API.queryLabelsUsingGet, (req, res) => { - const { page = 0, size = 20, keyword = "" } = req.query; - - let filteredLabels = labelList; - - if (keyword) { - filteredLabels = labelList.filter((label) => - label.name.toLowerCase().includes(keyword.toLowerCase()) - ); - } - - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = filteredLabels.slice(startIndex, endIndex); - - res.send({ - code: "0", - msg: "Success", - data: { - content: pageData, - totalElements: filteredLabels.length, - totalPages: Math.ceil(filteredLabels.length / size), - size: parseInt(size), - number: parseInt(page), - }, - }); - }); - - // 创建标签 - router.post(API.createLabelUsingPost, (req, res) => { - const { name } = req.body; - - const newLabel = { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - name, - usageCount: 0, - createdAt: new Date().toISOString(), - }; - - labelList.push(newLabel); - - res.status(201).send({ - code: "0", - msg: "Label created successfully", - data: newLabel, - }); - }); - - // 批量删除标签 - router.delete(API.deleteLabelsUsingDelete, (req, res) => { - const labelIds = req.body; // 数组形式的标签ID列表 - - let deletedCount = 0; - labelIds.forEach((labelId) => { - const index = labelList.findIndex((label) => label.id === labelId); - if (index !== -1) { - labelList.splice(index, 1); - deletedCount++; - } - }); - - res.status(204).send(); - }); - - // 更新标签 - router.put(API.updateLabelByIdUsingPut, (req, res) => { - const { id } = req.params; - const updates = req.body; // 数组形式的更新数据 - - updates.forEach((update) => { - const index = labelList.findIndex((label) => label.id === update.id); - if (index !== -1) { - labelList[index] = { - ...labelList[index], - ...update, - updatedAt: new Date().toISOString(), - }; - } - }); - - res.send({ - code: "0", - msg: "Labels updated successfully", - data: null, - }); - }); -}; +const Mock = require("mockjs"); +const API = require("../mock-apis.cjs"); + +// 算子标签数据 +function labelItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name: Mock.Random.pick([ + "数据清洗", + "特征选择", + "分类算法", + "聚类算法", + "回归分析", + "深度神经网络", + "卷积神经网络", + "循环神经网络", + "注意力机制", + "文本分析", + "图像处理", + "语音识别", + "推荐算法", + "异常检测", + "优化算法", + "集成学习", + "迁移学习", + "强化学习", + "联邦学习", + ]), + usageCount: Mock.Random.integer(1, 500), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + }; +} + +const labelList = new Array(50).fill(null).map(labelItem); + +module.exports = function (router) { + router.post(API.preUploadOperatorUsingPost, (req, res) => { + res.status(201).send(Mock.Random.guid()); + }); + + // 上传切片 + router.post(API.uploadFileChunkUsingPost, (req, res) => { + // res.status(500).send({ message: "Simulated upload failure" }); + res.status(201).send({ data: "success" }); + }); + + // 取消上传 + router.put(API.cancelUploadOperatorUsingPut, (req, res) => { + res.status(201).send({ data: "success" }); + }); + + router.post(API.uploadOperatorUsingPost, (req, res) => { + res.status(201).send({ + code: "0", + msg: "Upload successful", + data: { + operatorId: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + // 其他返回数据 + }, + }); + }); + + // 获取算子标签列表 + router.get(API.queryLabelsUsingGet, (req, res) => { + const { page = 0, size = 20, keyword = "" } = req.query; + + let filteredLabels = labelList; + + if (keyword) { + filteredLabels = labelList.filter((label) => + label.name.toLowerCase().includes(keyword.toLowerCase()) + ); + } + + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = filteredLabels.slice(startIndex, endIndex); + + res.send({ + code: "0", + msg: "Success", + data: { + content: pageData, + totalElements: filteredLabels.length, + totalPages: Math.ceil(filteredLabels.length / size), + size: parseInt(size), + number: parseInt(page), + }, + }); + }); + + // 创建标签 + router.post(API.createLabelUsingPost, (req, res) => { + const { name } = req.body; + + const newLabel = { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + name, + usageCount: 0, + createdAt: new Date().toISOString(), + }; + + labelList.push(newLabel); + + res.status(201).send({ + code: "0", + msg: "Label created successfully", + data: newLabel, + }); + }); + + // 批量删除标签 + router.delete(API.deleteLabelsUsingDelete, (req, res) => { + const labelIds = req.body; // 数组形式的标签ID列表 + + let deletedCount = 0; + labelIds.forEach((labelId) => { + const index = labelList.findIndex((label) => label.id === labelId); + if (index !== -1) { + labelList.splice(index, 1); + deletedCount++; + } + }); + + res.status(204).send(); + }); + + // 更新标签 + router.put(API.updateLabelByIdUsingPut, (req, res) => { + const { id } = req.params; + const updates = req.body; // 数组形式的更新数据 + + updates.forEach((update) => { + const index = labelList.findIndex((label) => label.id === update.id); + if (index !== -1) { + labelList[index] = { + ...labelList[index], + ...update, + updatedAt: new Date().toISOString(), + }; + } + }); + + res.send({ + code: "0", + msg: "Labels updated successfully", + data: null, + }); + }); +}; diff --git a/frontend/src/mock/mock-seed/settings.cjs b/frontend/src/mock/mock-seed/settings.cjs index 8bcca2fdd..886a0b345 100644 --- a/frontend/src/mock/mock-seed/settings.cjs +++ b/frontend/src/mock/mock-seed/settings.cjs @@ -1,177 +1,177 @@ -const Mock = require("mockjs"); -const API = require("../mock-apis.cjs"); - -// 算子标签数据 -function ModelItem() { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - modelName: Mock.Random.pick([ - "数据清洗", - "特征选择", - "分类算法", - "聚类算法", - "回归分析", - "深度神经网络", - "卷积神经网络", - "循环神经网络", - "注意力机制", - "文本分析", - "图像处理", - "语音识别", - "推荐算法", - "异常检测", - "优化算法", - "集成学习", - "迁移学习", - "强化学习", - "联邦学习", - ]), - provider: Mock.Random.pick([ - "OpenAI", - "Anthropic", - "Cohere", - "AI21 Labs", - "Hugging Face", - "Google Cloud AI", - "Microsoft Azure AI", - "Amazon Web Services AI", - "IBM Watson", - "Alibaba Cloud AI", - ]), - type: Mock.Random.pick(["CHAT", "EMBEDDING"]), - usageCount: Mock.Random.integer(1, 500), - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - }; -} - -const modelList = new Array(50).fill(null).map(ModelItem); - -function ProviderItem(provider) { - return { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - provider, - baseUrl: Mock.Random.url("https") + "/v1/models", - createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), - }; -} - -const ProviderList = [ - "OpenAI", - "Anthropic", - "Cohere", - "AI21 Labs", - "Hugging Face", - "Google Cloud AI", - "Microsoft Azure AI", - "Amazon Web Services AI", - "IBM Watson", - "Alibaba Cloud AI", -].map(ProviderItem); - -module.exports = function (router) { - // 获取模型列表 - router.get(API.queryModelsUsingGet, (req, res) => { - const { - page = 0, - size = 20, - keyword = "", - provider = "", - type = "", - } = req.query; - - let filteredModels = modelList; - - if (keyword) { - filteredModels = modelList.filter((model) => - model.modelName.toLowerCase().includes(keyword.toLowerCase()) - ); - } - if (provider && provider !== "all") { - filteredModels = filteredModels.filter( - (model) => model.provider === provider - ); - } - if (type && type !== "all") { - filteredModels = filteredModels.filter((model) => model.type === type); - } - - const startIndex = page * size; - const endIndex = startIndex + parseInt(size); - const pageData = filteredModels.slice(startIndex, endIndex); - - res.status(201).send({ - code: "0", - msg: "Success", - data: { - content: pageData, - totalElements: filteredModels.length, - totalPages: Math.ceil(filteredModels.length / size), - size: parseInt(size), - number: parseInt(page), - }, - }); - }); - - // 获取模型提供商列表 - router.get(API.queryProvidersUsingGet, (req, res) => { - res.status(201).send({ - code: "0", - msg: "success", - data: ProviderList, - }); - }); - - // 创建模型 - router.post(API.createModelUsingPost, (req, res) => { - const { ...modelData } = req.body; - const newModel = { - id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), - ...modelData, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; - modelList.unshift(newModel); - res.status(201).send({ - code: "0", - msg: "success", - data: newModel, - }); - }); - - // 删除模型 - router.delete(API.deleteModelUsingDelete, (req, res) => { - const { id } = req.params; - - const index = modelList.findIndex((model) => model.id === id); - if (index !== -1) { - modelList.splice(index, 1); - } - - res.status(204).send({ - code: "0", - msg: "success", - data: null, - }); - }); - - // 更新模型 - router.put(API.updateModelUsingPut, (req, res) => { - const { id, ...update } = req.params; - - const index = modelList.findIndex((model) => model.id === id); - if (index !== -1) { - modelList[index] = { - ...modelList[index], - ...update, - updatedAt: new Date().toISOString(), - }; - } - - res.status(201).send({ - code: "0", - msg: "success", - data: null, - }); - }); -}; +const Mock = require("mockjs"); +const API = require("../mock-apis.cjs"); + +// 算子标签数据 +function ModelItem() { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + modelName: Mock.Random.pick([ + "数据清洗", + "特征选择", + "分类算法", + "聚类算法", + "回归分析", + "深度神经网络", + "卷积神经网络", + "循环神经网络", + "注意力机制", + "文本分析", + "图像处理", + "语音识别", + "推荐算法", + "异常检测", + "优化算法", + "集成学习", + "迁移学习", + "强化学习", + "联邦学习", + ]), + provider: Mock.Random.pick([ + "OpenAI", + "Anthropic", + "Cohere", + "AI21 Labs", + "Hugging Face", + "Google Cloud AI", + "Microsoft Azure AI", + "Amazon Web Services AI", + "IBM Watson", + "Alibaba Cloud AI", + ]), + type: Mock.Random.pick(["CHAT", "EMBEDDING"]), + usageCount: Mock.Random.integer(1, 500), + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + updatedAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + }; +} + +const modelList = new Array(50).fill(null).map(ModelItem); + +function ProviderItem(provider) { + return { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + provider, + baseUrl: Mock.Random.url("https") + "/v1/models", + createdAt: Mock.Random.datetime("yyyy-MM-dd HH:mm:ss"), + }; +} + +const ProviderList = [ + "OpenAI", + "Anthropic", + "Cohere", + "AI21 Labs", + "Hugging Face", + "Google Cloud AI", + "Microsoft Azure AI", + "Amazon Web Services AI", + "IBM Watson", + "Alibaba Cloud AI", +].map(ProviderItem); + +module.exports = function (router) { + // 获取模型列表 + router.get(API.queryModelsUsingGet, (req, res) => { + const { + page = 0, + size = 20, + keyword = "", + provider = "", + type = "", + } = req.query; + + let filteredModels = modelList; + + if (keyword) { + filteredModels = modelList.filter((model) => + model.modelName.toLowerCase().includes(keyword.toLowerCase()) + ); + } + if (provider && provider !== "all") { + filteredModels = filteredModels.filter( + (model) => model.provider === provider + ); + } + if (type && type !== "all") { + filteredModels = filteredModels.filter((model) => model.type === type); + } + + const startIndex = page * size; + const endIndex = startIndex + parseInt(size); + const pageData = filteredModels.slice(startIndex, endIndex); + + res.status(201).send({ + code: "0", + msg: "Success", + data: { + content: pageData, + totalElements: filteredModels.length, + totalPages: Math.ceil(filteredModels.length / size), + size: parseInt(size), + number: parseInt(page), + }, + }); + }); + + // 获取模型提供商列表 + router.get(API.queryProvidersUsingGet, (req, res) => { + res.status(201).send({ + code: "0", + msg: "success", + data: ProviderList, + }); + }); + + // 创建模型 + router.post(API.createModelUsingPost, (req, res) => { + const { ...modelData } = req.body; + const newModel = { + id: Mock.Random.guid().replace(/[^a-zA-Z0-9]/g, ""), + ...modelData, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + modelList.unshift(newModel); + res.status(201).send({ + code: "0", + msg: "success", + data: newModel, + }); + }); + + // 删除模型 + router.delete(API.deleteModelUsingDelete, (req, res) => { + const { id } = req.params; + + const index = modelList.findIndex((model) => model.id === id); + if (index !== -1) { + modelList.splice(index, 1); + } + + res.status(204).send({ + code: "0", + msg: "success", + data: null, + }); + }); + + // 更新模型 + router.put(API.updateModelUsingPut, (req, res) => { + const { id, ...update } = req.params; + + const index = modelList.findIndex((model) => model.id === id); + if (index !== -1) { + modelList[index] = { + ...modelList[index], + ...update, + updatedAt: new Date().toISOString(), + }; + } + + res.status(201).send({ + code: "0", + msg: "success", + data: null, + }); + }); +}; diff --git a/frontend/src/mock/mock.cjs b/frontend/src/mock/mock.cjs index eb23a8a3d..1e50cd7ab 100644 --- a/frontend/src/mock/mock.cjs +++ b/frontend/src/mock/mock.cjs @@ -1,58 +1,58 @@ -const express = require('express'); -const fs = require('fs-extra'); -const path = require('path'); -const bodyParser = require('body-parser'); -const { genExpressSession } = require('./mock-core/session-helper.cjs'); -const { - setHeader, - sendJSON, - strongMatch, - errorHandle, -} = require('./mock-middleware/index.cjs'); - - -const { loadAllMockModules } = require('./mock-core/module-loader.cjs'); -const { log } = require('./mock-core/util.cjs'); - -const app = express(); -const router = express.Router(); - -const argv = require('minimist')(process.argv.slice(2)); -const deployUrl = argv['deploy-url'] || '/'; -const deployPath = argv['deploy-path'] || '/'; -const port = argv.port || 8002; -const env = argv.env || 'development'; - -// app静态文件实际目录 -const deployAppPath = path.join(__dirname, deployPath); -preStartCheck(deployAppPath); - -app.use(setHeader); - -// 提供静态文件服务 -app.use(deployUrl, express.static(deployAppPath)); -app.use(bodyParser.json({limit: '1mb'})); -app.use(bodyParser.urlencoded({ extended: false, limit: '1mb' })); -app.use(sendJSON); -app.use(strongMatch); -app.use(genExpressSession()); - -const mockDir = path.join(__dirname, '/mock-seed'); -loadAllMockModules(router, mockDir); -app.use(deployUrl, router); -app.use(errorHandle); - -app.get('/', (req, res) => { - res.sendFile('default response', { root: deployAppPath }); -}); - -app.listen(port, function() { - log(`Mock server is running at http://localhost:${port}${deployUrl} in ${env} mode`); -}) - -function preStartCheck(deployAppPath) { - if(!fs.existsSync(deployAppPath)) { - log(`Error: The path ${deployAppPath} does not exist. Please build the frontend application first.`, 'error'); - process.exit(1); - } +const express = require('express'); +const fs = require('fs-extra'); +const path = require('path'); +const bodyParser = require('body-parser'); +const { genExpressSession } = require('./mock-core/session-helper.cjs'); +const { + setHeader, + sendJSON, + strongMatch, + errorHandle, +} = require('./mock-middleware/index.cjs'); + + +const { loadAllMockModules } = require('./mock-core/module-loader.cjs'); +const { log } = require('./mock-core/util.cjs'); + +const app = express(); +const router = express.Router(); + +const argv = require('minimist')(process.argv.slice(2)); +const deployUrl = argv['deploy-url'] || '/'; +const deployPath = argv['deploy-path'] || '/'; +const port = argv.port || 8002; +const env = argv.env || 'development'; + +// app静态文件实际目录 +const deployAppPath = path.join(__dirname, deployPath); +preStartCheck(deployAppPath); + +app.use(setHeader); + +// 提供静态文件服务 +app.use(deployUrl, express.static(deployAppPath)); +app.use(bodyParser.json({limit: '1mb'})); +app.use(bodyParser.urlencoded({ extended: false, limit: '1mb' })); +app.use(sendJSON); +app.use(strongMatch); +app.use(genExpressSession()); + +const mockDir = path.join(__dirname, '/mock-seed'); +loadAllMockModules(router, mockDir); +app.use(deployUrl, router); +app.use(errorHandle); + +app.get('/', (req, res) => { + res.sendFile('default response', { root: deployAppPath }); +}); + +app.listen(port, function() { + log(`Mock server is running at http://localhost:${port}${deployUrl} in ${env} mode`); +}) + +function preStartCheck(deployAppPath) { + if(!fs.existsSync(deployAppPath)) { + log(`Error: The path ${deployAppPath} does not exist. Please build the frontend application first.`, 'error'); + process.exit(1); + } } \ No newline at end of file diff --git a/frontend/src/mock/nodemon.json b/frontend/src/mock/nodemon.json index eb9ea0c96..90e2cc486 100644 --- a/frontend/src/mock/nodemon.json +++ b/frontend/src/mock/nodemon.json @@ -1,22 +1,22 @@ -{ - "restartable": "rs", - "ignore": [ - ".git", - "node_modules/**/node_modules", - "dist", - "build", - "*.test.js", - "*.spec.js" - ], - "verbose": true, - "watch": ["*.cjs"], - "exec": "node --inspect=0.0.0.0:9229 mock.cjs", - "ext": "js,cjs,json", - "execMap": { - "js": "node --harmony" - }, - "env": { - "NODE_ENV": "development" - }, - "signal": "SIGTERM" -} +{ + "restartable": "rs", + "ignore": [ + ".git", + "node_modules/**/node_modules", + "dist", + "build", + "*.test.js", + "*.spec.js" + ], + "verbose": true, + "watch": ["*.cjs"], + "exec": "node --inspect=0.0.0.0:9229 mock.cjs", + "ext": "js,cjs,json", + "execMap": { + "js": "node --harmony" + }, + "env": { + "NODE_ENV": "development" + }, + "signal": "SIGTERM" +} diff --git a/frontend/src/mock/synthesis.tsx b/frontend/src/mock/synthesis.tsx index 5de7ae362..cc961207a 100644 --- a/frontend/src/mock/synthesis.tsx +++ b/frontend/src/mock/synthesis.tsx @@ -1,209 +1,209 @@ -// Add mock files data -export const mockFiles = [ - { id: "file1", name: "dataset_part_001.jsonl", size: "2.5MB", type: "JSONL" }, - { id: "file2", name: "dataset_part_002.jsonl", size: "2.3MB", type: "JSONL" }, - { id: "file3", name: "dataset_part_003.jsonl", size: "2.7MB", type: "JSONL" }, - { id: "file4", name: "training_data.txt", size: "1.8MB", type: "TXT" }, - { id: "file5", name: "validation_set.csv", size: "856KB", type: "CSV" }, - { id: "file6", name: "test_samples.json", size: "1.2MB", type: "JSON" }, - { id: "file7", name: "raw_text_001.txt", size: "3.1MB", type: "TXT" }, - { id: "file8", name: "raw_text_002.txt", size: "2.9MB", type: "TXT" }, -]; - -export const mockSynthesisTasks: SynthesisTask[] = [ - { - id: 1, - name: "文字生成问答对_判断题", - type: "qa", - status: "completed", - progress: 100, - sourceDataset: "orig_20250724_64082", - targetCount: 1000, - generatedCount: 1000, - createdAt: "2025-01-20", - template: "判断题生成模板", - estimatedTime: "已完成", - quality: 95, - }, - { - id: 2, - name: "知识蒸馏数据集", - type: "distillation", - status: "running", - progress: 65, - sourceDataset: "teacher_model_outputs", - targetCount: 5000, - generatedCount: 3250, - createdAt: "2025-01-22", - template: "蒸馏模板v2", - estimatedTime: "剩余 15 分钟", - quality: 88, - }, - { - id: 3, - name: "多模态对话生成", - type: "multimodal", - status: "failed", - progress: 25, - sourceDataset: "image_text_pairs", - targetCount: 2000, - generatedCount: 500, - createdAt: "2025-01-23", - template: "多模态对话模板", - errorMessage: "模型API调用失败,请检查配置", - }, - { - id: 4, - name: "金融问答数据生成", - type: "qa", - status: "pending", - progress: 0, - sourceDataset: "financial_qa_dataset", - targetCount: 800, - generatedCount: 0, - createdAt: "2025-01-24", - template: "金融问答模板", - estimatedTime: "等待开始", - quality: 0, - }, - { - id: 5, - name: "医疗文本蒸馏", - type: "distillation", - status: "paused", - progress: 45, - sourceDataset: "medical_corpus", - targetCount: 3000, - generatedCount: 1350, - createdAt: "2025-01-21", - template: "医疗蒸馏模板", - estimatedTime: "已暂停", - quality: 92, - }, -]; - -export const mockTemplates: Template[] = [ - { - id: 1, - name: "判断题生成模板", - type: "preset", - category: "问答对生成", - prompt: `根据给定的文本内容,生成一个判断题。 - -文本内容:{text} - -请按照以下格式生成: -1. 判断题:[基于文本内容的判断题] -2. 答案:[对/错] -3. 解释:[简要解释为什么这个答案是正确的] - -要求: -- 判断题应该基于文本的核心内容 -- 答案必须明确且有依据 -- 解释要简洁清晰`, - variables: ["text"], - description: "根据文本内容生成判断题,适用于教育和培训场景", - usageCount: 156, - lastUsed: "2025-01-20", - quality: 95, - }, - { - id: 2, - name: "选择题生成模板", - type: "preset", - category: "问答对生成", - prompt: `基于以下文本,创建一个多选题: - -{text} - -请按照以下格式生成: -问题:[基于文本的问题] -A. [选项A] -B. [选项B] -C. [选项C] -D. [选项D] -正确答案:[A/B/C/D] -解析:[详细解释] - -要求: -- 问题要有一定难度 -- 选项要有迷惑性 -- 正确答案要有充分依据`, - variables: ["text"], - description: "生成多选题的标准模板,适用于考试和评估", - usageCount: 89, - lastUsed: "2025-01-19", - quality: 92, - }, - { - id: 3, - name: "知识蒸馏模板", - type: "preset", - category: "蒸馏数据集", - prompt: `作为学生模型,学习教师模型的输出: - -输入:{input} -教师输出:{teacher_output} - -请模仿教师模型的推理过程和输出格式,生成相似质量的回答。 - -要求: -- 保持教师模型的推理逻辑 -- 输出格式要一致 -- 质量要接近教师模型水平`, - variables: ["input", "teacher_output"], - description: "用于知识蒸馏的模板,帮助小模型学习大模型的能力", - usageCount: 234, - lastUsed: "2025-01-22", - quality: 88, - }, - { - id: 4, - name: "金融问答模板", - type: "custom", - category: "问答对生成", - prompt: `基于金融领域知识,生成专业问答对: - -参考内容:{content} - -生成格式: -问题:[专业的金融问题] -答案:[准确的专业回答] -关键词:[相关金融术语] - -要求: -- 问题具有实用性 -- 答案准确专业 -- 符合金融行业标准`, - variables: ["content"], - description: "专门用于金融领域的问答对生成", - usageCount: 45, - lastUsed: "2025-01-18", - quality: 89, - }, - { - id: 5, - name: "医疗蒸馏模板", - type: "custom", - category: "蒸馏数据集", - prompt: `医疗知识蒸馏模板: - -原始医疗文本:{medical_text} -专家标注:{expert_annotation} - -生成医疗知识点: -1. 核心概念:[提取关键医疗概念] -2. 临床意义:[说明临床应用价值] -3. 注意事项:[重要提醒和禁忌] - -要求: -- 确保医疗信息准确性 -- 遵循医疗伦理规范 -- 适合医学教育使用`, - variables: ["medical_text", "expert_annotation"], - description: "医疗领域专用的知识蒸馏模板", - usageCount: 67, - lastUsed: "2025-01-21", - quality: 94, - }, -]; +// Add mock files data +export const mockFiles = [ + { id: "file1", name: "dataset_part_001.jsonl", size: "2.5MB", type: "JSONL" }, + { id: "file2", name: "dataset_part_002.jsonl", size: "2.3MB", type: "JSONL" }, + { id: "file3", name: "dataset_part_003.jsonl", size: "2.7MB", type: "JSONL" }, + { id: "file4", name: "training_data.txt", size: "1.8MB", type: "TXT" }, + { id: "file5", name: "validation_set.csv", size: "856KB", type: "CSV" }, + { id: "file6", name: "test_samples.json", size: "1.2MB", type: "JSON" }, + { id: "file7", name: "raw_text_001.txt", size: "3.1MB", type: "TXT" }, + { id: "file8", name: "raw_text_002.txt", size: "2.9MB", type: "TXT" }, +]; + +export const mockSynthesisTasks: SynthesisTask[] = [ + { + id: 1, + name: "文字生成问答对_判断题", + type: "qa", + status: "completed", + progress: 100, + sourceDataset: "orig_20250724_64082", + targetCount: 1000, + generatedCount: 1000, + createdAt: "2025-01-20", + template: "判断题生成模板", + estimatedTime: "已完成", + quality: 95, + }, + { + id: 2, + name: "知识蒸馏数据集", + type: "distillation", + status: "running", + progress: 65, + sourceDataset: "teacher_model_outputs", + targetCount: 5000, + generatedCount: 3250, + createdAt: "2025-01-22", + template: "蒸馏模板v2", + estimatedTime: "剩余 15 分钟", + quality: 88, + }, + { + id: 3, + name: "多模态对话生成", + type: "multimodal", + status: "failed", + progress: 25, + sourceDataset: "image_text_pairs", + targetCount: 2000, + generatedCount: 500, + createdAt: "2025-01-23", + template: "多模态对话模板", + errorMessage: "模型API调用失败,请检查配置", + }, + { + id: 4, + name: "金融问答数据生成", + type: "qa", + status: "pending", + progress: 0, + sourceDataset: "financial_qa_dataset", + targetCount: 800, + generatedCount: 0, + createdAt: "2025-01-24", + template: "金融问答模板", + estimatedTime: "等待开始", + quality: 0, + }, + { + id: 5, + name: "医疗文本蒸馏", + type: "distillation", + status: "paused", + progress: 45, + sourceDataset: "medical_corpus", + targetCount: 3000, + generatedCount: 1350, + createdAt: "2025-01-21", + template: "医疗蒸馏模板", + estimatedTime: "已暂停", + quality: 92, + }, +]; + +export const mockTemplates: Template[] = [ + { + id: 1, + name: "判断题生成模板", + type: "preset", + category: "问答对生成", + prompt: `根据给定的文本内容,生成一个判断题。 + +文本内容:{text} + +请按照以下格式生成: +1. 判断题:[基于文本内容的判断题] +2. 答案:[对/错] +3. 解释:[简要解释为什么这个答案是正确的] + +要求: +- 判断题应该基于文本的核心内容 +- 答案必须明确且有依据 +- 解释要简洁清晰`, + variables: ["text"], + description: "根据文本内容生成判断题,适用于教育和培训场景", + usageCount: 156, + lastUsed: "2025-01-20", + quality: 95, + }, + { + id: 2, + name: "选择题生成模板", + type: "preset", + category: "问答对生成", + prompt: `基于以下文本,创建一个多选题: + +{text} + +请按照以下格式生成: +问题:[基于文本的问题] +A. [选项A] +B. [选项B] +C. [选项C] +D. [选项D] +正确答案:[A/B/C/D] +解析:[详细解释] + +要求: +- 问题要有一定难度 +- 选项要有迷惑性 +- 正确答案要有充分依据`, + variables: ["text"], + description: "生成多选题的标准模板,适用于考试和评估", + usageCount: 89, + lastUsed: "2025-01-19", + quality: 92, + }, + { + id: 3, + name: "知识蒸馏模板", + type: "preset", + category: "蒸馏数据集", + prompt: `作为学生模型,学习教师模型的输出: + +输入:{input} +教师输出:{teacher_output} + +请模仿教师模型的推理过程和输出格式,生成相似质量的回答。 + +要求: +- 保持教师模型的推理逻辑 +- 输出格式要一致 +- 质量要接近教师模型水平`, + variables: ["input", "teacher_output"], + description: "用于知识蒸馏的模板,帮助小模型学习大模型的能力", + usageCount: 234, + lastUsed: "2025-01-22", + quality: 88, + }, + { + id: 4, + name: "金融问答模板", + type: "custom", + category: "问答对生成", + prompt: `基于金融领域知识,生成专业问答对: + +参考内容:{content} + +生成格式: +问题:[专业的金融问题] +答案:[准确的专业回答] +关键词:[相关金融术语] + +要求: +- 问题具有实用性 +- 答案准确专业 +- 符合金融行业标准`, + variables: ["content"], + description: "专门用于金融领域的问答对生成", + usageCount: 45, + lastUsed: "2025-01-18", + quality: 89, + }, + { + id: 5, + name: "医疗蒸馏模板", + type: "custom", + category: "蒸馏数据集", + prompt: `医疗知识蒸馏模板: + +原始医疗文本:{medical_text} +专家标注:{expert_annotation} + +生成医疗知识点: +1. 核心概念:[提取关键医疗概念] +2. 临床意义:[说明临床应用价值] +3. 注意事项:[重要提醒和禁忌] + +要求: +- 确保医疗信息准确性 +- 遵循医疗伦理规范 +- 适合医学教育使用`, + variables: ["medical_text", "expert_annotation"], + description: "医疗领域专用的知识蒸馏模板", + usageCount: 67, + lastUsed: "2025-01-21", + quality: 94, + }, +]; diff --git a/frontend/src/pages/Agent/Agent.tsx b/frontend/src/pages/Agent/Agent.tsx index 53861c633..94df683d5 100644 --- a/frontend/src/pages/Agent/Agent.tsx +++ b/frontend/src/pages/Agent/Agent.tsx @@ -1,480 +1,480 @@ -import type React from "react"; - -import { useState, useRef, useEffect } from "react"; -import { Card, Input, Button, Badge } from "antd"; -import { HomeOutlined } from "@ant-design/icons"; -import { - MessageSquare, - Send, - Bot, - User, - Sparkles, - Database, - BarChart3, - Settings, - Zap, - CheckCircle, - Clock, - Download, - ArrowLeft, -} from "lucide-react"; -import { useNavigate } from "react-router"; -import DevelopmentInProgress from "@/components/DevelopmentInProgress"; - -interface Message { - id: string; - type: "user" | "assistant"; - content: string; - timestamp: Date; - actions?: Array<{ - type: - | "create_dataset" - | "run_analysis" - | "start_synthesis" - | "export_report"; - label: string; - data?: any; - }>; - status?: "pending" | "completed" | "error"; -} - -interface QuickAction { - id: string; - label: string; - icon: any; - prompt: string; - category: string; -} - -const quickActions: QuickAction[] = [ - { - id: "create_dataset", - label: "创建数据集", - icon: Database, - prompt: "帮我创建一个新的数据集", - category: "数据管理", - }, - { - id: "analyze_quality", - label: "质量分析", - icon: BarChart3, - prompt: "分析我的数据集质量", - category: "数据评估", - }, - { - id: "start_synthesis", - label: "数据合成", - icon: Sparkles, - prompt: "启动数据合成任务", - category: "数据合成", - }, - { - id: "process_data", - label: "数据清洗", - icon: Settings, - prompt: "对数据集进行预处理", - category: "数据清洗", - }, - { - id: "export_report", - label: "导出报告", - icon: Download, - prompt: "导出最新的分析报告", - category: "报告导出", - }, - { - id: "check_status", - label: "查看状态", - icon: Clock, - prompt: "查看所有任务的运行状态", - category: "状态查询", - }, -]; - -const mockResponses = { - 创建数据集: { - content: - "我来帮您创建一个新的数据集。请告诉我以下信息:\n\n1. 数据集名称\n2. 数据类型(图像、文本、问答对等)\n3. 预期数据量\n4. 数据来源\n\n您也可以直接说出您的需求,我会为您推荐最适合的配置。", - actions: [ - { type: "create_dataset", label: "开始创建", data: { step: "config" } }, - ], - }, - 质量分析: { - content: - "正在为您分析数据集质量...\n\n📊 **分析结果概览:**\n- 图像分类数据集:质量分 92/100\n- 问答对数据集:质量分 87/100\n- 多模态数据集:质量分 78/100\n\n🔍 **发现的主要问题:**\n- 23个重复图像\n- 156个格式不正确的问答对\n- 78个图文不匹配项\n\n💡 **改进建议:**\n- 建议进行去重处理\n- 优化问答对格式\n- 重新标注图文匹配项", - actions: [ - { - type: "run_analysis", - label: "查看详细报告", - data: { type: "detailed" }, - }, - ], - }, - 数据合成: { - content: - "我可以帮您启动数据合成任务。目前支持以下合成类型:\n\n🖼️ **图像数据合成**\n- 数据增强(旋转、翻转、亮度调整)\n- 风格迁移\n- GAN生成\n\n📝 **文本数据合成**\n- 同义词替换\n- 回译增强\n- GPT生成\n\n❓ **问答对合成**\n- 基于知识库生成\n- 模板变换\n- 多轮对话生成\n\n请告诉我您需要合成什么类型的数据,以及目标数量。", - actions: [ - { - type: "start_synthesis", - label: "配置合成任务", - data: { step: "config" }, - }, - ], - }, - 导出报告: { - content: - "正在为您准备最新的分析报告...\n\n📋 **可用报告:**\n- 数据质量评估报告(PDF)\n- 数据分布统计报告(Excel)\n- 模型性能评估报告(PDF)\n- 偏见检测报告(PDF)\n- 综合分析报告(PDF + Excel)\n\n✅ 报告已生成完成,您可以选择下载格式。", - actions: [ - { type: "export_report", label: "下载报告", data: { format: "pdf" } }, - ], - }, - 查看状态: { - content: - "📊 **当前任务状态概览:**\n\n🟢 **运行中的任务:**\n- 问答对生成任务:65% 完成\n- 图像质量分析:运行中\n- 知识库构建:等待中\n\n✅ **已完成的任务:**\n- 图像分类数据集创建:已完成\n- PDF文档提取:已完成\n- 训练集配比任务:已完成\n\n⚠️ **需要关注的任务:**\n- 多模态数据合成:暂停(需要用户确认参数)\n\n所有任务运行正常,预计2小时内全部完成。", - actions: [], - }, -}; - -export default function AgentPage() { - return ; - const navigate = useNavigate(); - const [messages, setMessages] = useState([ - { - id: "welcome", - type: "assistant", - content: - "👋 您好!我是 Data Agent,您的AI数据助手。\n\n我可以帮您:\n• 创建和管理数据集\n• 分析数据质量\n• 启动处理任务\n• 生成分析报告\n• 回答数据相关问题\n\n请告诉我您需要什么帮助,或者点击下方的快捷操作开始。", - timestamp: new Date(), - }, - ]); - const [inputValue, setInputValue] = useState(""); - const [isTyping, setIsTyping] = useState(false); - const messagesEndRef = useRef(null); - const inputRef = useRef(null); - - const scrollToBottom = () => { - messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); - }; - - useEffect(() => { - scrollToBottom(); - }, [messages]); - - const handleSendMessage = async (content: string) => { - if (!content.trim()) return; - - const userMessage: Message = { - id: Date.now().toString(), - type: "user", - content: content.trim(), - timestamp: new Date(), - }; - - setMessages((prev) => [...prev, userMessage]); - setInputValue(""); - setIsTyping(true); - - // 模拟AI响应 - setTimeout(() => { - const response = generateResponse(content); - const assistantMessage: Message = { - id: (Date.now() + 1).toString(), - type: "assistant", - content: response.content, - timestamp: new Date(), - actions: response.actions, - }; - - setMessages((prev) => [...prev, assistantMessage]); - setIsTyping(false); - }, 1500); - }; - - const generateResponse = ( - input: string - ): { content: string; actions?: any[] } => { - const lowerInput = input.toLowerCase(); - - if (lowerInput.includes("创建") && lowerInput.includes("数据集")) { - return mockResponses["创建数据集"]; - } else if (lowerInput.includes("质量") || lowerInput.includes("分析")) { - return mockResponses["质量分析"]; - } else if (lowerInput.includes("合成") || lowerInput.includes("生成")) { - return mockResponses["数据合成"]; - } else if (lowerInput.includes("导出") || lowerInput.includes("报告")) { - return mockResponses["导出报告"]; - } else if (lowerInput.includes("状态") || lowerInput.includes("任务")) { - return mockResponses["查看状态"]; - } else if (lowerInput.includes("你好") || lowerInput.includes("帮助")) { - return { - content: - "很高兴为您服务!我是专门为数据集管理设计的AI助手。\n\n我的主要能力包括:\n\n🔧 **数据集操作**\n- 创建、导入、导出数据集\n- 数据预处理和清洗\n- 批量操作和自动化\n\n📊 **智能分析**\n- 数据质量评估\n- 分布统计分析\n- 性能和偏见检测\n\n🤖 **AI增强**\n- 智能数据合成\n- 自动标注建议\n- 知识库构建\n\n请告诉我您的具体需求,我会为您提供最合适的解决方案!", - }; - } else { - return { - content: `我理解您想要「${input}」。让我为您分析一下...\n\n基于您的需求,我建议:\n\n1. 首先确认具体的操作目标\n2. 选择合适的数据集和参数\n3. 执行相应的处理流程\n\n您可以提供更多详细信息,或者选择下方的快捷操作来开始。如果需要帮助,请说"帮助"获取完整功能列表。`, - actions: [ - { type: "run_analysis", label: "开始分析", data: { query: input } }, - ], - }; - } - }; - - const handleQuickAction = (action: QuickAction) => { - handleSendMessage(action.prompt); - }; - - const handleActionClick = (action: any) => { - const actionMessage: Message = { - id: Date.now().toString(), - type: "assistant", - content: `✅ 正在执行「${action.label}」...\n\n操作已启动,您可以在相应的功能模块中查看详细进度。`, - timestamp: new Date(), - status: "completed", - }; - setMessages((prev) => [...prev, actionMessage]); - }; - - const handleKeyPress = (e: React.KeyboardEvent) => { - if (e.key === "Enter" && !e.shiftKey) { - e.preventDefault(); - handleSendMessage(inputValue); - } - }; - - const formatMessage = (content: string) => { - return content.split("\n").map((line, index) => ( -
- {line ||
} -
- )); - }; - - const onBack = () => { - navigate("/"); - }; - - return ( -
-
- {/* Header */} -
-
-
-
-
- -
-
-

Data Agent

-

- AI驱动的智能数据助手,通过对话完成复杂数据操作 -

-
-
- -
-
-
- -
-
- {/* Chat Area */} -
-
-
-
- 对话窗口 -
- - 在线 -
-
-
-
- {/* Messages */} -
-
- {messages.map((message) => ( -
- {message.type === "assistant" && ( -
- -
- )} -
-
- {formatMessage(message.content)} -
- {message.actions && message.actions.length > 0 && ( -
- {message.actions.map((action, index) => ( - - ))} -
- )} -
- {message.timestamp.toLocaleTimeString()} -
-
- {message.type === "user" && ( -
- -
- )} -
- ))} - {isTyping && ( -
-
- -
-
-
-
-
-
-
-
-
- )} -
-
-
- - {/* Input Area */} -
-
- setInputValue(e.target.value)} - onKeyDown={handleKeyPress} - placeholder="输入您的需求,例如:创建一个图像分类数据集..." - disabled={isTyping} - /> - -
-
-
-
-
- - {/* Quick Actions Sidebar */} -
- -
- 快捷操作 -
- 点击快速开始常用操作 -
-
-
- {quickActions.map((action) => ( - - ))} -
-
- - -
- 系统状态 -
-
-
- - AI服务正常 -
-
- - 3个任务运行中 -
-
- - 12个数据集就绪 -
-
- - 响应时间: 0.8s -
-
-
- - -
- 使用提示 -
-
-
💡 您可以用自然语言描述需求
-
🔍 支持复杂的多步骤操作
-
📊 可以询问数据统计和分析
-
⚡ 使用快捷操作提高效率
-
-
- - -
- -
-
-
-
-
-
-
- ); -} +import type React from "react"; + +import { useState, useRef, useEffect } from "react"; +import { Card, Input, Button, Badge } from "antd"; +import { HomeOutlined } from "@ant-design/icons"; +import { + MessageSquare, + Send, + Bot, + User, + Sparkles, + Database, + BarChart3, + Settings, + Zap, + CheckCircle, + Clock, + Download, + ArrowLeft, +} from "lucide-react"; +import { useNavigate } from "react-router"; +import DevelopmentInProgress from "@/components/DevelopmentInProgress"; + +interface Message { + id: string; + type: "user" | "assistant"; + content: string; + timestamp: Date; + actions?: Array<{ + type: + | "create_dataset" + | "run_analysis" + | "start_synthesis" + | "export_report"; + label: string; + data?: any; + }>; + status?: "pending" | "completed" | "error"; +} + +interface QuickAction { + id: string; + label: string; + icon: any; + prompt: string; + category: string; +} + +const quickActions: QuickAction[] = [ + { + id: "create_dataset", + label: "创建数据集", + icon: Database, + prompt: "帮我创建一个新的数据集", + category: "数据管理", + }, + { + id: "analyze_quality", + label: "质量分析", + icon: BarChart3, + prompt: "分析我的数据集质量", + category: "数据评估", + }, + { + id: "start_synthesis", + label: "数据合成", + icon: Sparkles, + prompt: "启动数据合成任务", + category: "数据合成", + }, + { + id: "process_data", + label: "数据清洗", + icon: Settings, + prompt: "对数据集进行预处理", + category: "数据清洗", + }, + { + id: "export_report", + label: "导出报告", + icon: Download, + prompt: "导出最新的分析报告", + category: "报告导出", + }, + { + id: "check_status", + label: "查看状态", + icon: Clock, + prompt: "查看所有任务的运行状态", + category: "状态查询", + }, +]; + +const mockResponses = { + 创建数据集: { + content: + "我来帮您创建一个新的数据集。请告诉我以下信息:\n\n1. 数据集名称\n2. 数据类型(图像、文本、问答对等)\n3. 预期数据量\n4. 数据来源\n\n您也可以直接说出您的需求,我会为您推荐最适合的配置。", + actions: [ + { type: "create_dataset", label: "开始创建", data: { step: "config" } }, + ], + }, + 质量分析: { + content: + "正在为您分析数据集质量...\n\n📊 **分析结果概览:**\n- 图像分类数据集:质量分 92/100\n- 问答对数据集:质量分 87/100\n- 多模态数据集:质量分 78/100\n\n🔍 **发现的主要问题:**\n- 23个重复图像\n- 156个格式不正确的问答对\n- 78个图文不匹配项\n\n💡 **改进建议:**\n- 建议进行去重处理\n- 优化问答对格式\n- 重新标注图文匹配项", + actions: [ + { + type: "run_analysis", + label: "查看详细报告", + data: { type: "detailed" }, + }, + ], + }, + 数据合成: { + content: + "我可以帮您启动数据合成任务。目前支持以下合成类型:\n\n🖼️ **图像数据合成**\n- 数据增强(旋转、翻转、亮度调整)\n- 风格迁移\n- GAN生成\n\n📝 **文本数据合成**\n- 同义词替换\n- 回译增强\n- GPT生成\n\n❓ **问答对合成**\n- 基于知识库生成\n- 模板变换\n- 多轮对话生成\n\n请告诉我您需要合成什么类型的数据,以及目标数量。", + actions: [ + { + type: "start_synthesis", + label: "配置合成任务", + data: { step: "config" }, + }, + ], + }, + 导出报告: { + content: + "正在为您准备最新的分析报告...\n\n📋 **可用报告:**\n- 数据质量评估报告(PDF)\n- 数据分布统计报告(Excel)\n- 模型性能评估报告(PDF)\n- 偏见检测报告(PDF)\n- 综合分析报告(PDF + Excel)\n\n✅ 报告已生成完成,您可以选择下载格式。", + actions: [ + { type: "export_report", label: "下载报告", data: { format: "pdf" } }, + ], + }, + 查看状态: { + content: + "📊 **当前任务状态概览:**\n\n🟢 **运行中的任务:**\n- 问答对生成任务:65% 完成\n- 图像质量分析:运行中\n- 知识库构建:等待中\n\n✅ **已完成的任务:**\n- 图像分类数据集创建:已完成\n- PDF文档提取:已完成\n- 训练集配比任务:已完成\n\n⚠️ **需要关注的任务:**\n- 多模态数据合成:暂停(需要用户确认参数)\n\n所有任务运行正常,预计2小时内全部完成。", + actions: [], + }, +}; + +export default function AgentPage() { + return ; + const navigate = useNavigate(); + const [messages, setMessages] = useState([ + { + id: "welcome", + type: "assistant", + content: + "👋 您好!我是 Data Agent,您的AI数据助手。\n\n我可以帮您:\n• 创建和管理数据集\n• 分析数据质量\n• 启动处理任务\n• 生成分析报告\n• 回答数据相关问题\n\n请告诉我您需要什么帮助,或者点击下方的快捷操作开始。", + timestamp: new Date(), + }, + ]); + const [inputValue, setInputValue] = useState(""); + const [isTyping, setIsTyping] = useState(false); + const messagesEndRef = useRef(null); + const inputRef = useRef(null); + + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); + }; + + useEffect(() => { + scrollToBottom(); + }, [messages]); + + const handleSendMessage = async (content: string) => { + if (!content.trim()) return; + + const userMessage: Message = { + id: Date.now().toString(), + type: "user", + content: content.trim(), + timestamp: new Date(), + }; + + setMessages((prev) => [...prev, userMessage]); + setInputValue(""); + setIsTyping(true); + + // 模拟AI响应 + setTimeout(() => { + const response = generateResponse(content); + const assistantMessage: Message = { + id: (Date.now() + 1).toString(), + type: "assistant", + content: response.content, + timestamp: new Date(), + actions: response.actions, + }; + + setMessages((prev) => [...prev, assistantMessage]); + setIsTyping(false); + }, 1500); + }; + + const generateResponse = ( + input: string + ): { content: string; actions?: any[] } => { + const lowerInput = input.toLowerCase(); + + if (lowerInput.includes("创建") && lowerInput.includes("数据集")) { + return mockResponses["创建数据集"]; + } else if (lowerInput.includes("质量") || lowerInput.includes("分析")) { + return mockResponses["质量分析"]; + } else if (lowerInput.includes("合成") || lowerInput.includes("生成")) { + return mockResponses["数据合成"]; + } else if (lowerInput.includes("导出") || lowerInput.includes("报告")) { + return mockResponses["导出报告"]; + } else if (lowerInput.includes("状态") || lowerInput.includes("任务")) { + return mockResponses["查看状态"]; + } else if (lowerInput.includes("你好") || lowerInput.includes("帮助")) { + return { + content: + "很高兴为您服务!我是专门为数据集管理设计的AI助手。\n\n我的主要能力包括:\n\n🔧 **数据集操作**\n- 创建、导入、导出数据集\n- 数据预处理和清洗\n- 批量操作和自动化\n\n📊 **智能分析**\n- 数据质量评估\n- 分布统计分析\n- 性能和偏见检测\n\n🤖 **AI增强**\n- 智能数据合成\n- 自动标注建议\n- 知识库构建\n\n请告诉我您的具体需求,我会为您提供最合适的解决方案!", + }; + } else { + return { + content: `我理解您想要「${input}」。让我为您分析一下...\n\n基于您的需求,我建议:\n\n1. 首先确认具体的操作目标\n2. 选择合适的数据集和参数\n3. 执行相应的处理流程\n\n您可以提供更多详细信息,或者选择下方的快捷操作来开始。如果需要帮助,请说"帮助"获取完整功能列表。`, + actions: [ + { type: "run_analysis", label: "开始分析", data: { query: input } }, + ], + }; + } + }; + + const handleQuickAction = (action: QuickAction) => { + handleSendMessage(action.prompt); + }; + + const handleActionClick = (action: any) => { + const actionMessage: Message = { + id: Date.now().toString(), + type: "assistant", + content: `✅ 正在执行「${action.label}」...\n\n操作已启动,您可以在相应的功能模块中查看详细进度。`, + timestamp: new Date(), + status: "completed", + }; + setMessages((prev) => [...prev, actionMessage]); + }; + + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + handleSendMessage(inputValue); + } + }; + + const formatMessage = (content: string) => { + return content.split("\n").map((line, index) => ( +
+ {line ||
} +
+ )); + }; + + const onBack = () => { + navigate("/"); + }; + + return ( +
+
+ {/* Header */} +
+
+
+
+
+ +
+
+

Data Agent

+

+ AI驱动的智能数据助手,通过对话完成复杂数据操作 +

+
+
+ +
+
+
+ +
+
+ {/* Chat Area */} +
+
+
+
+ 对话窗口 +
+ + 在线 +
+
+
+
+ {/* Messages */} +
+
+ {messages.map((message) => ( +
+ {message.type === "assistant" && ( +
+ +
+ )} +
+
+ {formatMessage(message.content)} +
+ {message.actions && message.actions.length > 0 && ( +
+ {message.actions.map((action, index) => ( + + ))} +
+ )} +
+ {message.timestamp.toLocaleTimeString()} +
+
+ {message.type === "user" && ( +
+ +
+ )} +
+ ))} + {isTyping && ( +
+
+ +
+
+
+
+
+
+
+
+
+ )} +
+
+
+ + {/* Input Area */} +
+
+ setInputValue(e.target.value)} + onKeyDown={handleKeyPress} + placeholder="输入您的需求,例如:创建一个图像分类数据集..." + disabled={isTyping} + /> + +
+
+
+
+
+ + {/* Quick Actions Sidebar */} +
+ +
+ 快捷操作 +
+ 点击快速开始常用操作 +
+
+
+ {quickActions.map((action) => ( + + ))} +
+
+ + +
+ 系统状态 +
+
+
+ + AI服务正常 +
+
+ + 3个任务运行中 +
+
+ + 12个数据集就绪 +
+
+ + 响应时间: 0.8s +
+
+
+ + +
+ 使用提示 +
+
+
💡 您可以用自然语言描述需求
+
🔍 支持复杂的多步骤操作
+
📊 可以询问数据统计和分析
+
⚡ 使用快捷操作提高效率
+
+
+ + +
+ +
+
+
+
+
+
+
+ ); +} diff --git a/frontend/src/pages/DataAnnotation/Annotate/AnnotationWorkSpace.tsx b/frontend/src/pages/DataAnnotation/Annotate/AnnotationWorkSpace.tsx index 416640029..fb5910d80 100644 --- a/frontend/src/pages/DataAnnotation/Annotate/AnnotationWorkSpace.tsx +++ b/frontend/src/pages/DataAnnotation/Annotate/AnnotationWorkSpace.tsx @@ -1,229 +1,229 @@ -import { useEffect, useState } from "react"; -import { Card, message } from "antd"; -import { Button, Badge, Progress, Checkbox } from "antd"; -import { - ArrowLeft, - FileText, - ImageIcon, - Video, - Music, - Save, - SkipForward, - CheckCircle, - Eye, - Settings, -} from "lucide-react"; -import { mockTasks } from "@/mock/annotation"; -import { Outlet, useNavigate } from "react-router"; - -export default function AnnotationWorkspace() { - const navigate = useNavigate(); - const [task, setTask] = useState(mockTasks[0]); - - const [currentFileIndex, setCurrentFileIndex] = useState(0); - const [annotationProgress, setAnnotationProgress] = useState({ - completed: task.completedCount, - skipped: task.skippedCount, - total: task.totalCount, - }); - - const handleSaveAndNext = () => { - setAnnotationProgress((prev) => ({ - ...prev, - completed: prev.completed + 1, - })); - - if (currentFileIndex < task.totalCount - 1) { - setCurrentFileIndex(currentFileIndex + 1); - } - - message({ - title: "标注已保存", - description: "标注结果已保存,自动跳转到下一个", - }); - }; - - const handleSkipAndNext = () => { - setAnnotationProgress((prev) => ({ - ...prev, - skipped: prev.skipped + 1, - })); - - if (currentFileIndex < task.totalCount - 1) { - setCurrentFileIndex(currentFileIndex + 1); - } - - message({ - title: "已跳过", - description: "已跳过当前项目,自动跳转到下一个", - }); - }; - - const getDatasetTypeIcon = (type: string) => { - switch (type) { - case "text": - return ; - case "image": - return ; - case "video": - return