feat: 重构前端代码结构并添加Java后端支持

- 重构前端导入和组件结构,优化代码组织
- 添加Java后端基础框架和API实现
- 修复类型定义和接口兼容性问题
- 新增测试页面和工具函数
- 优化国际化支持和错误处理
- 更新依赖配置和构建脚本

新增Java后端模块:
- 实现基础认证、订单、支付等服务
- 添加Swagger API文档支持
- 配置数据库连接和缓存
- 实现国际化消息处理
- 添加安全过滤器和限流控制
This commit is contained in:
2026-03-30 16:51:18 +08:00
parent 1b14947e7b
commit e47beffaf9
199 changed files with 24719 additions and 958 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,9 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { Outlet, useOutletContext } from 'umi';
export default function EmptyRoute() {
const context = useOutletContext();
return <Outlet context={context} />;
}

View File

@@ -0,0 +1,16 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
interface IDefaultRuntimeConfig {
onRouteChange?: (props: { routes: any, clientRoutes: any, location: any, action: any, isFirst: boolean }) => void;
patchRoutes?: (props: { routes: any }) => void;
patchClientRoutes?: (props: { routes: any }) => void;
render?: (oldRender: () => void) => void;
rootContainer?: (lastRootContainer: JSX.Element, args?: any) => void;
[key: string]: any;
}
export type RuntimeConfig = IDefaultRuntimeConfig
export function defineApp(config: RuntimeConfig): RuntimeConfig {
return config;
}

View File

@@ -0,0 +1,10 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { HelmetProvider } from 'D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/renderer-react';
import { context } from './helmetContext';
export const innerProvider = (container) => {
return React.createElement(HelmetProvider, { context }, container);
}

View File

@@ -0,0 +1,4 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
export const context = {};

View File

@@ -0,0 +1,72 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { createHashHistory, createMemoryHistory, createBrowserHistory } from 'D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/renderer-react';
import type { UmiHistory } from './historyIntelli';
let history: UmiHistory;
let basename: string = '/';
export function createHistory(opts: any) {
let h;
if (opts.type === 'hash') {
h = createHashHistory();
} else if (opts.type === 'memory') {
h = createMemoryHistory(opts);
} else {
h = createBrowserHistory();
}
if (opts.basename) {
basename = opts.basename;
}
history = {
...h,
push(to, state) {
h.push(patchTo(to, h), state);
},
replace(to, state) {
h.replace(patchTo(to, h), state);
},
get location() {
return h.location;
},
get action() {
return h.action;
}
}
return h;
}
export function setHistory(h: UmiHistory) {
if (h) {
history = h;
}
}
// Patch `to` to support basename
// Refs:
// https://github.com/remix-run/history/blob/3e9dab4/packages/history/index.ts#L484
// https://github.com/remix-run/history/blob/dev/docs/api-reference.md#to
function patchTo(to: any, h: History) {
if (typeof to === 'string') {
return `${stripLastSlash(basename)}${to}`;
} else if (typeof to === 'object') {
const currentPathname = h.location.pathname;
return {
...to,
pathname: to.pathname? `${stripLastSlash(basename)}${to.pathname}` : currentPathname,
};
} else {
throw new Error(`Unexpected to: ${to}`);
}
}
function stripLastSlash(path) {
return path.slice(-1) === '/' ? path.slice(0, -1) : path;
}
export { history };

View File

@@ -0,0 +1,132 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { getRoutes } from './route'
import type { History } from 'D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/renderer-react'
type Routes = Awaited<ReturnType<typeof getRoutes>>['routes']
type AllRoute = Routes[keyof Routes]
type IsRoot<T extends any> = 'parentId' extends keyof T ? false : true
// show `/` in not `layout / wrapper` only
type GetAllRouteWithoutLayout<Item extends AllRoute> = Item extends any
? 'isWrapper' extends keyof Item
? never
: 'isLayout' extends keyof Item
? never
: Item
: never
type AllRouteWithoutLayout = GetAllRouteWithoutLayout<AllRoute>
type IndexRoutePathname = '/' extends AllRouteWithoutLayout['path']
? '/'
: never
type GetChildrens<T extends any> = T extends any
? IsRoot<T> extends true
? never
: T
: never
type Childrens = GetChildrens<AllRoute>
type Root = Exclude<AllRoute, Childrens>
type AllIds = AllRoute['id']
type GetChildrensByParentId<
Id extends AllIds,
Item = AllRoute
> = Item extends any
? 'parentId' extends keyof Item
? Item['parentId'] extends Id
? Item
: never
: never
: never
type RouteObject<
Id extends AllIds,
Item = GetChildrensByParentId<Id>
> = IsNever<Item> extends true
? ''
: Item extends AllRoute
? {
[Key in Item['path'] as TrimSlash<Key>]: UnionMerge<
RouteObject<Item['id']>
>
}
: never
type GetRootRouteObject<Item extends Root> = Item extends Root
? {
[K in Item['path'] as TrimSlash<K>]: UnionMerge<RouteObject<Item['id']>>
}
: never
type MergedResult = UnionMerge<GetRootRouteObject<Root>>
// --- patch history types ---
type HistoryTo = Parameters<History['push']>['0']
type HistoryPath = Exclude<HistoryTo, string>
type UmiPathname = Path<MergedResult> | (string & {})
interface UmiPath extends HistoryPath {
pathname: UmiPathname
}
type UmiTo = UmiPathname | UmiPath
type UmiPush = (to: UmiTo, state?: any) => void
type UmiReplace = (to: UmiTo, state?: any) => void
export interface UmiHistory extends History {
push: UmiPush
replace: UmiReplace
}
// --- type utils ---
type TrimLeftSlash<T extends string> = T extends `/${infer R}`
? TrimLeftSlash<R>
: T
type TrimRightSlash<T extends string> = T extends `${infer R}/`
? TrimRightSlash<R>
: T
type TrimSlash<T extends string> = TrimLeftSlash<TrimRightSlash<T>>
type IsNever<T> = [T] extends [never] ? true : false
type IsEqual<A, B> = (<G>() => G extends A ? 1 : 2) extends <G>() => G extends B
? 1
: 2
? true
: false
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never
type UnionMerge<U> = UnionToIntersection<U> extends infer O
? { [K in keyof O]: O[K] }
: never
type ExcludeEmptyKey<T> = IsEqual<T, ''> extends true ? never : T
type PathConcat<
TKey extends string,
TValue,
N = TrimSlash<TKey>
> = TValue extends string
? ExcludeEmptyKey<N>
:
| ExcludeEmptyKey<N>
| `${N & string}${IsNever<ExcludeEmptyKey<N>> extends true
? ''
: '/'}${UnionPath<TValue>}`
type UnionPath<T> = {
[K in keyof T]-?: PathConcat<K & string, T[K]>
}[keyof T]
type MakeSureLeftSlash<T> = T extends any
? `/${TrimRightSlash<T & string>}`
: never
// exclude `/*`, because it always at the top of the IDE tip list
type Path<T, K = UnionPath<T>> = Exclude<MakeSureLeftSlash<K>, '/*'> | IndexRoutePathname

View File

@@ -0,0 +1,45 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import * as Plugin_0 from 'D:/trae_projects/makemd/makemd/dashboard/src/app.tsx';
import * as Plugin_1 from '@@/core/helmet.ts';
import { PluginManager } from 'umi';
function __defaultExport (obj) {
if (obj.default) {
return typeof obj.default === 'function' ? obj.default() : obj.default
}
return obj;
}
export function getPlugins() {
return [
{
apply: __defaultExport(Plugin_0),
path: process.env.NODE_ENV === 'production' ? void 0 : 'D:/trae_projects/makemd/makemd/dashboard/src/app.tsx',
},
{
apply: Plugin_1,
path: process.env.NODE_ENV === 'production' ? void 0 : '@@/core/helmet.ts',
},
];
}
export function getValidKeys() {
return ['patchRoutes','patchClientRoutes','modifyContextOpts','modifyClientRenderOpts','rootContainer','innerProvider','i18nProvider','accessProvider','dataflowProvider','outerProvider','render','onRouteChange',];
}
let pluginManager = null;
export function createPluginManager() {
pluginManager = PluginManager.create({
plugins: getPlugins(),
validKeys: getValidKeys(),
});
return pluginManager;
}
export function getPluginManager() {
return pluginManager;
}

View File

@@ -0,0 +1,324 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { IConfigFromPluginsJoi } from "./pluginConfigJoi.d";
interface IConfigTypes {
codeSplitting: {
jsStrategy: "bigVendors" | "depPerChunk" | "granularChunks";
jsStrategyOptions?: ({
} | undefined);
cssStrategy?: ("mergeAll" | undefined);
cssStrategyOptions?: ({
} | undefined);
};
title: string;
styles: Array<string | {
src?: (string | undefined);
} | {
content?: (string | undefined);
} | { [x: string]: any }>;
scripts: Array<string | {
src?: (string | undefined);
} | {
content?: (string | undefined);
} | { [x: string]: any }>;
routes: Array<{
component?: (string | undefined);
layout?: (false | undefined);
path?: (string | undefined);
redirect?: (string | undefined);
routes?: IConfigTypes['routes'];
wrappers?: (Array<string> | undefined);
} | { [x: string]: any }>;
routeLoader: {
moduleType: "esm" | "cjs";
};
reactRouter5Compat: boolean | {
};
presets: Array<string>;
plugins: Array<string>;
npmClient: "pnpm" | "tnpm" | "cnpm" | "yarn" | "npm";
mountElementId: string;
metas: Array<{
charset?: (string | undefined);
content?: (string | undefined);
"http-equiv"?: (string | undefined);
name?: (string | undefined);
} | { [x: string]: any }>;
links: Array<{
crossorigin?: (string | undefined);
href?: (string | undefined);
hreflang?: (string | undefined);
media?: (string | undefined);
referrerpolicy?: (string | undefined);
rel?: (string | undefined);
sizes?: (any | undefined);
title?: (any | undefined);
type?: (any | undefined);
} | { [x: string]: any }>;
historyWithQuery: {
};
history: {
type: "browser" | "hash" | "memory";
};
headScripts: Array<string | {
src?: (string | undefined);
} | {
content?: (string | undefined);
} | { [x: string]: any }>;
esbuildMinifyIIFE: boolean;
conventionRoutes: {
base?: (string | undefined);
exclude?: (Array<any> | undefined);
};
conventionLayout: boolean;
base: string;
analyze: {
};
writeToDisk: boolean;
transformRuntime: { [x: string]: any };
theme: { [x: string]: any };
targets: { [x: string]: any };
svgr: { [x: string]: any };
svgo: { [x: string]: any } | boolean;
stylusLoader: { [x: string]: any };
styleLoader: { [x: string]: any };
srcTranspilerOptions: {
esbuild?: ({ [x: string]: any } | undefined);
swc?: ({ [x: string]: any } | undefined);
};
srcTranspiler: "babel" | "esbuild" | "swc";
sassLoader: { [x: string]: any };
runtimePublicPath: {
};
purgeCSS: { [x: string]: any };
publicPath: string;
proxy: { [x: string]: any } | Array<any>;
postcssLoader: { [x: string]: any };
outputPath: string;
normalCSSLoaderModules: { [x: string]: any };
mfsu: {
cacheDirectory?: (string | undefined);
chainWebpack?: (((...args: any[]) => unknown) | undefined);
esbuild?: (boolean | undefined);
exclude?: (Array<string | any> | undefined);
include?: (Array<string> | undefined);
mfName?: (string | undefined);
remoteAliases?: (Array<string> | undefined);
remoteName?: (string | undefined);
runtimePublicPath?: (boolean | undefined);
shared?: ({ [x: string]: any } | undefined);
strategy?: ("eager" | "normal" | undefined);
} | boolean;
mdx: {
loader?: (string | undefined);
loaderOptions?: ({ [x: string]: any } | undefined);
};
manifest: {
basePath?: (string | undefined);
fileName?: (string | undefined);
};
lessLoader: { [x: string]: any };
jsMinifierOptions: { [x: string]: any };
jsMinifier: "esbuild" | "swc" | "terser" | "uglifyJs" | "none";
inlineLimit: number;
ignoreMomentLocale: boolean;
https: {
cert?: (string | undefined);
hosts?: (Array<string> | undefined);
http2?: (boolean | undefined);
key?: (string | undefined);
};
hash: boolean;
forkTSChecker: { [x: string]: any };
fastRefresh: boolean;
extraPostCSSPlugins: Array<any>;
extraBabelPresets: Array<string | Array<any>>;
extraBabelPlugins: Array<string | Array<any>>;
extraBabelIncludes: Array<string | any>;
externals: { [x: string]: any } | string | ((...args: any[]) => unknown);
esm: {
};
devtool: "cheap-source-map" | "cheap-module-source-map" | "eval" | "eval-source-map" | "eval-cheap-source-map" | "eval-cheap-module-source-map" | "eval-nosources-cheap-source-map" | "eval-nosources-cheap-module-source-map" | "eval-nosources-source-map" | "source-map" | "hidden-source-map" | "hidden-nosources-cheap-source-map" | "hidden-nosources-cheap-module-source-map" | "hidden-nosources-source-map" | "hidden-cheap-source-map" | "hidden-cheap-module-source-map" | "inline-source-map" | "inline-cheap-source-map" | "inline-cheap-module-source-map" | "inline-nosources-cheap-source-map" | "inline-nosources-cheap-module-source-map" | "inline-nosources-source-map" | "nosources-source-map" | "nosources-cheap-source-map" | "nosources-cheap-module-source-map" | boolean;
depTranspiler: "babel" | "esbuild" | "swc" | "none";
define: { [x: string]: any };
deadCode: {
context?: (string | undefined);
detectUnusedExport?: (boolean | undefined);
detectUnusedFiles?: (boolean | undefined);
exclude?: (Array<string> | undefined);
failOnHint?: (boolean | undefined);
patterns?: (Array<string> | undefined);
};
cssPublicPath: string;
cssMinifierOptions: { [x: string]: any };
cssMinifier: "cssnano" | "esbuild" | "parcelCSS" | "none";
cssLoaderModules: { [x: string]: any };
cssLoader: { [x: string]: any };
copy: Array<{
from: string;
to: string;
} | string>;
checkDepCssModules?: boolean;
cacheDirectoryPath: string;
babelLoaderCustomize: string;
autoprefixer: { [x: string]: any };
autoCSSModules: boolean;
alias: { [x: string]: any };
crossorigin: boolean | {
includes?: (Array<any> | undefined);
};
esmi: {
cdnOrigin: string;
shimUrl?: (string | undefined);
};
exportStatic: {
extraRoutePaths?: (((...args: any[]) => unknown) | Array<string> | undefined);
ignorePreRenderError?: (boolean | undefined);
};
favicons: Array<string>;
helmet: boolean;
icons: {
autoInstall?: ({
} | undefined);
defaultComponentConfig?: ({
} | undefined);
alias?: ({
} | undefined);
include?: (Array<string> | undefined);
};
mock: {
exclude?: (Array<string> | undefined);
include?: (Array<string> | undefined);
};
mpa: {
template?: (string | undefined);
layout?: (string | undefined);
getConfigFromEntryFile?: (boolean | undefined);
entry?: ({
} | undefined);
};
phantomDependency: {
exclude?: (Array<string> | undefined);
};
polyfill: {
imports?: (Array<string> | undefined);
};
routePrefetch: {
defaultPrefetch?: ("none" | "intent" | "render" | "viewport" | undefined);
defaultPrefetchTimeout?: (number | undefined);
};
terminal: {
};
tmpFiles: boolean;
clientLoader: {
};
routeProps: {
};
ssr: {
serverBuildPath?: (string | undefined);
serverBuildTarget?: ("express" | "worker" | undefined);
platform?: (string | undefined);
builder?: ("esbuild" | "webpack" | "mako" | undefined);
__INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED?: ({
pureApp?: (boolean | undefined);
pureHtml?: (boolean | undefined);
} | undefined);
useStream?: (boolean | undefined);
};
lowImport: {
libs?: (Array<any> | undefined);
css?: (string | undefined);
};
vite: {
};
apiRoute: {
platform?: (string | undefined);
};
monorepoRedirect: boolean | {
srcDir?: (Array<string> | undefined);
exclude?: (Array<any> | undefined);
peerDeps?: (boolean | undefined);
};
test: {
};
clickToComponent: {
/** 默认情况下点击将默认编辑器为vscode, 你可以设置编辑器 vscode 或者 vscode-insiders */
editor?: (string | undefined);
};
legacy: {
buildOnly?: (boolean | undefined);
nodeModulesTransform?: (boolean | undefined);
checkOutput?: (boolean | undefined);
};
/** 设置 babel class-properties 启用 loose
@doc https://umijs.org/docs/api/config#classpropertiesloose */
classPropertiesLoose: boolean | {
};
ui: {
};
mako: {
plugins?: (Array<{
load?: (((...args: any[]) => unknown) | undefined);
generateEnd?: (((...args: any[]) => unknown) | undefined);
}> | undefined);
px2rem?: ({
root?: (number | undefined);
propBlackList?: (Array<string> | undefined);
propWhiteList?: (Array<string> | undefined);
selectorBlackList?: (Array<string> | undefined);
selectorWhiteList?: (Array<string> | undefined);
selectorDoubleList?: (Array<string> | undefined);
} | undefined);
experimental?: ({
webpackSyntaxValidate?: (Array<string> | undefined);
} | undefined);
flexBugs?: (boolean | undefined);
optimization?: ({
skipModules?: (boolean | undefined);
} | undefined);
};
utoopack: {
};
hmrGuardian: boolean;
forget: {
ReactCompilerConfig?: ({
} | undefined);
};
verifyCommit: {
scope?: (Array<string> | undefined);
allowEmoji?: (boolean | undefined);
};
run: {
globals?: (Array<string> | undefined);
};
};
type PrettifyWithCloseable<T> = {
[K in keyof T]: T[K] | false;
} & {};
export type IConfigFromPlugins = PrettifyWithCloseable<
IConfigFromPluginsJoi & Partial<IConfigTypes>
>;

