feat: 三端合一

This commit is contained in:
lcx
2026-04-29 15:39:28 +08:00
parent abb4963bac
commit 96ad58fe28
538 changed files with 2785 additions and 3396 deletions
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -6,7 +6,7 @@ yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
.next/
node_modules
dist
market_dist
+42
View File
@@ -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!');
+50
View File
@@ -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!');
-7
View File
@@ -1,7 +0,0 @@
{
"packages": [
"packages/*"
],
"version": "independent"
}
+144
View File
@@ -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 重新安装依赖。');
+4
View File
@@ -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.
+42
View File
@@ -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;
+59 -30
View File
@@ -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"
}
}
}
-41
View File
@@ -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: {}
},
}
-4
View File
@@ -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,
},
}
-28
View File
@@ -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"]
}
-49
View File
@@ -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
View File
@@ -1 +0,0 @@
VITE_APP_MODE=openSource
-18
View File
@@ -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 },
],
},
}
-36
View File
@@ -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>
-23
View File
@@ -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"
}
}
-10
View File
@@ -1,10 +0,0 @@
export default {
plugins: {
'postcss-import': {},
'tailwindcss/nesting': {},
tailwindcss: {},
autoprefixer: {}
},
}
-309
View File
@@ -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
-17
View File
@@ -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}`);
});
-82
View File
@@ -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,
},
}
-31
View File
@@ -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" }]
}
-10
View File
@@ -1,10 +0,0 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
-84
View File
@@ -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'
})
-11
View File
@@ -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,
},
}
-29
View File
@@ -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"]
}
-16
View File
@@ -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>
-17
View File
@@ -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: {}
},
}
-30
View File
@@ -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;
}
}
-29
View File
@@ -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"]
}
-52
View File
@@ -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'
})
-15
View File
@@ -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,
},
}
-29
View File
@@ -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"]
}
+5
View File
@@ -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";
+11
View File
@@ -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";
+12
View File
@@ -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";
+1
View File
@@ -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";
+1
View File
@@ -0,0 +1 @@
export { default } from "./_legacy/LegacyAppPage";
+1
View File
@@ -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 = {

Some files were not shown because too many files have changed in this diff Show More