Files
makemd/dashboard/src/.umi/appData.json
wurenzhi 989c4b13a6 feat: 添加@types/jest依赖并优化类型安全
refactor: 重构代码减少any类型使用,增加类型定义
fix: 修复TypeScript编译错误和类型不匹配问题
docs: 更新代码审查修复总结文档
style: 优化代码格式和注释
perf: 添加性能优化工具函数和虚拟滚动组件
test: 完善测试相关配置和类型定义
build: 更新package-lock.json文件
2026-03-20 09:53:25 +08:00

2242 lines
226 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"pkg": {
"name": "dashboard",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "umi dev",
"build": "umi build",
"postinstall": "umi setup",
"setup": "umi setup",
"start": "npm run dev"
},
"dependencies": {
"@ant-design/charts": "^2.6.7",
"@ant-design/icons": "^5.2.6",
"@ant-design/plots": "^2.6.8",
"@antv/g6": "^5.0.51",
"@antv/l7": "^2.25.2",
"@antv/l7-react": "^2.4.3",
"antd": "^5.12.2",
"axios": "^1.13.6",
"moment": "^2.30.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-responsive": "^10.0.1",
"recharts": "^3.8.0",
"umi": "^4.0.0"
},
"devDependencies": {
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"msw": "^2.12.13",
"typescript": "^5.9.3"
}
},
"pkgPath": "D:\\trae_projects\\makemd\\makemd\\dashboard\\package.json",
"plugins": {
"./node_modules/@umijs/core/dist/service/servicePlugin": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "preset",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/core/dist/service/servicePlugin.js",
"id": "./node_modules/@umijs/core/dist/service/servicePlugin",
"key": "servicePlugin",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "register"
},
"@umijs/preset-umi": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "preset",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/index.js",
"id": "@umijs/preset-umi",
"key": "umi",
"config": {},
"time": {
"hooks": {},
"register": 21
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/registerMethods": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/registerMethods.js",
"id": "./node_modules/@umijs/preset-umi/dist/registerMethods",
"key": "registerMethods",
"config": {},
"time": {
"hooks": {
"onStart": [
0
]
},
"register": 5
},
"enableBy": "register"
},
"@umijs/did-you-know": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/did-you-know/dist/plugin.js",
"id": "@umijs/did-you-know",
"key": "umijsDidYouKnow",
"config": {},
"time": {
"hooks": {
"onStart": [
3
]
},
"register": 3
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/404/404": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/404/404.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/404/404",
"key": "404",
"config": {},
"time": {
"hooks": {
"modifyRoutes": [
0
]
},
"register": 0
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/aiDev/aiDev": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/aiDev/aiDev.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/aiDev/aiDev",
"key": "aiDev",
"config": {},
"time": {
"hooks": {},
"register": 4
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/appData/appData": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/appData/appData.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/appData/appData",
"key": "appData",
"config": {},
"time": {
"hooks": {
"modifyAppData": [
25
]
},
"register": 37
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/appData/umiInfo": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/appData/umiInfo.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/appData/umiInfo",
"key": "umiInfo",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/check/check": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/check/check.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/check/check",
"key": "check",
"config": {},
"time": {
"hooks": {
"onCheckConfig": [
0
],
"onCheck": [
0
]
},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/check/babel722": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/check/babel722.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/check/babel722",
"key": "babel722",
"config": {},
"time": {
"hooks": {
"onCheck": [
1
]
},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/codeSplitting/codeSplitting": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/codeSplitting/codeSplitting.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/codeSplitting/codeSplitting",
"key": "codeSplitting",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/configPlugins/configPlugins": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/configPlugins/configPlugins.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/configPlugins/configPlugins",
"key": "configPlugins",
"config": {},
"time": {
"hooks": {
"modifyConfig": [
0
]
},
"register": 16
},
"enableBy": "register"
},
"virtual: config-title": {
"id": "virtual: config-title",
"key": "title",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-styles": {
"id": "virtual: config-styles",
"key": "styles",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-scripts": {
"id": "virtual: config-scripts",
"key": "scripts",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-routes": {
"id": "virtual: config-routes",
"key": "routes",
"config": {
"onChange": "regenerateTmpFiles"
},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-routeLoader": {
"id": "virtual: config-routeLoader",
"key": "routeLoader",
"config": {
"default": {
"moduleType": "esm"
}
},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-reactRouter5Compat": {
"id": "virtual: config-reactRouter5Compat",
"key": "reactRouter5Compat",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-presets": {
"id": "virtual: config-presets",
"key": "presets",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-plugins": {
"id": "virtual: config-plugins",
"key": "plugins",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-npmClient": {
"id": "virtual: config-npmClient",
"key": "npmClient",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-mountElementId": {
"id": "virtual: config-mountElementId",
"key": "mountElementId",
"config": {
"default": "root"
},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-metas": {
"id": "virtual: config-metas",
"key": "metas",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-links": {
"id": "virtual: config-links",
"key": "links",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-historyWithQuery": {
"id": "virtual: config-historyWithQuery",
"key": "historyWithQuery",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-history": {
"id": "virtual: config-history",
"key": "history",
"config": {
"default": {
"type": "browser"
}
},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-headScripts": {
"id": "virtual: config-headScripts",
"key": "headScripts",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-esbuildMinifyIIFE": {
"id": "virtual: config-esbuildMinifyIIFE",
"key": "esbuildMinifyIIFE",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-conventionRoutes": {
"id": "virtual: config-conventionRoutes",
"key": "conventionRoutes",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-conventionLayout": {
"id": "virtual: config-conventionLayout",
"key": "conventionLayout",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-base": {
"id": "virtual: config-base",
"key": "base",
"config": {
"default": "/"
},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-analyze": {
"id": "virtual: config-analyze",
"key": "analyze",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-writeToDisk": {
"id": "virtual: config-writeToDisk",
"key": "writeToDisk",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-transformRuntime": {
"id": "virtual: config-transformRuntime",
"key": "transformRuntime",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-theme": {
"id": "virtual: config-theme",
"key": "theme",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-targets": {
"id": "virtual: config-targets",
"key": "targets",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-svgr": {
"id": "virtual: config-svgr",
"key": "svgr",
"config": {
"default": {}
},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-svgo": {
"id": "virtual: config-svgo",
"key": "svgo",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-stylusLoader": {
"id": "virtual: config-stylusLoader",
"key": "stylusLoader",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-styleLoader": {
"id": "virtual: config-styleLoader",
"key": "styleLoader",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-srcTranspilerOptions": {
"id": "virtual: config-srcTranspilerOptions",
"key": "srcTranspilerOptions",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-srcTranspiler": {
"id": "virtual: config-srcTranspiler",
"key": "srcTranspiler",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-sassLoader": {
"id": "virtual: config-sassLoader",
"key": "sassLoader",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-runtimePublicPath": {
"id": "virtual: config-runtimePublicPath",
"key": "runtimePublicPath",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-purgeCSS": {
"id": "virtual: config-purgeCSS",
"key": "purgeCSS",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-publicPath": {
"id": "virtual: config-publicPath",
"key": "publicPath",
"config": {
"default": "/"
},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-proxy": {
"id": "virtual: config-proxy",
"key": "proxy",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-postcssLoader": {
"id": "virtual: config-postcssLoader",
"key": "postcssLoader",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-outputPath": {
"id": "virtual: config-outputPath",
"key": "outputPath",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-normalCSSLoaderModules": {
"id": "virtual: config-normalCSSLoaderModules",
"key": "normalCSSLoaderModules",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-mfsu": {
"id": "virtual: config-mfsu",
"key": "mfsu",
"config": {
"default": {
"strategy": "eager"
}
},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-mdx": {
"id": "virtual: config-mdx",
"key": "mdx",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-manifest": {
"id": "virtual: config-manifest",
"key": "manifest",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-lessLoader": {
"id": "virtual: config-lessLoader",
"key": "lessLoader",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-jsMinifierOptions": {
"id": "virtual: config-jsMinifierOptions",
"key": "jsMinifierOptions",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-jsMinifier": {
"id": "virtual: config-jsMinifier",
"key": "jsMinifier",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-inlineLimit": {
"id": "virtual: config-inlineLimit",
"key": "inlineLimit",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-ignoreMomentLocale": {
"id": "virtual: config-ignoreMomentLocale",
"key": "ignoreMomentLocale",
"config": {
"default": true
},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-https": {
"id": "virtual: config-https",
"key": "https",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-hash": {
"id": "virtual: config-hash",
"key": "hash",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-forkTSChecker": {
"id": "virtual: config-forkTSChecker",
"key": "forkTSChecker",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-fastRefresh": {
"id": "virtual: config-fastRefresh",
"key": "fastRefresh",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-extraPostCSSPlugins": {
"id": "virtual: config-extraPostCSSPlugins",
"key": "extraPostCSSPlugins",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-extraBabelPresets": {
"id": "virtual: config-extraBabelPresets",
"key": "extraBabelPresets",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-extraBabelPlugins": {
"id": "virtual: config-extraBabelPlugins",
"key": "extraBabelPlugins",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-extraBabelIncludes": {
"id": "virtual: config-extraBabelIncludes",
"key": "extraBabelIncludes",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-externals": {
"id": "virtual: config-externals",
"key": "externals",
"config": {
"default": {}
},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-esm": {
"id": "virtual: config-esm",
"key": "esm",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-devtool": {
"id": "virtual: config-devtool",
"key": "devtool",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-depTranspiler": {
"id": "virtual: config-depTranspiler",
"key": "depTranspiler",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-define": {
"id": "virtual: config-define",
"key": "define",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-deadCode": {
"id": "virtual: config-deadCode",
"key": "deadCode",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-cssPublicPath": {
"id": "virtual: config-cssPublicPath",
"key": "cssPublicPath",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-cssMinifierOptions": {
"id": "virtual: config-cssMinifierOptions",
"key": "cssMinifierOptions",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-cssMinifier": {
"id": "virtual: config-cssMinifier",
"key": "cssMinifier",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-cssLoaderModules": {
"id": "virtual: config-cssLoaderModules",
"key": "cssLoaderModules",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-cssLoader": {
"id": "virtual: config-cssLoader",
"key": "cssLoader",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-copy": {
"id": "virtual: config-copy",
"key": "copy",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-checkDepCssModules": {
"id": "virtual: config-checkDepCssModules",
"key": "checkDepCssModules",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-chainWebpack": {
"id": "virtual: config-chainWebpack",
"key": "chainWebpack",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-cacheDirectoryPath": {
"id": "virtual: config-cacheDirectoryPath",
"key": "cacheDirectoryPath",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-babelLoaderCustomize": {
"id": "virtual: config-babelLoaderCustomize",
"key": "babelLoaderCustomize",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-autoprefixer": {
"id": "virtual: config-autoprefixer",
"key": "autoprefixer",
"config": {},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-autoCSSModules": {
"id": "virtual: config-autoCSSModules",
"key": "autoCSSModules",
"config": {
"default": true
},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"virtual: config-alias": {
"id": "virtual: config-alias",
"key": "alias",
"config": {
"default": {
"umi": "@@/exports",
"react": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react",
"react-dom": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-dom",
"react-router": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-router",
"react-router-dom": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-router-dom"
}
},
"type": "plugin",
"enableBy": "register",
"time": {
"hooks": {},
"register": 0
}
},
"./node_modules/@umijs/preset-umi/dist/features/crossorigin/crossorigin": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/crossorigin/crossorigin.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/crossorigin/crossorigin",
"key": "crossorigin",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/depsOnDemand/depsOnDemand": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/depsOnDemand/depsOnDemand.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/depsOnDemand/depsOnDemand",
"key": "depsOnDemand",
"config": {},
"time": {
"hooks": {
"onStart": [
1
]
},
"register": 2
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/devTool/devTool": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/devTool/devTool.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/devTool/devTool",
"key": "devTool",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/esbuildHelperChecker/esbuildHelperChecker": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/esbuildHelperChecker/esbuildHelperChecker.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/esbuildHelperChecker/esbuildHelperChecker",
"key": "esbuildHelperChecker",
"config": {},
"time": {
"hooks": {},
"register": 128
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/esmi/esmi": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/esmi/esmi.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/esmi/esmi",
"key": "esmi",
"config": {},
"time": {
"hooks": {},
"register": 83
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/exportStatic/exportStatic": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/exportStatic/exportStatic.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/exportStatic/exportStatic",
"key": "exportStatic",
"config": {},
"time": {
"hooks": {},
"register": 37
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/favicons/favicons": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/favicons/favicons.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/favicons/favicons",
"key": "favicons",
"config": {},
"time": {
"hooks": {
"modifyAppData": [
0
]
},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/helmet/helmet": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/helmet/helmet.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/helmet/helmet",
"key": "helmet",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/icons/icons": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/icons/icons.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/icons/icons",
"key": "icons",
"config": {},
"time": {
"hooks": {},
"register": 7
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/mock/mock": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/mock/mock.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/mock/mock",
"key": "mock",
"config": {},
"time": {
"hooks": {},
"register": 72
}
},
"./node_modules/@umijs/preset-umi/dist/features/mpa/mpa": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/mpa/mpa.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/mpa/mpa",
"key": "mpa",
"config": {},
"time": {
"hooks": {},
"register": 3
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/okam/okam": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/okam/okam.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/okam/okam",
"key": "okam",
"config": {},
"time": {
"hooks": {},
"register": 2
}
},
"./node_modules/@umijs/preset-umi/dist/features/overrides/overrides": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/overrides/overrides.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/overrides/overrides",
"key": "overrides",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/phantomDependency/phantomDependency": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/phantomDependency/phantomDependency.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/phantomDependency/phantomDependency",
"key": "phantomDependency",
"config": {},
"time": {
"hooks": {},
"register": 2
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/polyfill/polyfill": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/polyfill/polyfill.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/polyfill/polyfill",
"key": "polyfill",
"config": {},
"time": {
"hooks": {
"modifyConfig": [
1
]
},
"register": 5
}
},
"./node_modules/@umijs/preset-umi/dist/features/polyfill/publicPathPolyfill": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/polyfill/publicPathPolyfill.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/polyfill/publicPathPolyfill",
"key": "publicPathPolyfill",
"config": {},
"time": {
"hooks": {},
"register": 2
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/prepare/prepare": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/prepare/prepare.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/prepare/prepare",
"key": "prepare",
"config": {},
"time": {
"hooks": {},
"register": 15
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/routePrefetch/routePrefetch": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/routePrefetch/routePrefetch.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/routePrefetch/routePrefetch",
"key": "routePrefetch",
"config": {},
"time": {
"hooks": {},
"register": 3
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/stagewise/stagewise": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/stagewise/stagewise.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/stagewise/stagewise",
"key": "stagewise",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/terminal/terminal": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/terminal/terminal.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/terminal/terminal",
"key": "terminal",
"config": {},
"time": {
"hooks": {},
"register": 2
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/tmpFiles/tmpFiles": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/tmpFiles/tmpFiles.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/tmpFiles/tmpFiles",
"key": "tmpFiles",
"config": {},
"time": {
"hooks": {},
"register": 11
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/clientLoader/clientLoader": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/clientLoader/clientLoader.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/clientLoader/clientLoader",
"key": "clientLoader",
"config": {},
"time": {
"hooks": {},
"register": 3
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/routeProps/routeProps": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/routeProps/routeProps.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/routeProps/routeProps",
"key": "routeProps",
"config": {},
"time": {
"hooks": {},
"register": 1
}
},
"./node_modules/@umijs/preset-umi/dist/features/ssr/ssr": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/ssr/ssr.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/ssr/ssr",
"key": "ssr",
"config": {},
"time": {
"hooks": {},
"register": 9
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/tmpFiles/configTypes": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/tmpFiles/configTypes.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/tmpFiles/configTypes",
"key": "configTypes",
"config": {},
"time": {
"hooks": {},
"register": 6
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/transform/transform": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/transform/transform.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/transform/transform",
"key": "transform",
"config": {},
"time": {
"hooks": {},
"register": 25
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/lowImport/lowImport": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/lowImport/lowImport.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/lowImport/lowImport",
"key": "lowImport",
"config": {},
"time": {
"hooks": {},
"register": 6
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/vite/vite": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/vite/vite.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/vite/vite",
"key": "vite",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/apiRoute/apiRoute": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/apiRoute/apiRoute.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/apiRoute/apiRoute",
"key": "apiRoute",
"config": {},
"time": {
"hooks": {},
"register": 17
}
},
"./node_modules/@umijs/preset-umi/dist/features/monorepo/redirect": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/monorepo/redirect.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/monorepo/redirect",
"key": "monorepoRedirect",
"config": {},
"time": {
"hooks": {},
"register": 75
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/test/test": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/test/test.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/test/test",
"key": "test",
"config": {},
"time": {
"hooks": {},
"register": 4
}
},
"./node_modules/@umijs/preset-umi/dist/features/clickToComponent/clickToComponent": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/clickToComponent/clickToComponent.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/clickToComponent/clickToComponent",
"key": "clickToComponent",
"config": {},
"time": {
"hooks": {},
"register": 2
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/legacy/legacy": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/legacy/legacy.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/legacy/legacy",
"key": "legacy",
"config": {},
"time": {
"hooks": {},
"register": 4
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/classPropertiesLoose/classPropertiesLoose": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/classPropertiesLoose/classPropertiesLoose.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/classPropertiesLoose/classPropertiesLoose",
"key": "classPropertiesLoose",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/webpack/webpack": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/webpack/webpack.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/webpack/webpack",
"key": "preset-umi:webpack",
"config": {},
"time": {
"hooks": {},
"register": 2
}
},
"./node_modules/@umijs/preset-umi/dist/features/swc/swc": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/swc/swc.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/swc/swc",
"key": "swc",
"config": {},
"time": {
"hooks": {
"addOnDemandDeps": [
0
]
},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/features/ui/ui": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/ui/ui.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/ui/ui",
"key": "ui",
"config": {},
"time": {
"hooks": {},
"register": 8
}
},
"./node_modules/@umijs/preset-umi/dist/features/mako/mako": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/mako/mako.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/mako/mako",
"key": "mako",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/utoopack/utoopack": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/utoopack/utoopack.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/utoopack/utoopack",
"key": "utoopack",
"config": {},
"time": {
"hooks": {},
"register": 3
}
},
"./node_modules/@umijs/preset-umi/dist/features/hmrGuardian/hmrGuardian": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/hmrGuardian/hmrGuardian.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/hmrGuardian/hmrGuardian",
"key": "hmrGuardian",
"config": {},
"time": {
"hooks": {},
"register": 5
}
},
"./node_modules/@umijs/preset-umi/dist/features/routePreloadOnLoad/routePreloadOnLoad": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/routePreloadOnLoad/routePreloadOnLoad.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/routePreloadOnLoad/routePreloadOnLoad",
"key": "routePreloadOnLoad",
"config": {},
"time": {
"hooks": {},
"register": 61
}
},
"./node_modules/@umijs/preset-umi/dist/features/forget/forget": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/forget/forget.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/forget/forget",
"key": "forget",
"config": {},
"time": {
"hooks": {},
"register": 3
},
"enableBy": "config"
},
"./node_modules/@umijs/preset-umi/dist/features/bundler/bundler": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/bundler/bundler.js",
"id": "./node_modules/@umijs/preset-umi/dist/features/bundler/bundler",
"key": "preset-umi:bundler",
"config": {},
"time": {
"hooks": {},
"register": 5
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/build": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/build.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/build",
"key": "build",
"config": {},
"time": {
"hooks": {},
"register": 9
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/config/config": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/config/config.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/config/config",
"key": "config",
"config": {},
"time": {
"hooks": {},
"register": 78
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/dev/dev": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/dev/dev.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/dev/dev",
"key": "dev",
"config": {},
"time": {
"hooks": {},
"register": 144
}
},
"./node_modules/@umijs/preset-umi/dist/commands/help": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/help.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/help",
"key": "help",
"config": {},
"time": {
"hooks": {},
"register": 2
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/lint": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/lint.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/lint",
"key": "lint",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/setup": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/setup.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/setup",
"key": "setup",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/deadcode": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/deadcode.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/deadcode",
"key": "deadcode",
"config": {},
"time": {
"hooks": {},
"register": 3
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/version": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/version.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/version",
"key": "version",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/generators/page": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/page.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/generators/page",
"key": "generator:page",
"config": {},
"time": {
"hooks": {},
"register": 4
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/generators/prettier": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/prettier.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/generators/prettier",
"key": "generator:prettier",
"config": {},
"time": {
"hooks": {},
"register": 3
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/generators/tsconfig": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/tsconfig.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/generators/tsconfig",
"key": "generator:tsconfig",
"config": {},
"time": {
"hooks": {},
"register": 3
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/generators/jest": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/jest.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/generators/jest",
"key": "generator:jest",
"config": {},
"time": {
"hooks": {},
"register": 2
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/generators/tailwindcss": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/tailwindcss.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/generators/tailwindcss",
"key": "generator:tailwindcss",
"config": {},
"time": {
"hooks": {},
"register": 2
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/generators/dva": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/dva.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/generators/dva",
"key": "generator:dva",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/generators/component": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/component.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/generators/component",
"key": "generator:component",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/generators/mock": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/mock.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/generators/mock",
"key": "generator:mock",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/generators/cypress": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/cypress.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/generators/cypress",
"key": "generator:cypress",
"config": {},
"time": {
"hooks": {},
"register": 2
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/generators/api": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/api.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/generators/api",
"key": "generator:api",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/generators/precommit": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/precommit.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/generators/precommit",
"key": "generator:precommit",
"config": {},
"time": {
"hooks": {},
"register": 2
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/plugin": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/plugin.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/plugin",
"key": "command:plugin",
"config": {},
"time": {
"hooks": {},
"register": 2
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/verify-commit": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/verify-commit.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/verify-commit",
"key": "verifyCommit",
"config": {},
"time": {
"hooks": {},
"register": 2
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/preview": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/preview.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/preview",
"key": "preview",
"config": {},
"time": {
"hooks": {},
"register": 40
},
"enableBy": "register"
},
"./node_modules/@umijs/preset-umi/dist/commands/mfsu/mfsu": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/mfsu/mfsu.js",
"id": "./node_modules/@umijs/preset-umi/dist/commands/mfsu/mfsu",
"key": "mfsu-cli",
"config": {},
"time": {
"hooks": {},
"register": 2
},
"enableBy": "register"
},
"@umijs/plugin-run": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/plugin-run/dist/index.js",
"id": "@umijs/plugin-run",
"key": "run",
"config": {},
"time": {
"hooks": {},
"register": 7
},
"enableBy": "register"
},
"./node_modules/@umijs/core/dist/service/generatePlugin": {
"cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard",
"type": "plugin",
"path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/core/dist/service/generatePlugin.js",
"id": "./node_modules/@umijs/core/dist/service/generatePlugin",
"key": "generatePlugin",
"config": {},
"time": {
"hooks": {},
"register": 1
},
"enableBy": "register"
}
},
"presets": [],
"name": "setup",
"args": {
"_": []
},
"userConfig": {
"routes": [
{
"path": "/",
"component": "@/pages/Homepage",
"layout": false
},
{
"path": "/pricing",
"component": "@/pages/Pricing",
"layout": false
},
{
"path": "/case-study",
"component": "@/pages/CaseStudy",
"layout": false
},
{
"path": "/case-study/:id",
"component": "@/pages/CaseStudy",
"layout": false
},
{
"path": "/auth",
"layout": false,
"routes": [
{
"path": "login",
"component": "@/pages/Auth/LoginPage"
},
{
"path": "register",
"component": "@/pages/Auth/RegisterPage"
}
]
},
{
"path": "/dashboard",
"layout": "@/layouts/index",
"routes": [
{
"path": "",
"component": "@/pages/OperationAgent"
},
{
"path": "operation-agent",
"component": "@/pages/OperationAgent"
}
]
}
],
"fastRefresh": true
},
"mainConfigFile": "D:\\trae_projects\\makemd\\makemd\\dashboard\\.umirc.ts",
"config": {
"routeLoader": {
"moduleType": "esm"
},
"mountElementId": "root",
"history": {
"type": "browser"
},
"base": "/",
"svgr": {},
"publicPath": "/",
"mfsu": {
"strategy": "eager"
},
"ignoreMomentLocale": true,
"externals": {},
"autoCSSModules": true,
"alias": {
"umi": "@@/exports",
"react": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react",
"react-dom": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-dom",
"react-router": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-router",
"react-router-dom": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-router-dom",
"@": "D:/trae_projects/makemd/makemd/dashboard/src",
"@@": "D:/trae_projects/makemd/makemd/dashboard/src/.umi",
"regenerator-runtime": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\regenerator-runtime"
},
"routes": [
{
"path": "/",
"component": "@/pages/Homepage",
"layout": false
},
{
"path": "/pricing",
"component": "@/pages/Pricing",
"layout": false
},
{
"path": "/case-study",
"component": "@/pages/CaseStudy",
"layout": false
},
{
"path": "/case-study/:id",
"component": "@/pages/CaseStudy",
"layout": false
},
{
"path": "/auth",
"layout": false,
"routes": [
{
"path": "login",
"component": "@/pages/Auth/LoginPage"
},
{
"path": "register",
"component": "@/pages/Auth/RegisterPage"
}
]
},
{
"path": "/dashboard",
"layout": "@/layouts/index",
"routes": [
{
"path": "",
"component": "@/pages/OperationAgent"
},
{
"path": "operation-agent",
"component": "@/pages/OperationAgent"
}
]
}
],
"fastRefresh": true,
"targets": {
"chrome": 80
}
},
"routes": {
"1": {
"path": "/",
"layout": false,
"file": "@/pages/Homepage.tsx",
"id": "1",
"absPath": "/",
"__content": "import React, { useState, useEffect } from 'react';\nimport { Link, useNavigate } from 'umi';\nimport { Button, Typography, Row, Col, Card, Divider } from 'antd';\nimport { ArrowRightOutlined, CheckCircleOutlined, MenuOutlined, XOutlined, TwitterOutlined, LinkedinOutlined, GithubOutlined } from '@ant-design/icons';\nimport Navbar from '@/components/Navbar';\n\nconst { Title, Paragraph, Text } = Typography;\n\nconst Homepage: React.FC = () => {\n const navigate = useNavigate();\n const [isScrolled, setIsScrolled] = useState(false);\n const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);\n\n useEffect(() => {\n const handleScroll = () => {\n setIsScrolled(window.scrollY > 50);\n };\n window.addEventListener('scroll', handleScroll);\n return () => window.removeEventListener('scroll', handleScroll);\n }, []);\n\n const features = [\n {\n title: '智能选品系统',\n description: '基于AI的商品推荐自动识别高潜力商品提升选品效率',\n },\n {\n title: 'AI动态定价',\n description: '实时市场分析,优化定价策略,最大化利润',\n },\n {\n title: '自动上架系统',\n description: '一键批量上架,节省人工成本,提高运营效率',\n },\n {\n title: '跨平台套利',\n description: '发现价格差异,实现利润最大化,降低运营风险',\n },\n {\n title: 'AI店铺托管',\n description: '24/7智能运营解放人力提升店铺表现',\n },\n {\n title: '多商户管理',\n description: '集中管理多店铺,数据一目了然,简化管理流程',\n },\n ];\n\n const stats = [\n { title: '平均提升', value: '30%', suffix: '运营效率' },\n { title: '平均提升', value: '25%', suffix: '利润率' },\n { title: '支持商户', value: '1000+', suffix: '同时在线' },\n ];\n\n return (\n <div className=\"homepage\" style={{ \n fontFamily: '-apple-system, BlinkMacSystemFont, \\'Segoe UI\\', Roboto, \\'Helvetica Neue\\', Arial, sans-serif',\n overflowX: 'hidden'\n }}>\n <Navbar />\n\n {/* 英雄区 */}\n <section className=\"hero\" style={{ \n padding: '180px 0 120px', \n background: 'linear-gradient(135deg, #0a192f 0%, #172a45 100%)',\n position: 'relative',\n overflow: 'hidden'\n }}>\n {/* 背景装饰 */}\n <div style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundImage: 'radial-gradient(circle at 25% 25%, rgba(24, 144, 255, 0.15) 0%, transparent 50%), radial-gradient(circle at 75% 75%, rgba(54, 207, 201, 0.15) 0%, transparent 50%)',\n zIndex: 1\n }} />\n {/* 网格背景 */}\n <div style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundImage: 'linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px), linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px)',\n backgroundSize: '40px 40px',\n zIndex: 1\n }} />\n <div className=\"container\" style={{ maxWidth: '1200px', margin: '0 auto', padding: '0 20px', position: 'relative', zIndex: 2 }}>\n <Row align=\"middle\" gutter={[48, 48]}>\n <Col xs={24} md={12} style={{ textAlign: 'left' }}>\n <div style={{ \n display: 'inline-block', \n background: 'rgba(24, 144, 255, 0.15)', \n color: '#1890ff', \n padding: '10px 20px', \n borderRadius: '25px', \n fontSize: '14px', \n fontWeight: '600',\n marginBottom: '32px',\n boxShadow: '0 4px 12px rgba(24, 144, 255, 0.15)'\n }}>\n AI驱动 · 智能运营\n </div>\n <Title level={1} style={{ \n color: '#fff', \n marginBottom: '32px', \n fontSize: '56px', \n fontWeight: 'bold',\n lineHeight: '1.1'\n }}>\n 重新定义跨境电商\n </Title>\n <Paragraph style={{ \n color: 'rgba(255, 255, 255, 0.8)', \n marginBottom: '48px', \n fontSize: '20px',\n lineHeight: '1.6'\n }}>\n 利用人工智能和自动化技术,帮助您实现从选品到运营的全流程智能化,提升效率,降低成本,实现业务增长\n </Paragraph>\n <div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>\n <Button \n type=\"primary\" \n size=\"large\" \n onClick={() => navigate('/auth/register')}\n style={{\n padding: '16px 40px', \n fontSize: '18px',\n borderRadius: '30px',\n boxShadow: '0 8px 24px rgba(24, 144, 255, 0.4)',\n transition: 'all 0.3s ease',\n '&:hover': {\n transform: 'translateY(-3px)',\n boxShadow: '0 12px 32px rgba(24, 144, 255, 0.5)'\n }\n }}\n >\n 免费注册\n </Button>\n <Button \n size=\"large\" \n onClick={() => navigate('/pricing')}\n style={{\n padding: '16px 40px', \n fontSize: '18px',\n borderRadius: '30px',\n background: 'rgba(255, 255, 255, 0.1)',\n color: '#fff',\n border: '1px solid rgba(255, 255, 255, 0.3)',\n transition: 'all 0.3s ease',\n '&:hover': {\n background: 'rgba(255, 255, 255, 0.2)',\n transform: 'translateY(-3px)'\n }\n }}\n >\n 了解更多\n </Button>\n </div>\n </Col>\n <Col xs={24} md={12}>\n <div style={{ \n textAlign: 'center',\n position: 'relative',\n perspective: '1000px'\n }}>\n <div style={{\n position: 'absolute',\n top: '-30px',\n left: '-30px',\n right: '-30px',\n bottom: '-30px',\n background: 'linear-gradient(45deg, #1890ff, #36cfc9)',\n borderRadius: '20px',\n filter: 'blur(60px)',\n opacity: 0.7,\n zIndex: -1,\n animation: 'pulse 3s ease-in-out infinite'\n }} />\n <img \n src=\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='800' height='450' viewBox='0 0 800 450'%3E%3Crect width='800' height='450' fill='%231890ff'/%3E%3Ctext x='50%25' y='50%25' dominant-baseline='middle' text-anchor='middle' font-family='Arial' font-size='24' fill='white'%3E智能电商平台%3C/text%3E%3C/svg%3E\" \n alt=\"智能电商平台\" \n style={{ \n maxWidth: '100%', \n borderRadius: '16px', \n boxShadow: '0 20px 60px rgba(0, 0, 0, 0.4)',\n transition: 'all 0.3s ease',\n transformStyle: 'preserve-3d',\n '&:hover': {\n transform: 'scale(1.05) rotateY(5deg)',\n boxShadow: '0 24px 72px rgba(0, 0, 0, 0.5)'\n }\n }}\n />\n </div>\n </Col>\n </Row>\n </div>\n </section>\n\n {/* 核心功能区 */}\n <section className=\"features\" style={{ \n padding: '140px 0', \n background: '#fafafa',\n position: 'relative'\n }}>\n {/* 背景装饰 */}\n <div style={{\n position: 'absolute',\n top: 0,\n right: 0,\n width: '50%',\n height: '100%',\n backgroundImage: 'radial-gradient(circle at 100% 50%, rgba(24, 144, 255, 0.05) 0%, transparent 50%)',\n zIndex: 1\n }} />\n <div className=\"container\" style={{ maxWidth: '1200px', margin: '0 auto', padding: '0 20px', position: 'relative', zIndex: 2 }}>\n <div style={{ textAlign: 'center', marginBottom: '96px' }}>\n <div style={{ \n display: 'inline-block', \n background: 'rgba(24, 144, 255, 0.1)', \n color: '#1890ff', \n padding: '10px 20px', \n borderRadius: '25px', \n fontSize: '14px', \n fontWeight: '600',\n marginBottom: '32px',\n boxShadow: '0 4px 12px rgba(24, 144, 255, 0.15)'\n }}>\n 核心功能\n </div>\n <Title level={2} style={{ \n fontSize: '48px', \n fontWeight: 'bold', \n marginBottom: '24px', \n color: '#333',\n lineHeight: '1.1'\n }}>全方位跨境电商解决方案</Title>\n <Paragraph style={{ \n fontSize: '20px', \n color: '#666', \n maxWidth: '800px', \n margin: '0 auto',\n lineHeight: '1.6'\n }}>\n 我们提供从选品到运营的完整解决方案,帮助您实现业务增长和利润最大化\n </Paragraph>\n </div>\n <Row gutter={[48, 48]}>\n {features.map((feature, index) => (\n <Col key={index} xs={24} sm={12} md={8}>\n <Card \n hoverable \n style={{ \n borderRadius: '16px', \n overflow: 'hidden', \n transition: 'all 0.4s ease',\n border: '1px solid #e8e8e8',\n boxShadow: '0 8px 24px rgba(0, 0, 0, 0.08)',\n height: '100%',\n '&:hover': {\n transform: 'translateY(-12px)',\n boxShadow: '0 16px 48px rgba(0, 0, 0, 0.15)',\n borderColor: '#1890ff'\n }\n }}\n >\n <div style={{ marginBottom: '32px', paddingTop: '32px' }}>\n <span style={{ \n display: 'inline-flex', \n width: '84px', \n height: '84px', \n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '32px', \n fontWeight: 'bold', \n background: 'linear-gradient(135deg, #1890ff 0%, #36cfc9 100%)', \n color: '#fff', \n borderRadius: '20px',\n boxShadow: '0 6px 20px rgba(24, 144, 255, 0.4)',\n transition: 'all 0.3s ease',\n '&:hover': {\n transform: 'scale(1.1)',\n boxShadow: '0 8px 24px rgba(24, 144, 255, 0.5)'\n }\n }}>{feature.title.charAt(0)}</span>\n </div>\n <Title level={4} style={{ \n marginBottom: '20px',\n color: '#333',\n fontWeight: 'bold',\n fontSize: '20px'\n }}>{feature.title}</Title>\n <Paragraph style={{ \n marginBottom: '32px',\n color: '#666',\n lineHeight: '1.6',\n fontSize: '16px'\n }}>{feature.description}</Paragraph>\n <Button \n type=\"text\" \n style={{\n color: '#1890ff',\n fontWeight: '600',\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n transition: 'all 0.3s ease',\n fontSize: '16px',\n '&:hover': {\n color: '#40a9ff',\n transform: 'translateX(6px)'\n }\n }}\n >\n 了解更多 <ArrowRightOutlined />\n </Button>\n </Card>\n </Col>\n ))}\n </Row>\n </div>\n </section>\n\n {/* 价值主张区 */}\n <section className=\"value-proposition\" style={{ \n padding: '140px 0', \n background: '#fff',\n position: 'relative'\n }}>\n {/* 背景装饰 */}\n <div style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '50%',\n height: '100%',\n backgroundImage: 'radial-gradient(circle at 0% 50%, rgba(24, 144, 255, 0.05) 0%, transparent 50%)',\n zIndex: 1\n }} />\n <div className=\"container\" style={{ maxWidth: '1200px', margin: '0 auto', padding: '0 20px', position: 'relative', zIndex: 2 }}>\n <Row align=\"middle\" gutter={[64, 64]}>\n <Col xs={24} md={12}>\n <div style={{ \n textAlign: 'center',\n position: 'relative',\n perspective: '1000px'\n }}>\n <div style={{\n position: 'absolute',\n top: '-30px',\n left: '-30px',\n right: '-30px',\n bottom: '-30px',\n background: 'linear-gradient(45deg, #1890ff, #36cfc9)',\n borderRadius: '20px',\n filter: 'blur(80px)',\n opacity: 0.15,\n zIndex: -1\n }} />\n <img \n src=\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='800' height='450' viewBox='0 0 800 450'%3E%3Crect width='800' height='450' fill='%2336cfc9'/%3E%3Ctext x='50%25' y='50%25' dominant-baseline='middle' text-anchor='middle' font-family='Arial' font-size='24' fill='white'%3E业务增长%3C/text%3E%3C/svg%3E\" \n alt=\"业务增长\" \n style={{ \n maxWidth: '100%', \n borderRadius: '16px', \n boxShadow: '0 20px 60px rgba(0, 0, 0, 0.15)',\n transition: 'all 0.4s ease',\n transformStyle: 'preserve-3d',\n '&:hover': {\n transform: 'scale(1.05) rotateY(-5deg)',\n boxShadow: '0 24px 72px rgba(0, 0, 0, 0.2)'\n }\n }}\n />\n </div>\n </Col>\n <Col xs={24} md={12}>\n <div style={{ \n display: 'inline-block', \n background: 'rgba(24, 144, 255, 0.1)', \n color: '#1890ff', \n padding: '10px 20px', \n borderRadius: '25px', \n fontSize: '14px', \n fontWeight: '600',\n marginBottom: '32px',\n boxShadow: '0 4px 12px rgba(24, 144, 255, 0.15)'\n }}>\n 为什么选择我们\n </div>\n <Title level={2} style={{ \n fontSize: '44px',\n fontWeight: 'bold',\n marginBottom: '36px', \n color: '#333',\n lineHeight: '1.1'\n }}>为什么选择 Crawlful Hub</Title>\n <div style={{ marginBottom: '48px' }}>\n <div style={{ \n display: 'flex', \n alignItems: 'flex-start', \n marginBottom: '32px', \n gap: '24px',\n padding: '24px',\n background: '#fafafa',\n borderRadius: '16px',\n transition: 'all 0.4s ease',\n '&:hover': {\n background: 'rgba(24, 144, 255, 0.05)',\n transform: 'translateX(12px)',\n boxShadow: '0 8px 24px rgba(0, 0, 0, 0.08)'\n }\n }}>\n <div style={{\n width: '56px',\n height: '56px',\n borderRadius: '14px',\n background: 'linear-gradient(135deg, #1890ff 0%, #36cfc9 100%)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n boxShadow: '0 4px 16px rgba(24, 144, 255, 0.3)'\n }}>\n <CheckCircleOutlined style={{ color: '#fff', fontSize: '28px' }} />\n </div>\n <div>\n <h3 style={{ \n marginBottom: '12px', \n color: '#333',\n fontSize: '20px',\n fontWeight: 'bold'\n }}>AI驱动决策</h3>\n <p style={{ \n color: '#666', \n margin: 0,\n lineHeight: '1.6',\n fontSize: '16px'\n }}>基于人工智能的数据分析和预测,帮助您做出更明智的业务决策</p>\n </div>\n </div>\n <div style={{ \n display: 'flex', \n alignItems: 'flex-start', \n marginBottom: '32px', \n gap: '24px',\n padding: '24px',\n background: '#fafafa',\n borderRadius: '16px',\n transition: 'all 0.4s ease',\n '&:hover': {\n background: 'rgba(24, 144, 255, 0.05)',\n transform: 'translateX(12px)',\n boxShadow: '0 8px 24px rgba(0, 0, 0, 0.08)'\n }\n }}>\n <div style={{\n width: '56px',\n height: '56px',\n borderRadius: '14px',\n background: 'linear-gradient(135deg, #1890ff 0%, #36cfc9 100%)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n boxShadow: '0 4px 16px rgba(24, 144, 255, 0.3)'\n }}>\n <CheckCircleOutlined style={{ color: '#fff', fontSize: '28px' }} />\n </div>\n <div>\n <h3 style={{ \n marginBottom: '12px', \n color: '#333',\n fontSize: '20px',\n fontWeight: 'bold'\n }}>全流程自动化</h3>\n <p style={{ \n color: '#666', \n margin: 0,\n lineHeight: '1.6',\n fontSize: '16px'\n }}>从选品到上架,从定价到运营,全流程自动化管理,节省人力成本</p>\n </div>\n </div>\n <div style={{ \n display: 'flex', \n alignItems: 'flex-start', \n marginBottom: '32px', \n gap: '24px',\n padding: '24px',\n background: '#fafafa',\n borderRadius: '16px',\n transition: 'all 0.4s ease',\n '&:hover': {\n background: 'rgba(24, 144, 255, 0.05)',\n transform: 'translateX(12px)',\n boxShadow: '0 8px 24px rgba(0, 0, 0, 0.08)'\n }\n }}>\n <div style={{\n width: '56px',\n height: '56px',\n borderRadius: '14px',\n background: 'linear-gradient(135deg, #1890ff 0%, #36cfc9 100%)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n boxShadow: '0 4px 16px rgba(24, 144, 255, 0.3)'\n }}>\n <CheckCircleOutlined style={{ color: '#fff', fontSize: '28px' }} />\n </div>\n <div>\n <h3 style={{ \n marginBottom: '12px', \n color: '#333',\n fontSize: '20px',\n fontWeight: 'bold'\n }}>多平台整合</h3>\n <p style={{ \n color: '#666', \n margin: 0,\n lineHeight: '1.6',\n fontSize: '16px'\n }}>支持主流电商平台,一站式管理多店铺,提高运营效率</p>\n </div>\n </div>\n <div style={{ \n display: 'flex', \n alignItems: 'flex-start', \n marginBottom: '32px', \n gap: '24px',\n padding: '24px',\n background: '#fafafa',\n borderRadius: '16px',\n transition: 'all 0.4s ease',\n '&:hover': {\n background: 'rgba(24, 144, 255, 0.05)',\n transform: 'translateX(12px)',\n boxShadow: '0 8px 24px rgba(0, 0, 0, 0.08)'\n }\n }}>\n <div style={{\n width: '56px',\n height: '56px',\n borderRadius: '14px',\n background: 'linear-gradient(135deg, #1890ff 0%, #36cfc9 100%)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n boxShadow: '0 4px 16px rgba(24, 144, 255, 0.3)'\n }}>\n <CheckCircleOutlined style={{ color: '#fff', fontSize: '28px' }} />\n </div>\n <div>\n <h3 style={{ \n marginBottom: '12px', \n color: '#333',\n fontSize: '20px',\n fontWeight: 'bold'\n }}>专业团队支持</h3>\n <p style={{ \n color: '#666', \n margin: 0,\n lineHeight: '1.6',\n fontSize: '16px'\n }}>7x24小时技术支持专业团队为您保驾护航确保业务稳定运行</p>\n </div>\n </div>\n </div>\n </Col>\n </Row>\n </div>\n </section>\n\n {/* 成功案例区 */}\n <section className=\"case-studies\" style={{ \n padding: '140px 0', \n background: '#fafafa',\n position: 'relative'\n }}>\n {/* 背景装饰 */}\n <div style={{\n position: 'absolute',\n top: 0,\n right: 0,\n width: '50%',\n height: '100%',\n backgroundImage: 'radial-gradient(circle at 100% 50%, rgba(24, 144, 255, 0.05) 0%, transparent 50%)',\n zIndex: 1\n }} />\n <div className=\"container\" style={{ maxWidth: '1200px', margin: '0 auto', padding: '0 20px', position: 'relative', zIndex: 2 }}>\n <div style={{ textAlign: 'center', marginBottom: '96px' }}>\n <div style={{ \n display: 'inline-block', \n background: 'rgba(24, 144, 255, 0.1)', \n color: '#1890ff', \n padding: '10px 20px', \n borderRadius: '25px', \n fontSize: '14px', \n fontWeight: '600',\n marginBottom: '32px',\n boxShadow: '0 4px 12px rgba(24, 144, 255, 0.15)'\n }}>\n 成功案例\n </div>\n <Title level={2} style={{ \n fontSize: '48px', \n fontWeight: 'bold', \n marginBottom: '24px', \n color: '#333',\n lineHeight: '1.1'\n }}>我们的客户成功故事</Title>\n <Paragraph style={{ \n fontSize: '20px', \n color: '#666', \n maxWidth: '800px', \n margin: '0 auto',\n lineHeight: '1.6'\n }}>\n 看看我们的客户如何使用 Crawlful Hub 实现业务增长\n </Paragraph>\n </div>\n <Row gutter={[48, 48]}>\n <Col xs={24} md={8}>\n <Card \n hoverable \n style={{ \n borderRadius: '20px', \n overflow: 'hidden', \n transition: 'all 0.4s ease',\n border: '1px solid #e8e8e8',\n boxShadow: '0 12px 32px rgba(0, 0, 0, 0.1)',\n height: '100%',\n '&:hover': {\n transform: 'translateY(-16px)',\n boxShadow: '0 20px 60px rgba(0, 0, 0, 0.18)',\n borderColor: '#1890ff'\n }\n }}\n >\n <div style={{ \n marginBottom: '0',\n position: 'relative',\n overflow: 'hidden',\n height: '280px'\n }}>\n <img \n src=\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='800' height='800' viewBox='0 0 800 800'%3E%3Crect width='800' height='800' fill='%231890ff'/%3E%3Ctext x='50%25' y='50%25' dominant-baseline='middle' text-anchor='middle' font-family='Arial' font-size='24' fill='white'%3E成功案例1%3C/text%3E%3C/svg%3E\" \n alt=\"成功案例1\" \n style={{ \n width: '100%', \n height: '100%', \n objectFit: 'cover',\n transition: 'all 0.4s ease',\n '&:hover': {\n transform: 'scale(1.1)'\n }\n }}\n />\n <div style={{\n position: 'absolute',\n bottom: 0,\n left: 0,\n right: 0,\n background: 'linear-gradient(transparent, rgba(0, 0, 0, 0.8))',\n padding: '24px',\n color: '#fff'\n }}>\n <div style={{ \n display: 'inline-block', \n background: 'rgba(255, 255, 255, 0.25)', \n color: '#fff', \n padding: '6px 16px', \n borderRadius: '16px', \n fontSize: '12px', \n fontWeight: '600',\n marginBottom: '12px'\n }}>\n 跨境电商\n </div>\n </div>\n </div>\n <div style={{ padding: '36px' }}>\n <Title level={4} style={{ \n marginBottom: '20px',\n color: '#333',\n fontWeight: 'bold',\n fontSize: '20px'\n }}>某跨境电商企业</Title>\n <Paragraph style={{ \n marginBottom: '32px',\n color: '#666',\n lineHeight: '1.6',\n fontSize: '16px'\n }}>通过智能选品和动态定价3个月内销售额提升45%</Paragraph>\n <Button \n type=\"text\" \n onClick={() => navigate('/case-study/1')}\n style={{\n color: '#1890ff',\n fontWeight: '600',\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n transition: 'all 0.3s ease',\n fontSize: '16px',\n '&:hover': {\n color: '#40a9ff',\n transform: 'translateX(6px)'\n }\n }}\n >\n 查看详情 <ArrowRightOutlined />\n </Button>\n </div>\n </Card>\n </Col>\n <Col xs={24} md={8}>\n <Card \n hoverable \n style={{ \n borderRadius: '20px', \n overflow: 'hidden', \n transition: 'all 0.4s ease',\n border: '1px solid #e8e8e8',\n boxShadow: '0 12px 32px rgba(0, 0, 0, 0.1)',\n height: '100%',\n '&:hover': {\n transform: 'translateY(-16px)',\n boxShadow: '0 20px 60px rgba(0, 0, 0, 0.18)',\n borderColor: '#1890ff'\n }\n }}\n >\n <div style={{ \n marginBottom: '0',\n position: 'relative',\n overflow: 'hidden',\n height: '280px'\n }}>\n <img \n src=\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='800' height='800' viewBox='0 0 800 800'%3E%3Crect width='800' height='800' fill='%2336cfc9'/%3E%3Ctext x='50%25' y='50%25' dominant-baseline='middle' text-anchor='middle' font-family='Arial' font-size='24' fill='white'%3E成功案例2%3C/text%3E%3C/svg%3E\" \n alt=\"成功案例2\" \n style={{ \n width: '100%', \n height: '100%', \n objectFit: 'cover',\n transition: 'all 0.4s ease',\n '&:hover': {\n transform: 'scale(1.1)'\n }\n }}\n />\n <div style={{\n position: 'absolute',\n bottom: 0,\n left: 0,\n right: 0,\n background: 'linear-gradient(transparent, rgba(0, 0, 0, 0.8))',\n padding: '24px',\n color: '#fff'\n }}>\n <div style={{ \n display: 'inline-block', \n background: 'rgba(255, 255, 255, 0.25)', \n color: '#fff', \n padding: '6px 16px', \n borderRadius: '16px', \n fontSize: '12px', \n fontWeight: '600',\n marginBottom: '12px'\n }}>\n 品牌零售\n </div>\n </div>\n </div>\n <div style={{ padding: '36px' }}>\n <Title level={4} style={{ \n marginBottom: '20px',\n color: '#333',\n fontWeight: 'bold',\n fontSize: '20px'\n }}>某品牌零售商</Title>\n <Paragraph style={{ \n marginBottom: '32px',\n color: '#666',\n lineHeight: '1.6',\n fontSize: '16px'\n }}>利用AI店铺托管运营成本降低30%效率提升50%</Paragraph>\n <Button \n type=\"text\" \n onClick={() => navigate('/case-study/2')}\n style={{\n color: '#1890ff',\n fontWeight: '600',\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n transition: 'all 0.3s ease',\n fontSize: '16px',\n '&:hover': {\n color: '#40a9ff',\n transform: 'translateX(6px)'\n }\n }}\n >\n 查看详情 <ArrowRightOutlined />\n </Button>\n </div>\n </Card>\n </Col>\n <Col xs={24} md={8}>\n <Card \n hoverable \n style={{ \n borderRadius: '20px', \n overflow: 'hidden', \n transition: 'all 0.4s ease',\n border: '1px solid #e8e8e8',\n boxShadow: '0 12px 32px rgba(0, 0, 0, 0.1)',\n height: '100%',\n '&:hover': {\n transform: 'translateY(-16px)',\n boxShadow: '0 20px 60px rgba(0, 0, 0, 0.18)',\n borderColor: '#1890ff'\n }\n }}\n >\n <div style={{ \n marginBottom: '0',\n position: 'relative',\n overflow: 'hidden',\n height: '280px'\n }}>\n <img \n src=\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='800' height='800' viewBox='0 0 800 800'%3E%3Crect width='800' height='800' fill='%23722ed1'/%3E%3Ctext x='50%25' y='50%25' dominant-baseline='middle' text-anchor='middle' font-family='Arial' font-size='24' fill='white'%3E成功案例3%3C/text%3E%3C/svg%3E\" \n alt=\"成功案例3\" \n style={{ \n width: '100%', \n height: '100%', \n objectFit: 'cover',\n transition: 'all 0.4s ease',\n '&:hover': {\n transform: 'scale(1.1)'\n }\n }}\n />\n <div style={{\n position: 'absolute',\n bottom: 0,\n left: 0,\n right: 0,\n background: 'linear-gradient(transparent, rgba(0, 0, 0, 0.8))',\n padding: '24px',\n color: '#fff'\n }}>\n <div style={{ \n display: 'inline-block', \n background: 'rgba(255, 255, 255, 0.25)', \n color: '#fff', \n padding: '6px 16px', \n borderRadius: '16px', \n fontSize: '12px', \n fontWeight: '600',\n marginBottom: '12px'\n }}>\n 多渠道运营\n </div>\n </div>\n </div>\n <div style={{ padding: '36px' }}>\n <Title level={4} style={{ \n marginBottom: '20px',\n color: '#333',\n fontWeight: 'bold',\n fontSize: '20px'\n }}>某多渠道卖家</Title>\n <Paragraph style={{ \n marginBottom: '32px',\n color: '#666',\n lineHeight: '1.6',\n fontSize: '16px'\n }}>通过跨平台套利6个月内利润率提升35%</Paragraph>\n <Button \n type=\"text\" \n onClick={() => navigate('/case-study/3')}\n style={{\n color: '#1890ff',\n fontWeight: '600',\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n transition: 'all 0.3s ease',\n fontSize: '16px',\n '&:hover': {\n color: '#40a9ff',\n transform: 'translateX(6px)'\n }\n }}\n >\n 查看详情 <ArrowRightOutlined />\n </Button>\n </div>\n </Card>\n </Col>\n </Row>\n <div style={{ textAlign: 'center', marginTop: '72px' }}>\n <Button \n type=\"primary\" \n onClick={() => navigate('/case-study')}\n style={{\n padding: '16px 40px', \n fontSize: '18px',\n borderRadius: '30px',\n boxShadow: '0 6px 18px rgba(24, 144, 255, 0.4)',\n transition: 'all 0.3s ease',\n '&:hover': {\n transform: 'translateY(-3px)',\n boxShadow: '0 8px 24px rgba(24, 144, 255, 0.5)'\n }\n }}\n >\n 查看更多案例\n </Button>\n </div>\n </div>\n </section>\n\n {/* 行动召唤区 */}\n <section className=\"cta\" style={{ \n padding: '160px 0', \n background: 'linear-gradient(135deg, #0a192f 0%, #172a45 100%)', \n color: '#fff', \n textAlign: 'center',\n position: 'relative',\n overflow: 'hidden'\n }}>\n {/* 背景装饰 */}\n <div style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundImage: 'radial-gradient(circle at 25% 25%, rgba(24, 144, 255, 0.15) 0%, transparent 50%), radial-gradient(circle at 75% 75%, rgba(54, 207, 201, 0.15) 0%, transparent 50%)',\n zIndex: 1\n }} />\n {/* 网格背景 */}\n <div style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundImage: 'linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px), linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px)',\n backgroundSize: '40px 40px',\n zIndex: 1\n }} />\n <div className=\"container\" style={{ maxWidth: '1200px', margin: '0 auto', padding: '0 20px', position: 'relative', zIndex: 2 }}>\n <div style={{ maxWidth: '800px', margin: '0 auto' }}>\n <div style={{ \n display: 'inline-block', \n background: 'rgba(24, 144, 255, 0.15)', \n color: '#1890ff', \n padding: '10px 20px', \n borderRadius: '25px', \n fontSize: '14px', \n fontWeight: '600',\n marginBottom: '32px',\n boxShadow: '0 4px 12px rgba(24, 144, 255, 0.2)'\n }}>\n 立即开始\n </div>\n <Title level={2} style={{ \n color: '#fff', \n marginBottom: '32px',\n fontSize: '48px',\n fontWeight: 'bold',\n lineHeight: '1.1'\n }}>准备好开始您的电商增长之旅了吗?</Title>\n <Paragraph style={{ \n color: 'rgba(255, 255, 255, 0.8)', \n marginBottom: '64px', \n fontSize: '22px',\n lineHeight: '1.6'\n }}>\n 立即注册享受14天免费试用体验AI驱动的跨境电商解决方案开启您的业务增长之路\n </Paragraph>\n <Button \n type=\"primary\" \n size=\"large\" \n onClick={() => navigate('/auth/register')}\n style={{\n padding: '18px 56px', \n fontSize: '20px',\n borderRadius: '35px',\n boxShadow: '0 8px 24px rgba(24, 144, 255, 0.4)',\n transition: 'all 0.3s ease',\n '&:hover': {\n transform: 'translateY(-3px)',\n boxShadow: '0 12px 32px rgba(24, 144, 255, 0.5)'\n }\n }}\n >\n 免费注册\n </Button>\n <div style={{ marginTop: '32px', color: 'rgba(255, 255, 255, 0.6)', fontSize: '16px' }}>\n 无需信用卡 · 14天免费试用 · 随时取消\n </div>\n </div>\n </div>\n </section>\n\n {/* 页脚 */}\n <footer style={{ \n padding: '120px 0 80px', \n background: '#0a192f', \n color: '#fff',\n position: 'relative',\n overflow: 'hidden'\n }}>\n {/* 背景装饰 */}\n <div style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundImage: 'radial-gradient(circle at 50% 50%, rgba(24, 144, 255, 0.05) 0%, transparent 70%)',\n zIndex: 1\n }} />\n <div className=\"container\" style={{ maxWidth: '1200px', margin: '0 auto', padding: '0 20px', position: 'relative', zIndex: 2 }}>\n <Row gutter={[48, 48]}>\n <Col xs={24} md={6}>\n <div style={{ \n fontSize: '32px', \n fontWeight: 'bold', \n marginBottom: '28px',\n color: '#1890ff',\n letterSpacing: '1px'\n }}>Crawlful Hub</div>\n <Paragraph style={{ \n color: 'rgba(255, 255, 255, 0.6)', \n marginBottom: '36px',\n lineHeight: '1.6',\n fontSize: '16px'\n }}>\n 智能驱动跨境电商增长,为您的业务提供全方位解决方案\n </Paragraph>\n <div style={{ display: 'flex', gap: '16px' }}>\n <a href=\"#\" style={{ \n display: 'inline-flex', \n alignItems: 'center', \n justifyContent: 'center',\n width: '48px',\n height: '48px',\n borderRadius: '50%',\n background: 'rgba(255, 255, 255, 0.08)',\n color: 'rgba(255, 255, 255, 0.6)',\n transition: 'all 0.3s ease',\n '&:hover': {\n background: '#1890ff',\n color: '#fff',\n transform: 'translateY(-2px)'\n }\n }}>\n <TwitterOutlined />\n </a>\n <a href=\"#\" style={{ \n display: 'inline-flex', \n alignItems: 'center', \n justifyContent: 'center',\n width: '48px',\n height: '48px',\n borderRadius: '50%',\n background: 'rgba(255, 255, 255, 0.08)',\n color: 'rgba(255, 255, 255, 0.6)',\n transition: 'all 0.3s ease',\n '&:hover': {\n background: '#1890ff',\n color: '#fff',\n transform: 'translateY(-2px)'\n }\n }}>\n <LinkedinOutlined />\n </a>\n <a href=\"#\" style={{ \n display: 'inline-flex', \n alignItems: 'center', \n justifyContent: 'center',\n width: '48px',\n height: '48px',\n borderRadius: '50%',\n background: 'rgba(255, 255, 255, 0.08)',\n color: 'rgba(255, 255, 255, 0.6)',\n transition: 'all 0.3s ease',\n '&:hover': {\n background: '#1890ff',\n color: '#fff',\n transform: 'translateY(-2px)'\n }\n }}>\n <GithubOutlined />\n </a>\n </div>\n </Col>\n <Col xs={24} md={6}>\n <h3 style={{ \n fontSize: '20px', \n fontWeight: 'bold', \n marginBottom: '28px', \n color: '#fff',\n letterSpacing: '0.5px'\n }}>产品</h3>\n <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>\n <li style={{ marginBottom: '20px' }}><Link to=\"/pricing\" style={{ \n color: 'rgba(255, 255, 255, 0.6)', \n transition: 'all 0.3s ease',\n textDecoration: 'none',\n fontSize: '16px',\n '&:hover': {\n color: '#1890ff',\n transform: 'translateX(4px)'\n }\n }}>定价方案</Link></li>\n <li style={{ marginBottom: '20px' }}><Link to=\"/case-study\" style={{ \n color: 'rgba(255, 255, 255, 0.6)', \n transition: 'all 0.3s ease',\n textDecoration: 'none',\n fontSize: '16px',\n '&:hover': {\n color: '#1890ff',\n transform: 'translateX(4px)'\n }\n }}>成功案例</Link></li>\n <li style={{ marginBottom: '20px' }}><Link to=\"/\" style={{ \n color: 'rgba(255, 255, 255, 0.6)', \n transition: 'all 0.3s ease',\n textDecoration: 'none',\n fontSize: '16px',\n '&:hover': {\n color: '#1890ff',\n transform: 'translateX(4px)'\n }\n }}>功能介绍</Link></li>\n <li style={{ marginBottom: '20px' }}><Link to=\"/\" style={{ \n color: 'rgba(255, 255, 255, 0.6)', \n transition: 'all 0.3s ease',\n textDecoration: 'none',\n fontSize: '16px',\n '&:hover': {\n color: '#1890ff',\n transform: 'translateX(4px)'\n }\n }}>API文档</Link></li>\n </ul>\n </Col>\n <Col xs={24} md={6}>\n <h3 style={{ \n fontSize: '20px', \n fontWeight: 'bold', \n marginBottom: '28px', \n color: '#fff',\n letterSpacing: '0.5px'\n }}>公司</h3>\n <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>\n <li style={{ marginBottom: '20px' }}><Link to=\"/\" style={{ \n color: 'rgba(255, 255, 255, 0.6)', \n transition: 'all 0.3s ease',\n textDecoration: 'none',\n fontSize: '16px',\n '&:hover': {\n color: '#1890ff',\n transform: 'translateX(4px)'\n }\n }}>关于我们</Link></li>\n <li style={{ marginBottom: '20px' }}><Link to=\"/\" style={{ \n color: 'rgba(255, 255, 255, 0.6)', \n transition: 'all 0.3s ease',\n textDecoration: 'none',\n fontSize: '16px',\n '&:hover': {\n color: '#1890ff',\n transform: 'translateX(4px)'\n }\n }}>联系我们</Link></li>\n <li style={{ marginBottom: '20px' }}><Link to=\"/\" style={{ \n color: 'rgba(255, 255, 255, 0.6)', \n transition: 'all 0.3s ease',\n textDecoration: 'none',\n fontSize: '16px',\n '&:hover': {\n color: '#1890ff',\n transform: 'translateX(4px)'\n }\n }}>招贤纳士</Link></li>\n <li style={{ marginBottom: '20px' }}><Link to=\"/\" style={{ \n color: 'rgba(255, 255, 255, 0.6)', \n transition: 'all 0.3s ease',\n textDecoration: 'none',\n fontSize: '16px',\n '&:hover': {\n color: '#1890ff',\n transform: 'translateX(4px)'\n }\n }}>新闻资讯</Link></li>\n </ul>\n </Col>\n <Col xs={24} md={6}>\n <h3 style={{ \n fontSize: '20px', \n fontWeight: 'bold', \n marginBottom: '28px', \n color: '#fff',\n letterSpacing: '0.5px'\n }}>支持</h3>\n <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>\n <li style={{ marginBottom: '20px' }}><Link to=\"/\" style={{ \n color: 'rgba(255, 255, 255, 0.6)', \n transition: 'all 0.3s ease',\n textDecoration: 'none',\n fontSize: '16px',\n '&:hover': {\n color: '#1890ff',\n transform: 'translateX(4px)'\n }\n }}>帮助中心</Link></li>\n <li style={{ marginBottom: '20px' }}><Link to=\"/\" style={{ \n color: 'rgba(255, 255, 255, 0.6)', \n transition: 'all 0.3s ease',\n textDecoration: 'none',\n fontSize: '16px',\n '&:hover': {\n color: '#1890ff',\n transform: 'translateX(4px)'\n }\n }}>常见问题</Link></li>\n <li style={{ marginBottom: '20px' }}><Link to=\"/\" style={{ \n color: 'rgba(255, 255, 255, 0.6)', \n transition: 'all 0.3s ease',\n textDecoration: 'none',\n fontSize: '16px',\n '&:hover': {\n color: '#1890ff',\n transform: 'translateX(4px)'\n }\n }}>联系支持</Link></li>\n <li style={{ marginBottom: '20px' }}><Link to=\"/\" style={{ \n color: 'rgba(255, 255, 255, 0.6)', \n transition: 'all 0.3s ease',\n textDecoration: 'none',\n fontSize: '16px',\n '&:hover': {\n color: '#1890ff',\n transform: 'translateX(4px)'\n }\n }}>API文档</Link></li>\n </ul>\n </Col>\n </Row>\n <Divider style={{ \n backgroundColor: 'rgba(255, 255, 255, 0.1)', \n margin: '80px 0 40px',\n height: '1px'\n }} />\n <div style={{ textAlign: 'center', color: 'rgba(255, 255, 255, 0.4)', fontSize: '14px' }}>\n <div style={{ marginBottom: '16px' }}>\n <Link to=\"/\" style={{ \n color: 'rgba(255, 255, 255, 0.4)', \n transition: 'color 0.3s ease',\n textDecoration: 'none',\n margin: '0 16px',\n '&:hover': {\n color: '#1890ff'\n }\n }}>隐私政策</Link>\n <Link to=\"/\" style={{ \n color: 'rgba(255, 255, 255, 0.4)', \n transition: 'color 0.3s ease',\n textDecoration: 'none',\n margin: '0 16px',\n '&:hover': {\n color: '#1890ff'\n }\n }}>服务条款</Link>\n <Link to=\"/\" style={{ \n color: 'rgba(255, 255, 255, 0.4)', \n transition: 'color 0.3s ease',\n textDecoration: 'none',\n margin: '0 16px',\n '&:hover': {\n color: '#1890ff'\n }\n }}>Cookie政策</Link>\n </div>\n © 2025 Crawlful Hub. All rights reserved.\n </div>\n </div>\n </footer>\n </div>\n );\n};\n\nexport default Homepage;",
"__isJSFile": true,
"__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/Homepage.tsx"
},
"2": {
"path": "/pricing",
"layout": false,
"file": "@/pages/Pricing.tsx",
"id": "2",
"absPath": "/pricing",
"__content": "import React, { useState } from 'react';\nimport { Link, useNavigate } from 'umi';\nimport { Card, Button, Typography, Divider, Radio, Row, Col, Tag, Alert } from 'antd';\nimport { CheckCircleOutlined, CloseCircleOutlined, ArrowRightOutlined, DollarOutlined, UsersOutlined, ShieldOutlined, BarChartOutlined, ZapOutlined, GlobeOutlined, StarOutlined } from '@ant-design/icons';\nimport Navbar from '@/components/Navbar';\n\nconst { Title, Paragraph, Text } = Typography;\n\nconst Pricing: React.FC = () => {\n const navigate = useNavigate();\n const [billingCycle, setBillingCycle] = useState<'monthly' | 'yearly'>('monthly');\n\n const plans = [\n {\n name: '免费版',\n price: 0,\n billing: '永久免费',\n features: [\n '基础功能',\n '最多1个店铺',\n '500条商品数据',\n '邮件支持',\n '基础报表',\n '手动操作',\n ],\n cta: '开始免费使用',\n popular: false,\n buttonType: 'primary',\n onClick: () => navigate('/auth/register'),\n },\n {\n name: '专业版',\n price: billingCycle === 'monthly' ? 999 : 9990,\n billing: billingCycle === 'monthly' ? '每月' : '每年',\n features: [\n '所有核心功能',\n '最多10个店铺',\n '5000条商品数据',\n '优先邮件支持',\n '高级报表',\n 'AI智能选品',\n '自动上架',\n '动态定价',\n '跨平台套利',\n ],\n cta: '选择专业版',\n popular: true,\n buttonType: 'primary',\n onClick: () => navigate('/checkout?plan=professional'),\n },\n {\n name: '企业版',\n price: 0,\n billing: '定制',\n features: [\n '完整功能',\n '无限店铺',\n '无限商品数据',\n '24/7专属支持',\n '定制化报表',\n 'AI店铺托管',\n '定制化开发',\n 'API接入',\n '专属客户经理',\n ],\n cta: '联系销售',\n popular: false,\n buttonType: 'default',\n onClick: () => navigate('/contact'),\n },\n ];\n\n const compareFeatures = [\n { feature: '核心功能', free: true, professional: true, enterprise: true },\n { feature: '店铺数量', free: '1个', professional: '10个', enterprise: '无限' },\n { feature: '商品数据', free: '500条', professional: '5000条', enterprise: '无限' },\n { feature: 'AI智能选品', free: false, professional: true, enterprise: true },\n { feature: '自动上架', free: false, professional: true, enterprise: true },\n { feature: '动态定价', free: false, professional: true, enterprise: true },\n { feature: '跨平台套利', free: false, professional: true, enterprise: true },\n { feature: 'AI店铺托管', free: false, professional: false, enterprise: true },\n { feature: '技术支持', free: '邮件', professional: '优先邮件', enterprise: '24/7专属' },\n { feature: '定制化开发', free: false, professional: false, enterprise: true },\n { feature: 'API接入', free: false, professional: false, enterprise: true },\n ];\n\n return (\n <div className=\"pricing-page\">\n <Navbar />\n {/* 页面头部 */}\n <section className=\"pricing-header\">\n <div className=\"container\">\n <Title level={1}>选择适合您的方案</Title>\n <Paragraph className=\"subtitle\">\n 无论您是个人卖家还是大型企业,我们都有适合您的解决方案\n </Paragraph>\n <div className=\"billing-cycle\">\n <Text>月付</Text>\n <Radio.Group value={billingCycle} onChange={(e) => setBillingCycle(e.target.value)}>\n <Radio.Button value=\"monthly\">月付</Radio.Button>\n <Radio.Button value=\"yearly\">年付 <Tag color=\"green\">省16%</Tag></Radio.Button>\n </Radio.Group>\n <Text>年付</Text>\n </div>\n </div>\n </section>\n\n {/* 定价方案 */}\n <section className=\"pricing-plans\">\n <div className=\"container\">\n <Row gutter={[32, 32]}>\n {plans.map((plan, index) => (\n <Col key={index} xs={24} md={8}>\n <Card className={`plan-card ${plan.popular ? 'popular' : ''}`}>\n {plan.popular && (\n <div className=\"popular-badge\">\n <StarOutlined /> 推荐\n </div>\n )}\n <div className=\"plan-header\">\n <Title level={3}>{plan.name}</Title>\n <div className=\"price\">\n <DollarOutlined />\n <span className=\"price-value\">{plan.price}</span>\n <span className=\"price-unit\">/{plan.billing === '永久免费' ? '' : plan.billing === '每月' ? '月' : '年'}</span>\n </div>\n {plan.billing === '永久免费' && (\n <Text type=\"secondary\">{plan.billing}</Text>\n )}\n </div>\n <Divider />\n <div className=\"plan-features\">\n {plan.features.map((feature, idx) => (\n <div key={idx} className=\"feature-item\">\n <CheckCircleOutlined className=\"feature-icon\" />\n <Text>{feature}</Text>\n </div>\n ))}\n </div>\n <Button \n type={plan.buttonType as 'primary' | 'default' | 'dashed' | 'text' | 'link'} \n size=\"large\" \n className=\"plan-button\" \n onClick={plan.onClick}\n >\n {plan.cta}\n </Button>\n </Card>\n </Col>\n ))}\n </Row>\n </div>\n </section>\n\n {/* 功能对比 */}\n <section className=\"feature-comparison\">\n <div className=\"container\">\n <Title level={2}>功能对比</Title>\n <div className=\"comparison-table\">\n <div className=\"table-header\">\n <div className=\"feature-cell\">功能</div>\n <div className=\"plan-cell\">免费版</div>\n <div className=\"plan-cell\">专业版</div>\n <div className=\"plan-cell\">企业版</div>\n </div>\n {compareFeatures.map((item, index) => (\n <div key={index} className=\"table-row\">\n <div className=\"feature-cell\">{item.feature}</div>\n <div className=\"plan-cell\">\n {typeof item.free === 'boolean' ? (\n item.free ? \n <CheckCircleOutlined className=\"check-icon\" /> : \n <CloseCircleOutlined className=\"close-icon\" />\n ) : (\n <Text>{item.free}</Text>\n )}\n </div>\n <div className=\"plan-cell\">\n {typeof item.professional === 'boolean' ? (\n item.professional ? \n <CheckCircleOutlined className=\"check-icon\" /> : \n <CloseCircleOutlined className=\"close-icon\" />\n ) : (\n <Text>{item.professional}</Text>\n )}\n </div>\n <div className=\"plan-cell\">\n {typeof item.enterprise === 'boolean' ? (\n item.enterprise ? \n <CheckCircleOutlined className=\"check-icon\" /> : \n <CloseCircleOutlined className=\"close-icon\" />\n ) : (\n <Text>{item.enterprise}</Text>\n )}\n </div>\n </div>\n ))}\n </div>\n </div>\n </section>\n\n {/* 常见问题 */}\n <section className=\"faq\">\n <div className=\"container\">\n <Title level={2}>常见问题</Title>\n <Row gutter={[32, 32]}>\n <Col xs={24} md={12}>\n <Card className=\"faq-card\">\n <Title level={4}>如何选择适合我的方案?</Title>\n <Paragraph>\n 根据您的店铺数量、商品数据量和功能需求来选择。如果您是个人卖家或刚刚起步,免费版是个不错的选择。如果您有多个店铺需要管理,专业版会更适合您。如果您是大型企业,需要定制化解决方案,建议选择企业版。\n </Paragraph>\n </Card>\n <Card className=\"faq-card\">\n <Title level={4}>可以随时升级或降级方案吗?</Title>\n <Paragraph>\n 是的,您可以随时升级或降级您的方案。升级会立即生效,降级会在下一个 billing cycle 开始时生效。\n </Paragraph>\n </Card>\n <Card className=\"faq-card\">\n <Title level={4}>如何取消订阅?</Title>\n <Paragraph>\n 您可以在账户设置中取消订阅。取消后,您的服务会持续到当前 billing cycle 结束,之后不会再收费。\n </Paragraph>\n </Card>\n </Col>\n <Col xs={24} md={12}>\n <Card className=\"faq-card\">\n <Title level={4}>年付和月付有什么区别?</Title>\n <Paragraph>\n 年付可以享受16%的折扣相当于免费使用2个月。其他功能和服务都是一样的。\n </Paragraph>\n </Card>\n <Card className=\"faq-card\">\n <Title level={4}>提供发票吗?</Title>\n <Paragraph>\n 是的,我们会为所有付费用户提供正规发票。您可以在账户设置中下载发票。\n </Paragraph>\n </Card>\n <Card className=\"faq-card\">\n <Title level={4}>有试用期吗?</Title>\n <Paragraph>\n 是的专业版和企业版都提供14天的免费试用期。试用期内您可以体验所有功能无需信用卡。\n </Paragraph>\n </Card>\n </Col>\n </Row>\n </div>\n </section>\n\n {/* 行动召唤 */}\n <section className=\"cta\">\n <div className=\"container\">\n <Title level={2}>准备好开始了吗?</Title>\n <Paragraph>选择适合您的方案,开始您的电商增长之旅</Paragraph>\n <Button type=\"primary\" size=\"large\" onClick={() => navigate('/auth/register')}>\n 免费注册\n </Button>\n </div>\n </section>\n\n <style jsx>{`\n .pricing-page {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n }\n\n .pricing-header {\n padding: 140px 0 40px;\n background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);\n text-align: center;\n }\n\n @media (max-width: 768px) {\n .pricing-header {\n padding: 120px 0 30px;\n }\n }\n\n .subtitle {\n font-size: 18px;\n color: #666;\n margin: 16px 0 32px;\n }\n\n .billing-cycle {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 16px;\n margin-top: 32px;\n }\n\n .pricing-plans {\n padding: 60px 0;\n background: #fff;\n }\n\n .plan-card {\n border-radius: 8px;\n transition: all 0.3s ease;\n position: relative;\n overflow: hidden;\n }\n\n .plan-card:hover {\n transform: translateY(-8px);\n box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);\n }\n\n .plan-card.popular {\n border: 2px solid #1890ff;\n transform: scale(1.05);\n }\n\n .plan-card.popular:hover {\n transform: scale(1.05) translateY(-8px);\n }\n\n .popular-badge {\n position: absolute;\n top: 0;\n right: 0;\n background: #1890ff;\n color: #fff;\n padding: 4px 16px;\n border-radius: 0 8px 0 8px;\n font-size: 12px;\n font-weight: bold;\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .plan-header {\n text-align: center;\n margin-bottom: 24px;\n }\n\n .price {\n display: flex;\n align-items: baseline;\n justify-content: center;\n margin: 16px 0;\n }\n\n .price-value {\n font-size: 36px;\n font-weight: bold;\n color: #1890ff;\n margin: 0 4px;\n }\n\n .price-unit {\n font-size: 16px;\n color: #666;\n }\n\n .plan-features {\n margin: 24px 0;\n }\n\n .feature-item {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n }\n\n .feature-icon {\n color: #52c41a;\n }\n\n .plan-button {\n width: 100%;\n margin-top: 24px;\n }\n\n .feature-comparison {\n padding: 80px 0;\n background: #f5f7fa;\n }\n\n .comparison-table {\n background: #fff;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n }\n\n .table-header {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr 1fr;\n background: #f0f2f5;\n padding: 16px;\n font-weight: bold;\n border-bottom: 1px solid #e8e8e8;\n }\n\n .table-row {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr 1fr;\n padding: 16px;\n border-bottom: 1px solid #e8e8e8;\n }\n\n .table-row:last-child {\n border-bottom: none;\n }\n\n .feature-cell {\n font-weight: 500;\n }\n\n .plan-cell {\n text-align: center;\n }\n\n .check-icon {\n color: #52c41a;\n font-size: 18px;\n }\n\n .close-icon {\n color: #ff4d4f;\n font-size: 18px;\n }\n\n .faq {\n padding: 80px 0;\n background: #fff;\n }\n\n .faq-card {\n padding: 24px;\n border-radius: 8px;\n transition: all 0.3s ease;\n }\n\n .faq-card:hover {\n box-shadow: 0 8px 16px rgba(0, 0, 0, 0.08);\n }\n\n .cta {\n padding: 80px 0;\n background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);\n color: #fff;\n text-align: center;\n }\n\n .cta .ant-btn {\n margin-top: 24px;\n }\n\n @media (max-width: 768px) {\n .pricing-header {\n padding: 60px 0 30px;\n }\n\n .pricing-plans {\n padding: 40px 0;\n }\n\n .feature-comparison {\n padding: 60px 0;\n }\n\n .table-header,\n .table-row {\n grid-template-columns: 1fr;\n gap: 8px;\n }\n\n .plan-cell {\n text-align: left;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .faq {\n padding: 60px 0;\n }\n\n .cta {\n padding: 60px 0;\n }\n }\n `}</style>\n </div>\n );\n};\n\nexport default Pricing;",
"__isJSFile": true,
"__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/Pricing.tsx"
},
"3": {
"path": "/case-study",
"layout": false,
"file": "@/pages/CaseStudy.tsx",
"id": "3",
"absPath": "/case-study",
"__content": "import React, { useState } from 'react';\nimport { Link, useNavigate } from 'umi';\nimport { Card, Button, Typography, Row, Col, Tag, Carousel, Pagination } from 'antd';\nimport { ArrowRightOutlined, CheckCircleOutlined, DollarOutlined, BarChartOutlined, ZapOutlined, GlobeOutlined, StarOutlined, UserOutlined, CompanyOutlined, TrendingUpOutlined } from '@ant-design/icons';\nimport Navbar from '@/components/Navbar';\n\nconst { Title, Paragraph, Text } = Typography;\n\nconst CaseStudy: React.FC = () => {\n const navigate = useNavigate();\n const [activeCategory, setActiveCategory] = useState('all');\n const [currentPage, setCurrentPage] = useState(1);\n\n const caseStudies = [\n {\n id: 1,\n title: '中小商户案例月销售额提升45%',\n category: 'small',\n company: '广州某跨境电商公司',\n industry: '电子产品',\n challenge: '手动选品效率低,定价策略单一,运营成本高',\n solution: '使用智能选品系统和AI动态定价实现自动化运营',\n results: [\n '月销售额提升45%',\n '运营成本降低30%',\n '选品效率提升60%',\n ],\n testimonial: '\"Crawlful Hub帮助我们实现了店铺的自动化运营节省了大量人力成本销售额提升了40%。\"',\n author: '张总',\n position: 'CEO',\n image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',\n },\n {\n id: 2,\n title: '大型企业案例多店铺管理效率提升60%',\n category: 'enterprise',\n company: '深圳某品牌电商',\n industry: '服装行业',\n challenge: '多店铺管理复杂,数据分散,难以统一运营',\n solution: '使用多店铺管理系统,实现数据集中管理和统一运营',\n results: [\n '管理效率提升60%',\n '数据处理时间减少70%',\n '运营成本降低25%',\n ],\n testimonial: '\"多店铺管理功能让我们能够集中管理所有店铺,数据一目了然,大大提高了管理效率。\"',\n author: '李经理',\n position: '运营总监',\n image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',\n },\n {\n id: 3,\n title: '跨境电商案例利润率提升30%',\n category: 'crossborder',\n company: '杭州某跨境电商平台',\n industry: '家居用品',\n challenge: '跨平台价格差异难以把握,利润空间小',\n solution: '使用跨平台套利系统,发现价格差异,优化定价策略',\n results: [\n '利润率提升30%',\n '价格优化效率提升80%',\n '市场竞争力增强',\n ],\n testimonial: '\"跨平台套利系统帮助我们发现了很多价格差异利润率提高了30%,市场竞争力大大增强。\"',\n author: '王女士',\n position: '业务经理',\n image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',\n },\n {\n id: 4,\n title: '新手卖家案例:快速启动电商业务',\n category: 'small',\n company: '上海某个人卖家',\n industry: '美妆产品',\n challenge: '缺乏电商运营经验,选品困难,运营成本高',\n solution: '使用智能选品系统和自动上架功能,快速启动业务',\n results: [\n '业务启动时间缩短50%',\n '选品准确率提升70%',\n '首月销售额达到预期目标',\n ],\n testimonial: '\"作为新手卖家Crawlful Hub帮助我快速启动了电商业务选品和上架都变得非常简单。\"',\n author: '陈先生',\n position: '个人卖家',\n image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',\n },\n {\n id: 5,\n title: '传统企业转型案例线上销售额占比提升至60%',\n category: 'enterprise',\n company: '北京某传统制造企业',\n industry: '机械设备',\n challenge: '线上业务占比低,数字化转型困难',\n solution: '使用全功能电商管理系统,实现线上线下一体化运营',\n results: [\n '线上销售额占比提升至60%',\n '客户获取成本降低40%',\n '品牌知名度提升',\n ],\n testimonial: '\"Crawlful Hub帮助我们成功实现了数字化转型线上销售额占比从10%提升到了60%。\"',\n author: '赵总',\n position: '总经理',\n image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',\n },\n {\n id: 6,\n title: '多平台运营案例管理效率提升70%',\n category: 'crossborder',\n company: '厦门某跨境电商公司',\n industry: '玩具产品',\n challenge: '多平台运营管理复杂,数据不同步,运营效率低',\n solution: '使用多平台集成管理系统,实现数据同步和统一运营',\n results: [\n '管理效率提升70%',\n '数据同步时间减少90%',\n '运营成本降低35%',\n ],\n testimonial: '\"多平台集成管理系统让我们能够统一管理所有平台的店铺,效率大大提升。\"',\n author: '刘经理',\n position: '运营主管',\n image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',\n },\n ];\n\n const filteredCases = activeCategory === 'all' \n ? caseStudies \n : caseStudies.filter(caseStudy => caseStudy.category === activeCategory);\n\n const itemsPerPage = 3;\n const totalPages = Math.ceil(filteredCases.length / itemsPerPage);\n const currentCases = filteredCases.slice(\n (currentPage - 1) * itemsPerPage,\n currentPage * itemsPerPage\n );\n\n const categories = [\n { value: 'all', label: '全部案例' },\n { value: 'small', label: '中小商户' },\n { value: 'enterprise', label: '大型企业' },\n { value: 'crossborder', label: '跨境电商' },\n ];\n\n return (\n <div className=\"case-study-page\">\n <Navbar />\n {/* 页面头部 */}\n <section className=\"case-header\">\n <div className=\"container\">\n <Title level={1}>成功案例</Title>\n <Paragraph className=\"subtitle\">\n 看看我们如何帮助客户实现业务增长\n </Paragraph>\n </div>\n </section>\n\n {/* 分类筛选 */}\n <section className=\"category-filter\">\n <div className=\"container\">\n <div className=\"categories\">\n {categories.map(category => (\n <Button\n key={category.value}\n type={activeCategory === category.value ? 'primary' : 'default'}\n onClick={() => {\n setActiveCategory(category.value);\n setCurrentPage(1);\n }}\n >\n {category.label}\n </Button>\n ))}\n </div>\n </div>\n </section>\n\n {/* 案例列表 */}\n <section className=\"case-list\">\n <div className=\"container\">\n <Row gutter={[32, 32]}>\n {currentCases.map(caseStudy => (\n <Col key={caseStudy.id} xs={24} md={8}>\n <Card hoverable className=\"case-card\">\n <div className=\"case-image\">\n <img src={caseStudy.image} alt={caseStudy.title} />\n </div>\n <div className=\"case-content\">\n <div className=\"case-meta\">\n <Tag color=\"blue\">{caseStudy.industry}</Tag>\n <Tag color=\"green\">{caseStudy.company}</Tag>\n </div>\n <Title level={4}>{caseStudy.title}</Title>\n <Paragraph className=\"case-challenge\">\n <Text strong>挑战:</Text>{caseStudy.challenge}\n </Paragraph>\n <Paragraph className=\"case-solution\">\n <Text strong>解决方案:</Text>{caseStudy.solution}\n </Paragraph>\n <div className=\"case-results\">\n <Title level={5}>成果:</Title>\n <ul>\n {caseStudy.results.map((result, index) => (\n <li key={index}>\n <CheckCircleOutlined className=\"result-icon\" />\n {result}\n </li>\n ))}\n </ul>\n </div>\n <div className=\"case-testimonial\">\n <div className=\"testimonial-content\">\n <StarOutlined className=\"star\" />\n <StarOutlined className=\"star\" />\n <StarOutlined className=\"star\" />\n <StarOutlined className=\"star\" />\n <StarOutlined className=\"star\" />\n <Paragraph>{caseStudy.testimonial}</Paragraph>\n </div>\n <div className=\"testimonial-author\">\n <UserOutlined className=\"author-icon\" />\n <div>\n <Text strong>{caseStudy.author}</Text>\n <Text type=\"secondary\">{caseStudy.position}</Text>\n </div>\n </div>\n </div>\n <Button type=\"primary\" className=\"case-button\" onClick={() => navigate(`/case-study/${caseStudy.id}`)}>\n 查看详情\n <ArrowRightOutlined />\n </Button>\n </div>\n </Card>\n </Col>\n ))}\n </Row>\n \n {/* 分页 */}\n {totalPages > 1 && (\n <div className=\"pagination\">\n <Pagination\n current={currentPage}\n total={filteredCases.length}\n pageSize={itemsPerPage}\n onChange={setCurrentPage}\n showSizeChanger={false}\n />\n </div>\n )}\n </div>\n </section>\n\n {/* 客户评价轮播 */}\n <section className=\"testimonial-carousel\">\n <div className=\"container\">\n <Title level={2}>客户评价</Title>\n <Carousel autoplay className=\"carousel\">\n {caseStudies.map(caseStudy => (\n <div key={caseStudy.id} className=\"carousel-item\">\n <Card className=\"testimonial-card\">\n <div className=\"testimonial-rating\">\n {[1, 2, 3, 4, 5].map(star => (\n <StarOutlined key={star} className=\"star\" />\n ))}\n </div>\n <Paragraph>{caseStudy.testimonial}</Paragraph>\n <div className=\"testimonial-author\">\n <UserOutlined className=\"author-icon\" />\n <div>\n <Text strong>{caseStudy.author}</Text>\n <Text type=\"secondary\">{caseStudy.position}{caseStudy.company}</Text>\n </div>\n </div>\n </Card>\n </div>\n ))}\n </Carousel>\n </div>\n </section>\n\n {/* 行动召唤 */}\n <section className=\"cta\">\n <div className=\"container\">\n <Title level={2}>准备好实现您的业务增长了吗?</Title>\n <Paragraph>加入我们的成功客户行列,开始您的电商增长之旅</Paragraph>\n <Button type=\"primary\" size=\"large\" onClick={() => navigate('/auth/register')}>\n 免费注册\n </Button>\n </div>\n </section>\n\n <style jsx>{`\n .case-study-page {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n }\n\n .case-header {\n padding: 140px 0 40px;\n background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);\n text-align: center;\n }\n\n @media (max-width: 768px) {\n .case-header {\n padding: 120px 0 30px;\n }\n }\n\n .subtitle {\n font-size: 18px;\n color: #666;\n margin: 16px 0;\n }\n\n .category-filter {\n padding: 40px 0;\n background: #fff;\n }\n\n .categories {\n display: flex;\n gap: 12px;\n justify-content: center;\n flex-wrap: wrap;\n }\n\n .case-list {\n padding: 40px 0 80px;\n background: #f5f7fa;\n }\n\n .case-card {\n border-radius: 8px;\n overflow: hidden;\n transition: all 0.3s ease;\n }\n\n .case-card:hover {\n transform: translateY(-8px);\n box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);\n }\n\n .case-image {\n height: 200px;\n overflow: hidden;\n }\n\n .case-image img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transition: transform 0.3s ease;\n }\n\n .case-card:hover .case-image img {\n transform: scale(1.05);\n }\n\n .case-content {\n padding: 24px;\n }\n\n .case-meta {\n margin-bottom: 16px;\n }\n\n .case-challenge,\n .case-solution {\n margin: 12px 0;\n }\n\n .case-results {\n margin: 24px 0;\n }\n\n .case-results ul {\n list-style: none;\n padding: 0;\n margin: 0;\n }\n\n .case-results li {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n }\n\n .result-icon {\n color: #52c41a;\n }\n\n .case-testimonial {\n margin: 24px 0;\n padding: 16px;\n background: #f0f2f5;\n border-radius: 8px;\n }\n\n .testimonial-rating {\n color: #faad14;\n margin-bottom: 16px;\n }\n\n .testimonial-author {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 16px;\n }\n\n .author-icon {\n font-size: 24px;\n color: #1890ff;\n }\n\n .case-button {\n margin-top: 16px;\n }\n\n .pagination {\n margin-top: 40px;\n display: flex;\n justify-content: center;\n }\n\n .testimonial-carousel {\n padding: 80px 0;\n background: #fff;\n }\n\n .carousel {\n margin-top: 40px;\n }\n\n .carousel-item {\n padding: 0 16px;\n }\n\n .testimonial-card {\n padding: 32px;\n border-radius: 8px;\n text-align: center;\n }\n\n .star {\n color: #faad14;\n margin-right: 4px;\n }\n\n .cta {\n padding: 80px 0;\n background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);\n color: #fff;\n text-align: center;\n }\n\n .cta .ant-btn {\n margin-top: 24px;\n }\n\n @media (max-width: 768px) {\n .case-header {\n padding: 60px 0 30px;\n }\n\n .category-filter {\n padding: 30px 0;\n }\n\n .case-list {\n padding: 30px 0 60px;\n }\n\n .testimonial-carousel {\n padding: 60px 0;\n }\n\n .cta {\n padding: 60px 0;\n }\n }\n `}</style>\n </div>\n );\n};\n\nexport default CaseStudy;",
"__isJSFile": true,
"__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/CaseStudy.tsx"
},
"4": {
"path": "/case-study/:id",
"layout": false,
"file": "@/pages/CaseStudy.tsx",
"id": "4",
"absPath": "/case-study/:id",
"__content": "import React, { useState } from 'react';\nimport { Link, useNavigate } from 'umi';\nimport { Card, Button, Typography, Row, Col, Tag, Carousel, Pagination } from 'antd';\nimport { ArrowRightOutlined, CheckCircleOutlined, DollarOutlined, BarChartOutlined, ZapOutlined, GlobeOutlined, StarOutlined, UserOutlined, CompanyOutlined, TrendingUpOutlined } from '@ant-design/icons';\nimport Navbar from '@/components/Navbar';\n\nconst { Title, Paragraph, Text } = Typography;\n\nconst CaseStudy: React.FC = () => {\n const navigate = useNavigate();\n const [activeCategory, setActiveCategory] = useState('all');\n const [currentPage, setCurrentPage] = useState(1);\n\n const caseStudies = [\n {\n id: 1,\n title: '中小商户案例月销售额提升45%',\n category: 'small',\n company: '广州某跨境电商公司',\n industry: '电子产品',\n challenge: '手动选品效率低,定价策略单一,运营成本高',\n solution: '使用智能选品系统和AI动态定价实现自动化运营',\n results: [\n '月销售额提升45%',\n '运营成本降低30%',\n '选品效率提升60%',\n ],\n testimonial: '\"Crawlful Hub帮助我们实现了店铺的自动化运营节省了大量人力成本销售额提升了40%。\"',\n author: '张总',\n position: 'CEO',\n image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',\n },\n {\n id: 2,\n title: '大型企业案例多店铺管理效率提升60%',\n category: 'enterprise',\n company: '深圳某品牌电商',\n industry: '服装行业',\n challenge: '多店铺管理复杂,数据分散,难以统一运营',\n solution: '使用多店铺管理系统,实现数据集中管理和统一运营',\n results: [\n '管理效率提升60%',\n '数据处理时间减少70%',\n '运营成本降低25%',\n ],\n testimonial: '\"多店铺管理功能让我们能够集中管理所有店铺,数据一目了然,大大提高了管理效率。\"',\n author: '李经理',\n position: '运营总监',\n image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',\n },\n {\n id: 3,\n title: '跨境电商案例利润率提升30%',\n category: 'crossborder',\n company: '杭州某跨境电商平台',\n industry: '家居用品',\n challenge: '跨平台价格差异难以把握,利润空间小',\n solution: '使用跨平台套利系统,发现价格差异,优化定价策略',\n results: [\n '利润率提升30%',\n '价格优化效率提升80%',\n '市场竞争力增强',\n ],\n testimonial: '\"跨平台套利系统帮助我们发现了很多价格差异利润率提高了30%,市场竞争力大大增强。\"',\n author: '王女士',\n position: '业务经理',\n image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',\n },\n {\n id: 4,\n title: '新手卖家案例:快速启动电商业务',\n category: 'small',\n company: '上海某个人卖家',\n industry: '美妆产品',\n challenge: '缺乏电商运营经验,选品困难,运营成本高',\n solution: '使用智能选品系统和自动上架功能,快速启动业务',\n results: [\n '业务启动时间缩短50%',\n '选品准确率提升70%',\n '首月销售额达到预期目标',\n ],\n testimonial: '\"作为新手卖家Crawlful Hub帮助我快速启动了电商业务选品和上架都变得非常简单。\"',\n author: '陈先生',\n position: '个人卖家',\n image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',\n },\n {\n id: 5,\n title: '传统企业转型案例线上销售额占比提升至60%',\n category: 'enterprise',\n company: '北京某传统制造企业',\n industry: '机械设备',\n challenge: '线上业务占比低,数字化转型困难',\n solution: '使用全功能电商管理系统,实现线上线下一体化运营',\n results: [\n '线上销售额占比提升至60%',\n '客户获取成本降低40%',\n '品牌知名度提升',\n ],\n testimonial: '\"Crawlful Hub帮助我们成功实现了数字化转型线上销售额占比从10%提升到了60%。\"',\n author: '赵总',\n position: '总经理',\n image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',\n },\n {\n id: 6,\n title: '多平台运营案例管理效率提升70%',\n category: 'crossborder',\n company: '厦门某跨境电商公司',\n industry: '玩具产品',\n challenge: '多平台运营管理复杂,数据不同步,运营效率低',\n solution: '使用多平台集成管理系统,实现数据同步和统一运营',\n results: [\n '管理效率提升70%',\n '数据同步时间减少90%',\n '运营成本降低35%',\n ],\n testimonial: '\"多平台集成管理系统让我们能够统一管理所有平台的店铺,效率大大提升。\"',\n author: '刘经理',\n position: '运营主管',\n image: 'data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%27600%27 height=%27400%27 viewBox=%270 0 600 400%27%3E%3Crect width=%27600%27 height=%27400%27 fill=%27%23f0f2f5%27/%3E%3Ctext x=%2750%25%27 y=%2750%25%27 dominant-baseline=%27middle%27 text-anchor=%27middle%27 font-family=%27Arial%27 font-size=%2716%27 fill=%27%231890ff%27%3E成功案例展示%3C/text%3E%3C/svg%3E',\n },\n ];\n\n const filteredCases = activeCategory === 'all' \n ? caseStudies \n : caseStudies.filter(caseStudy => caseStudy.category === activeCategory);\n\n const itemsPerPage = 3;\n const totalPages = Math.ceil(filteredCases.length / itemsPerPage);\n const currentCases = filteredCases.slice(\n (currentPage - 1) * itemsPerPage,\n currentPage * itemsPerPage\n );\n\n const categories = [\n { value: 'all', label: '全部案例' },\n { value: 'small', label: '中小商户' },\n { value: 'enterprise', label: '大型企业' },\n { value: 'crossborder', label: '跨境电商' },\n ];\n\n return (\n <div className=\"case-study-page\">\n <Navbar />\n {/* 页面头部 */}\n <section className=\"case-header\">\n <div className=\"container\">\n <Title level={1}>成功案例</Title>\n <Paragraph className=\"subtitle\">\n 看看我们如何帮助客户实现业务增长\n </Paragraph>\n </div>\n </section>\n\n {/* 分类筛选 */}\n <section className=\"category-filter\">\n <div className=\"container\">\n <div className=\"categories\">\n {categories.map(category => (\n <Button\n key={category.value}\n type={activeCategory === category.value ? 'primary' : 'default'}\n onClick={() => {\n setActiveCategory(category.value);\n setCurrentPage(1);\n }}\n >\n {category.label}\n </Button>\n ))}\n </div>\n </div>\n </section>\n\n {/* 案例列表 */}\n <section className=\"case-list\">\n <div className=\"container\">\n <Row gutter={[32, 32]}>\n {currentCases.map(caseStudy => (\n <Col key={caseStudy.id} xs={24} md={8}>\n <Card hoverable className=\"case-card\">\n <div className=\"case-image\">\n <img src={caseStudy.image} alt={caseStudy.title} />\n </div>\n <div className=\"case-content\">\n <div className=\"case-meta\">\n <Tag color=\"blue\">{caseStudy.industry}</Tag>\n <Tag color=\"green\">{caseStudy.company}</Tag>\n </div>\n <Title level={4}>{caseStudy.title}</Title>\n <Paragraph className=\"case-challenge\">\n <Text strong>挑战:</Text>{caseStudy.challenge}\n </Paragraph>\n <Paragraph className=\"case-solution\">\n <Text strong>解决方案:</Text>{caseStudy.solution}\n </Paragraph>\n <div className=\"case-results\">\n <Title level={5}>成果:</Title>\n <ul>\n {caseStudy.results.map((result, index) => (\n <li key={index}>\n <CheckCircleOutlined className=\"result-icon\" />\n {result}\n </li>\n ))}\n </ul>\n </div>\n <div className=\"case-testimonial\">\n <div className=\"testimonial-content\">\n <StarOutlined className=\"star\" />\n <StarOutlined className=\"star\" />\n <StarOutlined className=\"star\" />\n <StarOutlined className=\"star\" />\n <StarOutlined className=\"star\" />\n <Paragraph>{caseStudy.testimonial}</Paragraph>\n </div>\n <div className=\"testimonial-author\">\n <UserOutlined className=\"author-icon\" />\n <div>\n <Text strong>{caseStudy.author}</Text>\n <Text type=\"secondary\">{caseStudy.position}</Text>\n </div>\n </div>\n </div>\n <Button type=\"primary\" className=\"case-button\" onClick={() => navigate(`/case-study/${caseStudy.id}`)}>\n 查看详情\n <ArrowRightOutlined />\n </Button>\n </div>\n </Card>\n </Col>\n ))}\n </Row>\n \n {/* 分页 */}\n {totalPages > 1 && (\n <div className=\"pagination\">\n <Pagination\n current={currentPage}\n total={filteredCases.length}\n pageSize={itemsPerPage}\n onChange={setCurrentPage}\n showSizeChanger={false}\n />\n </div>\n )}\n </div>\n </section>\n\n {/* 客户评价轮播 */}\n <section className=\"testimonial-carousel\">\n <div className=\"container\">\n <Title level={2}>客户评价</Title>\n <Carousel autoplay className=\"carousel\">\n {caseStudies.map(caseStudy => (\n <div key={caseStudy.id} className=\"carousel-item\">\n <Card className=\"testimonial-card\">\n <div className=\"testimonial-rating\">\n {[1, 2, 3, 4, 5].map(star => (\n <StarOutlined key={star} className=\"star\" />\n ))}\n </div>\n <Paragraph>{caseStudy.testimonial}</Paragraph>\n <div className=\"testimonial-author\">\n <UserOutlined className=\"author-icon\" />\n <div>\n <Text strong>{caseStudy.author}</Text>\n <Text type=\"secondary\">{caseStudy.position}{caseStudy.company}</Text>\n </div>\n </div>\n </Card>\n </div>\n ))}\n </Carousel>\n </div>\n </section>\n\n {/* 行动召唤 */}\n <section className=\"cta\">\n <div className=\"container\">\n <Title level={2}>准备好实现您的业务增长了吗?</Title>\n <Paragraph>加入我们的成功客户行列,开始您的电商增长之旅</Paragraph>\n <Button type=\"primary\" size=\"large\" onClick={() => navigate('/auth/register')}>\n 免费注册\n </Button>\n </div>\n </section>\n\n <style jsx>{`\n .case-study-page {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n }\n\n .case-header {\n padding: 140px 0 40px;\n background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);\n text-align: center;\n }\n\n @media (max-width: 768px) {\n .case-header {\n padding: 120px 0 30px;\n }\n }\n\n .subtitle {\n font-size: 18px;\n color: #666;\n margin: 16px 0;\n }\n\n .category-filter {\n padding: 40px 0;\n background: #fff;\n }\n\n .categories {\n display: flex;\n gap: 12px;\n justify-content: center;\n flex-wrap: wrap;\n }\n\n .case-list {\n padding: 40px 0 80px;\n background: #f5f7fa;\n }\n\n .case-card {\n border-radius: 8px;\n overflow: hidden;\n transition: all 0.3s ease;\n }\n\n .case-card:hover {\n transform: translateY(-8px);\n box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);\n }\n\n .case-image {\n height: 200px;\n overflow: hidden;\n }\n\n .case-image img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transition: transform 0.3s ease;\n }\n\n .case-card:hover .case-image img {\n transform: scale(1.05);\n }\n\n .case-content {\n padding: 24px;\n }\n\n .case-meta {\n margin-bottom: 16px;\n }\n\n .case-challenge,\n .case-solution {\n margin: 12px 0;\n }\n\n .case-results {\n margin: 24px 0;\n }\n\n .case-results ul {\n list-style: none;\n padding: 0;\n margin: 0;\n }\n\n .case-results li {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n }\n\n .result-icon {\n color: #52c41a;\n }\n\n .case-testimonial {\n margin: 24px 0;\n padding: 16px;\n background: #f0f2f5;\n border-radius: 8px;\n }\n\n .testimonial-rating {\n color: #faad14;\n margin-bottom: 16px;\n }\n\n .testimonial-author {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 16px;\n }\n\n .author-icon {\n font-size: 24px;\n color: #1890ff;\n }\n\n .case-button {\n margin-top: 16px;\n }\n\n .pagination {\n margin-top: 40px;\n display: flex;\n justify-content: center;\n }\n\n .testimonial-carousel {\n padding: 80px 0;\n background: #fff;\n }\n\n .carousel {\n margin-top: 40px;\n }\n\n .carousel-item {\n padding: 0 16px;\n }\n\n .testimonial-card {\n padding: 32px;\n border-radius: 8px;\n text-align: center;\n }\n\n .star {\n color: #faad14;\n margin-right: 4px;\n }\n\n .cta {\n padding: 80px 0;\n background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);\n color: #fff;\n text-align: center;\n }\n\n .cta .ant-btn {\n margin-top: 24px;\n }\n\n @media (max-width: 768px) {\n .case-header {\n padding: 60px 0 30px;\n }\n\n .category-filter {\n padding: 30px 0;\n }\n\n .case-list {\n padding: 30px 0 60px;\n }\n\n .testimonial-carousel {\n padding: 60px 0;\n }\n\n .cta {\n padding: 60px 0;\n }\n }\n `}</style>\n </div>\n );\n};\n\nexport default CaseStudy;",
"__isJSFile": true,
"__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/CaseStudy.tsx"
},
"5": {
"path": "/auth",
"layout": false,
"id": "5",
"absPath": "/auth"
},
"6": {
"path": "login",
"file": "@/pages/Auth/LoginPage.tsx",
"parentId": "5",
"id": "6",
"absPath": "/auth/login",
"__content": "import React, { useState } from 'react';\nimport { useNavigate } from 'umi';\nimport {\n Card,\n Form,\n Input,\n Button,\n Checkbox,\n Space,\n Divider,\n Typography,\n Alert,\n message,\n Row,\n Col,\n Image,\n} from 'antd';\nimport {\n UserOutlined,\n LockOutlined,\n SafetyOutlined,\n EyeInvisibleOutlined,\n EyeTwoTone,\n LoginOutlined,\n GoogleOutlined,\n GithubOutlined,\n} from '@ant-design/icons';\n\nconst { Title, Text, Link } = Typography;\n\ninterface LoginFormValues {\n username: string;\n password: string;\n remember: boolean;\n captcha?: string;\n}\n\nexport const LoginPage: React.FC = () => {\n const [form] = Form.useForm();\n const [loading, setLoading] = useState(false);\n const [loginError, setLoginError] = useState<string | null>(null);\n const [captchaCode, setCaptchaCode] = useState('');\n const navigate = useNavigate();\n\n const generateCaptcha = () => {\n const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';\n let result = '';\n for (let i = 0; i < 4; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n setCaptchaCode(result);\n };\n\n React.useEffect(() => {\n generateCaptcha();\n }, []);\n\n const handleLogin = async (values: LoginFormValues) => {\n setLoading(true);\n setLoginError(null);\n\n try {\n await new Promise(resolve => setTimeout(resolve, 1500));\n\n if (values.captcha?.toUpperCase() !== captchaCode) {\n setLoginError('Invalid verification code');\n generateCaptcha();\n setLoading(false);\n return;\n }\n\n message.success('Login successful! Redirecting...');\n setTimeout(() => {\n navigate('/dashboard');\n }, 1000);\n } catch (error) {\n setLoginError('Login failed. Please check your credentials.');\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <div style={{\n minHeight: '100vh',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',\n padding: 24,\n }}>\n <Row gutter={[48, 0]} align=\"middle\" style={{ maxWidth: 1000, width: '100%' }}>\n <Col xs={0} md={12}>\n <div style={{ color: 'white', paddingRight: 48 }}>\n <Title level={1} style={{ color: 'white', marginBottom: 24 }}>\n Crawlful Hub\n </Title>\n <Text style={{ color: 'rgba(255,255,255,0.9)', fontSize: 18, display: 'block', marginBottom: 32 }}>\n Your all-in-one cross-border e-commerce management platform\n </Text>\n <Space direction=\"vertical\" size=\"large\" style={{ color: 'rgba(255,255,255,0.8)' }}>\n <div>✓ Multi-platform integration</div>\n <div>✓ Automated operations</div>\n <div>✓ Real-time analytics</div>\n <div>✓ Compliance management</div>\n </Space>\n </div>\n </Col>\n\n <Col xs={24} md={12}>\n <Card\n style={{\n borderRadius: 16,\n boxShadow: '0 20px 60px rgba(0,0,0,0.3)',\n }}\n bodyStyle={{ padding: 40 }}\n >\n <div style={{ textAlign: 'center', marginBottom: 32 }}>\n <Title level={3}>Welcome Back</Title>\n <Text type=\"secondary\">Sign in to your account</Text>\n </div>\n\n {loginError && (\n <Alert\n message={loginError}\n type=\"error\"\n showIcon\n style={{ marginBottom: 24 }}\n closable\n onClose={() => setLoginError(null)}\n />\n )}\n\n <Form\n form={form}\n layout=\"vertical\"\n onFinish={handleLogin}\n initialValues={{ remember: true }}\n >\n <Form.Item\n name=\"username\"\n rules={[\n { required: true, message: 'Please enter your username' },\n { min: 3, message: 'Username must be at least 3 characters' },\n ]}\n >\n <Input\n prefix={<UserOutlined style={{ color: '#bfbfbf' }} />}\n placeholder=\"Username or Email\"\n size=\"large\"\n />\n </Form.Item>\n\n <Form.Item\n name=\"password\"\n rules={[\n { required: true, message: 'Please enter your password' },\n { min: 6, message: 'Password must be at least 6 characters' },\n ]}\n >\n <Input.Password\n prefix={<LockOutlined style={{ color: '#bfbfbf' }} />}\n placeholder=\"Password\"\n size=\"large\"\n iconRender={visible => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)}\n />\n </Form.Item>\n\n <Form.Item>\n <Row gutter={8} align=\"middle\">\n <Col flex=\"auto\">\n <Form.Item\n name=\"captcha\"\n noStyle\n rules={[{ required: true, message: 'Please enter verification code' }]}\n >\n <Input\n prefix={<SafetyOutlined style={{ color: '#bfbfbf' }} />}\n placeholder=\"Verification Code\"\n size=\"large\"\n maxLength={4}\n />\n </Form.Item>\n </Col>\n <Col>\n <div\n onClick={generateCaptcha}\n style={{\n width: 100,\n height: 40,\n background: '#f0f2f5',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontFamily: 'monospace',\n fontSize: 20,\n letterSpacing: 4,\n cursor: 'pointer',\n userSelect: 'none',\n borderRadius: 4,\n color: '#1890ff',\n fontWeight: 'bold',\n }}\n >\n {captchaCode}\n </div>\n </Col>\n </Row>\n </Form.Item>\n\n <Form.Item>\n <Row justify=\"space-between\" align=\"middle\">\n <Col>\n <Form.Item name=\"remember\" valuePropName=\"checked\" noStyle>\n <Checkbox>Remember me</Checkbox>\n </Form.Item>\n </Col>\n <Col>\n <Link href=\"/auth/reset-password\">Forgot password?</Link>\n </Col>\n </Row>\n </Form.Item>\n\n <Form.Item>\n <Button\n type=\"primary\"\n htmlType=\"submit\"\n size=\"large\"\n block\n loading={loading}\n icon={<LoginOutlined />}\n >\n Sign In\n </Button>\n </Form.Item>\n\n <Divider>Or continue with</Divider>\n\n <Space style={{ width: '100%', justifyContent: 'center' }}>\n <Button icon={<GoogleOutlined />} size=\"large\">\n Google\n </Button>\n <Button icon={<GithubOutlined />} size=\"large\">\n GitHub\n </Button>\n </Space>\n\n <div style={{ textAlign: 'center', marginTop: 24 }}>\n <Text type=\"secondary\">\n Don't have an account? <Link href=\"/auth/register\">Sign up</Link>\n </Text>\n </div>\n </Form>\n </Card>\n </Col>\n </Row>\n </div>\n );\n};\n\nexport default LoginPage;\n",
"__isJSFile": true,
"__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/Auth/LoginPage.tsx"
},
"7": {
"path": "register",
"file": "@/pages/Auth/RegisterPage.tsx",
"parentId": "5",
"id": "7",
"absPath": "/auth/register",
"__content": "import React, { useState } from 'react';\nimport {\n Card,\n Form,\n Input,\n Button,\n Checkbox,\n Space,\n Divider,\n Typography,\n Alert,\n message,\n Steps,\n Row,\n Col,\n Select,\n} from 'antd';\nimport {\n UserOutlined,\n LockOutlined,\n MailOutlined,\n SafetyOutlined,\n EyeInvisibleOutlined,\n EyeTwoTone,\n UserAddOutlined,\n CheckCircleOutlined,\n ArrowLeftOutlined,\n ArrowRightOutlined,\n BankOutlined,\n PhoneOutlined,\n} from '@ant-design/icons';\n\nconst { Title, Text, Link } = Typography;\nconst { Step } = Steps;\nconst { Option } = Select;\n\ninterface RegisterFormValues {\n username: string;\n email: string;\n password: string;\n confirmPassword: string;\n companyName: string;\n phone: string;\n businessType: string;\n agreeTerms: boolean;\n captcha: string;\n}\n\nexport const RegisterPage: React.FC = () => {\n const [form] = Form.useForm();\n const [currentStep, setCurrentStep] = useState(0);\n const [loading, setLoading] = useState(false);\n const [registerError, setRegisterError] = useState<string | null>(null);\n const [captchaCode, setCaptchaCode] = useState('');\n const [registrationComplete, setRegistrationComplete] = useState(false);\n\n const generateCaptcha = () => {\n const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';\n let result = '';\n for (let i = 0; i < 4; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n setCaptchaCode(result);\n };\n\n React.useEffect(() => {\n generateCaptcha();\n }, []);\n\n const steps = [\n { title: 'Account', description: 'Basic info' },\n { title: 'Business', description: 'Company details' },\n { title: 'Verify', description: 'Confirmation' },\n ];\n\n const nextStep = async () => {\n try {\n if (currentStep === 0) {\n await form.validateFields(['username', 'email', 'password', 'confirmPassword']);\n } else if (currentStep === 1) {\n await form.validateFields(['companyName', 'phone', 'businessType']);\n }\n setCurrentStep(currentStep + 1);\n } catch (error) {\n // Validation failed\n }\n };\n\n const prevStep = () => {\n setCurrentStep(currentStep - 1);\n };\n\n const handleRegister = async (values: RegisterFormValues) => {\n setLoading(true);\n setRegisterError(null);\n\n try {\n await new Promise(resolve => setTimeout(resolve, 2000));\n\n if (values.captcha?.toUpperCase() !== captchaCode) {\n setRegisterError('Invalid verification code');\n generateCaptcha();\n setLoading(false);\n return;\n }\n\n setRegistrationComplete(true);\n message.success('Registration successful!');\n } catch (error) {\n setRegisterError('Registration failed. Please try again.');\n } finally {\n setLoading(false);\n }\n };\n\n if (registrationComplete) {\n return (\n <div style={{\n minHeight: '100vh',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',\n padding: 24,\n }}>\n <Card style={{ maxWidth: 500, width: '100%', textAlign: 'center', borderRadius: 16 }}>\n <CheckCircleOutlined style={{ fontSize: 80, color: '#52c41a', marginBottom: 24 }} />\n <Title level={3}>Registration Complete!</Title>\n <Text type=\"secondary\" style={{ display: 'block', marginBottom: 24 }}>\n Your account has been created successfully. Please check your email to verify your account.\n </Text>\n <Button type=\"primary\" size=\"large\" href=\"/auth/login\">\n Go to Login\n </Button>\n </Card>\n </div>\n );\n }\n\n return (\n <div style={{\n minHeight: '100vh',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',\n padding: 24,\n }}>\n <Card\n style={{\n maxWidth: 600,\n width: '100%',\n borderRadius: 16,\n boxShadow: '0 20px 60px rgba(0,0,0,0.3)',\n }}\n bodyStyle={{ padding: 40 }}\n >\n <div style={{ textAlign: 'center', marginBottom: 32 }}>\n <Title level={3}>Create Account</Title>\n <Text type=\"secondary\">Join Crawlful Hub today</Text>\n </div>\n\n <Steps current={currentStep} style={{ marginBottom: 32 }}>\n {steps.map(step => (\n <Step key={step.title} title={step.title} description={step.description} />\n ))}\n </Steps>\n\n {registerError && (\n <Alert\n message={registerError}\n type=\"error\"\n showIcon\n style={{ marginBottom: 24 }}\n closable\n onClose={() => setRegisterError(null)}\n />\n )}\n\n <Form\n form={form}\n layout=\"vertical\"\n onFinish={handleRegister}\n >\n {currentStep === 0 && (\n <>\n <Form.Item\n name=\"username\"\n rules={[\n { required: true, message: 'Please enter username' },\n { min: 3, message: 'Username must be at least 3 characters' },\n { pattern: /^[a-zA-Z0-9_]+$/, message: 'Only letters, numbers and underscores allowed' },\n ]}\n >\n <Input\n prefix={<UserOutlined style={{ color: '#bfbfbf' }} />}\n placeholder=\"Username\"\n size=\"large\"\n />\n </Form.Item>\n\n <Form.Item\n name=\"email\"\n rules={[\n { required: true, message: 'Please enter email' },\n { type: 'email', message: 'Please enter valid email' },\n ]}\n >\n <Input\n prefix={<MailOutlined style={{ color: '#bfbfbf' }} />}\n placeholder=\"Email\"\n size=\"large\"\n />\n </Form.Item>\n\n <Form.Item\n name=\"password\"\n rules={[\n { required: true, message: 'Please enter password' },\n { min: 8, message: 'Password must be at least 8 characters' },\n { pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)/, message: 'Must contain uppercase, lowercase and number' },\n ]}\n >\n <Input.Password\n prefix={<LockOutlined style={{ color: '#bfbfbf' }} />}\n placeholder=\"Password\"\n size=\"large\"\n iconRender={visible => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)}\n />\n </Form.Item>\n\n <Form.Item\n name=\"confirmPassword\"\n dependencies={['password']}\n rules={[\n { required: true, message: 'Please confirm password' },\n ({ getFieldValue }) => ({\n validator(_, value) {\n if (!value || getFieldValue('password') === value) {\n return Promise.resolve();\n }\n return Promise.reject(new Error('Passwords do not match'));\n },\n }),\n ]}\n >\n <Input.Password\n prefix={<LockOutlined style={{ color: '#bfbfbf' }} />}\n placeholder=\"Confirm Password\"\n size=\"large\"\n iconRender={visible => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)}\n />\n </Form.Item>\n </>\n )}\n\n {currentStep === 1 && (\n <>\n <Form.Item\n name=\"companyName\"\n rules={[{ required: true, message: 'Please enter company name' }]}\n >\n <Input\n prefix={<BankOutlined style={{ color: '#bfbfbf' }} />}\n placeholder=\"Company Name\"\n size=\"large\"\n />\n </Form.Item>\n\n <Form.Item\n name=\"phone\"\n rules={[\n { required: true, message: 'Please enter phone number' },\n { pattern: /^\\+?[\\d\\s-()]+$/, message: 'Please enter valid phone number' },\n ]}\n >\n <Input\n prefix={<PhoneOutlined style={{ color: '#bfbfbf' }} />}\n placeholder=\"Phone Number\"\n size=\"large\"\n />\n </Form.Item>\n\n <Form.Item\n name=\"businessType\"\n rules={[{ required: true, message: 'Please select business type' }]}\n >\n <Select placeholder=\"Business Type\" size=\"large\">\n <Option value=\"manufacturer\">Manufacturer</Option>\n <Option value=\"trading\">Trading Company</Option>\n <Option value=\"wholesaler\">Wholesaler</Option>\n <Option value=\"retailer\">Retailer</Option>\n <Option value=\"other\">Other</Option>\n </Select>\n </Form.Item>\n </>\n )}\n\n {currentStep === 2 && (\n <>\n <Form.Item\n name=\"captcha\"\n rules={[{ required: true, message: 'Please enter verification code' }]}\n >\n <Row gutter={8} align=\"middle\">\n <Col flex=\"auto\">\n <Input\n prefix={<SafetyOutlined style={{ color: '#bfbfbf' }} />}\n placeholder=\"Verification Code\"\n size=\"large\"\n maxLength={4}\n />\n </Col>\n <Col>\n <div\n onClick={generateCaptcha}\n style={{\n width: 100,\n height: 40,\n background: '#f0f2f5',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontFamily: 'monospace',\n fontSize: 20,\n letterSpacing: 4,\n cursor: 'pointer',\n userSelect: 'none',\n borderRadius: 4,\n color: '#1890ff',\n fontWeight: 'bold',\n }}\n >\n {captchaCode}\n </div>\n </Col>\n </Row>\n </Form.Item>\n\n <Form.Item\n name=\"agreeTerms\"\n valuePropName=\"checked\"\n rules={[\n {\n validator: (_, value) =>\n value ? Promise.resolve() : Promise.reject(new Error('Please agree to terms')),\n },\n ]}\n >\n <Checkbox>\n I agree to the <Link href=\"/terms\">Terms of Service</Link> and{' '}\n <Link href=\"/privacy\">Privacy Policy</Link>\n </Checkbox>\n </Form.Item>\n </>\n )}\n\n <Form.Item>\n <Row justify=\"space-between\">\n <Col>\n {currentStep > 0 && (\n <Button icon={<ArrowLeftOutlined />} onClick={prevStep}>\n Previous\n </Button>\n )}\n </Col>\n <Col>\n {currentStep < 2 ? (\n <Button type=\"primary\" icon={<ArrowRightOutlined />} onClick={nextStep}>\n Next\n </Button>\n ) : (\n <Button\n type=\"primary\"\n htmlType=\"submit\"\n loading={loading}\n icon={<UserAddOutlined />}\n >\n Create Account\n </Button>\n )}\n </Col>\n </Row>\n </Form.Item>\n </Form>\n\n <Divider />\n\n <div style={{ textAlign: 'center' }}>\n <Text type=\"secondary\">\n Already have an account? <Link href=\"/auth/login\">Sign in</Link>\n </Text>\n </div>\n </Card>\n </div>\n );\n};\n\nexport default RegisterPage;\n",
"__isJSFile": true,
"__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/Auth/RegisterPage.tsx"
},
"8": {
"path": "/dashboard",
"layout": "@/layouts/index",
"parentId": "@@/global-layout",
"id": "8",
"absPath": "/dashboard"
},
"9": {
"path": "",
"file": "@/pages/OperationAgent.tsx",
"parentId": "8",
"id": "9",
"absPath": "/dashboard",
"__content": "import React, { useState, useEffect } from 'react';\nimport { Button, Table, Form, Input, Select, Modal, message, Card, Tabs, Space, Tag, Divider, Alert } from 'antd';\nimport { PlusOutlined, SyncOutlined, EditOutlined, DeleteOutlined, CheckOutlined, CloseOutlined, LoadingOutlined } from '@ant-design/icons';\nimport { operationAgentService, Store, StoreBindingData } from '../services/operationAgentService';\n\nconst { Option } = Select;\nconst { TabPane } = Tabs;\nconst { TextArea } = Input;\n\nconst platforms = [\n { value: 'amazon', label: 'Amazon' },\n { value: 'shopee', label: 'Shopee' },\n { value: 'aliexpress', label: 'AliExpress' },\n { value: 'tiktok', label: 'TikTok' },\n { value: 'ebay', label: 'Ebay' },\n { value: 'lazada', label: 'Lazada' },\n { value: 'wish', label: 'Wish' },\n { value: 'shein', label: 'Shein' },\n { value: 'jd_worldwide', label: 'JD Worldwide' },\n { value: 'walmart', label: 'Walmart' },\n { value: 'etsy', label: 'Etsy' },\n { value: 'target', label: 'Target' },\n { value: 'newegg', label: 'Newegg' },\n { value: 'cdiscount', label: 'Cdiscount' },\n { value: 'allegro', label: 'Allegro' },\n { value: 'otto', label: 'Otto' },\n { value: 'rakuten', label: 'Rakuten' },\n { value: 'qoo10', label: 'Qoo10' },\n];\n\nconst statusMap = {\n active: { color: 'green', text: '活跃' },\n inactive: { color: 'red', text: '停用' },\n pending: { color: 'orange', text: '待处理' },\n suspended: { color: 'gray', text: '暂停' },\n};\n\nconst OperationAgent: React.FC = () => {\n const [stores, setStores] = useState<Store[]>([]);\n const [loading, setLoading] = useState(false);\n const [bindingModalVisible, setBindingModalVisible] = useState(false);\n const [currentStore, setCurrentStore] = useState<Store | null>(null);\n const [merchantId, setMerchantId] = useState('merchant-1'); // 默认商户ID\n const [form] = Form.useForm();\n\n // 加载店铺列表\n const loadStores = async () => {\n setLoading(true);\n try {\n const data = await operationAgentService.getStores(merchantId);\n setStores(data);\n } catch (error) {\n message.error('加载店铺失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 初始加载\n useEffect(() => {\n loadStores();\n }, [merchantId]);\n\n // 绑定店铺\n const handleBindStore = async (values: any) => {\n setLoading(true);\n try {\n const bindingData: StoreBindingData = {\n merchantId: values.merchantId,\n platform: values.platform,\n platformShopId: values.platformShopId,\n name: values.name,\n description: values.description,\n authInfo: {\n ...(values.platform === 'amazon' && {\n accessKey: values.accessKey,\n secretKey: values.secretKey,\n sellerId: values.sellerId,\n marketplaceId: values.marketplaceId,\n }),\n ...(values.platform === 'shopee' && {\n partnerId: values.partnerId,\n partnerKey: values.partnerKey,\n shopId: values.shopId,\n }),\n ...(values.platform === 'aliexpress' && {\n appKey: values.appKey,\n appSecret: values.appSecret,\n accessToken: values.accessToken,\n }),\n ...(values.platform === 'tiktok' && {\n appId: values.appId,\n appSecret: values.appSecret,\n accessToken: values.accessToken,\n }),\n ...(values.platform === 'ebay' && {\n clientId: values.clientId,\n clientSecret: values.clientSecret,\n refreshToken: values.refreshToken,\n }),\n ...(values.platform && !['amazon', 'shopee', 'aliexpress', 'tiktok', 'ebay'].includes(values.platform) && {\n apiKey: values.apiKey,\n apiSecret: values.apiSecret,\n }),\n },\n };\n\n await operationAgentService.bindStore(bindingData);\n message.success('店铺绑定成功');\n setBindingModalVisible(false);\n form.resetFields();\n loadStores();\n } catch (error) {\n message.error('店铺绑定失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 同步商品\n const handleSyncProducts = async (storeId: string) => {\n setLoading(true);\n try {\n const result = await operationAgentService.syncProducts(storeId);\n if (result.success) {\n message.success(`商品同步成功,共 ${result.count} 个商品`);\n } else {\n message.error('商品同步失败');\n }\n } catch (error) {\n message.error('商品同步失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 同步订单\n const handleSyncOrders = async (storeId: string) => {\n setLoading(true);\n try {\n const result = await operationAgentService.syncOrders(storeId);\n if (result.success) {\n message.success(`订单同步成功,共 ${result.count} 个订单`);\n } else {\n message.error('订单同步失败');\n }\n } catch (error) {\n message.error('订单同步失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 停用店铺\n const handleDeactivateStore = async (storeId: string) => {\n setLoading(true);\n try {\n await operationAgentService.deactivateStore(storeId);\n message.success('店铺已停用');\n loadStores();\n } catch (error) {\n message.error('停用店铺失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 重新激活店铺\n const handleReactivateStore = async (storeId: string) => {\n setLoading(true);\n try {\n await operationAgentService.reactivateStore(storeId);\n message.success('店铺已重新激活');\n loadStores();\n } catch (error) {\n message.error('激活店铺失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 查看店铺详情\n const handleViewStore = async (storeId: string) => {\n setLoading(true);\n try {\n const store = await operationAgentService.getStore(storeId);\n setCurrentStore(store);\n } catch (error) {\n message.error('获取店铺详情失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 渲染平台特定的授权信息表单\n const renderAuthInfoForm = (platform: string) => {\n switch (platform) {\n case 'amazon':\n return (\n <>\n <Form.Item name=\"accessKey\" label=\"Access Key\" rules={[{ required: true, message: '请输入Access Key' }]}>\n <Input placeholder=\"请输入Access Key\" />\n </Form.Item>\n <Form.Item name=\"secretKey\" label=\"Secret Key\" rules={[{ required: true, message: '请输入Secret Key' }]}>\n <Input.Password placeholder=\"请输入Secret Key\" />\n </Form.Item>\n <Form.Item name=\"sellerId\" label=\"Seller ID\" rules={[{ required: true, message: '请输入Seller ID' }]}>\n <Input placeholder=\"请输入Seller ID\" />\n </Form.Item>\n <Form.Item name=\"marketplaceId\" label=\"Marketplace ID\" rules={[{ required: true, message: '请输入Marketplace ID' }]}>\n <Input placeholder=\"请输入Marketplace ID\" />\n </Form.Item>\n </>\n );\n case 'shopee':\n return (\n <>\n <Form.Item name=\"partnerId\" label=\"Partner ID\" rules={[{ required: true, message: '请输入Partner ID' }]}>\n <Input placeholder=\"请输入Partner ID\" />\n </Form.Item>\n <Form.Item name=\"partnerKey\" label=\"Partner Key\" rules={[{ required: true, message: '请输入Partner Key' }]}>\n <Input.Password placeholder=\"请输入Partner Key\" />\n </Form.Item>\n <Form.Item name=\"shopId\" label=\"Shop ID\" rules={[{ required: true, message: '请输入Shop ID' }]}>\n <Input placeholder=\"请输入Shop ID\" />\n </Form.Item>\n </>\n );\n case 'aliexpress':\n return (\n <>\n <Form.Item name=\"appKey\" label=\"App Key\" rules={[{ required: true, message: '请输入App Key' }]}>\n <Input placeholder=\"请输入App Key\" />\n </Form.Item>\n <Form.Item name=\"appSecret\" label=\"App Secret\" rules={[{ required: true, message: '请输入App Secret' }]}>\n <Input.Password placeholder=\"请输入App Secret\" />\n </Form.Item>\n <Form.Item name=\"accessToken\" label=\"Access Token\" rules={[{ required: true, message: '请输入Access Token' }]}>\n <Input placeholder=\"请输入Access Token\" />\n </Form.Item>\n </>\n );\n case 'tiktok':\n return (\n <>\n <Form.Item name=\"appId\" label=\"App ID\" rules={[{ required: true, message: '请输入App ID' }]}>\n <Input placeholder=\"请输入App ID\" />\n </Form.Item>\n <Form.Item name=\"appSecret\" label=\"App Secret\" rules={[{ required: true, message: '请输入App Secret' }]}>\n <Input.Password placeholder=\"请输入App Secret\" />\n </Form.Item>\n <Form.Item name=\"accessToken\" label=\"Access Token\" rules={[{ required: true, message: '请输入Access Token' }]}>\n <Input placeholder=\"请输入Access Token\" />\n </Form.Item>\n </>\n );\n case 'ebay':\n return (\n <>\n <Form.Item name=\"clientId\" label=\"Client ID\" rules={[{ required: true, message: '请输入Client ID' }]}>\n <Input placeholder=\"请输入Client ID\" />\n </Form.Item>\n <Form.Item name=\"clientSecret\" label=\"Client Secret\" rules={[{ required: true, message: '请输入Client Secret' }]}>\n <Input.Password placeholder=\"请输入Client Secret\" />\n </Form.Item>\n <Form.Item name=\"refreshToken\" label=\"Refresh Token\" rules={[{ required: true, message: '请输入Refresh Token' }]}>\n <Input placeholder=\"请输入Refresh Token\" />\n </Form.Item>\n </>\n );\n default:\n return (\n <>\n <Form.Item name=\"apiKey\" label=\"API Key\" rules={[{ required: true, message: '请输入API Key' }]}>\n <Input placeholder=\"请输入API Key\" />\n </Form.Item>\n <Form.Item name=\"apiSecret\" label=\"API Secret\" rules={[{ required: true, message: '请输入API Secret' }]}>\n <Input.Password placeholder=\"请输入API Secret\" />\n </Form.Item>\n </>\n );\n }\n };\n\n return (\n <div style={{ padding: '20px' }}>\n <Card title=\"Operation-Agent 管理\" extra={<Button type=\"primary\" icon={<PlusOutlined />} onClick={() => setBindingModalVisible(true)}>绑定店铺</Button>}>\n <Alert\n message=\"操作说明\"\n description=\"本页面用于管理Operation-Agent平台集成包括店铺绑定、商品/订单同步等功能。\"\n type=\"info\"\n style={{ marginBottom: '20px' }}\n />\n\n <Form layout=\"inline\" onFinish={(values) => setMerchantId(values.merchantId)} style={{ marginBottom: '20px' }}>\n <Form.Item name=\"merchantId\" initialValue={merchantId} label=\"商户ID\">\n <Input placeholder=\"请输入商户ID\" />\n </Form.Item>\n <Form.Item>\n <Button type=\"primary\" htmlType=\"submit\">查询</Button>\n </Form.Item>\n </Form>\n\n <Table\n loading={loading}\n dataSource={stores}\n rowKey=\"id\"\n columns={[\n {\n title: '店铺名称',\n dataIndex: 'name',\n key: 'name',\n },\n {\n title: '平台',\n dataIndex: 'platform',\n key: 'platform',\n render: (platform: string) => {\n const platformInfo = platforms.find(p => p.value === platform);\n return platformInfo ? platformInfo.label : platform;\n },\n },\n {\n title: '平台店铺ID',\n dataIndex: 'platformShopId',\n key: 'platformShopId',\n },\n {\n title: '状态',\n dataIndex: 'status',\n key: 'status',\n render: (status: string) => {\n const statusInfo = statusMap[status as keyof typeof statusMap];\n return statusInfo ? (\n <Tag color={statusInfo.color}>{statusInfo.text}</Tag>\n ) : (\n <Tag color=\"default\">{status}</Tag>\n );\n },\n },\n {\n title: '创建时间',\n dataIndex: 'created_at',\n key: 'created_at',\n },\n {\n title: '操作',\n key: 'action',\n render: (_: any, record: Store) => (\n <Space size=\"middle\">\n <Button icon={<SyncOutlined />} onClick={() => handleSyncProducts(record.id)}>同步商品</Button>\n <Button icon={<SyncOutlined />} onClick={() => handleSyncOrders(record.id)}>同步订单</Button>\n {record.status === 'active' ? (\n <Button danger icon={<CloseOutlined />} onClick={() => handleDeactivateStore(record.id)}>停用</Button>\n ) : (\n <Button type=\"primary\" icon={<CheckOutlined />} onClick={() => handleReactivateStore(record.id)}>激活</Button>\n )}\n </Space>\n ),\n },\n ]}\n />\n </Card>\n\n {/* 绑定店铺模态框 */}\n <Modal\n title=\"绑定店铺\"\n visible={bindingModalVisible}\n onCancel={() => setBindingModalVisible(false)}\n footer={null}\n >\n <Form form={form} layout=\"vertical\" onFinish={handleBindStore}>\n <Form.Item name=\"merchantId\" label=\"商户ID\" rules={[{ required: true, message: '请输入商户ID' }]} initialValue={merchantId}>\n <Input placeholder=\"请输入商户ID\" />\n </Form.Item>\n <Form.Item name=\"platform\" label=\"平台\" rules={[{ required: true, message: '请选择平台' }]}>\n <Select placeholder=\"请选择平台\" onChange={() => form.resetFields(['accessKey', 'secretKey', 'sellerId', 'marketplaceId', 'partnerId', 'partnerKey', 'shopId', 'appKey', 'appSecret', 'accessToken', 'appId', 'clientId', 'clientSecret', 'refreshToken', 'apiKey', 'apiSecret'])}>\n {platforms.map(platform => (\n <Option key={platform.value} value={platform.value}>{platform.label}</Option>\n ))}\n </Select>\n </Form.Item>\n <Form.Item name=\"platformShopId\" label=\"平台店铺ID\" rules={[{ required: true, message: '请输入平台店铺ID' }]}>\n <Input placeholder=\"请输入平台店铺ID\" />\n </Form.Item>\n <Form.Item name=\"name\" label=\"店铺名称\" rules={[{ required: true, message: '请输入店铺名称' }]}>\n <Input placeholder=\"请输入店铺名称\" />\n </Form.Item>\n <Form.Item name=\"description\" label=\"店铺描述\">\n <TextArea placeholder=\"请输入店铺描述\" rows={3} />\n </Form.Item>\n <Divider orientation=\"left\">授权信息</Divider>\n <Form.Item name=\"platform\" noStyle shouldUpdate>\n {({ getFieldValue }) => {\n const platform = getFieldValue('platform');\n return platform ? renderAuthInfoForm(platform) : null;\n }}\n </Form.Item>\n <Form.Item>\n <Space style={{ width: '100%', justifyContent: 'flex-end' }}>\n <Button onClick={() => setBindingModalVisible(false)}>取消</Button>\n <Button type=\"primary\" htmlType=\"submit\" loading={loading}>\n 绑定\n </Button>\n </Space>\n </Form.Item>\n </Form>\n </Modal>\n\n {/* 店铺详情模态框 */}\n {currentStore && (\n <Modal\n title=\"店铺详情\"\n visible={!!currentStore}\n onCancel={() => setCurrentStore(null)}\n footer={null}\n >\n <Card>\n <Card.Meta title={currentStore.name} description={`平台: ${platforms.find(p => p.value === currentStore.platform)?.label || currentStore.platform}`} />\n <Divider />\n <p><strong>商户ID:</strong> {currentStore.merchantId}</p>\n <p><strong>平台店铺ID:</strong> {currentStore.platformShopId}</p>\n <p><strong>状态:</strong> <Tag color={statusMap[currentStore.status as keyof typeof statusMap]?.color || 'default'}>{statusMap[currentStore.status as keyof typeof statusMap]?.text || currentStore.status}</Tag></p>\n <p><strong>描述:</strong> {currentStore.description || '无'}</p>\n <p><strong>创建时间:</strong> {currentStore.created_at}</p>\n <p><strong>更新时间:</strong> {currentStore.updated_at}</p>\n <Divider />\n <Space style={{ width: '100%', justifyContent: 'flex-end' }}>\n <Button onClick={() => setCurrentStore(null)}>关闭</Button>\n </Space>\n </Card>\n </Modal>\n )}\n </div>\n );\n};\n\nexport default OperationAgent;\n",
"__isJSFile": true,
"__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/OperationAgent.tsx"
},
"10": {
"path": "operation-agent",
"file": "@/pages/OperationAgent.tsx",
"parentId": "8",
"id": "10",
"absPath": "/dashboard/operation-agent",
"__content": "import React, { useState, useEffect } from 'react';\nimport { Button, Table, Form, Input, Select, Modal, message, Card, Tabs, Space, Tag, Divider, Alert } from 'antd';\nimport { PlusOutlined, SyncOutlined, EditOutlined, DeleteOutlined, CheckOutlined, CloseOutlined, LoadingOutlined } from '@ant-design/icons';\nimport { operationAgentService, Store, StoreBindingData } from '../services/operationAgentService';\n\nconst { Option } = Select;\nconst { TabPane } = Tabs;\nconst { TextArea } = Input;\n\nconst platforms = [\n { value: 'amazon', label: 'Amazon' },\n { value: 'shopee', label: 'Shopee' },\n { value: 'aliexpress', label: 'AliExpress' },\n { value: 'tiktok', label: 'TikTok' },\n { value: 'ebay', label: 'Ebay' },\n { value: 'lazada', label: 'Lazada' },\n { value: 'wish', label: 'Wish' },\n { value: 'shein', label: 'Shein' },\n { value: 'jd_worldwide', label: 'JD Worldwide' },\n { value: 'walmart', label: 'Walmart' },\n { value: 'etsy', label: 'Etsy' },\n { value: 'target', label: 'Target' },\n { value: 'newegg', label: 'Newegg' },\n { value: 'cdiscount', label: 'Cdiscount' },\n { value: 'allegro', label: 'Allegro' },\n { value: 'otto', label: 'Otto' },\n { value: 'rakuten', label: 'Rakuten' },\n { value: 'qoo10', label: 'Qoo10' },\n];\n\nconst statusMap = {\n active: { color: 'green', text: '活跃' },\n inactive: { color: 'red', text: '停用' },\n pending: { color: 'orange', text: '待处理' },\n suspended: { color: 'gray', text: '暂停' },\n};\n\nconst OperationAgent: React.FC = () => {\n const [stores, setStores] = useState<Store[]>([]);\n const [loading, setLoading] = useState(false);\n const [bindingModalVisible, setBindingModalVisible] = useState(false);\n const [currentStore, setCurrentStore] = useState<Store | null>(null);\n const [merchantId, setMerchantId] = useState('merchant-1'); // 默认商户ID\n const [form] = Form.useForm();\n\n // 加载店铺列表\n const loadStores = async () => {\n setLoading(true);\n try {\n const data = await operationAgentService.getStores(merchantId);\n setStores(data);\n } catch (error) {\n message.error('加载店铺失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 初始加载\n useEffect(() => {\n loadStores();\n }, [merchantId]);\n\n // 绑定店铺\n const handleBindStore = async (values: any) => {\n setLoading(true);\n try {\n const bindingData: StoreBindingData = {\n merchantId: values.merchantId,\n platform: values.platform,\n platformShopId: values.platformShopId,\n name: values.name,\n description: values.description,\n authInfo: {\n ...(values.platform === 'amazon' && {\n accessKey: values.accessKey,\n secretKey: values.secretKey,\n sellerId: values.sellerId,\n marketplaceId: values.marketplaceId,\n }),\n ...(values.platform === 'shopee' && {\n partnerId: values.partnerId,\n partnerKey: values.partnerKey,\n shopId: values.shopId,\n }),\n ...(values.platform === 'aliexpress' && {\n appKey: values.appKey,\n appSecret: values.appSecret,\n accessToken: values.accessToken,\n }),\n ...(values.platform === 'tiktok' && {\n appId: values.appId,\n appSecret: values.appSecret,\n accessToken: values.accessToken,\n }),\n ...(values.platform === 'ebay' && {\n clientId: values.clientId,\n clientSecret: values.clientSecret,\n refreshToken: values.refreshToken,\n }),\n ...(values.platform && !['amazon', 'shopee', 'aliexpress', 'tiktok', 'ebay'].includes(values.platform) && {\n apiKey: values.apiKey,\n apiSecret: values.apiSecret,\n }),\n },\n };\n\n await operationAgentService.bindStore(bindingData);\n message.success('店铺绑定成功');\n setBindingModalVisible(false);\n form.resetFields();\n loadStores();\n } catch (error) {\n message.error('店铺绑定失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 同步商品\n const handleSyncProducts = async (storeId: string) => {\n setLoading(true);\n try {\n const result = await operationAgentService.syncProducts(storeId);\n if (result.success) {\n message.success(`商品同步成功,共 ${result.count} 个商品`);\n } else {\n message.error('商品同步失败');\n }\n } catch (error) {\n message.error('商品同步失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 同步订单\n const handleSyncOrders = async (storeId: string) => {\n setLoading(true);\n try {\n const result = await operationAgentService.syncOrders(storeId);\n if (result.success) {\n message.success(`订单同步成功,共 ${result.count} 个订单`);\n } else {\n message.error('订单同步失败');\n }\n } catch (error) {\n message.error('订单同步失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 停用店铺\n const handleDeactivateStore = async (storeId: string) => {\n setLoading(true);\n try {\n await operationAgentService.deactivateStore(storeId);\n message.success('店铺已停用');\n loadStores();\n } catch (error) {\n message.error('停用店铺失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 重新激活店铺\n const handleReactivateStore = async (storeId: string) => {\n setLoading(true);\n try {\n await operationAgentService.reactivateStore(storeId);\n message.success('店铺已重新激活');\n loadStores();\n } catch (error) {\n message.error('激活店铺失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 查看店铺详情\n const handleViewStore = async (storeId: string) => {\n setLoading(true);\n try {\n const store = await operationAgentService.getStore(storeId);\n setCurrentStore(store);\n } catch (error) {\n message.error('获取店铺详情失败');\n console.error(error);\n } finally {\n setLoading(false);\n }\n };\n\n // 渲染平台特定的授权信息表单\n const renderAuthInfoForm = (platform: string) => {\n switch (platform) {\n case 'amazon':\n return (\n <>\n <Form.Item name=\"accessKey\" label=\"Access Key\" rules={[{ required: true, message: '请输入Access Key' }]}>\n <Input placeholder=\"请输入Access Key\" />\n </Form.Item>\n <Form.Item name=\"secretKey\" label=\"Secret Key\" rules={[{ required: true, message: '请输入Secret Key' }]}>\n <Input.Password placeholder=\"请输入Secret Key\" />\n </Form.Item>\n <Form.Item name=\"sellerId\" label=\"Seller ID\" rules={[{ required: true, message: '请输入Seller ID' }]}>\n <Input placeholder=\"请输入Seller ID\" />\n </Form.Item>\n <Form.Item name=\"marketplaceId\" label=\"Marketplace ID\" rules={[{ required: true, message: '请输入Marketplace ID' }]}>\n <Input placeholder=\"请输入Marketplace ID\" />\n </Form.Item>\n </>\n );\n case 'shopee':\n return (\n <>\n <Form.Item name=\"partnerId\" label=\"Partner ID\" rules={[{ required: true, message: '请输入Partner ID' }]}>\n <Input placeholder=\"请输入Partner ID\" />\n </Form.Item>\n <Form.Item name=\"partnerKey\" label=\"Partner Key\" rules={[{ required: true, message: '请输入Partner Key' }]}>\n <Input.Password placeholder=\"请输入Partner Key\" />\n </Form.Item>\n <Form.Item name=\"shopId\" label=\"Shop ID\" rules={[{ required: true, message: '请输入Shop ID' }]}>\n <Input placeholder=\"请输入Shop ID\" />\n </Form.Item>\n </>\n );\n case 'aliexpress':\n return (\n <>\n <Form.Item name=\"appKey\" label=\"App Key\" rules={[{ required: true, message: '请输入App Key' }]}>\n <Input placeholder=\"请输入App Key\" />\n </Form.Item>\n <Form.Item name=\"appSecret\" label=\"App Secret\" rules={[{ required: true, message: '请输入App Secret' }]}>\n <Input.Password placeholder=\"请输入App Secret\" />\n </Form.Item>\n <Form.Item name=\"accessToken\" label=\"Access Token\" rules={[{ required: true, message: '请输入Access Token' }]}>\n <Input placeholder=\"请输入Access Token\" />\n </Form.Item>\n </>\n );\n case 'tiktok':\n return (\n <>\n <Form.Item name=\"appId\" label=\"App ID\" rules={[{ required: true, message: '请输入App ID' }]}>\n <Input placeholder=\"请输入App ID\" />\n </Form.Item>\n <Form.Item name=\"appSecret\" label=\"App Secret\" rules={[{ required: true, message: '请输入App Secret' }]}>\n <Input.Password placeholder=\"请输入App Secret\" />\n </Form.Item>\n <Form.Item name=\"accessToken\" label=\"Access Token\" rules={[{ required: true, message: '请输入Access Token' }]}>\n <Input placeholder=\"请输入Access Token\" />\n </Form.Item>\n </>\n );\n case 'ebay':\n return (\n <>\n <Form.Item name=\"clientId\" label=\"Client ID\" rules={[{ required: true, message: '请输入Client ID' }]}>\n <Input placeholder=\"请输入Client ID\" />\n </Form.Item>\n <Form.Item name=\"clientSecret\" label=\"Client Secret\" rules={[{ required: true, message: '请输入Client Secret' }]}>\n <Input.Password placeholder=\"请输入Client Secret\" />\n </Form.Item>\n <Form.Item name=\"refreshToken\" label=\"Refresh Token\" rules={[{ required: true, message: '请输入Refresh Token' }]}>\n <Input placeholder=\"请输入Refresh Token\" />\n </Form.Item>\n </>\n );\n default:\n return (\n <>\n <Form.Item name=\"apiKey\" label=\"API Key\" rules={[{ required: true, message: '请输入API Key' }]}>\n <Input placeholder=\"请输入API Key\" />\n </Form.Item>\n <Form.Item name=\"apiSecret\" label=\"API Secret\" rules={[{ required: true, message: '请输入API Secret' }]}>\n <Input.Password placeholder=\"请输入API Secret\" />\n </Form.Item>\n </>\n );\n }\n };\n\n return (\n <div style={{ padding: '20px' }}>\n <Card title=\"Operation-Agent 管理\" extra={<Button type=\"primary\" icon={<PlusOutlined />} onClick={() => setBindingModalVisible(true)}>绑定店铺</Button>}>\n <Alert\n message=\"操作说明\"\n description=\"本页面用于管理Operation-Agent平台集成包括店铺绑定、商品/订单同步等功能。\"\n type=\"info\"\n style={{ marginBottom: '20px' }}\n />\n\n <Form layout=\"inline\" onFinish={(values) => setMerchantId(values.merchantId)} style={{ marginBottom: '20px' }}>\n <Form.Item name=\"merchantId\" initialValue={merchantId} label=\"商户ID\">\n <Input placeholder=\"请输入商户ID\" />\n </Form.Item>\n <Form.Item>\n <Button type=\"primary\" htmlType=\"submit\">查询</Button>\n </Form.Item>\n </Form>\n\n <Table\n loading={loading}\n dataSource={stores}\n rowKey=\"id\"\n columns={[\n {\n title: '店铺名称',\n dataIndex: 'name',\n key: 'name',\n },\n {\n title: '平台',\n dataIndex: 'platform',\n key: 'platform',\n render: (platform: string) => {\n const platformInfo = platforms.find(p => p.value === platform);\n return platformInfo ? platformInfo.label : platform;\n },\n },\n {\n title: '平台店铺ID',\n dataIndex: 'platformShopId',\n key: 'platformShopId',\n },\n {\n title: '状态',\n dataIndex: 'status',\n key: 'status',\n render: (status: string) => {\n const statusInfo = statusMap[status as keyof typeof statusMap];\n return statusInfo ? (\n <Tag color={statusInfo.color}>{statusInfo.text}</Tag>\n ) : (\n <Tag color=\"default\">{status}</Tag>\n );\n },\n },\n {\n title: '创建时间',\n dataIndex: 'created_at',\n key: 'created_at',\n },\n {\n title: '操作',\n key: 'action',\n render: (_: any, record: Store) => (\n <Space size=\"middle\">\n <Button icon={<SyncOutlined />} onClick={() => handleSyncProducts(record.id)}>同步商品</Button>\n <Button icon={<SyncOutlined />} onClick={() => handleSyncOrders(record.id)}>同步订单</Button>\n {record.status === 'active' ? (\n <Button danger icon={<CloseOutlined />} onClick={() => handleDeactivateStore(record.id)}>停用</Button>\n ) : (\n <Button type=\"primary\" icon={<CheckOutlined />} onClick={() => handleReactivateStore(record.id)}>激活</Button>\n )}\n </Space>\n ),\n },\n ]}\n />\n </Card>\n\n {/* 绑定店铺模态框 */}\n <Modal\n title=\"绑定店铺\"\n visible={bindingModalVisible}\n onCancel={() => setBindingModalVisible(false)}\n footer={null}\n >\n <Form form={form} layout=\"vertical\" onFinish={handleBindStore}>\n <Form.Item name=\"merchantId\" label=\"商户ID\" rules={[{ required: true, message: '请输入商户ID' }]} initialValue={merchantId}>\n <Input placeholder=\"请输入商户ID\" />\n </Form.Item>\n <Form.Item name=\"platform\" label=\"平台\" rules={[{ required: true, message: '请选择平台' }]}>\n <Select placeholder=\"请选择平台\" onChange={() => form.resetFields(['accessKey', 'secretKey', 'sellerId', 'marketplaceId', 'partnerId', 'partnerKey', 'shopId', 'appKey', 'appSecret', 'accessToken', 'appId', 'clientId', 'clientSecret', 'refreshToken', 'apiKey', 'apiSecret'])}>\n {platforms.map(platform => (\n <Option key={platform.value} value={platform.value}>{platform.label}</Option>\n ))}\n </Select>\n </Form.Item>\n <Form.Item name=\"platformShopId\" label=\"平台店铺ID\" rules={[{ required: true, message: '请输入平台店铺ID' }]}>\n <Input placeholder=\"请输入平台店铺ID\" />\n </Form.Item>\n <Form.Item name=\"name\" label=\"店铺名称\" rules={[{ required: true, message: '请输入店铺名称' }]}>\n <Input placeholder=\"请输入店铺名称\" />\n </Form.Item>\n <Form.Item name=\"description\" label=\"店铺描述\">\n <TextArea placeholder=\"请输入店铺描述\" rows={3} />\n </Form.Item>\n <Divider orientation=\"left\">授权信息</Divider>\n <Form.Item name=\"platform\" noStyle shouldUpdate>\n {({ getFieldValue }) => {\n const platform = getFieldValue('platform');\n return platform ? renderAuthInfoForm(platform) : null;\n }}\n </Form.Item>\n <Form.Item>\n <Space style={{ width: '100%', justifyContent: 'flex-end' }}>\n <Button onClick={() => setBindingModalVisible(false)}>取消</Button>\n <Button type=\"primary\" htmlType=\"submit\" loading={loading}>\n 绑定\n </Button>\n </Space>\n </Form.Item>\n </Form>\n </Modal>\n\n {/* 店铺详情模态框 */}\n {currentStore && (\n <Modal\n title=\"店铺详情\"\n visible={!!currentStore}\n onCancel={() => setCurrentStore(null)}\n footer={null}\n >\n <Card>\n <Card.Meta title={currentStore.name} description={`平台: ${platforms.find(p => p.value === currentStore.platform)?.label || currentStore.platform}`} />\n <Divider />\n <p><strong>商户ID:</strong> {currentStore.merchantId}</p>\n <p><strong>平台店铺ID:</strong> {currentStore.platformShopId}</p>\n <p><strong>状态:</strong> <Tag color={statusMap[currentStore.status as keyof typeof statusMap]?.color || 'default'}>{statusMap[currentStore.status as keyof typeof statusMap]?.text || currentStore.status}</Tag></p>\n <p><strong>描述:</strong> {currentStore.description || '无'}</p>\n <p><strong>创建时间:</strong> {currentStore.created_at}</p>\n <p><strong>更新时间:</strong> {currentStore.updated_at}</p>\n <Divider />\n <Space style={{ width: '100%', justifyContent: 'flex-end' }}>\n <Button onClick={() => setCurrentStore(null)}>关闭</Button>\n </Space>\n </Card>\n </Modal>\n )}\n </div>\n );\n};\n\nexport default OperationAgent;\n",
"__isJSFile": true,
"__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/OperationAgent.tsx"
},
"@@/global-layout": {
"id": "@@/global-layout",
"path": "/",
"file": "D:/trae_projects/makemd/makemd/dashboard/src/layouts/index.tsx",
"absPath": "/",
"isLayout": true,
"__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/layouts/index.tsx"
}
},
"apiRoutes": {},
"hasSrcDir": true,
"npmClient": "cnpm",
"umi": {
"version": "4.6.31",
"name": "Umi",
"importSource": "umi",
"cliName": "umi"
},
"bundleStatus": {
"done": false
},
"mfsuBundleStatus": {
"done": false
},
"react": {
"version": "18.3.1",
"path": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react"
},
"react-dom": {
"version": "18.3.1",
"path": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-dom"
},
"appJS": {
"path": "D:\\trae_projects\\makemd\\makemd\\dashboard\\src\\app.ts",
"exports": [
"render"
]
},
"locale": "zh-CN",
"globalCSS": [],
"globalJS": [],
"overridesCSS": [],
"bundler": "webpack",
"git": {
"originUrl": "https://github.com/Ansonfishing/makemd.git"
},
"framework": "react",
"typescript": {
"tsVersion": "5.9.3",
"tslibVersion": "2.8.1"
},
"faviconFiles": []
}