View File

@@ -0,0 +1,7 @@
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
// Created by Umi Plugin
export interface IConfigFromPluginsJoi {
stagewise?: unknown
}

View File

@@ -0,0 +1,220 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.error.cause.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.aggregate-error.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.aggregate-error.cause.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.array.at.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.array.find-last.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.array.find-last-index.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.array.push.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.array.reduce.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.array.reduce-right.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.array.to-reversed.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.array.to-sorted.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.array.to-spliced.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.array.with.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.map.group-by.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.object.group-by.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.object.has-own.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.promise.any.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.promise.with-resolvers.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.reflect.to-string-tag.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.regexp.flags.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.string.at-alternative.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.string.is-well-formed.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.string.replace-all.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.string.to-well-formed.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.typed-array.at.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.typed-array.find-last.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.typed-array.find-last-index.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.typed-array.set.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.typed-array.to-reversed.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.typed-array.to-sorted.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/es.typed-array.with.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.suppressed-error.constructor.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array.from-async.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array.filter-out.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array.filter-reject.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array.group.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array.group-by.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array.group-by-to-map.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array.group-to-map.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array.is-template-object.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array.last-index.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array.last-item.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array.unique-by.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array-buffer.detached.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array-buffer.transfer.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.array-buffer.transfer-to-fixed-length.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-disposable-stack.constructor.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.constructor.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.as-indexed-pairs.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.async-dispose.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.drop.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.every.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.filter.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.find.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.flat-map.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.for-each.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.from.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.indexed.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.map.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.reduce.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.some.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.take.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.async-iterator.to-array.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.bigint.range.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.composite-key.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.composite-symbol.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.data-view.get-float16.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.data-view.get-uint8-clamped.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.data-view.set-float16.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.data-view.set-uint8-clamped.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.disposable-stack.constructor.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.function.demethodize.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.function.is-callable.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.function.is-constructor.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.function.metadata.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.function.un-this.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.constructor.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.as-indexed-pairs.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.dispose.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.drop.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.every.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.filter.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.find.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.flat-map.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.for-each.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.from.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.indexed.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.map.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.range.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.reduce.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.some.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.take.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.to-array.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.iterator.to-async.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.json.is-raw-json.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.json.parse.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.json.raw-json.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.delete-all.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.emplace.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.every.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.filter.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.find.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.find-key.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.from.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.includes.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.key-by.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.key-of.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.map-keys.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.map-values.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.merge.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.of.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.reduce.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.some.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.update.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.update-or-insert.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.map.upsert.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.clamp.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.deg-per-rad.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.degrees.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.fscale.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.f16round.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.iaddh.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.imulh.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.isubh.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.rad-per-deg.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.radians.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.scale.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.seeded-prng.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.signbit.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.math.umulh.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.number.from-string.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.number.range.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.object.iterate-entries.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.object.iterate-keys.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.object.iterate-values.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.observable.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.promise.try.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.reflect.define-metadata.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.reflect.delete-metadata.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.reflect.get-metadata.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.reflect.get-metadata-keys.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.reflect.get-own-metadata.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.reflect.get-own-metadata-keys.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.reflect.has-metadata.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.reflect.has-own-metadata.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.reflect.metadata.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.regexp.escape.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.add-all.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.delete-all.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.difference.v2.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.difference.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.every.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.filter.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.find.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.from.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.intersection.v2.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.intersection.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.is-disjoint-from.v2.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.is-disjoint-from.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.is-subset-of.v2.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.is-subset-of.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.is-superset-of.v2.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.is-superset-of.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.join.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.map.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.of.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.reduce.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.some.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.symmetric-difference.v2.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.symmetric-difference.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.union.v2.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.set.union.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.string.at.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.string.cooked.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.string.code-points.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.string.dedent.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.symbol.async-dispose.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.symbol.dispose.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.symbol.is-registered-symbol.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.symbol.is-registered.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.symbol.is-well-known-symbol.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.symbol.is-well-known.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.symbol.matcher.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.symbol.metadata.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.symbol.metadata-key.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.symbol.observable.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.symbol.pattern-match.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.symbol.replace-all.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.typed-array.from-async.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.typed-array.filter-out.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.typed-array.filter-reject.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.typed-array.group-by.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.typed-array.to-spliced.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.typed-array.unique-by.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.uint8-array.from-base64.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.uint8-array.from-hex.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.uint8-array.to-base64.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.uint8-array.to-hex.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.weak-map.delete-all.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.weak-map.from.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.weak-map.of.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.weak-map.emplace.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.weak-map.upsert.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.weak-set.add-all.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.weak-set.delete-all.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.weak-set.from.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/esnext.weak-set.of.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/web.dom-exception.stack.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/web.immediate.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/web.self.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/web.structured-clone.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/web.url.can-parse.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/web.url-search-params.delete.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/web.url-search-params.has.js";
import "D:/trae_projects/makemd/makemd/dashboard/node_modules/core-js/modules/web.url-search-params.size.js";
import 'D:/trae_projects/makemd/makemd/dashboard/node_modules/regenerator-runtime/runtime.js';
export {};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,37 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
let count = 0;
let groupLevel = 0;
function send(type: string, message?: string) {
if(process.env.NODE_ENV==='production'){
return;
}else{
const encodedMessage = message ? `&m=${encodeURI(message)}` : '';
fetch(`/__umi/api/terminal?type=${type}&t=${Date.now()}&c=${count++}&g=${groupLevel}${encodedMessage}`, { mode: 'no-cors' })
}
}
function prettyPrint(obj: any) {
return JSON.stringify(obj, null, 2);
}
function stringifyObjs(objs: any[]) {
const obj = objs.length > 1 ? objs.map(stringify).join(' ') : objs[0];
return typeof obj === 'object' ? `${prettyPrint(obj)}` : obj.toString();
}
function stringify(obj: any) {
return typeof obj === 'object' ? `${JSON.stringify(obj)}` : obj.toString();
}
const terminal = {
log(...objs: any[]) { send('log', stringifyObjs(objs)) },
info(...objs: any[]) { send('info', stringifyObjs(objs)) },
warn(...objs: any[]) { send('warn', stringifyObjs(objs)) },
error(...objs: any[]) { send('error', stringifyObjs(objs)) },
group() { groupLevel++ },
groupCollapsed() { groupLevel++ },
groupEnd() { groupLevel && --groupLevel },
clear() { send('clear') },
trace(...args: any[]) { console.trace(...args) },
profile(...args: any[]) { console.profile(...args) },
profileEnd(...args: any[]) { console.profileEnd(...args) },
};
export { terminal };

View File

@@ -0,0 +1,19 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
// defineApp
export { defineApp } from './core/defineApp'
export type { RuntimeConfig } from './core/defineApp'
// plugins
// plugins types.d.ts
// @umijs/renderer-*
export { createBrowserHistory, createHashHistory, createMemoryHistory, Helmet, HelmetProvider, createSearchParams, generatePath, matchPath, matchRoutes, Navigate, NavLink, Outlet, resolvePath, useLocation, useMatch, useNavigate, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes, useSearchParams, useAppData, useClientLoaderData, useLoaderData, useRouteProps, useSelectedRoutes, useServerLoaderData, renderClient, __getRoot, Link, useRouteData, __useFetcher, withRouter } from 'D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/renderer-react';
export type { History, ClientLoader } from 'D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/renderer-react'
// umi/client/client/plugin
export { ApplyPluginsType, PluginManager } from 'D:/trae_projects/makemd/makemd/dashboard/node_modules/umi/client/client/plugin.js';
export { history, createHistory } from './core/history';
export { terminal } from './core/terminal';
// react ssr
export const useServerInsertedHTML: Function = () => {};
// test
export { TestBrowser } from './testBrowser';

View File

@@ -0,0 +1,88 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React, { useEffect, useState } from 'react';
import { ApplyPluginsType } from 'umi';
import { renderClient, RenderClientOpts } from 'D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/renderer-react';
import { createHistory } from './core/history';
import { createPluginManager } from './core/plugin';
import { getRoutes } from './core/route';
import type { Location } from 'history';
const publicPath = '/';
const runtimePublicPath = false;
type TestBrowserProps = {
location?: Partial<Location>;
historyRef?: React.MutableRefObject<Location>;
};
export function TestBrowser(props: TestBrowserProps) {
const pluginManager = createPluginManager();
const [context, setContext] = useState<RenderClientOpts | undefined>(
undefined
);
useEffect(() => {
const genContext = async () => {
const { routes, routeComponents } = await getRoutes(pluginManager);
// allow user to extend routes
await pluginManager.applyPlugins({
key: 'patchRoutes',
type: ApplyPluginsType.event,
args: {
routes,
routeComponents,
},
});
const contextOpts = pluginManager.applyPlugins({
key: 'modifyContextOpts',
type: ApplyPluginsType.modify,
initialValue: {},
});
const basename = contextOpts.basename || '/';
const history = createHistory({
type: 'memory',
basename,
});
const context = {
routes,
routeComponents,
pluginManager,
rootElement: contextOpts.rootElement || document.getElementById('root'),
publicPath,
runtimePublicPath,
history,
basename,
components: true,
};
const modifiedContext = pluginManager.applyPlugins({
key: 'modifyClientRenderOpts',
type: ApplyPluginsType.modify,
initialValue: context,
});
return modifiedContext;
};
genContext().then((context) => {
setContext(context);
if (props.location) {
context?.history?.push(props.location);
}
if (props.historyRef) {
props.historyRef.current = context?.history;
}
});
}, []);
if (context === undefined) {
return <div id="loading" />;
}
const Children = renderClient(context);
return (
<React.Fragment>
<Children />
</React.Fragment>
);
}

View File

@@ -0,0 +1,44 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"moduleResolution": "bundler",
"importHelpers": true,
"noEmit": true,
"jsx": "react-jsx",
"esModuleInterop": true,
"sourceMap": true,
"baseUrl": "../../",
"strict": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"paths": {
"@/*": [
"src/*"
],
"@@/*": [
"src/.umi/*"
],
"umi": [
"../../node_modules/umi"
],
"umi/typings": [
"src/.umi/typings"
]
}
},
"include": [
"../../.umirc.ts",
"../../.umirc.*.ts",
"../../**/*.d.ts",
"../../**/*.ts",
"../../**/*.tsx"
]
}

View File

@@ -0,0 +1,136 @@
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
type CSSModuleClasses = { readonly [key: string]: string }
declare module '*.css' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.scss' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.sass' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.less' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.styl' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.stylus' {
const classes: CSSModuleClasses
export default classes
}
// images
declare module '*.jpg' {
const src: string
export default src
}
declare module '*.jpeg' {
const src: string
export default src
}
declare module '*.png' {
const src: string
export default src
}
declare module '*.gif' {
const src: string
export default src
}
declare module '*.svg' {
import * as React from 'react';
export const ReactComponent: React.FunctionComponent<React.SVGProps<
SVGSVGElement
> & { title?: string }>;
const src: string
export default src
}
declare module '*.ico' {
const src: string
export default src
}
declare module '*.webp' {
const src: string
export default src
}
declare module '*.avif' {
const src: string
export default src
}
// media
declare module '*.mp4' {
const src: string
export default src
}
declare module '*.webm' {
const src: string
export default src
}
declare module '*.ogg' {
const src: string
export default src
}
declare module '*.mp3' {
const src: string
export default src
}
declare module '*.wav' {
const src: string
export default src
}
declare module '*.flac' {
const src: string
export default src
}
declare module '*.aac' {
const src: string
export default src
}
// fonts
declare module '*.woff' {
const src: string
export default src
}
declare module '*.woff2' {
const src: string
export default src
}
declare module '*.eot' {
const src: string
export default src
}
declare module '*.ttf' {
const src: string
export default src
}
declare module '*.otf' {
const src: string
export default src
}
// other
declare module '*.wasm' {
const initWasm: (options: WebAssembly.Imports) => Promise<WebAssembly.Exports>
export default initWasm
}
declare module '*.webmanifest' {
const src: string
export default src
}
declare module '*.pdf' {
const src: string
export default src
}
declare module '*.txt' {
const src: string
export default src
}

