mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-11 05:20:57 +00:00
feat: update eslint & prettier rules
This commit is contained in:
@@ -1,3 +1,2 @@
|
|||||||
cd web
|
cd web
|
||||||
pnpm lint-staged
|
pnpm lint-staged
|
||||||
pnpm test
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"*.{js,jsx,ts,tsx}": ["prettier --write", "eslint --fix", "eslint"]
|
"*.{js,jsx,ts,tsx}": ["eslint --fix", "eslint"]
|
||||||
}
|
}
|
||||||
+14
-1
@@ -3,7 +3,20 @@
|
|||||||
* @type {import("prettier").Config}
|
* @type {import("prettier").Config}
|
||||||
*/
|
*/
|
||||||
const config = {
|
const config = {
|
||||||
trailingComma: "none",
|
// 单行长度
|
||||||
|
printWidth: 80,
|
||||||
|
// 缩进
|
||||||
|
tabWidth: 2,
|
||||||
|
// 使用空格代替tab缩进
|
||||||
|
useTabs: false,
|
||||||
|
// 句末使用分号
|
||||||
|
semi: true,
|
||||||
|
// 使用单引号
|
||||||
|
singleQuote: true,
|
||||||
|
// 大括号前后空格
|
||||||
|
bracketSpacing: true,
|
||||||
|
attributeVerticalAlignment: 'auto',
|
||||||
|
trailingComma: 'all',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { dirname } from "path";
|
import { dirname } from 'path';
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from 'url';
|
||||||
import { FlatCompat } from "@eslint/eslintrc";
|
import { FlatCompat } from '@eslint/eslintrc';
|
||||||
|
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = dirname(__filename);
|
const __dirname = dirname(__filename);
|
||||||
@@ -10,7 +11,8 @@ const compat = new FlatCompat({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const eslintConfig = [
|
const eslintConfig = [
|
||||||
...compat.extends("next/core-web-vitals", "next/typescript"),
|
...compat.extends('next/core-web-vitals', 'next/typescript'),
|
||||||
|
eslintPluginPrettierRecommended,
|
||||||
];
|
];
|
||||||
|
|
||||||
export default eslintConfig;
|
export default eslintConfig;
|
||||||
|
|||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from 'next';
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
/* config options here */
|
/* config options here */
|
||||||
output: 'export'
|
output: 'export',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|||||||
Generated
+159
-46
@@ -25,10 +25,13 @@
|
|||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "15.2.4",
|
"eslint-config-next": "15.2.4",
|
||||||
|
"eslint-config-prettier": "^10.1.2",
|
||||||
|
"eslint-plugin-prettier": "^5.2.6",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"lint-staged": "^15.5.1",
|
"lint-staged": "^15.5.1",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"typescript": "^5"
|
"typescript": "^5.8.3",
|
||||||
|
"typescript-eslint": "^8.31.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ant-design/colors": {
|
"node_modules/@ant-design/colors": {
|
||||||
@@ -906,6 +909,18 @@
|
|||||||
"node": ">=12.4.0"
|
"node": ">=12.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@pkgr/core": {
|
||||||
|
"version": "0.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz",
|
||||||
|
"integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/pkgr"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@rc-component/async-validator": {
|
"node_modules/@rc-component/async-validator": {
|
||||||
"version": "5.0.4",
|
"version": "5.0.4",
|
||||||
"resolved": "https://registry.npmmirror.com/@rc-component/async-validator/-/async-validator-5.0.4.tgz",
|
"resolved": "https://registry.npmmirror.com/@rc-component/async-validator/-/async-validator-5.0.4.tgz",
|
||||||
@@ -1133,16 +1148,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.28.0",
|
"version": "8.31.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.1.tgz",
|
||||||
"integrity": "sha512-lvFK3TCGAHsItNdWZ/1FkvpzCxTHUVuFrdnOGLMa0GGCFIbCgQWVk3CzCGdA7kM3qGVc+dfW9tr0Z/sHnGDFyg==",
|
"integrity": "sha512-oUlH4h1ABavI4F0Xnl8/fOtML/eu8nI2A1nYd+f+55XI0BLu+RIqKoCiZKNo6DtqZBEQm5aNKA20G3Z5w3R6GQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/regexpp": "^4.10.0",
|
"@eslint-community/regexpp": "^4.10.0",
|
||||||
"@typescript-eslint/scope-manager": "8.28.0",
|
"@typescript-eslint/scope-manager": "8.31.1",
|
||||||
"@typescript-eslint/type-utils": "8.28.0",
|
"@typescript-eslint/type-utils": "8.31.1",
|
||||||
"@typescript-eslint/utils": "8.28.0",
|
"@typescript-eslint/utils": "8.31.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.28.0",
|
"@typescript-eslint/visitor-keys": "8.31.1",
|
||||||
"graphemer": "^1.4.0",
|
"graphemer": "^1.4.0",
|
||||||
"ignore": "^5.3.1",
|
"ignore": "^5.3.1",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
@@ -1162,15 +1177,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "8.28.0",
|
"version": "8.31.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.31.1.tgz",
|
||||||
"integrity": "sha512-LPcw1yHD3ToaDEoljFEfQ9j2xShY367h7FZ1sq5NJT9I3yj4LHer1Xd1yRSOdYy9BpsrxU7R+eoDokChYM53lQ==",
|
"integrity": "sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.28.0",
|
"@typescript-eslint/scope-manager": "8.31.1",
|
||||||
"@typescript-eslint/types": "8.28.0",
|
"@typescript-eslint/types": "8.31.1",
|
||||||
"@typescript-eslint/typescript-estree": "8.28.0",
|
"@typescript-eslint/typescript-estree": "8.31.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.28.0",
|
"@typescript-eslint/visitor-keys": "8.31.1",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1186,13 +1201,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "8.28.0",
|
"version": "8.31.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.31.1.tgz",
|
||||||
"integrity": "sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==",
|
"integrity": "sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.28.0",
|
"@typescript-eslint/types": "8.31.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.28.0"
|
"@typescript-eslint/visitor-keys": "8.31.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -1203,13 +1218,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "8.28.0",
|
"version": "8.31.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.31.1.tgz",
|
||||||
"integrity": "sha512-oRoXu2v0Rsy/VoOGhtWrOKDiIehvI+YNrDk5Oqj40Mwm0Yt01FC/Q7nFqg088d3yAsR1ZcZFVfPCTTFCe/KPwg==",
|
"integrity": "sha512-fNaT/m9n0+dpSp8G/iOQ05GoHYXbxw81x+yvr7TArTuZuCA6VVKbqWYVZrV5dVagpDTtj/O8k5HBEE/p/HM5LA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/typescript-estree": "8.28.0",
|
"@typescript-eslint/typescript-estree": "8.31.1",
|
||||||
"@typescript-eslint/utils": "8.28.0",
|
"@typescript-eslint/utils": "8.31.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ts-api-utils": "^2.0.1"
|
"ts-api-utils": "^2.0.1"
|
||||||
},
|
},
|
||||||
@@ -1226,9 +1241,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "8.28.0",
|
"version": "8.31.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.31.1.tgz",
|
||||||
"integrity": "sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==",
|
"integrity": "sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -1239,13 +1254,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "8.28.0",
|
"version": "8.31.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.1.tgz",
|
||||||
"integrity": "sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==",
|
"integrity": "sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.28.0",
|
"@typescript-eslint/types": "8.31.1",
|
||||||
"@typescript-eslint/visitor-keys": "8.28.0",
|
"@typescript-eslint/visitor-keys": "8.31.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
@@ -1317,15 +1332,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "8.28.0",
|
"version": "8.31.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.31.1.tgz",
|
||||||
"integrity": "sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==",
|
"integrity": "sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.4.0",
|
"@eslint-community/eslint-utils": "^4.4.0",
|
||||||
"@typescript-eslint/scope-manager": "8.28.0",
|
"@typescript-eslint/scope-manager": "8.31.1",
|
||||||
"@typescript-eslint/types": "8.28.0",
|
"@typescript-eslint/types": "8.31.1",
|
||||||
"@typescript-eslint/typescript-estree": "8.28.0"
|
"@typescript-eslint/typescript-estree": "8.31.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -1340,12 +1355,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "8.28.0",
|
"version": "8.31.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.1.tgz",
|
||||||
"integrity": "sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==",
|
"integrity": "sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "8.28.0",
|
"@typescript-eslint/types": "8.31.1",
|
||||||
"eslint-visitor-keys": "^4.2.0"
|
"eslint-visitor-keys": "^4.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -2640,6 +2655,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint-config-prettier": {
|
||||||
|
"version": "10.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.2.tgz",
|
||||||
|
"integrity": "sha512-Epgp/EofAUeEpIdZkW60MHKvPyru1ruQJxPL+WIycnaPApuseK0Zpkrh/FwL9oIpQvIhJwV7ptOy0DWUjTlCiA==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"eslint-config-prettier": "bin/cli.js"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"eslint": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eslint-import-resolver-node": {
|
"node_modules/eslint-import-resolver-node": {
|
||||||
"version": "0.3.9",
|
"version": "0.3.9",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
|
||||||
@@ -2800,6 +2827,36 @@
|
|||||||
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9"
|
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint-plugin-prettier": {
|
||||||
|
"version": "5.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.6.tgz",
|
||||||
|
"integrity": "sha512-mUcf7QG2Tjk7H055Jk0lGBjbgDnfrvqjhXh9t2xLMSCjZVcw9Rb1V6sVNXO0th3jgeO7zllWPTNRil3JW94TnQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"prettier-linter-helpers": "^1.0.0",
|
||||||
|
"synckit": "^0.11.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.18.0 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/eslint-plugin-prettier"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/eslint": ">=8.0.0",
|
||||||
|
"eslint": ">=8.0.0",
|
||||||
|
"eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0",
|
||||||
|
"prettier": ">=3.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/eslint": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"eslint-config-prettier": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eslint-plugin-react": {
|
"node_modules/eslint-plugin-react": {
|
||||||
"version": "7.37.4",
|
"version": "7.37.4",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz",
|
||||||
@@ -2992,6 +3049,12 @@
|
|||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/fast-diff": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/fast-glob": {
|
"node_modules/fast-glob": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
|
||||||
@@ -4715,6 +4778,18 @@
|
|||||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prettier-linter-helpers": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"fast-diff": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prop-types": {
|
"node_modules/prop-types": {
|
||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
@@ -6117,6 +6192,22 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/synckit": {
|
||||||
|
"version": "0.11.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.4.tgz",
|
||||||
|
"integrity": "sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@pkgr/core": "^0.2.3",
|
||||||
|
"tslib": "^2.8.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.18.0 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://opencollective.com/synckit"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/throttle-debounce": {
|
"node_modules/throttle-debounce": {
|
||||||
"version": "5.0.2",
|
"version": "5.0.2",
|
||||||
"resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-5.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-5.0.2.tgz",
|
||||||
@@ -6300,9 +6391,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "5.8.2",
|
"version": "5.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
||||||
"integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
|
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
@@ -6312,6 +6403,28 @@
|
|||||||
"node": ">=14.17"
|
"node": ">=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/typescript-eslint": {
|
||||||
|
"version": "8.31.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.31.1.tgz",
|
||||||
|
"integrity": "sha512-j6DsEotD/fH39qKzXTQRwYYWlt7D+0HmfpOK+DVhwJOFLcdmn92hq3mBb7HlKJHbjjI/gTOqEcc9d6JfpFf/VA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@typescript-eslint/eslint-plugin": "8.31.1",
|
||||||
|
"@typescript-eslint/parser": "8.31.1",
|
||||||
|
"@typescript-eslint/utils": "8.31.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 <5.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/unbox-primitive": {
|
"node_modules/unbox-primitive": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
|
||||||
|
|||||||
+4
-1
@@ -28,9 +28,12 @@
|
|||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "15.2.4",
|
"eslint-config-next": "15.2.4",
|
||||||
|
"eslint-config-prettier": "^10.1.2",
|
||||||
|
"eslint-plugin-prettier": "^5.2.6",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"lint-staged": "^15.5.1",
|
"lint-staged": "^15.5.1",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"typescript": "^5"
|
"typescript": "^5.8.3",
|
||||||
|
"typescript-eslint": "^8.31.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,33 @@
|
|||||||
import {BotCardVO} from "@/app/home/bots/components/bot-card/BotCardVO";
|
import { BotCardVO } from '@/app/home/bots/components/bot-card/BotCardVO';
|
||||||
import styles from "./botCard.module.css";
|
import styles from './botCard.module.css';
|
||||||
|
|
||||||
export default function BotCard({
|
export default function BotCard({ botCardVO }: { botCardVO: BotCardVO }) {
|
||||||
botCardVO
|
return (
|
||||||
}: {
|
<div className={`${styles.cardContainer}`}>
|
||||||
botCardVO: BotCardVO;
|
{/* icon和基本信息 */}
|
||||||
}) {
|
<div className={`${styles.iconBasicInfoContainer}`}>
|
||||||
return (
|
{/* icon */}
|
||||||
<div className={`${styles.cardContainer}`}>
|
<div className={`${styles.icon}`}>ICO</div>
|
||||||
{/* icon和基本信息 */}
|
{/* bot基本信息 */}
|
||||||
<div className={`${styles.iconBasicInfoContainer}`}>
|
<div className={`${styles.basicInfoContainer}`}>
|
||||||
{/* icon */}
|
<div className={`${styles.basicInfoText} ${styles.bigText}`}>
|
||||||
<div className={`${styles.icon}`}>
|
{botCardVO.name}
|
||||||
ICO
|
</div>
|
||||||
</div>
|
<div className={`${styles.basicInfoText}`}>
|
||||||
{/* bot基本信息 */}
|
平台:{botCardVO.adapter}
|
||||||
<div className={`${styles.basicInfoContainer}`}>
|
</div>
|
||||||
<div className={`${styles.basicInfoText} ${styles.bigText}`}>
|
<div className={`${styles.basicInfoText}`}>
|
||||||
{botCardVO.name}
|
绑定流水线:{botCardVO.pipelineName}
|
||||||
</div>
|
</div>
|
||||||
<div className={`${styles.basicInfoText}`}>
|
</div>
|
||||||
平台:{botCardVO.adapter}
|
</div>
|
||||||
</div>
|
{/* 描述和创建时间 */}
|
||||||
<div className={`${styles.basicInfoText}`}>
|
<div className={`${styles.urlAndUpdateText}`}>
|
||||||
绑定流水线:{botCardVO.pipelineName}
|
描述:{botCardVO.description}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/* <div className={`${styles.urlAndUpdateText}`}>
|
||||||
</div>
|
|
||||||
{/* 描述和创建时间 */}
|
|
||||||
<div className={`${styles.urlAndUpdateText}`}>
|
|
||||||
描述:{botCardVO.description}
|
|
||||||
</div>
|
|
||||||
{/* <div className={`${styles.urlAndUpdateText}`}>
|
|
||||||
更新时间:{botCardVO.updateTime}
|
更新时间:{botCardVO.updateTime}
|
||||||
</div> */}
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
@@ -1,28 +1,26 @@
|
|||||||
export interface IBotCardVO {
|
export interface IBotCardVO {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
adapter: string;
|
adapter: string;
|
||||||
description: string;
|
description: string;
|
||||||
updateTime: string;
|
updateTime: string;
|
||||||
pipelineName: string;
|
pipelineName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BotCardVO implements IBotCardVO {
|
export class BotCardVO implements IBotCardVO {
|
||||||
id: string;
|
id: string;
|
||||||
adapter: string;
|
adapter: string;
|
||||||
description: string;
|
description: string;
|
||||||
name: string;
|
name: string;
|
||||||
updateTime: string;
|
updateTime: string;
|
||||||
pipelineName: string;
|
pipelineName: string;
|
||||||
|
|
||||||
|
|
||||||
constructor(props: IBotCardVO) {
|
|
||||||
this.id = props.id;
|
|
||||||
this.name = props.name;
|
|
||||||
this.adapter = props.adapter;
|
|
||||||
this.description = props.description;
|
|
||||||
this.updateTime = props.updateTime;
|
|
||||||
this.pipelineName = props.pipelineName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
constructor(props: IBotCardVO) {
|
||||||
|
this.id = props.id;
|
||||||
|
this.name = props.name;
|
||||||
|
this.adapter = props.adapter;
|
||||||
|
this.description = props.description;
|
||||||
|
this.updateTime = props.updateTime;
|
||||||
|
this.pipelineName = props.pipelineName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,24 @@
|
|||||||
import {
|
import {
|
||||||
BotFormEntity,
|
BotFormEntity,
|
||||||
IBotFormEntity
|
IBotFormEntity,
|
||||||
} from "@/app/home/bots/components/bot-form/BotFormEntity";
|
} from '@/app/home/bots/components/bot-form/BotFormEntity';
|
||||||
import { Button, Form, Input, notification, Select, Space } from "antd";
|
import { Button, Form, Input, notification, Select, Space } from 'antd';
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react';
|
||||||
import { IChooseAdapterEntity } from "@/app/home/bots/components/bot-form/ChooseAdapterEntity";
|
import { IChooseAdapterEntity } from '@/app/home/bots/components/bot-form/ChooseAdapterEntity';
|
||||||
import {
|
import {
|
||||||
DynamicFormItemConfig,
|
DynamicFormItemConfig,
|
||||||
IDynamicFormItemConfig,
|
IDynamicFormItemConfig,
|
||||||
parseDynamicFormItemType
|
parseDynamicFormItemType,
|
||||||
} from "@/app/home/components/dynamic-form/DynamicFormItemConfig";
|
} from '@/app/home/components/dynamic-form/DynamicFormItemConfig';
|
||||||
import { UUID } from "uuidjs";
|
import { UUID } from 'uuidjs';
|
||||||
import DynamicFormComponent from "@/app/home/components/dynamic-form/DynamicFormComponent";
|
import DynamicFormComponent from '@/app/home/components/dynamic-form/DynamicFormComponent';
|
||||||
import { httpClient } from "@/app/infra/http/HttpClient";
|
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||||
import { Bot } from "@/app/infra/api/api-types";
|
import { Bot } from '@/app/infra/api/api-types';
|
||||||
|
|
||||||
export default function BotForm({
|
export default function BotForm({
|
||||||
initBotId,
|
initBotId,
|
||||||
onFormSubmit,
|
onFormSubmit,
|
||||||
onFormCancel
|
onFormCancel,
|
||||||
}: {
|
}: {
|
||||||
initBotId?: string;
|
initBotId?: string;
|
||||||
onFormSubmit: (value: IBotFormEntity) => void;
|
onFormSubmit: (value: IBotFormEntity) => void;
|
||||||
@@ -55,9 +55,9 @@ export default function BotForm({
|
|||||||
rawAdapterList.adapters.map((item) => {
|
rawAdapterList.adapters.map((item) => {
|
||||||
return {
|
return {
|
||||||
label: item.label.zh_CN,
|
label: item.label.zh_CN,
|
||||||
value: item.name
|
value: item.name,
|
||||||
};
|
};
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
// 初始化适配器表单map
|
// 初始化适配器表单map
|
||||||
rawAdapterList.adapters.forEach((rawAdapter) => {
|
rawAdapterList.adapters.forEach((rawAdapter) => {
|
||||||
@@ -71,9 +71,9 @@ export default function BotForm({
|
|||||||
label: item.label,
|
label: item.label,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
required: item.required,
|
required: item.required,
|
||||||
type: parseDynamicFormItemType(item.type)
|
type: parseDynamicFormItemType(item.type),
|
||||||
})
|
}),
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
// 拉取初始化表单信息
|
// 拉取初始化表单信息
|
||||||
@@ -99,12 +99,12 @@ export default function BotForm({
|
|||||||
adapter: bot.adapter,
|
adapter: bot.adapter,
|
||||||
description: bot.description,
|
description: bot.description,
|
||||||
name: bot.name,
|
name: bot.name,
|
||||||
adapter_config: bot.adapter_config
|
adapter_config: bot.adapter_config,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAdapterSelect(adapterName: string) {
|
function handleAdapterSelect(adapterName: string) {
|
||||||
console.log("Select adapter: ", adapterName);
|
console.log('Select adapter: ', adapterName);
|
||||||
if (adapterName) {
|
if (adapterName) {
|
||||||
const dynamicFormConfigList =
|
const dynamicFormConfigList =
|
||||||
adapterNameToDynamicConfigMap.get(adapterName);
|
adapterNameToDynamicConfigMap.get(adapterName);
|
||||||
@@ -129,33 +129,33 @@ export default function BotForm({
|
|||||||
// 只有通过外层固定表单验证才会走到这里,真正的提交逻辑在这里
|
// 只有通过外层固定表单验证才会走到这里,真正的提交逻辑在这里
|
||||||
function onDynamicFormSubmit(value: object) {
|
function onDynamicFormSubmit(value: object) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
console.log("set loading", true);
|
console.log('set loading', true);
|
||||||
if (initBotId) {
|
if (initBotId) {
|
||||||
// 编辑提交
|
// 编辑提交
|
||||||
console.log("submit edit", form.getFieldsValue(), value);
|
console.log('submit edit', form.getFieldsValue(), value);
|
||||||
const updateBot: Bot = {
|
const updateBot: Bot = {
|
||||||
uuid: initBotId,
|
uuid: initBotId,
|
||||||
name: form.getFieldsValue().name,
|
name: form.getFieldsValue().name,
|
||||||
description: form.getFieldsValue().description,
|
description: form.getFieldsValue().description,
|
||||||
adapter: form.getFieldsValue().adapter,
|
adapter: form.getFieldsValue().adapter,
|
||||||
adapter_config: value
|
adapter_config: value,
|
||||||
};
|
};
|
||||||
httpClient
|
httpClient
|
||||||
.updateBot(initBotId, updateBot)
|
.updateBot(initBotId, updateBot)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
// TODO success toast
|
// TODO success toast
|
||||||
console.log("update bot success", res);
|
console.log('update bot success', res);
|
||||||
onFormSubmit(form.getFieldsValue());
|
onFormSubmit(form.getFieldsValue());
|
||||||
notification.success({
|
notification.success({
|
||||||
message: "更新成功",
|
message: '更新成功',
|
||||||
description: "机器人更新成功"
|
description: '机器人更新成功',
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
// TODO error toast
|
// TODO error toast
|
||||||
notification.error({
|
notification.error({
|
||||||
message: "更新失败",
|
message: '更新失败',
|
||||||
description: "机器人更新失败"
|
description: '机器人更新失败',
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -165,20 +165,20 @@ export default function BotForm({
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// 创建提交
|
// 创建提交
|
||||||
console.log("submit create", form.getFieldsValue(), value);
|
console.log('submit create', form.getFieldsValue(), value);
|
||||||
const newBot: Bot = {
|
const newBot: Bot = {
|
||||||
name: form.getFieldsValue().name,
|
name: form.getFieldsValue().name,
|
||||||
description: form.getFieldsValue().description,
|
description: form.getFieldsValue().description,
|
||||||
adapter: form.getFieldsValue().adapter,
|
adapter: form.getFieldsValue().adapter,
|
||||||
adapter_config: value
|
adapter_config: value,
|
||||||
};
|
};
|
||||||
httpClient
|
httpClient
|
||||||
.createBot(newBot)
|
.createBot(newBot)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
// TODO success toast
|
// TODO success toast
|
||||||
notification.success({
|
notification.success({
|
||||||
message: "创建成功",
|
message: '创建成功',
|
||||||
description: "机器人创建成功"
|
description: '机器人创建成功',
|
||||||
});
|
});
|
||||||
console.log(res);
|
console.log(res);
|
||||||
onFormSubmit(form.getFieldsValue());
|
onFormSubmit(form.getFieldsValue());
|
||||||
@@ -186,8 +186,8 @@ export default function BotForm({
|
|||||||
.catch(() => {
|
.catch(() => {
|
||||||
// TODO error toast
|
// TODO error toast
|
||||||
notification.error({
|
notification.error({
|
||||||
message: "创建失败",
|
message: '创建失败',
|
||||||
description: "机器人创建失败"
|
description: '机器人创建失败',
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -197,7 +197,7 @@ export default function BotForm({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
setShowDynamicForm(false);
|
setShowDynamicForm(false);
|
||||||
console.log("set loading", false);
|
console.log('set loading', false);
|
||||||
// TODO 刷新bot列表
|
// TODO 刷新bot列表
|
||||||
// TODO 关闭当前弹窗 Already closed @setShowDynamicForm(false)?
|
// TODO 关闭当前弹窗 Already closed @setShowDynamicForm(false)?
|
||||||
}
|
}
|
||||||
@@ -217,9 +217,9 @@ export default function BotForm({
|
|||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
>
|
>
|
||||||
<Form.Item<IBotFormEntity>
|
<Form.Item<IBotFormEntity>
|
||||||
label={"机器人名称"}
|
label={'机器人名称'}
|
||||||
name={"name"}
|
name={'name'}
|
||||||
rules={[{ required: true, message: "该项为必填项哦~" }]}
|
rules={[{ required: true, message: '该项为必填项哦~' }]}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
placeholder="为机器人取个好听的名字吧~"
|
placeholder="为机器人取个好听的名字吧~"
|
||||||
@@ -228,17 +228,17 @@ export default function BotForm({
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item<IBotFormEntity>
|
<Form.Item<IBotFormEntity>
|
||||||
label={"描述"}
|
label={'描述'}
|
||||||
name={"description"}
|
name={'description'}
|
||||||
rules={[{ required: true, message: "该项为必填项哦~" }]}
|
rules={[{ required: true, message: '该项为必填项哦~' }]}
|
||||||
>
|
>
|
||||||
<Input placeholder="简单描述一下这个机器人"></Input>
|
<Input placeholder="简单描述一下这个机器人"></Input>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item<IBotFormEntity>
|
<Form.Item<IBotFormEntity>
|
||||||
label={"平台/适配器选择"}
|
label={'平台/适配器选择'}
|
||||||
name={"adapter"}
|
name={'adapter'}
|
||||||
rules={[{ required: true, message: "该项为必填项哦~" }]}
|
rules={[{ required: true, message: '该项为必填项哦~' }]}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
style={{ width: 220 }}
|
style={{ width: 220 }}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
export interface IBotFormEntity {
|
export interface IBotFormEntity {
|
||||||
name: string,
|
name: string;
|
||||||
description: string,
|
description: string;
|
||||||
adapter: string,
|
adapter: string;
|
||||||
adapter_config: object;
|
adapter_config: object;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BotFormEntity implements IBotFormEntity {
|
export class BotFormEntity implements IBotFormEntity {
|
||||||
adapter: string;
|
adapter: string;
|
||||||
description: string;
|
description: string;
|
||||||
name: string;
|
name: string;
|
||||||
adapter_config: object;
|
adapter_config: object;
|
||||||
|
|
||||||
constructor(props: IBotFormEntity) {
|
constructor(props: IBotFormEntity) {
|
||||||
this.adapter = props.adapter;
|
this.adapter = props.adapter;
|
||||||
this.description = props.description;
|
this.description = props.description;
|
||||||
this.name = props.name;
|
this.name = props.name;
|
||||||
this.adapter_config = props.adapter_config;
|
this.adapter_config = props.adapter_config;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
export interface IChooseAdapterEntity {
|
export interface IChooseAdapterEntity {
|
||||||
label: string
|
label: string;
|
||||||
value: string
|
value: string;
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react';
|
||||||
import styles from "./botConfig.module.css";
|
import styles from './botConfig.module.css';
|
||||||
import EmptyAndCreateComponent from "@/app/home/components/empty-and-create-component/EmptyAndCreateComponent";
|
import EmptyAndCreateComponent from '@/app/home/components/empty-and-create-component/EmptyAndCreateComponent';
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from 'next/navigation';
|
||||||
import { BotCardVO } from "@/app/home/bots/components/bot-card/BotCardVO";
|
import { BotCardVO } from '@/app/home/bots/components/bot-card/BotCardVO';
|
||||||
import { Modal, notification, Spin } from "antd";
|
import { Modal, notification, Spin } from 'antd';
|
||||||
import BotForm from "@/app/home/bots/components/bot-form/BotForm";
|
import BotForm from '@/app/home/bots/components/bot-form/BotForm';
|
||||||
import BotCard from "@/app/home/bots/components/bot-card/BotCard";
|
import BotCard from '@/app/home/bots/components/bot-card/BotCard';
|
||||||
import CreateCardComponent from "@/app/infra/basic-component/create-card-component/CreateCardComponent";
|
import CreateCardComponent from '@/app/infra/basic-component/create-card-component/CreateCardComponent';
|
||||||
import { httpClient } from "@/app/infra/http/HttpClient";
|
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||||
import { Bot } from "@/app/infra/api/api-types";
|
import { Bot } from '@/app/infra/api/api-types';
|
||||||
|
|
||||||
export default function BotConfigPage() {
|
export default function BotConfigPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [pageShowRule, setPageShowRule] = useState<BotConfigPageShowRule>(
|
const [pageShowRule, setPageShowRule] = useState<BotConfigPageShowRule>(
|
||||||
BotConfigPageShowRule.NO_BOT
|
BotConfigPageShowRule.NO_BOT,
|
||||||
);
|
);
|
||||||
const [modalOpen, setModalOpen] = useState<boolean>(false);
|
const [modalOpen, setModalOpen] = useState<boolean>(false);
|
||||||
const [botList, setBotList] = useState<BotCardVO[]>([]);
|
const [botList, setBotList] = useState<BotCardVO[]>([]);
|
||||||
@@ -49,10 +49,10 @@ export default function BotConfigPage() {
|
|||||||
return new BotCardVO({
|
return new BotCardVO({
|
||||||
adapter: bot.adapter,
|
adapter: bot.adapter,
|
||||||
description: bot.description,
|
description: bot.description,
|
||||||
id: bot.uuid || "",
|
id: bot.uuid || '',
|
||||||
name: bot.name,
|
name: bot.name,
|
||||||
updateTime: bot.updated_at || "",
|
updateTime: bot.updated_at || '',
|
||||||
pipelineName: bot.use_pipeline_name || ""
|
pipelineName: bot.use_pipeline_name || '',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
if (botList.length === 0) {
|
if (botList.length === 0) {
|
||||||
@@ -63,12 +63,12 @@ export default function BotConfigPage() {
|
|||||||
setBotList(botList);
|
setBotList(botList);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error("get bot list error", err);
|
console.error('get bot list error', err);
|
||||||
// TODO HACK: need refactor to hook mode Notification, but it's not working under render
|
// TODO HACK: need refactor to hook mode Notification, but it's not working under render
|
||||||
notification.error({
|
notification.error({
|
||||||
message: "获取机器人列表失败",
|
message: '获取机器人列表失败',
|
||||||
description: err.message,
|
description: err.message,
|
||||||
placement: "bottomRight"
|
placement: 'bottomRight',
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -89,7 +89,7 @@ export default function BotConfigPage() {
|
|||||||
function selectBot(cardVO: BotCardVO) {
|
function selectBot(cardVO: BotCardVO) {
|
||||||
setIsEditForm(true);
|
setIsEditForm(true);
|
||||||
setNowSelectedCard(cardVO);
|
setNowSelectedCard(cardVO);
|
||||||
console.log("set now vo", cardVO);
|
console.log('set now vo', cardVO);
|
||||||
setModalOpen(true);
|
setModalOpen(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ export default function BotConfigPage() {
|
|||||||
<div className={styles.configPageContainer}>
|
<div className={styles.configPageContainer}>
|
||||||
<Spin spinning={isLoading} tip="加载中..." size="large">
|
<Spin spinning={isLoading} tip="加载中..." size="large">
|
||||||
<Modal
|
<Modal
|
||||||
title={isEditForm ? "编辑机器人" : "创建机器人"}
|
title={isEditForm ? '编辑机器人' : '创建机器人'}
|
||||||
centered
|
centered
|
||||||
open={modalOpen}
|
open={modalOpen}
|
||||||
onOk={() => setModalOpen(false)}
|
onOk={() => setModalOpen(false)}
|
||||||
@@ -117,20 +117,20 @@ export default function BotConfigPage() {
|
|||||||
</Modal>
|
</Modal>
|
||||||
{pageShowRule === BotConfigPageShowRule.NO_LLM && (
|
{pageShowRule === BotConfigPageShowRule.NO_LLM && (
|
||||||
<EmptyAndCreateComponent
|
<EmptyAndCreateComponent
|
||||||
title={"需要先创建大模型才能配置机器人哦~"}
|
title={'需要先创建大模型才能配置机器人哦~'}
|
||||||
subTitle={"快去创建一个吧!"}
|
subTitle={'快去创建一个吧!'}
|
||||||
buttonText={"创建大模型 GO!"}
|
buttonText={'创建大模型 GO!'}
|
||||||
onButtonClick={() => {
|
onButtonClick={() => {
|
||||||
router.push("/home/models");
|
router.push('/home/models');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{pageShowRule === BotConfigPageShowRule.NO_BOT && (
|
{pageShowRule === BotConfigPageShowRule.NO_BOT && (
|
||||||
<EmptyAndCreateComponent
|
<EmptyAndCreateComponent
|
||||||
title={"您还未配置机器人哦~"}
|
title={'您还未配置机器人哦~'}
|
||||||
subTitle={"快去创建一个吧!"}
|
subTitle={'快去创建一个吧!'}
|
||||||
buttonText={"创建机器人 +"}
|
buttonText={'创建机器人 +'}
|
||||||
onButtonClick={handleCreateBotClick}
|
onButtonClick={handleCreateBotClick}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -164,5 +164,5 @@ export default function BotConfigPage() {
|
|||||||
enum BotConfigPageShowRule {
|
enum BotConfigPageShowRule {
|
||||||
NO_LLM,
|
NO_LLM,
|
||||||
NO_BOT,
|
NO_BOT,
|
||||||
HAVE_BOT
|
HAVE_BOT,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,21 @@
|
|||||||
import {IDynamicFormItemConfig} from "@/app/home/components/dynamic-form/DynamicFormItemConfig";
|
import { IDynamicFormItemConfig } from '@/app/home/components/dynamic-form/DynamicFormItemConfig';
|
||||||
import {Form, FormInstance} from "antd";
|
import { Form, FormInstance } from 'antd';
|
||||||
import DynamicFormItemComponent from "@/app/home/components/dynamic-form/DynamicFormItemComponent";
|
import DynamicFormItemComponent from '@/app/home/components/dynamic-form/DynamicFormItemComponent';
|
||||||
|
|
||||||
export default function DynamicFormComponent({
|
export default function DynamicFormComponent({
|
||||||
form,
|
form,
|
||||||
itemConfigList,
|
itemConfigList,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
}: {
|
}: {
|
||||||
form: FormInstance<object>
|
form: FormInstance<object>;
|
||||||
itemConfigList: IDynamicFormItemConfig[]
|
itemConfigList: IDynamicFormItemConfig[];
|
||||||
onSubmit?: (val: object) => unknown
|
onSubmit?: (val: object) => unknown;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form form={form} onFinish={onSubmit} layout={'vertical'}>
|
||||||
form={form}
|
{itemConfigList.map((config) => (
|
||||||
onFinish={onSubmit}
|
<DynamicFormItemComponent key={config.id} config={config} />
|
||||||
layout={"vertical"}
|
))}
|
||||||
>
|
</Form>
|
||||||
{
|
);
|
||||||
itemConfigList.map(config =>
|
|
||||||
<DynamicFormItemComponent
|
|
||||||
key={config.id}
|
|
||||||
config={config}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</Form>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
@@ -1,38 +1,30 @@
|
|||||||
import {Form, Input, InputNumber, Select, Switch} from "antd";
|
import { Form, Input, InputNumber, Select, Switch } from 'antd';
|
||||||
import {DynamicFormItemType, IDynamicFormItemConfig} from "@/app/home/components/dynamic-form/DynamicFormItemConfig";
|
import {
|
||||||
|
DynamicFormItemType,
|
||||||
|
IDynamicFormItemConfig,
|
||||||
|
} from '@/app/home/components/dynamic-form/DynamicFormItemConfig';
|
||||||
|
|
||||||
export default function DynamicFormItemComponent({
|
export default function DynamicFormItemComponent({
|
||||||
config
|
config,
|
||||||
}: {
|
}: {
|
||||||
config: IDynamicFormItemConfig
|
config: IDynamicFormItemConfig;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={config.label.zh_CN}
|
label={config.label.zh_CN}
|
||||||
name={config.name}
|
name={config.name}
|
||||||
rules={[{required: config.required, message: "该项为必填项哦~"}]}
|
rules={[{ required: config.required, message: '该项为必填项哦~' }]}
|
||||||
initialValue={config.default}
|
initialValue={config.default}
|
||||||
>
|
>
|
||||||
{
|
{config.type === DynamicFormItemType.INT && <InputNumber />}
|
||||||
config.type === DynamicFormItemType.INT &&
|
|
||||||
<InputNumber/>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{config.type === DynamicFormItemType.STRING && <Input />}
|
||||||
config.type === DynamicFormItemType.STRING &&
|
|
||||||
<Input/>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{config.type === DynamicFormItemType.BOOLEAN && <Switch defaultChecked />}
|
||||||
config.type === DynamicFormItemType.BOOLEAN &&
|
|
||||||
<Switch defaultChecked/>
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
config.type === DynamicFormItemType.STRING_ARRAY &&
|
|
||||||
<Select options={[]}/>
|
|
||||||
}
|
|
||||||
</Form.Item>
|
|
||||||
)
|
|
||||||
|
|
||||||
|
{config.type === DynamicFormItemType.STRING_ARRAY && (
|
||||||
|
<Select options={[]} />
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -1,51 +1,54 @@
|
|||||||
export interface IDynamicFormItemConfig {
|
export interface IDynamicFormItemConfig {
|
||||||
id: string;
|
id: string;
|
||||||
default: string | number | boolean | Array<unknown>;
|
default: string | number | boolean | Array<unknown>;
|
||||||
label: IDynamicFormItemLabel;
|
label: IDynamicFormItemLabel;
|
||||||
name: string;
|
name: string;
|
||||||
required: boolean;
|
required: boolean;
|
||||||
type: DynamicFormItemType
|
type: DynamicFormItemType;
|
||||||
description?: IDynamicFormItemLabel;
|
description?: IDynamicFormItemLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DynamicFormItemConfig implements IDynamicFormItemConfig {
|
export class DynamicFormItemConfig implements IDynamicFormItemConfig {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
default: string | number | boolean | Array<unknown>;
|
default: string | number | boolean | Array<unknown>;
|
||||||
label: IDynamicFormItemLabel;
|
label: IDynamicFormItemLabel;
|
||||||
required: boolean;
|
required: boolean;
|
||||||
type: DynamicFormItemType;
|
type: DynamicFormItemType;
|
||||||
description?: IDynamicFormItemLabel;
|
description?: IDynamicFormItemLabel;
|
||||||
|
|
||||||
constructor(params: IDynamicFormItemConfig) {
|
|
||||||
this.id = params.id;
|
|
||||||
this.name = params.name;
|
|
||||||
this.default = params.default;
|
|
||||||
this.label = params.label;
|
|
||||||
this.required = params.required;
|
|
||||||
this.type = params.type;
|
|
||||||
this.description = params.description;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
constructor(params: IDynamicFormItemConfig) {
|
||||||
|
this.id = params.id;
|
||||||
|
this.name = params.name;
|
||||||
|
this.default = params.default;
|
||||||
|
this.label = params.label;
|
||||||
|
this.required = params.required;
|
||||||
|
this.type = params.type;
|
||||||
|
this.description = params.description;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDynamicFormItemLabel {
|
export interface IDynamicFormItemLabel {
|
||||||
en_US: string,
|
en_US: string;
|
||||||
zh_CN: string,
|
zh_CN: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DynamicFormItemType {
|
export enum DynamicFormItemType {
|
||||||
INT = "integer",
|
INT = 'integer',
|
||||||
STRING = "string",
|
STRING = 'string',
|
||||||
BOOLEAN = "boolean",
|
BOOLEAN = 'boolean',
|
||||||
STRING_ARRAY = "array[string]",
|
STRING_ARRAY = 'array[string]',
|
||||||
UNKNOWN = "unknown",
|
UNKNOWN = 'unknown',
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isDynamicFormItemType(value: string): value is DynamicFormItemType {
|
export function isDynamicFormItemType(
|
||||||
return Object.values(DynamicFormItemType).includes(value as DynamicFormItemType);
|
value: string,
|
||||||
|
): value is DynamicFormItemType {
|
||||||
|
return Object.values(DynamicFormItemType).includes(
|
||||||
|
value as DynamicFormItemType,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseDynamicFormItemType(value: string): DynamicFormItemType {
|
export function parseDynamicFormItemType(value: string): DynamicFormItemType {
|
||||||
return isDynamicFormItemType(value) ? value : DynamicFormItemType.UNKNOWN;
|
return isDynamicFormItemType(value) ? value : DynamicFormItemType.UNKNOWN;
|
||||||
}
|
}
|
||||||
@@ -1,41 +1,41 @@
|
|||||||
import {
|
import {
|
||||||
DynamicFormItemConfig,
|
DynamicFormItemConfig,
|
||||||
DynamicFormItemType,
|
DynamicFormItemType,
|
||||||
IDynamicFormItemConfig
|
IDynamicFormItemConfig,
|
||||||
} from "@/app/home/components/dynamic-form/DynamicFormItemConfig";
|
} from '@/app/home/components/dynamic-form/DynamicFormItemConfig';
|
||||||
|
|
||||||
export const testDynamicConfigList: IDynamicFormItemConfig[] = [
|
export const testDynamicConfigList: IDynamicFormItemConfig[] = [
|
||||||
new DynamicFormItemConfig({
|
new DynamicFormItemConfig({
|
||||||
default: "",
|
default: '',
|
||||||
id: "111",
|
id: '111',
|
||||||
label: {
|
label: {
|
||||||
zh_CN: "测试字段string",
|
zh_CN: '测试字段string',
|
||||||
en_US: "eng test"
|
en_US: 'eng test',
|
||||||
},
|
},
|
||||||
name: "string_test",
|
name: 'string_test',
|
||||||
required: false,
|
required: false,
|
||||||
type: DynamicFormItemType.STRING
|
type: DynamicFormItemType.STRING,
|
||||||
}),
|
}),
|
||||||
new DynamicFormItemConfig({
|
new DynamicFormItemConfig({
|
||||||
default: "",
|
default: '',
|
||||||
id: "222",
|
id: '222',
|
||||||
label: {
|
label: {
|
||||||
zh_CN: "测试字段int",
|
zh_CN: '测试字段int',
|
||||||
en_US: "int eng test"
|
en_US: 'int eng test',
|
||||||
},
|
},
|
||||||
name: "int_test",
|
name: 'int_test',
|
||||||
required: true,
|
required: true,
|
||||||
type: DynamicFormItemType.INT
|
type: DynamicFormItemType.INT,
|
||||||
}),
|
}),
|
||||||
new DynamicFormItemConfig({
|
new DynamicFormItemConfig({
|
||||||
default: "",
|
default: '',
|
||||||
id: "333",
|
id: '333',
|
||||||
label: {
|
label: {
|
||||||
zh_CN: "测试字段boolean",
|
zh_CN: '测试字段boolean',
|
||||||
en_US: "boolean eng test"
|
en_US: 'boolean eng test',
|
||||||
},
|
},
|
||||||
name: "boolean_test",
|
name: 'boolean_test',
|
||||||
required: false,
|
required: false,
|
||||||
type: DynamicFormItemType.BOOLEAN
|
type: DynamicFormItemType.BOOLEAN,
|
||||||
}),
|
}),
|
||||||
]
|
];
|
||||||
|
|||||||
+22
-30
@@ -1,35 +1,27 @@
|
|||||||
import styles from "./emptyAndCreate.module.css";
|
import styles from './emptyAndCreate.module.css';
|
||||||
|
|
||||||
export default function EmptyAndCreateComponent({
|
export default function EmptyAndCreateComponent({
|
||||||
title,
|
title,
|
||||||
subTitle,
|
subTitle,
|
||||||
buttonText,
|
buttonText,
|
||||||
onButtonClick,
|
onButtonClick,
|
||||||
}: {
|
}: {
|
||||||
title: string,
|
title: string;
|
||||||
subTitle: string,
|
subTitle: string;
|
||||||
buttonText: string,
|
buttonText: string;
|
||||||
onButtonClick: () => void,
|
onButtonClick: () => void;
|
||||||
}) {
|
}) {
|
||||||
|
return (
|
||||||
return (
|
<div className={`${styles.emptyPageContainer}`}>
|
||||||
<div className={`${styles.emptyPageContainer}`}>
|
<div className={`${styles.emptyContainer}`}>
|
||||||
<div className={`${styles.emptyContainer}`}>
|
<div className={`${styles.emptyInfoContainer}`}>
|
||||||
<div className={`${styles.emptyInfoContainer}`}>
|
<div className={`${styles.emptyInfoText}`}>{title}</div>
|
||||||
<div className={`${styles.emptyInfoText}`}>
|
<div className={`${styles.emptyInfoSubText}`}>{subTitle}</div>
|
||||||
{title}
|
|
||||||
</div>
|
|
||||||
<div className={`${styles.emptyInfoSubText}`}>
|
|
||||||
{subTitle}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={`${styles.emptyCreateButton}`}
|
|
||||||
onClick={onButtonClick}
|
|
||||||
>
|
|
||||||
{buttonText}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
<div className={`${styles.emptyCreateButton}`} onClick={onButtonClick}>
|
||||||
|
{buttonText}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import styles from "./HomeSidebar.module.css";
|
import styles from './HomeSidebar.module.css';
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
SidebarChild,
|
SidebarChild,
|
||||||
SidebarChildVO
|
SidebarChildVO,
|
||||||
} from "@/app/home/components/home-sidebar/HomeSidebarChild";
|
} from '@/app/home/components/home-sidebar/HomeSidebarChild';
|
||||||
import { useRouter, usePathname } from "next/navigation";
|
import { useRouter, usePathname } from 'next/navigation';
|
||||||
import { sidebarConfigList } from "@/app/home/components/home-sidebar/sidbarConfigList";
|
import { sidebarConfigList } from '@/app/home/components/home-sidebar/sidbarConfigList';
|
||||||
|
|
||||||
// TODO 侧边导航栏要加动画
|
// TODO 侧边导航栏要加动画
|
||||||
export default function HomeSidebar({
|
export default function HomeSidebar({
|
||||||
onSelectedChangeAction
|
onSelectedChangeAction,
|
||||||
}: {
|
}: {
|
||||||
onSelectedChangeAction: (sidebarChild: SidebarChildVO) => void;
|
onSelectedChangeAction: (sidebarChild: SidebarChildVO) => void;
|
||||||
}) {
|
}) {
|
||||||
@@ -24,13 +24,13 @@ export default function HomeSidebar({
|
|||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
||||||
const [selectedChild, setSelectedChild] = useState<SidebarChildVO>(
|
const [selectedChild, setSelectedChild] = useState<SidebarChildVO>(
|
||||||
sidebarConfigList[0]
|
sidebarConfigList[0],
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("HomeSidebar挂载完成");
|
console.log('HomeSidebar挂载完成');
|
||||||
initSelect();
|
initSelect();
|
||||||
return () => console.log("HomeSidebar卸载");
|
return () => console.log('HomeSidebar卸载');
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -52,14 +52,14 @@ export default function HomeSidebar({
|
|||||||
function handleRouteChange(pathname: string) {
|
function handleRouteChange(pathname: string) {
|
||||||
// TODO 这段逻辑并不好,未来router封装好后改掉
|
// TODO 这段逻辑并不好,未来router封装好后改掉
|
||||||
// 判断在home下,并且路由更改的是自己的路由子组件则更新UI
|
// 判断在home下,并且路由更改的是自己的路由子组件则更新UI
|
||||||
const routeList = pathname.split("/");
|
const routeList = pathname.split('/');
|
||||||
if (
|
if (
|
||||||
routeList[1] === "home" &&
|
routeList[1] === 'home' &&
|
||||||
sidebarConfigList.find((childConfig) => childConfig.route === pathname)
|
sidebarConfigList.find((childConfig) => childConfig.route === pathname)
|
||||||
) {
|
) {
|
||||||
console.log("find success");
|
console.log('find success');
|
||||||
const routeSelectChild = sidebarConfigList.find(
|
const routeSelectChild = sidebarConfigList.find(
|
||||||
(childConfig) => childConfig.route === pathname
|
(childConfig) => childConfig.route === pathname,
|
||||||
);
|
);
|
||||||
if (routeSelectChild) {
|
if (routeSelectChild) {
|
||||||
setSelectedChild(routeSelectChild);
|
setSelectedChild(routeSelectChild);
|
||||||
@@ -67,42 +67,34 @@ export default function HomeSidebar({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
return (
|
<div className={`${styles.sidebarContainer}`}>
|
||||||
<div className={`${styles.sidebarContainer}`}>
|
{/* LangBot、ICON区域 */}
|
||||||
{/* LangBot、ICON区域 */}
|
<div className={`${styles.langbotIconContainer}`}>
|
||||||
<div className={`${styles.langbotIconContainer}`}>
|
{/* icon */}
|
||||||
{/* icon */}
|
<div className={`${styles.langbotIcon}`}>L</div>
|
||||||
<div className={`${styles.langbotIcon}`}>
|
<div className={`${styles.langbotText}`}>Langbot</div>
|
||||||
L
|
</div>
|
||||||
</div>
|
{/* 菜单列表,后期可升级成配置驱动 */}
|
||||||
<div className={`${styles.langbotText}`}>
|
<div>
|
||||||
Langbot
|
{sidebarConfigList.map((config) => {
|
||||||
</div>
|
return (
|
||||||
|
<div
|
||||||
|
key={config.id}
|
||||||
|
onClick={() => {
|
||||||
|
console.log('click:', config.id);
|
||||||
|
handleChildClick(config);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SidebarChild
|
||||||
|
isSelected={selectedChild.id === config.id}
|
||||||
|
icon={config.icon}
|
||||||
|
name={config.name}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/* 菜单列表,后期可升级成配置驱动 */}
|
);
|
||||||
<div>
|
})}
|
||||||
{
|
</div>
|
||||||
sidebarConfigList.map(config => {
|
</div>
|
||||||
return (
|
);
|
||||||
<div
|
|
||||||
key={config.id}
|
|
||||||
onClick={() => {
|
|
||||||
console.log('click:', config.id)
|
|
||||||
handleChildClick(config)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SidebarChild
|
|
||||||
isSelected={selectedChild.id === config.id}
|
|
||||||
icon={config.icon}
|
|
||||||
name={config.name}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import styles from "./HomeSidebar.module.css";
|
import styles from './HomeSidebar.module.css';
|
||||||
|
|
||||||
export interface ISidebarChildVO {
|
export interface ISidebarChildVO {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -24,7 +24,7 @@ export class SidebarChildVO {
|
|||||||
export function SidebarChild({
|
export function SidebarChild({
|
||||||
icon,
|
icon,
|
||||||
name,
|
name,
|
||||||
isSelected
|
isSelected,
|
||||||
}: {
|
}: {
|
||||||
icon: string;
|
icon: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
import {SidebarChildVO} from "@/app/home/components/home-sidebar/HomeSidebarChild";
|
import { SidebarChildVO } from '@/app/home/components/home-sidebar/HomeSidebarChild';
|
||||||
|
|
||||||
export const sidebarConfigList = [
|
export const sidebarConfigList = [
|
||||||
new SidebarChildVO({
|
new SidebarChildVO({
|
||||||
id: "models",
|
id: 'models',
|
||||||
name: "模型配置",
|
name: '模型配置',
|
||||||
icon: "",
|
icon: '',
|
||||||
route: "/home/models",
|
route: '/home/models',
|
||||||
}),
|
}),
|
||||||
new SidebarChildVO({
|
new SidebarChildVO({
|
||||||
id: "bots",
|
id: 'bots',
|
||||||
name: "机器人",
|
name: '机器人',
|
||||||
icon: "",
|
icon: '',
|
||||||
route: "/home/bots",
|
route: '/home/bots',
|
||||||
}),
|
}),
|
||||||
new SidebarChildVO({
|
new SidebarChildVO({
|
||||||
id: "pipelines",
|
id: 'pipelines',
|
||||||
name: "流水线",
|
name: '流水线',
|
||||||
icon: "",
|
icon: '',
|
||||||
route: "/home/pipelines",
|
route: '/home/pipelines',
|
||||||
}),
|
}),
|
||||||
new SidebarChildVO({
|
new SidebarChildVO({
|
||||||
id: "plugins",
|
id: 'plugins',
|
||||||
name: "插件管理",
|
name: '插件管理',
|
||||||
icon: "",
|
icon: '',
|
||||||
route: "/home/plugins",
|
route: '/home/plugins',
|
||||||
}),
|
}),
|
||||||
]
|
];
|
||||||
|
|||||||
@@ -1,16 +1,9 @@
|
|||||||
import styles from "./HomeTittleBar.module.css"
|
import styles from './HomeTittleBar.module.css';
|
||||||
|
|
||||||
|
export default function HomeTitleBar({ title }: { title: string }) {
|
||||||
export default function HomeTitleBar({
|
return (
|
||||||
title,
|
<div className={`${styles.titleBarContainer}`}>
|
||||||
}: {
|
<div className={`${styles.titleText}`}>{title}</div>
|
||||||
title: string
|
</div>
|
||||||
}) {
|
);
|
||||||
return (
|
|
||||||
<div className={`${styles.titleBarContainer}`}>
|
|
||||||
<div
|
|
||||||
className={`${styles.titleText}`}
|
|
||||||
>{title}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
+12
-16
@@ -1,35 +1,31 @@
|
|||||||
"use client"
|
'use client';
|
||||||
|
|
||||||
import '@ant-design/v5-patch-for-react-19';
|
import '@ant-design/v5-patch-for-react-19';
|
||||||
import styles from "./layout.module.css"
|
import styles from './layout.module.css';
|
||||||
import HomeSidebar from "@/app/home/components/home-sidebar/HomeSidebar";
|
import HomeSidebar from '@/app/home/components/home-sidebar/HomeSidebar';
|
||||||
import HomeTitleBar from "@/app/home/components/home-titlebar/HomeTitleBar";
|
import HomeTitleBar from '@/app/home/components/home-titlebar/HomeTitleBar';
|
||||||
import React, { useState } from "react";
|
import React, { useState } from 'react';
|
||||||
import { SidebarChildVO } from "@/app/home/components/home-sidebar/HomeSidebarChild";
|
import { SidebarChildVO } from '@/app/home/components/home-sidebar/HomeSidebarChild';
|
||||||
import { useRouter } from 'next/navigation';
|
|
||||||
import { Layout } from 'antd';
|
import { Layout } from 'antd';
|
||||||
|
|
||||||
const { Sider, Content } = Layout;
|
const { Sider, Content } = Layout;
|
||||||
|
|
||||||
export default function HomeLayout({
|
export default function HomeLayout({
|
||||||
children
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
const router = useRouter();
|
const [title, setTitle] = useState<string>('');
|
||||||
const [title, setTitle] = useState<string>("")
|
|
||||||
const onSelectedChangeAction = (child: SidebarChildVO) => {
|
const onSelectedChangeAction = (child: SidebarChildVO) => {
|
||||||
setTitle(child.name)
|
setTitle(child.name);
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout className={styles.homeLayoutContainer}>
|
<Layout className={styles.homeLayoutContainer}>
|
||||||
{/* homeLayoutContainer 是整个容器的入口,使用 flex 的左右布局 */}
|
{/* homeLayoutContainer 是整个容器的入口,使用 flex 的左右布局 */}
|
||||||
|
|
||||||
<Sider className="left">
|
<Sider className="left">
|
||||||
<HomeSidebar
|
<HomeSidebar onSelectedChangeAction={onSelectedChangeAction} />
|
||||||
onSelectedChangeAction={onSelectedChangeAction}
|
|
||||||
/>
|
|
||||||
{/* HomeSidebar 为侧边栏 */}
|
{/* HomeSidebar 为侧边栏 */}
|
||||||
</Sider>
|
</Sider>
|
||||||
|
|
||||||
@@ -44,5 +40,5 @@ export default function HomeLayout({
|
|||||||
</Content>
|
</Content>
|
||||||
</Layout>
|
</Layout>
|
||||||
</Layout>
|
</Layout>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+725
-722
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
|||||||
export interface ICreateLLMField {
|
export interface ICreateLLMField {
|
||||||
name: string;
|
name: string;
|
||||||
model_provider: string;
|
model_provider: string;
|
||||||
url: string;
|
url: string;
|
||||||
api_key: string;
|
api_key: string;
|
||||||
abilities: string[];
|
abilities: string[];
|
||||||
extra_args: string[];
|
extra_args: string[];
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,25 @@
|
|||||||
import styles from "../../LLMConfig.module.css"
|
import styles from '../../LLMConfig.module.css';
|
||||||
import {LLMCardVO} from "@/app/home/models/component/llm-card/LLMCardVO";
|
import { LLMCardVO } from '@/app/home/models/component/llm-card/LLMCardVO';
|
||||||
|
|
||||||
export default function LLMCard({
|
export default function LLMCard({ cardVO }: { cardVO: LLMCardVO }) {
|
||||||
cardVO
|
return (
|
||||||
}: {
|
<div className={`${styles.cardContainer}`}>
|
||||||
cardVO: LLMCardVO
|
{/* icon和基本信息 */}
|
||||||
}) {
|
<div className={`${styles.iconBasicInfoContainer}`}>
|
||||||
return (
|
{/* icon */}
|
||||||
<div className={`${styles.cardContainer}`}>
|
<div className={`${styles.icon}`}>ICO</div>
|
||||||
{/* icon和基本信息 */}
|
{/* bot基本信息 */}
|
||||||
<div className={`${styles.iconBasicInfoContainer}`}>
|
<div className={`${styles.basicInfoContainer}`}>
|
||||||
{/* icon */}
|
<div className={`${styles.basicInfoText} ${styles.bigText}`}>
|
||||||
<div className={`${styles.icon}`}>
|
{cardVO.name}
|
||||||
ICO
|
</div>
|
||||||
</div>
|
<div className={`${styles.basicInfoText}`}>
|
||||||
{/* bot基本信息 */}
|
厂商:{cardVO.company}
|
||||||
<div className={`${styles.basicInfoContainer}`}>
|
</div>
|
||||||
<div className={`${styles.basicInfoText} ${styles.bigText}`}>
|
|
||||||
{cardVO.name}
|
|
||||||
</div>
|
|
||||||
<div className={`${styles.basicInfoText}`}>
|
|
||||||
厂商:{cardVO.company}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* URL和创建时间 */}
|
|
||||||
<div className={`${styles.urlAndUpdateText}`}>
|
|
||||||
URL:{cardVO.URL}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
</div>
|
||||||
|
{/* URL和创建时间 */}
|
||||||
|
<div className={`${styles.urlAndUpdateText}`}>URL:{cardVO.URL}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,20 @@
|
|||||||
export interface ILLMCardVO {
|
export interface ILLMCardVO {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
company: string;
|
company: string;
|
||||||
URL: string;
|
URL: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LLMCardVO implements ILLMCardVO {
|
export class LLMCardVO implements ILLMCardVO {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
company: string;
|
company: string;
|
||||||
URL: string;
|
URL: string;
|
||||||
|
|
||||||
constructor(props: ILLMCardVO) {
|
|
||||||
this.id = props.id;
|
|
||||||
this.name = props.name;
|
|
||||||
this.company = props.company;
|
|
||||||
this.URL = props.URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
constructor(props: ILLMCardVO) {
|
||||||
|
this.id = props.id;
|
||||||
|
this.name = props.name;
|
||||||
|
this.company = props.company;
|
||||||
|
this.URL = props.URL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
export interface IChooseRequesterEntity {
|
export interface IChooseRequesterEntity {
|
||||||
label: string
|
label: string;
|
||||||
value: string
|
value: string;
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
import styles from "@/app/home/models/LLMConfig.module.css";
|
import styles from '@/app/home/models/LLMConfig.module.css';
|
||||||
import { Button, Form, Input, Select, SelectProps, Space, Modal } from "antd";
|
import { Button, Form, Input, Select, SelectProps, Space, Modal } from 'antd';
|
||||||
import { ICreateLLMField } from "@/app/home/models/ICreateLLMField";
|
import { ICreateLLMField } from '@/app/home/models/ICreateLLMField';
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react';
|
||||||
import { IChooseRequesterEntity } from "@/app/home/models/component/llm-form/ChooseAdapterEntity";
|
import { IChooseRequesterEntity } from '@/app/home/models/component/llm-form/ChooseAdapterEntity';
|
||||||
import { httpClient } from "@/app/infra/http/HttpClient";
|
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||||
import { LLMModel } from "@/app/infra/api/api-types";
|
import { LLMModel } from '@/app/infra/api/api-types';
|
||||||
import { UUID } from "uuidjs";
|
import { UUID } from 'uuidjs';
|
||||||
|
|
||||||
export default function LLMForm({
|
export default function LLMForm({
|
||||||
editMode,
|
editMode,
|
||||||
initLLMId,
|
initLLMId,
|
||||||
onFormSubmit,
|
onFormSubmit,
|
||||||
onFormCancel,
|
onFormCancel,
|
||||||
onLLMDeleted
|
onLLMDeleted,
|
||||||
}: {
|
}: {
|
||||||
editMode: boolean;
|
editMode: boolean;
|
||||||
initLLMId?: string;
|
initLLMId?: string;
|
||||||
@@ -21,18 +21,18 @@ export default function LLMForm({
|
|||||||
onLLMDeleted: () => void;
|
onLLMDeleted: () => void;
|
||||||
}) {
|
}) {
|
||||||
const [form] = Form.useForm<ICreateLLMField>();
|
const [form] = Form.useForm<ICreateLLMField>();
|
||||||
const extraOptions: SelectProps["options"] = [];
|
const extraOptions: SelectProps['options'] = [];
|
||||||
const [initValue] = useState<ICreateLLMField>();
|
const [initValue] = useState<ICreateLLMField>();
|
||||||
const [showDeleteConfirmModal, setShowDeleteConfirmModal] = useState(false);
|
const [showDeleteConfirmModal, setShowDeleteConfirmModal] = useState(false);
|
||||||
const abilityOptions: SelectProps["options"] = [
|
const abilityOptions: SelectProps['options'] = [
|
||||||
{
|
{
|
||||||
label: "函数调用",
|
label: '函数调用',
|
||||||
value: "func_call"
|
value: 'func_call',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "图像识别",
|
label: '图像识别',
|
||||||
value: "vision"
|
value: 'vision',
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
const [requesterNameList, setRequesterNameList] = useState<
|
const [requesterNameList, setRequesterNameList] = useState<
|
||||||
IChooseRequesterEntity[]
|
IChooseRequesterEntity[]
|
||||||
@@ -56,9 +56,9 @@ export default function LLMForm({
|
|||||||
requesterNameList.requesters.map((item) => {
|
requesterNameList.requesters.map((item) => {
|
||||||
return {
|
return {
|
||||||
label: item.label.zh_CN,
|
label: item.label.zh_CN,
|
||||||
value: item.name
|
value: item.name,
|
||||||
};
|
};
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ export default function LLMForm({
|
|||||||
url: llmModel.model.requester_config?.base_url,
|
url: llmModel.model.requester_config?.base_url,
|
||||||
api_key: llmModel.model.api_keys[0],
|
api_key: llmModel.model.api_keys[0],
|
||||||
abilities: llmModel.model.abilities,
|
abilities: llmModel.model.abilities,
|
||||||
extra_args: fakeExtraArgs
|
extra_args: fakeExtraArgs,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,19 +110,19 @@ export default function LLMForm({
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
function onCreateLLM(value: ICreateLLMField) {
|
function onCreateLLM(value: ICreateLLMField) {
|
||||||
console.log("create llm", value);
|
console.log('create llm', value);
|
||||||
const requestParam: LLMModel = {
|
const requestParam: LLMModel = {
|
||||||
uuid: UUID.generate(),
|
uuid: UUID.generate(),
|
||||||
name: value.name,
|
name: value.name,
|
||||||
description: "",
|
description: '',
|
||||||
requester: value.model_provider,
|
requester: value.model_provider,
|
||||||
requester_config: {
|
requester_config: {
|
||||||
base_url: value.url,
|
base_url: value.url,
|
||||||
timeout: 120
|
timeout: 120,
|
||||||
},
|
},
|
||||||
extra_args: value.extra_args,
|
extra_args: value.extra_args,
|
||||||
api_keys: [value.api_key],
|
api_keys: [value.api_key],
|
||||||
abilities: value.abilities
|
abilities: value.abilities,
|
||||||
// created_at: 'Sun Apr 27 2025 21:56:35 GMT+0800',
|
// created_at: 'Sun Apr 27 2025 21:56:35 GMT+0800',
|
||||||
// updated_at: 'Sun Apr 27 2025 21:56:35 GMT+0800',
|
// updated_at: 'Sun Apr 27 2025 21:56:35 GMT+0800',
|
||||||
};
|
};
|
||||||
@@ -145,15 +145,15 @@ export default function LLMForm({
|
|||||||
<div className={styles.modalContainer}>
|
<div className={styles.modalContainer}>
|
||||||
<Modal
|
<Modal
|
||||||
open={showDeleteConfirmModal}
|
open={showDeleteConfirmModal}
|
||||||
title={"删除确认"}
|
title={'删除确认'}
|
||||||
onCancel={() => setShowDeleteConfirmModal(false)}
|
onCancel={() => setShowDeleteConfirmModal(false)}
|
||||||
footer={
|
footer={
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
width: "170px",
|
width: '170px',
|
||||||
display: "flex",
|
display: 'flex',
|
||||||
flexDirection: "row",
|
flexDirection: 'row',
|
||||||
justifyContent: "space-between"
|
justifyContent: 'space-between',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
@@ -183,27 +183,27 @@ export default function LLMForm({
|
|||||||
wrapperCol={{ span: 14 }}
|
wrapperCol={{ span: 14 }}
|
||||||
layout="horizontal"
|
layout="horizontal"
|
||||||
initialValues={{
|
initialValues={{
|
||||||
...initValue
|
...initValue,
|
||||||
}}
|
}}
|
||||||
onFinish={handleFormSubmit}
|
onFinish={handleFormSubmit}
|
||||||
clearOnDestroy={true}
|
clearOnDestroy={true}
|
||||||
disabled={editMode}
|
disabled={editMode}
|
||||||
>
|
>
|
||||||
<Form.Item<ICreateLLMField>
|
<Form.Item<ICreateLLMField>
|
||||||
label={"模型名称"}
|
label={'模型名称'}
|
||||||
name={"name"}
|
name={'name'}
|
||||||
rules={[{ required: true, message: "该项为必填项哦~" }]}
|
rules={[{ required: true, message: '该项为必填项哦~' }]}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
placeholder={"为自己的大模型取个好听的名字~"}
|
placeholder={'为自己的大模型取个好听的名字~'}
|
||||||
style={{ width: 260 }}
|
style={{ width: 260 }}
|
||||||
></Input>
|
></Input>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item<ICreateLLMField>
|
<Form.Item<ICreateLLMField>
|
||||||
label={"模型供应商"}
|
label={'模型供应商'}
|
||||||
name={"model_provider"}
|
name={'model_provider'}
|
||||||
rules={[{ required: true, message: "该项为必填项哦~" }]}
|
rules={[{ required: true, message: '该项为必填项哦~' }]}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
style={{ width: 120 }}
|
style={{ width: 120 }}
|
||||||
@@ -213,9 +213,9 @@ export default function LLMForm({
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item<ICreateLLMField>
|
<Form.Item<ICreateLLMField>
|
||||||
label={"请求URL"}
|
label={'请求URL'}
|
||||||
name={"url"}
|
name={'url'}
|
||||||
rules={[{ required: true, message: "该项为必填项哦~" }]}
|
rules={[{ required: true, message: '该项为必填项哦~' }]}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
placeholder="请求地址,一般是API提供商提供的URL"
|
placeholder="请求地址,一般是API提供商提供的URL"
|
||||||
@@ -224,14 +224,14 @@ export default function LLMForm({
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item<ICreateLLMField>
|
<Form.Item<ICreateLLMField>
|
||||||
label={"API Key"}
|
label={'API Key'}
|
||||||
name={"api_key"}
|
name={'api_key'}
|
||||||
rules={[{ required: true, message: "该项为必填项哦~" }]}
|
rules={[{ required: true, message: '该项为必填项哦~' }]}
|
||||||
>
|
>
|
||||||
<Input placeholder="你的API Key" style={{ width: 500 }}></Input>
|
<Input placeholder="你的API Key" style={{ width: 500 }}></Input>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item<ICreateLLMField> label={"开启能力"} name={"abilities"}>
|
<Form.Item<ICreateLLMField> label={'开启能力'} name={'abilities'}>
|
||||||
<Select
|
<Select
|
||||||
mode="tags"
|
mode="tags"
|
||||||
style={{ width: 500 }}
|
style={{ width: 500 }}
|
||||||
@@ -241,7 +241,7 @@ export default function LLMForm({
|
|||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item<ICreateLLMField> label={"其他参数"} name={"extra_args"}>
|
<Form.Item<ICreateLLMField> label={'其他参数'} name={'extra_args'}>
|
||||||
<Select
|
<Select
|
||||||
mode="tags"
|
mode="tags"
|
||||||
style={{ width: 500 }}
|
style={{ width: 500 }}
|
||||||
|
|||||||
+114
-107
@@ -1,116 +1,123 @@
|
|||||||
"use client"
|
'use client';
|
||||||
|
|
||||||
import {useState, useEffect} from "react";
|
import { useState, useEffect } from 'react';
|
||||||
import {LLMCardVO} from "@/app/home/models/component/llm-card/LLMCardVO";
|
import { LLMCardVO } from '@/app/home/models/component/llm-card/LLMCardVO';
|
||||||
import styles from "./LLMConfig.module.css"
|
import styles from './LLMConfig.module.css';
|
||||||
import EmptyAndCreateComponent from "@/app/home/components/empty-and-create-component/EmptyAndCreateComponent";
|
import EmptyAndCreateComponent from '@/app/home/components/empty-and-create-component/EmptyAndCreateComponent';
|
||||||
import {Modal} from "antd";
|
import { Modal } from 'antd';
|
||||||
import LLMCard from "@/app/home/models/component/llm-card/LLMCard";
|
import LLMCard from '@/app/home/models/component/llm-card/LLMCard';
|
||||||
import LLMForm from "@/app/home/models/component/llm-form/LLMForm";
|
import LLMForm from '@/app/home/models/component/llm-form/LLMForm';
|
||||||
import CreateCardComponent from "@/app/infra/basic-component/create-card-component/CreateCardComponent";
|
import CreateCardComponent from '@/app/infra/basic-component/create-card-component/CreateCardComponent';
|
||||||
import { httpClient } from "@/app/infra/http/HttpClient";
|
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||||
import { LLMModel } from "@/app/infra/api/api-types";
|
import { LLMModel } from '@/app/infra/api/api-types';
|
||||||
|
|
||||||
export default function LLMConfigPage() {
|
export default function LLMConfigPage() {
|
||||||
const [cardList, setCardList] = useState<LLMCardVO[]>([])
|
const [cardList, setCardList] = useState<LLMCardVO[]>([]);
|
||||||
const [modalOpen, setModalOpen] = useState<boolean>(false);
|
const [modalOpen, setModalOpen] = useState<boolean>(false);
|
||||||
const [isEditForm, setIsEditForm] = useState(false)
|
const [isEditForm, setIsEditForm] = useState(false);
|
||||||
const [nowSelectedLLM, setNowSelectedLLM] = useState<LLMCardVO | null>(null)
|
const [nowSelectedLLM, setNowSelectedLLM] = useState<LLMCardVO | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getLLMModelList()
|
getLLMModelList();
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
function getLLMModelList() {
|
function getLLMModelList() {
|
||||||
httpClient.getProviderLLMModels().then((resp) => {
|
httpClient
|
||||||
const llmModelList: LLMCardVO[] = resp.models.map((model: LLMModel) => {
|
.getProviderLLMModels()
|
||||||
console.log("model", model)
|
.then((resp) => {
|
||||||
return new LLMCardVO({
|
const llmModelList: LLMCardVO[] = resp.models.map((model: LLMModel) => {
|
||||||
id: model.uuid,
|
console.log('model', model);
|
||||||
name: model.name,
|
return new LLMCardVO({
|
||||||
company: model.requester,
|
id: model.uuid,
|
||||||
URL: model.requester_config?.base_url,
|
name: model.name,
|
||||||
})
|
company: model.requester,
|
||||||
})
|
URL: model.requester_config?.base_url,
|
||||||
console.log("get llmModelList", llmModelList)
|
});
|
||||||
setCardList(llmModelList)
|
});
|
||||||
}).catch((err) => {
|
console.log('get llmModelList', llmModelList);
|
||||||
// TODO error toast
|
setCardList(llmModelList);
|
||||||
console.error("get LLM model list error", err)
|
})
|
||||||
})
|
.catch((err) => {
|
||||||
}
|
// TODO error toast
|
||||||
|
console.error('get LLM model list error', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function selectLLM(cardVO: LLMCardVO) {
|
function selectLLM(cardVO: LLMCardVO) {
|
||||||
setIsEditForm(true)
|
setIsEditForm(true);
|
||||||
setNowSelectedLLM(cardVO)
|
setNowSelectedLLM(cardVO);
|
||||||
console.log("set now vo", cardVO)
|
console.log('set now vo', cardVO);
|
||||||
setModalOpen(true)
|
setModalOpen(true);
|
||||||
}
|
}
|
||||||
function handleCreateModelClick() {
|
function handleCreateModelClick() {
|
||||||
setIsEditForm(false)
|
setIsEditForm(false);
|
||||||
setNowSelectedLLM(null)
|
setNowSelectedLLM(null);
|
||||||
setModalOpen(true);
|
setModalOpen(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.configPageContainer}>
|
<div className={styles.configPageContainer}>
|
||||||
<Modal
|
<Modal
|
||||||
title={isEditForm ? "预览模型" : "创建模型"}
|
title={isEditForm ? '预览模型' : '创建模型'}
|
||||||
centered
|
centered
|
||||||
open={modalOpen}
|
open={modalOpen}
|
||||||
destroyOnClose={true}
|
destroyOnClose={true}
|
||||||
onOk={() => setModalOpen(false)}
|
onOk={() => setModalOpen(false)}
|
||||||
onCancel={() => setModalOpen(false)}
|
onCancel={() => setModalOpen(false)}
|
||||||
width={700}
|
width={700}
|
||||||
footer={null}
|
footer={null}
|
||||||
>
|
>
|
||||||
<LLMForm
|
<LLMForm
|
||||||
editMode={isEditForm}
|
editMode={isEditForm}
|
||||||
initLLMId={nowSelectedLLM?.id}
|
initLLMId={nowSelectedLLM?.id}
|
||||||
onFormSubmit={() => {
|
onFormSubmit={() => {
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
getLLMModelList()
|
getLLMModelList();
|
||||||
}}
|
}}
|
||||||
onFormCancel={() => {
|
onFormCancel={() => {
|
||||||
setModalOpen(false);
|
setModalOpen(false);
|
||||||
}}
|
}}
|
||||||
onLLMDeleted={() => {
|
onLLMDeleted={() => {
|
||||||
setModalOpen(false)
|
setModalOpen(false);
|
||||||
getLLMModelList()
|
getLLMModelList();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
{
|
{cardList.length > 0 && (
|
||||||
cardList.length > 0 &&
|
<div className={`${styles.modelListContainer}`}>
|
||||||
<div className={`${styles.modelListContainer}`}
|
{cardList.map((cardVO) => {
|
||||||
>
|
return (
|
||||||
{cardList.map(cardVO => {
|
<div
|
||||||
return <div key={cardVO.id} onClick={() => {selectLLM(cardVO)}}>
|
key={cardVO.id}
|
||||||
<LLMCard cardVO={cardVO}></LLMCard>
|
onClick={() => {
|
||||||
</div>
|
selectLLM(cardVO);
|
||||||
})}
|
}}
|
||||||
<CreateCardComponent
|
>
|
||||||
width={360}
|
<LLMCard cardVO={cardVO}></LLMCard>
|
||||||
height={200}
|
</div>
|
||||||
plusSize={90}
|
);
|
||||||
onClick={handleCreateModelClick}
|
})}
|
||||||
/>
|
<CreateCardComponent
|
||||||
</div>
|
width={360}
|
||||||
}
|
height={200}
|
||||||
|
plusSize={90}
|
||||||
{
|
onClick={handleCreateModelClick}
|
||||||
cardList.length === 0 &&
|
/>
|
||||||
<div className={`${styles.emptyContainer}`}>
|
|
||||||
<EmptyAndCreateComponent
|
|
||||||
title={"模型列表空空如也~"}
|
|
||||||
subTitle={"快去创建一个吧!"}
|
|
||||||
buttonText={"创建模型 +"}
|
|
||||||
onButtonClick={() => {
|
|
||||||
handleCreateModelClick()
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)}
|
||||||
|
|
||||||
|
{cardList.length === 0 && (
|
||||||
|
<div className={`${styles.emptyContainer}`}>
|
||||||
|
<EmptyAndCreateComponent
|
||||||
|
title={'模型列表空空如也~'}
|
||||||
|
subTitle={'快去创建一个吧!'}
|
||||||
|
buttonText={'创建模型 +'}
|
||||||
|
onButtonClick={() => {
|
||||||
|
handleCreateModelClick();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return <div className={``}></div>;
|
||||||
<div className={``}>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,29 @@
|
|||||||
import styles from "./pipelineCard.module.css";
|
import styles from './pipelineCard.module.css';
|
||||||
import {PipelineCardVO} from "@/app/home/pipelines/components/pipeline-card/PipelineCardVO";
|
import { PipelineCardVO } from '@/app/home/pipelines/components/pipeline-card/PipelineCardVO';
|
||||||
|
|
||||||
export default function PipelineCardComponent({
|
export default function PipelineCardComponent({
|
||||||
cardVO
|
cardVO,
|
||||||
}: {
|
}: {
|
||||||
cardVO: PipelineCardVO
|
cardVO: PipelineCardVO;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className={`${styles.cardContainer}`}>
|
<div className={`${styles.cardContainer}`}>
|
||||||
{/* icon和基本信息 */}
|
{/* icon和基本信息 */}
|
||||||
<div className={`${styles.iconBasicInfoContainer}`}>
|
<div className={`${styles.iconBasicInfoContainer}`}>
|
||||||
{/* icon */}
|
{/* icon */}
|
||||||
<div className={`${styles.icon}`}>
|
<div className={`${styles.icon}`}>ICO</div>
|
||||||
ICO
|
{/* 基本信息 */}
|
||||||
</div>
|
<div className={`${styles.basicInfoContainer}`}>
|
||||||
{/* 基本信息 */}
|
<div className={`${styles.basicInfoText} ${styles.bigText}`}>
|
||||||
<div className={`${styles.basicInfoContainer}`}>
|
{cardVO.name}
|
||||||
<div className={`${styles.basicInfoText} ${styles.bigText}`}>
|
</div>
|
||||||
{cardVO.name}
|
<div className={`${styles.basicInfoText}`}>
|
||||||
</div>
|
描述:{cardVO.description}
|
||||||
<div className={`${styles.basicInfoText}`}>
|
</div>
|
||||||
描述:{cardVO.description}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* URL和创建时间 */}
|
|
||||||
<div className={`${styles.urlAndUpdateText}`}>
|
|
||||||
版本:{cardVO.version}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
</div>
|
||||||
|
{/* URL和创建时间 */}
|
||||||
|
<div className={`${styles.urlAndUpdateText}`}>版本:{cardVO.version}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
export interface IPipelineCardVO {
|
export interface IPipelineCardVO {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
createTime: string;
|
createTime: string;
|
||||||
version: string;
|
version: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PipelineCardVO implements IPipelineCardVO {
|
export class PipelineCardVO implements IPipelineCardVO {
|
||||||
createTime: string;
|
createTime: string;
|
||||||
description: string;
|
description: string;
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
version: string;
|
version: string;
|
||||||
|
|
||||||
constructor(props: IPipelineCardVO) {
|
constructor(props: IPipelineCardVO) {
|
||||||
this.id = props.id;
|
this.id = props.id;
|
||||||
this.name = props.name;
|
this.name = props.name;
|
||||||
this.description = props.description;
|
this.description = props.description;
|
||||||
this.createTime = props.createTime;
|
this.createTime = props.createTime;
|
||||||
this.version = props.version;
|
this.version = props.version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { DynamicFormItemConfig } from "@/app/home/components/dynamic-form/DynamicFormItemConfig";
|
import { DynamicFormItemConfig } from '@/app/home/components/dynamic-form/DynamicFormItemConfig';
|
||||||
|
|
||||||
export interface IPipelineChildFormEntity {
|
export interface IPipelineChildFormEntity {
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ import {
|
|||||||
Select,
|
Select,
|
||||||
Input,
|
Input,
|
||||||
InputNumber,
|
InputNumber,
|
||||||
SelectProps
|
SelectProps,
|
||||||
} from "antd";
|
} from 'antd';
|
||||||
import { CaretLeftOutlined, CaretRightOutlined } from "@ant-design/icons";
|
import { CaretLeftOutlined, CaretRightOutlined } from '@ant-design/icons';
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react';
|
||||||
import styles from "./pipelineFormStyle.module.css";
|
import styles from './pipelineFormStyle.module.css';
|
||||||
import { httpClient } from "@/app/infra/http/HttpClient";
|
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||||
import { LLMModel, Pipeline } from "@/app/infra/api/api-types";
|
import { LLMModel, Pipeline } from '@/app/infra/api/api-types';
|
||||||
import { UUID } from "uuidjs";
|
import { UUID } from 'uuidjs';
|
||||||
import {PipelineFormEntity} from "@/app/home/pipelines/components/pipeline-form/PipelineFormEntity";
|
import { PipelineFormEntity } from '@/app/home/pipelines/components/pipeline-form/PipelineFormEntity';
|
||||||
|
|
||||||
export default function PipelineFormComponent({
|
export default function PipelineFormComponent({
|
||||||
initValues,
|
initValues,
|
||||||
@@ -30,15 +30,15 @@ export default function PipelineFormComponent({
|
|||||||
onFinish: () => void;
|
onFinish: () => void;
|
||||||
}) {
|
}) {
|
||||||
const [nowFormIndex, setNowFormIndex] = useState<number>(0);
|
const [nowFormIndex, setNowFormIndex] = useState<number>(0);
|
||||||
const [nowAIRunner, setNowAIRunner] = useState("");
|
const [nowAIRunner, setNowAIRunner] = useState('');
|
||||||
const [llmModelList, setLlmModelList] = useState<SelectProps["options"]>([]);
|
const [llmModelList, setLlmModelList] = useState<SelectProps['options']>([]);
|
||||||
// 这里不好,可以改成enum等
|
// 这里不好,可以改成enum等
|
||||||
const formLabelList: FormLabel[] = [
|
const formLabelList: FormLabel[] = [
|
||||||
{ label: "基础", name: "basic" },
|
{ label: '基础', name: 'basic' },
|
||||||
{ label: "AI能力", name: "ai" },
|
{ label: 'AI能力', name: 'ai' },
|
||||||
{ label: "触发条件", name: "trigger" },
|
{ label: '触发条件', name: 'trigger' },
|
||||||
{ label: "安全能力", name: "safety" },
|
{ label: '安全能力', name: 'safety' },
|
||||||
{ label: "输出处理", name: "output" }
|
{ label: '输出处理', name: 'output' },
|
||||||
];
|
];
|
||||||
const [basicForm] = Form.useForm();
|
const [basicForm] = Form.useForm();
|
||||||
const [aiForm] = Form.useForm();
|
const [aiForm] = Form.useForm();
|
||||||
@@ -51,7 +51,7 @@ export default function PipelineFormComponent({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("initValues change: ", initValues);
|
console.log('initValues change: ', initValues);
|
||||||
if (initValues) {
|
if (initValues) {
|
||||||
basicForm.setFieldsValue(initValues.basic);
|
basicForm.setFieldsValue(initValues.basic);
|
||||||
aiForm.setFieldsValue(initValues.ai);
|
aiForm.setFieldsValue(initValues.ai);
|
||||||
@@ -59,8 +59,7 @@ export default function PipelineFormComponent({
|
|||||||
safetyForm.setFieldsValue(initValues.safety);
|
safetyForm.setFieldsValue(initValues.safety);
|
||||||
outputForm.setFieldsValue(initValues.output);
|
outputForm.setFieldsValue(initValues.output);
|
||||||
}
|
}
|
||||||
}, [initValues]);
|
}, [aiForm, basicForm, initValues, outputForm, safetyForm, triggerForm]);
|
||||||
|
|
||||||
|
|
||||||
function getLLMModelList() {
|
function getLLMModelList() {
|
||||||
httpClient
|
httpClient
|
||||||
@@ -70,13 +69,13 @@ export default function PipelineFormComponent({
|
|||||||
resp.models.map((model: LLMModel) => {
|
resp.models.map((model: LLMModel) => {
|
||||||
return {
|
return {
|
||||||
value: model.uuid,
|
value: model.uuid,
|
||||||
label: model.name
|
label: model.name,
|
||||||
};
|
};
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error("get LLM model list error", err);
|
console.error('get LLM model list error', err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,9 +113,9 @@ export default function PipelineFormComponent({
|
|||||||
|
|
||||||
function handleCommit() {
|
function handleCommit() {
|
||||||
if (isEditMode) {
|
if (isEditMode) {
|
||||||
handleModify()
|
handleModify();
|
||||||
} else {
|
} else {
|
||||||
handleCreate()
|
handleCreate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,15 +125,15 @@ export default function PipelineFormComponent({
|
|||||||
aiForm.validateFields(),
|
aiForm.validateFields(),
|
||||||
triggerForm.validateFields(),
|
triggerForm.validateFields(),
|
||||||
safetyForm.validateFields(),
|
safetyForm.validateFields(),
|
||||||
outputForm.validateFields()
|
outputForm.validateFields(),
|
||||||
])
|
])
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const pipeline = assembleForm();
|
const pipeline = assembleForm();
|
||||||
httpClient.createPipeline(pipeline).then(() => onFinish());
|
httpClient.createPipeline(pipeline).then(() => onFinish());
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleModify() {
|
function handleModify() {
|
||||||
@@ -143,61 +142,63 @@ export default function PipelineFormComponent({
|
|||||||
aiForm.validateFields(),
|
aiForm.validateFields(),
|
||||||
triggerForm.validateFields(),
|
triggerForm.validateFields(),
|
||||||
safetyForm.validateFields(),
|
safetyForm.validateFields(),
|
||||||
outputForm.validateFields()
|
outputForm.validateFields(),
|
||||||
])
|
])
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const pipeline = assembleForm();
|
const pipeline = assembleForm();
|
||||||
httpClient.updatePipeline(pipelineId || '', pipeline).then(() => onFinish());
|
httpClient
|
||||||
})
|
.updatePipeline(pipelineId || '', pipeline)
|
||||||
.catch((e) => {
|
.then(() => onFinish());
|
||||||
console.error(e);
|
})
|
||||||
});
|
.catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 类型混乱,需要优化
|
// TODO 类型混乱,需要优化
|
||||||
function assembleForm(): Pipeline {
|
function assembleForm(): Pipeline {
|
||||||
console.log("basicForm:", basicForm.getFieldsValue());
|
console.log('basicForm:', basicForm.getFieldsValue());
|
||||||
console.log("aiForm:", aiForm.getFieldsValue());
|
console.log('aiForm:', aiForm.getFieldsValue());
|
||||||
console.log("triggerForm:", triggerForm.getFieldsValue());
|
console.log('triggerForm:', triggerForm.getFieldsValue());
|
||||||
console.log("safetyForm:", safetyForm.getFieldsValue());
|
console.log('safetyForm:', safetyForm.getFieldsValue());
|
||||||
console.log("outputForm:", outputForm.getFieldsValue());
|
console.log('outputForm:', outputForm.getFieldsValue());
|
||||||
const config: object = {
|
const config: object = {
|
||||||
ai: aiForm.getFieldsValue(),
|
ai: aiForm.getFieldsValue(),
|
||||||
trigger: triggerForm.getFieldsValue(),
|
trigger: triggerForm.getFieldsValue(),
|
||||||
safety: safetyForm.getFieldsValue(),
|
safety: safetyForm.getFieldsValue(),
|
||||||
output: outputForm.getFieldsValue()
|
output: outputForm.getFieldsValue(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
config,
|
config,
|
||||||
created_at: "",
|
created_at: '',
|
||||||
description: basicForm.getFieldsValue().description,
|
description: basicForm.getFieldsValue().description,
|
||||||
for_version: "",
|
for_version: '',
|
||||||
name: basicForm.getFieldsValue().name,
|
name: basicForm.getFieldsValue().name,
|
||||||
stages: [],
|
stages: [],
|
||||||
updated_at: "",
|
updated_at: '',
|
||||||
uuid: UUID.generate()
|
uuid: UUID.generate(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ maxHeight: "70vh", overflowY: "auto" }}>
|
<div style={{ maxHeight: '70vh', overflowY: 'auto' }}>
|
||||||
<h1>{getNowFormLabel().label}</h1>
|
<h1>{getNowFormLabel().label}</h1>
|
||||||
<Form
|
<Form
|
||||||
layout={"vertical"}
|
layout={'vertical'}
|
||||||
style={{
|
style={{
|
||||||
display: getNowFormLabel().name === "basic" ? "block" : "none"
|
display: getNowFormLabel().name === 'basic' ? 'block' : 'none',
|
||||||
}}
|
}}
|
||||||
form={basicForm}
|
form={basicForm}
|
||||||
disabled={disableForm}
|
disabled={disableForm}
|
||||||
>
|
>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="流水线名称"
|
label="流水线名称"
|
||||||
name={"name"}
|
name={'name'}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
@@ -205,11 +206,11 @@ export default function PipelineFormComponent({
|
|||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="流水线描述"
|
label="流水线描述"
|
||||||
name={"description"}
|
name={'description'}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
@@ -217,8 +218,8 @@ export default function PipelineFormComponent({
|
|||||||
</Form>
|
</Form>
|
||||||
{/* AI能力表单 ai */}
|
{/* AI能力表单 ai */}
|
||||||
<Form
|
<Form
|
||||||
layout={"vertical"}
|
layout={'vertical'}
|
||||||
style={{ display: getNowFormLabel().name === "ai" ? "block" : "none" }}
|
style={{ display: getNowFormLabel().name === 'ai' ? 'block' : 'none' }}
|
||||||
form={aiForm}
|
form={aiForm}
|
||||||
disabled={disableForm}
|
disabled={disableForm}
|
||||||
>
|
>
|
||||||
@@ -226,26 +227,26 @@ export default function PipelineFormComponent({
|
|||||||
<div className={`${styles.formItemSubtitle}`}>运行器</div>
|
<div className={`${styles.formItemSubtitle}`}>运行器</div>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="运行器"
|
label="运行器"
|
||||||
name={["runner", "runner"]}
|
name={['runner', 'runner']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
options={[
|
options={[
|
||||||
{ label: "内置 Agent", value: "local-agent" },
|
{ label: '内置 Agent', value: 'local-agent' },
|
||||||
{ label: "Dify 服务 API", value: "dify-service-api" },
|
{ label: 'Dify 服务 API', value: 'dify-service-api' },
|
||||||
{ label: "阿里云百炼平台 API", value: "dashscope-app-api" }
|
{ label: '阿里云百炼平台 API', value: 'dashscope-app-api' },
|
||||||
]}
|
]}
|
||||||
onChange={(value) => setNowAIRunner(value)}
|
onChange={(value) => setNowAIRunner(value)}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
{/* 内置 Agent 配置区块 */}
|
{/* 内置 Agent 配置区块 */}
|
||||||
{nowAIRunner === "local-agent" && (
|
{nowAIRunner === 'local-agent' && (
|
||||||
<>
|
<>
|
||||||
<div className={`${styles.formItemSubtitle}`}>配置内置Agent</div>
|
<div className={`${styles.formItemSubtitle}`}>配置内置Agent</div>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="模型"
|
label="模型"
|
||||||
name={["local-agent", "model"]}
|
name={['local-agent', 'model']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
tooltip="从模型库中选择"
|
tooltip="从模型库中选择"
|
||||||
>
|
>
|
||||||
@@ -257,11 +258,11 @@ export default function PipelineFormComponent({
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="最大回合数"
|
label="最大回合数"
|
||||||
name={["local-agent", "max-round"]}
|
name={['local-agent', 'max-round']}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber precision={0} />
|
<InputNumber precision={0} />
|
||||||
@@ -269,7 +270,7 @@ export default function PipelineFormComponent({
|
|||||||
{/* TODO 这里要做转换处理 */}
|
{/* TODO 这里要做转换处理 */}
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="提示词"
|
label="提示词"
|
||||||
name={["local-agent", "prompt"]}
|
name={['local-agent', 'prompt']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
tooltip="按JSON格式输入"
|
tooltip="按JSON格式输入"
|
||||||
>
|
>
|
||||||
@@ -281,91 +282,91 @@ export default function PipelineFormComponent({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{/* Dify 服务 API 区块 */}
|
{/* Dify 服务 API 区块 */}
|
||||||
{nowAIRunner === "dify-service-api" && (
|
{nowAIRunner === 'dify-service-api' && (
|
||||||
<>
|
<>
|
||||||
<div className={`${styles.formItemSubtitle}`}>配置Dify服务API</div>
|
<div className={`${styles.formItemSubtitle}`}>配置Dify服务API</div>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="基础 URL"
|
label="基础 URL"
|
||||||
name={["dify-service-api", "base-url"]}
|
name={['dify-service-api', 'base-url']}
|
||||||
rules={[
|
rules={[
|
||||||
{ required: true },
|
{ required: true },
|
||||||
{ type: "url", message: "请输入有效的URL地址" }
|
{ type: 'url', message: '请输入有效的URL地址' },
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="应用类型"
|
label="应用类型"
|
||||||
name={["dify-service-api", "app-type"]}
|
name={['dify-service-api', 'app-type']}
|
||||||
initialValue={"chat"}
|
initialValue={'chat'}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
options={[
|
options={[
|
||||||
{ label: "聊天(包括Chatflow)", value: "chat" },
|
{ label: '聊天(包括Chatflow)', value: 'chat' },
|
||||||
{ label: "Agent", value: "agent" },
|
{ label: 'Agent', value: 'agent' },
|
||||||
{ label: "工作流", value: "workflow" }
|
{ label: '工作流', value: 'workflow' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="API 密钥"
|
label="API 密钥"
|
||||||
name={["dify-service-api", "api-key"]}
|
name={['dify-service-api', 'api-key']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Input.Password visibilityToggle={false} />
|
<Input.Password visibilityToggle={false} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="思维链转换"
|
label="思维链转换"
|
||||||
name={["dify-service-api", "thinking-convert"]}
|
name={['dify-service-api', 'thinking-convert']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
options={[
|
options={[
|
||||||
{ label: "转换成 \<think\>...\<\/think\>", value: "plain" },
|
{ label: '转换成 \<think\>...\<\/think\>', value: 'plain' },
|
||||||
{ label: "原始", value: "original" },
|
{ label: '原始', value: 'original' },
|
||||||
{ label: "移除", value: "remove" }
|
{ label: '移除', value: 'remove' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{/* 阿里云百炼区块 */}
|
{/* 阿里云百炼区块 */}
|
||||||
{nowAIRunner === "dashscope-app-api" && (
|
{nowAIRunner === 'dashscope-app-api' && (
|
||||||
<>
|
<>
|
||||||
<div className={`${styles.formItemSubtitle}`}>
|
<div className={`${styles.formItemSubtitle}`}>
|
||||||
配置阿里云百炼平台 API
|
配置阿里云百炼平台 API
|
||||||
</div>
|
</div>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="应用类型"
|
label="应用类型"
|
||||||
name={["dashscope-app-api", "app-type"]}
|
name={['dashscope-app-api', 'app-type']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
options={[
|
options={[
|
||||||
{ label: "Agent", value: "agent" },
|
{ label: 'Agent', value: 'agent' },
|
||||||
{ label: "工作流", value: "workflow" }
|
{ label: '工作流', value: 'workflow' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="API 密钥"
|
label="API 密钥"
|
||||||
name={["dashscope-app-api", "api-key"]}
|
name={['dashscope-app-api', 'api-key']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Input.Password visibilityToggle={false} />
|
<Input.Password visibilityToggle={false} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="应用 ID"
|
label="应用 ID"
|
||||||
name={["dashscope-app-api", "app-id"]}
|
name={['dashscope-app-api', 'app-id']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="引用文本"
|
label="引用文本"
|
||||||
name={["dashscope-app-api", "references_quote"]}
|
name={['dashscope-app-api', 'references_quote']}
|
||||||
initialValue={"参考资料来自:"}
|
initialValue={'参考资料来自:'}
|
||||||
>
|
>
|
||||||
<Input.TextArea rows={2} />
|
<Input.TextArea rows={2} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -375,9 +376,9 @@ export default function PipelineFormComponent({
|
|||||||
|
|
||||||
{/* 触发条件表单 trigger */}
|
{/* 触发条件表单 trigger */}
|
||||||
<Form
|
<Form
|
||||||
layout={"vertical"}
|
layout={'vertical'}
|
||||||
style={{
|
style={{
|
||||||
display: getNowFormLabel().name === "trigger" ? "block" : "none"
|
display: getNowFormLabel().name === 'trigger' ? 'block' : 'none',
|
||||||
}}
|
}}
|
||||||
form={triggerForm}
|
form={triggerForm}
|
||||||
disabled={disableForm}
|
disabled={disableForm}
|
||||||
@@ -385,15 +386,15 @@ export default function PipelineFormComponent({
|
|||||||
{/* 群响应规则块 */}
|
{/* 群响应规则块 */}
|
||||||
<div className={`${styles.formItemSubtitle}`}> 群响应规则</div>
|
<div className={`${styles.formItemSubtitle}`}> 群响应规则</div>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"是否在消息@机器人时触发"}
|
label={'是否在消息@机器人时触发'}
|
||||||
name={["group-respond-rules", "at"]}
|
name={['group-respond-rules', 'at']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"消息前缀"}
|
label={'消息前缀'}
|
||||||
name={["group-respond-rules", "prefix"]}
|
name={['group-respond-rules', 'prefix']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
@@ -401,76 +402,76 @@ export default function PipelineFormComponent({
|
|||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"正则表达式"}
|
label={'正则表达式'}
|
||||||
name={["group-respond-rules", "regexp"]}
|
name={['group-respond-rules', 'regexp']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Select mode="tags" options={[]} />
|
<Select mode="tags" options={[]} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"随机"}
|
label={'随机'}
|
||||||
name={["group-respond-rules", "random"]}
|
name={['group-respond-rules', 'random']}
|
||||||
rules={[{ required: false }]}
|
rules={[{ required: false }]}
|
||||||
>
|
>
|
||||||
<InputNumber max={1} min={0} step={0.05} />
|
<InputNumber max={1} min={0} step={0.05} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<div className={`${styles.formItemSubtitle}`}> 访问控制 </div>
|
<div className={`${styles.formItemSubtitle}`}> 访问控制 </div>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"模式"}
|
label={'模式'}
|
||||||
name={["access-control", "mode"]}
|
name={['access-control', 'mode']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
tooltip={"访问控制模式"}
|
tooltip={'访问控制模式'}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
options={[
|
options={[
|
||||||
{ label: "黑名单", value: "blacklist" },
|
{ label: '黑名单', value: 'blacklist' },
|
||||||
{ label: "白名单", value: "Whitelist" }
|
{ label: '白名单', value: 'Whitelist' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"黑名单"}
|
label={'黑名单'}
|
||||||
name={["access-control", "blacklist"]}
|
name={['access-control', 'blacklist']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Select mode={"tags"} options={[]} />
|
<Select mode={'tags'} options={[]} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"白名单"}
|
label={'白名单'}
|
||||||
name={["access-control", "whitelist"]}
|
name={['access-control', 'whitelist']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Select mode={"tags"} options={[]} />
|
<Select mode={'tags'} options={[]} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<div className={`${styles.formItemSubtitle}`}> 消息忽略规则 </div>
|
<div className={`${styles.formItemSubtitle}`}> 消息忽略规则 </div>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"前缀"}
|
label={'前缀'}
|
||||||
name={["ignore-rules", "whitelist"]}
|
name={['ignore-rules', 'whitelist']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
tooltip={"消息前缀"}
|
tooltip={'消息前缀'}
|
||||||
>
|
>
|
||||||
<Select mode={"tags"} options={[]} />
|
<Select mode={'tags'} options={[]} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"正则表达式"}
|
label={'正则表达式'}
|
||||||
name={["ignore-rules", "regexp"]}
|
name={['ignore-rules', 'regexp']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
tooltip={"消息正则表达式"}
|
tooltip={'消息正则表达式'}
|
||||||
>
|
>
|
||||||
<Select mode={"tags"} options={[]} />
|
<Select mode={'tags'} options={[]} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
||||||
{/* 安全控制表单 safety */}
|
{/* 安全控制表单 safety */}
|
||||||
<Form
|
<Form
|
||||||
layout={"vertical"}
|
layout={'vertical'}
|
||||||
style={{
|
style={{
|
||||||
display: getNowFormLabel().name === "safety" ? "block" : "none"
|
display: getNowFormLabel().name === 'safety' ? 'block' : 'none',
|
||||||
}}
|
}}
|
||||||
form={safetyForm}
|
form={safetyForm}
|
||||||
disabled={disableForm}
|
disabled={disableForm}
|
||||||
@@ -478,22 +479,22 @@ export default function PipelineFormComponent({
|
|||||||
{/* 内容过滤块 content-filter */}
|
{/* 内容过滤块 content-filter */}
|
||||||
<div className={`${styles.formItemSubtitle}`}> 内容过滤 </div>
|
<div className={`${styles.formItemSubtitle}`}> 内容过滤 </div>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"检查范围"}
|
label={'检查范围'}
|
||||||
name={["content-filter", "scope"]}
|
name={['content-filter', 'scope']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
options={[
|
options={[
|
||||||
{ label: "全部", value: "all" },
|
{ label: '全部', value: 'all' },
|
||||||
{ label: "传入消息(用户消息)", value: "income-msg" },
|
{ label: '传入消息(用户消息)', value: 'income-msg' },
|
||||||
{ label: "传出消息(机器人消息)", value: "output-msg" }
|
{ label: '传出消息(机器人消息)', value: 'output-msg' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"检查敏感词"}
|
label={'检查敏感词'}
|
||||||
name={["content-filter", "check-sensitive-words"]}
|
name={['content-filter', 'check-sensitive-words']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
@@ -502,31 +503,31 @@ export default function PipelineFormComponent({
|
|||||||
{/* 速率限制块 rate-limit */}
|
{/* 速率限制块 rate-limit */}
|
||||||
<div className={`${styles.formItemSubtitle}`}> 速率限制 </div>
|
<div className={`${styles.formItemSubtitle}`}> 速率限制 </div>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"窗口长度(秒)"}
|
label={'窗口长度(秒)'}
|
||||||
name={["rate-limit", "window-length"]}
|
name={['rate-limit', 'window-length']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
initialValue={60}
|
initialValue={60}
|
||||||
>
|
>
|
||||||
<InputNumber></InputNumber>
|
<InputNumber></InputNumber>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"限制次数"}
|
label={'限制次数'}
|
||||||
name={["rate-limit", "limitation"]}
|
name={['rate-limit', 'limitation']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
initialValue={60}
|
initialValue={60}
|
||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={"策略"}
|
label={'策略'}
|
||||||
name={["rate-limit", "strategy"]}
|
name={['rate-limit', 'strategy']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
initialValue={"drop"}
|
initialValue={'drop'}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
options={[
|
options={[
|
||||||
{ label: "丢弃", value: "drop" },
|
{ label: '丢弃', value: 'drop' },
|
||||||
{ label: "等待", value: "wait" }
|
{ label: '等待', value: 'wait' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -534,9 +535,9 @@ export default function PipelineFormComponent({
|
|||||||
|
|
||||||
{/* 输出处理控制表单 output */}
|
{/* 输出处理控制表单 output */}
|
||||||
<Form
|
<Form
|
||||||
layout={"vertical"}
|
layout={'vertical'}
|
||||||
style={{
|
style={{
|
||||||
display: getNowFormLabel().name === "output" ? "block" : "none"
|
display: getNowFormLabel().name === 'output' ? 'block' : 'none',
|
||||||
}}
|
}}
|
||||||
form={outputForm}
|
form={outputForm}
|
||||||
disabled={disableForm}
|
disabled={disableForm}
|
||||||
@@ -545,26 +546,26 @@ export default function PipelineFormComponent({
|
|||||||
<div className={`${styles.formItemSubtitle}`}> 长文本处理 </div>
|
<div className={`${styles.formItemSubtitle}`}> 长文本处理 </div>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="阈值"
|
label="阈值"
|
||||||
name={["long-text-processing", "threshold"]}
|
name={['long-text-processing', 'threshold']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="策略"
|
label="策略"
|
||||||
name={["long-text-processing", "strategy"]}
|
name={['long-text-processing', 'strategy']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
options={[
|
options={[
|
||||||
{ label: "转发消息组件", value: "forward" },
|
{ label: '转发消息组件', value: 'forward' },
|
||||||
{ label: "转换为图片", value: "image" }
|
{ label: '转换为图片', value: 'image' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="字体路径"
|
label="字体路径"
|
||||||
name={["long-text-processing", "font-path"]}
|
name={['long-text-processing', 'font-path']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
@@ -574,14 +575,14 @@ export default function PipelineFormComponent({
|
|||||||
<div className={`${styles.formItemSubtitle}`}> 强制延迟 </div>
|
<div className={`${styles.formItemSubtitle}`}> 强制延迟 </div>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="最小秒数"
|
label="最小秒数"
|
||||||
name={["force-delay", "min"]}
|
name={['force-delay', 'min']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="最大秒数"
|
label="最大秒数"
|
||||||
name={["force-delay", "max"]}
|
name={['force-delay', 'max']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
@@ -591,7 +592,7 @@ export default function PipelineFormComponent({
|
|||||||
<div className={`${styles.formItemSubtitle}`}> 杂项 </div>
|
<div className={`${styles.formItemSubtitle}`}> 杂项 </div>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="不输出异常信息给用户"
|
label="不输出异常信息给用户"
|
||||||
name={["misc", "hide-exception"]}
|
name={['misc', 'hide-exception']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
valuePropName="checked"
|
valuePropName="checked"
|
||||||
>
|
>
|
||||||
@@ -599,7 +600,7 @@ export default function PipelineFormComponent({
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="在回复中@发送者"
|
label="在回复中@发送者"
|
||||||
name={["misc", "at-sender"]}
|
name={['misc', 'at-sender']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
valuePropName="checked"
|
valuePropName="checked"
|
||||||
>
|
>
|
||||||
@@ -607,7 +608,7 @@ export default function PipelineFormComponent({
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="引用原文"
|
label="引用原文"
|
||||||
name={["misc", "quote-origin"]}
|
name={['misc', 'quote-origin']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
valuePropName="checked"
|
valuePropName="checked"
|
||||||
>
|
>
|
||||||
@@ -615,7 +616,7 @@ export default function PipelineFormComponent({
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="跟踪函数调用"
|
label="跟踪函数调用"
|
||||||
name={["misc", "track-function-calls"]}
|
name={['misc', 'track-function-calls']}
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
valuePropName="checked"
|
valuePropName="checked"
|
||||||
>
|
>
|
||||||
@@ -630,16 +631,16 @@ export default function PipelineFormComponent({
|
|||||||
onClick={reduceFormLabelIndex}
|
onClick={reduceFormLabelIndex}
|
||||||
disabled={!getPreFormLabel()}
|
disabled={!getPreFormLabel()}
|
||||||
>
|
>
|
||||||
{getPreFormLabel()?.label || "暂无更多"}
|
{getPreFormLabel()?.label || '暂无更多'}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
icon={<CaretRightOutlined />}
|
icon={<CaretRightOutlined />}
|
||||||
onClick={addFormLabelIndex}
|
onClick={addFormLabelIndex}
|
||||||
disabled={!getNextFormLabel()}
|
disabled={!getNextFormLabel()}
|
||||||
iconPosition={"end"}
|
iconPosition={'end'}
|
||||||
>
|
>
|
||||||
{getNextFormLabel()?.label || "暂无更多"}
|
{getNextFormLabel()?.label || '暂无更多'}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button type="primary" onClick={handleCommit}>
|
<Button type="primary" onClick={handleCommit}>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export interface PipelineFormEntity {
|
export interface PipelineFormEntity {
|
||||||
basic: object,
|
basic: object;
|
||||||
ai: object,
|
ai: object;
|
||||||
trigger: object,
|
trigger: object;
|
||||||
safety: object,
|
safety: object;
|
||||||
output: object,
|
output: object;
|
||||||
}
|
}
|
||||||
@@ -1,26 +1,27 @@
|
|||||||
"use client";
|
'use client';
|
||||||
import { Modal } from "antd";
|
import { Modal } from 'antd';
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from 'react';
|
||||||
import CreateCardComponent from "@/app/infra/basic-component/create-card-component/CreateCardComponent";
|
import CreateCardComponent from '@/app/infra/basic-component/create-card-component/CreateCardComponent';
|
||||||
import PipelineFormComponent from "./components/pipeline-form/PipelineFormComponent";
|
import PipelineFormComponent from './components/pipeline-form/PipelineFormComponent';
|
||||||
import { httpClient } from "@/app/infra/http/HttpClient";
|
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||||
import { PipelineCardVO } from "@/app/home/pipelines/components/pipeline-card/PipelineCardVO";
|
import { PipelineCardVO } from '@/app/home/pipelines/components/pipeline-card/PipelineCardVO';
|
||||||
import PipelineCardComponent from "@/app/home/pipelines/components/pipeline-card/PipelineCardComponent";
|
import PipelineCardComponent from '@/app/home/pipelines/components/pipeline-card/PipelineCardComponent';
|
||||||
import {PipelineFormEntity} from "@/app/home/pipelines/components/pipeline-form/PipelineFormEntity";
|
import { PipelineFormEntity } from '@/app/home/pipelines/components/pipeline-form/PipelineFormEntity';
|
||||||
|
|
||||||
export default function PluginConfigPage() {
|
export default function PluginConfigPage() {
|
||||||
const [modalOpen, setModalOpen] = useState<boolean>(false);
|
const [modalOpen, setModalOpen] = useState<boolean>(false);
|
||||||
const [isEditForm, setIsEditForm] = useState(false);
|
const [isEditForm, setIsEditForm] = useState(false);
|
||||||
const [pipelineList, setPipelineList] = useState<PipelineCardVO[]>([]);
|
const [pipelineList, setPipelineList] = useState<PipelineCardVO[]>([]);
|
||||||
const [selectedPipelineId, setSelectedPipelineId] = useState("")
|
const [selectedPipelineId, setSelectedPipelineId] = useState('');
|
||||||
const [selectedPipelineFormValue, setSelectedPipelineFormValue] = useState<PipelineFormEntity>({
|
const [selectedPipelineFormValue, setSelectedPipelineFormValue] =
|
||||||
|
useState<PipelineFormEntity>({
|
||||||
basic: {},
|
basic: {},
|
||||||
ai: {},
|
ai: {},
|
||||||
trigger: {},
|
trigger: {},
|
||||||
safety: {},
|
safety: {},
|
||||||
output: {},
|
output: {},
|
||||||
})
|
});
|
||||||
const [disableForm, setDisableForm] = useState(false)
|
const [disableForm, setDisableForm] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getPipelines();
|
getPipelines();
|
||||||
@@ -36,7 +37,7 @@ export default function PluginConfigPage() {
|
|||||||
description: pipeline.description,
|
description: pipeline.description,
|
||||||
id: pipeline.uuid,
|
id: pipeline.uuid,
|
||||||
name: pipeline.name,
|
name: pipeline.name,
|
||||||
version: pipeline.for_version
|
version: pipeline.for_version,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
setPipelineList(pipelineList);
|
setPipelineList(pipelineList);
|
||||||
@@ -48,25 +49,25 @@ export default function PluginConfigPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSelectedPipelineForm(id?: string) {
|
function getSelectedPipelineForm(id?: string) {
|
||||||
httpClient.getPipeline(id ?? selectedPipelineId).then((value) => {
|
httpClient.getPipeline(id ?? selectedPipelineId).then((value) => {
|
||||||
setSelectedPipelineFormValue({
|
setSelectedPipelineFormValue({
|
||||||
ai: value.pipeline.config.ai,
|
ai: value.pipeline.config.ai,
|
||||||
basic: {
|
basic: {
|
||||||
description: value.pipeline.description,
|
description: value.pipeline.description,
|
||||||
name: value.pipeline.name,
|
name: value.pipeline.name,
|
||||||
},
|
},
|
||||||
output: value.pipeline.config.output,
|
output: value.pipeline.config.output,
|
||||||
safety: value.pipeline.config.safety,
|
safety: value.pipeline.config.safety,
|
||||||
trigger: value.pipeline.config.trigger,
|
trigger: value.pipeline.config.trigger,
|
||||||
})
|
});
|
||||||
setDisableForm(false)
|
setDisableForm(false);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={``}>
|
<div className={``}>
|
||||||
<Modal
|
<Modal
|
||||||
title={isEditForm ? "编辑流水线" : "创建流水线"}
|
title={isEditForm ? '编辑流水线' : '创建流水线'}
|
||||||
centered
|
centered
|
||||||
open={modalOpen}
|
open={modalOpen}
|
||||||
destroyOnClose={true}
|
destroyOnClose={true}
|
||||||
@@ -94,11 +95,11 @@ export default function PluginConfigPage() {
|
|||||||
<div
|
<div
|
||||||
key={pipeline.id}
|
key={pipeline.id}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDisableForm(true)
|
setDisableForm(true);
|
||||||
setIsEditForm(true);
|
setIsEditForm(true);
|
||||||
setModalOpen(true);
|
setModalOpen(true);
|
||||||
setSelectedPipelineId(pipeline.id)
|
setSelectedPipelineId(pipeline.id);
|
||||||
getSelectedPipelineForm(pipeline.id);
|
getSelectedPipelineForm(pipeline.id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PipelineCardComponent cardVO={pipeline} />
|
<PipelineCardComponent cardVO={pipeline} />
|
||||||
|
|||||||
@@ -1,37 +1,41 @@
|
|||||||
"use client"
|
'use client';
|
||||||
import { Radio } from 'antd';
|
import { Radio } from 'antd';
|
||||||
import { useState } from "react";
|
import { useState } from 'react';
|
||||||
import PluginInstalledComponent from "@/app/home/plugins/plugin-installed/PluginInstalledComponent";
|
import PluginInstalledComponent from '@/app/home/plugins/plugin-installed/PluginInstalledComponent';
|
||||||
import PluginMarketComponent from "@/app/home/plugins/plugin-market/PluginMarketComponent";
|
import PluginMarketComponent from '@/app/home/plugins/plugin-market/PluginMarketComponent';
|
||||||
import styles from './plugins.module.css'
|
import styles from './plugins.module.css';
|
||||||
|
|
||||||
export default function PluginConfigPage() {
|
export default function PluginConfigPage() {
|
||||||
enum PageType {
|
enum PageType {
|
||||||
INSTALLED = "installed",
|
INSTALLED = 'installed',
|
||||||
MARKET = 'market'
|
MARKET = 'market',
|
||||||
}
|
}
|
||||||
|
|
||||||
const [nowPageType, setNowPageType] = useState(PageType.INSTALLED)
|
const [nowPageType, setNowPageType] = useState(PageType.INSTALLED);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.pageContainer}>
|
<div className={styles.pageContainer}>
|
||||||
<Radio.Group
|
<Radio.Group
|
||||||
block
|
block
|
||||||
options={[
|
options={[
|
||||||
{ label: '已安装', value: PageType.INSTALLED },
|
{ label: '已安装', value: PageType.INSTALLED },
|
||||||
{ label: '插件市场', value: PageType.MARKET },
|
{ label: '插件市场', value: PageType.MARKET },
|
||||||
]}
|
]}
|
||||||
defaultValue={PageType.INSTALLED}
|
defaultValue={PageType.INSTALLED}
|
||||||
value={nowPageType}
|
value={nowPageType}
|
||||||
optionType="button"
|
optionType="button"
|
||||||
buttonStyle="solid"
|
buttonStyle="solid"
|
||||||
style={{ marginBottom: '20px' }}
|
style={{ marginBottom: '20px' }}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setNowPageType(e.target.value as PageType)
|
setNowPageType(e.target.value as PageType);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{nowPageType === PageType.INSTALLED ? <PluginInstalledComponent /> : <PluginMarketComponent />}
|
{nowPageType === PageType.INSTALLED ? (
|
||||||
</div>
|
<PluginInstalledComponent />
|
||||||
);
|
) : (
|
||||||
|
<PluginMarketComponent />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,26 @@
|
|||||||
export interface IPluginCardVO {
|
export interface IPluginCardVO {
|
||||||
author: string,
|
author: string;
|
||||||
version: string,
|
version: string;
|
||||||
name: string,
|
name: string;
|
||||||
description: string,
|
description: string;
|
||||||
handlerCount: number,
|
handlerCount: number;
|
||||||
isInitialized: boolean,
|
isInitialized: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PluginCardVO implements IPluginCardVO {
|
export class PluginCardVO implements IPluginCardVO {
|
||||||
description: string;
|
description: string;
|
||||||
handlerCount: number;
|
handlerCount: number;
|
||||||
name: string;
|
name: string;
|
||||||
author: string;
|
author: string;
|
||||||
version: string;
|
version: string;
|
||||||
isInitialized: boolean;
|
isInitialized: boolean;
|
||||||
|
|
||||||
constructor(prop: IPluginCardVO) {
|
|
||||||
this.description = prop.description
|
|
||||||
this.handlerCount = prop.handlerCount
|
|
||||||
this.name = prop.name
|
|
||||||
this.author = prop.author
|
|
||||||
this.version = prop.version
|
|
||||||
this.isInitialized = prop.isInitialized
|
|
||||||
}
|
|
||||||
|
|
||||||
|
constructor(prop: IPluginCardVO) {
|
||||||
|
this.description = prop.description;
|
||||||
|
this.handlerCount = prop.handlerCount;
|
||||||
|
this.name = prop.name;
|
||||||
|
this.author = prop.author;
|
||||||
|
this.version = prop.version;
|
||||||
|
this.isInitialized = prop.isInitialized;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from 'react';
|
||||||
import CreateCardComponent from "@/app/infra/basic-component/create-card-component/CreateCardComponent";
|
import CreateCardComponent from '@/app/infra/basic-component/create-card-component/CreateCardComponent';
|
||||||
import { PluginCardVO } from "@/app/home/plugins/plugin-installed/PluginCardVO";
|
import { PluginCardVO } from '@/app/home/plugins/plugin-installed/PluginCardVO';
|
||||||
import PluginCardComponent from "@/app/home/plugins/plugin-installed/plugin-card/PluginCardComponent";
|
import PluginCardComponent from '@/app/home/plugins/plugin-installed/plugin-card/PluginCardComponent';
|
||||||
import styles from "@/app/home/plugins/plugins.module.css";
|
import styles from '@/app/home/plugins/plugins.module.css';
|
||||||
import { Modal, Input } from "antd";
|
import { Modal, Input } from 'antd';
|
||||||
import { GithubOutlined } from "@ant-design/icons";
|
import { GithubOutlined } from '@ant-design/icons';
|
||||||
import { httpClient } from "@/app/infra/http/HttpClient";
|
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||||
|
|
||||||
export default function PluginInstalledComponent() {
|
export default function PluginInstalledComponent() {
|
||||||
const [pluginList, setPluginList] = useState<PluginCardVO[]>([]);
|
const [pluginList, setPluginList] = useState<PluginCardVO[]>([]);
|
||||||
const [modalOpen, setModalOpen] = useState(false);
|
const [modalOpen, setModalOpen] = useState(false);
|
||||||
const [githubURL, setGithubURL] = useState("");
|
const [githubURL, setGithubURL] = useState('');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initData();
|
initData();
|
||||||
@@ -33,9 +33,9 @@ export default function PluginInstalledComponent() {
|
|||||||
handlerCount: 0,
|
handlerCount: 0,
|
||||||
name: plugin.name,
|
name: plugin.name,
|
||||||
version: plugin.version,
|
version: plugin.version,
|
||||||
isInitialized: plugin.status === "initialized"
|
isInitialized: plugin.status === 'initialized',
|
||||||
});
|
});
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ export default function PluginInstalledComponent() {
|
|||||||
getPluginList();
|
getPluginList();
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log("error when install plugin:", err);
|
console.log('error when install plugin:', err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
@@ -63,8 +63,8 @@ export default function PluginInstalledComponent() {
|
|||||||
<div className={`${styles.modalTitle}`}>
|
<div className={`${styles.modalTitle}`}>
|
||||||
<GithubOutlined
|
<GithubOutlined
|
||||||
style={{
|
style={{
|
||||||
fontSize: "30px",
|
fontSize: '30px',
|
||||||
marginRight: "20px"
|
marginRight: '20px',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import styles from "./pluginCard.module.css";
|
import styles from './pluginCard.module.css';
|
||||||
import { PluginCardVO } from "@/app/home/plugins/plugin-installed/PluginCardVO";
|
import { PluginCardVO } from '@/app/home/plugins/plugin-installed/PluginCardVO';
|
||||||
import { GithubOutlined, LinkOutlined, ToolOutlined } from "@ant-design/icons";
|
import { GithubOutlined, LinkOutlined, ToolOutlined } from '@ant-design/icons';
|
||||||
import { Switch, Tag } from "antd";
|
import { Switch, Tag } from 'antd';
|
||||||
import { useState } from "react";
|
import { useState } from 'react';
|
||||||
import { httpClient } from "@/app/infra/http/HttpClient";
|
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||||
|
|
||||||
export default function PluginCardComponent({
|
export default function PluginCardComponent({
|
||||||
cardVO
|
cardVO,
|
||||||
}: {
|
}: {
|
||||||
cardVO: PluginCardVO;
|
cardVO: PluginCardVO;
|
||||||
}) {
|
}) {
|
||||||
@@ -21,7 +21,7 @@ export default function PluginCardComponent({
|
|||||||
setInitialized(!initialized);
|
setInitialized(!initialized);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log("error: ", err);
|
console.log('error: ', err);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
setSwitchEnable(true);
|
setSwitchEnable(true);
|
||||||
@@ -35,7 +35,7 @@ export default function PluginCardComponent({
|
|||||||
<div className={`${styles.fontGray}`}>{cardVO.author}</div>
|
<div className={`${styles.fontGray}`}>{cardVO.author}</div>
|
||||||
{/* right icon & version */}
|
{/* right icon & version */}
|
||||||
<div className={`${styles.iconVersionContainer}`}>
|
<div className={`${styles.iconVersionContainer}`}>
|
||||||
<GithubOutlined style={{ fontSize: "26px" }} type="setting" />
|
<GithubOutlined style={{ fontSize: '26px' }} type="setting" />
|
||||||
<Tag color="#108ee9">v{cardVO.version}</Tag>
|
<Tag color="#108ee9">v{cardVO.version}</Tag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -49,10 +49,10 @@ export default function PluginCardComponent({
|
|||||||
<div className={`${styles.footerContainer}`}>
|
<div className={`${styles.footerContainer}`}>
|
||||||
<div className={`${styles.linkAndToolContainer}`}>
|
<div className={`${styles.linkAndToolContainer}`}>
|
||||||
<div className={`${styles.link}`}>
|
<div className={`${styles.link}`}>
|
||||||
<LinkOutlined style={{ fontSize: "22px" }} />
|
<LinkOutlined style={{ fontSize: '22px' }} />
|
||||||
<span>1</span>
|
<span>1</span>
|
||||||
</div>
|
</div>
|
||||||
<ToolOutlined style={{ fontSize: "22px" }} />
|
<ToolOutlined style={{ fontSize: '22px' }} />
|
||||||
</div>
|
</div>
|
||||||
<div className={`${styles.switchContainer}`}>
|
<div className={`${styles.switchContainer}`}>
|
||||||
<Switch
|
<Switch
|
||||||
|
|||||||
@@ -1,107 +1,122 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react';
|
||||||
import styles from "@/app/home/plugins/plugins.module.css";
|
import styles from '@/app/home/plugins/plugins.module.css';
|
||||||
import { PluginMarketCardVO } from "@/app/home/plugins/plugin-market/plugin-market-card/PluginMarketCardVO";
|
import { PluginMarketCardVO } from '@/app/home/plugins/plugin-market/plugin-market-card/PluginMarketCardVO';
|
||||||
import PluginMarketCardComponent from "@/app/home/plugins/plugin-market/plugin-market-card/PluginMarketCardComponent";
|
import PluginMarketCardComponent from '@/app/home/plugins/plugin-market/plugin-market-card/PluginMarketCardComponent';
|
||||||
import { Input, Pagination } from "antd";
|
import { Input, Pagination } from 'antd';
|
||||||
import { spaceClient } from "@/app/infra/http/HttpClient";
|
import { spaceClient } from '@/app/infra/http/HttpClient';
|
||||||
|
|
||||||
export default function PluginMarketComponent() {
|
export default function PluginMarketComponent() {
|
||||||
const [marketPluginList, setMarketPluginList] = useState<
|
const [marketPluginList, setMarketPluginList] = useState<
|
||||||
PluginMarketCardVO[]
|
PluginMarketCardVO[]
|
||||||
>([]);
|
>([]);
|
||||||
const [totalCount, setTotalCount] = useState(0);
|
const [totalCount, setTotalCount] = useState(0);
|
||||||
const [nowPage, setNowPage] = useState(1);
|
const [nowPage, setNowPage] = useState(1);
|
||||||
const [searchKeyword, setSearchKeyword] = useState("");
|
const [searchKeyword, setSearchKeyword] = useState('');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const pageSize = 10;
|
const pageSize = 10;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initData();
|
initData();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
function initData() {
|
function initData() {
|
||||||
getPluginList();
|
getPluginList();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onInputSearchKeyword(keyword: string) {
|
function onInputSearchKeyword(keyword: string) {
|
||||||
// 这里记得加防抖,暂时没加
|
// 这里记得加防抖,暂时没加
|
||||||
setSearchKeyword(keyword);
|
setSearchKeyword(keyword);
|
||||||
setNowPage(1);
|
setNowPage(1);
|
||||||
getPluginList(1, keyword);
|
getPluginList(1, keyword);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPluginList(
|
function getPluginList(
|
||||||
page: number = nowPage,
|
page: number = nowPage,
|
||||||
keyword: string = searchKeyword
|
keyword: string = searchKeyword,
|
||||||
) {
|
) {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
spaceClient.getMarketPlugins(page, pageSize, keyword).then((res) => {
|
spaceClient
|
||||||
setMarketPluginList(
|
.getMarketPlugins(page, pageSize, keyword)
|
||||||
res.plugins.map(
|
.then((res) => {
|
||||||
(marketPlugin) =>
|
setMarketPluginList(
|
||||||
new PluginMarketCardVO({
|
res.plugins.map(
|
||||||
author: marketPlugin.author,
|
(marketPlugin) =>
|
||||||
description: marketPlugin.description,
|
new PluginMarketCardVO({
|
||||||
githubURL: marketPlugin.repository,
|
author: marketPlugin.author,
|
||||||
name: marketPlugin.name,
|
description: marketPlugin.description,
|
||||||
pluginId: String(marketPlugin.ID),
|
githubURL: marketPlugin.repository,
|
||||||
starCount: marketPlugin.stars,
|
name: marketPlugin.name,
|
||||||
version: "version" in marketPlugin ? String(marketPlugin.version) : "1.0.0", // Default version if not provided
|
pluginId: String(marketPlugin.ID),
|
||||||
})
|
starCount: marketPlugin.stars,
|
||||||
)
|
version:
|
||||||
);
|
'version' in marketPlugin
|
||||||
setTotalCount(res.total);
|
? String(marketPlugin.version)
|
||||||
setLoading(false);
|
: '1.0.0', // Default version if not provided
|
||||||
console.log("market plugins:", res);
|
}),
|
||||||
}).catch(error => {
|
),
|
||||||
console.error("获取插件列表失败:", error);
|
);
|
||||||
setLoading(false);
|
setTotalCount(res.total);
|
||||||
});
|
setLoading(false);
|
||||||
}
|
console.log('market plugins:', res);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('获取插件列表失败:', error);
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function handlePageChange(page: number) {
|
function handlePageChange(page: number) {
|
||||||
setNowPage(page);
|
setNowPage(page);
|
||||||
getPluginList(page);
|
getPluginList(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${styles.marketComponentBody}`}>
|
<div className={`${styles.marketComponentBody}`}>
|
||||||
<Input
|
<Input
|
||||||
style={{
|
style={{
|
||||||
width: '300px',
|
width: '300px',
|
||||||
marginBottom: '10px',
|
marginBottom: '10px',
|
||||||
}}
|
}}
|
||||||
value={searchKeyword}
|
value={searchKeyword}
|
||||||
placeholder="搜索插件"
|
placeholder="搜索插件"
|
||||||
onChange={(e) => onInputSearchKeyword(e.target.value)}
|
onChange={(e) => onInputSearchKeyword(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<div className={`${styles.pluginListContainer}`}>
|
<div className={`${styles.pluginListContainer}`}>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div style={{ textAlign: 'center', padding: '20px' }}>加载中...</div>
|
<div style={{ textAlign: 'center', padding: '20px' }}>加载中...</div>
|
||||||
) : marketPluginList.length === 0 ? (
|
) : marketPluginList.length === 0 ? (
|
||||||
<div style={{ textAlign: 'center', padding: '20px' }}>没有找到匹配的插件</div>
|
<div style={{ textAlign: 'center', padding: '20px' }}>
|
||||||
) : (
|
没有找到匹配的插件
|
||||||
marketPluginList.map((vo, index) => (
|
</div>
|
||||||
<div key={`${vo.pluginId}-${index}`}>
|
) : (
|
||||||
<PluginMarketCardComponent cardVO={vo} />
|
marketPluginList.map((vo, index) => (
|
||||||
</div>
|
<div key={`${vo.pluginId}-${index}`}>
|
||||||
))
|
<PluginMarketCardComponent cardVO={vo} />
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
{totalCount > 0 && (
|
))
|
||||||
<div style={{ display: 'flex', justifyContent: 'center', width: '100%', marginTop: '20px' }}>
|
)}
|
||||||
<Pagination
|
</div>
|
||||||
current={nowPage}
|
{totalCount > 0 && (
|
||||||
total={totalCount}
|
<div
|
||||||
pageSize={pageSize}
|
style={{
|
||||||
onChange={handlePageChange}
|
display: 'flex',
|
||||||
showSizeChanger={false}
|
justifyContent: 'center',
|
||||||
/>
|
width: '100%',
|
||||||
</div>
|
marginTop: '20px',
|
||||||
)}
|
}}
|
||||||
|
>
|
||||||
|
<Pagination
|
||||||
|
current={nowPage}
|
||||||
|
total={totalCount}
|
||||||
|
pageSize={pageSize}
|
||||||
|
onChange={handlePageChange}
|
||||||
|
showSizeChanger={false}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -1,15 +1,15 @@
|
|||||||
import styles from "./pluginMarketCard.module.css";
|
import styles from './pluginMarketCard.module.css';
|
||||||
import { GithubOutlined, StarOutlined } from "@ant-design/icons";
|
import { GithubOutlined, StarOutlined } from '@ant-design/icons';
|
||||||
import { PluginMarketCardVO } from "@/app/home/plugins/plugin-market/plugin-market-card/PluginMarketCardVO";
|
import { PluginMarketCardVO } from '@/app/home/plugins/plugin-market/plugin-market-card/PluginMarketCardVO';
|
||||||
import { Button } from "antd";
|
import { Button } from 'antd';
|
||||||
|
|
||||||
export default function PluginMarketCardComponent({
|
export default function PluginMarketCardComponent({
|
||||||
cardVO
|
cardVO,
|
||||||
}: {
|
}: {
|
||||||
cardVO: PluginMarketCardVO;
|
cardVO: PluginMarketCardVO;
|
||||||
}) {
|
}) {
|
||||||
function handleInstallClick(pluginId: string) {
|
function handleInstallClick(pluginId: string) {
|
||||||
console.log("Install plugin: ", pluginId);
|
console.log('Install plugin: ', pluginId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -19,7 +19,7 @@ export default function PluginMarketCardComponent({
|
|||||||
{/* left author */}
|
{/* left author */}
|
||||||
<div className={`${styles.fontGray}`}>{cardVO.author}</div>
|
<div className={`${styles.fontGray}`}>{cardVO.author}</div>
|
||||||
{/* right icon */}
|
{/* right icon */}
|
||||||
<GithubOutlined style={{ fontSize: "26px" }} type="setting" />
|
<GithubOutlined style={{ fontSize: '26px' }} type="setting" />
|
||||||
</div>
|
</div>
|
||||||
{/* content */}
|
{/* content */}
|
||||||
<div className={`${styles.cardContent}`}>
|
<div className={`${styles.cardContent}`}>
|
||||||
@@ -30,13 +30,13 @@ export default function PluginMarketCardComponent({
|
|||||||
<div className={`${styles.cardFooter}`}>
|
<div className={`${styles.cardFooter}`}>
|
||||||
<div className={`${styles.linkSettingContainer}`}>
|
<div className={`${styles.linkSettingContainer}`}>
|
||||||
<div className={`${styles.link}`}>
|
<div className={`${styles.link}`}>
|
||||||
<StarOutlined style={{ fontSize: "22px" }} />
|
<StarOutlined style={{ fontSize: '22px' }} />
|
||||||
<span style={{ paddingLeft: "5px" }}>{cardVO.starCount}</span>
|
<span style={{ paddingLeft: '5px' }}>{cardVO.starCount}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
size={"small"}
|
size={'small'}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleInstallClick(cardVO.pluginId);
|
handleInstallClick(cardVO.pluginId);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
export interface IPluginMarketCardVO {
|
export interface IPluginMarketCardVO {
|
||||||
pluginId: string;
|
pluginId: string;
|
||||||
author: string,
|
author: string;
|
||||||
name: string,
|
name: string;
|
||||||
description: string,
|
description: string;
|
||||||
starCount: number,
|
starCount: number;
|
||||||
githubURL: string,
|
githubURL: string;
|
||||||
version: string,
|
version: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PluginMarketCardVO implements IPluginMarketCardVO {
|
export class PluginMarketCardVO implements IPluginMarketCardVO {
|
||||||
pluginId: string;
|
pluginId: string;
|
||||||
description: string;
|
description: string;
|
||||||
name: string;
|
name: string;
|
||||||
author: string;
|
author: string;
|
||||||
githubURL: string;
|
githubURL: string;
|
||||||
starCount: number;
|
starCount: number;
|
||||||
version: string;
|
version: string;
|
||||||
|
|
||||||
constructor(prop: IPluginMarketCardVO) {
|
constructor(prop: IPluginMarketCardVO) {
|
||||||
this.description = prop.description
|
this.description = prop.description;
|
||||||
this.name = prop.name
|
this.name = prop.name;
|
||||||
this.author = prop.author
|
this.author = prop.author;
|
||||||
this.githubURL = prop.githubURL
|
this.githubURL = prop.githubURL;
|
||||||
this.starCount = prop.starCount
|
this.starCount = prop.starCount;
|
||||||
this.pluginId = prop.pluginId
|
this.pluginId = prop.pluginId;
|
||||||
this.version = prop.version
|
this.version = prop.version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ export interface ApiRespPipelines {
|
|||||||
pipelines: Pipeline[];
|
pipelines: Pipeline[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface Pipeline {
|
export interface Pipeline {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -203,7 +202,7 @@ export interface MarketPlugin {
|
|||||||
artifacts_path: string;
|
artifacts_path: string;
|
||||||
stars: number;
|
stars: number;
|
||||||
downloads: number;
|
downloads: number;
|
||||||
status: "initialized" | "mounted"; // 可根据实际状态值扩展联合类型
|
status: 'initialized' | 'mounted'; // 可根据实际状态值扩展联合类型
|
||||||
synced_at: string;
|
synced_at: string;
|
||||||
pushed_at: string; // 最后一次代码推送时间
|
pushed_at: string; // 最后一次代码推送时间
|
||||||
}
|
}
|
||||||
@@ -213,24 +212,23 @@ export interface MarketPluginResponse {
|
|||||||
total: number;
|
total: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface GetPipelineConfig {
|
interface GetPipelineConfig {
|
||||||
ai: {
|
ai: {
|
||||||
"dashscope-app-api": {
|
'dashscope-app-api': {
|
||||||
"api-key": string;
|
'api-key': string;
|
||||||
"app-id": string;
|
'app-id': string;
|
||||||
"app-type": "agent" | "workflow";
|
'app-type': 'agent' | 'workflow';
|
||||||
"references-quote"?: string;
|
'references-quote'?: string;
|
||||||
};
|
};
|
||||||
"dify-service-api": {
|
'dify-service-api': {
|
||||||
"api-key": string;
|
'api-key': string;
|
||||||
"app-type": "chat" | "agent" | "workflow";
|
'app-type': 'chat' | 'agent' | 'workflow';
|
||||||
"base-url": string;
|
'base-url': string;
|
||||||
"thinking-convert": "plain" | "original" | "remove";
|
'thinking-convert': 'plain' | 'original' | 'remove';
|
||||||
timeout?: number;
|
timeout?: number;
|
||||||
};
|
};
|
||||||
"local-agent": {
|
'local-agent': {
|
||||||
"max-round": number;
|
'max-round': number;
|
||||||
model: string;
|
model: string;
|
||||||
prompt: Array<{
|
prompt: Array<{
|
||||||
content: string;
|
content: string;
|
||||||
@@ -238,50 +236,50 @@ interface GetPipelineConfig {
|
|||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
runner: {
|
runner: {
|
||||||
runner: "local-agent" | "dify-service-api" | "dashscope-app-api";
|
runner: 'local-agent' | 'dify-service-api' | 'dashscope-app-api';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
output: {
|
output: {
|
||||||
"force-delay": {
|
'force-delay': {
|
||||||
max: number;
|
max: number;
|
||||||
min: number;
|
min: number;
|
||||||
};
|
};
|
||||||
"long-text-processing": {
|
'long-text-processing': {
|
||||||
"font-path": string;
|
'font-path': string;
|
||||||
strategy: "forward" | "image";
|
strategy: 'forward' | 'image';
|
||||||
threshold: number;
|
threshold: number;
|
||||||
};
|
};
|
||||||
misc: {
|
misc: {
|
||||||
"at-sender": boolean;
|
'at-sender': boolean;
|
||||||
"hide-exception": boolean;
|
'hide-exception': boolean;
|
||||||
"quote-origin": boolean;
|
'quote-origin': boolean;
|
||||||
"track-function-calls": boolean;
|
'track-function-calls': boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
safety: {
|
safety: {
|
||||||
"content-filter": {
|
'content-filter': {
|
||||||
"check-sensitive-words": boolean;
|
'check-sensitive-words': boolean;
|
||||||
scope: "all" | "income-msg" | "output-msg";
|
scope: 'all' | 'income-msg' | 'output-msg';
|
||||||
};
|
};
|
||||||
"rate-limit": {
|
'rate-limit': {
|
||||||
limitation: number;
|
limitation: number;
|
||||||
strategy: "drop" | "wait";
|
strategy: 'drop' | 'wait';
|
||||||
"window-length": number;
|
'window-length': number;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
trigger: {
|
trigger: {
|
||||||
"access-control": {
|
'access-control': {
|
||||||
blacklist: string[];
|
blacklist: string[];
|
||||||
mode: "blacklist" | "whitelist";
|
mode: 'blacklist' | 'whitelist';
|
||||||
whitelist: string[];
|
whitelist: string[];
|
||||||
};
|
};
|
||||||
"group-respond-rules": {
|
'group-respond-rules': {
|
||||||
at: boolean;
|
at: boolean;
|
||||||
prefix: string[];
|
prefix: string[];
|
||||||
random: number;
|
random: number;
|
||||||
regexp: string[];
|
regexp: string[];
|
||||||
};
|
};
|
||||||
"ignore-rules": {
|
'ignore-rules': {
|
||||||
prefix: string[];
|
prefix: string[];
|
||||||
regexp: string[];
|
regexp: string[];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
import styles from "./createCartComponent.module.css";
|
import styles from './createCartComponent.module.css';
|
||||||
|
|
||||||
export default function CreateCardComponent({
|
export default function CreateCardComponent({
|
||||||
height,
|
height,
|
||||||
plusSize,
|
plusSize,
|
||||||
onClick,
|
onClick,
|
||||||
}: {
|
}: {
|
||||||
height: number;
|
height: number;
|
||||||
plusSize: number;
|
plusSize: number;
|
||||||
onClick: () => void
|
onClick: () => void;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`${styles.cardContainer} ${styles.createCardContainer} `}
|
className={`${styles.cardContainer} ${styles.createCardContainer} `}
|
||||||
style={{
|
style={{
|
||||||
width: `100%`,
|
width: `100%`,
|
||||||
height: `${height}px`,
|
height: `${height}px`,
|
||||||
fontSize: `${plusSize}px`
|
fontSize: `${plusSize}px`,
|
||||||
}}
|
}}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
+
|
+
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
export interface I18NText {
|
export interface I18NText {
|
||||||
en_US: string;
|
en_US: string;
|
||||||
zh_CN: string;
|
zh_CN: string;
|
||||||
}
|
}
|
||||||
@@ -2,8 +2,8 @@ import axios, {
|
|||||||
AxiosInstance,
|
AxiosInstance,
|
||||||
AxiosRequestConfig,
|
AxiosRequestConfig,
|
||||||
AxiosResponse,
|
AxiosResponse,
|
||||||
AxiosError
|
AxiosError,
|
||||||
} from "axios";
|
} from 'axios';
|
||||||
import {
|
import {
|
||||||
ApiRespProviderRequesters,
|
ApiRespProviderRequesters,
|
||||||
ApiRespProviderRequester,
|
ApiRespProviderRequester,
|
||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
ApiRespProviderLLMModel,
|
ApiRespProviderLLMModel,
|
||||||
LLMModel,
|
LLMModel,
|
||||||
ApiRespPipelines,
|
ApiRespPipelines,
|
||||||
ApiRespPipeline,
|
|
||||||
Pipeline,
|
Pipeline,
|
||||||
ApiRespPlatformAdapters,
|
ApiRespPlatformAdapters,
|
||||||
ApiRespPlatformAdapter,
|
ApiRespPlatformAdapter,
|
||||||
@@ -27,9 +26,10 @@ import {
|
|||||||
ApiRespAsyncTasks,
|
ApiRespAsyncTasks,
|
||||||
ApiRespAsyncTask,
|
ApiRespAsyncTask,
|
||||||
ApiRespUserToken,
|
ApiRespUserToken,
|
||||||
MarketPluginResponse, GetPipelineResponseData
|
MarketPluginResponse,
|
||||||
} from "../api/api-types";
|
GetPipelineResponseData,
|
||||||
import { notification } from "antd";
|
} from '../api/api-types';
|
||||||
|
import { notification } from 'antd';
|
||||||
|
|
||||||
type JSONValue = string | number | boolean | JSONObject | JSONArray | null;
|
type JSONValue = string | number | boolean | JSONObject | JSONArray | null;
|
||||||
interface JSONObject {
|
interface JSONObject {
|
||||||
@@ -60,8 +60,8 @@ class HttpClient {
|
|||||||
baseURL: baseURL || this.getBaseUrl(),
|
baseURL: baseURL || this.getBaseUrl(),
|
||||||
timeout: 15000,
|
timeout: 15000,
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
'Content-Type': 'application/json',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
this.disableToken = disableToken || false;
|
this.disableToken = disableToken || false;
|
||||||
this.initInterceptors();
|
this.initInterceptors();
|
||||||
@@ -69,26 +69,26 @@ class HttpClient {
|
|||||||
|
|
||||||
// 兜底URL,如果使用未配置会走到这里
|
// 兜底URL,如果使用未配置会走到这里
|
||||||
private getBaseUrl(): string {
|
private getBaseUrl(): string {
|
||||||
return "http://localhost:5300";
|
return 'http://localhost:5300';
|
||||||
// NOT IMPLEMENT
|
// NOT IMPLEMENT
|
||||||
if (typeof window === "undefined") {
|
if (typeof window === 'undefined') {
|
||||||
// 服务端环境
|
// 服务端环境
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
// 客户端环境
|
// 客户端环境
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取Session
|
// 获取Session
|
||||||
private async getSession() {
|
private async getSession() {
|
||||||
// NOT IMPLEMENT
|
// NOT IMPLEMENT
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 同步获取Session
|
// 同步获取Session
|
||||||
private getSessionSync() {
|
private getSessionSync() {
|
||||||
// NOT IMPLEMENT
|
// NOT IMPLEMENT
|
||||||
return localStorage.getItem("token");
|
return localStorage.getItem('token');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 拦截器配置
|
// 拦截器配置
|
||||||
@@ -103,14 +103,14 @@ class HttpClient {
|
|||||||
// config.headers.Cookie = cookies().toString()
|
// config.headers.Cookie = cookies().toString()
|
||||||
|
|
||||||
// 客户端添加认证头
|
// 客户端添加认证头
|
||||||
if (typeof window !== "undefined" && !this.disableToken) {
|
if (typeof window !== 'undefined' && !this.disableToken) {
|
||||||
const session = this.getSessionSync();
|
const session = this.getSessionSync();
|
||||||
config.headers.Authorization = `Bearer ${session}`;
|
config.headers.Authorization = `Bearer ${session}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
(error) => Promise.reject(error)
|
(error) => Promise.reject(error),
|
||||||
);
|
);
|
||||||
|
|
||||||
// 响应拦截
|
// 响应拦截
|
||||||
@@ -128,36 +128,36 @@ class HttpClient {
|
|||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 401:
|
case 401:
|
||||||
window.location.href = "/login";
|
window.location.href = '/login';
|
||||||
break;
|
break;
|
||||||
case 403:
|
case 403:
|
||||||
console.error("Permission denied:", errMessage);
|
console.error('Permission denied:', errMessage);
|
||||||
break;
|
break;
|
||||||
case 500:
|
case 500:
|
||||||
// TODO 弹Toast窗
|
// TODO 弹Toast窗
|
||||||
// NOTE: move to component layer for customized message?
|
// NOTE: move to component layer for customized message?
|
||||||
notification.error({
|
notification.error({
|
||||||
message: "服务器错误",
|
message: '服务器错误',
|
||||||
description: errMessage,
|
description: errMessage,
|
||||||
placement: "bottomRight"
|
placement: 'bottomRight',
|
||||||
});
|
});
|
||||||
console.error("Server error:", errMessage);
|
console.error('Server error:', errMessage);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject({
|
return Promise.reject({
|
||||||
code: data?.code || status,
|
code: data?.code || status,
|
||||||
message: errMessage,
|
message: errMessage,
|
||||||
data: data?.data || null
|
data: data?.data || null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject({
|
return Promise.reject({
|
||||||
code: -1,
|
code: -1,
|
||||||
message: error.message || "Network Error",
|
message: error.message || 'Network Error',
|
||||||
data: null
|
data: null,
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,10 +165,10 @@ class HttpClient {
|
|||||||
private convertKeysToCamel(obj: JSONValue): JSONValue {
|
private convertKeysToCamel(obj: JSONValue): JSONValue {
|
||||||
if (Array.isArray(obj)) {
|
if (Array.isArray(obj)) {
|
||||||
return obj.map((v) => this.convertKeysToCamel(v));
|
return obj.map((v) => this.convertKeysToCamel(v));
|
||||||
} else if (obj !== null && typeof obj === "object") {
|
} else if (obj !== null && typeof obj === 'object') {
|
||||||
return Object.keys(obj).reduce((acc, key) => {
|
return Object.keys(obj).reduce((acc, key) => {
|
||||||
const camelKey = key.replace(/_([a-z])/g, (_, letter) =>
|
const camelKey = key.replace(/_([a-z])/g, (_, letter) =>
|
||||||
letter.toUpperCase()
|
letter.toUpperCase(),
|
||||||
);
|
);
|
||||||
acc[camelKey] = this.convertKeysToCamel((obj as JSONObject)[key]);
|
acc[camelKey] = this.convertKeysToCamel((obj as JSONObject)[key]);
|
||||||
return acc;
|
return acc;
|
||||||
@@ -191,7 +191,7 @@ class HttpClient {
|
|||||||
|
|
||||||
private handleError(error: object): never {
|
private handleError(error: object): never {
|
||||||
if (axios.isCancel(error)) {
|
if (axios.isCancel(error)) {
|
||||||
throw { code: -2, message: "Request canceled", data: null };
|
throw { code: -2, message: 'Request canceled', data: null };
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@@ -200,27 +200,27 @@ class HttpClient {
|
|||||||
public get<T = unknown>(
|
public get<T = unknown>(
|
||||||
url: string,
|
url: string,
|
||||||
params?: object,
|
params?: object,
|
||||||
config?: RequestConfig
|
config?: RequestConfig,
|
||||||
) {
|
) {
|
||||||
return this.request<T>({ method: "get", url, params, ...config });
|
return this.request<T>({ method: 'get', url, params, ...config });
|
||||||
}
|
}
|
||||||
|
|
||||||
public post<T = unknown>(url: string, data?: object, config?: RequestConfig) {
|
public post<T = unknown>(url: string, data?: object, config?: RequestConfig) {
|
||||||
return this.request<T>({ method: "post", url, data, ...config });
|
return this.request<T>({ method: 'post', url, data, ...config });
|
||||||
}
|
}
|
||||||
|
|
||||||
public put<T = unknown>(url: string, data?: object, config?: RequestConfig) {
|
public put<T = unknown>(url: string, data?: object, config?: RequestConfig) {
|
||||||
return this.request<T>({ method: "put", url, data, ...config });
|
return this.request<T>({ method: 'put', url, data, ...config });
|
||||||
}
|
}
|
||||||
|
|
||||||
public delete<T = unknown>(url: string, config?: RequestConfig) {
|
public delete<T = unknown>(url: string, config?: RequestConfig) {
|
||||||
return this.request<T>({ method: "delete", url, ...config });
|
return this.request<T>({ method: 'delete', url, ...config });
|
||||||
}
|
}
|
||||||
|
|
||||||
// real api request implementation
|
// real api request implementation
|
||||||
// ============ Provider API ============
|
// ============ Provider API ============
|
||||||
public getProviderRequesters(): Promise<ApiRespProviderRequesters> {
|
public getProviderRequesters(): Promise<ApiRespProviderRequesters> {
|
||||||
return this.get("/api/v1/provider/requesters");
|
return this.get('/api/v1/provider/requesters');
|
||||||
}
|
}
|
||||||
|
|
||||||
public getProviderRequester(name: string): Promise<ApiRespProviderRequester> {
|
public getProviderRequester(name: string): Promise<ApiRespProviderRequester> {
|
||||||
@@ -233,7 +233,7 @@ class HttpClient {
|
|||||||
|
|
||||||
// ============ Provider Model LLM ============
|
// ============ Provider Model LLM ============
|
||||||
public getProviderLLMModels(): Promise<ApiRespProviderLLMModels> {
|
public getProviderLLMModels(): Promise<ApiRespProviderLLMModels> {
|
||||||
return this.get("/api/v1/provider/models/llm");
|
return this.get('/api/v1/provider/models/llm');
|
||||||
}
|
}
|
||||||
|
|
||||||
public getProviderLLMModel(uuid: string): Promise<ApiRespProviderLLMModel> {
|
public getProviderLLMModel(uuid: string): Promise<ApiRespProviderLLMModel> {
|
||||||
@@ -241,7 +241,7 @@ class HttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public createProviderLLMModel(model: LLMModel): Promise<object> {
|
public createProviderLLMModel(model: LLMModel): Promise<object> {
|
||||||
return this.post("/api/v1/provider/models/llm", model);
|
return this.post('/api/v1/provider/models/llm', model);
|
||||||
}
|
}
|
||||||
|
|
||||||
public deleteProviderLLMModel(uuid: string): Promise<object> {
|
public deleteProviderLLMModel(uuid: string): Promise<object> {
|
||||||
@@ -251,11 +251,11 @@ class HttpClient {
|
|||||||
// ============ Pipeline API ============
|
// ============ Pipeline API ============
|
||||||
public getGeneralPipelineMetadata(): Promise<object> {
|
public getGeneralPipelineMetadata(): Promise<object> {
|
||||||
// as designed, this method will be deprecated, and only for developer to check the prefered config schema
|
// as designed, this method will be deprecated, and only for developer to check the prefered config schema
|
||||||
return this.get("/api/v1/pipelines/_/metadata");
|
return this.get('/api/v1/pipelines/_/metadata');
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPipelines(): Promise<ApiRespPipelines> {
|
public getPipelines(): Promise<ApiRespPipelines> {
|
||||||
return this.get("/api/v1/pipelines");
|
return this.get('/api/v1/pipelines');
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPipeline(uuid: string): Promise<GetPipelineResponseData> {
|
public getPipeline(uuid: string): Promise<GetPipelineResponseData> {
|
||||||
@@ -263,7 +263,7 @@ class HttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public createPipeline(pipeline: Pipeline): Promise<object> {
|
public createPipeline(pipeline: Pipeline): Promise<object> {
|
||||||
return this.post("/api/v1/pipelines", pipeline);
|
return this.post('/api/v1/pipelines', pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
public updatePipeline(uuid: string, pipeline: Pipeline): Promise<object> {
|
public updatePipeline(uuid: string, pipeline: Pipeline): Promise<object> {
|
||||||
@@ -276,7 +276,7 @@ class HttpClient {
|
|||||||
|
|
||||||
// ============ Platform API ============
|
// ============ Platform API ============
|
||||||
public getAdapters(): Promise<ApiRespPlatformAdapters> {
|
public getAdapters(): Promise<ApiRespPlatformAdapters> {
|
||||||
return this.get("/api/v1/platform/adapters");
|
return this.get('/api/v1/platform/adapters');
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAdapter(name: string): Promise<ApiRespPlatformAdapter> {
|
public getAdapter(name: string): Promise<ApiRespPlatformAdapter> {
|
||||||
@@ -289,7 +289,7 @@ class HttpClient {
|
|||||||
|
|
||||||
// ============ Platform Bots ============
|
// ============ Platform Bots ============
|
||||||
public getBots(): Promise<ApiRespPlatformBots> {
|
public getBots(): Promise<ApiRespPlatformBots> {
|
||||||
return this.get("/api/v1/platform/bots");
|
return this.get('/api/v1/platform/bots');
|
||||||
}
|
}
|
||||||
|
|
||||||
public getBot(uuid: string): Promise<ApiRespPlatformBot> {
|
public getBot(uuid: string): Promise<ApiRespPlatformBot> {
|
||||||
@@ -297,7 +297,7 @@ class HttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public createBot(bot: Bot): Promise<object> {
|
public createBot(bot: Bot): Promise<object> {
|
||||||
return this.post("/api/v1/platform/bots", bot);
|
return this.post('/api/v1/platform/bots', bot);
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateBot(uuid: string, bot: Bot): Promise<object> {
|
public updateBot(uuid: string, bot: Bot): Promise<object> {
|
||||||
@@ -310,7 +310,7 @@ class HttpClient {
|
|||||||
|
|
||||||
// ============ Plugins API ============
|
// ============ Plugins API ============
|
||||||
public getPlugins(): Promise<ApiRespPlugins> {
|
public getPlugins(): Promise<ApiRespPlugins> {
|
||||||
return this.get("/api/v1/plugins");
|
return this.get('/api/v1/plugins');
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPlugin(author: string, name: string): Promise<ApiRespPlugin> {
|
public getPlugin(author: string, name: string): Promise<ApiRespPlugin> {
|
||||||
@@ -319,7 +319,7 @@ class HttpClient {
|
|||||||
|
|
||||||
public getPluginConfig(
|
public getPluginConfig(
|
||||||
author: string,
|
author: string,
|
||||||
name: string
|
name: string,
|
||||||
): Promise<ApiRespPluginConfig> {
|
): Promise<ApiRespPluginConfig> {
|
||||||
return this.get(`/api/v1/plugins/${author}/${name}/config`);
|
return this.get(`/api/v1/plugins/${author}/${name}/config`);
|
||||||
}
|
}
|
||||||
@@ -327,7 +327,7 @@ class HttpClient {
|
|||||||
public updatePluginConfig(
|
public updatePluginConfig(
|
||||||
author: string,
|
author: string,
|
||||||
name: string,
|
name: string,
|
||||||
config: object
|
config: object,
|
||||||
): Promise<object> {
|
): Promise<object> {
|
||||||
return this.put(`/api/v1/plugins/${author}/${name}/config`, config);
|
return this.put(`/api/v1/plugins/${author}/${name}/config`, config);
|
||||||
}
|
}
|
||||||
@@ -335,20 +335,20 @@ class HttpClient {
|
|||||||
public togglePlugin(
|
public togglePlugin(
|
||||||
author: string,
|
author: string,
|
||||||
name: string,
|
name: string,
|
||||||
target_enabled: boolean
|
target_enabled: boolean,
|
||||||
): Promise<object> {
|
): Promise<object> {
|
||||||
return this.put(`/api/v1/plugins/${author}/${name}/toggle`, {
|
return this.put(`/api/v1/plugins/${author}/${name}/toggle`, {
|
||||||
target_enabled
|
target_enabled,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public reorderPlugins(plugins: PluginReorderElement[]): Promise<object> {
|
public reorderPlugins(plugins: PluginReorderElement[]): Promise<object> {
|
||||||
return this.post("/api/v1/plugins/reorder", plugins);
|
return this.post('/api/v1/plugins/reorder', plugins);
|
||||||
}
|
}
|
||||||
|
|
||||||
public updatePlugin(
|
public updatePlugin(
|
||||||
author: string,
|
author: string,
|
||||||
name: string
|
name: string,
|
||||||
): Promise<AsyncTaskCreatedResp> {
|
): Promise<AsyncTaskCreatedResp> {
|
||||||
return this.post(`/api/v1/plugins/${author}/${name}/update`);
|
return this.post(`/api/v1/plugins/${author}/${name}/update`);
|
||||||
}
|
}
|
||||||
@@ -356,36 +356,36 @@ class HttpClient {
|
|||||||
public getMarketPlugins(
|
public getMarketPlugins(
|
||||||
page: number,
|
page: number,
|
||||||
page_size: number,
|
page_size: number,
|
||||||
query: string
|
query: string,
|
||||||
): Promise<MarketPluginResponse> {
|
): Promise<MarketPluginResponse> {
|
||||||
return this.post(`/api/v1/market/plugins`, {
|
return this.post(`/api/v1/market/plugins`, {
|
||||||
page,
|
page,
|
||||||
page_size,
|
page_size,
|
||||||
query,
|
query,
|
||||||
sort_by: "stars",
|
sort_by: 'stars',
|
||||||
sort_order: "DESC"
|
sort_order: 'DESC',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public installPluginFromGithub(
|
public installPluginFromGithub(
|
||||||
source: string
|
source: string,
|
||||||
): Promise<AsyncTaskCreatedResp> {
|
): Promise<AsyncTaskCreatedResp> {
|
||||||
return this.post("/api/v1/plugins/install/github", { source });
|
return this.post('/api/v1/plugins/install/github', { source });
|
||||||
}
|
}
|
||||||
|
|
||||||
public removePlugin(
|
public removePlugin(
|
||||||
author: string,
|
author: string,
|
||||||
name: string
|
name: string,
|
||||||
): Promise<AsyncTaskCreatedResp> {
|
): Promise<AsyncTaskCreatedResp> {
|
||||||
return this.delete(`/api/v1/plugins/${author}/${name}`);
|
return this.delete(`/api/v1/plugins/${author}/${name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============ System API ============
|
// ============ System API ============
|
||||||
public getSystemInfo(): Promise<ApiRespSystemInfo> {
|
public getSystemInfo(): Promise<ApiRespSystemInfo> {
|
||||||
return this.get("/api/v1/system/info");
|
return this.get('/api/v1/system/info');
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAsyncTasks(): Promise<ApiRespAsyncTasks> {
|
public getAsyncTasks(): Promise<ApiRespAsyncTasks> {
|
||||||
return this.get("/api/v1/system/tasks");
|
return this.get('/api/v1/system/tasks');
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAsyncTask(id: number): Promise<ApiRespAsyncTask> {
|
public getAsyncTask(id: number): Promise<ApiRespAsyncTask> {
|
||||||
@@ -394,23 +394,23 @@ class HttpClient {
|
|||||||
|
|
||||||
// ============ User API ============
|
// ============ User API ============
|
||||||
public checkIfInited(): Promise<{ initialized: boolean }> {
|
public checkIfInited(): Promise<{ initialized: boolean }> {
|
||||||
return this.get("/api/v1/user/init");
|
return this.get('/api/v1/user/init');
|
||||||
}
|
}
|
||||||
|
|
||||||
public initUser(user: string, password: string): Promise<object> {
|
public initUser(user: string, password: string): Promise<object> {
|
||||||
return this.post("/api/v1/user/init", { user, password });
|
return this.post('/api/v1/user/init', { user, password });
|
||||||
}
|
}
|
||||||
|
|
||||||
public authUser(user: string, password: string): Promise<ApiRespUserToken> {
|
public authUser(user: string, password: string): Promise<ApiRespUserToken> {
|
||||||
return this.post("/api/v1/user/auth", { user, password });
|
return this.post('/api/v1/user/auth', { user, password });
|
||||||
}
|
}
|
||||||
|
|
||||||
public checkUserToken(): Promise<ApiRespUserToken> {
|
public checkUserToken(): Promise<ApiRespUserToken> {
|
||||||
return this.get("/api/v1/user/check-token");
|
return this.get('/api/v1/user/check-token');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const httpClient = new HttpClient("https://version-4.langbot.dev");
|
export const httpClient = new HttpClient('https://version-4.langbot.dev');
|
||||||
|
|
||||||
// 临时写法,未来两种Client都继承自HttpClient父类,不允许共享方法
|
// 临时写法,未来两种Client都继承自HttpClient父类,不允许共享方法
|
||||||
export const spaceClient = new HttpClient("https://space.langbot.app");
|
export const spaceClient = new HttpClient('https://space.langbot.app');
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import "./global.css"
|
import './global.css';
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Create Next App",
|
title: 'Create Next App',
|
||||||
description: "Generated by create next app",
|
description: 'Generated by create next app',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
@@ -14,9 +13,7 @@ export default function RootLayout({
|
|||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body className={``}>
|
<body className={``}>{children}</body>
|
||||||
{children}
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import React from "react";
|
import React from 'react';
|
||||||
import { ConfigProvider, theme } from 'antd';
|
import { ConfigProvider, theme } from 'antd';
|
||||||
|
|
||||||
export default function LoginLayout({
|
export default function LoginLayout({
|
||||||
children
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<ConfigProvider
|
<ConfigProvider
|
||||||
theme={{
|
theme={{
|
||||||
token: {
|
token: {
|
||||||
colorPrimary: '#2288ee',
|
colorPrimary: '#2288ee',
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
},
|
},
|
||||||
algorithm: theme.defaultAlgorithm,
|
algorithm: theme.defaultAlgorithm,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ width: '100%', height: '100%' }}>
|
<div style={{ width: '100%', height: '100%' }}>
|
||||||
<main style={{ width: '100%', height: '100%' }}>{children}</main>
|
<main style={{ width: '100%', height: '100%' }}>{children}</main>
|
||||||
</div>
|
</div>
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-23
@@ -1,17 +1,17 @@
|
|||||||
"use client";
|
'use client';
|
||||||
import { Button, Input, Form, Checkbox, Divider } from "antd";
|
import { Button, Input, Form, Checkbox, Divider } from 'antd';
|
||||||
import {
|
import {
|
||||||
GoogleOutlined,
|
GoogleOutlined,
|
||||||
LockOutlined,
|
LockOutlined,
|
||||||
UserOutlined,
|
UserOutlined,
|
||||||
QqOutlined
|
QqOutlined,
|
||||||
} from "@ant-design/icons";
|
} from '@ant-design/icons';
|
||||||
import styles from "./login.module.css";
|
import styles from './login.module.css';
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { httpClient } from "@/app/infra/http/HttpClient";
|
import { httpClient } from '@/app/infra/http/HttpClient';
|
||||||
import "@ant-design/v5-patch-for-react-19";
|
import '@ant-design/v5-patch-for-react-19';
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from 'next/navigation';
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -32,7 +32,7 @@ export default function Home() {
|
|||||||
setIsInitialized(res.initialized);
|
setIsInitialized(res.initialized);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log("error at getIsInitialized: ", err);
|
console.log('error at getIsInitialized: ', err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,10 +48,10 @@ export default function Home() {
|
|||||||
httpClient
|
httpClient
|
||||||
.initUser(username, password)
|
.initUser(username, password)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
console.log("init user success: ", res);
|
console.log('init user success: ', res);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log("init user error: ", err);
|
console.log('init user error: ', err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,12 +59,12 @@ export default function Home() {
|
|||||||
httpClient
|
httpClient
|
||||||
.authUser(username, password)
|
.authUser(username, password)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
localStorage.setItem("token", res.token);
|
localStorage.setItem('token', res.token);
|
||||||
console.log("login success: ", res);
|
console.log('login success: ', res);
|
||||||
router.push("/home");
|
router.push('/home');
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log("login error: ", err);
|
console.log('login error: ', err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,8 +94,8 @@ export default function Home() {
|
|||||||
<Form.Item
|
<Form.Item
|
||||||
name="email"
|
name="email"
|
||||||
rules={[
|
rules={[
|
||||||
{ required: true, message: "请输入邮箱!" },
|
{ required: true, message: '请输入邮箱!' },
|
||||||
{ type: "email", message: "请输入有效的邮箱地址!" }
|
{ type: 'email', message: '请输入有效的邮箱地址!' },
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
@@ -107,7 +107,7 @@ export default function Home() {
|
|||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="password"
|
name="password"
|
||||||
rules={[{ required: true, message: "请输入密码!" }]}
|
rules={[{ required: true, message: '请输入密码!' }]}
|
||||||
>
|
>
|
||||||
<Input.Password
|
<Input.Password
|
||||||
placeholder="输入密码"
|
placeholder="输入密码"
|
||||||
@@ -162,9 +162,9 @@ export default function Home() {
|
|||||||
>
|
>
|
||||||
{isRegisterMode
|
{isRegisterMode
|
||||||
? isInitialized
|
? isInitialized
|
||||||
? "暂不提供注册"
|
? '暂不提供注册'
|
||||||
: "注册"
|
: '注册'
|
||||||
: "登录"}
|
: '登录'}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Divider className={styles.divider}>或</Divider>
|
<Divider className={styles.divider}>或</Divider>
|
||||||
@@ -179,7 +179,7 @@ export default function Home() {
|
|||||||
使用谷歌账号登录
|
使用谷歌账号登录
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ height: "10px" }}></div>
|
<div style={{ height: '10px' }}></div>
|
||||||
<div className={styles.socialLogin}>
|
<div className={styles.socialLogin}>
|
||||||
<Button
|
<Button
|
||||||
className={styles.socialButton}
|
className={styles.socialButton}
|
||||||
|
|||||||
+119
-66
@@ -1,78 +1,131 @@
|
|||||||
"use client";
|
'use client';
|
||||||
|
|
||||||
import { Button, Typography, Space, Layout, Row, Col, Result } from 'antd';
|
import { Button, Typography, Space, Layout, Row, Col, Result } from 'antd';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import Image from 'next/image';
|
|
||||||
|
|
||||||
const { Title, Paragraph } = Typography;
|
const { Title, Paragraph } = Typography;
|
||||||
|
|
||||||
export default function NotFound() {
|
export default function NotFound() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout style={{ minHeight: '100vh', background: 'white' }}>
|
<Layout style={{ minHeight: '100vh', background: 'white' }}>
|
||||||
<Row justify="center" align="middle" style={{ minHeight: '100vh' }}>
|
<Row justify="center" align="middle" style={{ minHeight: '100vh' }}>
|
||||||
<Col xs={22} sm={20} md={18} lg={14} xl={10}>
|
<Col xs={22} sm={20} md={18} lg={14} xl={10}>
|
||||||
<div className="error-container" style={{ width: '100%', padding: '20px 0', textAlign: 'center' }}>
|
<div
|
||||||
<div className="error-card" style={{
|
className="error-container"
|
||||||
display: 'flex',
|
style={{ width: '100%', padding: '20px 0', textAlign: 'center' }}
|
||||||
flexDirection: 'column',
|
>
|
||||||
alignItems: 'center',
|
<div
|
||||||
padding: '24px'
|
className="error-card"
|
||||||
}}>
|
style={{
|
||||||
{/* Ant Design 图标,可以换成 Langbot 的 Logo */}
|
display: 'flex',
|
||||||
<div style={{ marginBottom: '20px', maxWidth: '100%', height: 'auto' }}>
|
flexDirection: 'column',
|
||||||
<Result
|
alignItems: 'center',
|
||||||
status="404"
|
padding: '24px',
|
||||||
title={null}
|
}}
|
||||||
subTitle={null}
|
>
|
||||||
style={{ padding: 0 }}
|
{/* Ant Design 图标,可以换成 Langbot 的 Logo */}
|
||||||
/>
|
<div
|
||||||
</div>
|
style={{
|
||||||
|
marginBottom: '20px',
|
||||||
|
maxWidth: '100%',
|
||||||
|
height: 'auto',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Result
|
||||||
|
status="404"
|
||||||
|
title={null}
|
||||||
|
subTitle={null}
|
||||||
|
style={{ padding: 0 }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="error-text" style={{ textAlign: 'center', marginBottom: '24px' }}>
|
<div
|
||||||
<Title level={1} style={{ margin: '0 0 16px 0', fontSize: '72px', fontWeight: 'bold', color: '#333' }}>
|
className="error-text"
|
||||||
404
|
style={{ textAlign: 'center', marginBottom: '24px' }}
|
||||||
</Title>
|
>
|
||||||
<Title level={3} style={{ margin: '0 0 8px 0', fontWeight: 'normal', color: '#333' }}>
|
<Title
|
||||||
页面不存在
|
level={1}
|
||||||
</Title>
|
style={{
|
||||||
<Paragraph style={{ fontSize: '16px', color: '#666', maxWidth: '450px', margin: '0 auto 32px auto' }}>
|
margin: '0 0 16px 0',
|
||||||
您要查找的页面似乎不存在。请检查您输入的 URL 是否正确,或者返回首页。
|
fontSize: '72px',
|
||||||
</Paragraph>
|
fontWeight: 'bold',
|
||||||
</div>
|
color: '#333',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
404
|
||||||
|
</Title>
|
||||||
|
<Title
|
||||||
|
level={3}
|
||||||
|
style={{
|
||||||
|
margin: '0 0 8px 0',
|
||||||
|
fontWeight: 'normal',
|
||||||
|
color: '#333',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
页面不存在
|
||||||
|
</Title>
|
||||||
|
<Paragraph
|
||||||
|
style={{
|
||||||
|
fontSize: '16px',
|
||||||
|
color: '#666',
|
||||||
|
maxWidth: '450px',
|
||||||
|
margin: '0 auto 32px auto',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
您要查找的页面似乎不存在。请检查您输入的 URL
|
||||||
|
是否正确,或者返回首页。
|
||||||
|
</Paragraph>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="error-button" style={{ marginBottom: '24px' }}>
|
<div className="error-button" style={{ marginBottom: '24px' }}>
|
||||||
<Space>
|
<Space>
|
||||||
<Button type="primary" style={{
|
<Button
|
||||||
backgroundColor: '#2288ee',
|
type="primary"
|
||||||
borderColor: '#2288ee',
|
style={{
|
||||||
borderRadius: '4px',
|
backgroundColor: '#2288ee',
|
||||||
height: '36px',
|
borderColor: '#2288ee',
|
||||||
padding: '0 16px'
|
borderRadius: '4px',
|
||||||
}} onClick={() => router.back()}>
|
height: '36px',
|
||||||
上一级
|
padding: '0 16px',
|
||||||
</Button>
|
}}
|
||||||
<Button style={{
|
onClick={() => router.back()}
|
||||||
borderColor: '#d9d9d9',
|
>
|
||||||
borderRadius: '4px',
|
上一级
|
||||||
height: '36px',
|
</Button>
|
||||||
padding: '0 16px'
|
<Button
|
||||||
}} onClick={() => router.push('/')}>
|
style={{
|
||||||
返回主页
|
borderColor: '#d9d9d9',
|
||||||
</Button>
|
borderRadius: '4px',
|
||||||
</Space>
|
height: '36px',
|
||||||
</div>
|
padding: '0 16px',
|
||||||
|
}}
|
||||||
|
onClick={() => router.push('/')}
|
||||||
|
>
|
||||||
|
返回主页
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="error-support" style={{ textAlign: 'center', marginTop: '16px' }}>
|
<div
|
||||||
<Paragraph style={{ fontSize: '14px', color: '#666' }}>
|
className="error-support"
|
||||||
需要帮助吗?您可以联系 <a href="mailto:support@qq.com" style={{ color: '#000', textDecoration: 'none' }}>support@qq.com</a>
|
style={{ textAlign: 'center', marginTop: '16px' }}
|
||||||
</Paragraph>
|
>
|
||||||
</div>
|
<Paragraph style={{ fontSize: '14px', color: '#666' }}>
|
||||||
</div>
|
需要帮助吗?您可以联系{' '}
|
||||||
</div>
|
<a
|
||||||
</Col>
|
href="mailto:support@qq.com"
|
||||||
</Row>
|
style={{ color: '#000', textDecoration: 'none' }}
|
||||||
</Layout>
|
>
|
||||||
);
|
support@qq.com
|
||||||
|
</a>
|
||||||
|
</Paragraph>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return <div className={``}></div>;
|
||||||
<div className={``}>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user