feat: 三端合一
@@ -21,7 +21,7 @@
|
||||
"plugins": ["react", "@typescript-eslint", "prettier", "unused-imports"],
|
||||
"rules": {
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"prettier/prettier": "error",
|
||||
"prettier/prettier": "off",
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
|
||||
@@ -6,7 +6,7 @@ yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
.next/
|
||||
node_modules
|
||||
dist
|
||||
market_dist
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const srcDir = path.join(__dirname, 'src');
|
||||
|
||||
const filesToDelete = [
|
||||
'package.json',
|
||||
'tsconfig.json',
|
||||
'tsconfig.node.json',
|
||||
'vite.config.ts',
|
||||
'postcss.config.js',
|
||||
'tailwind.config.js',
|
||||
'.eslintrc.cjs',
|
||||
'index.html',
|
||||
'start-vite.js'
|
||||
];
|
||||
|
||||
function walkDirAndClean(dir) {
|
||||
if (!fs.existsSync(dir)) return;
|
||||
|
||||
fs.readdirSync(dir).forEach(f => {
|
||||
let dirPath = path.join(dir, f);
|
||||
try {
|
||||
let stat = fs.statSync(dirPath);
|
||||
if (stat.isDirectory() && f !== 'node_modules') {
|
||||
// If it's a top-level module directory like src/core, src/common
|
||||
if (dir === srcDir) {
|
||||
filesToDelete.forEach(file => {
|
||||
const fileToDelete = path.join(dirPath, file);
|
||||
if (fs.existsSync(fileToDelete)) {
|
||||
fs.unlinkSync(fileToDelete);
|
||||
console.log(`Deleted: ${fileToDelete}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch(e) {}
|
||||
});
|
||||
}
|
||||
|
||||
walkDirAndClean(srcDir);
|
||||
console.log('Cleanup completed!');
|
||||
@@ -0,0 +1,50 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const srcDir = path.join(__dirname, 'src');
|
||||
|
||||
function walkDir(dir, callback) {
|
||||
if (dir.includes('node_modules')) return;
|
||||
fs.readdirSync(dir).forEach(f => {
|
||||
let dirPath = path.join(dir, f);
|
||||
try {
|
||||
let isDirectory = fs.statSync(dirPath).isDirectory();
|
||||
isDirectory ? walkDir(dirPath, callback) : callback(path.join(dir, f));
|
||||
} catch(e) {}
|
||||
});
|
||||
}
|
||||
|
||||
const filesToRename = [];
|
||||
const filesToUpdate = [];
|
||||
|
||||
walkDir(srcDir, (filePath) => {
|
||||
if (filePath.endsWith('.module.css')) {
|
||||
filesToRename.push(filePath);
|
||||
} else if (filePath.endsWith('.tsx') || filePath.endsWith('.ts')) {
|
||||
filesToUpdate.push(filePath);
|
||||
}
|
||||
});
|
||||
|
||||
filesToRename.forEach(oldPath => {
|
||||
const newPath = oldPath.replace(/\.module\.css$/, '.css');
|
||||
|
||||
// Read and remove :global wrappers entirely
|
||||
let content = fs.readFileSync(oldPath, 'utf8');
|
||||
content = content.replace(/:global\(([^)]+)\)/g, '$1'); // replace :global(.foo) with .foo
|
||||
content = content.replace(/:global\s+/g, ''); // replace :global .foo with .foo
|
||||
|
||||
fs.writeFileSync(oldPath, content);
|
||||
fs.renameSync(oldPath, newPath);
|
||||
console.log(`Renamed and cleaned: ${path.basename(oldPath)} -> ${path.basename(newPath)}`);
|
||||
});
|
||||
|
||||
filesToUpdate.forEach(filePath => {
|
||||
let content = fs.readFileSync(filePath, 'utf8');
|
||||
if (content.includes('.module.css')) {
|
||||
content = content.replace(/\.module\.css/g, '.css');
|
||||
fs.writeFileSync(filePath, content);
|
||||
console.log(`Updated imports in: ${path.basename(filePath)}`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Done!');
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "independent"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const rootDir = __dirname;
|
||||
const packagesDir = path.join(rootDir, 'packages');
|
||||
const srcDir = path.join(rootDir, 'src');
|
||||
const appDir = path.join(srcDir, 'app');
|
||||
|
||||
console.log('🚀 开始拆除 Lerna 并迁移至 Next.js...');
|
||||
|
||||
// 1. 创建基础目录
|
||||
if (!fs.existsSync(srcDir)) fs.mkdirSync(srcDir);
|
||||
if (!fs.existsSync(appDir)) fs.mkdirSync(appDir);
|
||||
|
||||
// 2. 读取并合并 package.json
|
||||
const rootPkgPath = path.join(rootDir, 'package.json');
|
||||
const rootPkg = JSON.parse(fs.readFileSync(rootPkgPath, 'utf8'));
|
||||
|
||||
const mergedDeps = { ...rootPkg.dependencies };
|
||||
const mergedDevDeps = { ...rootPkg.devDependencies };
|
||||
|
||||
if (fs.existsSync(packagesDir)) {
|
||||
const packages = fs.readdirSync(packagesDir);
|
||||
for (const pkg of packages) {
|
||||
const pkgPath = path.join(packagesDir, pkg);
|
||||
if (fs.statSync(pkgPath).isDirectory()) {
|
||||
// 合并依赖
|
||||
const childPkgPath = path.join(pkgPath, 'package.json');
|
||||
if (fs.existsSync(childPkgPath)) {
|
||||
const childPkg = JSON.parse(fs.readFileSync(childPkgPath, 'utf8'));
|
||||
Object.assign(mergedDeps, childPkg.dependencies || {});
|
||||
Object.assign(mergedDevDeps, childPkg.devDependencies || {});
|
||||
}
|
||||
// 移动目录到 src 下
|
||||
const destPath = path.join(srcDir, pkg);
|
||||
if (!fs.existsSync(destPath)) {
|
||||
fs.renameSync(pkgPath, destPath);
|
||||
console.log(`📦 已迁移模块: packages/${pkg} -> src/${pkg}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 删除空的 packages 文件夹
|
||||
try { fs.rmdirSync(packagesDir); } catch (e) { console.error('Failed to remove packages dir, skipping', e) }
|
||||
}
|
||||
|
||||
// 3. 清理并更新根 package.json
|
||||
delete rootPkg.workspaces; // 移除 lerna workspaces
|
||||
rootPkg.scripts = {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
};
|
||||
|
||||
// 移除 Vite 和 Lerna 相关依赖
|
||||
const removeDeps = ['lerna', 'vite', '@originjs/vite-plugin-federation', '@vitejs/plugin-react', 'vite-tsconfig-paths'];
|
||||
removeDeps.forEach(dep => {
|
||||
delete mergedDeps[dep];
|
||||
delete mergedDevDeps[dep];
|
||||
});
|
||||
|
||||
// 添加 Next.js 和 React 最新核心依赖 (与 xroute-ui 对齐)
|
||||
mergedDeps['next'] = "15.4.5";
|
||||
mergedDeps['react'] = "19.1.0";
|
||||
mergedDeps['react-dom'] = "19.1.0";
|
||||
mergedDevDeps['@types/react'] = "^19";
|
||||
mergedDevDeps['@types/react-dom'] = "^19";
|
||||
|
||||
rootPkg.dependencies = mergedDeps;
|
||||
rootPkg.devDependencies = mergedDevDeps;
|
||||
|
||||
fs.writeFileSync(rootPkgPath, JSON.stringify(rootPkg, null, 2));
|
||||
console.log('✅ package.json 依赖已合并并重写');
|
||||
|
||||
// 4. 生成 tsconfig.json (配置路径别名)
|
||||
const tsconfigPath = path.join(rootDir, 'tsconfig.json');
|
||||
const tsconfig = {
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
lib: ["dom", "dom.iterable", "esnext"],
|
||||
allowJs: true,
|
||||
skipLibCheck: true,
|
||||
strict: false,
|
||||
noEmit: true,
|
||||
esModuleInterop: true,
|
||||
module: "esnext",
|
||||
moduleResolution: "bundler",
|
||||
resolveJsonModule: true,
|
||||
isolatedModules: true,
|
||||
jsx: "preserve",
|
||||
incremental: true,
|
||||
plugins: [{ name: "next" }],
|
||||
baseUrl: ".",
|
||||
paths: {
|
||||
"@/*": ["src/*"],
|
||||
// 欺骗原有代码,使其能找到拍平后的新路径
|
||||
"@apipark/common/*": ["src/common/src/*"],
|
||||
"@apipark/core/*": ["src/core/src/*"],
|
||||
"@apipark/dashboard/*": ["src/dashboard/src/*"],
|
||||
"@apipark/market/*": ["src/market/src/*"],
|
||||
"@apipark/openApi/*": ["src/openApi/src/*"],
|
||||
"@apipark/systemRunning/*": ["src/systemRunning/src/*"]
|
||||
}
|
||||
},
|
||||
include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
exclude: ["node_modules"]
|
||||
};
|
||||
fs.writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2));
|
||||
console.log('✅ tsconfig.json 别名映射已配置');
|
||||
|
||||
// 5. 创建 Next.js App Router 挂载点
|
||||
const layoutCode = `export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}`;
|
||||
fs.writeFileSync(path.join(appDir, 'layout.tsx'), layoutCode);
|
||||
|
||||
const slugDir = path.join(appDir, '[[...slug]]');
|
||||
if (!fs.existsSync(slugDir)) fs.mkdirSync(slugDir, { recursive: true });
|
||||
|
||||
const pageCode = `"use client";
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
// 动态导入原有的 Vite SPA 根组件,禁用 SSR 避免 window 报错
|
||||
const ApiParkApp = dynamic(() => import('@/core/src/App'), {
|
||||
ssr: false,
|
||||
loading: () => <div style={{ padding: 50 }}>Loading APIPark...</div>
|
||||
});
|
||||
|
||||
export default function Page() {
|
||||
const [mounted, setMounted] = useState(false);
|
||||
useEffect(() => setMounted(true), []);
|
||||
|
||||
if (!mounted) return null;
|
||||
return <ApiParkApp />;
|
||||
}`;
|
||||
fs.writeFileSync(path.join(slugDir, 'page.tsx'), pageCode);
|
||||
|
||||
console.log('✅ Next.js 路由挂载点创建完毕!');
|
||||
console.log('🎉 迁移完成!请执行 pnpm install 重新安装依赖。');
|
||||
@@ -0,0 +1,4 @@
|
||||
/// <reference types="next" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||
@@ -0,0 +1,42 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
images: {
|
||||
disableStaticImages: true,
|
||||
},
|
||||
experimental: {
|
||||
optimizePackageImports: ["@heroui/react"],
|
||||
},
|
||||
transpilePackages: ['@heroui/react', '@heroui/theme', '@ant-design', 'antd', 'rc-util', 'rc-pagination', 'rc-picker', 'rc-tree', 'rc-table'],
|
||||
async rewrites() {
|
||||
return [
|
||||
{
|
||||
source: '/api/v1/:path*',
|
||||
destination: 'http://172.18.166.219:8288/api/v1/:path*', // Proxy to backend
|
||||
},
|
||||
{
|
||||
source: '/api2/v1/:path*',
|
||||
destination: 'http://172.18.166.219:8288/api2/v1/:path*', // Proxy to backend 2
|
||||
}
|
||||
];
|
||||
},
|
||||
webpack: (config) => {
|
||||
config.module.rules.push({
|
||||
test: /\.(svg|png|jpe?g|gif|webp)$/i,
|
||||
type: 'asset/resource',
|
||||
generator: {
|
||||
filename: 'static/media/[name].[hash][ext]'
|
||||
}
|
||||
});
|
||||
|
||||
// 解决一些 Node.js polyfill 在浏览器端缺失的问题
|
||||
config.resolve.fallback = {
|
||||
...config.resolve.fallback,
|
||||
fs: false,
|
||||
path: false,
|
||||
os: false,
|
||||
};
|
||||
return config;
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
||||
@@ -2,20 +2,12 @@
|
||||
"name": "frontend",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"build": "set NODE_OPTIONS=--max-old-space-size=8192 && lerna run build --scope=core --stream --verbose ",
|
||||
"serve": "lerna run preview --parallel",
|
||||
"serve:remotes": "lerna run serve --scope=remote --parallel",
|
||||
"dev": "lerna run dev --scope=core --stream",
|
||||
"stop": "kill-port --port 5000",
|
||||
"scan": "i18next-scanner --config i18next-scanner.config.js",
|
||||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
|
||||
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix && prettier --write ."
|
||||
"dev": "next dev -p 5000",
|
||||
"build": "next build",
|
||||
"start": "next start -p 5000",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
@@ -23,51 +15,88 @@
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^5.2.6",
|
||||
"@ant-design/pro-components": "2.7.19",
|
||||
"@originjs/vite-plugin-federation": "^1.3.3",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@floating-ui/react": "^0.26.24",
|
||||
"@formkit/auto-animate": "^0.8.1",
|
||||
"@heroui/react": "^3.0.3",
|
||||
"@heroui/styles": "^3.0.3",
|
||||
"@heroui/theme": "^2.4.20",
|
||||
"@lexical/code": "^0.17.1",
|
||||
"@lexical/react": "^0.17.1",
|
||||
"@lexical/selection": "^0.17.1",
|
||||
"@lexical/text": "^0.17.1",
|
||||
"@lexical/utils": "^0.17.1",
|
||||
"@modelcontextprotocol/sdk": "^1.9.0",
|
||||
"@mui/icons-material": "^5.15.6",
|
||||
"@mui/lab": "5.0.0-alpha.150",
|
||||
"@mui/material": "5.14.14",
|
||||
"@mui/x-data-grid-pro": "6.18.1",
|
||||
"@rollup/plugin-dynamic-import-vars": "^2.1.2",
|
||||
"@tinymce/tinymce-react": "^4.3.2",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@vitejs/plugin-react": "^4.2.0",
|
||||
"@xyflow/react": "^12.3.6",
|
||||
"ahooks": "^3.8.1",
|
||||
"allotment": "^1.20.0",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"crc": "^4.3.2",
|
||||
"dayjs": "^1.11.10",
|
||||
"dompurify": "^3.1.6",
|
||||
"echarts": "^5.5.0",
|
||||
"echarts-for-react": "^3.0.2",
|
||||
"framer-motion": "^10.16.4",
|
||||
"fs-extra": "^11.2.0",
|
||||
"highlight.js": "^11.9.0",
|
||||
"i18next": "^23.12.2",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"js-base64": "^3.7.5",
|
||||
"lexical": "^0.17.1",
|
||||
"mockjs": "^1.1.0",
|
||||
"next": "15.4.5",
|
||||
"postcss": "^8.4.31",
|
||||
"postcss-import": "^16.1.0",
|
||||
"postcss-nesting": "^12.1.5",
|
||||
"react": "^18.2.0",
|
||||
"rc-picker": "^4.1.1",
|
||||
"react": "19.1.0",
|
||||
"react-ace": "^10.1.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dom": "19.1.0",
|
||||
"react-dropzone": "^14.2.3",
|
||||
"react-hook-form": "^7.49.3",
|
||||
"react-i18next": "^15.0.1",
|
||||
"react-joyride": "^2.8.2",
|
||||
"react-router-dom": "6.20.0",
|
||||
"swagger-ui-react": "^5.17.14",
|
||||
"tailwindcss": "^3.3.5",
|
||||
"uuid": "^9.0.1",
|
||||
"vite-tsconfig-paths": "^4.3.2",
|
||||
"react-json-view": "^1.21.3",
|
||||
"zod": "^3.23.8",
|
||||
"@modelcontextprotocol/sdk": "^1.9.0",
|
||||
"echarts-for-react": "^3.0.2"
|
||||
"react-router-dom": "6.20.0",
|
||||
"react-virtuoso": "^4.7.11",
|
||||
"swagger-ui-react": "^5.17.14",
|
||||
"tailwindcss": "^4.2.1",
|
||||
"tinymce": "^6.8.1",
|
||||
"use-context-selector": "^2.0.0",
|
||||
"uuid": "^9.0.1",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ant-design/cssinjs": "^1.18.2",
|
||||
"@antv/g6": "^4.8.24",
|
||||
"@formily/antd-v5": "^1.2.1",
|
||||
"@formily/core": "^2.2.13",
|
||||
"@formily/react": "^2.2.13",
|
||||
"@formily/reactive": "^2.2.13",
|
||||
"@iconify/react": "^5.0.2",
|
||||
"@monaco-editor/react": "^4.6.0",
|
||||
"@tailwindcss/postcss": "^4.2.1",
|
||||
"lightningcss": "^1.32.0",
|
||||
"@testing-library/jest-dom": "^6.4.5",
|
||||
"@testing-library/react": "^15.0.7",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.10.5",
|
||||
"@types/react": "^18.2.37",
|
||||
"@types/react-dom": "^18.2.15",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"@typescript-eslint/eslint-plugin": "^6.10.0",
|
||||
"@typescript-eslint/parser": "^6.10.0",
|
||||
"@vitejs/plugin-react": "^4.2.0",
|
||||
"antd": "^5.19.4",
|
||||
"babel-jest": "^29.7.0",
|
||||
"eslint": "^8.53.0",
|
||||
@@ -77,22 +106,22 @@
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.4",
|
||||
"eslint-plugin-unused-imports": "^4.1.4",
|
||||
"exceljs": "^4.4.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"i18next-scanner": "^4.5.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"jest-fetch-mock": "^3.0.3",
|
||||
"jsdom": "^24.0.0",
|
||||
"lerna": "^8.1.3",
|
||||
"less": "^4.2.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"monaco-editor": "^0.45.0",
|
||||
"postcss-nested": "^6.0.1",
|
||||
"prettier": "^3.1.1",
|
||||
"react-test-renderer": "^18.3.1",
|
||||
"ts-jest": "^29.1.2",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^5.0.0",
|
||||
"vite-jest": "^0.1.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
{
|
||||
"name": "common",
|
||||
"version": "1.0.0",
|
||||
"description": "Common library for AO Platform",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"test": "node ./__tests__/common.test.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@floating-ui/react": "^0.26.24",
|
||||
"@formkit/auto-animate": "^0.8.1",
|
||||
"@lexical/code": "^0.17.1",
|
||||
"@lexical/react": "^0.17.1",
|
||||
"@lexical/selection": "^0.17.1",
|
||||
"@lexical/text": "^0.17.1",
|
||||
"@lexical/utils": "^0.17.1",
|
||||
"@mui/icons-material": "^5.15.6",
|
||||
"@mui/lab": "5.0.0-alpha.150",
|
||||
"@mui/material": "5.14.14",
|
||||
"@mui/x-data-grid-pro": "6.18.1",
|
||||
"ahooks": "^3.8.1",
|
||||
"allotment": "^1.20.0",
|
||||
"echarts": "^5.5.0",
|
||||
"lexical": "^0.17.1",
|
||||
"mockjs": "^1.1.0",
|
||||
"rc-picker": "^4.1.1",
|
||||
"react-dropzone": "^14.2.3",
|
||||
"react-hook-form": "^7.49.3",
|
||||
"use-context-selector": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@formily/antd-v5": "^1.2.1",
|
||||
"@formily/core": "^2.2.13",
|
||||
"@formily/react": "^2.2.13",
|
||||
"@formily/reactive": "^2.2.13",
|
||||
"@monaco-editor/react": "^4.6.0",
|
||||
"exceljs": "^4.4.0",
|
||||
"monaco-editor": "^0.45.0"
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
export default {
|
||||
plugins: {
|
||||
'postcss-import': {},
|
||||
'tailwindcss/nesting': {},
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@@ -1,26 +0,0 @@
|
||||
import * as monaco from 'monaco-editor'
|
||||
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
|
||||
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
|
||||
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
|
||||
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
|
||||
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
|
||||
|
||||
self.MonacoEnvironment = {
|
||||
getWorker(_, label) {
|
||||
if (label === 'json') {
|
||||
return new jsonWorker()
|
||||
}
|
||||
if (label === 'css' || label === 'scss' || label === 'less') {
|
||||
return new cssWorker()
|
||||
}
|
||||
if (label === 'html' || label === 'handlebars' || label === 'razor') {
|
||||
return new htmlWorker()
|
||||
}
|
||||
if (label === 'typescript' || label === 'javascript') {
|
||||
return new tsWorker()
|
||||
}
|
||||
return new editorWorker()
|
||||
}
|
||||
}
|
||||
|
||||
export { monaco }
|
||||
@@ -1,98 +0,0 @@
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
important:true,
|
||||
content: [
|
||||
`../*/src/**/*.{js,ts,jsx,tsx}`,
|
||||
]
|
||||
,
|
||||
theme: {
|
||||
extend: {
|
||||
width: {
|
||||
INPUT_NORMAL: '100%',
|
||||
// INPUT_NORMAL: '346px',
|
||||
INPUT_LARGE: '508px',
|
||||
GROUP: '240px',
|
||||
SEARCH: '276px',
|
||||
LOG: '254px'
|
||||
},
|
||||
minHeight:{
|
||||
TEXTAREA:'68px'
|
||||
},
|
||||
borderRadius: {
|
||||
DEFAULT: 'var(--border-radius)',
|
||||
SEARCH_RADIUS: '50px'
|
||||
},
|
||||
boxShadow:{
|
||||
SCROLL: '0 2px 2px #0000000d',
|
||||
SCROLL_TOP:' 0 -2px 2px -2px var(--border-color)'
|
||||
},
|
||||
colors: {
|
||||
DISABLE_BG: 'var(--disabled-background-color)',
|
||||
MAIN_TEXT: 'var(--text-color)',
|
||||
MAIN_HOVER_TEXT: 'var(--text-hover-color)',
|
||||
SECOND_TEXT:'var(--disabled-text-color)',
|
||||
MAIN_BG: 'var(--background-color)',
|
||||
MENU_BG:'var(--MENU-BG-COLOR)',
|
||||
'bar-theme': 'var(--bar-background-color)',
|
||||
BORDER: 'var(--border-color)',
|
||||
NAVBAR_BTN_BG: 'var(--item-active-background-color)',
|
||||
MAIN_DISABLED_BG: 'var(--disabled-background-color)',
|
||||
theme: 'var(--primary-color)',
|
||||
DESC_TEXT: 'var(--TITLE_TEXT)',
|
||||
HOVER_BG: 'var(--item-hover-background-color)',
|
||||
guide_cluster: '#ee6760',
|
||||
guide_upstream: '#f9a429',
|
||||
guide_api: '#71d24d',
|
||||
guide_publishApi: '#5884ff',
|
||||
guide_final: '#915bf9',
|
||||
table_text: 'var(--table-text-color)',
|
||||
status_success:'#138913',
|
||||
status_fail:"#ff3b30",
|
||||
status_update:"#03a9f4",
|
||||
status_pending:"#ffa500",
|
||||
status_offline:"#8f8e93",
|
||||
A_HOVER:'var(--button-primary-hover-background-color)'
|
||||
},
|
||||
backgroundImage:{
|
||||
LAYOUT_BG:'linear-gradient(107.97deg, rgba(32,41,117,1) 4.41%,rgba(16,13,27,1) 86.11%)',
|
||||
LAYOUT_BG_DARK:'#fff',
|
||||
},
|
||||
spacing: {
|
||||
mbase: 'var(--FORM_SPAN)',
|
||||
label: '12px', // 选择器和label之间的间距,待删
|
||||
btnbase: 'var(--LAYOUT_MARGIN)', // x方向的间距
|
||||
btnybase: 'var(--LAYOUT_MARGIN)', // y轴方向的间距
|
||||
btnrbase: '20px', // 页面最右侧边距20px
|
||||
formtop: 'var(--FORM_SPAN)',
|
||||
icon: '5px',
|
||||
blockbase: '40px',
|
||||
DEFAULT_BORDER_RADIUS: 'var(--border-radius)',
|
||||
TREE_TITLE:'var(--small-padding) var(--LAYOUT_PADDING);',
|
||||
'navbar-height': 'var(--layout-header-height)',
|
||||
TAG_LEFT:'10px',
|
||||
PAGE_INSIDE_X:'40px',
|
||||
PAGE_INSIDE_T:'30px',
|
||||
PAGE_INSIDE_B:'20px',
|
||||
},
|
||||
borderColor: {
|
||||
'color-base': 'var(--border-color)'
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
function({ addUtilities }) {
|
||||
addUtilities({
|
||||
'.h-calc-100vh-minus-navbar': {
|
||||
height: 'calc(100vh - var(--layout-header-height))',
|
||||
},
|
||||
'.w-calc-100vw-minus-padding-r': {
|
||||
width: 'calc(100% - 40px)',
|
||||
},
|
||||
}, ['responsive', 'hover']);
|
||||
}
|
||||
],
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"paths": {
|
||||
"@common/*": ["./src/*"],
|
||||
"@core/*": ["../core/src/*"],
|
||||
"@market/*": ["../market/src/*"]
|
||||
},
|
||||
},
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import path from 'path'
|
||||
import dynamicImportVars from '@rollup/plugin-dynamic-import-vars'
|
||||
|
||||
export default defineConfig({
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
less: {
|
||||
javascriptEnabled: true
|
||||
}
|
||||
},
|
||||
modules: {
|
||||
localsConvention: 'camelCase',
|
||||
generateScopedName: '[local]_[hash:base64:2]'
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
react(),
|
||||
dynamicImportVars({
|
||||
include: ['src'],
|
||||
exclude: [],
|
||||
warnOnError: false
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
alias: [
|
||||
{ find: /^~/, replacement: '' },
|
||||
{ find: '@common', replacement: path.resolve(__dirname, './src') },
|
||||
{ find: '@market', replacement: path.resolve(__dirname, '/./market/src') },
|
||||
{ find: '@core', replacement: path.resolve(__dirname, '../core/src') }
|
||||
]
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
'/api/v1': {
|
||||
// target: 'http://uat.apikit.com:11204/mockApi/aoplatform/',
|
||||
target: 'http://172.18.166.219:8288/',
|
||||
changeOrigin: true
|
||||
},
|
||||
'/api2/v1': {
|
||||
// target: 'http://uat.apikit.com:11204/mockApi/aoplatform/',
|
||||
target: 'http://172.18.166.219:8288/',
|
||||
changeOrigin: true
|
||||
}
|
||||
}
|
||||
},
|
||||
logLevel: 'info'
|
||||
})
|
||||
@@ -1 +0,0 @@
|
||||
VITE_APP_MODE=openSource
|
||||
@@ -1,18 +0,0 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: { browser: true, es2020: true },
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
],
|
||||
ignorePatterns: ['dist', '.eslintrc.cjs','public','code-snippet','ace-editor'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['react-refresh'],
|
||||
rules: {
|
||||
'react-refresh/only-export-components': [
|
||||
'warn',
|
||||
{ allowConstantExport: true },
|
||||
],
|
||||
},
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head id="head">
|
||||
<meta charset="UTF-8" />
|
||||
<link id="favicon" rel="icon" type="image/svg+xml" href="/frontend/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
</head>
|
||||
<body id="eo-body">
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const eoBody = document.getElementById('eo-body');
|
||||
const favicon = document.getElementById('favicon');
|
||||
|
||||
const createScript = (id, src) => {
|
||||
const script = document.createElement('script');
|
||||
script.id = id;
|
||||
script.async = true;
|
||||
script.src = src;
|
||||
return script;
|
||||
};
|
||||
|
||||
const iconparkApintoSrc = window.location.hostname === 'localhost' ? '/iconpark_apinto.js' : '/frontend/iconpark_apinto.js';
|
||||
const iconparkEolinkSrc = window.location.hostname === 'localhost' ? '/iconpark_eolink.js' : '/frontend/iconpark_eolink.js';
|
||||
const faviconSrc = window.location.hostname === 'localhost' ? '/favicon.ico' : '/frontend/favicon.ico';
|
||||
|
||||
favicon.href = faviconSrc;
|
||||
|
||||
eoBody.appendChild(createScript('iconpark_apinto', iconparkApintoSrc));
|
||||
eoBody.appendChild(createScript('iconpark_eolink', iconparkEolinkSrc));
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "core",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": " vite --mode open --port 5000 --strictPort",
|
||||
"dev:pro": " vite --config ./vite.pro.config.ts --mode pro --port 5000 --strictPort ",
|
||||
"build": "vite build --mode open",
|
||||
"build:pro": "vite --config ./vite.pro.config.ts build --mode pro",
|
||||
"postinstall": "node scripts/moveTinymce.js",
|
||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview --port 5000 --strictPort",
|
||||
"serve": "vite preview --port 5000 --strictPort"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tinymce/tinymce-react": "^4.3.2",
|
||||
"@xyflow/react": "^12.3.6",
|
||||
"fs-extra": "^11.2.0",
|
||||
"highlight.js": "^11.9.0",
|
||||
"tinymce": "^6.8.1"
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
export default {
|
||||
plugins: {
|
||||
'postcss-import': {},
|
||||
'tailwindcss/nesting': {},
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,309 +0,0 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
|
||||
@layer components {
|
||||
.button-bottom-default {
|
||||
@apply border-[0px] border-b-[1px] border-solid border-BORDER;
|
||||
}
|
||||
}
|
||||
|
||||
@tailwind utilities;
|
||||
|
||||
|
||||
#root {
|
||||
width: 100vw;
|
||||
height:100vh;
|
||||
}
|
||||
|
||||
:global.ant-tree-node-content-wrapper{
|
||||
overflow: hidden;
|
||||
}
|
||||
.tree-title-hover{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items:center;
|
||||
.tree-title-span{
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.tree-title-more{
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover .tree-title-more{
|
||||
display: flex;
|
||||
height:22px;
|
||||
width:22px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ant-layout-content.apipark-layout-layout-content{
|
||||
border-radius:10px 0 0 0 ;
|
||||
overflow:hidden;
|
||||
background-color:'transparent'
|
||||
}
|
||||
|
||||
|
||||
.apipark-layout-global-header-collapsed-button{
|
||||
color:hsl(0, 0%, 100%);
|
||||
}
|
||||
|
||||
.apipark-layout-top-nav-header-main{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.apipark-layout-top-nav-header-menu {
|
||||
height:50px;
|
||||
line-height:50px;
|
||||
|
||||
.ant-menu-item.apipark-layout-base-menu-horizontal-menu-item.ant-menu-item-selected::after{
|
||||
border-bottom:2px solid #fff !important;
|
||||
}
|
||||
.ant-menu-item.apipark-layout-base-menu-horizontal-menu-item.ant-menu-item-active:not(.ant-menu-item-selected)::after{
|
||||
border-bottom:2px solid transparent !important;
|
||||
}
|
||||
}
|
||||
.apipark-layout-base-menu-inline-group .ant-menu-item-group-title{
|
||||
color:rgb(255 255 255 / 70%) !important;
|
||||
}
|
||||
.avatar-dom > div{
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
align-items: center;
|
||||
gap:8px;
|
||||
}
|
||||
|
||||
.apipark-layout-layout{
|
||||
|
||||
.apipark-layout-layout-bg-list{
|
||||
background-image: radial-gradient(circle farthest-corner at 450px 350px, #050eb7, #17163e 500px);
|
||||
}
|
||||
.ant-layout-header.apipark-layout-layout-header{
|
||||
backdrop-filter: unset !important;
|
||||
height:var(--layout-header-height);
|
||||
line-height: var(--layout-header-height);
|
||||
background-color: transparent;
|
||||
|
||||
li.apipark-layout-base-menu-horizontal-menu-item{
|
||||
color:rgb(255 255 255 / 70%) !important;
|
||||
|
||||
&.ant-menu-item-selected{
|
||||
color:#fff !important;
|
||||
}
|
||||
&.ant-menu-item-active{
|
||||
color:#fff !important;
|
||||
}
|
||||
}
|
||||
|
||||
li.ant-menu-submenu-horizontal.ant-menu-overflow-item-rest .ant-menu-submenu-title{
|
||||
color:#fff !important;
|
||||
}
|
||||
}
|
||||
.ant-layout-sider.apipark-layout-sider{
|
||||
height:calc(100vh - var(--layout-header-height)) !important;
|
||||
inset-block-start: var(--layout-header-height);
|
||||
|
||||
.ant-menu {
|
||||
.ant-menu-item-group-title{
|
||||
font-size:12px;
|
||||
padding:12px 16px;
|
||||
}
|
||||
|
||||
.ant-menu-item{
|
||||
margin-block:0 !important;
|
||||
}
|
||||
.ant-menu-light:not(.ant-menu-horizontal) .ant-menu-item:not(.ant-menu-item-selected):active{
|
||||
background-color: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.apipark-layout-sider-collapsed-button{
|
||||
display: none;
|
||||
}
|
||||
|
||||
ul.ant-menu.ant-menu-root.ant-menu-inline,
|
||||
ul.ant-menu.ant-menu-root.ant-menu-vertical{
|
||||
> li {
|
||||
color:rgb(255 255 255 / 70%) !important;
|
||||
/* border-radius: 10px;
|
||||
background-color: rgba(255,255,255,0.1) !important;
|
||||
border: 1px solid rgba(255,255,255,0.15); */
|
||||
}
|
||||
> li.ant-menu-item-active {
|
||||
color:#fff !important;
|
||||
}
|
||||
> li.ant-menu-item-selected {
|
||||
background-color: #fff !important;
|
||||
border: 1px solid #fff !important;
|
||||
color:#333 !important;
|
||||
}
|
||||
}
|
||||
ul.apipark-layout-sider-menu .ant-menu-item-group-list{
|
||||
> li {
|
||||
color:rgb(255 255 255 / 70%) !important;
|
||||
}
|
||||
> li:active{
|
||||
background-color: transparent;
|
||||
}
|
||||
> li.ant-menu-item-active {
|
||||
color:#fff !important;
|
||||
}
|
||||
> li.ant-menu-item-selected {
|
||||
background-color: #fff !important;
|
||||
border: 1px solid #fff !important;
|
||||
color:#333 !important;
|
||||
}
|
||||
}
|
||||
.ant-menu-item {
|
||||
height:40px;
|
||||
margin-block:10px;
|
||||
}
|
||||
}
|
||||
.apipark-layout-drawer-sider{
|
||||
background:#17163E;
|
||||
padding-top:20px;
|
||||
.ant-layout-sider.apipark-layout-sider{
|
||||
height: 100% !important;
|
||||
inset-block: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.apipark-layout-layout-container{
|
||||
|
||||
>.ant-layout-header{
|
||||
height:var(--layout-header-height) !important;
|
||||
line-height:var(--layout-header-height) !important;
|
||||
}
|
||||
|
||||
>.apipark-layout-layout-content.apipark-layout-layout-has-header{
|
||||
padding-block:0px;
|
||||
padding-inline:0px;
|
||||
background-color: #fff !important;
|
||||
}
|
||||
}
|
||||
.ant-pro-global-header-header-actions-avatar > div{
|
||||
color:#fff !important;
|
||||
}
|
||||
|
||||
.ant-menu-item-divider.apipark-layout-base-menu-inline-divider{
|
||||
border-color: rgb(255 255 255 / 15%) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.tox-tinymce{
|
||||
border:none !important;
|
||||
}
|
||||
|
||||
a{
|
||||
transition:none !important;
|
||||
}
|
||||
|
||||
.ant-result ant-result-error{
|
||||
background-color: #fff !important;
|
||||
}
|
||||
|
||||
.ant-tabs-tab-btn{
|
||||
display: flex;
|
||||
align-items:center;
|
||||
.ant-tabs-tab-icon{
|
||||
display: inline-flex;
|
||||
align-items:center;
|
||||
}
|
||||
}
|
||||
|
||||
.eo_page_list .ant-pro-table{
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
border:1px solid var(--table-border-color) !important;
|
||||
}
|
||||
|
||||
.swagger-ui{
|
||||
width: 100%;
|
||||
.model-box-control:focus,.models-control:focus, .opblock-summary-control:focus{
|
||||
outline:unset !important;
|
||||
}
|
||||
.information-container{
|
||||
.info{
|
||||
display: none;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.ant-pro-table .ant-popover .ant-popover-inner-content{
|
||||
.ant-form-item{
|
||||
background-color: transparent;
|
||||
border:none;
|
||||
}
|
||||
}
|
||||
.ant-menu .ant-menu-title-content{
|
||||
display:unset !important;
|
||||
}
|
||||
|
||||
|
||||
.ai-setting-svg-container svg{
|
||||
width: 100%;
|
||||
height:100%;
|
||||
display:block;
|
||||
}
|
||||
.ai-service-api-preview .swagger-ui h3.opblock-tag{
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 整个背景容器设置 */
|
||||
.background-container {
|
||||
background: radial-gradient(ellipse 80% 900px at top, rgb(255 255 255 / 10%) 0%, rgb(4 0 71) 30%, rgb(13 17 23) 100%);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
isolate: isolate;
|
||||
}
|
||||
|
||||
/* SVG背景图案 */
|
||||
.background-pattern {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
stroke: rgba(255, 255, 255, 0.1);
|
||||
mask-image: radial-gradient(100% 100% at top right, white, transparent);
|
||||
}
|
||||
|
||||
.login-block{
|
||||
background: rgba(255, 255, 255, 0.1) !important;
|
||||
.login-input{
|
||||
color:#fff !important;
|
||||
background: rgba(255, 255, 255, 0.1) !important;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1) !important;
|
||||
&:hover, &:focus, &.ant-input-status-error, &.ant-input-status-error:hover, &.ant-input-status-error:focus-within{
|
||||
background: rgba(255, 255, 255, 0.2) !important;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2) !important;
|
||||
}
|
||||
}
|
||||
|
||||
input:-webkit-autofill,
|
||||
input:-webkit-autofill:focus {
|
||||
transition: background-color 0s 600000s, color 0s 600000s !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-select-selection-overflow-item:first-child {
|
||||
max-width: calc(100% - 60px);
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
a[disabled]:hover {
|
||||
color: #BBB;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.ant-input-group-addon{
|
||||
height:32px !important;
|
||||
.ant-btn.ant-btn-default{
|
||||
height:32px !important;
|
||||
}
|
||||
}
|
||||
@@ -1,656 +0,0 @@
|
||||
import { App, Button, Card, CascaderProps, Empty, Select } from 'antd'
|
||||
import { $t } from '@common/locales/index.ts'
|
||||
import { Icon } from '@iconify/react/dist/iconify.js'
|
||||
import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react'
|
||||
import ReactJson from 'react-json-view'
|
||||
import { IconButton } from '@common/components/postcat/api/IconButton'
|
||||
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
|
||||
import { useFetch } from '@common/hooks/http'
|
||||
import { useConnection } from './hook/useConnection'
|
||||
import { ClientRequest, Tool, ListToolsResultSchema } from '@modelcontextprotocol/sdk/types.js'
|
||||
import { z } from 'zod'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { ServiceDetailType } from '@market/const/serviceHub/type'
|
||||
import useCopyToClipboard from '@common/hooks/copy'
|
||||
import { useGlobalContext } from '@common/contexts/GlobalStateContext'
|
||||
import { Cascader } from 'antd/lib'
|
||||
|
||||
type ConfigList = {
|
||||
openApi?: {
|
||||
title: string
|
||||
configContent: string
|
||||
apiKeys: string[]
|
||||
}
|
||||
mcp: {
|
||||
title: string
|
||||
configContent: string
|
||||
apiKeys: string[]
|
||||
}
|
||||
}
|
||||
|
||||
type ApiKeyItem = {
|
||||
expired: number
|
||||
id: string
|
||||
name: string
|
||||
value: string
|
||||
}
|
||||
interface Option {
|
||||
value: string
|
||||
label: string
|
||||
children?: Option[]
|
||||
}
|
||||
|
||||
type ServiceApiKeyList = {
|
||||
id: string
|
||||
name: string
|
||||
apikeys: Array<{
|
||||
id: string
|
||||
name: string
|
||||
value: string
|
||||
expired: number
|
||||
}>
|
||||
}
|
||||
|
||||
type ConsumerParamsType = {
|
||||
consumerId: string
|
||||
teamId: string
|
||||
}
|
||||
export interface IntegrationAIContainerRef {
|
||||
getServiceKeysList: () => void;
|
||||
}
|
||||
export interface IntegrationAIContainerProps {
|
||||
type: 'global' | 'service' | 'consumer'
|
||||
handleToolsChange: (value: Tool[]) => void
|
||||
customClassName?: string
|
||||
service?: ServiceDetailType
|
||||
serviceId?: string
|
||||
currentTab?: string
|
||||
openModal?: (type: 'apply') => void
|
||||
consumerParams?: ConsumerParamsType
|
||||
}
|
||||
export const IntegrationAIContainer = forwardRef<IntegrationAIContainerRef, IntegrationAIContainerProps>(
|
||||
({
|
||||
type,
|
||||
handleToolsChange,
|
||||
customClassName,
|
||||
service,
|
||||
serviceId,
|
||||
currentTab,
|
||||
openModal,
|
||||
consumerParams
|
||||
}: IntegrationAIContainerProps, ref) => {
|
||||
/** 当前激活的标签 */
|
||||
const [activeTab, setActiveTab] = useState(type === 'service' ? 'openApi' : 'mcp')
|
||||
/** 弹窗组件 */
|
||||
const { message } = App.useApp()
|
||||
/** 配置内容 */
|
||||
const [configContent, setConfigContent] = useState<string>('')
|
||||
/** 当前选中 API Key */
|
||||
const [apiKey, setApiKey] = useState<string>('')
|
||||
/** API Key 列表 */
|
||||
const [apiKeyList, setApiKeyList] = useState<any[]>([])
|
||||
/** Cascader Key 列表 */
|
||||
const [cascaderKeyList, setCascaderKeyList] = useState<string[]>([])
|
||||
/** MCP 服务器地址 */
|
||||
const [mcpServerUrl, setMcpServerUrl] = useState<string>('')
|
||||
/** 全局状态 */
|
||||
const { state } = useGlobalContext()
|
||||
const navigator = useNavigate()
|
||||
/** 复制组件 */
|
||||
const { copyToClipboard } = useCopyToClipboard()
|
||||
/** 错误提示 */
|
||||
const [errors, setErrors] = useState<Record<string, string | null>>({
|
||||
resources: null,
|
||||
prompts: null,
|
||||
tools: null
|
||||
})
|
||||
/** 标签内容 */
|
||||
const [tabContent, setTabContent] = useState<ConfigList>({
|
||||
mcp: {
|
||||
title: $t('MCP 配置'),
|
||||
configContent: '',
|
||||
apiKeys: []
|
||||
}
|
||||
})
|
||||
/** HTTP 请求 */
|
||||
const { fetchData } = useFetch()
|
||||
|
||||
/**
|
||||
* 初始化标签数据
|
||||
*/
|
||||
const initTabsData = () => {
|
||||
const params: ConfigList = {
|
||||
mcp: {
|
||||
title: $t('MCP 配置'),
|
||||
configContent: service?.mcpAccessConfig || '',
|
||||
apiKeys: []
|
||||
}
|
||||
}
|
||||
if (type === 'service') {
|
||||
params.openApi = {
|
||||
title: $t('Open API 文档'),
|
||||
configContent: service?.openapiAddress || '',
|
||||
apiKeys: []
|
||||
}
|
||||
}
|
||||
setTabContent(params)
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制
|
||||
* @param value
|
||||
* @returns
|
||||
*/
|
||||
const handleCopy = async (value: string): Promise<void> => {
|
||||
if (value) {
|
||||
copyToClipboard(value)
|
||||
message.success($t(RESPONSE_TIPS.copySuccess))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择 API Key
|
||||
* @param value
|
||||
*/
|
||||
const handleSelectChange = (value: string) => {
|
||||
setApiKey(value)
|
||||
}
|
||||
/**
|
||||
* Cascader 选择
|
||||
* @param value
|
||||
*/
|
||||
const handleCascaderChange: CascaderProps<Option>['onChange'] = (value) => {
|
||||
setApiKey(value.at(-1) || '')
|
||||
setCascaderKeyList(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全局 MCP 配置
|
||||
* @returns
|
||||
*/
|
||||
const getGlobalMcpConfig = () => {
|
||||
fetchData<BasicResponse<null>>('global/mcp/config', {
|
||||
method: 'GET'
|
||||
})
|
||||
.then((response) => {
|
||||
const { code, msg, data } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
setTabContent((prevTabContent) => ({
|
||||
...prevTabContent,
|
||||
mcp: {
|
||||
...prevTabContent.mcp,
|
||||
configContent: data.config || ''
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||
}
|
||||
})
|
||||
.catch((errorInfo) => {
|
||||
message.error(errorInfo?.toString() || $t(RESPONSE_TIPS.error))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取消费者 MCP 配置
|
||||
* @returns
|
||||
*/
|
||||
const getConsumerMcpConfig = () => {
|
||||
fetchData<BasicResponse<null>>('app/mcp/config', {
|
||||
method: 'GET',
|
||||
eoParams: { app: consumerParams?.consumerId, team: consumerParams?.teamId }
|
||||
})
|
||||
.then((response) => {
|
||||
const { code, msg, data } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
setTabContent((prevTabContent) => ({
|
||||
...prevTabContent,
|
||||
mcp: {
|
||||
...prevTabContent.mcp,
|
||||
configContent: data.config || ''
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||
}
|
||||
})
|
||||
.catch((errorInfo) => {
|
||||
message.error(errorInfo?.toString() || $t(RESPONSE_TIPS.error))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局 MCP 跳转
|
||||
*/
|
||||
const addKey = () => {
|
||||
navigator('/mcpKey')
|
||||
}
|
||||
|
||||
const dropAuthPage = () => {
|
||||
navigator(`/consumer/${consumerParams?.teamId}/inside/${consumerParams?.consumerId}/authorization`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全局 API Key 列表
|
||||
*/
|
||||
const getGlobalKeysList = () => {
|
||||
fetchData<BasicResponse<null>>('simple/system/apikeys', {
|
||||
method: 'GET'
|
||||
})
|
||||
.then((response) => {
|
||||
const { code, msg, data } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
if (data.apikeys && data.apikeys.length > 0) {
|
||||
setApiKeyList(
|
||||
data.apikeys.map((item: ApiKeyItem) => {
|
||||
return {
|
||||
label: item.name,
|
||||
value: item.value
|
||||
}
|
||||
})
|
||||
)
|
||||
setApiKey(data.apikeys[0].value)
|
||||
}
|
||||
} else {
|
||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||
}
|
||||
})
|
||||
.catch((errorInfo) => {
|
||||
message.error(errorInfo?.toString() || $t(RESPONSE_TIPS.error))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 抛出获取服务 API Key 列表
|
||||
*/
|
||||
useImperativeHandle(ref, () => ({
|
||||
getServiceKeysList
|
||||
}))
|
||||
|
||||
/**
|
||||
* 获取 API Key 列表
|
||||
*/
|
||||
const getServiceKeysList = (consumerId?: string) => {
|
||||
fetchData<BasicResponse<null>>(`my/app/apikeys`, {
|
||||
method: 'GET',
|
||||
eoParams: consumerId ? { app: consumerId } : { service: serviceId }
|
||||
})
|
||||
.then((response) => {
|
||||
const { code, msg, data } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
if (data.apps && data.apps.length > 0) {
|
||||
// 转换数据结构为 Cascader 所需格式
|
||||
const transformedData = data.apps.map((app: ServiceApiKeyList) => ({
|
||||
value: app.id,
|
||||
label: app.name,
|
||||
children: app.apikeys.map((key) => ({
|
||||
...key,
|
||||
label: key.name
|
||||
}))
|
||||
}))
|
||||
setApiKeyList(transformedData)
|
||||
if (data.apps[0].apikeys?.length) {
|
||||
setApiKey(data.apps[0].apikeys[0].value)
|
||||
setCascaderKeyList([data.apps[0].id, data.apps[0].apikeys[0].value])
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((errorInfo) => {
|
||||
message.error(errorInfo?.toString() || $t(RESPONSE_TIPS.error))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除错误提示
|
||||
*/
|
||||
const clearError = (tabKey: keyof typeof errors) => {
|
||||
setErrors((prev) => ({ ...prev, [tabKey]: null }))
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送请求
|
||||
*/
|
||||
const makeRequest = async <T extends z.ZodType>(request: ClientRequest, schema: T, tabKey?: keyof typeof errors) => {
|
||||
try {
|
||||
const response = await makeConnectionRequest(request, schema)
|
||||
if (tabKey !== undefined) {
|
||||
clearError(tabKey)
|
||||
}
|
||||
return response
|
||||
} catch (e) {
|
||||
const errorString = (e as Error).message ?? String(e)
|
||||
if (tabKey !== undefined) {
|
||||
setErrors((prev) => ({
|
||||
...prev,
|
||||
[tabKey]: errorString
|
||||
}))
|
||||
}
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 MCP 的 tools
|
||||
*/
|
||||
const listTools = async () => {
|
||||
const response = await makeRequest(
|
||||
{
|
||||
method: 'tools/list' as const,
|
||||
params: {}
|
||||
},
|
||||
ListToolsResultSchema,
|
||||
'tools'
|
||||
)
|
||||
handleToolsChange(response.tools)
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化连接 mcp
|
||||
*/
|
||||
const {
|
||||
connectionStatus,
|
||||
serverCapabilities,
|
||||
mcpClient,
|
||||
requestHistory,
|
||||
makeRequest: makeConnectionRequest,
|
||||
sendNotification,
|
||||
handleCompletion,
|
||||
completionsSupported,
|
||||
connect: connectMcpServer,
|
||||
disconnect: disconnectMcpServer
|
||||
} = useConnection({
|
||||
transportType: 'sse',
|
||||
sseUrl: '',
|
||||
proxyServerUrl: mcpServerUrl,
|
||||
requestTimeout: 1000
|
||||
})
|
||||
// 使用 useRef 保存最新的连接状态和断开函数
|
||||
const connectionStatusRef = useRef(connectionStatus)
|
||||
const disconnectFnRef = useRef(disconnectMcpServer)
|
||||
|
||||
// 当连接状态或断开函数变化时更新 ref
|
||||
useEffect(() => {
|
||||
connectionStatusRef.current = connectionStatus
|
||||
disconnectFnRef.current = disconnectMcpServer
|
||||
}, [connectionStatus, disconnectMcpServer])
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
const setupComponent = () => {
|
||||
initTabsData()
|
||||
if (type === 'global') {
|
||||
getGlobalMcpConfig()
|
||||
setMcpServerUrl('mcp/global/sse')
|
||||
getGlobalKeysList()
|
||||
} else if (type === 'consumer'){
|
||||
getConsumerMcpConfig()
|
||||
setMcpServerUrl(`mcp/app/${consumerParams?.consumerId}/sse`)
|
||||
getServiceKeysList(consumerParams?.consumerId)
|
||||
} else {
|
||||
service?.basic.enableMcp && setMcpServerUrl(`mcp/service/${serviceId}/sse`)
|
||||
getServiceKeysList()
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
useEffect(() => {
|
||||
setupComponent()
|
||||
}, [service])
|
||||
/**
|
||||
* 初始化标签数据
|
||||
*/
|
||||
useEffect(() => {
|
||||
initTabsData()
|
||||
type === 'global' && getGlobalMcpConfig()
|
||||
type === 'consumer' && getConsumerMcpConfig()
|
||||
}, [state.language])
|
||||
/**
|
||||
* 切换标签
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (type === 'service') {
|
||||
currentTab === 'MCP' ? setActiveTab('mcp') : setActiveTab('openApi')
|
||||
}
|
||||
}, [currentTab])
|
||||
/**
|
||||
* 仅在组件加载时执行初始化逻辑
|
||||
*/
|
||||
useEffect(() => {
|
||||
// 返回清理函数,只会在组件卸载时执行
|
||||
return () => {
|
||||
try {
|
||||
// 使用 ref 中保存的最新函数强制断开连接
|
||||
const disconnectFn = disconnectFnRef.current
|
||||
if (disconnectFn) {
|
||||
disconnectFn()
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('断开连接时出错:', err)
|
||||
}
|
||||
}
|
||||
}, [type])
|
||||
/**
|
||||
* 切换标签时更新配置内容
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (activeTab === 'openApi' && tabContent?.openApi?.configContent) {
|
||||
setConfigContent(tabContent?.openApi?.configContent)
|
||||
} else if (activeTab === 'mcp' && tabContent?.mcp?.configContent) {
|
||||
setConfigContent(tabContent.mcp.configContent?.replace('{your_api_key}', apiKey || '{your_api_key}'))
|
||||
}
|
||||
}, [service, apiKey, activeTab, tabContent])
|
||||
/**
|
||||
* 连接 MCP 服务器
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (mcpServerUrl) {
|
||||
if (connectionStatus === 'connected') {
|
||||
disconnectMcpServer()
|
||||
}
|
||||
connectMcpServer()
|
||||
}
|
||||
}, [mcpServerUrl, ...(type === 'global' || type === 'consumer' ? [state.language] : [])])
|
||||
/**
|
||||
* 获取 MCP tools
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (connectionStatus === 'connected') {
|
||||
listTools()
|
||||
}
|
||||
}, [connectionStatus])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card
|
||||
style={{ borderRadius: '10px' }}
|
||||
className={`w-[400px] h-fit ${customClassName}`}
|
||||
classNames={{
|
||||
body: 'p-[10px]'
|
||||
}}
|
||||
>
|
||||
<p>
|
||||
<Icon
|
||||
icon="icon-park-solid:connection-point-two"
|
||||
className="align-text-bottom mr-[5px]"
|
||||
width="16"
|
||||
height="16"
|
||||
/>
|
||||
{$t('AI 代理集成')}
|
||||
</p>
|
||||
{type === 'service' && service?.basic.enableMcp && (
|
||||
<div className="mt-3 tab-nav flex rounded-md overflow-hidden border border-solid border-[#3D46F2] w-fit">
|
||||
<div
|
||||
className={`tab-item px-5 py-1.5 cursor-pointer text-sm transition-colors ${activeTab === 'openApi' ? 'bg-[#3D46F2] text-white' : 'bg-white text-[#3D46F2]'}`}
|
||||
onClick={() => setActiveTab('openApi')}
|
||||
>
|
||||
Open API
|
||||
</div>
|
||||
<div
|
||||
className={`tab-item px-5 py-1.5 cursor-pointer text-sm transition-colors ${activeTab === 'mcp' ? 'bg-[#3D46F2] text-white' : 'bg-white text-[#3D46F2]'}`}
|
||||
onClick={() => setActiveTab('mcp')}
|
||||
>
|
||||
MCP
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{(type === 'service' || type === 'consumer') && !apiKeyList.length ? (
|
||||
<>
|
||||
<Card
|
||||
style={{ borderRadius: '10px' }}
|
||||
className={`w-full mt-3`}
|
||||
classNames={{
|
||||
body: 'p-[10px]'
|
||||
}}
|
||||
>
|
||||
{
|
||||
type === 'service' ? (
|
||||
<div className="flex flex-col items-center justify-center py-3">
|
||||
<span className="text-[14px] mb-5">{$t('请先订阅该服务')}</span>
|
||||
<Button type="primary" onClick={() => openModal?.('apply')}>
|
||||
{$t('申请')}
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col items-center justify-center py-3">
|
||||
<span className="text-[14px] mb-5">{$t('未配置 API Key')}</span>
|
||||
<Button type="primary" onClick={() => dropAuthPage()}>
|
||||
{$t('配置')}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</Card>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div className="tab-container mt-3">
|
||||
<div className="tab-content font-semibold mt-[10px]">
|
||||
{activeTab === 'openApi' ? tabContent.openApi?.title : tabContent.mcp.title}
|
||||
</div>
|
||||
{/* 标签页内容区域 */}
|
||||
<div className="bg-[#0a0b21] text-white p-4 rounded-md my-2 font-mono text-sm overflow-auto relative">
|
||||
{activeTab === 'mcp' ? (
|
||||
<ReactJson
|
||||
src={
|
||||
configContent
|
||||
? typeof configContent === 'string'
|
||||
? (() => {
|
||||
try {
|
||||
return JSON.parse(configContent)
|
||||
} catch (e) {
|
||||
return {}
|
||||
}
|
||||
})()
|
||||
: configContent
|
||||
: {}
|
||||
}
|
||||
theme="monokai"
|
||||
indentWidth={2}
|
||||
displayDataTypes={false}
|
||||
displayObjectSize={false}
|
||||
name={false}
|
||||
collapsed={false}
|
||||
enableClipboard={false}
|
||||
style={{
|
||||
backgroundColor: 'transparent',
|
||||
wordBreak: 'break-word',
|
||||
whiteSpace: 'normal'
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<pre className="whitespace-pre-wrap break-words">{configContent || ''}</pre>
|
||||
</>
|
||||
)}
|
||||
<IconButton
|
||||
name="copy"
|
||||
onClick={() => handleCopy(configContent)}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: '5px',
|
||||
right: '5px',
|
||||
color: '#999',
|
||||
transition: 'none',
|
||||
'&.MuiButtonBase-root:hover': {
|
||||
background: 'transparent',
|
||||
color: '#3D46F2',
|
||||
transition: 'none'
|
||||
}
|
||||
}}
|
||||
></IconButton>
|
||||
</div>
|
||||
</div>
|
||||
{activeTab === 'mcp' && (
|
||||
<>
|
||||
<div className="tab-content font-semibold my-[10px]">API Key</div>
|
||||
{apiKeyList.length ? (
|
||||
<>
|
||||
{type === 'global' ? (
|
||||
<>
|
||||
<Select
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
value={apiKey}
|
||||
className="w-full"
|
||||
onChange={handleSelectChange}
|
||||
options={apiKeyList}
|
||||
/>
|
||||
<Card
|
||||
style={{ borderRadius: '5px' }}
|
||||
className="w-full mt-[5px] "
|
||||
classNames={{
|
||||
body: 'p-[5px]'
|
||||
}}
|
||||
>
|
||||
<div className="relative h-[25px]">
|
||||
{apiKey}
|
||||
<IconButton
|
||||
name="copy"
|
||||
onClick={() => handleCopy(apiKey)}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: '0px',
|
||||
right: '5px',
|
||||
color: '#999',
|
||||
transition: 'none',
|
||||
'&.MuiButtonBase-root:hover': {
|
||||
background: 'transparent',
|
||||
color: '#3D46F2',
|
||||
transition: 'none'
|
||||
}
|
||||
}}
|
||||
></IconButton>
|
||||
</div>
|
||||
</Card>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Cascader
|
||||
className='w-full'
|
||||
allowClear={false}
|
||||
options={apiKeyList}
|
||||
value={cascaderKeyList}
|
||||
onChange={handleCascaderChange}
|
||||
placeholder={$t('选择 API Key')}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={''}>
|
||||
<Button onClick={addKey} type="primary">
|
||||
{$t('新增 API Key')}
|
||||
</Button>
|
||||
</Empty>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Card>
|
||||
</>
|
||||
)
|
||||
})
|
||||
@@ -1,199 +0,0 @@
|
||||
|
||||
import PageList from "@common/components/aoplatform/PageList.tsx"
|
||||
import {ActionType} from "@ant-design/pro-components";
|
||||
import {FC, useEffect, useMemo, useRef, useState} from "react";
|
||||
import {useLocation, useNavigate} from "react-router-dom";
|
||||
import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx";
|
||||
import {App, Modal} from "antd";
|
||||
import {BasicResponse, DELETE_TIPS, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
|
||||
import { SimpleMemberItem } from "@common/const/type.ts";
|
||||
import {useFetch} from "@common/hooks/http.ts";
|
||||
import { TEAM_TABLE_COLUMNS } from "../../const/team/const.tsx";
|
||||
import { TeamConfigFieldType, TeamConfigHandle, TeamTableListItem } from "../../const/team/type.ts";
|
||||
import { useGlobalContext } from "@common/contexts/GlobalStateContext.tsx";
|
||||
import { checkAccess } from "@common/utils/permission.ts";
|
||||
import TeamConfig from "./TeamConfig.tsx";
|
||||
import InsidePage from "@common/components/aoplatform/InsidePage.tsx";
|
||||
import { $t } from "@common/locales/index.ts";
|
||||
|
||||
const TeamList:FC = ()=>{
|
||||
const [searchWord, setSearchWord] = useState<string>('')
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation()
|
||||
const currentUrl = location.pathname
|
||||
const { setBreadcrumb } = useBreadcrumb()
|
||||
const { modal,message } = App.useApp()
|
||||
const pageListRef = useRef<ActionType>(null);
|
||||
const {fetchData} = useFetch()
|
||||
const [memberValueEnum, setMemberValueEnum] = useState<{[k:string]:{text:string}}>({})
|
||||
const teamConfigRef = useRef<TeamConfigHandle>(null)
|
||||
const {accessData,checkPermission,accessInit, getGlobalAccessData,state} = useGlobalContext()
|
||||
const [curTeam, setCurTeam] = useState<TeamConfigFieldType>({} as TeamConfigFieldType)
|
||||
const [modalVisible, setModalVisible] = useState<boolean>(false)
|
||||
const [modalType, setModalType] = useState<'add'|'edit'>('add')
|
||||
const getTeamList = ()=>{
|
||||
if(!accessInit){
|
||||
getGlobalAccessData()?.then?.(()=>{getTeamList()})
|
||||
return
|
||||
}
|
||||
return fetchData<BasicResponse<{teams:TeamTableListItem}>>(!checkPermission('system.workspace.team.view_all') ? 'teams':'manager/teams',{method:'GET',eoParams:{keyword:searchWord},eoTransformKeys:['create_time','service_num','can_delete']}).then(response=>{
|
||||
const {code,data,msg} = response
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
return {data:data.teams, success: true}
|
||||
}else{
|
||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||
return {data:[], success:false}
|
||||
}
|
||||
}).catch(() => {
|
||||
return {data:[], success:false}
|
||||
})
|
||||
}
|
||||
|
||||
const deleteTeam = (entity:TeamTableListItem)=>{
|
||||
return new Promise((resolve, reject)=>{
|
||||
fetchData<BasicResponse<null>>(`manager/team`,{method:'DELETE',eoParams:{id:entity.id}}).then(response=>{
|
||||
const {code,msg} = response
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
message.success(msg || $t(RESPONSE_TIPS.success))
|
||||
resolve(true)
|
||||
}else{
|
||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||
reject(msg || $t(RESPONSE_TIPS.error))
|
||||
}
|
||||
}).catch((errorInfo)=> reject(errorInfo))
|
||||
})
|
||||
}
|
||||
|
||||
const getMemberList = async ()=>{
|
||||
setMemberValueEnum({})
|
||||
const {code,data,msg} = await fetchData<BasicResponse<{ members: SimpleMemberItem[] }>>('simple/member',{method:'GET'})
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
const tmpValueEnum:{[k:string]:{text:string}} = {}
|
||||
data.members?.forEach((x:SimpleMemberItem)=>{
|
||||
tmpValueEnum[x.name] = {text:x.name}
|
||||
})
|
||||
setMemberValueEnum(tmpValueEnum)
|
||||
}else{
|
||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||
}
|
||||
}
|
||||
|
||||
const manualReloadTable = () => {
|
||||
pageListRef.current?.reload()
|
||||
};
|
||||
|
||||
const openModal = async (type:'add'|'edit'|'delete',entity?:TeamTableListItem)=>{
|
||||
let title:string = ''
|
||||
let content:string | React.ReactNode= ''
|
||||
switch (type){
|
||||
case 'add':{
|
||||
setModalType('add')
|
||||
setModalVisible(true)
|
||||
return;}
|
||||
case 'edit':{
|
||||
message.loading($t(RESPONSE_TIPS.loading))
|
||||
const {code,data,msg} = await fetchData<BasicResponse<{team:TeamConfigFieldType}>>(`manager/team`,{method:'GET',eoParams:{id:entity!.id}})
|
||||
message.destroy()
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
setCurTeam({...data.team,master:data.team.master.id})
|
||||
setModalVisible(true)
|
||||
}else{
|
||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||
return
|
||||
}
|
||||
setModalType('edit')
|
||||
return;}
|
||||
case 'delete':
|
||||
title=$t('删除')
|
||||
content=$t(DELETE_TIPS.default)
|
||||
break;
|
||||
}
|
||||
|
||||
modal.confirm({
|
||||
title,
|
||||
content,
|
||||
onOk:()=>{
|
||||
switch (type){
|
||||
case 'delete':
|
||||
return deleteTeam(entity!).then((res)=>{if(res === true) manualReloadTable()})
|
||||
}
|
||||
},
|
||||
width:600,
|
||||
okText:$t('确认'),
|
||||
okButtonProps:{
|
||||
disabled : !checkAccess( `system.organization.team.${type}`, accessData)
|
||||
},
|
||||
cancelText:$t('取消'),
|
||||
closable:true,
|
||||
icon:<></>,
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setBreadcrumb([
|
||||
{title: $t('团队')}
|
||||
])
|
||||
manualReloadTable()
|
||||
}, [currentUrl]);
|
||||
|
||||
useEffect(()=>{
|
||||
getMemberList()
|
||||
},[])
|
||||
|
||||
const columns = useMemo(()=>{
|
||||
return TEAM_TABLE_COLUMNS.map(x=>{if(x.filters &&((x.dataIndex as string[])?.indexOf('master') !== -1 ) ){x.valueEnum = memberValueEnum} return {...x, title:typeof x.title === 'string' ? $t(x.title as string) : x.title}})
|
||||
},[memberValueEnum,state.language])
|
||||
|
||||
|
||||
return (
|
||||
<InsidePage
|
||||
pageTitle={$t('团队')}
|
||||
description={$t("设置团队和成员,然后你可以在团队内创建服务和消费者、订阅API,成员只能看到所属团队内的服务和消费者。")}
|
||||
showBorder={false}
|
||||
contentClassName=" pr-PAGE_INSIDE_X pb-PAGE_INSIDE_B"
|
||||
>
|
||||
<PageList
|
||||
id="global_team"
|
||||
className="pl-btnbase"
|
||||
ref={pageListRef}
|
||||
columns = {[...columns]}
|
||||
request = {()=>getTeamList()}
|
||||
showPagination={false}
|
||||
addNewBtnTitle={$t('添加团队')}
|
||||
addNewBtnAccess = "system.organization.team.add"
|
||||
searchPlaceholder={$t("输入名称、ID、负责人查找团队")}
|
||||
onAddNewBtnClick={()=>{openModal('add')}}
|
||||
onSearchWordChange={(e)=>{setSearchWord(e.target.value)}}
|
||||
onRowClick={(row:TeamTableListItem)=>(navigate(`../inside/${row.id}/setting`))}
|
||||
/>
|
||||
<Modal
|
||||
title={modalType === 'add' ? $t("添加团队") : $t("配置团队")}
|
||||
open={modalVisible}
|
||||
width={600}
|
||||
destroyOnClose={true}
|
||||
maskClosable={false}
|
||||
afterOpenChange={(open:boolean)=>{
|
||||
if(!open){
|
||||
setModalVisible(false)
|
||||
setCurTeam({} as unknown as TeamConfigFieldType)
|
||||
}
|
||||
}}
|
||||
onCancel={() => {setModalVisible(false)}}
|
||||
okText={$t("确认")}
|
||||
okButtonProps={{disabled : !checkAccess( `system.organization.team.edit`, accessData)}}
|
||||
cancelText={$t('取消')}
|
||||
closable={true}
|
||||
onOk={()=>teamConfigRef.current?.save().then((res)=>{
|
||||
if(res){
|
||||
setModalVisible(false)
|
||||
manualReloadTable()
|
||||
}
|
||||
return res})}
|
||||
>
|
||||
<TeamConfig ref={teamConfigRef} entity={modalType === 'add' ? undefined : curTeam} />
|
||||
</Modal>
|
||||
</InsidePage>
|
||||
)
|
||||
|
||||
}
|
||||
export default TeamList
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
// start-vite.js// start-vite.js
|
||||
import { exec } from 'child_process';
|
||||
|
||||
const viteProcess = exec('pnpm run build');
|
||||
|
||||
viteProcess.stdout.on('data', (data) => {
|
||||
console.log(data.toString());
|
||||
});
|
||||
|
||||
viteProcess.stderr.on('data', (data) => {
|
||||
console.error(data.toString());
|
||||
});
|
||||
|
||||
viteProcess.on('close', (code) => {
|
||||
console.log(`Vite process exited with code ${code}`);
|
||||
});
|
||||
@@ -1,82 +0,0 @@
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
|
||||
export default {
|
||||
important:true,
|
||||
content: [
|
||||
`./index.html`,
|
||||
`../*/src/**/*.{js,ts,jsx,tsx}`,
|
||||
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
width: {
|
||||
INPUT_NORMAL: '100%',
|
||||
// INPUT_NORMAL: '346px',
|
||||
INPUT_LARGE: '508px',
|
||||
GROUP: '240px',
|
||||
SEARCH: '276px',
|
||||
LOG: '254px'
|
||||
},
|
||||
minHeight:{
|
||||
TEXTAREA:'68px'
|
||||
},
|
||||
borderRadius: {
|
||||
DEFAULT: 'var(--border-radius)',
|
||||
SEARCH_RADIUS: '50px'
|
||||
},
|
||||
boxShadow:{
|
||||
SCROLL: '0 2px 2px #0000000d',
|
||||
SCROLL_TOP:' 0 -2px 2px -2px var(--border-color)'
|
||||
},
|
||||
colors: {
|
||||
DISABLE_BG: 'var(--disabled-background-color)',
|
||||
MAIN_TEXT: 'var(--text-color)',
|
||||
MAIN_HOVER_TEXT: 'var(--text-hover-color)',
|
||||
SECOND_TEXT:'var(--disabled-text-color)',
|
||||
MAIN_BG: 'var(--background-color)',
|
||||
MENU_BG:'var(--MENU-BG-COLOR)',
|
||||
'bar-theme': 'var(--bar-background-color)',
|
||||
BORDER: 'var(--border-color)',
|
||||
NAVBAR_BTN_BG: 'var(--item-active-background-color)',
|
||||
MAIN_DISABLED_BG: 'var(--disabled-background-color)',
|
||||
theme: 'var(--primary-color)',
|
||||
DESC_TEXT: 'var(--TITLE_TEXT)',
|
||||
HOVER_BG: 'var(--item-hover-background-color)',
|
||||
guide_cluster: '#ee6760',
|
||||
guide_upstream: '#f9a429',
|
||||
guide_api: '#71d24d',
|
||||
guide_publishApi: '#5884ff',
|
||||
guide_final: '#915bf9',
|
||||
table_text: 'var(--table-text-color)',
|
||||
status_success:'#138913',
|
||||
status_fail:"#ff3b30",
|
||||
status_update:"#03a9f4",
|
||||
status_pending:"#ffa500",
|
||||
status_offline:"#8f8e93",
|
||||
A_HOVER:'var(--button-primary-hover-background-color)'
|
||||
},
|
||||
spacing: {
|
||||
mbase: 'var(--FORM_SPAN)',
|
||||
label: '12px', // 选择器和label之间的间距,待删
|
||||
btnbase: 'var(--LAYOUT_MARGIN)', // x方向的间距
|
||||
btnybase: 'var(--LAYOUT_MARGIN)', // y轴方向的间距
|
||||
btnrbase: '20px', // 页面最右侧边距20px
|
||||
formtop: 'var(--FORM_SPAN)',
|
||||
icon: '5px',
|
||||
blockbase: '40px',
|
||||
DEFAULT_BORDER_RADIUS: 'var(--border-radius)',
|
||||
TREE_TITLE:'var(--small-padding) var(--LAYOUT_PADDING);',
|
||||
},
|
||||
borderColor: {
|
||||
'color-base': 'var(--border-color)'
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [],
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
"typeRoots": ["./node_modules/@types", "../common/src/types"],
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"paths": {
|
||||
"@core/*": ["./src/*"],
|
||||
"@common/*": ["../common/src/*"],
|
||||
"@market/*": ["../market/src/*"],
|
||||
"@dashboard/*": ["../dashboard/src/*"],
|
||||
},
|
||||
},
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../common/src/components/aoplatform/ScrollableSection.tsx", "../common/src/utils/postcat.tsx", "../common/src/utils/curl.ts", "../common/src/components/aoplatform/ResetPsw.tsx", "../common/src/components/aoplatform/SubscribeApprovalModalContent.tsx", "../common/src/components/aoplatform/InsidePageForHub.tsx", "src/components/aoplatform/RenderRoutes.tsx", "../common/src/components/aoplatform/PublishApprovalModalContent.tsx", "../common/src/components/aoplatform/InsidePage.tsx", "../common/src/const/type.ts", "../common/src/components/aoplatform/intelligent-plugin", "../common/src/const/domain"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import path from 'path'
|
||||
import dynamicImportVars from '@rollup/plugin-dynamic-import-vars';
|
||||
import tailwindcss from 'tailwindcss';
|
||||
import autoprefixer from 'autoprefixer';
|
||||
import federation from "@originjs/vite-plugin-federation";
|
||||
|
||||
export default defineConfig({
|
||||
cacheDir: './node_modules/.vite',
|
||||
build:{
|
||||
target: 'esnext',
|
||||
outDir:'../../dist',
|
||||
sourcemap: false,
|
||||
chunkSizeWarningLimit: 50,
|
||||
cacheDir: './node_modules/.vite',
|
||||
rollupOptions: {
|
||||
output: {
|
||||
chunkFileNames: 'assets/eo-[name]-[hash].js',
|
||||
},
|
||||
},
|
||||
},
|
||||
css: {
|
||||
postcss: {
|
||||
plugins: [
|
||||
tailwindcss(path.resolve(__dirname, '../common/tailwind.config.js')),
|
||||
autoprefixer
|
||||
],
|
||||
},
|
||||
preprocessorOptions: {
|
||||
less: {
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
},
|
||||
modules:{
|
||||
localsConvention:"camelCase",
|
||||
generateScopedName:"[local]_[hash:base64:2]"
|
||||
}
|
||||
},
|
||||
plugins: [react(),
|
||||
dynamicImportVars({
|
||||
include:["src"],
|
||||
exclude:[],
|
||||
warnOnError:false
|
||||
}),
|
||||
federation({
|
||||
name:"container",
|
||||
remotes:{
|
||||
remoteApp: 'http://localhost:5001/assets/remoteEntry.js' // 远程项目的URL
|
||||
},
|
||||
shared:[
|
||||
"react",
|
||||
"react-dom",
|
||||
]
|
||||
})
|
||||
|
||||
],
|
||||
resolve: {
|
||||
alias: [
|
||||
{ find: /^~/, replacement: '' },
|
||||
{ find: '@common', replacement: path.resolve(__dirname, '../common/src') },
|
||||
{ find: '@market', replacement: path.resolve(__dirname, '../market/src') },
|
||||
{ find: '@core', replacement: path.resolve(__dirname, './src') },
|
||||
{ find: '@dashboard', replacement: path.resolve(__dirname, '../dashboard/src') },
|
||||
]
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
'/api/v1': {
|
||||
// target: 'http://uat.apikit.com:11204/mockApi/aoplatform/',
|
||||
target: 'http://172.18.166.219:8288/',
|
||||
changeOrigin: true,
|
||||
},
|
||||
'/api2/v1': {
|
||||
// target: 'http://uat.apikit.com:11204/mockApi/aoplatform/',
|
||||
target: 'http://172.18.166.219:8288/',
|
||||
changeOrigin: true,
|
||||
}
|
||||
},
|
||||
open: true
|
||||
},
|
||||
logLevel:'info'
|
||||
})
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"name": "dashboard",
|
||||
"version": "0.0.0",
|
||||
"description": "dashboard for AO Platform",
|
||||
"author": "maggieyyy ",
|
||||
"homepage": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"echarts-for-react": "^3.0.2"
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
export default {
|
||||
plugins: {
|
||||
'postcss-import': {},
|
||||
'tailwindcss/nesting': {},
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
|
||||
export default {
|
||||
important:true,
|
||||
content: [
|
||||
`./index.html`,
|
||||
`../*/src/**/*.{js,ts,jsx,tsx}`,
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
width: {
|
||||
INPUT_NORMAL: '100%',
|
||||
// INPUT_NORMAL: '346px',
|
||||
INPUT_LARGE: '508px',
|
||||
GROUP: '240px',
|
||||
SEARCH: '276px',
|
||||
LOG: '254px'
|
||||
},
|
||||
minHeight:{
|
||||
TEXTAREA:'68px'
|
||||
},
|
||||
borderRadius: {
|
||||
DEFAULT: 'var(--border-radius)',
|
||||
SEARCH_RADIUS: '50px'
|
||||
},
|
||||
boxShadow:{
|
||||
SCROLL: '0 2px 2px #0000000d',
|
||||
SCROLL_TOP:' 0 -2px 2px -2px var(--border-color)'
|
||||
},
|
||||
colors: {
|
||||
DISABLE_BG: 'var(--disabled-background-color)',
|
||||
MAIN_TEXT: 'var(--text-color)',
|
||||
MAIN_HOVER_TEXT: 'var(--text-hover-color)',
|
||||
SECOND_TEXT:'var(--disabled-text-color)',
|
||||
MAIN_BG: 'var(--background-color)',
|
||||
MENU_BG:'var(--MENU-BG-COLOR)',
|
||||
'bar-theme': 'var(--bar-background-color)',
|
||||
BORDER: 'var(--border-color)',
|
||||
NAVBAR_BTN_BG: 'var(--item-active-background-color)',
|
||||
MAIN_DISABLED_BG: 'var(--disabled-background-color)',
|
||||
theme: 'var(--primary-color)',
|
||||
DESC_TEXT: 'var(--TITLE_TEXT)',
|
||||
HOVER_BG: 'var(--item-hover-background-color)',
|
||||
guide_cluster: '#ee6760',
|
||||
guide_upstream: '#f9a429',
|
||||
guide_api: '#71d24d',
|
||||
guide_publishApi: '#5884ff',
|
||||
guide_final: '#915bf9',
|
||||
table_text: 'var(--table-text-color)',
|
||||
status_success:'#138913',
|
||||
status_fail:"#ff3b30",
|
||||
status_update:"#03a9f4",
|
||||
status_pending:"#ffa500",
|
||||
status_offline:"#8f8e93",
|
||||
A_HOVER:'var(--button-primary-hover-background-color)'
|
||||
},
|
||||
spacing: {
|
||||
mbase: 'var(--FORM_SPAN)',
|
||||
label: '12px', // 选择器和label之间的间距,待删
|
||||
btnbase: 'var(--LAYOUT_MARGIN)', // x方向的间距
|
||||
btnybase: 'var(--LAYOUT_MARGIN)', // y轴方向的间距
|
||||
btnrbase: '20px', // 页面最右侧边距20px
|
||||
formtop: 'var(--FORM_SPAN)',
|
||||
icon: '5px',
|
||||
blockbase: '40px',
|
||||
DEFAULT_BORDER_RADIUS: 'var(--border-radius)',
|
||||
TREE_TITLE:'var(--small-padding) var(--LAYOUT_PADDING);'
|
||||
},
|
||||
borderColor: {
|
||||
'color-base': 'var(--border-color)'
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [],
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"paths": {
|
||||
"@common/*": ["../common/src/*"],
|
||||
"@core/*": ["../core/src/*"],
|
||||
"@dashboard/*": ["./src/*"]
|
||||
},
|
||||
},
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/frontend/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>APIPark - 企业API数据开放平台</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
<script src="/frontend/iconpark_eolink.js"></script>
|
||||
<script src="/frontend/iconpark_apinto.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"name": "market",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "service market project",
|
||||
"scripts": {
|
||||
"dev": " vite --port 5000 --strictPort",
|
||||
"build": "vite build",
|
||||
"test": "node ./__tests__/market.test.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"dompurify": "^3.1.6",
|
||||
"react-virtuoso": "^4.7.11"
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
export default {
|
||||
plugins: {
|
||||
'postcss-import': {},
|
||||
'tailwindcss/nesting': {},
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
|
||||
#root {
|
||||
width: 100vw;
|
||||
height:100vh;
|
||||
}
|
||||
|
||||
:global.ant-tree-node-content-wrapper{
|
||||
overflow: hidden;
|
||||
}
|
||||
.tree-title-hover{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items:center;
|
||||
.tree-title-span{
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.tree-title-more{
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover .tree-title-more{
|
||||
display: flex;
|
||||
height:22px;
|
||||
width:22px;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"paths": {
|
||||
"@common/*": ["../common/src/*"],
|
||||
"@core/*": ["../core/src/*"],
|
||||
"@market/*": ["./src/*"]
|
||||
},
|
||||
},
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import path from 'path'
|
||||
import dynamicImportVars from '@rollup/plugin-dynamic-import-vars'
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
outDir: '../../tenant_dist',
|
||||
sourcemap: false,
|
||||
chunkSizeWarningLimit: 50000,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks(id) {
|
||||
if (id.includes('node_modules')) {
|
||||
return id.toString().split('node_modules/')[1].split('/')[0].toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
react(),
|
||||
dynamicImportVars({
|
||||
include: ['src'],
|
||||
exclude: [],
|
||||
warnOnError: false
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
alias: [
|
||||
{ find: /^~/, replacement: '' },
|
||||
{ find: '@market', replacement: path.resolve(__dirname, './src') },
|
||||
{ find: '@common', replacement: path.resolve(__dirname, '../common/src') },
|
||||
{ find: '@core', replacement: path.resolve(__dirname, '../core/src') }
|
||||
]
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
'/api/v1': {
|
||||
// target: 'http://uat.apikit.com:11204/mockApi/aoplatform/',
|
||||
target: 'http://172.18.166.219:8488/',
|
||||
changeOrigin: true
|
||||
},
|
||||
'/api2/v1': {
|
||||
// target: 'http://uat.apikit.com:11204/mockApi/aoplatform/',
|
||||
target: 'http://172.18.166.219:8488/',
|
||||
changeOrigin: true
|
||||
}
|
||||
}
|
||||
},
|
||||
logLevel: 'info'
|
||||
})
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "open-api",
|
||||
"version": "0.0.0",
|
||||
"description": "openApi module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"test": "node ./__tests__/common.test.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"copy-to-clipboard": "^3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
export default {
|
||||
plugins: {
|
||||
'postcss-import': {},
|
||||
'tailwindcss/nesting': {},
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
|
||||
export default {
|
||||
important:true,
|
||||
content: [
|
||||
`./index.html`,
|
||||
`../*/src/**/*.{js,ts,jsx,tsx}`,
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
width: {
|
||||
INPUT_NORMAL: '100%',
|
||||
// INPUT_NORMAL: '346px',
|
||||
INPUT_LARGE: '508px',
|
||||
GROUP: '240px',
|
||||
SEARCH: '276px',
|
||||
LOG: '254px'
|
||||
},
|
||||
minHeight:{
|
||||
TEXTAREA:'68px'
|
||||
},
|
||||
borderRadius: {
|
||||
DEFAULT: 'var(--border-radius)',
|
||||
SEARCH_RADIUS: '50px'
|
||||
},
|
||||
boxShadow:{
|
||||
SCROLL: '0 2px 2px #0000000d',
|
||||
SCROLL_TOP:' 0 -2px 2px -2px var(--border-color)'
|
||||
},
|
||||
colors: {
|
||||
DISABLE_BG: 'var(--disabled-background-color)',
|
||||
MAIN_TEXT: 'var(--text-color)',
|
||||
MAIN_HOVER_TEXT: 'var(--text-hover-color)',
|
||||
SECOND_TEXT:'var(--disabled-text-color)',
|
||||
MAIN_BG: 'var(--background-color)',
|
||||
MENU_BG:'var(--MENU-BG-COLOR)',
|
||||
'bar-theme': 'var(--bar-background-color)',
|
||||
BORDER: 'var(--border-color)',
|
||||
NAVBAR_BTN_BG: 'var(--item-active-background-color)',
|
||||
MAIN_DISABLED_BG: 'var(--disabled-background-color)',
|
||||
theme: 'var(--primary-color)',
|
||||
DESC_TEXT: 'var(--TITLE_TEXT)',
|
||||
HOVER_BG: 'var(--item-hover-background-color)',
|
||||
guide_cluster: '#ee6760',
|
||||
guide_upstream: '#f9a429',
|
||||
guide_api: '#71d24d',
|
||||
guide_publishApi: '#5884ff',
|
||||
guide_final: '#915bf9',
|
||||
table_text: 'var(--table-text-color)',
|
||||
status_success:'#138913',
|
||||
status_fail:"#ff3b30",
|
||||
status_update:"#03a9f4",
|
||||
status_pending:"#ffa500",
|
||||
status_offline:"#8f8e93",
|
||||
A_HOVER:'var(--button-primary-hover-background-color)'
|
||||
},
|
||||
spacing: {
|
||||
mbase: 'var(--FORM_SPAN)',
|
||||
label: '12px', // 选择器和label之间的间距,待删
|
||||
btnbase: 'var(--LAYOUT_MARGIN)', // x方向的间距
|
||||
btnybase: 'var(--LAYOUT_MARGIN)', // y轴方向的间距
|
||||
btnrbase: '20px', // 页面最右侧边距20px
|
||||
formtop: 'var(--FORM_SPAN)',
|
||||
icon: '5px',
|
||||
blockbase: '40px',
|
||||
DEFAULT_BORDER_RADIUS: 'var(--border-radius)',
|
||||
TREE_TITLE:'var(--small-padding) var(--LAYOUT_PADDING);'
|
||||
},
|
||||
borderColor: {
|
||||
'color-base': 'var(--border-color)'
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [],
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"paths": {
|
||||
"@common/*": ["../common/src/*"],
|
||||
"@core/*": ["../core/src/*"],
|
||||
"@openApi/*": ["./src/*"]
|
||||
},
|
||||
},
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"name": "systemrunning",
|
||||
"version": "1.0.0",
|
||||
"description": "> TODO: description",
|
||||
"author": "maggieyyy <61950669+maggieyyy@users.noreply.github.com>",
|
||||
"homepage": "",
|
||||
"license": "ISC"
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
export default {
|
||||
plugins: {
|
||||
'postcss-import': {},
|
||||
'tailwindcss/nesting': {},
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
|
||||
export default {
|
||||
important:true,
|
||||
content: [
|
||||
`./index.html`,
|
||||
`../*/src/**/*.{js,ts,jsx,tsx}`,
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
width: {
|
||||
INPUT_NORMAL: '100%',
|
||||
// INPUT_NORMAL: '346px',
|
||||
INPUT_LARGE: '508px',
|
||||
GROUP: '240px',
|
||||
SEARCH: '276px',
|
||||
LOG: '254px'
|
||||
},
|
||||
minHeight:{
|
||||
TEXTAREA:'68px'
|
||||
},
|
||||
borderRadius: {
|
||||
DEFAULT: 'var(--border-radius)',
|
||||
SEARCH_RADIUS: '50px'
|
||||
},
|
||||
boxShadow:{
|
||||
SCROLL: '0 2px 2px #0000000d',
|
||||
SCROLL_TOP:' 0 -2px 2px -2px var(--border-color)'
|
||||
},
|
||||
colors: {
|
||||
DISABLE_BG: 'var(--disabled-background-color)',
|
||||
MAIN_TEXT: 'var(--text-color)',
|
||||
MAIN_HOVER_TEXT: 'var(--text-hover-color)',
|
||||
SECOND_TEXT:'var(--disabled-text-color)',
|
||||
MAIN_BG: 'var(--background-color)',
|
||||
MENU_BG:'var(--MENU-BG-COLOR)',
|
||||
'bar-theme': 'var(--bar-background-color)',
|
||||
BORDER: 'var(--border-color)',
|
||||
NAVBAR_BTN_BG: 'var(--item-active-background-color)',
|
||||
MAIN_DISABLED_BG: 'var(--disabled-background-color)',
|
||||
theme: 'var(--primary-color)',
|
||||
DESC_TEXT: 'var(--TITLE_TEXT)',
|
||||
HOVER_BG: 'var(--item-hover-background-color)',
|
||||
guide_cluster: '#ee6760',
|
||||
guide_upstream: '#f9a429',
|
||||
guide_api: '#71d24d',
|
||||
guide_publishApi: '#5884ff',
|
||||
guide_final: '#915bf9',
|
||||
table_text: 'var(--table-text-color)',
|
||||
status_success:'#138913',
|
||||
status_fail:"#ff3b30",
|
||||
status_update:"#03a9f4",
|
||||
status_pending:"#ffa500",
|
||||
status_offline:"#8f8e93",
|
||||
A_HOVER:'var(--button-primary-hover-background-color)'
|
||||
},
|
||||
spacing: {
|
||||
mbase: 'var(--FORM_SPAN)',
|
||||
label: '12px', // 选择器和label之间的间距,待删
|
||||
btnbase: 'var(--LAYOUT_MARGIN)', // x方向的间距
|
||||
btnybase: 'var(--LAYOUT_MARGIN)', // y轴方向的间距
|
||||
btnrbase: '20px', // 页面最右侧边距20px
|
||||
formtop: 'var(--FORM_SPAN)',
|
||||
icon: '5px',
|
||||
blockbase: '40px',
|
||||
DEFAULT_BORDER_RADIUS: 'var(--border-radius)',
|
||||
TREE_TITLE:'var(--small-padding) var(--LAYOUT_PADDING);'
|
||||
},
|
||||
borderColor: {
|
||||
'color-base': 'var(--border-color)'
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [],
|
||||
corePlugins: {
|
||||
preflight: false,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"paths": {
|
||||
"@common/*": ["../common/src/*"],
|
||||
"@core/*": ["../core/src/*"],
|
||||
},
|
||||
},
|
||||
"include": ["src", "public/iconpark_eolink.js", "public/iconpark_apinto.js", "../common/src/component/aoplatform/EditableTableWithModal.tsx", "../common/src/components/aoplatform/TreeWithMore.tsx", "../common/src/components/aoplatform/DatePicker.tsx", "../common/src/components/aoplatform/TimeRangeSelector.tsx", "../common/src/components/aoplatform/TimePicker.tsx", "../common/src/components/aoplatform/MemberTransfer.tsx", "../common/src/components/aoplatform/PageList.tsx", "../common/src/components/aoplatform/ErrorBoundary.tsx", "../core/src/pages/serviceCategory/ServiceHubCategoryConfig.tsx"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
'@tailwindcss/postcss': {},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
"use client";
|
||||
|
||||
import dynamic from "next/dynamic";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const ApiParkApp = dynamic(() => import("@/core/src/App"), {
|
||||
ssr: false,
|
||||
loading: () => <div style={{ padding: 50 }}>Loading APIPark...</div>
|
||||
});
|
||||
|
||||
export default function LegacyAppPage() {
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
if (!mounted) return null;
|
||||
|
||||
return <ApiParkApp />;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1,11 @@
|
||||
@import "tailwindcss/theme" layer(theme);
|
||||
@import "tailwindcss/utilities" layer(utilities);
|
||||
@config "../../tailwind.config.js";
|
||||
@import "@heroui/styles";
|
||||
|
||||
/* Avoid reset styles forcing media icons to line-break as block elements. */
|
||||
img,
|
||||
svg {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1,12 @@
|
||||
import '../core/src/App.css';
|
||||
import '../core/src/index.css';
|
||||
import '../market/src/index.css';
|
||||
import './globals.css';
|
||||
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "./_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "../../_legacy/LegacyAppPage";
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
@@ -15,7 +15,7 @@ import { useEffect, useMemo, useState } from 'react'
|
||||
import { Outlet, useLocation, useNavigate } from 'react-router-dom'
|
||||
import LanguageSetting from './LanguageSetting'
|
||||
|
||||
const APP_MODE = import.meta.env.VITE_APP_MODE
|
||||
const APP_MODE = process.env.NEXT_PUBLIC_APP_MODE || 'production'
|
||||
export type MenuItem = Required<MenuProps>['items'][number]
|
||||
|
||||
const themeToken = {
|
||||