View File

@@ -0,0 +1,81 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import './core/polyfill';
import { renderClient } from 'D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/renderer-react';
import { getRoutes } from './core/route';
import { createPluginManager } from './core/plugin';
import { createHistory } from './core/history';
import { ApplyPluginsType } from 'umi';
const publicPath = "/";
const runtimePublicPath = false;
async function render() {
const pluginManager = createPluginManager();
const { routes, routeComponents } = await getRoutes(pluginManager);
// allow user to extend routes
await pluginManager.applyPlugins({
key: 'patchRoutes',
type: ApplyPluginsType.event,
args: {
routes,
routeComponents,
},
});
const contextOpts = pluginManager.applyPlugins({
key: 'modifyContextOpts',
type: ApplyPluginsType.modify,
initialValue: {},
});
const basename = contextOpts.basename || '/';
const historyType = contextOpts.historyType || 'browser';
const history = createHistory({
type: historyType,
basename,
...contextOpts.historyOpts,
});
return (pluginManager.applyPlugins({
key: 'render',
type: ApplyPluginsType.compose,
initialValue() {
const context = {
useStream: true,
routes,
routeComponents,
pluginManager,
mountElementId: 'root',
rootElement: contextOpts.rootElement || document.getElementById('root'),
publicPath,
runtimePublicPath,
history,
historyType,
basename,
__INTERNAL_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {"pureApp":false,"pureHtml":false},
callback: contextOpts.callback,
};
const modifiedContext = pluginManager.applyPlugins({
key: 'modifyClientRenderOpts',
type: ApplyPluginsType.modify,
initialValue: context,
});
return renderClient(modifiedContext);
},
}))();
}
render();
if (typeof window !== 'undefined') {
window.g_umi = {
version: '4.6.31',
};
}

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import * as Plugin_0 from 'D:/trae_projects/makemd/makemd/dashboard/src/app.ts';
import * as Plugin_0 from 'D:/trae_projects/makemd/makemd/dashboard/src/app.tsx';
import * as Plugin_1 from '@@/core/helmet.ts';
import { PluginManager } from 'umi';
@@ -15,7 +15,7 @@ export function getPlugins() {
return [
{
apply: __defaultExport(Plugin_0),
path: process.env.NODE_ENV === 'production' ? void 0 : 'D:/trae_projects/makemd/makemd/dashboard/src/app.ts',
path: process.env.NODE_ENV === 'production' ? void 0 : 'D:/trae_projects/makemd/makemd/dashboard/src/app.tsx',
},
{
apply: Plugin_1,

File diff suppressed because one or more lines are too long

View File

@@ -1,15 +1,47 @@
import { FC, ReactNode } from '@/imports';
import { ConfigProvider } from 'antd';
import { LocaleProvider as CustomLocaleProvider } from './contexts/LocaleContext';
import React from 'react';
import { UserProvider } from './contexts/UserContext';
import { LocaleProvider } from './contexts/LocaleContext';
import { ThemeProvider } from './contexts/ThemeContext';
const App: FC<{ children: ReactNode }> = ({ children }) => {
return (
<CustomLocaleProvider>
<ConfigProvider>
{children}
</ConfigProvider>
</CustomLocaleProvider>
/**
* 应用启动时执行
* 用于初始化MSW等全局配置
*/
export async function render(oldRender: () => void) {
// 开发环境且启用Mock时初始化MSW
if (process.env.NODE_ENV === 'development' && process.env.REACT_APP_USE_MOCK === 'true') {
console.log('[App] Initializing Mock Service Worker...');
try {
const { startMSW } = await import('./mock/browser');
await startMSW({
onUnhandledRequest: 'bypass',
});
console.log('[App] MSW initialized successfully');
} catch (error) {
console.error('[App] Failed to initialize MSW:', error);
}
}
oldRender();
}
/**
* 包裹全局Providers
* 确保所有组件都能访问到 Context
*/
export function rootContainer(container: React.ReactNode) {
return React.createElement(
ThemeProvider,
null,
React.createElement(
LocaleProvider,
null,
React.createElement(
UserProvider,
null,
container
)
)
);
};
export default App;
}

View File

@@ -1,35 +0,0 @@
/**
* [MOCK-004] Umi运行时配置
* 应用启动时初始化MSW
*
* @module app
* @author AI-Frontend-Team
* @created 2026-03-19
*/
/**
* 应用启动时执行
* 用于初始化MSW等全局配置
*/
export async function render(oldRender: () => void) {
// 开发环境且启用Mock时初始化MSW
if (process.env.NODE_ENV === 'development' && process.env.REACT_APP_USE_MOCK === 'true') {
console.log('[App] Initializing Mock Service Worker...');
try {
const { startMSW } = await import('./mock/browser');
await startMSW({
onUnhandledRequest: 'bypass',
});
console.log('[App] MSW initialized successfully');
} catch (error) {
console.error('[App] Failed to initialize MSW:', error);
}
}
oldRender();
}

View File

@@ -2,8 +2,8 @@ import {
useLocation,
useNavigate,
Link,
} from 'react-router-dom';
import { FC } from 'react';
FC,
} from '@/imports';
import {
Breadcrumb as AntBreadcrumb,
Space,

View File

@@ -1,4 +1,20 @@
// 导出 UI 组件
export * from './ui';
// 导出根目录组件
export { Table } from './Table';
export { VirtualList } from './VirtualList';
export { LazyLoad, LazyImage } from './LazyLoad';
export { LazyLoad, LazyImage } from './LazyLoad';
export { ErrorBoundary } from './ErrorBoundary';
export { default as Navbar } from './Navbar';
export { default as ThemeSwitch } from './ThemeSwitch';
export { default as Breadcrumb } from './Breadcrumb';
export * from './ResponsiveLayout';
// 导出子目录组件
export { default as HierarchySelector } from './HierarchySelector';
export { default as LanguageSwitch } from './LanguageSwitch';
export { default as NotificationCenter } from './NotificationCenter';
export { default as OrderAggregate } from './OrderAggregate';
export { default as AISuggestionDisplay } from './ai-suggestion/AISuggestionDisplay';
export { default as HumanApprovalForm } from './human-approval/HumanApprovalForm';

View File

@@ -207,7 +207,6 @@ const zhCN = {
'product.publish.cancel': '取消',
// Product publish form additional translations
'product.publish.productImages': '商品图片',
'product.publish.images': '图片',
'product.publish.upload': '上传',
'product.publish.pricing': '定价',
'product.publish.profitMarginValidation': '利润率验证',
@@ -327,7 +326,6 @@ const zhCN = {
'autopilot.type': '类型',
'autopilot.task': '任务',
'autopilot.status': '状态',
'autopilot.description': '描述',
'autopilot.duration': '持续时间',
'autopilot.auto': '自动',
'autopilot.enabledFeatures': '已启用功能',
@@ -453,16 +451,12 @@ const zhCN = {
'taskCenter.actualDuration': '实际持续时间',
'taskCenter.result': '结果',
'taskCenter.createNewTask': '创建新任务',
'taskCenter.editTask': '编辑任务',
'taskCenter.taskName': '任务名称',
'taskCenter.enterTaskName': '请输入任务名称',
'taskCenter.taskType': '任务类型',
'taskCenter.selectTaskType': '请选择任务类型',
'taskCenter.priority': '优先级',
'taskCenter.selectPriority': '请选择优先级',
'taskCenter.scheduleType': '调度类型',
'taskCenter.selectScheduleType': '请选择调度类型',
'taskCenter.scheduleTime': '调度时间',
'taskCenter.maxRetries': '最大重试次数',
'taskCenter.enterMaxRetries': '请输入最大重试次数',
@@ -501,23 +495,15 @@ const zhCN = {
'aiActionTaskManager.aiSuggestion': 'AI 建议',
'aiActionTaskManager.executionResult': '执行结果',
'aiActionTaskManager.taskTimeline': '任务时间线',
'aiActionTaskManager.createTask': '创建任务',
'aiActionTaskManager.editTask': '编辑任务',
'aiActionTaskManager.taskName': '任务名称',
'aiActionTaskManager.enterTaskName': '请输入任务名称',
'aiActionTaskManager.actionType': '行动类型',
'aiActionTaskManager.selectActionType': '请选择行动类型',
'aiActionTaskManager.priority': '优先级',
'aiActionTaskManager.selectPriority': '请选择优先级',
'aiActionTaskManager.maxRetries': '最大重试次数',
'aiActionTaskManager.enterMaxRetries': '请输入最大重试次数',
'aiActionTaskManager.estimatedDuration': '预计持续时间(分钟)',
'aiActionTaskManager.enterEstimatedDuration': '请输入预计持续时间',
'aiActionTaskManager.all': '全部',
'aiActionTaskManager.pending': '待处理',
'aiActionTaskManager.analyzing': '分析中',
'aiActionTaskManager.pendingReview': '待审核',
'aiActionTaskManager.executing': '执行中',
'aiActionTaskManager.completed': '已完成',
'aiActionTaskManager.failed': '失败',
'aiActionTaskManager.taskCreated': '任务创建成功',
@@ -620,9 +606,6 @@ const zhCN = {
'humanApproval.custom': '自定义操作',
'humanApproval.pending': '待处理',
'humanApproval.aiAnalyzing': 'AI 分析中',
'humanApproval.pendingReview': '待审核',
'humanApproval.approved': '已批准',
'humanApproval.rejected': '已拒绝',
'humanApproval.aiExecuting': 'AI 执行中',
'humanApproval.completed': '已完成',
'humanApproval.failed': '失败',
@@ -810,7 +793,6 @@ const zhCN = {
'abTest.config.review': '最终检查',
'abTest.config.testName': '测试名称',
'abTest.config.enterTestName': '请输入测试名称',
'abTest.config.description': '描述',
'abTest.config.enterDescription': '请输入测试描述',
'abTest.config.testType': '测试类型',
'abTest.config.selectTestType': '请选择测试类型',
@@ -834,8 +816,6 @@ const zhCN = {
'abTest.config.reviewConfiguration': '审核配置',
'abTest.config.reviewDesc': '请在启动测试前审核所有设置。',
'abTest.config.testDetails': '测试详情',
'abTest.config.variants': '变体',
'abTest.config.audience': '受众',
'abTest.config.saveLaunch': '保存并启动',
'abTest.config.previous': '上一步',
'abTest.config.next': '下一步',
@@ -867,7 +847,6 @@ const zhCN = {
'abTest.results.confidenceLevel': '置信水平',
'abTest.results.testCompleted': '测试已完成',
'abTest.results.variantPerformance': '变体性能',
'abTest.results.visitors': '访问者',
'abTest.results.conversions': '转化',
'abTest.results.conversionRate': '转化率',
'abTest.results.improvement': '改进',
@@ -902,11 +881,9 @@ const zhCN = {
'aiDecisionLog.query': '查询',
'aiDecisionLog.refresh': '刷新',
'aiDecisionLog.decisionId': '决策 ID',
'aiDecisionLog.decisionType': '决策类型',
'aiDecisionLog.businessType': '业务类型',
'aiDecisionLog.decisionContent': '决策内容',
'aiDecisionLog.confidence': '置信度',
'aiDecisionLog.status': '状态',
'aiDecisionLog.executionTime': '执行时间',
'aiDecisionLog.createdTime': '创建时间',
'aiDecisionLog.actions': '操作',
@@ -943,9 +920,7 @@ const zhCN = {
'ad.status': '状态',
'ad.filter': '筛选',
'ad.adName': '广告名称',
'ad.platform': '平台',
'ad.campaign': '活动',
'ad.status': '状态',
'ad.budget': '预算',
'ad.spend': '支出',
'ad.gmv': 'GMV',
@@ -958,10 +933,7 @@ const zhCN = {
'ad.edit': '编辑',
'ad.delete': '删除',
'ad.editAd': '编辑广告',
'ad.createAd': '创建广告',
'ad.adName': '广告名称',
'ad.enterAdName': '请输入广告名称',
'ad.platform': '平台',
'ad.selectPlatform': '请选择平台',
'ad.gmvMaxType': 'GMV Max 类型',
'ad.selectGmvMaxType': '请选择 GMV Max 类型',
@@ -983,7 +955,6 @@ const zhCN = {
'ad.budgetSettings': '预算设置',
'ad.campaignName': '活动名称',
'ad.enterCampaignName': '请输入活动名称',
'ad.status': '状态',
'ad.selectStatus': '请选择状态',
'ad.active': '活跃',
'ad.paused': '暂停',
@@ -993,7 +964,6 @@ const zhCN = {
'ad.dailyBudget': '日预算 ($)',
'ad.enterDailyBudget': '请输入日预算',
'ad.bidStrategy': '出价策略',
'ad.autoBid': '自动出价',
'ad.manualBid': '手动出价',
'ad.targetCpa': '目标CPA',
'ad.targetRoas': '目标ROAS',
@@ -1266,7 +1236,6 @@ const enUS = {
'abTest.config.review': 'Final Check',
'abTest.config.testName': 'Test Name',
'abTest.config.enterTestName': 'Please enter test name',
'abTest.config.description': 'Description',
'abTest.config.enterDescription': 'Please enter test description',
'abTest.config.testType': 'Test Type',
'abTest.config.selectTestType': 'Please select test type',
@@ -1290,8 +1259,6 @@ const enUS = {
'abTest.config.reviewConfiguration': 'Review Configuration',
'abTest.config.reviewDesc': 'Please review all settings before launching the test.',
'abTest.config.testDetails': 'Test Details',
'abTest.config.variants': 'Variants',
'abTest.config.audience': 'Audience',
'abTest.config.saveLaunch': 'Save & Launch',
'abTest.config.previous': 'Previous',
'abTest.config.next': 'Next',
@@ -1323,7 +1290,6 @@ const enUS = {
'abTest.results.confidenceLevel': 'Confidence Level',
'abTest.results.testCompleted': 'Test Completed',
'abTest.results.variantPerformance': 'Variant Performance',
'abTest.results.visitors': 'Visitors',
'abTest.results.conversions': 'Conversions',
'abTest.results.conversionRate': 'Conversion Rate',
'abTest.results.improvement': 'Improvement',
@@ -1358,11 +1324,9 @@ const enUS = {
'aiDecisionLog.query': 'Query',
'aiDecisionLog.refresh': 'Refresh',
'aiDecisionLog.decisionId': 'Decision ID',
'aiDecisionLog.decisionType': 'Decision Type',
'aiDecisionLog.businessType': 'Business Type',
'aiDecisionLog.decisionContent': 'Decision Content',
'aiDecisionLog.confidence': 'Confidence',
'aiDecisionLog.status': 'Status',
'aiDecisionLog.executionTime': 'Execution Time',
'aiDecisionLog.createdTime': 'Created Time',
'aiDecisionLog.actions': 'Actions',
@@ -1399,9 +1363,7 @@ const enUS = {
'ad.status': 'Status',
'ad.filter': 'Filter',
'ad.adName': 'Ad Name',
'ad.platform': 'Platform',
'ad.campaign': 'Campaign',
'ad.status': 'Status',
'ad.budget': 'Budget',
'ad.spend': 'Spend',
'ad.gmv': 'GMV',
@@ -1414,10 +1376,7 @@ const enUS = {
'ad.edit': 'Edit',
'ad.delete': 'Delete',
'ad.editAd': 'Edit Ad',
'ad.createAd': 'Create Ad',
'ad.adName': 'Ad Name',
'ad.enterAdName': 'Please enter ad name',
'ad.platform': 'Platform',
'ad.selectPlatform': 'Please select platform',
'ad.gmvMaxType': 'GMV Max Type',
'ad.selectGmvMaxType': 'Please select GMV Max type',
@@ -1439,7 +1398,6 @@ const enUS = {
'ad.budgetSettings': 'Budget Settings',
'ad.campaignName': 'Campaign Name',
'ad.enterCampaignName': 'Please enter campaign name',
'ad.status': 'Status',
'ad.selectStatus': 'Please select status',
'ad.active': 'Active',
'ad.paused': 'Paused',
@@ -1449,7 +1407,6 @@ const enUS = {
'ad.dailyBudget': 'Daily Budget ($)',
'ad.enterDailyBudget': 'Please enter daily budget',
'ad.bidStrategy': 'Bid Strategy',
'ad.autoBid': 'Auto Bid',
'ad.manualBid': 'Manual Bid',
'ad.targetCpa': 'Target CPA',
'ad.targetRoas': 'Target ROAS',
@@ -1541,7 +1498,6 @@ const enUS = {
'product.publish.cancel': 'Cancel',
// Product publish form additional translations
'product.publish.productImages': 'Product Images',
'product.publish.images': 'Images',
'product.publish.upload': 'Upload',
'product.publish.pricing': 'Pricing',
'product.publish.profitMarginValidation': 'Profit Margin Validation',
@@ -1662,7 +1618,6 @@ const enUS = {
'autopilot.type': 'Type',
'autopilot.task': 'Task',
'autopilot.status': 'Status',
'autopilot.description': 'Description',
'autopilot.duration': 'Duration',
'autopilot.auto': 'Auto',
'autopilot.enabledFeatures': 'Enabled Features',
@@ -1787,16 +1742,12 @@ const enUS = {
'taskCenter.actualDuration': 'Actual Duration',
'taskCenter.result': 'Result',
'taskCenter.createNewTask': 'Create New Task',
'taskCenter.editTask': 'Edit Task',
'taskCenter.taskName': 'Task Name',
'taskCenter.enterTaskName': 'Please enter task name',
'taskCenter.taskType': 'Task Type',
'taskCenter.selectTaskType': 'Please select task type',
'taskCenter.priority': 'Priority',
'taskCenter.selectPriority': 'Please select priority',
'taskCenter.scheduleType': 'Schedule Type',
'taskCenter.selectScheduleType': 'Please select schedule type',
'taskCenter.scheduleTime': 'Schedule Time',
'taskCenter.maxRetries': 'Max Retries',
'taskCenter.enterMaxRetries': 'Please enter max retries',
@@ -1835,23 +1786,15 @@ const enUS = {
'aiActionTaskManager.aiSuggestion': 'AI Suggestion',
'aiActionTaskManager.executionResult': 'Execution Result',
'aiActionTaskManager.taskTimeline': 'Task Timeline',
'aiActionTaskManager.createTask': 'Create Task',
'aiActionTaskManager.editTask': 'Edit Task',
'aiActionTaskManager.taskName': 'Task Name',
'aiActionTaskManager.enterTaskName': 'Please enter task name',
'aiActionTaskManager.actionType': 'Action Type',
'aiActionTaskManager.selectActionType': 'Please select action type',
'aiActionTaskManager.priority': 'Priority',
'aiActionTaskManager.selectPriority': 'Please select priority',
'aiActionTaskManager.maxRetries': 'Max Retries',
'aiActionTaskManager.enterMaxRetries': 'Please enter max retries',
'aiActionTaskManager.estimatedDuration': 'Estimated Duration (minutes)',
'aiActionTaskManager.enterEstimatedDuration': 'Please enter estimated duration',
'aiActionTaskManager.all': 'All',
'aiActionTaskManager.pending': 'Pending',
'aiActionTaskManager.analyzing': 'Analyzing',
'aiActionTaskManager.pendingReview': 'Pending Review',
'aiActionTaskManager.executing': 'Executing',
'aiActionTaskManager.completed': 'Completed',
'aiActionTaskManager.failed': 'Failed',
'aiActionTaskManager.taskCreated': 'Task created successfully',
@@ -1954,9 +1897,6 @@ const enUS = {
'humanApproval.custom': 'Custom Action',
'humanApproval.pending': 'Pending',
'humanApproval.aiAnalyzing': 'AI Analyzing',
'humanApproval.pendingReview': 'Pending Review',
'humanApproval.approved': 'Approved',
'humanApproval.rejected': 'Rejected',
'humanApproval.aiExecuting': 'AI Executing',
'humanApproval.completed': 'Completed',
'humanApproval.failed': 'Failed',

View File

@@ -37,62 +37,68 @@ export const ThemeProvider: FC<ThemeProviderProps> = ({ children }) => {
});
const [resolvedTheme, setResolvedTheme] = useState<'light' | 'dark'>(() => {
if (theme === 'auto') {
if (typeof window !== 'undefined' && theme === 'auto') {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
return theme;
});
useEffect(() => {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handleChange = (e: MediaQueryListEvent) => {
if (theme === 'auto') {
setResolvedTheme(e.matches ? 'dark' : 'light');
}
};
if (typeof window !== 'undefined') {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handleChange = (e: MediaQueryListEvent) => {
if (theme === 'auto') {
setResolvedTheme(e.matches ? 'dark' : 'light');
}
};
mediaQuery.addEventListener('change', handleChange);
return () => mediaQuery.removeEventListener('change', handleChange);
mediaQuery.addEventListener('change', handleChange);
return () => mediaQuery.removeEventListener('change', handleChange);
}
}, [theme]);
useEffect(() => {
const applyTheme = (isDark: boolean) => {
const root = document.documentElement;
if (isDark) {
root.classList.add('dark');
root.style.setProperty('--text-primary', '#e5e7eb');
root.style.setProperty('--text-secondary', '#d1d5db');
root.style.setProperty('--text-tertiary', '#9ca3af');
root.style.setProperty('--background-light', '#1f2937');
root.style.setProperty('--background-white', '#111827');
root.style.setProperty('--background-gray', '#374151');
root.style.setProperty('--background-dark', '#0f172a');
root.style.setProperty('--border-color', '#374151');
root.style.setProperty('--border-hover', '#4b5563');
} else {
root.classList.remove('dark');
root.style.setProperty('--text-primary', '#262626');
root.style.setProperty('--text-secondary', '#595959');
root.style.setProperty('--text-tertiary', '#8c8c8c');
root.style.setProperty('--background-light', '#f5f5f5');
root.style.setProperty('--background-white', '#ffffff');
root.style.setProperty('--background-gray', '#f0f0f0');
root.style.setProperty('--background-dark', '#1f2937');
root.style.setProperty('--border-color', '#e8e8e8');
root.style.setProperty('--border-hover', '#d9d9d9');
}
};
if (typeof window !== 'undefined') {
const applyTheme = (isDark: boolean) => {
const root = document.documentElement;
if (isDark) {
root.classList.add('dark');
root.style.setProperty('--text-primary', '#e5e7eb');
root.style.setProperty('--text-secondary', '#d1d5db');
root.style.setProperty('--text-tertiary', '#9ca3af');
root.style.setProperty('--background-light', '#1f2937');
root.style.setProperty('--background-white', '#111827');
root.style.setProperty('--background-gray', '#374151');
root.style.setProperty('--background-dark', '#0f172a');
root.style.setProperty('--border-color', '#374151');
root.style.setProperty('--border-hover', '#4b5563');
} else {
root.classList.remove('dark');
root.style.setProperty('--text-primary', '#262626');
root.style.setProperty('--text-secondary', '#595959');
root.style.setProperty('--text-tertiary', '#8c8c8c');
root.style.setProperty('--background-light', '#f5f5f5');
root.style.setProperty('--background-white', '#ffffff');
root.style.setProperty('--background-gray', '#f0f0f0');
root.style.setProperty('--background-dark', '#1f2937');
root.style.setProperty('--border-color', '#e8e8e8');
root.style.setProperty('--border-hover', '#d9d9d9');
}
};
const isDark = theme === 'dark' || (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches);
setResolvedTheme(isDark ? 'dark' : 'light');
applyTheme(isDark);
const isDark = theme === 'dark' || (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches);
setResolvedTheme(isDark ? 'dark' : 'light');
applyTheme(isDark);
}
}, [theme]);
const setTheme = (newTheme: Theme) => {
setThemeState(newTheme);
localStorage.setItem('theme', newTheme);
if (typeof window !== 'undefined') {
localStorage.setItem('theme', newTheme);
}
};
const toggleTheme = () => {

564
dashboard/src/imports.ts Normal file
View File

@@ -0,0 +1,564 @@
import React, { useState, useEffect, useRef, useCallback, useMemo, memo, FC } from 'react';
import { useNavigate, useLocation, Link, Outlet, useParams } from 'react-router-dom';
import {
Button,
Card,
Form,
Input,
Checkbox,
Space,
Divider,
Typography,
Alert,
message,
Row,
Col,
Modal,
Table,
Tag,
Select,
DatePicker,
TimePicker,
Popover,
Tooltip,
Badge,
Menu,
Breadcrumb,
Layout,
Drawer,
Tabs,
Avatar,
Steps,
Progress,
Radio,
Slider,
Rate,
Upload,
Switch,
InputNumber,
Tree,
Cascader,
Carousel,
Calendar,
Descriptions,
Empty,
Statistic,
Timeline,
Transfer,
TreeSelect,
ConfigProvider,
Spin,
Result,
Skeleton,
BackTop,
Mentions,
Popconfirm,
Collapse,
Dropdown,
List,
Image,
SelectProps,
TableProps,
FormProps,
ButtonProps,
CardProps,
InputProps,
ModalProps,
DrawerProps,
TabsProps,
TableColumnsType,
FormInstance,
} from 'antd';
import type { ColumnsType } from 'antd/es/table';
import {
UserOutlined,
LockOutlined,
SafetyOutlined,
EyeInvisibleOutlined,
EyeTwoTone,
LoginOutlined,
GoogleOutlined,
GithubOutlined,
HomeOutlined,
SettingOutlined,
UserAddOutlined,
LogoutOutlined,
MenuFoldOutlined,
MenuUnfoldOutlined,
MenuOutlined,
XOutlined,
ArrowLeftOutlined,
ArrowRightOutlined,
ArrowUpOutlined,
SunOutlined,
MoonOutlined,
BgColorsOutlined,
CrownOutlined,
SyncOutlined,
ApartmentOutlined,
ShopOutlined,
DashboardOutlined,
ShoppingOutlined,
CarOutlined,
CreditCardOutlined,
BarChartOutlined,
FileTextOutlined,
BellOutlined,
MailOutlined,
NotificationOutlined,
SettingFilled,
SmileOutlined,
FrownOutlined,
MehOutlined,
StarOutlined,
HeartOutlined,
LikeOutlined,
DislikeOutlined,
ClockCircleOutlined,
CheckCircleOutlined,
CloseCircleOutlined,
ExclamationCircleOutlined,
QuestionCircleOutlined,
InfoCircleOutlined,
PlusOutlined,
MinusOutlined,
DeleteOutlined,
EditOutlined,
SearchOutlined,
ReloadOutlined,
DownloadOutlined,
UploadOutlined,
LeftOutlined,
RightOutlined,
UpOutlined,
DownOutlined,
MoreOutlined,
EllipsisOutlined,
RedoOutlined,
UndoOutlined,
SaveOutlined,
PrinterOutlined,
FileOutlined,
FolderOutlined,
AppstoreOutlined,
CodeOutlined,
DatabaseOutlined,
CloudOutlined,
ApiOutlined,
BulbOutlined,
RobotOutlined,
TeamOutlined,
BuildingOutlined,
PhoneOutlined,
LinkOutlined,
GlobalOutlined,
DollarOutlined,
EuroOutlined,
PoundOutlined,
YuanOutlined,
AccountBookOutlined,
BankOutlined,
WalletOutlined,
PayCircleOutlined,
SwapOutlined,
BorderOutlined,
TableOutlined,
ListOutlined,
ColumnWidthOutlined,
ColumnHeightOutlined,
FullscreenOutlined,
FullscreenExitOutlined,
CopyOutlined,
ScissorOutlined,
PasteOutlined,
FilterOutlined,
SortAscendOutlined,
SortDescendOutlined,
UnorderedListOutlined,
OrderedListOutlined,
AlignLeftOutlined,
AlignCenterOutlined,
AlignRightOutlined,
AlignJustifyOutlined,
BoldOutlined,
ItalicOutlined,
UnderlineOutlined,
StrikethroughOutlined,
FontSizeOutlined,
FontColorsOutlined,
HighlightOutlined,
ClearOutlined,
InboxOutlined,
SendOutlined,
DraftOutlined,
DeleteColumnOutlined,
InsertColumnLeftOutlined,
InsertColumnRightOutlined,
InsertRowAboveOutlined,
InsertRowBelowOutlined,
DeleteRowOutlined,
MergeCellsOutlined,
SplitCellsOutlined,
CellMergeOutlined,
CellSplitOutlined,
RollbackOutlined,
CommitOutlined,
HistoryOutlined,
AuditOutlined,
ShieldOutlined,
UnlockOutlined,
KeyOutlined,
CloudUploadOutlined,
CloudDownloadOutlined,
CloudSyncOutlined,
CloudLoadingOutlined,
ShoppingCartOutlined,
RiseOutlined,
FallOutlined,
LineChartOutlined,
ThunderboltOutlined,
RocketOutlined,
CloudServerOutlined,
ArrowDownOutlined,
EyeOutlined,
CheckOutlined,
CloseOutlined,
WarningOutlined,
AimOutlined,
PieChartOutlined,
TruckOutlined,
AlertOutlined,
ExperimentOutlined,
PlayCircleOutlined,
StopOutlined,
SafetyCertificateOutlined,
ExportOutlined,
TrademarkOutlined,
PauseCircleOutlined,
CalendarOutlined,
PercentageOutlined,
FireOutlined,
StarFilled,
VideoCameraOutlined,
ScheduleOutlined,
ProductOutlined,
FundOutlined,
TransactionOutlined,
TrophyOutlined,
StockOutlined,
DisconnectOutlined,
GroupOutlined,
MonitorOutlined,
TwitterOutlined,
LinkedinOutlined,
BarcodeOutlined,
CalculatorOutlined,
DesktopOutlined,
AmazonOutlined,
BoxPlotOutlined,
PictureOutlined,
TagOutlined,
} from '@ant-design/icons';
const { Title, Text, Paragraph, Link: AntLink } = Typography;
const { Header, Sider, Content, Footer } = Layout;
const { Option } = Select;
const { RangePicker } = DatePicker;
const { TabPane } = Tabs;
const { Step } = Steps;
const { RadioGroup, RadioButton } = Radio;
const { Dragger } = Upload;
const { TreeSelect: AntTreeSelect } = TreeSelect;
const { Panel } = Collapse;
const { TextArea, Search } = Input;
// 导出所有组件
export {
React,
useState,
useEffect,
useRef,
useCallback,
useMemo,
useNavigate,
useLocation,
Link,
Outlet,
useParams,
Button,
Card,
Form,
Input,
TextArea,
Search,
Checkbox,
Space,
Divider,
Typography,
Alert,
message,
Row,
Col,
Modal,
Table,
Tag,
Select,
DatePicker,
TimePicker,
Popover,
Tooltip,
Badge,
Menu,
Breadcrumb,
Layout,
Drawer,
Tabs,
Avatar,
Steps,
Progress,
Radio,
Slider,
Rate,
Upload,
Switch,
InputNumber,
Tree,
Cascader,
Carousel,
Calendar,
Descriptions,
Empty,
Statistic,
Timeline,
Transfer,
TreeSelect,
ConfigProvider,
Spin,
Result,
Skeleton,
BackTop,
Mentions,
Popconfirm,
Collapse,
SelectProps,
TableProps,
FormProps,
ButtonProps,
CardProps,
InputProps,
ModalProps,
DrawerProps,
TabsProps,
TableColumnsType,
ColumnsType,
FormInstance,
Dropdown,
List,
Image,
UserOutlined,
LockOutlined,
SafetyOutlined,
EyeInvisibleOutlined,
EyeTwoTone,
LoginOutlined,
GoogleOutlined,
GithubOutlined,
HomeOutlined,
SettingOutlined,
UserAddOutlined,
LogoutOutlined,
MenuFoldOutlined,
MenuUnfoldOutlined,
MenuOutlined,
XOutlined,
ArrowLeftOutlined,
ArrowRightOutlined,
ArrowUpOutlined,
SunOutlined,
MoonOutlined,
BgColorsOutlined,
CrownOutlined,
SyncOutlined,
ApartmentOutlined,
ShopOutlined,
DashboardOutlined,
ShoppingOutlined,
CarOutlined,
CreditCardOutlined,
BarChartOutlined,
FileTextOutlined,
BellOutlined,
MailOutlined,
NotificationOutlined,
SettingFilled,
SmileOutlined,
FrownOutlined,
MehOutlined,
StarOutlined,
HeartOutlined,
LikeOutlined,
DislikeOutlined,
ClockCircleOutlined,
CheckCircleOutlined,
CloseCircleOutlined,
ExclamationCircleOutlined,
QuestionCircleOutlined,
InfoCircleOutlined,
PlusOutlined,
MinusOutlined,
DeleteOutlined,
EditOutlined,
SearchOutlined,
ReloadOutlined,
DownloadOutlined,
UploadOutlined,
LeftOutlined,
RightOutlined,
UpOutlined,
DownOutlined,
MoreOutlined,
EllipsisOutlined,
RedoOutlined,
UndoOutlined,
SaveOutlined,
PrinterOutlined,
FileOutlined,
FolderOutlined,
AppstoreOutlined,
CodeOutlined,
DatabaseOutlined,
CloudOutlined,
ApiOutlined,
BulbOutlined,
RobotOutlined,
TeamOutlined,
BuildingOutlined,
PhoneOutlined,
LinkOutlined,
GlobalOutlined,
DollarOutlined,
EuroOutlined,
PoundOutlined,
YuanOutlined,
AccountBookOutlined,
BankOutlined,
WalletOutlined,
PayCircleOutlined,
SwapOutlined,
BorderOutlined,
TableOutlined,
ListOutlined,
ColumnWidthOutlined,
ColumnHeightOutlined,
FullscreenOutlined,
FullscreenExitOutlined,
CopyOutlined,
ScissorOutlined,
PasteOutlined,
FilterOutlined,
SortAscendOutlined,
SortDescendOutlined,
UnorderedListOutlined,
OrderedListOutlined,
AlignLeftOutlined,
AlignCenterOutlined,
AlignRightOutlined,
AlignJustifyOutlined,
BoldOutlined,
ItalicOutlined,
UnderlineOutlined,
StrikethroughOutlined,
FontSizeOutlined,
FontColorsOutlined,
HighlightOutlined,
ClearOutlined,
InboxOutlined,
SendOutlined,
DraftOutlined,
DeleteColumnOutlined,
InsertColumnLeftOutlined,
InsertColumnRightOutlined,
InsertRowAboveOutlined,
InsertRowBelowOutlined,
DeleteRowOutlined,
MergeCellsOutlined,
SplitCellsOutlined,
CellMergeOutlined,
CellSplitOutlined,
RollbackOutlined,
CommitOutlined,
HistoryOutlined,
AuditOutlined,
ShieldOutlined,
UnlockOutlined,
KeyOutlined,
CloudUploadOutlined,
CloudDownloadOutlined,
CloudSyncOutlined,
CloudLoadingOutlined,
ShoppingCartOutlined,
RiseOutlined,
FallOutlined,
LineChartOutlined,
ThunderboltOutlined,
RocketOutlined,
CloudServerOutlined,
ArrowDownOutlined,
EyeOutlined,
CheckOutlined,
CloseOutlined,
WarningOutlined,
AimOutlined,
PieChartOutlined,
TruckOutlined,
AlertOutlined,
ExperimentOutlined,
PlayCircleOutlined,
StopOutlined,
SafetyCertificateOutlined,
ExportOutlined,
TrademarkOutlined,
PauseCircleOutlined,
CalendarOutlined,
PercentageOutlined,
FireOutlined,
StarFilled,
VideoCameraOutlined,
ScheduleOutlined,
ProductOutlined,
FundOutlined,
TransactionOutlined,
TrophyOutlined,
StockOutlined,
DisconnectOutlined,
GroupOutlined,
MonitorOutlined,
TwitterOutlined,
LinkedinOutlined,
BarcodeOutlined,
CalculatorOutlined,
DesktopOutlined,
AmazonOutlined,
BoxPlotOutlined,
PictureOutlined,
TagOutlined,
Title,
Text,
Paragraph,
AntLink,
Header,
Sider,
Content,
Footer,
Option,
RangePicker,
TabPane,
Step,
RadioGroup,
RadioButton,
Dragger,
AntTreeSelect,
Panel,
FC,
memo,
};

View File

@@ -67,6 +67,16 @@ import {
} from 'antd';
const { Sider, Header, Content, Footer } = Layout;
const { Item } = Form;
const { Title, Text, Paragraph } = Typography;
const { Option } = Select;
const { RangePicker } = DatePicker;
const { Step } = Steps;
const { Search } = Input;
const { TextArea } = Input;
const { Panel } = Collapse;
const { TabPane } = Tabs;
const { Meta } = Card;
export {
Card,
Table,
@@ -136,15 +146,17 @@ export {
Item,
Carousel,
ColorPicker,
Title,
Text,
Paragraph,
Option,
RangePicker,
Step,
Search,
TextArea,
Panel,
TabPane,
Meta,
};
export type { ColumnsType, TablePaginationConfig } from 'antd/es/table';
export type { FilterValue, SorterResult, TableCurrentDataSource } from 'antd/es/table/interface';
export const { Title, Text, Paragraph } = Typography;
export const { Option } = Select;
export const { RangePicker } = DatePicker;
export const { Step } = Steps;
export const { Search } = Input;
export const { TextArea } = Input;
export const { Panel } = Collapse;
export const { TabPane } = Tabs;
export const { Meta } = Card;

View File

@@ -33,7 +33,7 @@ export { materialProcessingDataSource } from '../services/materialProcessingData
export { operationAgentDataSource } from '../services/operationAgentDataSource';
export { platformAuthDataSource } from '../services/platformAuthDataSource';
export { procurementDataSource } from '../services/procurementDataSource';
export { ProductManagementMockDataSource } from '../services/productManagementDataSource';
export { createProductManagementDataSource } from '../services/productManagementDataSource';
export { productSelectionDataSource } from '../services/productSelectionDataSource';
export { reportsDataSource } from '../services/reportsDataSource';
export { saasTenantDataSource } from '../services/saasTenantDataSource';

View File

@@ -1,3 +1,4 @@
import type { ColumnsType } from 'antd/es/table';
export type { Product, Shop, ProductFilter, ProductSort, ProductDataSource } from '../services/productDataSource';
export type { OrderDataSource } from '../services/orderDataSource';
export type { ProductManagementMockDataSource } from '../services/productManagementDataSource';
export type { ColumnsType };

View File

@@ -4,4 +4,3 @@ import _debounce from 'lodash/debounce';
import _throttle from 'lodash/throttle';
export const debounce = _debounce;
export const throttle = _throttle;
export { useLocale } from '@/contexts/LocaleContext';

View File

@@ -1,7 +1,5 @@
import React, { useState, useEffect, useMemo, FC } from 'react';
import {
useState,
useEffect,
useMemo,
Layout,
Menu,
Typography,
@@ -12,6 +10,8 @@ import {
Tag,
message,
Button,
} from 'antd';
import {
DashboardOutlined,
ShoppingOutlined,
FileTextOutlined,
@@ -32,21 +32,14 @@ import {
SafetyOutlined,
CrownOutlined,
SwapOutlined,
Header,
Sider,
Content,
Title,
Text,
Link,
useLocation,
useNavigate,
Outlet,
FC,
} from '@/imports';
} from '@ant-design/icons';
import { Link, useLocation, useNavigate, Outlet } from 'react-router-dom';
const { Header, Sider, Content } = Layout;
const { Title, Text } = Typography;
import type { MenuProps } from 'antd';
import { UserProvider, useUser, MOCK_USERS, ROLE_CONFIG, FEATURES, PERMISSIONS } from '@/contexts/UserContext';
import { LocaleProvider, useLocale } from '@/contexts/LocaleContext';
import { ThemeProvider } from '@/contexts/ThemeContext';
import { useUser, MOCK_USERS, ROLE_CONFIG, FEATURES, PERMISSIONS } from '@/contexts/UserContext';
import { useLocale } from '@/contexts/LocaleContext';
import ThemeSwitch from '@/components/ThemeSwitch';
import Breadcrumb from '@/components/Breadcrumb';
@@ -592,15 +585,7 @@ const MainLayoutContent: FC = () => {
};
const MainLayout: FC = () => {
return (
<ThemeProvider>
<LocaleProvider>
<UserProvider>
<MainLayoutContent />
</UserProvider>
</LocaleProvider>
</ThemeProvider>
);
return <MainLayoutContent />;
};
export default MainLayout;

View File

@@ -52,11 +52,11 @@ import {
UserOutlined,
RobotOutlined,
ArrowRightOutlined,
aiActionTaskDataSource,
Option,
RangePicker,
Step,
} from '@/imports';
import { aiActionTaskDataSource } from '@/services/aiActionTaskDataSource';
import type { AITask } from '@/services/aiActionTaskDataSource';
import type { ColumnsType } from 'antd/es/table';

View File

@@ -22,7 +22,7 @@ import {
} from '@/imports';
import { aiSuggestionDataSource } from '@/services/aiSuggestionDataSource';
import type { AISuggestion } from '../services/aiSuggestionDataSource';
import AISuggestionDisplay from '../components/ai-suggestion/AISuggestionDisplay';
// import { AISuggestionDisplay } from '@/components';
const AISuggestionPage: FC = () => {
const { t } = useLocale();
@@ -209,12 +209,21 @@ const AISuggestionPage: FC = () => {
</Col>
<Col span={8}>
{selectedSuggestion && (
<AISuggestionDisplay
suggestion={selectedSuggestion}
onApprove={handleApprove}
onReject={handleReject}
onModify={handleModify}
/>
<Card>
<h3>{selectedSuggestion.title}</h3>
<p>{selectedSuggestion.description}</p>
<div style={{ marginTop: 16 }}>
<Button type="primary" onClick={handleApprove} style={{ marginRight: 8 }}>
{t('aiSuggestion.approve')}
</Button>
<Button danger onClick={handleReject} style={{ marginRight: 8 }}>
{t('aiSuggestion.reject')}
</Button>
<Button onClick={handleModify}>
{t('aiSuggestion.modify')}
</Button>
</div>
</Card>
)}
</Col>
</Row>

View File

@@ -31,13 +31,13 @@ import {
BarChartOutlined,
ScheduleOutlined,
ThunderboltOutlined,
marketingDataSource,
Option,
RangePicker,
Search,
TextArea,
FC,
} from '@/imports';
import { marketingDataSource } from '@/services/marketingDataSource';
import type { Ad } from '@/services/marketingDataSource';
import AdPlanPage from './AdPlanPage';
import AdDelivery from './AdDelivery';

View File

@@ -39,7 +39,7 @@ interface AnalyticsDashboardProps {
const AnalyticsDashboard: FC<AnalyticsDashboardProps> = ({ tenantId }) => {
const [loading, setLoading] = useState(false);
const [activeTab, setActiveTab] = useState('userActivity');
const [dateRange, setDateRange] = useState<[string, string] | null>(null);
const [dateRange, setDateRange] = useState<[string, string] | undefined>(undefined);
const [userActivity, setUserActivity] = useState<UserActivity[]>([]);
const [tenantUsage, setTenantUsage] = useState<TenantUsage | null>(null);
const [permissionUsage, setPermissionUsage] = useState<PermissionUsage[]>([]);

View File

@@ -85,7 +85,63 @@ import {
} from '@/imports';
import { Line, Column, Pie, Area, DualAxes } from '@ant-design/charts';
import type { ColumnsType } from 'antd/es/table';
import { analyticsDataSource, ProductAnalytics, OrderAnalytics, ProfitAnalytics, RealtimeMetrics, AlertRule, Dashboard } from '@/services/analyticsDataSource';
import { analyticsDataSource } from '@/services/analyticsDataSource';
interface ProductAnalytics {
productId: string;
productName: string;
sales: number;
revenue: number;
profit: number;
conversionRate: number;
image?: string;
category?: string;
profitMargin?: number;
views?: number;
returnRate?: number;
}
interface OrderAnalytics {
status: string;
count: number;
revenue: number;
avgOrderValue: number;
}
interface ProfitAnalytics {
platform: string;
revenue: number;
cost: number;
profit: number;
profitMargin: number;
}
interface RealtimeMetrics {
activeUsers: number;
currentSales: number;
currentOrders: number;
conversionRate: number;
avgSessionTime: number;
ordersPerMinute?: number;
revenuePerMinute?: number;
}
interface AlertRule {
id: string;
name: string;
condition: string;
threshold: number;
status: string;
lastTriggered: string;
}
interface Dashboard {
id: string;
name: string;
widgets: string[];
lastUpdated: string;
createdBy: string;
}
interface LocalChartData {
date: string;
@@ -227,7 +283,7 @@ const Analytics: FC = () => {
setLoading(true);
try {
const data = await analyticsDataSource.fetchAllData();
const localMetrics: LocalMetricData[] = data.metrics.map(m => ({
const localMetrics: LocalMetricData[] = data.metrics.map((m: any) => ({
...m,
icon: iconMap[m.icon] || <BarChartOutlined />,
}));
@@ -326,10 +382,10 @@ const Analytics: FC = () => {
{ title: '销量', dataIndex: 'sales', key: 'sales', sorter: (a, b) => a.sales - b.sales },
{ title: '销售额', dataIndex: 'revenue', key: 'revenue', render: (v) => `¥${v.toLocaleString()}`, sorter: (a, b) => a.revenue - b.revenue },
{ title: '利润', dataIndex: 'profit', key: 'profit', render: (v) => `¥${v.toLocaleString()}`, sorter: (a, b) => a.profit - b.profit },
{ title: '利润率', dataIndex: 'profitMargin', key: 'profitMargin', render: (v) => `${v}%`, sorter: (a, b) => a.profitMargin - b.profitMargin },
{ title: '浏览量', dataIndex: 'views', key: 'views', sorter: (a, b) => a.views - b.views },
{ title: '利润率', dataIndex: 'profitMargin', key: 'profitMargin', render: (v) => `${v}%`, sorter: (a, b) => (a.profitMargin || 0) - (b.profitMargin || 0) },
{ title: '浏览量', dataIndex: 'views', key: 'views', sorter: (a, b) => (a.views || 0) - (b.views || 0) },
{ title: '转化率', dataIndex: 'conversionRate', key: 'conversionRate', render: (v) => `${v}%`, sorter: (a, b) => a.conversionRate - b.conversionRate },
{ title: '退货率', dataIndex: 'returnRate', key: 'returnRate', render: (v) => <Tag color={v > 5 ? 'error' : 'success'}>{v}%</Tag>, sorter: (a, b) => a.returnRate - b.returnRate },
{ title: '退货率', dataIndex: 'returnRate', key: 'returnRate', render: (v) => <Tag color={v > 5 ? 'error' : 'success'}>{v}%</Tag>, sorter: (a, b) => (a.returnRate || 0) - (b.returnRate || 0) },
{
title: '趋势',
dataIndex: 'trend',

View File

@@ -1,7 +1,6 @@
import { useLocale } from '@/contexts/LocaleContext';
import React, { useState, useEffect, FC } from 'react';
import {
useState,
useEffect,
Card,
Table,
Tag,
@@ -26,6 +25,8 @@ import {
Timeline,
Tooltip,
Popconfirm,
} from 'antd';
import {
PlusOutlined,
EditOutlined,
DeleteOutlined,
@@ -40,9 +41,9 @@ import {
CheckCircleOutlined,
CloseCircleOutlined,
ClockCircleOutlined,
Option,
FC,
} from '@/imports';
} from '@ant-design/icons';
const { Option } = Select;
import { clientDataSource } from '@/services/clientDataSource';
import type { Client, ClientGroup } from '../services/clientDataSource';

View File

@@ -1,7 +1,6 @@
import { useLocale } from '@/contexts/LocaleContext';
import React, { useState, useEffect, FC } from 'react';
import {
useState,
useEffect,
Card,
Table,
Tag,
@@ -22,6 +21,8 @@ import {
Progress,
Alert,
Tooltip,
} from 'antd';
import {
CheckCircleOutlined,
CloseCircleOutlined,
ClockCircleOutlined,
@@ -33,10 +34,11 @@ import {
CalendarOutlined,
BarChartOutlined,
InfoCircleOutlined,
Option,
RangePicker,
FC,
} from '@/imports';
} from '@ant-design/icons';
import { Link, useLocation, useNavigate, Outlet } from 'react-router-dom';
const { Option } = Select;
const { RangePicker } = DatePicker;
import { executionResultDataSource } from '@/services/executionResultDataSource';
import type { ExecutionResult, StatData } from '../services/executionResultDataSource';
import dayjs from 'dayjs';

View File

@@ -35,11 +35,13 @@ const Homepage: FC = () => {
}
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 50);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
if (typeof window !== 'undefined') {
const handleScroll = () => {
setIsScrolled(window.scrollY > 50);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}
}, []);
const features = [

View File

@@ -1,7 +1,6 @@
import { useLocale } from '@/contexts/LocaleContext';
import React, { useState, useEffect, FC } from 'react';
import {
useState,
useEffect,
Card,
Table,
Tag,
@@ -15,6 +14,8 @@ import {
Select,
Badge,
Tabs,
} from 'antd';
import {
CheckCircleOutlined,
CloseCircleOutlined,
EyeOutlined,
@@ -22,13 +23,12 @@ import {
SearchOutlined,
FilterOutlined,
ReloadOutlined,
Option,
FC,
} from '@/imports';
} from '@ant-design/icons';
const { Option } = Select;
import { humanApprovalDataSource } from '@/services/humanApprovalDataSource';
import type { Task } from '../services/humanApprovalDataSource';
import HumanApprovalForm from '../components/human-approval/HumanApprovalForm';
import AISuggestionDisplay from '../components/ai-suggestion/AISuggestionDisplay';
import { HumanApprovalForm, AISuggestionDisplay } from '@/components';
const ACTION_TYPE_MAP: Record<string, { color: string; text: string }> = {
PRICING_OPTIMIZATION: { color: 'blue', text: 'Pricing Optimization' },

View File

@@ -12,9 +12,9 @@ import {
CheckCircleOutlined,
DollarOutlined,
useNavigate,
inventoryDataSource,
FC,
} from '@/imports';
import { inventoryDataSource } from '@/services/inventoryDataSource';
import type { Inventory } from '@/types/inventory';
import { InventoryStatus } from '@/types/inventory';

View File

@@ -49,7 +49,7 @@ import {
} from '@/imports';
import { Line, Column, Pie, Area, Funnel } from '@ant-design/charts';
import moment from 'moment';
import HierarchySelector from '../../components/HierarchySelector';
import { HierarchySelector } from '@/components';
// 平台颜色
const PLATFORM_COLORS: Record<string, string> = {

View File

@@ -83,8 +83,7 @@ import {
Paragraph,
FC,
} from '@/imports';
import { lightweightClientService } from '../services/lightweightClientService';
import { cloudService, CreateInstanceRequest, CloudInstance, CloudProvider, CloudRegion, InstanceType, CloudImage, InstanceMetrics } from '../services/cloud-service';
import { lightweightClientService, cloudService, CreateInstanceRequest, CloudInstance, CloudProvider, CloudRegion, InstanceType, CloudImage, InstanceMetrics } from '@/services';
import {
CloudControlLayerService,
ControlCommand,

View File

@@ -1,4 +1,5 @@
import { useState, useEffect, useCallback, useMemo, moment, FC } from '@/imports';
import React, { useState, useEffect, useCallback, useMemo, FC } from 'react';
import moment from 'moment';
import {
Card,
Table,
@@ -26,11 +27,13 @@ import {
Typography,
Image,
Steps,
Line,
} from 'antd';
import {
LineChart,
Line,
Pie,
Bar,
BarChart,
Bar,
ResponsiveContainer,
Tooltip,
Legend,
@@ -38,6 +41,8 @@ import {
YAxis,
CartesianGrid,
Cell,
} from 'recharts';
import {
EyeOutlined,
SyncOutlined,
CheckCircleOutlined,
@@ -63,18 +68,21 @@ import {
GlobalOutlined,
ShopOutlined,
AppstoreOutlined,
Title,
Text,
Option,
RangePicker,
Step,
Search,
} from '@ant-design/icons';
const { Text, Title } = Typography;
const { Option } = Select;
const { RangePicker } = DatePicker;
const { Step } = Steps;
const { Search } = Input;
import type {
ColumnsType,
TablePaginationConfig,
FilterValue,
SorterResult,
TableCurrentDataSource,
} from '@/imports';
} from 'antd/es/table';
interface Order {
id: string;

View File

@@ -22,12 +22,12 @@ import {
CheckCircleOutlined,
CloseCircleOutlined,
Link,
orderDataSource,
Title,
Text,
Paragraph,
FC,
} from '@/imports';
import { orderDataSource } from '@/services/orderDataSource';
import { Area, Pie, Column } from '@ant-design/charts';
import moment from 'moment';

View File

@@ -22,7 +22,6 @@ import {
Text,
Paragraph,
Option,
Item,
FC,
} from '@/imports';
@@ -230,38 +229,38 @@ const AIPricing: FC = () => {
>
<Row gutter={[16, 16]}>
<Col span={6}>
<Item label="商品ID" name="productId">
<Form.Item label="商品ID" name="productId">
<Input placeholder="输入商品ID" />
</Item>
</Form.Item>
</Col>
<Col span={6}>
<Item label="成本" name="cost" rules={[{ required: true, message: '请输入成本' }]}>
<Form.Item label="成本" name="cost" rules={[{ required: true, message: '请输入成本' }]}>
<Input type="number" prefix="¥" placeholder="输入成本" />
</Item>
</Form.Item>
</Col>
<Col span={6}>
<Item label="当前售价" name="currentPrice" rules={[{ required: true, message: '请输入当前售价' }]}>
<Form.Item label="当前售价" name="currentPrice" rules={[{ required: true, message: '请输入当前售价' }]}>
<Input type="number" prefix="¥" placeholder="输入当前售价" />
</Item>
</Form.Item>
</Col>
<Col span={6}>
<Item label="竞品价格" name="competitorPrice">
<Form.Item label="竞品价格" name="competitorPrice">
<Input type="number" prefix="¥" placeholder="输入竞品价格" />
</Item>
</Form.Item>
</Col>
<Col span={6}>
<Item label="月销量" name="salesVolume">
<Form.Item label="月销量" name="salesVolume">
<Input type="number" placeholder="输入月销量" />
</Item>
</Form.Item>
</Col>
<Col span={6}>
<Item label="定价策略" name="pricingStrategy">
<Form.Item label="定价策略" name="pricingStrategy">
<Select>
<Option value="aggressive"></Option>
<Option value="balanced"></Option>
<Option value="conservative"></Option>
</Select>
</Item>
</Form.Item>
</Col>
<Col span={12} style={{ display: 'flex', alignItems: 'flex-end' }}>
<Button

View File

@@ -37,30 +37,15 @@ import {
} from '@/imports';
import type { ColumnsType } from 'antd/es/table';
import { productDataSource } from '@/services/productDataSource';
import { Product } from '@/types/product';
import type { Product } from '../../../server/src/shared/schemas/productManagement.schema';
interface ProductDetailData {
id: string;
interface ProductDetailData extends Product {
productId: string;
platform: string;
name: string;
description: string;
category: string;
brand: string;
status: 'DRAFT' | 'PENDING' | 'ACTIVE' | 'INACTIVE' | 'SUSPENDED';
price: number;
costPrice: number;
currency: string;
stock: number;
sku: string;
images: string[];
attributes: Record<string, string>;
variants: ProductVariant[];
complianceStatus: 'COMPLIANT' | 'NON_COMPLIANT' | 'PENDING_REVIEW';
certificates: string[];
createdAt: string;
updatedAt: string;
publishedAt?: string;
variants: ProductVariant[];
}
interface ProductVariant {
@@ -305,7 +290,7 @@ const ProductDetail: FC = () => {
</div>
<Descriptions column={2} size="small">
<Descriptions.Item label="Category">{product.category}</Descriptions.Item>
<Descriptions.Item label="Category">{product.categories?.[0] || ''}</Descriptions.Item>
<Descriptions.Item label="Brand">{product.brand}</Descriptions.Item>
<Descriptions.Item label={<><DollarOutlined /> Price</>}>
<Text strong style={{ fontSize: 18 }}>{product.currency} {product.price.toFixed(2)}</Text>

View File

@@ -495,11 +495,11 @@ const ProductList: FC = () => {
key: 'name',
render: (text, record) => (
<Space>
<Image src={record.image} width={60} height={60} style={{ objectFit: 'cover' }} />
<Image src={record.images?.[0] || ''} width={60} height={60} style={{ objectFit: 'cover' }} />
<div>
<div style={{ fontWeight: 500 }}>{text}</div>
<div style={{ fontSize: 12, color: '#999' }}>SKU: {record.sku}</div>
<div style={{ fontSize: 12, color: '#666' }}>{record.category}</div>
<div style={{ fontSize: 12, color: '#666' }}>{record.categories?.[0] || ''}</div>
</div>
</Space>
),

View File

@@ -18,7 +18,7 @@ import {
Divider,
Collapse,
} from 'antd';
import { PlusOutlined, EditOutlined, DeleteOutlined, SaveOutlined, CloseOutlined, KeyOutlined, LockOutlined, DownOutlined, UpOutlined, LineChartOutlined } from '@ant-design/icons';
import { PlusOutlined, EditOutlined, DeleteOutlined, SaveOutlined, CloseOutlined, KeyOutlined, LockOutlined, DownOutlined, UpOutlined, LineChartOutlined } from '@/imports';
import { useRequest } from 'umi';
import {
createRole as createRoleAPI,

View File

@@ -1,17 +1,29 @@
import {
Card,
Typography,
Title,
Text,
FC,
} from '@/imports';
import React from 'react';
import { Card, Typography, Button } from '@/imports';
const TestPage: FC = () => {
const TestPage: React.FC = () => {
return (
<div style={{ padding: 24 }}>
<Card>
<Title level={2}></Title>
<Text></Text>
<div style={{
minHeight: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: '#f0f2f5'
}}>
<Card style={{
width: 400,
padding: 24,
textAlign: 'center'
}}>
<Typography.Title level={2} style={{ marginBottom: 24 }}>
Test Page
</Typography.Title>
<Typography.Paragraph>
This is a test page to check if the frontend is working properly.
</Typography.Paragraph>
<Button type="primary" style={{ marginTop: 24 }}>
Test Button
</Button>
</Card>
</div>
);

View File

@@ -210,4 +210,127 @@ export const analyticsDataSource = {
throw new Error(error.message || '导出分析数据失败');
}
},
/**
* 获取所有分析数据
*/
async fetchAllData(): Promise<any> {
try {
// 模拟API调用延迟
await new Promise(resolve => setTimeout(resolve, 800));
return {
metrics: [
{ key: 'sales', label: '总销售额', value: 125000, unit: '元', change: 15.2, changeType: 'up', icon: 'BarChartOutlined', color: '#52c41a' },
{ key: 'orders', label: '订单数', value: 850, unit: '单', change: 8.7, changeType: 'up', icon: 'ShoppingOutlined', color: '#1890ff' },
{ key: 'visitors', label: '访客数', value: 12000, unit: '人', change: 5.3, changeType: 'up', icon: 'UserOutlined', color: '#faad14' },
{ key: 'conversion', label: '转化率', value: 7.1, unit: '%', change: -1.2, changeType: 'down', icon: 'LineChartOutlined', color: '#ff4d4f' },
],
chartData: Array.from({ length: 7 }, (_, i) => ({
date: `2026-03-${24 + i}`,
sales: 15000 + Math.random() * 10000,
orders: 80 + Math.random() * 50,
visitors: 1200 + Math.random() * 800,
conversion: 6 + Math.random() * 3,
})),
productAnalytics: [
{ productId: 'P001', productName: '无线蓝牙耳机', sales: 120, revenue: 24000, profit: 8400, conversionRate: 8.5 },
{ productId: 'P002', productName: '智能手表', sales: 85, revenue: 17000, profit: 5950, conversionRate: 6.2 },
{ productId: 'P003', productName: '便携充电宝', sales: 210, revenue: 16800, profit: 4200, conversionRate: 10.3 },
],
orderAnalytics: [
{ status: 'PENDING', count: 35, revenue: 7000, avgOrderValue: 200 },
{ status: 'CONFIRMED', count: 120, revenue: 24000, avgOrderValue: 200 },
{ status: 'SHIPPED', count: 210, revenue: 42000, avgOrderValue: 200 },
{ status: 'DELIVERED', count: 380, revenue: 76000, avgOrderValue: 200 },
{ status: 'COMPLETED', count: 85, revenue: 17000, avgOrderValue: 200 },
],
profitAnalytics: [
{ platform: 'AMAZON', revenue: 50000, cost: 35000, profit: 15000, profitMargin: 30 },
{ platform: 'SHOPEE', revenue: 35000, cost: 28000, profit: 7000, profitMargin: 20 },
{ platform: 'LAZADA', revenue: 20000, cost: 16000, profit: 4000, profitMargin: 20 },
{ platform: 'TikTok', revenue: 20000, cost: 14000, profit: 6000, profitMargin: 30 },
],
realtimeMetrics: {
activeUsers: 125,
currentSales: 8500,
currentOrders: 42,
conversionRate: 6.8,
avgSessionTime: 245,
},
alertRules: [
{ id: 'A001', name: '销售额下降', condition: 'sales < 5000', threshold: 5000, status: 'active', lastTriggered: '2026-03-26 14:30:00' },
{ id: 'A002', name: '订单量异常', condition: 'orders < 20', threshold: 20, status: 'inactive', lastTriggered: '2026-03-20 10:15:00' },
{ id: 'A003', name: '转化率低', condition: 'conversion < 5', threshold: 5, status: 'active', lastTriggered: '2026-03-25 09:45:00' },
],
dashboards: [
{ id: 'D001', name: '销售概览', widgets: ['sales', 'orders', 'visitors', 'conversion'], lastUpdated: '2026-03-27 10:00:00', createdBy: 'admin' },
{ id: 'D002', name: '产品分析', widgets: ['products', 'categories', 'brands'], lastUpdated: '2026-03-26 16:30:00', createdBy: 'manager' },
{ id: 'D003', name: '平台对比', widgets: ['platforms', 'regions', 'channels'], lastUpdated: '2026-03-25 14:00:00', createdBy: 'analyst' },
],
};
} catch (error: any) {
message.error(error.message || '获取分析数据失败');
return {
metrics: [],
chartData: [],
productAnalytics: [],
orderAnalytics: [],
profitAnalytics: [],
realtimeMetrics: {
activeUsers: 0,
currentSales: 0,
currentOrders: 0,
conversionRate: 0,
avgSessionTime: 0,
},
alertRules: [],
dashboards: [],
};
}
},
/**
* 获取实时数据
*/
async fetchRealtimeData(): Promise<any> {
try {
// 模拟API调用延迟
await new Promise(resolve => setTimeout(resolve, 300));
return {
activeUsers: 100 + Math.floor(Math.random() * 50),
currentSales: 5000 + Math.random() * 5000,
currentOrders: 20 + Math.floor(Math.random() * 30),
conversionRate: 5 + Math.random() * 3,
avgSessionTime: 200 + Math.random() * 100,
};
} catch (error: any) {
message.error(error.message || '获取实时数据失败');
return {
activeUsers: 0,
currentSales: 0,
currentOrders: 0,
conversionRate: 0,
avgSessionTime: 0,
};
}
},
/**
* 获取告警规则
*/
async fetchAlertRules(): Promise<any[]> {
try {
// 模拟API调用延迟
await new Promise(resolve => setTimeout(resolve, 400));
return [
{ id: 'A001', name: '销售额下降', condition: 'sales < 5000', threshold: 5000, status: 'active', lastTriggered: '2026-03-26 14:30:00' },
{ id: 'A002', name: '订单量异常', condition: 'orders < 20', threshold: 20, status: 'inactive', lastTriggered: '2026-03-20 10:15:00' },
{ id: 'A003', name: '转化率低', condition: 'conversion < 5', threshold: 5, status: 'active', lastTriggered: '2026-03-25 09:45:00' },
{ id: 'A004', name: '库存不足', condition: 'stock < 10', threshold: 10, status: 'active', lastTriggered: '2026-03-27 08:20:00' },
];
} catch (error: any) {
message.error(error.message || '获取告警规则失败');
return [];
}
},
};

View File

@@ -0,0 +1,93 @@
// 统一导出所有服务和 DataSource
// API 服务
export * from './api';
// 基础服务
export { http } from './http';
export { DataSourceFactory, BaseDataSource, BaseMockDataSource, __MOCK__, __DATA_SOURCE_TYPE__ } from './dataSourceFactory';
// 数据源服务
export { abTestDataSource } from './abTestDataSource';
export { adOptimizationDataSource } from './adOptimizationDataSource';
export { afterSalesDataSource } from './afterSalesDataSource';
export { aiActionTaskDataSource } from './aiActionTaskDataSource';
export { aiSuggestionDataSource } from './aiSuggestionDataSource';
export { analyticsDataSource } from './analyticsDataSource';
export { arbitrageDataSource } from './arbitrageDataSource';
export { AuditDataSource } from './auditDataSource';
export { autoExecutionDataSource } from './autoExecutionDataSource';
export { b2bTradeDataSource } from './b2bTradeDataSource';
export { batchOperationDataSource } from './batchOperationDataSource';
export { blacklistDataSource } from './blacklistDataSource';
export { certificateDataSource } from './certificateDataSource';
export { ChatbotDataSource } from './chatbotDataSource';
export { clientDataSource } from './clientDataSource';
export { CommandDataSource } from './commandDataSource';
export { CreativeDataSource } from './creativeDataSource';
export { crossBorderIntegrationDataSource } from './crossBorderIntegrationDataSource';
export { CustomerDataSource } from './customerDataSource';
export { dashboardDataSource } from './dashboardDataSource';
export { dynamicPricingDataSource } from './dynamicPricingDataSource';
export { exchangeDataSource } from './exchangeDataSource';
export { executionResultDataSource } from './executionResultDataSource';
export { financeDataSource } from './financeDataSource';
export { GovernanceDataSource } from './governanceDataSource';
export { humanApprovalDataSource } from './humanApprovalDataSource';
export { independentSiteDataSource } from './independentSiteDataSource';
export { instanceDataSource } from './instanceDataSource';
export { inventoryDataSource } from './inventoryDataSource';
export { leaderboardDataSource } from './leaderboardDataSource';
export { logisticsDataSource } from './logisticsDataSource';
export { marketingDataSource } from './marketingDataSource';
export { materialProcessingDataSource } from './materialProcessingDataSource';
export { merchantDataSource } from './merchantDataSource';
export { MonitoringDataSource } from './monitoringDataSource';
export { NLPDataSource } from './nlpDataSource';
export { omnichannelCommunicationDataSource } from './omnichannelCommunicationDataSource';
export { OmnichannelDataSource } from './omnichannelDataSource';
export { omnichannelMarketingDataSource } from './omnichannelMarketingDataSource';
export { operationAgentDataSource } from './operationAgentDataSource';
export { OperationLogDataSource } from './operationLogDataSource';
export { orderDataSource } from './orderDataSource';
export { createOrderManagementDataSource } from './orderManagementDataSource';
export { platformAuthDataSource } from './platformAuthDataSource';
export { procurementDataSource } from './procurementDataSource';
export { productDataSource } from './productDataSource';
export { createProductManagementDataSource } from './productManagementDataSource';
export { productSelectionDataSource } from './productSelectionDataSource';
export { RecommendationDataSource } from './recommendationDataSource';
export { reportsDataSource } from './reportsDataSource';
export { returnDataSource } from './returnDataSource';
export * from './roleDataSource';
export { saasTenantDataSource } from './saasTenantDataSource';
export { serviceManagerDataSource } from './serviceManagerDataSource';
export { settingsDataSource } from './settingsDataSource';
export { shopDataSource } from './shopDataSource';
export { shopReportDataSource } from './shopReportDataSource';
export { SovereigntyDataSource } from './sovereigntyDataSource';
export { storeCreationDataSource } from './storeCreationDataSource';
export { suppliersDataSource } from './suppliersDataSource';
export { SyncDataSource } from './syncDataSource';
export { systemStatusDataSource } from './systemStatusDataSource';
export { taskCenterDataSource } from './taskCenterDataSource';
export { TelemetryDataSource } from './telemetryDataSource';
export { unifiedFulfillmentDataSource } from './unifiedFulfillmentDataSource';
export { userAssetDataSource } from './userAssetDataSource';
export { userDataSource } from './userDataSource';
export { TraceDataSource } from './traceDataSource';
export { VaultDataSource } from './vaultDataSource';
export { WebhookDataSource } from './webhookDataSource';
// 其他服务
export { lightweightClientService } from './lightweightClientService';
export { cloudService } from './cloud-service';
export * from './merchantService';
export * from './merchantOrderService';
export * from './merchantSettlementService';
export * from './merchantShopService';
export { default as behaviorAnalyticsService } from './behaviorAnalyticsService';
export { default as errorMonitorService } from './errorMonitorService';
export { notificationService } from './notificationService';
export { performanceMonitor } from './performanceMonitorService';
export { orderInventoryService } from './orderInventoryService';

View File

@@ -60,7 +60,7 @@ export class PlatformAuthMockDataSource implements PlatformAuthDataSource {
platform: 'AMAZON',
accountName: 'Amazon美国主店',
accountId: 'amazon_us_001',
status: 'active',
status: 'ACTIVE',
lastSyncAt: '2024-01-15T10:30:00Z',
createdAt: '2024-01-01T00:00:00Z',
updatedAt: '2024-01-15T10:30:00Z',
@@ -71,7 +71,7 @@ export class PlatformAuthMockDataSource implements PlatformAuthDataSource {
platform: 'SHOPIFY',
accountName: 'my-brand.myshopify.com',
accountId: 'shopify_456',
status: 'active',
status: 'ACTIVE',
lastSyncAt: '2024-01-15T09:15:00Z',
createdAt: '2024-01-01T00:00:00Z',
updatedAt: '2024-01-15T09:15:00Z',
@@ -82,7 +82,7 @@ export class PlatformAuthMockDataSource implements PlatformAuthDataSource {
platform: 'SHOPEE',
accountName: 'Shopee新加坡旗舰店',
accountId: 'shopee_sg_789',
status: 'expired',
status: 'EXPIRED',
lastSyncAt: '2023-12-01T08:00:00Z',
createdAt: '2023-06-01T00:00:00Z',
updatedAt: '2024-01-01T08:00:00Z',
@@ -93,7 +93,7 @@ export class PlatformAuthMockDataSource implements PlatformAuthDataSource {
platform: 'EBAY',
accountName: 'eBay全球店',
accountId: 'ebay_global_101',
status: 'inactive',
status: 'INACTIVE',
createdAt: '2024-01-10T00:00:00Z',
updatedAt: '2024-01-10T00:00:00Z',
},
@@ -103,7 +103,7 @@ export class PlatformAuthMockDataSource implements PlatformAuthDataSource {
platform: 'TIKTOK',
accountName: 'TikTok Shop官方店',
accountId: 'tiktok_official_202',
status: 'active',
status: 'ACTIVE',
lastSyncAt: '2024-01-15T14:20:00Z',
createdAt: '2023-12-15T00:00:00Z',
updatedAt: '2024-01-15T14:20:00Z',
@@ -114,7 +114,7 @@ export class PlatformAuthMockDataSource implements PlatformAuthDataSource {
platform: 'LAZADA',
accountName: 'Lazada泰国店',
accountId: 'lazada_th_303',
status: 'active',
status: 'ACTIVE',
lastSyncAt: '2024-01-14T16:45:00Z',
createdAt: '2023-11-20T00:00:00Z',
updatedAt: '2024-01-14T16:45:00Z',
@@ -125,7 +125,7 @@ export class PlatformAuthMockDataSource implements PlatformAuthDataSource {
platform: 'TEMU_FULL',
accountName: 'Temu全托管旗舰店',
accountId: 'temu_full_404',
status: 'active',
status: 'ACTIVE',
lastSyncAt: '2024-01-15T11:00:00Z',
createdAt: '2023-10-01T00:00:00Z',
updatedAt: '2024-01-15T11:00:00Z',
@@ -136,7 +136,7 @@ export class PlatformAuthMockDataSource implements PlatformAuthDataSource {
platform: 'SHEIN',
accountName: 'SHEIN官方店',
accountId: 'shein_official_505',
status: 'error',
status: 'ERROR',
lastSyncAt: '2024-01-10T09:30:00Z',
createdAt: '2023-09-15T00:00:00Z',
updatedAt: '2024-01-12T10:00:00Z',
@@ -147,7 +147,7 @@ export class PlatformAuthMockDataSource implements PlatformAuthDataSource {
platform: 'ALIEXPRESS',
accountName: '速卖通俄罗斯店',
accountId: 'aliexpress_ru_606',
status: 'active',
status: 'ACTIVE',
lastSyncAt: '2024-01-15T08:20:00Z',
createdAt: '2023-08-01T00:00:00Z',
updatedAt: '2024-01-15T08:20:00Z',
@@ -158,7 +158,7 @@ export class PlatformAuthMockDataSource implements PlatformAuthDataSource {
platform: 'WALMART',
accountName: 'Walmart美国店',
accountId: 'walmart_us_707',
status: 'inactive',
status: 'INACTIVE',
createdAt: '2024-01-05T00:00:00Z',
updatedAt: '2024-01-05T00:00:00Z',
},
@@ -168,7 +168,7 @@ export class PlatformAuthMockDataSource implements PlatformAuthDataSource {
platform: 'OZON',
accountName: 'Ozon俄罗斯店',
accountId: 'ozon_ru_808',
status: 'active',
status: 'ACTIVE',
lastSyncAt: '2024-01-15T07:15:00Z',
createdAt: '2023-07-01T00:00:00Z',
updatedAt: '2024-01-15T07:15:00Z',
@@ -179,7 +179,7 @@ export class PlatformAuthMockDataSource implements PlatformAuthDataSource {
platform: 'COUPANG',
accountName: 'Coupang韩国店',
accountId: 'coupang_kr_909',
status: 'expired',
status: 'EXPIRED',
lastSyncAt: '2023-11-15T06:00:00Z',
createdAt: '2023-05-01T00:00:00Z',
updatedAt: '2023-12-01T00:00:00Z',

View File

@@ -5,35 +5,10 @@
import moment from 'moment';
import { BaseDataSource, DataSourceFactory } from './baseDataSource';
import type { ExtendedProduct, ProductManagementStatus, Shop } from '../../../server/src/shared/schemas/productManagement.schema';
export interface Product {
id: string;
sku: string;
name: string;
image: string;
category: string;
price: number;
costPrice: number;
profit: number;
roi: number;
stock: number;
status: 'DRAFT' | 'PRICED' | 'LISTED' | 'SYNCING' | 'LIVE' | 'SYNC_FAILED' | 'OFFLINE';
platformStatus: Record<string, string>;
shopId: string;
shopName: string;
platform: string;
createdAt: string;
updatedAt: string;
}
export interface Shop {
id: string;
name: string;
platform: string;
status: 'ACTIVE' | 'INACTIVE' | 'SUSPENDED';
region: string;
currency: string;
}
export type Product = ExtendedProduct;
export type ProductStatus = ProductManagementStatus;
export interface ProductFilter {
keyword?: string;
@@ -123,286 +98,331 @@ const MOCK_PRODUCTS: Product[] = [
id: '1',
sku: 'TP-TEMP-001',
name: '工业温度传感器 Pro',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '工业自动化',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['工业自动化'],
price: 89.99,
costPrice: 45.00,
profit: 44.99,
roi: 99.98,
stock: 256,
description: '工业级温度传感器,高精度测量',
attributes: {},
status: 'LIVE',
platformStatus: { Amazon: 'LIVE', eBay: 'LIVE', Shopee: 'PENDING' },
shopId: 'shop-amazon-1',
shopName: 'Amazon美国店',
platform: 'Amazon',
createdAt: '2025-12-15',
updatedAt: '2026-03-18',
managementStatus: 'LIVE',
createdAt: '2025-12-15T00:00:00Z',
updatedAt: '2026-03-18T00:00:00Z',
},
{
id: '2',
sku: 'TP-PRES-002',
name: '压力传感器 Digital',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '工业自动化',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['工业自动化'],
price: 129.99,
costPrice: 65.00,
profit: 64.99,
roi: 99.98,
stock: 128,
description: '数字压力传感器,高精度测量',
attributes: {},
status: 'DRAFT',
platformStatus: {},
shopId: 'shop-tiktok-1',
shopName: 'TikTok旗舰店',
platform: 'TikTok',
createdAt: '2026-03-10',
updatedAt: '2026-03-10',
managementStatus: 'DRAFT',
createdAt: '2026-03-10T00:00:00Z',
updatedAt: '2026-03-10T00:00:00Z',
},
{
id: '3',
sku: 'TP-FLOW-003',
name: '流量计 Ultra',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '仪器仪表',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['仪器仪表'],
price: 299.99,
costPrice: 150.00,
profit: 149.99,
roi: 99.99,
stock: 64,
description: '高精度流量计,适用于工业环境',
attributes: {},
status: 'PRICED',
platformStatus: {},
shopId: 'shop-shopee-1',
shopName: 'Shopee官方店',
platform: 'Shopee',
createdAt: '2026-03-15',
updatedAt: '2026-03-16',
managementStatus: 'PRICED',
createdAt: '2026-03-15T00:00:00Z',
updatedAt: '2026-03-16T00:00:00Z',
},
{
id: '4',
sku: 'TP-MOTR-004',
name: '步进电机 57型',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '工业自动化',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['工业自动化'],
price: 59.99,
costPrice: 30.00,
profit: 29.99,
roi: 99.97,
stock: 512,
description: '57型步进电机高扭矩',
attributes: {},
status: 'LISTED',
platformStatus: { Amazon: 'LISTED' },
shopId: 'shop-amazon-2',
shopName: 'Amazon欧洲店',
platform: 'Amazon',
createdAt: '2026-03-01',
updatedAt: '2026-03-17',
managementStatus: 'LISTED',
createdAt: '2026-03-01T00:00:00Z',
updatedAt: '2026-03-17T00:00:00Z',
},
{
id: '5',
sku: 'TP-CTRL-005',
name: 'PLC控制器 Mini',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '工业自动化',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['工业自动化'],
price: 199.99,
costPrice: 100.00,
profit: 99.99,
roi: 99.99,
stock: 32,
description: '小型PLC控制器适用于自动化控制',
attributes: {},
status: 'SYNCING',
platformStatus: { Amazon: 'SYNCING', eBay: 'SYNCING' },
shopId: 'shop-ebay-1',
shopName: 'eBay全球店',
platform: 'eBay',
createdAt: '2026-03-18',
updatedAt: '2026-03-18',
managementStatus: 'SYNCING',
createdAt: '2026-03-18T00:00:00Z',
updatedAt: '2026-03-18T00:00:00Z',
},
{
id: '6',
sku: 'TP-SENS-006',
name: '光电传感器',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '工业自动化',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['工业自动化'],
price: 39.99,
costPrice: 20.00,
profit: 19.99,
roi: 99.95,
stock: 0,
description: '光电传感器,用于检测物体',
attributes: {},
status: 'SYNC_FAILED',
platformStatus: { Amazon: 'FAILED' },
shopId: 'shop-temu-1',
shopName: 'Temu旗舰店',
platform: 'TemuFull',
createdAt: '2026-03-05',
updatedAt: '2026-03-18',
managementStatus: 'SYNC_FAILED',
createdAt: '2026-03-05T00:00:00Z',
updatedAt: '2026-03-18T00:00:00Z',
},
{
id: '7',
sku: 'TP-VALV-007',
name: '电磁阀 24V',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '工具设备',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['工具设备'],
price: 79.99,
costPrice: 40.00,
profit: 39.99,
roi: 99.98,
stock: 200,
description: '24V电磁阀用于流体控制',
attributes: {},
status: 'OFFLINE',
platformStatus: { Amazon: 'OFFLINE', eBay: 'OFFLINE' },
shopId: 'shop-shein-1',
shopName: 'SHEIN官方店',
platform: 'Shein',
createdAt: '2025-11-20',
updatedAt: '2026-02-28',
managementStatus: 'OFFLINE',
createdAt: '2025-11-20T00:00:00Z',
updatedAt: '2026-02-28T00:00:00Z',
},
{
id: '8',
sku: 'TP-LEVEL-008',
name: '液位传感器',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '工业自动化',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['工业自动化'],
price: 69.99,
costPrice: 35.00,
profit: 34.99,
roi: 99.97,
stock: 150,
description: '液位传感器,用于检测液体 level',
attributes: {},
status: 'LIVE',
platformStatus: { Amazon: 'LIVE', TikTok: 'LIVE' },
shopId: 'shop-amazon-3',
shopName: 'Amazon日本店',
platform: 'Amazon',
createdAt: '2026-03-08',
updatedAt: '2026-03-18',
managementStatus: 'LIVE',
createdAt: '2026-03-08T00:00:00Z',
updatedAt: '2026-03-18T00:00:00Z',
},
{
id: '9',
sku: 'TP-RELAY-009',
name: '继电器模块',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '电子元器件',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['电子元器件'],
price: 29.99,
costPrice: 15.00,
profit: 14.99,
roi: 99.93,
stock: 1000,
description: '继电器模块,用于电路控制',
attributes: {},
status: 'LIVE',
platformStatus: { Shopee: 'LIVE', Lazada: 'LIVE' },
shopId: 'shop-shopee-2',
shopName: 'Shopee官方店B',
platform: 'Shopee',
createdAt: '2026-03-12',
updatedAt: '2026-03-17',
managementStatus: 'LIVE',
createdAt: '2026-03-12T00:00:00Z',
updatedAt: '2026-03-17T00:00:00Z',
},
{
id: '10',
sku: 'TP-FUSE-010',
name: '熔断器',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '电子元器件',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['电子元器件'],
price: 19.99,
costPrice: 10.00,
profit: 9.99,
roi: 99.90,
stock: 2000,
description: '熔断器,用于电路保护',
attributes: {},
status: 'LIVE',
platformStatus: { eBay: 'LIVE', AliExpress: 'LIVE' },
shopId: 'shop-ebay-2',
shopName: 'eBay全球店B',
platform: 'eBay',
createdAt: '2026-03-05',
updatedAt: '2026-03-16',
managementStatus: 'LIVE',
createdAt: '2026-03-05T00:00:00Z',
updatedAt: '2026-03-16T00:00:00Z',
},
{
id: '11',
sku: 'TP-METER-011',
name: '万用表 Digital',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '仪器仪表',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['仪器仪表'],
price: 149.99,
costPrice: 75.00,
profit: 74.99,
roi: 99.99,
stock: 80,
description: '数字万用表,用于电气测量',
attributes: {},
status: 'PRICED',
platformStatus: {},
shopId: 'shop-lazada-1',
shopName: 'Lazada官方店A',
platform: 'Lazada',
createdAt: '2026-03-14',
updatedAt: '2026-03-15',
managementStatus: 'PRICED',
createdAt: '2026-03-14T00:00:00Z',
updatedAt: '2026-03-15T00:00:00Z',
},
{
id: '12',
sku: 'TP-TOOL-012',
name: '电动螺丝刀套装',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '工具设备',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['工具设备'],
price: 89.99,
costPrice: 45.00,
profit: 44.99,
roi: 99.98,
stock: 120,
description: '电动螺丝刀套装,多规格批头',
attributes: {},
status: 'LISTED',
platformStatus: { Amazon: 'LISTED' },
shopId: 'shop-amazon-4',
shopName: 'Amazon欧洲店D',
platform: 'Amazon',
createdAt: '2026-03-03',
updatedAt: '2026-03-17',
managementStatus: 'LISTED',
createdAt: '2026-03-03T00:00:00Z',
updatedAt: '2026-03-17T00:00:00Z',
},
{
id: '13',
sku: 'TP-CAM-013',
name: '安防摄像头',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '安防设备',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['安防设备'],
price: 199.99,
costPrice: 100.00,
profit: 99.99,
roi: 99.99,
stock: 50,
description: '安防摄像头,高清监控',
attributes: {},
status: 'DRAFT',
platformStatus: {},
shopId: 'shop-tiktok-2',
shopName: 'TikTok旗舰店B',
platform: 'TikTok',
createdAt: '2026-03-16',
updatedAt: '2026-03-16',
managementStatus: 'DRAFT',
createdAt: '2026-03-16T00:00:00Z',
updatedAt: '2026-03-16T00:00:00Z',
},
{
id: '14',
sku: 'TP-ALARM-014',
name: '烟雾报警器',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '安防设备',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['安防设备'],
price: 49.99,
costPrice: 25.00,
profit: 24.99,
roi: 99.96,
stock: 180,
description: '烟雾报警器,火灾预警',
attributes: {},
status: 'LIVE',
platformStatus: { Shopee: 'LIVE', TemuFull: 'LIVE' },
shopId: 'shop-temu-2',
shopName: 'Temu旗舰店B',
platform: 'TemuFull',
createdAt: '2026-03-07',
updatedAt: '2026-03-18',
managementStatus: 'LIVE',
createdAt: '2026-03-07T00:00:00Z',
updatedAt: '2026-03-18T00:00:00Z',
},
{
id: '15',
sku: 'TP-SENSOR-015',
name: '湿度传感器',
image: 'https://via.placeholder.com/80x80?text=Product',
category: '工业自动化',
images: ['https://via.placeholder.com/80x80?text=Product'],
categories: ['工业自动化'],
price: 59.99,
costPrice: 30.00,
profit: 29.99,
roi: 99.97,
stock: 200,
description: '湿度传感器,用于环境监测',
attributes: {},
status: 'SYNCING',
platformStatus: { Amazon: 'SYNCING' },
shopId: 'shop-amazon-5',
shopName: 'Amazon日本店E',
platform: 'Amazon',
createdAt: '2026-03-17',
updatedAt: '2026-03-18',
managementStatus: 'SYNCING',
createdAt: '2026-03-17T00:00:00Z',
updatedAt: '2026-03-18T00:00:00Z',
},
];
@@ -502,8 +522,8 @@ export class ProductDataSourceImpl extends BaseDataSource implements ProductData
const newProduct: Product = {
...product,
id: `${Date.now()}`,
createdAt: moment().format('YYYY-MM-DD'),
updatedAt: moment().format('YYYY-MM-DD'),
createdAt: moment().toISOString(),
updatedAt: moment().toISOString(),
};
this.products.unshift(newProduct);
return newProduct;
@@ -523,7 +543,7 @@ export class ProductDataSourceImpl extends BaseDataSource implements ProductData
this.products[index] = {
...this.products[index],
...product,
updatedAt: moment().format('YYYY-MM-DD'),
updatedAt: moment().toISOString(),
};
return this.products[index];
@@ -557,9 +577,10 @@ export class ProductDataSourceImpl extends BaseDataSource implements ProductData
sku: `${originalProduct.sku}-COPY`,
name: `${originalProduct.name} (复制)`,
status: 'DRAFT',
managementStatus: 'DRAFT',
platformStatus: {},
createdAt: moment().format('YYYY-MM-DD'),
updatedAt: moment().format('YYYY-MM-DD'),
createdAt: moment().toISOString(),
updatedAt: moment().toISOString(),
};
this.products.unshift(newProduct);

View File

@@ -1 +1,16 @@
// 导出后端共享类型
export * from '../../../server/src/shared/types/index';
// 导出前端本地类型
export * from './certificate';
export * from './dataSourceMap';
export * from './datasource';
export * from './order';
export * from './platform';
export * from './procurement';
export * from './product';
export * from './productManagement';
export * from './productSelection';
export * from './user';
export * from './warehouse';

View File

@@ -0,0 +1,12 @@
// 统一导出所有工具函数
export * from './api';
export * from './apiDebounce';
export * from './cache';
export * from './errorHandler';
export * from './memo';
export * from './notification';
export * from './performance';
export * from './responsive';
export * from './security';