From 6d0d2b6157f23de03b84a8bb887c815f63a50dbc Mon Sep 17 00:00:00 2001 From: wurenzhi Date: Wed, 18 Mar 2026 19:12:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=92=8C=E4=B8=9A=E5=8A=A1=E8=AF=B4=E6=98=8E?= =?UTF-8?q?=E4=B9=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refactor(server): 重构服务层代码结构 feat(server): 添加基础设施、跨境电商、AI决策等核心服务 docs: 完善前端业务说明书和开发进度文档 style: 格式化代码和文档 --- client/src/components/ComponentLibrary.tsx | 302 +++ client/src/components/Layout.tsx | 26 + client/src/components/MenuComponent.tsx | 89 + client/src/pages/AdPage.tsx | 435 ++++ client/src/pages/B2BPage.tsx | 474 ++++ client/src/pages/CompliancePage.tsx | 500 ++++ client/src/pages/DashboardPage.tsx | 235 ++ client/src/pages/FinancePage.tsx | 436 ++++ client/src/pages/IndependentSite/List.tsx | 287 +++ client/src/pages/InventoryPage.tsx | 370 +++ client/src/pages/OrdersPage.tsx | 480 ++++ client/src/pages/ProductPage.tsx | 527 +++++ client/src/pages/SettingsPage.tsx | 581 +++++ client/src/routes/index.tsx | 37 + client/src/services/ApiService.ts | 83 + dashboard/.umi/appData.json | 2025 ----------------- dashboard/.umi/core/EmptyRoute.tsx | 9 - dashboard/.umi/core/defineApp.ts | 16 - dashboard/.umi/core/helmet.ts | 10 - dashboard/.umi/core/helmetContext.ts | 4 - dashboard/.umi/core/history.ts | 72 - dashboard/.umi/core/historyIntelli.ts | 132 -- dashboard/.umi/core/plugin.ts | 40 - dashboard/.umi/core/pluginConfig.ts | 324 --- dashboard/.umi/core/pluginConfigJoi.d.ts | 7 - dashboard/.umi/core/polyfill.ts | 220 -- dashboard/.umi/core/route.tsx | 29 - dashboard/.umi/core/routeProps.ts | 6 - dashboard/.umi/core/terminal.ts | 37 - dashboard/.umi/exports.ts | 19 - dashboard/.umi/testBrowser.tsx | 88 - dashboard/.umi/tsconfig.json | 44 - dashboard/.umi/typings.d.ts | 136 -- dashboard/.umi/umi.ts | 81 - dashboard/src/.umi/appData.json | 472 +++- dashboard/src/.umi/core/route.tsx | 54 +- .../src/pages/Ad/AIOptimization/index.tsx | 410 ++++ .../src/pages/Ad/AutoAdjustment/index.tsx | 369 +++ dashboard/src/pages/Ad/Performance/index.tsx | 485 ++++ dashboard/src/pages/Ad/index.tsx | 29 + dashboard/src/pages/AfterSales/index.tsx | 29 + dashboard/src/pages/B2B/index.tsx | 29 + dashboard/src/pages/Blacklist/index.tsx | 29 + dashboard/src/pages/Compliance/index.tsx | 29 + .../src/pages/Finance/Reconciliation.tsx | 243 ++ dashboard/src/pages/Finance/Transactions.tsx | 221 ++ dashboard/src/pages/Finance/index.ts | 11 + dashboard/src/pages/Finance/index.tsx | 137 ++ .../IndependentSiteAnalytics.tsx | 283 +++ .../IndependentSite/IndependentSiteConfig.tsx | 292 +++ .../IndependentSite/IndependentSiteCreate.tsx | 154 ++ .../IndependentSite/IndependentSiteList.tsx | 251 ++ .../IndependentSite/IndependentSiteOrder.tsx | 359 +++ .../IndependentSiteProduct.tsx | 330 +++ dashboard/src/pages/IndependentSite/index.ts | 17 + .../src/pages/Inventory/InventoryForecast.tsx | 224 ++ dashboard/src/pages/Inventory/Warehouses.tsx | 282 +++ dashboard/src/pages/Inventory/index.ts | 11 + dashboard/src/pages/Inventory/index.tsx | 214 ++ dashboard/src/pages/Logistics/index.tsx | 29 + dashboard/src/pages/Marketing/Ads.tsx | 281 +++ dashboard/src/pages/Marketing/Competitors.tsx | 321 +++ dashboard/src/pages/Marketing/index.ts | 11 + dashboard/src/pages/Marketing/index.tsx | 123 + dashboard/src/pages/Merchant/index.tsx | 29 + dashboard/src/pages/Orders/index.tsx | 38 + .../src/pages/Product/AIPricing/index.tsx | 297 +++ .../src/pages/Product/ProfitMonitor/index.tsx | 360 +++ .../src/pages/Product/ROIAnalysis/index.tsx | 325 +++ dashboard/src/pages/Product/index.tsx | 38 + .../src/pages/Reports/PerformanceReport.tsx | 295 +++ dashboard/src/pages/Reports/ProfitReport.tsx | 305 +++ dashboard/src/pages/Reports/index.ts | 11 + dashboard/src/pages/Reports/index.tsx | 130 ++ dashboard/src/pages/Role/index.tsx | 311 +++ .../src/pages/Settings/ProfileSettings.tsx | 189 ++ .../src/pages/Settings/TenantSettings.tsx | 187 ++ .../src/pages/Settings/UserManagement.tsx | 315 +++ dashboard/src/pages/Settings/index.ts | 13 + dashboard/src/pages/Settings/index.tsx | 115 + .../src/pages/Suppliers/SupplierDetail.tsx | 323 +++ dashboard/src/pages/Suppliers/index.ts | 9 + dashboard/src/pages/Suppliers/index.tsx | 255 +++ dashboard/src/pages/System/index.tsx | 287 +++ dashboard/src/pages/User/index.tsx | 271 +++ dashboard/src/pages/index.tsx | 19 +- docs/00_Business/Business_ClosedLoops.md | 183 +- .../Business_ClosedLoops_Analysis.md | 42 +- docs/00_Business/Task_Overview.md | 164 +- docs/01_Architecture/frontend/Ad.front.md | 138 ++ .../frontend/IndependentSite.front.md | 145 ++ docs/01_Architecture/frontend/Orders.front.md | 130 ++ .../01_Architecture/frontend/Product.front.md | 124 + docs/02_Backend/Config_Driven.md | 402 ++++ docs/02_Backend/Data_Consistency.md | 442 ++++ docs/02_Backend/Event_Driven.md | 492 ++++ docs/02_Backend/Observability.md | 349 +++ docs/02_Backend/RBAC_Design.md | 383 ++++ docs/02_Backend/Service_Design.md | 433 ++++ docs/03_Frontend/Frontend_Design.md | 467 ++-- .../03_Frontend/Frontend_Development_Guide.md | 792 +++++++ .../Frontend_Optimization_Guide.md | 511 +++++ docs/03_Frontend/Interaction_Guidelines.md | 287 +++ docs/03_Frontend/Pages_Flow.md | 193 +- docs/03_Frontend/UI_Components.md | 409 +++- docs/Development_Progress.md | 41 +- docs/临时修改建议 copy.MD | 745 ++++++ docs1/Business_ClosedLoops.md | 964 -------- docs1/README.md | 33 - docs1/Task_Overview.md | 509 ----- docs1/临时修改建议.MD | 78 - docs11/临时修改建议 copy.MD | 327 --- server/src/core/runtime/DomainBootstrap.ts | 24 +- .../core/runtime/LegacyTableInitializer.ts | 567 ++--- server/src/index.ts | 23 +- server/src/services/AIDecisionService.ts | 58 + server/src/services/BillingService.ts | 2 +- server/src/services/CoreBusinessService.ts | 299 +++ .../services/CoreServicePriorityService.ts | 47 + server/src/services/CrossBorderService.ts | 58 + server/src/services/CustomerService.ts | 47 + server/src/services/DataManagementService.ts | 298 +++ .../src/services/FeatureActivationService.ts | 5 +- .../services/FinanceReconciliationService.ts | 2 +- server/src/services/InfrastructureService.ts | 58 + server/src/services/MediaAssetService.ts | 2 +- .../services/MerchantProductOrderService.ts | 4 +- .../src/services/MerchantSettlementService.ts | 2 +- .../src/services/MessageProcessingService.ts | 325 +++ server/src/services/MonitoringAlertService.ts | 334 +++ server/src/services/PaymentService.ts | 2 +- server/src/services/RBACService.ts | 2 +- server/src/services/ReportService.ts | 2 +- .../src/services/SecurityComplianceService.ts | 289 +++ .../src/services/ServiceManagementService.ts | 239 ++ server/src/types/data.ts | 46 + server/src/types/message.ts | 44 + server/src/types/monitoring.ts | 41 + server/src/types/security.ts | 44 + server/src/types/service.ts | 33 + 140 files changed, 23859 insertions(+), 5833 deletions(-) create mode 100644 client/src/components/ComponentLibrary.tsx create mode 100644 client/src/components/Layout.tsx create mode 100644 client/src/components/MenuComponent.tsx create mode 100644 client/src/pages/AdPage.tsx create mode 100644 client/src/pages/B2BPage.tsx create mode 100644 client/src/pages/CompliancePage.tsx create mode 100644 client/src/pages/DashboardPage.tsx create mode 100644 client/src/pages/FinancePage.tsx create mode 100644 client/src/pages/IndependentSite/List.tsx create mode 100644 client/src/pages/InventoryPage.tsx create mode 100644 client/src/pages/OrdersPage.tsx create mode 100644 client/src/pages/ProductPage.tsx create mode 100644 client/src/pages/SettingsPage.tsx create mode 100644 client/src/routes/index.tsx create mode 100644 client/src/services/ApiService.ts delete mode 100644 dashboard/.umi/appData.json delete mode 100644 dashboard/.umi/core/EmptyRoute.tsx delete mode 100644 dashboard/.umi/core/defineApp.ts delete mode 100644 dashboard/.umi/core/helmet.ts delete mode 100644 dashboard/.umi/core/helmetContext.ts delete mode 100644 dashboard/.umi/core/history.ts delete mode 100644 dashboard/.umi/core/historyIntelli.ts delete mode 100644 dashboard/.umi/core/plugin.ts delete mode 100644 dashboard/.umi/core/pluginConfig.ts delete mode 100644 dashboard/.umi/core/pluginConfigJoi.d.ts delete mode 100644 dashboard/.umi/core/polyfill.ts delete mode 100644 dashboard/.umi/core/route.tsx delete mode 100644 dashboard/.umi/core/routeProps.ts delete mode 100644 dashboard/.umi/core/terminal.ts delete mode 100644 dashboard/.umi/exports.ts delete mode 100644 dashboard/.umi/testBrowser.tsx delete mode 100644 dashboard/.umi/tsconfig.json delete mode 100644 dashboard/.umi/typings.d.ts delete mode 100644 dashboard/.umi/umi.ts create mode 100644 dashboard/src/pages/Ad/AIOptimization/index.tsx create mode 100644 dashboard/src/pages/Ad/AutoAdjustment/index.tsx create mode 100644 dashboard/src/pages/Ad/Performance/index.tsx create mode 100644 dashboard/src/pages/Ad/index.tsx create mode 100644 dashboard/src/pages/AfterSales/index.tsx create mode 100644 dashboard/src/pages/B2B/index.tsx create mode 100644 dashboard/src/pages/Blacklist/index.tsx create mode 100644 dashboard/src/pages/Compliance/index.tsx create mode 100644 dashboard/src/pages/Finance/Reconciliation.tsx create mode 100644 dashboard/src/pages/Finance/Transactions.tsx create mode 100644 dashboard/src/pages/Finance/index.ts create mode 100644 dashboard/src/pages/Finance/index.tsx create mode 100644 dashboard/src/pages/IndependentSite/IndependentSiteAnalytics.tsx create mode 100644 dashboard/src/pages/IndependentSite/IndependentSiteConfig.tsx create mode 100644 dashboard/src/pages/IndependentSite/IndependentSiteCreate.tsx create mode 100644 dashboard/src/pages/IndependentSite/IndependentSiteList.tsx create mode 100644 dashboard/src/pages/IndependentSite/IndependentSiteOrder.tsx create mode 100644 dashboard/src/pages/IndependentSite/IndependentSiteProduct.tsx create mode 100644 dashboard/src/pages/IndependentSite/index.ts create mode 100644 dashboard/src/pages/Inventory/InventoryForecast.tsx create mode 100644 dashboard/src/pages/Inventory/Warehouses.tsx create mode 100644 dashboard/src/pages/Inventory/index.ts create mode 100644 dashboard/src/pages/Inventory/index.tsx create mode 100644 dashboard/src/pages/Logistics/index.tsx create mode 100644 dashboard/src/pages/Marketing/Ads.tsx create mode 100644 dashboard/src/pages/Marketing/Competitors.tsx create mode 100644 dashboard/src/pages/Marketing/index.ts create mode 100644 dashboard/src/pages/Marketing/index.tsx create mode 100644 dashboard/src/pages/Merchant/index.tsx create mode 100644 dashboard/src/pages/Orders/index.tsx create mode 100644 dashboard/src/pages/Product/AIPricing/index.tsx create mode 100644 dashboard/src/pages/Product/ProfitMonitor/index.tsx create mode 100644 dashboard/src/pages/Product/ROIAnalysis/index.tsx create mode 100644 dashboard/src/pages/Product/index.tsx create mode 100644 dashboard/src/pages/Reports/PerformanceReport.tsx create mode 100644 dashboard/src/pages/Reports/ProfitReport.tsx create mode 100644 dashboard/src/pages/Reports/index.ts create mode 100644 dashboard/src/pages/Reports/index.tsx create mode 100644 dashboard/src/pages/Role/index.tsx create mode 100644 dashboard/src/pages/Settings/ProfileSettings.tsx create mode 100644 dashboard/src/pages/Settings/TenantSettings.tsx create mode 100644 dashboard/src/pages/Settings/UserManagement.tsx create mode 100644 dashboard/src/pages/Settings/index.ts create mode 100644 dashboard/src/pages/Settings/index.tsx create mode 100644 dashboard/src/pages/Suppliers/SupplierDetail.tsx create mode 100644 dashboard/src/pages/Suppliers/index.ts create mode 100644 dashboard/src/pages/Suppliers/index.tsx create mode 100644 dashboard/src/pages/System/index.tsx create mode 100644 dashboard/src/pages/User/index.tsx create mode 100644 docs/01_Architecture/frontend/Ad.front.md create mode 100644 docs/01_Architecture/frontend/IndependentSite.front.md create mode 100644 docs/01_Architecture/frontend/Orders.front.md create mode 100644 docs/01_Architecture/frontend/Product.front.md create mode 100644 docs/02_Backend/Config_Driven.md create mode 100644 docs/02_Backend/Data_Consistency.md create mode 100644 docs/02_Backend/Event_Driven.md create mode 100644 docs/02_Backend/Observability.md create mode 100644 docs/02_Backend/RBAC_Design.md create mode 100644 docs/02_Backend/Service_Design.md create mode 100644 docs/03_Frontend/Frontend_Development_Guide.md create mode 100644 docs/03_Frontend/Frontend_Optimization_Guide.md create mode 100644 docs/03_Frontend/Interaction_Guidelines.md create mode 100644 docs/临时修改建议 copy.MD delete mode 100644 docs1/Business_ClosedLoops.md delete mode 100644 docs1/README.md delete mode 100644 docs1/Task_Overview.md delete mode 100644 docs1/临时修改建议.MD delete mode 100644 docs11/临时修改建议 copy.MD create mode 100644 server/src/services/AIDecisionService.ts create mode 100644 server/src/services/CoreBusinessService.ts create mode 100644 server/src/services/CoreServicePriorityService.ts create mode 100644 server/src/services/CrossBorderService.ts create mode 100644 server/src/services/CustomerService.ts create mode 100644 server/src/services/DataManagementService.ts create mode 100644 server/src/services/InfrastructureService.ts create mode 100644 server/src/services/MessageProcessingService.ts create mode 100644 server/src/services/MonitoringAlertService.ts create mode 100644 server/src/services/SecurityComplianceService.ts create mode 100644 server/src/services/ServiceManagementService.ts create mode 100644 server/src/types/data.ts create mode 100644 server/src/types/message.ts create mode 100644 server/src/types/monitoring.ts create mode 100644 server/src/types/security.ts create mode 100644 server/src/types/service.ts diff --git a/client/src/components/ComponentLibrary.tsx b/client/src/components/ComponentLibrary.tsx new file mode 100644 index 0000000..588ce5a --- /dev/null +++ b/client/src/components/ComponentLibrary.tsx @@ -0,0 +1,302 @@ +import React from 'react'; +import { Button, Card, Table, Input, Select, DatePicker, Space, Modal, Form, InputNumber, Tag, Badge, message, Spin, Alert } from 'antd'; + +// 业务按钮组件 +export const BusinessButton: React.FC<{ + type: 'primary' | 'default' | 'dashed' | 'danger' | 'link'; + onClick: () => void; + children: React.ReactNode; + loading?: boolean; + disabled?: boolean; +}> = ({ type, onClick, children, loading = false, disabled = false }) => { + return ( + + ); +}; + +// 业务卡片组件 +export const BusinessCard: React.FC<{ + title: string; + children: React.ReactNode; + extra?: React.ReactNode; + style?: React.CSSProperties; +}> = ({ title, children, extra, style }) => { + return ( + + {children} + + ); +}; + +// 业务表格组件 +export const BusinessTable: React.FC<{ + columns: any[]; + dataSource: any[]; + rowKey: string; + pagination?: boolean | any; + rowSelection?: any; +}> = ({ columns, dataSource, rowKey, pagination = true, rowSelection }) => { + return ( + + ); +}; + +// 业务输入框组件 +export const BusinessInput: React.FC<{ + placeholder: string; + value: string; + onChange: (e: React.ChangeEvent) => void; + style?: React.CSSProperties; + prefix?: React.ReactNode; + suffix?: React.ReactNode; +}> = ({ placeholder, value, onChange, style, prefix, suffix }) => { + return ( + + ); +}; + +// 业务选择器组件 +export const BusinessSelect: React.FC<{ + placeholder: string; + value: string; + onChange: (value: string) => void; + options: { label: string; value: string }[]; + style?: React.CSSProperties; +}> = ({ placeholder, value, onChange, options, style }) => { + return ( + + ); +}; + +// 业务日期选择器组件 +export const BusinessDatePicker: React.FC<{ + placeholder: string; + value: any; + onChange: (dates: any, dateStrings: any) => void; + style?: React.CSSProperties; + range?: boolean; +}> = ({ placeholder, value, onChange, style, range = false }) => { + const { RangePicker, DatePicker: AntDatePicker } = DatePicker; + return range ? ( + + ) : ( + + ); +}; + +// 业务模态框组件 +export const BusinessModal: React.FC<{ + title: string; + open: boolean; + onCancel: () => void; + onOk: () => void; + children: React.ReactNode; + width?: number; + footer?: React.ReactNode; +}> = ({ title, open, onCancel, onOk, children, width = 600, footer }) => { + return ( + + {children} + + ); +}; + +// 业务表单组件 +export const BusinessForm: React.FC<{ + form: any; + onFinish: (values: any) => void; + children: React.ReactNode; + layout?: 'horizontal' | 'vertical' | 'inline'; +}> = ({ form, onFinish, children, layout = 'vertical' }) => { + return ( +
+ {children} + + ); +}; + +// 业务加载组件 +export const BusinessLoading: React.FC<{ + loading: boolean; + children: React.ReactNode; + tip?: string; +}> = ({ loading, children, tip = 'Loading...' }) => { + return ( + + {children} + + ); +}; + +// 业务提示组件 +export const BusinessAlert: React.FC<{ + type: 'success' | 'info' | 'warning' | 'error'; + message: string; + description?: string; + closable?: boolean; +}> = ({ type, message, description, closable = true }) => { + return ( + + ); +}; + +// 业务标签组件 +export const BusinessTag: React.FC<{ + color: string; + children: React.ReactNode; +}> = ({ color, children }) => { + return ( + + {children} + + ); +}; + +// 业务徽章组件 +export const BusinessBadge: React.FC<{ + status: 'success' | 'processing' | 'default' | 'error' | 'warning'; + text: string; +}> = ({ status, text }) => { + return ( + + ); +}; + +// 业务消息组件 +export const BusinessMessage: { + success: (content: string) => void; + error: (content: string) => void; + warning: (content: string) => void; + info: (content: string) => void; +} = { + success: (content) => message.success(content), + error: (content) => message.error(content), + warning: (content) => message.warning(content), + info: (content) => message.info(content), +}; + +// 业务间距组件 +export const BusinessSpace: React.FC<{ + children: React.ReactNode; + size?: 'small' | 'middle' | 'large'; + direction?: 'horizontal' | 'vertical'; +}> = ({ children, size = 'middle', direction = 'horizontal' }) => { + return ( + + {children} + + ); +}; + +export default { + BusinessButton, + BusinessCard, + BusinessTable, + BusinessInput, + BusinessSelect, + BusinessDatePicker, + BusinessModal, + BusinessForm, + BusinessLoading, + BusinessAlert, + BusinessTag, + BusinessBadge, + BusinessMessage, + BusinessSpace, +}; \ No newline at end of file diff --git a/client/src/components/Layout.tsx b/client/src/components/Layout.tsx new file mode 100644 index 0000000..06e55ad --- /dev/null +++ b/client/src/components/Layout.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Layout as AntLayout } from 'antd'; +import MenuComponent from './MenuComponent'; +import { Outlet } from 'react-router-dom'; + +const { Sider, Content } = AntLayout; + +const Layout: React.FC = () => { + return ( + + +
+ Crawlful Hub +
+ +
+ + + + + +
+ ); +}; + +export default Layout; \ No newline at end of file diff --git a/client/src/components/MenuComponent.tsx b/client/src/components/MenuComponent.tsx new file mode 100644 index 0000000..ad6fa25 --- /dev/null +++ b/client/src/components/MenuComponent.tsx @@ -0,0 +1,89 @@ +import React from 'react'; +import { Menu } from 'antd'; +import { + DashboardOutlined, + ShoppingOutlined, + OrderedListOutlined, + TabletOutlined, + InboxOutlined, + TeamOutlined, + DollarOutlined, + SafetyCertificateOutlined, + SettingOutlined, + HomeOutlined +} from '@ant-design/icons'; +import { Link, useLocation } from 'react-router-dom'; + +const MenuComponent: React.FC = () => { + const location = useLocation(); + const currentPath = location.pathname; + + const menuItems = [ + { + key: '/dashboard', + icon: , + label: Dashboard, + }, + { + key: '/product', + icon: , + label: Product, + }, + { + key: '/orders', + icon: , + label: Orders, + }, + { + key: '/ad', + icon: , + label: Ad, + }, + { + key: '/inventory', + icon: , + label: Inventory, + }, + { + key: '/b2b', + icon: , + label: B2B, + }, + { + key: '/finance', + icon: , + label: Finance, + }, + { + key: '/compliance', + icon: , + label: Compliance, + }, + { + key: '/settings', + icon: , + label: Settings, + }, + { + key: '/independent-site', + icon: , + label: Independent Site, + }, + ]; + + return ( +
+ +
+ ); +}; + +export default MenuComponent; \ No newline at end of file diff --git a/client/src/pages/AdPage.tsx b/client/src/pages/AdPage.tsx new file mode 100644 index 0000000..81926e6 --- /dev/null +++ b/client/src/pages/AdPage.tsx @@ -0,0 +1,435 @@ +import React, { useState } from 'react'; +import { Card, Table, Button, Select, DatePicker, Space, Modal, Typography, Badge, message, Tabs, Row, Col, Statistic } from 'antd'; +import { PlusOutlined, EyeOutlined, EditOutlined, DeleteOutlined, ReloadOutlined, PlayCircleOutlined, PauseCircleOutlined, BarChartOutlined, DollarOutlined } from '@ant-design/icons'; + +const { Option } = Select; +const { RangePicker } = DatePicker; +const { Title, Text } = Typography; +const { TabPane } = Tabs; + +const mockAds = [ + { + id: '1', + name: 'Electronics Sale Campaign', + platform: 'Amazon', + status: 'active', + budget: 1000, + spent: 650, + clicks: 1250, + impressions: 15000, + ctr: 8.33, + conversions: 85, + cpa: 7.65, + roi: 2.5, + createdAt: '2026-03-01', + updatedAt: '2026-03-18', + }, + { + id: '2', + name: 'Fashion Week Promotion', + platform: 'eBay', + status: 'paused', + budget: 800, + spent: 400, + clicks: 800, + impressions: 10000, + ctr: 8.0, + conversions: 45, + cpa: 8.89, + roi: 1.8, + createdAt: '2026-03-05', + updatedAt: '2026-03-15', + }, + { + id: '3', + name: 'Home Decor Spring Sale', + platform: 'Shopee', + status: 'active', + budget: 600, + spent: 350, + clicks: 700, + impressions: 9000, + ctr: 7.78, + conversions: 40, + cpa: 8.75, + roi: 2.2, + createdAt: '2026-03-10', + updatedAt: '2026-03-18', + }, + { + id: '4', + name: 'Sports Equipment Launch', + platform: 'Amazon', + status: 'completed', + budget: 1200, + spent: 1180, + clicks: 2400, + impressions: 30000, + ctr: 8.0, + conversions: 180, + cpa: 6.56, + roi: 3.2, + createdAt: '2026-02-20', + updatedAt: '2026-03-10', + }, +]; + +const AdPage: React.FC = () => { + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const [isDetailModalVisible, setIsDetailModalVisible] = useState(false); + const [selectedAd, setSelectedAd] = useState(null); + const [activeTab, setActiveTab] = useState('campaigns'); + + const handleViewDetail = (record: any) => { + setSelectedAd(record); + setIsDetailModalVisible(true); + }; + + const handleCreateAd = () => { + message.success('Create ad campaign form opened'); + }; + + const handleEditAd = (record: any) => { + message.success(`Edit ad campaign ${record.name}`); + }; + + const handleDeleteAd = (record: any) => { + message.success(`Delete ad campaign ${record.name}`); + }; + + const handleStartAd = (record: any) => { + message.success(`Start ad campaign ${record.name}`); + }; + + const handlePauseAd = (record: any) => { + message.success(`Pause ad campaign ${record.name}`); + }; + + const handleBatchDelete = () => { + message.success('Batch delete initiated'); + }; + + const handleBatchPause = () => { + message.success('Batch pause initiated'); + }; + + const handleBatchStart = () => { + message.success('Batch start initiated'); + }; + + const getStatusColor = (status: string) => { + switch (status) { + case 'active': return 'success'; + case 'paused': return 'warning'; + case 'completed': return 'default'; + case 'error': return 'error'; + default: return 'default'; + } + }; + + const columns = [ + { + title: 'Campaign Name', + dataIndex: 'name', + key: 'name', + }, + { + title: 'Platform', + dataIndex: 'platform', + key: 'platform', + }, + { + title: 'Status', + dataIndex: 'status', + key: 'status', + render: (status: string) => ( + + ), + }, + { + title: 'Budget', + dataIndex: 'budget', + key: 'budget', + render: (value: number) => `$${value.toFixed(2)}`, + }, + { + title: 'Spent', + dataIndex: 'spent', + key: 'spent', + render: (value: number) => `$${value.toFixed(2)}`, + }, + { + title: 'Clicks', + dataIndex: 'clicks', + key: 'clicks', + }, + { + title: 'Impressions', + dataIndex: 'impressions', + key: 'impressions', + }, + { + title: 'CTR', + dataIndex: 'ctr', + key: 'ctr', + render: (value: number) => `${value.toFixed(2)}%`, + }, + { + title: 'Conversions', + dataIndex: 'conversions', + key: 'conversions', + }, + { + title: 'CPA', + dataIndex: 'cpa', + key: 'cpa', + render: (value: number) => `$${value.toFixed(2)}`, + }, + { + title: 'ROI', + dataIndex: 'roi', + key: 'roi', + render: (value: number) => `${value.toFixed(2)}x`, + }, + { + title: 'Actions', + key: 'actions', + render: (_: any, record: any) => ( + + + + {record.status === 'active' ? ( + + ) : ( + + )} + + + + ), + }, + ]; + + const rowSelection = { + selectedRowKeys, + onChange: (keys: React.Key[]) => { + setSelectedRowKeys(keys); + }, + }; + + return ( +
+
+ Advertising Management + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + +
+ + + +
+ +
+ + +
+ Analytics dashboard will be displayed here +
+
+ +
+ AI optimization suggestions will be displayed here +
+
+ + + + setIsDetailModalVisible(false)} + footer={[ + , + ]} + width={1000} + > + {selectedAd && ( + + +
+

Basic Information

+
+
+ Campaign Name: {selectedAd.name} +
+
+ Platform: {selectedAd.platform} +
+
+ Status: +
+
+ Budget: ${selectedAd.budget.toFixed(2)} +
+
+ Spent: ${selectedAd.spent.toFixed(2)} +
+
+ Created At: {selectedAd.createdAt} +
+
+ Updated At: {selectedAd.updatedAt} +
+
+
+
+

Performance Metrics

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Detailed analytics will be displayed here +
+
+ +
+ AI optimization suggestions will be displayed here +
+
+ + )} + + + ); +}; + +export default AdPage; \ No newline at end of file diff --git a/client/src/pages/B2BPage.tsx b/client/src/pages/B2BPage.tsx new file mode 100644 index 0000000..4afd92f --- /dev/null +++ b/client/src/pages/B2BPage.tsx @@ -0,0 +1,474 @@ +import React, { useState } from 'react'; +import { Card, Table, Button, Select, DatePicker, Space, Modal, Typography, Badge, message, Tabs, Row, Col, Statistic, Input, Form } from 'antd'; +import { PlusOutlined, EyeOutlined, EditOutlined, DeleteOutlined, ReloadOutlined, FileTextOutlined, DollarOutlined, TeamOutlined, CheckCircleOutlined, CloseCircleOutlined } from '@ant-design/icons'; + +const { Option } = Select; +const { RangePicker } = DatePicker; +const { Title, Text } = Typography; +const { TabPane } = Tabs; +const { TextArea } = Input; + +const mockQuotes = [ + { + id: '1', + quoteNo: 'B2B-2026-001', + customer: 'ABC Electronics Inc.', + contact: 'John Smith', + email: 'john@abc-electronics.com', + totalAmount: 15000, + status: 'pending', + items: [ + { name: 'Wireless Headphones', quantity: 100, price: 50 }, + { name: 'Bluetooth Speaker', quantity: 50, price: 80 }, + ], + createdAt: '2026-03-15', + updatedAt: '2026-03-18', + }, + { + id: '2', + quoteNo: 'B2B-2026-002', + customer: 'XYZ Fashion Ltd.', + contact: 'Jane Doe', + email: 'jane@xyz-fashion.com', + totalAmount: 25000, + status: 'approved', + items: [ + { name: 'Smart Watch', quantity: 80, price: 120 }, + { name: 'Fitness Tracker', quantity: 120, price: 80 }, + ], + createdAt: '2026-03-10', + updatedAt: '2026-03-16', + }, + { + id: '3', + quoteNo: 'B2B-2026-003', + customer: 'Global Home Decor', + contact: 'Bob Johnson', + email: 'bob@global-home.com', + totalAmount: 8000, + status: 'rejected', + items: [ + { name: 'Home Decor Set', quantity: 40, price: 200 }, + ], + createdAt: '2026-03-05', + updatedAt: '2026-03-12', + }, + { + id: '4', + quoteNo: 'B2B-2026-004', + customer: 'Sports Equipment Co.', + contact: 'Alice Williams', + email: 'alice@sports-equip.com', + totalAmount: 18000, + status: 'completed', + items: [ + { name: 'Sports Equipment Set', quantity: 60, price: 300 }, + ], + createdAt: '2026-03-01', + updatedAt: '2026-03-10', + }, +]; + +const mockContracts = [ + { + id: '1', + contractNo: 'CON-2026-001', + customer: 'ABC Electronics Inc.', + startDate: '2026-03-01', + endDate: '2026-12-31', + totalAmount: 150000, + status: 'active', + terms: 'Net 30 days', + createdAt: '2026-02-28', + }, + { + id: '2', + contractNo: 'CON-2026-002', + customer: 'XYZ Fashion Ltd.', + startDate: '2026-03-15', + endDate: '2027-03-14', + totalAmount: 300000, + status: 'active', + terms: 'Net 45 days', + createdAt: '2026-03-10', + }, + { + id: '3', + contractNo: 'CON-2026-003', + customer: 'Global Home Decor', + startDate: '2026-01-01', + endDate: '2026-12-31', + totalAmount: 100000, + status: 'expired', + terms: 'Net 30 days', + createdAt: '2025-12-28', + }, +]; + +const B2BPage: React.FC = () => { + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const [isDetailModalVisible, setIsDetailModalVisible] = useState(false); + const [selectedQuote, setSelectedQuote] = useState(null); + const [activeTab, setActiveTab] = useState('quotes'); + const [searchKeyword, setSearchKeyword] = useState(''); + + const handleViewDetail = (record: any) => { + setSelectedQuote(record); + setIsDetailModalVisible(true); + }; + + const handleCreateQuote = () => { + message.success('Create quote form opened'); + }; + + const handleEditQuote = (record: any) => { + message.success(`Edit quote ${record.quoteNo}`); + }; + + const handleDeleteQuote = (record: any) => { + message.success(`Delete quote ${record.quoteNo}`); + }; + + const handleApproveQuote = (record: any) => { + message.success(`Approve quote ${record.quoteNo}`); + }; + + const handleRejectQuote = (record: any) => { + message.success(`Reject quote ${record.quoteNo}`); + }; + + const handleConvertToOrder = (record: any) => { + message.success(`Convert quote ${record.quoteNo} to order`); + }; + + const handleBatchDelete = () => { + message.success('Batch delete initiated'); + }; + + const handleBatchApprove = () => { + message.success('Batch approve initiated'); + }; + + const getStatusColor = (status: string) => { + switch (status) { + case 'pending': return 'processing'; + case 'approved': return 'success'; + case 'rejected': return 'error'; + case 'completed': return 'success'; + case 'active': return 'success'; + case 'expired': return 'default'; + default: return 'default'; + } + }; + + const quoteColumns = [ + { + title: 'Quote No', + dataIndex: 'quoteNo', + key: 'quoteNo', + }, + { + title: 'Customer', + dataIndex: 'customer', + key: 'customer', + }, + { + title: 'Contact', + dataIndex: 'contact', + key: 'contact', + }, + { + title: 'Email', + dataIndex: 'email', + key: 'email', + }, + { + title: 'Total Amount', + dataIndex: 'totalAmount', + key: 'totalAmount', + render: (value: number) => `$${value.toLocaleString()}`, + }, + { + title: 'Status', + dataIndex: 'status', + key: 'status', + render: (status: string) => ( + + ), + }, + { + title: 'Created At', + dataIndex: 'createdAt', + key: 'createdAt', + }, + { + title: 'Actions', + key: 'actions', + render: (_: any, record: any) => ( + + + + {record.status === 'pending' && ( + <> + + + + )} + {record.status === 'approved' && ( + + )} + + + ), + }, + ]; + + const contractColumns = [ + { + title: 'Contract No', + dataIndex: 'contractNo', + key: 'contractNo', + }, + { + title: 'Customer', + dataIndex: 'customer', + key: 'customer', + }, + { + title: 'Start Date', + dataIndex: 'startDate', + key: 'startDate', + }, + { + title: 'End Date', + dataIndex: 'endDate', + key: 'endDate', + }, + { + title: 'Total Amount', + dataIndex: 'totalAmount', + key: 'totalAmount', + render: (value: number) => `$${value.toLocaleString()}`, + }, + { + title: 'Status', + dataIndex: 'status', + key: 'status', + render: (status: string) => ( + + ), + }, + { + title: 'Terms', + dataIndex: 'terms', + key: 'terms', + }, + { + title: 'Created At', + dataIndex: 'createdAt', + key: 'createdAt', + }, + ]; + + const rowSelection = { + selectedRowKeys, + onChange: (keys: React.Key[]) => { + setSelectedRowKeys(keys); + }, + }; + + const filteredQuotes = mockQuotes.filter(quote => + quote.customer.toLowerCase().includes(searchKeyword.toLowerCase()) || + quote.quoteNo.toLowerCase().includes(searchKeyword.toLowerCase()) + ); + + return ( +
+
+ B2B Trade Management + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + +
+ setSearchKeyword(e.target.value)} + style={{ width: 300 }} + allowClear + /> + + +
+ +
+ + +
+ + +
+ +
+ + + + + setIsDetailModalVisible(false)} + footer={[ + , + ]} + width={1000} + > + {selectedQuote && ( + + +
+

Basic Information

+
+
+ Quote No: {selectedQuote.quoteNo} +
+
+ Customer: {selectedQuote.customer} +
+
+ Contact: {selectedQuote.contact} +
+
+ Email: {selectedQuote.email} +
+
+ Total Amount: ${selectedQuote.totalAmount.toLocaleString()} +
+
+ Status: +
+
+ Created At: {selectedQuote.createdAt} +
+
+ Updated At: {selectedQuote.updatedAt} +
+
+
+
+

Quote Items

+
`$${value.toFixed(2)}` }, + { title: 'Total', key: 'total', render: (_: any, record: any) => `$${(record.quantity * record.price).toFixed(2)}` }, + ]} + dataSource={selectedQuote.items} + rowKey="name" + pagination={false} + /> + +
+

Quick Actions

+ + {selectedQuote.status === 'pending' && ( + <> + + + + )} + {selectedQuote.status === 'approved' && ( + + )} + +
+ + +
+ Customer information will be displayed here +
+
+ +
+ Quote history will be displayed here +
+
+ + )} + + + ); +}; + +export default B2BPage; \ No newline at end of file diff --git a/client/src/pages/CompliancePage.tsx b/client/src/pages/CompliancePage.tsx new file mode 100644 index 0000000..e0bffd7 --- /dev/null +++ b/client/src/pages/CompliancePage.tsx @@ -0,0 +1,500 @@ +import React, { useState } from 'react'; +import { Card, Table, Button, Select, DatePicker, Space, Modal, Typography, Badge, message, Tabs, Row, Col, Statistic, Input, Alert } from 'antd'; +import { PlusOutlined, EyeOutlined, EditOutlined, DeleteOutlined, ReloadOutlined, WarningOutlined, CheckCircleOutlined, ExclamationCircleOutlined, SafetyCertificateOutlined, FileTextOutlined } from '@ant-design/icons'; + +const { Option } = Select; +const { RangePicker } = DatePicker; +const { Title, Text } = Typography; +const { TabPane } = Tabs; + +const mockCertificates = [ + { + id: '1', + certificateNo: 'CERT-2026-001', + name: 'CE Certification', + type: 'Product Safety', + status: 'valid', + expiryDate: '2026-12-31', + issuingAuthority: 'European Commission', + products: ['Wireless Headphones', 'Bluetooth Speaker'], + document: 'ce-cert-001.pdf', + createdAt: '2026-01-15', + updatedAt: '2026-03-18', + }, + { + id: '2', + certificateNo: 'CERT-2026-002', + name: 'FCC Certification', + type: 'Electromagnetic Compatibility', + status: 'valid', + expiryDate: '2027-06-30', + issuingAuthority: 'Federal Communications Commission', + products: ['Smart Watch', 'Fitness Tracker'], + document: 'fcc-cert-002.pdf', + createdAt: '2026-02-20', + updatedAt: '2026-03-18', + }, + { + id: '3', + certificateNo: 'CERT-2026-003', + name: 'RoHS Certification', + type: 'Environmental', + status: 'expiring', + expiryDate: '2026-04-30', + issuingAuthority: 'European Union', + products: ['Home Decor Set'], + document: 'rohs-cert-003.pdf', + createdAt: '2026-01-10', + updatedAt: '2026-03-18', + }, + { + id: '4', + certificateNo: 'CERT-2026-004', + name: 'ISO 9001 Certification', + type: 'Quality Management', + status: 'expired', + expiryDate: '2026-02-28', + issuingAuthority: 'International Organization for Standardization', + products: ['All Products'], + document: 'iso-9001-004.pdf', + createdAt: '2025-12-01', + updatedAt: '2026-03-01', + }, +]; + +const mockComplianceChecks = [ + { + id: '1', + checkNo: 'COMP-2026-001', + productId: 'P001', + productName: 'Wireless Headphones', + platform: 'Amazon', + checkType: 'Product Listing', + status: 'passed', + issues: [], + checkedAt: '2026-03-18', + checkedBy: 'System', + }, + { + id: '2', + checkNo: 'COMP-2026-002', + productId: 'P002', + productName: 'Bluetooth Speaker', + platform: 'eBay', + checkType: 'Product Listing', + status: 'warning', + issues: ['Missing product description', 'Incomplete specifications'], + checkedAt: '2026-03-18', + checkedBy: 'System', + }, + { + id: '3', + checkNo: 'COMP-2026-003', + productId: 'P003', + productName: 'Smart Watch', + platform: 'Shopee', + checkType: 'Product Listing', + status: 'failed', + issues: ['Invalid certificate', 'Missing safety warnings'], + checkedAt: '2026-03-17', + checkedBy: 'System', + }, +]; + +const CompliancePage: React.FC = () => { + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const [isDetailModalVisible, setIsDetailModalVisible] = useState(false); + const [selectedCertificate, setSelectedCertificate] = useState(null); + const [activeTab, setActiveTab] = useState('certificates'); + const [searchKeyword, setSearchKeyword] = useState(''); + + const handleViewDetail = (record: any) => { + setSelectedCertificate(record); + setIsDetailModalVisible(true); + }; + + const handleAddCertificate = () => { + message.success('Add certificate form opened'); + }; + + const handleEditCertificate = (record: any) => { + message.success(`Edit certificate ${record.certificateNo}`); + }; + + const handleDeleteCertificate = (record: any) => { + message.success(`Delete certificate ${record.certificateNo}`); + }; + + const handleRenewCertificate = (record: any) => { + message.success(`Renew certificate ${record.certificateNo}`); + }; + + const handleRunComplianceCheck = () => { + message.success('Compliance check initiated'); + }; + + const handleBatchDelete = () => { + message.success('Batch delete initiated'); + }; + + const handleBatchRenew = () => { + message.success('Batch renew initiated'); + }; + + const getStatusColor = (status: string) => { + switch (status) { + case 'valid': return 'success'; + case 'expiring': return 'warning'; + case 'expired': return 'error'; + case 'passed': return 'success'; + case 'warning': return 'warning'; + case 'failed': return 'error'; + default: return 'default'; + } + }; + + const getStatusIcon = (status: string) => { + switch (status) { + case 'valid': return ; + case 'expiring': return ; + case 'expired': return ; + case 'passed': return ; + case 'warning': return ; + case 'failed': return ; + default: return null; + } + }; + + const certificateColumns = [ + { + title: 'Certificate No', + dataIndex: 'certificateNo', + key: 'certificateNo', + }, + { + title: 'Name', + dataIndex: 'name', + key: 'name', + }, + { + title: 'Type', + dataIndex: 'type', + key: 'type', + }, + { + title: 'Status', + dataIndex: 'status', + key: 'status', + render: (status: string) => ( + + ), + }, + { + title: 'Expiry Date', + dataIndex: 'expiryDate', + key: 'expiryDate', + render: (date: string) => { + const expiryDate = new Date(date); + const today = new Date(); + const daysUntilExpiry = Math.ceil((expiryDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24)); + + if (daysUntilExpiry < 0) { + return {date} (Expired); + } else if (daysUntilExpiry <= 30) { + return {date} (Expiring Soon); + } else { + return {date}; + } + }, + }, + { + title: 'Issuing Authority', + dataIndex: 'issuingAuthority', + key: 'issuingAuthority', + }, + { + title: 'Products', + dataIndex: 'products', + key: 'products', + render: (products: string[]) => products.join(', '), + }, + { + title: 'Actions', + key: 'actions', + render: (_: any, record: any) => ( + + + + + + + ), + }, + ]; + + const checkColumns = [ + { + title: 'Check No', + dataIndex: 'checkNo', + key: 'checkNo', + }, + { + title: 'Product', + dataIndex: 'productName', + key: 'productName', + }, + { + title: 'Platform', + dataIndex: 'platform', + key: 'platform', + }, + { + title: 'Check Type', + dataIndex: 'checkType', + key: 'checkType', + }, + { + title: 'Status', + dataIndex: 'status', + key: 'status', + render: (status: string) => ( + + ), + }, + { + title: 'Issues', + dataIndex: 'issues', + key: 'issues', + render: (issues: string[]) => ( +
+ {issues.length === 0 ? ( + No issues + ) : ( + issues.map((issue, index) => ( +
+ {issue} +
+ )) + )} +
+ ), + }, + { + title: 'Checked At', + dataIndex: 'checkedAt', + key: 'checkedAt', + }, + { + title: 'Checked By', + dataIndex: 'checkedBy', + key: 'checkedBy', + }, + ]; + + const rowSelection = { + selectedRowKeys, + onChange: (keys: React.Key[]) => { + setSelectedRowKeys(keys); + }, + }; + + const filteredCertificates = mockCertificates.filter(certificate => + certificate.name.toLowerCase().includes(searchKeyword.toLowerCase()) || + certificate.certificateNo.toLowerCase().includes(searchKeyword.toLowerCase()) + ); + + return ( +
+
+ Compliance Management + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + +
+ setSearchKeyword(e.target.value)} + style={{ width: 300 }} + allowClear + /> + + + +
+ +
+ + +
+ + + +
+ +
+ + + + + setIsDetailModalVisible(false)} + footer={[ + , + ]} + width={800} + > + {selectedCertificate && ( +
+
+

Basic Information

+
+
+ Certificate No: {selectedCertificate.certificateNo} +
+
+ Name: {selectedCertificate.name} +
+
+ Type: {selectedCertificate.type} +
+
+ Status: +
+
+ Expiry Date: {selectedCertificate.expiryDate} +
+
+ Issuing Authority: {selectedCertificate.issuingAuthority} +
+
+ Created At: {selectedCertificate.createdAt} +
+
+ Updated At: {selectedCertificate.updatedAt} +
+
+
+
+

Products

+
+ {selectedCertificate.products.map((product: string, index: number) => ( +
+ +
+ ))} +
+
+
+

Document

+
+ +
+
+
+

Quick Actions

+ + + + +
+
+ )} +
+ + ); +}; + +export default CompliancePage; \ No newline at end of file diff --git a/client/src/pages/DashboardPage.tsx b/client/src/pages/DashboardPage.tsx new file mode 100644 index 0000000..17e2d76 --- /dev/null +++ b/client/src/pages/DashboardPage.tsx @@ -0,0 +1,235 @@ +import React, { useState, useEffect } from 'react'; +import { Card, Row, Col, DatePicker, Statistic, Button, Select, message } from 'antd'; +import { ArrowUpOutlined, ArrowDownOutlined, ReloadOutlined, DownloadOutlined, SettingOutlined } from '@ant-design/icons'; +import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'; +import { dashboardApi } from '../services/ApiService'; + +const { RangePicker } = DatePicker; +const { Option } = Select; + +const DashboardPage: React.FC = () => { + const [timeRange, setTimeRange] = useState(null); + const [shop, setShop] = useState('all'); + const [kpiData, setKpiData] = useState([]); + const [trendData, setTrendData] = useState([]); + const [loading, setLoading] = useState(false); + + // 加载Dashboard数据 + useEffect(() => { + loadDashboardData(); + }, [shop, timeRange]); + + const loadDashboardData = async () => { + setLoading(true); + try { + const response = await dashboardApi.getDashboardData({ + shop, + startDate: timeRange?.[0]?.format('YYYY-MM-DD'), + endDate: timeRange?.[1]?.format('YYYY-MM-DD'), + }); + + if (response.kpiData) { + setKpiData(response.kpiData); + } else { + // 使用默认KPI数据 + setKpiData([ + { + title: '总销售额', + value: '¥128,500', + change: 12.5, + status: 'up', + icon: , + }, + { + title: '订单数', + value: '2,850', + change: 8.2, + status: 'up', + icon: , + }, + { + title: '转化率', + value: '4.8%', + change: -1.2, + status: 'down', + icon: , + }, + { + title: '平均订单价值', + value: '¥45.1', + change: 3.5, + status: 'up', + icon: , + }, + ]); + } + + if (response.trendData) { + setTrendData(response.trendData); + } else { + // 使用默认趋势数据 + setTrendData([ + { date: '1/1', sales: 12000, orders: 350 }, + { date: '1/2', sales: 15000, orders: 420 }, + { date: '1/3', sales: 18000, orders: 480 }, + { date: '1/4', sales: 16000, orders: 430 }, + { date: '1/5', sales: 20000, orders: 520 }, + { date: '1/6', sales: 22000, orders: 550 }, + { date: '1/7', sales: 25000, orders: 600 }, + ]); + } + } catch (error) { + console.error('Failed to load dashboard data:', error); + message.error('Failed to load dashboard data'); + // 使用默认数据 + setKpiData([ + { + title: '总销售额', + value: '¥128,500', + change: 12.5, + status: 'up', + icon: , + }, + { + title: '订单数', + value: '2,850', + change: 8.2, + status: 'up', + icon: , + }, + { + title: '转化率', + value: '4.8%', + change: -1.2, + status: 'down', + icon: , + }, + { + title: '平均订单价值', + value: '¥45.1', + change: 3.5, + status: 'up', + icon: , + }, + ]); + setTrendData([ + { date: '1/1', sales: 12000, orders: 350 }, + { date: '1/2', sales: 15000, orders: 420 }, + { date: '1/3', sales: 18000, orders: 480 }, + { date: '1/4', sales: 16000, orders: 430 }, + { date: '1/5', sales: 20000, orders: 520 }, + { date: '1/6', sales: 22000, orders: 550 }, + { date: '1/7', sales: 25000, orders: 600 }, + ]); + } finally { + setLoading(false); + } + }; + + const handleTimeRangeChange = (dates: any) => { + setTimeRange(dates); + }; + + const handleShopChange = (value: string) => { + setShop(value); + }; + + const handleRefresh = () => { + loadDashboardData(); + }; + + const handleExport = async () => { + try { + await dashboardApi.getDashboardData({ + shop, + startDate: timeRange?.[0]?.format('YYYY-MM-DD'), + endDate: timeRange?.[1]?.format('YYYY-MM-DD'), + export: true, + }); + message.success('Report exported successfully'); + } catch (error) { + console.error('Failed to export report:', error); + message.error('Failed to export report'); + } + }; + + return ( +
+
+

Dashboard

+
+ + + + + +
+
+ + + {kpiData.map((kpi, index) => ( +
+ + + {kpi.status === 'up' ? : } + {Math.abs(kpi.change)}% + + } + /> + + + ))} + + + +
+ + + + + + + + + + + +
+
+ + + + +
+

Product performance data will be displayed here

+
+
+ + + +
+

Recent orders data will be displayed here

+
+
+ + + + ); +}; + +// 导入缺失的图标 +import { DollarOutlined, OrderedListOutlined, LineChartOutlined, ShoppingOutlined } from '@ant-design/icons'; + +export default DashboardPage; \ No newline at end of file diff --git a/client/src/pages/FinancePage.tsx b/client/src/pages/FinancePage.tsx new file mode 100644 index 0000000..6e85feb --- /dev/null +++ b/client/src/pages/FinancePage.tsx @@ -0,0 +1,436 @@ +import React, { useState } from 'react'; +import { Card, Table, Button, Select, DatePicker, Space, Modal, Typography, Badge, message, Tabs, Row, Col, Statistic } from 'antd'; +import { PlusOutlined, EyeOutlined, EditOutlined, DeleteOutlined, ReloadOutlined, DollarOutlined, FileTextOutlined, CheckCircleOutlined, CloseCircleOutlined, SyncOutlined } from '@ant-design/icons'; + +const { Option } = Select; +const { RangePicker } = DatePicker; +const { Title, Text } = Typography; +const { TabPane } = Tabs; + +const mockTransactions = [ + { + id: '1', + transactionNo: 'TXN-2026-001', + type: 'income', + category: 'Sales Revenue', + amount: 12500, + status: 'completed', + description: 'Product sales revenue', + date: '2026-03-18', + createdAt: '2026-03-18', + }, + { + id: '2', + transactionNo: 'TXN-2026-002', + type: 'expense', + category: 'Product Cost', + amount: 8500, + status: 'completed', + description: 'Product purchase cost', + date: '2026-03-17', + createdAt: '2026-03-17', + }, + { + id: '3', + transactionNo: 'TXN-2026-003', + type: 'expense', + category: 'Shipping Cost', + amount: 1200, + status: 'completed', + description: 'Shipping and logistics cost', + date: '2026-03-16', + createdAt: '2026-03-16', + }, + { + id: '4', + transactionNo: 'TXN-2026-004', + type: 'income', + category: 'Refund', + amount: 350, + status: 'pending', + description: 'Customer refund', + date: '2026-03-15', + createdAt: '2026-03-15', + }, +]; + +const mockSettlements = [ + { + id: '1', + settlementNo: 'SET-2026-001', + platform: 'Amazon', + period: '2026-03-01 to 2026-03-15', + totalAmount: 45000, + fee: 2250, + netAmount: 42750, + status: 'completed', + createdAt: '2026-03-16', + }, + { + id: '2', + settlementNo: 'SET-2026-002', + platform: 'eBay', + period: '2026-03-01 to 2026-03-15', + totalAmount: 28000, + fee: 1400, + netAmount: 26600, + status: 'pending', + createdAt: '2026-03-16', + }, + { + id: '3', + settlementNo: 'SET-2026-003', + platform: 'Shopee', + period: '2026-02-16 to 2026-02-28', + totalAmount: 32000, + fee: 1600, + netAmount: 30400, + status: 'completed', + createdAt: '2026-03-01', + }, +]; + +const FinancePage: React.FC = () => { + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const [isDetailModalVisible, setIsDetailModalVisible] = useState(false); + const [selectedTransaction, setSelectedTransaction] = useState(null); + const [activeTab, setActiveTab] = useState('transactions'); + const [searchKeyword, setSearchKeyword] = useState(''); + + const handleViewDetail = (record: any) => { + setSelectedTransaction(record); + setIsDetailModalVisible(true); + }; + + const handleCreateTransaction = () => { + message.success('Create transaction form opened'); + }; + + const handleEditTransaction = (record: any) => { + message.success(`Edit transaction ${record.transactionNo}`); + }; + + const handleDeleteTransaction = (record: any) => { + message.success(`Delete transaction ${record.transactionNo}`); + }; + + const handleReconcile = (record: any) => { + message.success(`Reconcile transaction ${record.transactionNo}`); + }; + + const handleBatchDelete = () => { + message.success('Batch delete initiated'); + }; + + const handleBatchReconcile = () => { + message.success('Batch reconcile initiated'); + }; + + const getStatusColor = (status: string) => { + switch (status) { + case 'completed': return 'success'; + case 'pending': return 'processing'; + case 'failed': return 'error'; + case 'cancelled': return 'default'; + default: return 'default'; + } + }; + + const getTypeColor = (type: string) => { + switch (type) { + case 'income': return 'success'; + case 'expense': return 'error'; + default: return 'default'; + } + }; + + const transactionColumns = [ + { + title: 'Transaction No', + dataIndex: 'transactionNo', + key: 'transactionNo', + }, + { + title: 'Type', + dataIndex: 'type', + key: 'type', + render: (type: string) => ( + + ), + }, + { + title: 'Category', + dataIndex: 'category', + key: 'category', + }, + { + title: 'Amount', + dataIndex: 'amount', + key: 'amount', + render: (value: number) => `$${value.toLocaleString()}`, + }, + { + title: 'Status', + dataIndex: 'status', + key: 'status', + render: (status: string) => ( + + ), + }, + { + title: 'Description', + dataIndex: 'description', + key: 'description', + }, + { + title: 'Date', + dataIndex: 'date', + key: 'date', + }, + { + title: 'Actions', + key: 'actions', + render: (_: any, record: any) => ( + + + + + + + ), + }, + ]; + + const settlementColumns = [ + { + title: 'Settlement No', + dataIndex: 'settlementNo', + key: 'settlementNo', + }, + { + title: 'Platform', + dataIndex: 'platform', + key: 'platform', + }, + { + title: 'Period', + dataIndex: 'period', + key: 'period', + }, + { + title: 'Total Amount', + dataIndex: 'totalAmount', + key: 'totalAmount', + render: (value: number) => `$${value.toLocaleString()}`, + }, + { + title: 'Fee', + dataIndex: 'fee', + key: 'fee', + render: (value: number) => `$${value.toLocaleString()}`, + }, + { + title: 'Net Amount', + dataIndex: 'netAmount', + key: 'netAmount', + render: (value: number) => `$${value.toLocaleString()}`, + }, + { + title: 'Status', + dataIndex: 'status', + key: 'status', + render: (status: string) => ( + + ), + }, + { + title: 'Created At', + dataIndex: 'createdAt', + key: 'createdAt', + }, + ]; + + const rowSelection = { + selectedRowKeys, + onChange: (keys: React.Key[]) => { + setSelectedRowKeys(keys); + }, + }; + + const filteredTransactions = mockTransactions.filter(transaction => + transaction.description.toLowerCase().includes(searchKeyword.toLowerCase()) || + transaction.transactionNo.toLowerCase().includes(searchKeyword.toLowerCase()) + ); + + return ( +
+
+ Finance Management + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + +
+ + + +
+ +
+ + +
+ + + +
+ +
+ + +
+ Financial reports will be displayed here +
+
+ + + + setIsDetailModalVisible(false)} + footer={[ + , + ]} + width={800} + > + {selectedTransaction && ( +
+
+

Basic Information

+
+
+ Transaction No: {selectedTransaction.transactionNo} +
+
+ Type: +
+
+ Category: {selectedTransaction.category} +
+
+ Amount: ${selectedTransaction.amount.toLocaleString()} +
+
+ Status: +
+
+ Date: {selectedTransaction.date} +
+
+ Created At: {selectedTransaction.createdAt} +
+
+
+
+

Description

+
+ {selectedTransaction.description} +
+
+
+

Quick Actions

+ + + + +
+
+ )} +
+ + ); +}; + +export default FinancePage; \ No newline at end of file diff --git a/client/src/pages/IndependentSite/List.tsx b/client/src/pages/IndependentSite/List.tsx new file mode 100644 index 0000000..9f9bbbe --- /dev/null +++ b/client/src/pages/IndependentSite/List.tsx @@ -0,0 +1,287 @@ +import React, { useState } from 'react'; +import { Card, Table, Button, Select, DatePicker, Space, Modal, Typography, Badge, message } from 'antd'; +import { PlusOutlined, EyeOutlined, EditOutlined, DeleteOutlined, ReloadOutlined, SettingOutlined, ShoppingOutlined, FileTextOutlined, BarChartOutlined } from '@ant-design/icons'; + +const { Option } = Select; +const { RangePicker } = DatePicker; +const { Title, Text } = Typography; + +const mockSites = [ + { + id: '1', + name: 'My Electronics Store', + domain: 'electronics-store.com', + status: 'active', + template: 'Modern E-commerce', + theme: 'Blue', + createdAt: '2026-03-01', + updatedAt: '2026-03-15', + }, + { + id: '2', + name: 'Fashion Boutique', + domain: 'fashion-boutique.com', + status: 'active', + template: 'Fashion Store', + theme: 'Pink', + createdAt: '2026-03-05', + updatedAt: '2026-03-10', + }, + { + id: '3', + name: 'Home Decor Shop', + domain: 'home-decor-shop.com', + status: 'inactive', + template: 'Home Decor', + theme: 'Neutral', + createdAt: '2026-02-20', + updatedAt: '2026-03-01', + }, + { + id: '4', + name: 'Sports Equipment Store', + domain: 'sports-equipment.com', + status: 'active', + template: 'Sports Store', + theme: 'Green', + createdAt: '2026-03-10', + updatedAt: '2026-03-18', + }, +]; + +const IndependentSiteList: React.FC = () => { + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const [isDetailModalVisible, setIsDetailModalVisible] = useState(false); + const [selectedSite, setSelectedSite] = useState(null); + + const handleViewDetail = (record: any) => { + setSelectedSite(record); + setIsDetailModalVisible(true); + }; + + const handleCreateSite = () => { + message.success('Create site form opened'); + }; + + const handleEditSite = (record: any) => { + message.success(`Edit site ${record.name}`); + }; + + const handleDeleteSite = (record: any) => { + message.success(`Delete site ${record.name}`); + }; + + const handleConfigureSite = (record: any) => { + message.success(`Configure site ${record.name}`); + }; + + const handleManageProducts = (record: any) => { + message.success(`Manage products for ${record.name}`); + }; + + const handleManageOrders = (record: any) => { + message.success(`Manage orders for ${record.name}`); + }; + + const handleAnalyzeData = (record: any) => { + message.success(`Analyze data for ${record.name}`); + }; + + const handleBatchDelete = () => { + message.success('Batch delete initiated'); + }; + + const getStatusColor = (status: string) => { + switch (status) { + case 'active': return 'success'; + case 'inactive': return 'default'; + case 'pending': return 'processing'; + case 'error': return 'error'; + default: return 'default'; + } + }; + + const columns = [ + { + title: 'Site Name', + dataIndex: 'name', + key: 'name', + }, + { + title: 'Domain', + dataIndex: 'domain', + key: 'domain', + }, + { + title: 'Status', + dataIndex: 'status', + key: 'status', + render: (status: string) => ( + + ), + }, + { + title: 'Template', + dataIndex: 'template', + key: 'template', + }, + { + title: 'Theme', + dataIndex: 'theme', + key: 'theme', + }, + { + title: 'Created At', + dataIndex: 'createdAt', + key: 'createdAt', + }, + { + title: 'Updated At', + dataIndex: 'updatedAt', + key: 'updatedAt', + }, + { + title: 'Actions', + key: 'actions', + render: (_: any, record: any) => ( + + + + + + + + + + ), + }, + ]; + + const rowSelection = { + selectedRowKeys, + onChange: (keys: React.Key[]) => { + setSelectedRowKeys(keys); + }, + }; + + return ( +
+
+ Independent Sites + + + + + +
+ + +
+ + + +
+ +
+ + + +
+
+

Total Sites

+

4

+
+
+

Active Sites

+

3

+
+
+

Inactive Sites

+

1

+
+
+

Total Products

+

120

+
+
+

Total Orders

+

85

+
+
+
+ + setIsDetailModalVisible(false)} + footer={[ + , + ]} + width={800} + > + {selectedSite && ( +
+
+

Basic Information

+
+
+ Site Name: {selectedSite.name} +
+
+ Domain: {selectedSite.domain} +
+
+ Status: +
+
+ Template: {selectedSite.template} +
+
+ Theme: {selectedSite.theme} +
+
+ Created At: {selectedSite.createdAt} +
+
+ Updated At: {selectedSite.updatedAt} +
+
+
+
+

Quick Actions

+ + + + + + +
+
+ )} +
+ + ); +}; + +export default IndependentSiteList; \ No newline at end of file diff --git a/client/src/pages/InventoryPage.tsx b/client/src/pages/InventoryPage.tsx new file mode 100644 index 0000000..e0d8aeb --- /dev/null +++ b/client/src/pages/InventoryPage.tsx @@ -0,0 +1,370 @@ +import React, { useState } from 'react'; +import { Card, Table, Button, Select, DatePicker, Space, Modal, Typography, Badge, message, Row, Col, Statistic, Input } from 'antd'; +import { PlusOutlined, EyeOutlined, EditOutlined, DeleteOutlined, ReloadOutlined, WarningOutlined, CheckCircleOutlined, ExclamationCircleOutlined } from '@ant-design/icons'; + +const { Option } = Select; +const { RangePicker } = DatePicker; +const { Title, Text } = Typography; + +const mockInventory = [ + { + id: '1', + productId: 'P001', + productName: 'Wireless Headphones', + sku: 'WH-001', + quantity: 150, + available: 120, + reserved: 30, + reorderPoint: 50, + location: 'Warehouse A', + status: 'normal', + lastUpdated: '2026-03-18', + }, + { + id: '2', + productId: 'P002', + productName: 'Bluetooth Speaker', + sku: 'BS-002', + quantity: 80, + available: 20, + reserved: 60, + reorderPoint: 30, + location: 'Warehouse B', + status: 'low', + lastUpdated: '2026-03-18', + }, + { + id: '3', + productId: 'P003', + productName: 'Smart Watch', + sku: 'SW-003', + quantity: 200, + available: 180, + reserved: 20, + reorderPoint: 100, + location: 'Warehouse A', + status: 'normal', + lastUpdated: '2026-03-17', + }, + { + id: '4', + productId: 'P004', + productName: 'Fitness Tracker', + sku: 'FT-004', + quantity: 10, + available: 5, + reserved: 5, + reorderPoint: 20, + location: 'Warehouse C', + status: 'critical', + lastUpdated: '2026-03-18', + }, +]; + +const InventoryPage: React.FC = () => { + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const [isDetailModalVisible, setIsDetailModalVisible] = useState(false); + const [selectedItem, setSelectedItem] = useState(null); + const [searchKeyword, setSearchKeyword] = useState(''); + + const handleViewDetail = (record: any) => { + setSelectedItem(record); + setIsDetailModalVisible(true); + }; + + const handleAddInventory = () => { + message.success('Add inventory form opened'); + }; + + const handleEditInventory = (record: any) => { + message.success(`Edit inventory ${record.productName}`); + }; + + const handleDeleteInventory = (record: any) => { + message.success(`Delete inventory ${record.productName}`); + }; + + const handleAdjustStock = (record: any) => { + message.success(`Adjust stock for ${record.productName}`); + }; + + const handleTransferStock = (record: any) => { + message.success(`Transfer stock for ${record.productName}`); + }; + + const handleBatchDelete = () => { + message.success('Batch delete initiated'); + }; + + const handleBatchAdjust = () => { + message.success('Batch adjust initiated'); + }; + + const getStatusColor = (status: string) => { + switch (status) { + case 'normal': return 'success'; + case 'low': return 'warning'; + case 'critical': return 'error'; + default: return 'default'; + } + }; + + const getStatusIcon = (status: string) => { + switch (status) { + case 'normal': return ; + case 'low': return ; + case 'critical': return ; + default: return null; + } + }; + + const columns = [ + { + title: 'Product ID', + dataIndex: 'productId', + key: 'productId', + }, + { + title: 'Product Name', + dataIndex: 'productName', + key: 'productName', + }, + { + title: 'SKU', + dataIndex: 'sku', + key: 'sku', + }, + { + title: 'Total Quantity', + dataIndex: 'quantity', + key: 'quantity', + }, + { + title: 'Available', + dataIndex: 'available', + key: 'available', + render: (value: number) => ( + {value} + ), + }, + { + title: 'Reserved', + dataIndex: 'reserved', + key: 'reserved', + }, + { + title: 'Reorder Point', + dataIndex: 'reorderPoint', + key: 'reorderPoint', + }, + { + title: 'Location', + dataIndex: 'location', + key: 'location', + }, + { + title: 'Status', + dataIndex: 'status', + key: 'status', + render: (status: string) => ( + + ), + }, + { + title: 'Last Updated', + dataIndex: 'lastUpdated', + key: 'lastUpdated', + }, + { + title: 'Actions', + key: 'actions', + render: (_: any, record: any) => ( + + + + + + + + ), + }, + ]; + + const rowSelection = { + selectedRowKeys, + onChange: (keys: React.Key[]) => { + setSelectedRowKeys(keys); + }, + }; + + const filteredInventory = mockInventory.filter(item => + item.productName.toLowerCase().includes(searchKeyword.toLowerCase()) || + item.sku.toLowerCase().includes(searchKeyword.toLowerCase()) + ); + + return ( +
+
+ Inventory Management + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + +
+ setSearchKeyword(e.target.value)} + style={{ width: 300 }} + allowClear + /> + + + +
+ +
+ + + setIsDetailModalVisible(false)} + footer={[ + , + ]} + width={800} + > + {selectedItem && ( +
+
+

Basic Information

+
+
+ Product ID: {selectedItem.productId} +
+
+ Product Name: {selectedItem.productName} +
+
+ SKU: {selectedItem.sku} +
+
+ Location: {selectedItem.location} +
+
+ Status: +
+
+ Last Updated: {selectedItem.lastUpdated} +
+
+
+
+

Stock Information

+ +
+ + + + + + + + + + + + + + + +
+ Reorder Point: {selectedItem.reorderPoint} +
+ +
+

Quick Actions

+ + + + +
+ + )} + + + ); +}; + +export default InventoryPage; \ No newline at end of file diff --git a/client/src/pages/OrdersPage.tsx b/client/src/pages/OrdersPage.tsx new file mode 100644 index 0000000..0eb1aa9 --- /dev/null +++ b/client/src/pages/OrdersPage.tsx @@ -0,0 +1,480 @@ +import React, { useState, useEffect } from 'react'; +import { Card, Table, Button, Select, DatePicker, Space, Modal, Tabs, Descriptions, Badge, message, Spin, Input } from 'antd'; +import { EyeOutlined, CheckOutlined, CloseOutlined, DownloadOutlined, UploadOutlined, PlusOutlined } from '@ant-design/icons'; +import { orderApi } from '../services/ApiService'; + +const { Option } = Select; +const { RangePicker } = DatePicker; +const { TabPane } = Tabs; + +const OrdersPage: React.FC = () => { + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const [isDetailModalVisible, setIsDetailModalVisible] = useState(false); + const [isProcessModalVisible, setIsProcessModalVisible] = useState(false); + const [selectedOrder, setSelectedOrder] = useState(null); + const [isProcessing, setIsProcessing] = useState(false); + const [orderStatus, setOrderStatus] = useState(''); + const [orders, setOrders] = useState([]); + const [loading, setLoading] = useState(false); + const [totalOrders, setTotalOrders] = useState(0); + const [pendingOrders, setPendingOrders] = useState(0); + const [shippedOrders, setShippedOrders] = useState(0); + const [deliveredOrders, setDeliveredOrders] = useState(0); + const [refundedOrders, setRefundedOrders] = useState(0); + + // 加载订单数据 + useEffect(() => { + loadOrders(); + }, []); + + const loadOrders = async () => { + setLoading(true); + try { + const response = await orderApi.getOrders(); + setOrders(response.data || []); + calculateStatistics(response.data || []); + } catch (error) { + console.error('Failed to load orders:', error); + message.error('Failed to load orders'); + // 加载失败时使用mock数据 + const mockOrders = [ + { + id: '1001', + orderNo: 'ORD-2026-0001', + customer: 'John Doe', + total: 259.98, + status: 'pending', + platform: 'Amazon', + date: '2026-03-18', + items: [ + { name: 'Wireless Headphones', quantity: 2, price: 129.99 }, + ], + }, + { + id: '1002', + orderNo: 'ORD-2026-0002', + customer: 'Jane Smith', + total: 89.99, + status: 'shipped', + platform: 'eBay', + date: '2026-03-17', + items: [ + { name: 'Bluetooth Speaker', quantity: 1, price: 89.99 }, + ], + }, + { + id: '1003', + orderNo: 'ORD-2026-0003', + customer: 'Bob Johnson', + total: 199.99, + status: 'delivered', + platform: 'Shopee', + date: '2026-03-16', + items: [ + { name: 'Smart Watch', quantity: 1, price: 199.99 }, + ], + }, + { + id: '1004', + orderNo: 'ORD-2026-0004', + customer: 'Alice Williams', + total: 69.99, + status: 'refunded', + platform: 'Amazon', + date: '2026-03-15', + items: [ + { name: 'Fitness Tracker', quantity: 1, price: 69.99 }, + ], + }, + ]; + setOrders(mockOrders); + calculateStatistics(mockOrders); + } finally { + setLoading(false); + } + }; + + const calculateStatistics = (orderList: any[]) => { + if (!orderList || orderList.length === 0) { + setTotalOrders(0); + setPendingOrders(0); + setShippedOrders(0); + setDeliveredOrders(0); + setRefundedOrders(0); + return; + } + + const total = orderList.length; + const pending = orderList.filter(order => order.status === 'pending').length; + const shipped = orderList.filter(order => order.status === 'shipped').length; + const delivered = orderList.filter(order => order.status === 'delivered').length; + const refunded = orderList.filter(order => order.status === 'refunded').length; + + setTotalOrders(total); + setPendingOrders(pending); + setShippedOrders(shipped); + setDeliveredOrders(delivered); + setRefundedOrders(refunded); + }; + + const handleViewDetail = async (record: any) => { + try { + const response = await orderApi.getOrder(record.id); + setSelectedOrder(response.data || record); + setIsDetailModalVisible(true); + } catch (error) { + console.error('Failed to get order detail:', error); + setSelectedOrder(record); + setIsDetailModalVisible(true); + } + }; + + const handleProcessOrder = (record: any) => { + setSelectedOrder(record); + setOrderStatus(record.status); + setIsProcessModalVisible(true); + }; + + const handleRefundOrder = async (record: any) => { + try { + await orderApi.updateStatus(record.id, 'refunded'); + message.success(`Refund process initiated for order ${record.orderNo}`); + // 重新加载订单数据 + loadOrders(); + } catch (error) { + console.error('Failed to refund order:', error); + message.error('Failed to refund order'); + } + }; + + const handleBatchShip = async () => { + if (selectedRowKeys.length === 0) return; + + try { + // 批量发货 + for (const key of selectedRowKeys) { + await orderApi.updateStatus(key.toString(), 'shipped'); + } + message.success('Batch shipping initiated'); + // 重新加载订单数据 + loadOrders(); + } catch (error) { + console.error('Failed to batch ship:', error); + message.error('Failed to batch ship'); + } + }; + + const handleBatchCancel = async () => { + if (selectedRowKeys.length === 0) return; + + try { + // 批量取消 + for (const key of selectedRowKeys) { + await orderApi.updateStatus(key.toString(), 'cancelled'); + } + message.success('Batch cancellation initiated'); + // 重新加载订单数据 + loadOrders(); + } catch (error) { + console.error('Failed to batch cancel:', error); + message.error('Failed to batch cancel'); + } + }; + + const handleBatchExport = async () => { + if (selectedRowKeys.length === 0) return; + + try { + // 调用导出API + await orderApi.getOrders({ export: true, ids: selectedRowKeys }); + message.success('Orders exported'); + } catch (error) { + console.error('Failed to batch export:', error); + message.error('Failed to batch export'); + } + }; + + const handleCreateOrder = () => { + // 这里可以打开创建订单的表单 + message.success('Create order form opened'); + }; + + const handleImportOrders = () => { + // 这里可以打开导入订单的对话框 + message.success('Import orders dialog opened'); + }; + + const handleExportOrders = async () => { + try { + // 调用导出API + await orderApi.getOrders({ export: true }); + message.success('Orders exported'); + } catch (error) { + console.error('Failed to export orders:', error); + message.error('Failed to export orders'); + } + }; + + const getStatusColor = (status: string) => { + switch (status) { + case 'pending': return 'blue'; + case 'shipped': return 'green'; + case 'delivered': return 'green'; + case 'refunded': return 'red'; + case 'cancelled': return 'red'; + default: return 'default'; + } + }; + + const columns = [ + { + title: 'Order No', + dataIndex: 'orderNo', + key: 'orderNo', + }, + { + title: 'Customer', + dataIndex: 'customer', + key: 'customer', + }, + { + title: 'Total', + dataIndex: 'total', + key: 'total', + render: (value: number) => `¥${value}`, + }, + { + title: 'Status', + dataIndex: 'status', + key: 'status', + render: (status: string) => ( + + ), + }, + { + title: 'Platform', + dataIndex: 'platform', + key: 'platform', + }, + { + title: 'Date', + dataIndex: 'date', + key: 'date', + }, + { + title: 'Actions', + key: 'actions', + render: (_: any, record: any) => ( + + + + + + ), + }, + ]; + + const rowSelection = { + selectedRowKeys, + onChange: (keys: React.Key[]) => { + setSelectedRowKeys(keys); + }, + }; + + return ( +
+
+

Orders

+ + + + + +
+ + +
+ + + +
+ +
+ + + + + +
+ +
+ + + +
+
+

Total Orders

+

{totalOrders}

+
+
+

Pending

+

{pendingOrders}

+
+
+

Shipped

+

{shippedOrders}

+
+
+

Delivered

+

{deliveredOrders}

+
+
+

Refunded

+

{refundedOrders}

+
+
+
+ + setIsDetailModalVisible(false)} + footer={[ + , + ]} + width={800} + > + {selectedOrder && ( + + + + {selectedOrder.orderNo} + {selectedOrder.customer} + ¥{selectedOrder.total} + + + + {selectedOrder.platform} + {selectedOrder.date} + +

Items

+
`¥${value}` }, + ]} + dataSource={selectedOrder.items} + rowKey="name" + pagination={false} + /> + + +

Shipping information will be displayed here

+
+ +

Payment information will be displayed here

+
+ + )} + + + setIsProcessModalVisible(false)} + onOk={async () => { + setIsProcessing(true); + + try { + await orderApi.updateStatus(selectedOrder.id, orderStatus); + setIsProcessing(false); + setIsProcessModalVisible(false); + message.success('Order processed successfully'); + // 重新加载订单数据 + loadOrders(); + } catch (error) { + console.error('Failed to process order:', error); + setIsProcessing(false); + message.error('Failed to process order'); + } + }} + > + {isProcessing ? ( +
+
+

Processing order...

+
+ +
+
+
+ ) : ( + <> +
+

Order: {selectedOrder?.orderNo}

+

Customer: {selectedOrder?.customer}

+

Current Status:

+
+
+

Update Status

+ +
+ {orderStatus === 'shipped' && ( +
+

Shipping Information

+ + +
+ )} + + )} +
+ + ); +}; + +export default OrdersPage; \ No newline at end of file diff --git a/client/src/pages/ProductPage.tsx b/client/src/pages/ProductPage.tsx new file mode 100644 index 0000000..3ab85b5 --- /dev/null +++ b/client/src/pages/ProductPage.tsx @@ -0,0 +1,527 @@ +import React, { useState, useEffect } from 'react'; +import { Card, Table, Button, Input, Select, DatePicker, Space, Modal, Form, InputNumber, message, Spin } from 'antd'; +import { EditOutlined, DollarOutlined, BarChartOutlined, RocketOutlined, UploadOutlined, DownloadOutlined, PlusOutlined } from '@ant-design/icons'; +import { Tag } from 'antd'; +import { productApi } from '../services/ApiService'; + +const { Option } = Select; +const { Search } = Input; + +const ProductPage: React.FC = () => { + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const [isEditModalVisible, setIsEditModalVisible] = useState(false); + const [isPriceModalVisible, setIsPriceModalVisible] = useState(false); + const [isAiPricingModalVisible, setIsAiPricingModalVisible] = useState(false); + const [editingProduct, setEditingProduct] = useState(null); + const [form] = Form.useForm(); + const [products, setProducts] = useState([]); + const [loading, setLoading] = useState(false); + const [totalProducts, setTotalProducts] = useState(0); + const [totalCost, setTotalCost] = useState(0); + const [totalRevenue, setTotalRevenue] = useState(0); + const [totalProfit, setTotalProfit] = useState(0); + const [averageRoi, setAverageRoi] = useState(0); + + // 加载商品数据 + useEffect(() => { + loadProducts(); + }, []); + + const loadProducts = async () => { + setLoading(true); + try { + const response = await productApi.getProducts(); + setProducts(response.data || []); + calculateSummary(response.data || []); + } catch (error) { + console.error('Failed to load products:', error); + message.error('Failed to load products'); + // 加载失败时使用mock数据 + const mockProducts = [ + { + id: '1', + name: 'Wireless Headphones', + sku: 'WH-123', + cost: 50, + price: 129.99, + profit: 79.99, + roi: 159.98, + stock: 150, + status: 'active', + category: 'Electronics', + shop: 'Shop 1', + }, + { + id: '2', + name: 'Bluetooth Speaker', + sku: 'BS-456', + cost: 35, + price: 89.99, + profit: 54.99, + roi: 157.11, + stock: 80, + status: 'active', + category: 'Electronics', + shop: 'Shop 1', + }, + { + id: '3', + name: 'Smart Watch', + sku: 'SW-789', + cost: 80, + price: 199.99, + profit: 119.99, + roi: 149.99, + stock: 50, + status: 'active', + category: 'Electronics', + shop: 'Shop 2', + }, + { + id: '4', + name: 'Fitness Tracker', + sku: 'FT-321', + cost: 25, + price: 69.99, + profit: 44.99, + roi: 179.96, + stock: 200, + status: 'inactive', + category: 'Electronics', + shop: 'Shop 2', + }, + ]; + setProducts(mockProducts); + calculateSummary(mockProducts); + } finally { + setLoading(false); + } + }; + + const calculateSummary = (productList: any[]) => { + if (!productList || productList.length === 0) { + setTotalProducts(0); + setTotalCost(0); + setTotalRevenue(0); + setTotalProfit(0); + setAverageRoi(0); + return; + } + + const total = productList.length; + const cost = productList.reduce((sum, product) => sum + product.cost, 0); + const revenue = productList.reduce((sum, product) => sum + product.price, 0); + const profit = productList.reduce((sum, product) => sum + product.profit, 0); + const roi = productList.reduce((sum, product) => sum + product.roi, 0) / total; + + setTotalProducts(total); + setTotalCost(cost); + setTotalRevenue(revenue); + setTotalProfit(profit); + setAverageRoi(roi); + }; + + const handleEdit = (record: any) => { + setEditingProduct(record); + form.setFieldsValue(record); + setIsEditModalVisible(true); + }; + + const handlePriceChange = (record: any) => { + setEditingProduct(record); + form.setFieldsValue({ price: record.price }); + setIsPriceModalVisible(true); + }; + + const [isAiLoading, setIsAiLoading] = useState(false); + const [aiSuggestedPrice, setAiSuggestedPrice] = useState(0); + + const handleAiPricing = async (record: any) => { + setEditingProduct(record); + setIsAiLoading(true); + + try { + // 调用AI定价API + const response = await productApi.getAiPricing(record.id); + setAiSuggestedPrice(response.suggestedPrice || record.cost * (2 + Math.random() * 1)); + } catch (error) { + console.error('Failed to get AI pricing:', error); + // 失败时使用模拟数据 + const suggestedPrice = record.cost * (2 + Math.random() * 1); + setAiSuggestedPrice(suggestedPrice); + } finally { + setIsAiLoading(false); + setIsAiPricingModalVisible(true); + } + }; + + const handleToggleStatus = async (record: any) => { + try { + await productApi.toggleStatus(record.id); + message.success(`${record.name} has been ${record.status === 'active' ? 'deactivated' : 'activated'}`); + // 重新加载商品数据 + loadProducts(); + } catch (error) { + console.error('Failed to toggle status:', error); + message.error('Failed to toggle status'); + } + }; + + const handleBatchPriceChange = async () => { + if (selectedRowKeys.length === 0) return; + + try { + await productApi.batchUpdate(selectedRowKeys.map(key => key.toString()), { action: 'price' }); + message.success('Batch price change initiated'); + // 重新加载商品数据 + loadProducts(); + } catch (error) { + console.error('Failed to batch update price:', error); + message.error('Failed to batch update price'); + } + }; + + const handleBatchActivate = async () => { + if (selectedRowKeys.length === 0) return; + + try { + await productApi.batchUpdate(selectedRowKeys.map(key => key.toString()), { action: 'activate' }); + message.success('Batch activation initiated'); + // 重新加载商品数据 + loadProducts(); + } catch (error) { + console.error('Failed to batch activate:', error); + message.error('Failed to batch activate'); + } + }; + + const handleBatchAnalysis = async () => { + if (selectedRowKeys.length === 0) return; + + try { + await productApi.batchUpdate(selectedRowKeys.map(key => key.toString()), { action: 'analyze' }); + message.success('Batch analysis initiated'); + } catch (error) { + console.error('Failed to batch analyze:', error); + message.error('Failed to batch analyze'); + } + }; + + const handleCreateProduct = () => { + // 这里可以打开创建商品的表单 + message.success('Create product form opened'); + }; + + const handleImportProducts = () => { + // 这里可以打开导入商品的对话框 + message.success('Import products dialog opened'); + }; + + const handleExportProducts = async () => { + try { + // 调用导出API + await productApi.getProducts({ export: true }); + message.success('Products exported'); + } catch (error) { + console.error('Failed to export products:', error); + message.error('Failed to export products'); + } + }; + + const columns = [ + { + title: 'Product Name', + dataIndex: 'name', + key: 'name', + }, + { + title: 'SKU', + dataIndex: 'sku', + key: 'sku', + }, + { + title: 'Cost', + dataIndex: 'cost', + key: 'cost', + render: (value: number) => `¥${value}`, + }, + { + title: 'Price', + dataIndex: 'price', + key: 'price', + render: (value: number) => `¥${value}`, + }, + { + title: 'Profit', + dataIndex: 'profit', + key: 'profit', + render: (value: number) => `¥${value}`, + }, + { + title: 'ROI', + dataIndex: 'roi', + key: 'roi', + render: (value: number) => `${value}%`, + }, + { + title: 'Stock', + dataIndex: 'stock', + key: 'stock', + }, + { + title: 'Status', + dataIndex: 'status', + key: 'status', + render: (status: string) => ( + + {status === 'active' ? 'Active' : 'Inactive'} + + ), + }, + { + title: 'Actions', + key: 'actions', + render: (_: any, record: any) => ( + + + + + + + + ), + }, + ]; + + const rowSelection = { + selectedRowKeys, + onChange: (keys: React.Key[]) => { + setSelectedRowKeys(keys); + }, + }; + + return ( +
+
+

Products

+ + + + + +
+ + +
+ + + + +
+ +
+ + + + + +
+ +
+ + + +
+
+

Total Products

+

{totalProducts}

+
+
+

Total Cost

+

¥{totalCost.toFixed(2)}

+
+
+

Total Revenue

+

¥{totalRevenue.toFixed(2)}

+
+
+

Total Profit

+

¥{totalProfit.toFixed(2)}

+
+
+

Average ROI

+

{averageRoi.toFixed(2)}%

+
+
+
+ + setIsEditModalVisible(false)} + onOk={async () => { + try { + const values = await form.validateFields(); + await productApi.updateProduct(editingProduct.id, values); + setIsEditModalVisible(false); + message.success('Product updated successfully'); + // 重新加载商品数据 + loadProducts(); + } catch (error) { + console.error('Failed to update product:', error); + message.error('Failed to update product'); + } + }} + > +
+ + + + + + + + + + + + + +
+ + setIsPriceModalVisible(false)} + onOk={async () => { + try { + const newPrice = form.getFieldValue('price'); + if (newPrice) { + await productApi.updatePrice(editingProduct.id, newPrice); + setIsPriceModalVisible(false); + message.success('Price updated successfully'); + // 重新加载商品数据 + loadProducts(); + } + } catch (error) { + console.error('Failed to update price:', error); + message.error('Failed to update price'); + } + }} + > +
+ + { + if (value && editingProduct) { + // 实时计算ROI + const newProfit = value - editingProduct.cost; + const newRoi = (newProfit / editingProduct.cost) * 100; + + // 更新ROI显示 + const roiElement = document.getElementById('estimated-roi'); + if (roiElement) { + roiElement.textContent = `${newRoi.toFixed(2)}%`; + roiElement.style.color = newRoi >= 150 ? '#52c41a' : '#faad14'; + } + } + }} + /> + +
+

Current Cost: ¥{editingProduct?.cost}

+

Estimated Profit: + ¥{(form.getFieldValue('price') - editingProduct?.cost).toFixed(2)} +

+

Estimated ROI: + {((form.getFieldValue('price') - editingProduct?.cost) / editingProduct?.cost * 100).toFixed(2)}% +

+
+ +
+ + setIsAiPricingModalVisible(false)} + onOk={async () => { + try { + if (editingProduct && aiSuggestedPrice > 0) { + await productApi.updatePrice(editingProduct.id, aiSuggestedPrice); + setIsAiPricingModalVisible(false); + message.success('AI pricing applied successfully'); + // 重新加载商品数据 + loadProducts(); + } + } catch (error) { + console.error('Failed to apply AI pricing:', error); + message.error('Failed to apply AI pricing'); + } + }} + > + {isAiLoading ? ( +
+
+

AI is calculating the optimal price...

+
+ +
+
+
+ ) : ( +
+

Current Price: ¥{editingProduct?.price}

+

AI Suggested Price: ¥{aiSuggestedPrice.toFixed(2)}

+

Estimated Profit: + ¥{(aiSuggestedPrice - editingProduct?.cost).toFixed(2)} +

+

Estimated ROI: + {((aiSuggestedPrice - editingProduct?.cost) / editingProduct?.cost * 100).toFixed(2)}% +

+
+

AI Pricing Insights:

+
    +
  • Market competitive price: ¥{aiSuggestedPrice.toFixed(2)}
  • +
  • Expected conversion rate: 8.5%
  • +
  • Recommended pricing strategy: Dynamic pricing
  • +
+
+
+ )} +
+ + ); +}; + +export default ProductPage; \ No newline at end of file diff --git a/client/src/pages/SettingsPage.tsx b/client/src/pages/SettingsPage.tsx new file mode 100644 index 0000000..49abdf6 --- /dev/null +++ b/client/src/pages/SettingsPage.tsx @@ -0,0 +1,581 @@ +import React, { useState } from 'react'; +import { Card, Form, Input, Select, Button, Space, Typography, Switch, Tabs, Row, Col, message, Divider, Upload, Avatar } from 'antd'; +import { SaveOutlined, ReloadOutlined, UserOutlined, LockOutlined, BellOutlined, GlobalOutlined, DatabaseOutlined, ApiOutlined, SettingOutlined } from '@ant-design/icons'; + +const { Option } = Select; +const { Title, Text } = Typography; +const { TabPane } = Tabs; +const { TextArea } = Input; + +const SettingsPage: React.FC = () => { + const [activeTab, setActiveTab] = useState('profile'); + const [loading, setLoading] = useState(false); + const [profileForm] = Form.useForm(); + const [securityForm] = Form.useForm(); + const [notificationForm] = Form.useForm(); + const [systemForm] = Form.useForm(); + + const handleSaveProfile = async (values: any) => { + setLoading(true); + setTimeout(() => { + setLoading(false); + message.success('Profile updated successfully'); + }, 1000); + }; + + const handleSaveSecurity = async (values: any) => { + setLoading(true); + setTimeout(() => { + setLoading(false); + message.success('Security settings updated successfully'); + }, 1000); + }; + + const handleSaveNotification = async (values: any) => { + setLoading(true); + setTimeout(() => { + setLoading(false); + message.success('Notification settings updated successfully'); + }, 1000); + }; + + const handleSaveSystem = async (values: any) => { + setLoading(true); + setTimeout(() => { + setLoading(false); + message.success('System settings updated successfully'); + }, 1000); + }; + + const handleResetSettings = () => { + message.success('Settings reset to default'); + }; + + const handleExportSettings = () => { + message.success('Settings exported successfully'); + }; + + const handleImportSettings = () => { + message.success('Settings imported successfully'); + }; + + return ( +
+
+ System Settings + + + + + +
+ + + + +
+
+ } style={{ marginBottom: 16 }} /> + User Profile + Manage your personal information and preferences +
+ +
+ +
+ + } placeholder="Username" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ } style={{ marginBottom: 16 }} /> + Security Settings + Manage your security and authentication preferences +
+ +
+ + } placeholder="Current Password" /> + + + + } placeholder="New Password" /> + + + ({ + validator(_, value) { + if (!value || getFieldValue('newPassword') === value) { + return Promise.resolve(); + } + return Promise.reject(new Error('The two passwords do not match')); + }, + }), + ]} + > + } placeholder="Confirm Password" /> + + + + + + + + + + + + + + + + +
+
+ + +
+
+ } style={{ marginBottom: 16 }} /> + Notification Settings + Manage your notification preferences +
+ +
+ Email Notifications + + + + + + + + + + + + + + + + + + + + + + + + + + + + Push Notifications + + + + + + + + + +
+
+ + +
+
+ } style={{ marginBottom: 16 }} /> + System Settings + Manage system-wide preferences and configurations +
+ +
+ General Settings + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + API Settings + + + + + + + + Data Settings + + + + + + + + + + + + + +
+
+ } style={{ marginBottom: 16 }} /> + Integrations + Manage third-party service integrations +
+ + + +
+
+ Amazon Integration +
+ Connect your Amazon seller account +
+ +
+ +
+
+ eBay Integration +
+ Connect your eBay seller account +
+ +
+ +
+
+ Shopee Integration +
+ Connect your Shopee seller account +
+ +
+
+
+ + + +
+
+ Payment Gateway +
+ Connect payment processing service +
+ +
+ +
+
+ Shipping Service +
+ Connect logistics and shipping service +
+ +
+ +
+
+ Analytics Service +
+ Connect analytics and reporting service +
+ +
+
+
+ + +
+ + + + + + + + + + + + + + +
+
+
+ + + + ); +}; + +export default SettingsPage; \ No newline at end of file diff --git a/client/src/routes/index.tsx b/client/src/routes/index.tsx new file mode 100644 index 0000000..a354b05 --- /dev/null +++ b/client/src/routes/index.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; +import Layout from '../components/Layout'; +import DashboardPage from '../pages/DashboardPage'; +import ProductPage from '../pages/ProductPage'; +import OrdersPage from '../pages/OrdersPage'; +import AdPage from '../pages/AdPage'; +import InventoryPage from '../pages/InventoryPage'; +import B2BPage from '../pages/B2BPage'; +import FinancePage from '../pages/FinancePage'; +import CompliancePage from '../pages/CompliancePage'; +import SettingsPage from '../pages/SettingsPage'; +import IndependentSiteList from '../pages/IndependentSite/List'; + +const AppRoutes: React.FC = () => { + return ( + + + } /> + }> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + + ); +}; + +export default AppRoutes; \ No newline at end of file diff --git a/client/src/services/ApiService.ts b/client/src/services/ApiService.ts new file mode 100644 index 0000000..f33564c --- /dev/null +++ b/client/src/services/ApiService.ts @@ -0,0 +1,83 @@ +import axios from 'axios'; + +// 创建axios实例 +const api = axios.create({ + baseURL: 'http://localhost:3000/api', // 后端API基础URL + timeout: 10000, // 请求超时时间 + headers: { + 'Content-Type': 'application/json', + }, +}); + +// 请求拦截器 +api.interceptors.request.use( + (config) => { + // 可以在这里添加token等认证信息 + return config; + }, + (error) => { + return Promise.reject(error); + } +); + +// 响应拦截器 +api.interceptors.response.use( + (response) => { + return response.data; + }, + (error) => { + // 统一错误处理 + console.error('API Error:', error); + return Promise.reject(error); + } +); + +// 商品相关API +export const productApi = { + // 获取商品列表 + getProducts: (params?: any) => api.get('/products', { params }), + + // 获取商品详情 + getProduct: (id: string) => api.get(`/products/${id}`), + + // 创建商品 + createProduct: (data: any) => api.post('/products', data), + + // 更新商品 + updateProduct: (id: string, data: any) => api.put(`/products/${id}`, data), + + // 修改商品价格 + updatePrice: (id: string, price: number) => api.patch(`/products/${id}/price`, { price }), + + // AI定价 + getAiPricing: (id: string) => api.get(`/products/${id}/ai-pricing`), + + // 上下架商品 + toggleStatus: (id: string) => api.patch(`/products/${id}/status`), + + // 批量操作 + batchUpdate: (ids: string[], data: any) => api.post('/products/batch', { ids, data }), +}; + +// 订单相关API +export const orderApi = { + // 获取订单列表 + getOrders: (params?: any) => api.get('/orders', { params }), + + // 获取订单详情 + getOrder: (id: string) => api.get(`/orders/${id}`), + + // 更新订单状态 + updateStatus: (id: string, status: string) => api.patch(`/orders/${id}/status`, { status }), + + // 处理订单 + processOrder: (id: string, data: any) => api.post(`/orders/${id}/process`, data), +}; + +// Dashboard相关API +export const dashboardApi = { + // 获取Dashboard数据 + getDashboardData: (params?: any) => api.get('/dashboard', { params }), +}; + +export default api; \ No newline at end of file diff --git a/dashboard/.umi/appData.json b/dashboard/.umi/appData.json deleted file mode 100644 index 9e0f61e..0000000 --- a/dashboard/.umi/appData.json +++ /dev/null @@ -1,2025 +0,0 @@ -{ - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "pkg": { - "name": "dashboard", - "version": "1.0.0", - "private": true, - "scripts": { - "dev": "umi dev", - "build": "umi build", - "postinstall": "umi setup", - "setup": "umi setup", - "start": "npm run dev" - }, - "dependencies": { - "@ant-design/icons": "^5.2.6", - "@antv/g6": "^5.0.51", - "@antv/l7": "^2.25.2", - "@antv/l7-react": "^2.4.3", - "antd": "^5.12.2", - "axios": "^1.6.2", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "umi": "^4.0.0" - }, - "devDependencies": { - "@types/react": "^18.2.0", - "@types/react-dom": "^18.2.0", - "typescript": "^5.0.0" - } - }, - "pkgPath": "D:\\trae_projects\\makemd\\makemd\\dashboard\\package.json", - "plugins": { - "./node_modules/@umijs/core/dist/service/servicePlugin": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "preset", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/core/dist/service/servicePlugin.js", - "id": "./node_modules/@umijs/core/dist/service/servicePlugin", - "key": "servicePlugin", - "config": {}, - "time": { - "hooks": {}, - "register": 18 - }, - "enableBy": "register" - }, - "@umijs/preset-umi": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "preset", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/index.js", - "id": "@umijs/preset-umi", - "key": "umi", - "config": {}, - "time": { - "hooks": {}, - "register": 81 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/registerMethods": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/registerMethods.js", - "id": "./node_modules/@umijs/preset-umi/dist/registerMethods", - "key": "registerMethods", - "config": {}, - "time": { - "hooks": { - "onStart": [ - 4 - ] - }, - "register": 75 - }, - "enableBy": "register" - }, - "@umijs/did-you-know": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/did-you-know/dist/plugin.js", - "id": "@umijs/did-you-know", - "key": "umijsDidYouKnow", - "config": {}, - "time": { - "hooks": { - "onStart": [ - 10 - ] - }, - "register": 150 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/404/404": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/404/404.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/404/404", - "key": "404", - "config": {}, - "time": { - "hooks": { - "modifyRoutes": [ - 0 - ] - }, - "register": 23 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/aiDev/aiDev": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/aiDev/aiDev.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/aiDev/aiDev", - "key": "aiDev", - "config": {}, - "time": { - "hooks": {}, - "register": 29 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/appData/appData": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/appData/appData.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/appData/appData", - "key": "appData", - "config": {}, - "time": { - "hooks": { - "modifyAppData": [ - 76 - ] - }, - "register": 257 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/appData/umiInfo": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/appData/umiInfo.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/appData/umiInfo", - "key": "umiInfo", - "config": {}, - "time": { - "hooks": {}, - "register": 20 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/check/check": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/check/check.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/check/check", - "key": "check", - "config": {}, - "time": { - "hooks": { - "onCheckConfig": [ - 0 - ], - "onCheck": [ - 1 - ] - }, - "register": 25 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/check/babel722": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/check/babel722.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/check/babel722", - "key": "babel722", - "config": {}, - "time": { - "hooks": { - "onCheck": [ - 0 - ] - }, - "register": 24 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/codeSplitting/codeSplitting": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/codeSplitting/codeSplitting.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/codeSplitting/codeSplitting", - "key": "codeSplitting", - "config": {}, - "time": { - "hooks": {}, - "register": 29 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/configPlugins/configPlugins": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/configPlugins/configPlugins.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/configPlugins/configPlugins", - "key": "configPlugins", - "config": {}, - "time": { - "hooks": { - "modifyConfig": [ - 0 - ] - }, - "register": 231 - }, - "enableBy": "register" - }, - "virtual: config-title": { - "id": "virtual: config-title", - "key": "title", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-styles": { - "id": "virtual: config-styles", - "key": "styles", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-scripts": { - "id": "virtual: config-scripts", - "key": "scripts", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-routes": { - "id": "virtual: config-routes", - "key": "routes", - "config": { - "onChange": "regenerateTmpFiles" - }, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-routeLoader": { - "id": "virtual: config-routeLoader", - "key": "routeLoader", - "config": { - "default": { - "moduleType": "esm" - } - }, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-reactRouter5Compat": { - "id": "virtual: config-reactRouter5Compat", - "key": "reactRouter5Compat", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-presets": { - "id": "virtual: config-presets", - "key": "presets", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-plugins": { - "id": "virtual: config-plugins", - "key": "plugins", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-npmClient": { - "id": "virtual: config-npmClient", - "key": "npmClient", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-mountElementId": { - "id": "virtual: config-mountElementId", - "key": "mountElementId", - "config": { - "default": "root" - }, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-metas": { - "id": "virtual: config-metas", - "key": "metas", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-links": { - "id": "virtual: config-links", - "key": "links", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-historyWithQuery": { - "id": "virtual: config-historyWithQuery", - "key": "historyWithQuery", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-history": { - "id": "virtual: config-history", - "key": "history", - "config": { - "default": { - "type": "browser" - } - }, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-headScripts": { - "id": "virtual: config-headScripts", - "key": "headScripts", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-esbuildMinifyIIFE": { - "id": "virtual: config-esbuildMinifyIIFE", - "key": "esbuildMinifyIIFE", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-conventionRoutes": { - "id": "virtual: config-conventionRoutes", - "key": "conventionRoutes", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-conventionLayout": { - "id": "virtual: config-conventionLayout", - "key": "conventionLayout", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-base": { - "id": "virtual: config-base", - "key": "base", - "config": { - "default": "/" - }, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-analyze": { - "id": "virtual: config-analyze", - "key": "analyze", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-writeToDisk": { - "id": "virtual: config-writeToDisk", - "key": "writeToDisk", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-transformRuntime": { - "id": "virtual: config-transformRuntime", - "key": "transformRuntime", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-theme": { - "id": "virtual: config-theme", - "key": "theme", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-targets": { - "id": "virtual: config-targets", - "key": "targets", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-svgr": { - "id": "virtual: config-svgr", - "key": "svgr", - "config": { - "default": {} - }, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-svgo": { - "id": "virtual: config-svgo", - "key": "svgo", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-stylusLoader": { - "id": "virtual: config-stylusLoader", - "key": "stylusLoader", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-styleLoader": { - "id": "virtual: config-styleLoader", - "key": "styleLoader", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-srcTranspilerOptions": { - "id": "virtual: config-srcTranspilerOptions", - "key": "srcTranspilerOptions", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-srcTranspiler": { - "id": "virtual: config-srcTranspiler", - "key": "srcTranspiler", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-sassLoader": { - "id": "virtual: config-sassLoader", - "key": "sassLoader", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-runtimePublicPath": { - "id": "virtual: config-runtimePublicPath", - "key": "runtimePublicPath", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-purgeCSS": { - "id": "virtual: config-purgeCSS", - "key": "purgeCSS", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-publicPath": { - "id": "virtual: config-publicPath", - "key": "publicPath", - "config": { - "default": "/" - }, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-proxy": { - "id": "virtual: config-proxy", - "key": "proxy", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-postcssLoader": { - "id": "virtual: config-postcssLoader", - "key": "postcssLoader", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-outputPath": { - "id": "virtual: config-outputPath", - "key": "outputPath", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-normalCSSLoaderModules": { - "id": "virtual: config-normalCSSLoaderModules", - "key": "normalCSSLoaderModules", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-mfsu": { - "id": "virtual: config-mfsu", - "key": "mfsu", - "config": { - "default": { - "strategy": "eager" - } - }, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-mdx": { - "id": "virtual: config-mdx", - "key": "mdx", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-manifest": { - "id": "virtual: config-manifest", - "key": "manifest", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-lessLoader": { - "id": "virtual: config-lessLoader", - "key": "lessLoader", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-jsMinifierOptions": { - "id": "virtual: config-jsMinifierOptions", - "key": "jsMinifierOptions", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-jsMinifier": { - "id": "virtual: config-jsMinifier", - "key": "jsMinifier", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-inlineLimit": { - "id": "virtual: config-inlineLimit", - "key": "inlineLimit", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-ignoreMomentLocale": { - "id": "virtual: config-ignoreMomentLocale", - "key": "ignoreMomentLocale", - "config": { - "default": true - }, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-https": { - "id": "virtual: config-https", - "key": "https", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-hash": { - "id": "virtual: config-hash", - "key": "hash", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-forkTSChecker": { - "id": "virtual: config-forkTSChecker", - "key": "forkTSChecker", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-fastRefresh": { - "id": "virtual: config-fastRefresh", - "key": "fastRefresh", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-extraPostCSSPlugins": { - "id": "virtual: config-extraPostCSSPlugins", - "key": "extraPostCSSPlugins", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-extraBabelPresets": { - "id": "virtual: config-extraBabelPresets", - "key": "extraBabelPresets", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-extraBabelPlugins": { - "id": "virtual: config-extraBabelPlugins", - "key": "extraBabelPlugins", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-extraBabelIncludes": { - "id": "virtual: config-extraBabelIncludes", - "key": "extraBabelIncludes", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-externals": { - "id": "virtual: config-externals", - "key": "externals", - "config": { - "default": {} - }, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-esm": { - "id": "virtual: config-esm", - "key": "esm", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-devtool": { - "id": "virtual: config-devtool", - "key": "devtool", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-depTranspiler": { - "id": "virtual: config-depTranspiler", - "key": "depTranspiler", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-define": { - "id": "virtual: config-define", - "key": "define", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-deadCode": { - "id": "virtual: config-deadCode", - "key": "deadCode", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-cssPublicPath": { - "id": "virtual: config-cssPublicPath", - "key": "cssPublicPath", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-cssMinifierOptions": { - "id": "virtual: config-cssMinifierOptions", - "key": "cssMinifierOptions", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-cssMinifier": { - "id": "virtual: config-cssMinifier", - "key": "cssMinifier", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-cssLoaderModules": { - "id": "virtual: config-cssLoaderModules", - "key": "cssLoaderModules", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-cssLoader": { - "id": "virtual: config-cssLoader", - "key": "cssLoader", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-copy": { - "id": "virtual: config-copy", - "key": "copy", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-checkDepCssModules": { - "id": "virtual: config-checkDepCssModules", - "key": "checkDepCssModules", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-chainWebpack": { - "id": "virtual: config-chainWebpack", - "key": "chainWebpack", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-cacheDirectoryPath": { - "id": "virtual: config-cacheDirectoryPath", - "key": "cacheDirectoryPath", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-babelLoaderCustomize": { - "id": "virtual: config-babelLoaderCustomize", - "key": "babelLoaderCustomize", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-autoprefixer": { - "id": "virtual: config-autoprefixer", - "key": "autoprefixer", - "config": {}, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-autoCSSModules": { - "id": "virtual: config-autoCSSModules", - "key": "autoCSSModules", - "config": { - "default": true - }, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "virtual: config-alias": { - "id": "virtual: config-alias", - "key": "alias", - "config": { - "default": { - "umi": "@@/exports", - "react": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react", - "react-dom": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-dom", - "react-router": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-router", - "react-router-dom": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-router-dom" - } - }, - "type": "plugin", - "enableBy": "register", - "time": { - "hooks": {}, - "register": 0 - } - }, - "./node_modules/@umijs/preset-umi/dist/features/crossorigin/crossorigin": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/crossorigin/crossorigin.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/crossorigin/crossorigin", - "key": "crossorigin", - "config": {}, - "time": { - "hooks": {}, - "register": 23 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/depsOnDemand/depsOnDemand": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/depsOnDemand/depsOnDemand.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/depsOnDemand/depsOnDemand", - "key": "depsOnDemand", - "config": {}, - "time": { - "hooks": { - "onStart": [ - 1 - ] - }, - "register": 25 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/devTool/devTool": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/devTool/devTool.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/devTool/devTool", - "key": "devTool", - "config": {}, - "time": { - "hooks": {}, - "register": 26 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/esbuildHelperChecker/esbuildHelperChecker": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/esbuildHelperChecker/esbuildHelperChecker.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/esbuildHelperChecker/esbuildHelperChecker", - "key": "esbuildHelperChecker", - "config": {}, - "time": { - "hooks": {}, - "register": 182 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/esmi/esmi": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/esmi/esmi.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/esmi/esmi", - "key": "esmi", - "config": {}, - "time": { - "hooks": {}, - "register": 1620 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/exportStatic/exportStatic": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/exportStatic/exportStatic.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/exportStatic/exportStatic", - "key": "exportStatic", - "config": {}, - "time": { - "hooks": {}, - "register": 389 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/favicons/favicons": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/favicons/favicons.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/favicons/favicons", - "key": "favicons", - "config": {}, - "time": { - "hooks": { - "modifyAppData": [ - 0 - ] - }, - "register": 27 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/helmet/helmet": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/helmet/helmet.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/helmet/helmet", - "key": "helmet", - "config": {}, - "time": { - "hooks": {}, - "register": 28 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/icons/icons": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/icons/icons.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/icons/icons", - "key": "icons", - "config": {}, - "time": { - "hooks": {}, - "register": 36 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/mock/mock": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/mock/mock.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/mock/mock", - "key": "mock", - "config": {}, - "time": { - "hooks": {}, - "register": 349 - } - }, - "./node_modules/@umijs/preset-umi/dist/features/mpa/mpa": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/mpa/mpa.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/mpa/mpa", - "key": "mpa", - "config": {}, - "time": { - "hooks": {}, - "register": 38 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/okam/okam": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/okam/okam.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/okam/okam", - "key": "okam", - "config": {}, - "time": { - "hooks": {}, - "register": 23 - } - }, - "./node_modules/@umijs/preset-umi/dist/features/overrides/overrides": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/overrides/overrides.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/overrides/overrides", - "key": "overrides", - "config": {}, - "time": { - "hooks": {}, - "register": 0 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/phantomDependency/phantomDependency": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/phantomDependency/phantomDependency.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/phantomDependency/phantomDependency", - "key": "phantomDependency", - "config": {}, - "time": { - "hooks": {}, - "register": 24 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/polyfill/polyfill": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/polyfill/polyfill.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/polyfill/polyfill", - "key": "polyfill", - "config": {}, - "time": { - "hooks": { - "modifyConfig": [ - 9 - ] - }, - "register": 57 - } - }, - "./node_modules/@umijs/preset-umi/dist/features/polyfill/publicPathPolyfill": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/polyfill/publicPathPolyfill.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/polyfill/publicPathPolyfill", - "key": "publicPathPolyfill", - "config": {}, - "time": { - "hooks": {}, - "register": 30 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/prepare/prepare": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/prepare/prepare.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/prepare/prepare", - "key": "prepare", - "config": {}, - "time": { - "hooks": {}, - "register": 48 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/routePrefetch/routePrefetch": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/routePrefetch/routePrefetch.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/routePrefetch/routePrefetch", - "key": "routePrefetch", - "config": {}, - "time": { - "hooks": {}, - "register": 24 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/stagewise/stagewise": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/stagewise/stagewise.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/stagewise/stagewise", - "key": "stagewise", - "config": {}, - "time": { - "hooks": {}, - "register": 27 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/terminal/terminal": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/terminal/terminal.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/terminal/terminal", - "key": "terminal", - "config": {}, - "time": { - "hooks": {}, - "register": 30 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/tmpFiles/tmpFiles": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/tmpFiles/tmpFiles.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/tmpFiles/tmpFiles", - "key": "tmpFiles", - "config": {}, - "time": { - "hooks": {}, - "register": 182 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/clientLoader/clientLoader": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/clientLoader/clientLoader.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/clientLoader/clientLoader", - "key": "clientLoader", - "config": {}, - "time": { - "hooks": {}, - "register": 41 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/routeProps/routeProps": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/routeProps/routeProps.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/routeProps/routeProps", - "key": "routeProps", - "config": {}, - "time": { - "hooks": {}, - "register": 18 - } - }, - "./node_modules/@umijs/preset-umi/dist/features/ssr/ssr": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/ssr/ssr.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/ssr/ssr", - "key": "ssr", - "config": {}, - "time": { - "hooks": {}, - "register": 45 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/tmpFiles/configTypes": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/tmpFiles/configTypes.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/tmpFiles/configTypes", - "key": "configTypes", - "config": {}, - "time": { - "hooks": {}, - "register": 97 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/transform/transform": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/transform/transform.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/transform/transform", - "key": "transform", - "config": {}, - "time": { - "hooks": {}, - "register": 96 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/lowImport/lowImport": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/lowImport/lowImport.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/lowImport/lowImport", - "key": "lowImport", - "config": {}, - "time": { - "hooks": {}, - "register": 90 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/vite/vite": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/vite/vite.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/vite/vite", - "key": "vite", - "config": {}, - "time": { - "hooks": {}, - "register": 30 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/apiRoute/apiRoute": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/apiRoute/apiRoute.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/apiRoute/apiRoute", - "key": "apiRoute", - "config": {}, - "time": { - "hooks": {}, - "register": 240 - } - }, - "./node_modules/@umijs/preset-umi/dist/features/monorepo/redirect": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/monorepo/redirect.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/monorepo/redirect", - "key": "monorepoRedirect", - "config": {}, - "time": { - "hooks": {}, - "register": 671 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/test/test": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/test/test.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/test/test", - "key": "test", - "config": {}, - "time": { - "hooks": {}, - "register": 28 - } - }, - "./node_modules/@umijs/preset-umi/dist/features/clickToComponent/clickToComponent": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/clickToComponent/clickToComponent.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/clickToComponent/clickToComponent", - "key": "clickToComponent", - "config": {}, - "time": { - "hooks": {}, - "register": 25 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/legacy/legacy": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/legacy/legacy.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/legacy/legacy", - "key": "legacy", - "config": {}, - "time": { - "hooks": {}, - "register": 28 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/classPropertiesLoose/classPropertiesLoose": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/classPropertiesLoose/classPropertiesLoose.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/classPropertiesLoose/classPropertiesLoose", - "key": "classPropertiesLoose", - "config": {}, - "time": { - "hooks": {}, - "register": 21 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/webpack/webpack": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/webpack/webpack.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/webpack/webpack", - "key": "preset-umi:webpack", - "config": {}, - "time": { - "hooks": {}, - "register": 50 - } - }, - "./node_modules/@umijs/preset-umi/dist/features/swc/swc": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/swc/swc.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/swc/swc", - "key": "swc", - "config": {}, - "time": { - "hooks": { - "addOnDemandDeps": [ - 0 - ] - }, - "register": 21 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/features/ui/ui": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/ui/ui.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/ui/ui", - "key": "ui", - "config": {}, - "time": { - "hooks": {}, - "register": 84 - } - }, - "./node_modules/@umijs/preset-umi/dist/features/mako/mako": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/mako/mako.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/mako/mako", - "key": "mako", - "config": {}, - "time": { - "hooks": {}, - "register": 26 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/utoopack/utoopack": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/utoopack/utoopack.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/utoopack/utoopack", - "key": "utoopack", - "config": {}, - "time": { - "hooks": {}, - "register": 27 - } - }, - "./node_modules/@umijs/preset-umi/dist/features/hmrGuardian/hmrGuardian": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/hmrGuardian/hmrGuardian.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/hmrGuardian/hmrGuardian", - "key": "hmrGuardian", - "config": {}, - "time": { - "hooks": {}, - "register": 50 - } - }, - "./node_modules/@umijs/preset-umi/dist/features/routePreloadOnLoad/routePreloadOnLoad": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/routePreloadOnLoad/routePreloadOnLoad.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/routePreloadOnLoad/routePreloadOnLoad", - "key": "routePreloadOnLoad", - "config": {}, - "time": { - "hooks": {}, - "register": 99 - } - }, - "./node_modules/@umijs/preset-umi/dist/features/forget/forget": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/forget/forget.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/forget/forget", - "key": "forget", - "config": {}, - "time": { - "hooks": {}, - "register": 29 - }, - "enableBy": "config" - }, - "./node_modules/@umijs/preset-umi/dist/features/bundler/bundler": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/features/bundler/bundler.js", - "id": "./node_modules/@umijs/preset-umi/dist/features/bundler/bundler", - "key": "preset-umi:bundler", - "config": {}, - "time": { - "hooks": {}, - "register": 35 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/build": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/build.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/build", - "key": "build", - "config": {}, - "time": { - "hooks": {}, - "register": 136 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/config/config": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/config/config.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/config/config", - "key": "config", - "config": {}, - "time": { - "hooks": {}, - "register": 460 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/dev/dev": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/dev/dev.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/dev/dev", - "key": "dev", - "config": {}, - "time": { - "hooks": {}, - "register": 1699 - } - }, - "./node_modules/@umijs/preset-umi/dist/commands/help": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/help.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/help", - "key": "help", - "config": {}, - "time": { - "hooks": {}, - "register": 23 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/lint": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/lint.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/lint", - "key": "lint", - "config": {}, - "time": { - "hooks": {}, - "register": 24 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/setup": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/setup.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/setup", - "key": "setup", - "config": {}, - "time": { - "hooks": {}, - "register": 21 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/deadcode": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/deadcode.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/deadcode", - "key": "deadcode", - "config": {}, - "time": { - "hooks": {}, - "register": 28 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/version": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/version.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/version", - "key": "version", - "config": {}, - "time": { - "hooks": {}, - "register": 25 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/generators/page": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/page.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/generators/page", - "key": "generator:page", - "config": {}, - "time": { - "hooks": {}, - "register": 68 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/generators/prettier": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/prettier.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/generators/prettier", - "key": "generator:prettier", - "config": {}, - "time": { - "hooks": {}, - "register": 21 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/generators/tsconfig": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/tsconfig.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/generators/tsconfig", - "key": "generator:tsconfig", - "config": {}, - "time": { - "hooks": {}, - "register": 21 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/generators/jest": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/jest.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/generators/jest", - "key": "generator:jest", - "config": {}, - "time": { - "hooks": {}, - "register": 23 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/generators/tailwindcss": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/tailwindcss.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/generators/tailwindcss", - "key": "generator:tailwindcss", - "config": {}, - "time": { - "hooks": {}, - "register": 20 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/generators/dva": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/dva.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/generators/dva", - "key": "generator:dva", - "config": {}, - "time": { - "hooks": {}, - "register": 21 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/generators/component": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/component.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/generators/component", - "key": "generator:component", - "config": {}, - "time": { - "hooks": {}, - "register": 24 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/generators/mock": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/mock.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/generators/mock", - "key": "generator:mock", - "config": {}, - "time": { - "hooks": {}, - "register": 27 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/generators/cypress": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/cypress.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/generators/cypress", - "key": "generator:cypress", - "config": {}, - "time": { - "hooks": {}, - "register": 29 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/generators/api": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/api.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/generators/api", - "key": "generator:api", - "config": {}, - "time": { - "hooks": {}, - "register": 21 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/generators/precommit": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/generators/precommit.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/generators/precommit", - "key": "generator:precommit", - "config": {}, - "time": { - "hooks": {}, - "register": 21 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/plugin": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/plugin.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/plugin", - "key": "command:plugin", - "config": {}, - "time": { - "hooks": {}, - "register": 24 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/verify-commit": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/verify-commit.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/verify-commit", - "key": "verifyCommit", - "config": {}, - "time": { - "hooks": {}, - "register": 29 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/preview": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/preview.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/preview", - "key": "preview", - "config": {}, - "time": { - "hooks": {}, - "register": 79 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/preset-umi/dist/commands/mfsu/mfsu": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/preset-umi/dist/commands/mfsu/mfsu.js", - "id": "./node_modules/@umijs/preset-umi/dist/commands/mfsu/mfsu", - "key": "mfsu-cli", - "config": {}, - "time": { - "hooks": {}, - "register": 26 - }, - "enableBy": "register" - }, - "@umijs/plugin-run": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/plugin-run/dist/index.js", - "id": "@umijs/plugin-run", - "key": "run", - "config": {}, - "time": { - "hooks": {}, - "register": 68 - }, - "enableBy": "register" - }, - "./node_modules/@umijs/core/dist/service/generatePlugin": { - "cwd": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "type": "plugin", - "path": "D:/trae_projects/makemd/makemd/dashboard/node_modules/@umijs/core/dist/service/generatePlugin.js", - "id": "./node_modules/@umijs/core/dist/service/generatePlugin", - "key": "generatePlugin", - "config": {}, - "time": { - "hooks": {}, - "register": 25 - }, - "enableBy": "register" - } - }, - "presets": [], - "name": "setup", - "args": { - "_": [] - }, - "userConfig": {}, - "mainConfigFile": null, - "config": { - "routeLoader": { - "moduleType": "esm" - }, - "mountElementId": "root", - "history": { - "type": "browser" - }, - "base": "/", - "svgr": {}, - "publicPath": "/", - "mfsu": { - "strategy": "eager" - }, - "ignoreMomentLocale": true, - "externals": {}, - "autoCSSModules": true, - "alias": { - "umi": "@@/exports", - "react": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react", - "react-dom": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-dom", - "react-router": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-router", - "react-router-dom": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-router-dom", - "@": "D:\\trae_projects\\makemd\\makemd\\dashboard", - "@@": "D:/trae_projects/makemd/makemd/dashboard/.umi", - "regenerator-runtime": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\regenerator-runtime" - }, - "targets": { - "chrome": 80 - } - }, - "routes": {}, - "apiRoutes": {}, - "hasSrcDir": false, - "npmClient": "cnpm", - "umi": { - "version": "4.6.31", - "name": "Umi", - "importSource": "umi", - "cliName": "umi" - }, - "bundleStatus": { - "done": false - }, - "mfsuBundleStatus": { - "done": false - }, - "react": { - "version": "18.3.1", - "path": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react" - }, - "react-dom": { - "version": "18.3.1", - "path": "D:\\trae_projects\\makemd\\makemd\\dashboard\\node_modules\\react-dom" - }, - "appJS": null, - "locale": "zh-CN", - "globalCSS": [], - "globalJS": [], - "overridesCSS": [], - "bundler": "webpack", - "git": { - "originUrl": "https://github.com/Ansonfishing/makemd.git" - }, - "framework": "react", - "typescript": { - "tsVersion": "5.9.3", - "tslibVersion": "2.8.1" - }, - "faviconFiles": [] -} diff --git a/dashboard/.umi/core/EmptyRoute.tsx b/dashboard/.umi/core/EmptyRoute.tsx deleted file mode 100644 index bee45a6..0000000 --- a/dashboard/.umi/core/EmptyRoute.tsx +++ /dev/null @@ -1,9 +0,0 @@ -// @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 ; -} diff --git a/dashboard/.umi/core/defineApp.ts b/dashboard/.umi/core/defineApp.ts deleted file mode 100644 index 063eb08..0000000 --- a/dashboard/.umi/core/defineApp.ts +++ /dev/null @@ -1,16 +0,0 @@ -// @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; -} diff --git a/dashboard/.umi/core/helmet.ts b/dashboard/.umi/core/helmet.ts deleted file mode 100644 index 159315c..0000000 --- a/dashboard/.umi/core/helmet.ts +++ /dev/null @@ -1,10 +0,0 @@ -// @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); -} diff --git a/dashboard/.umi/core/helmetContext.ts b/dashboard/.umi/core/helmetContext.ts deleted file mode 100644 index 2faa971..0000000 --- a/dashboard/.umi/core/helmetContext.ts +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-nocheck -// This file is generated by Umi automatically -// DO NOT CHANGE IT MANUALLY! -export const context = {}; diff --git a/dashboard/.umi/core/history.ts b/dashboard/.umi/core/history.ts deleted file mode 100644 index 7ac9d0e..0000000 --- a/dashboard/.umi/core/history.ts +++ /dev/null @@ -1,72 +0,0 @@ -// @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 }; diff --git a/dashboard/.umi/core/historyIntelli.ts b/dashboard/.umi/core/historyIntelli.ts deleted file mode 100644 index aa7aeda..0000000 --- a/dashboard/.umi/core/historyIntelli.ts +++ /dev/null @@ -1,132 +0,0 @@ -// @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>['routes'] -type AllRoute = Routes[keyof Routes] -type IsRoot = 'parentId' extends keyof T ? false : true - -// show `/` in not `layout / wrapper` only -type GetAllRouteWithoutLayout = Item extends any - ? 'isWrapper' extends keyof Item - ? never - : 'isLayout' extends keyof Item - ? never - : Item - : never -type AllRouteWithoutLayout = GetAllRouteWithoutLayout -type IndexRoutePathname = '/' extends AllRouteWithoutLayout['path'] - ? '/' - : never - -type GetChildrens = T extends any - ? IsRoot extends true - ? never - : T - : never -type Childrens = GetChildrens -type Root = Exclude -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 -> = IsNever extends true - ? '' - : Item extends AllRoute - ? { - [Key in Item['path'] as TrimSlash]: UnionMerge< - RouteObject - > - } - : never - -type GetRootRouteObject = Item extends Root - ? { - [K in Item['path'] as TrimSlash]: UnionMerge> - } - : never -type MergedResult = UnionMerge> - -// --- patch history types --- - -type HistoryTo = Parameters['0'] -type HistoryPath = Exclude - -type UmiPathname = Path | (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 `/${infer R}` - ? TrimLeftSlash - : T -type TrimRightSlash = T extends `${infer R}/` - ? TrimRightSlash - : T -type TrimSlash = TrimLeftSlash> - -type IsNever = [T] extends [never] ? true : false -type IsEqual = (() => G extends A ? 1 : 2) extends () => G extends B - ? 1 - : 2 - ? true - : false - -type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ( - k: infer I -) => void - ? I - : never -type UnionMerge = UnionToIntersection extends infer O - ? { [K in keyof O]: O[K] } - : never - -type ExcludeEmptyKey = IsEqual extends true ? never : T - -type PathConcat< - TKey extends string, - TValue, - N = TrimSlash -> = TValue extends string - ? ExcludeEmptyKey - : - | ExcludeEmptyKey - | `${N & string}${IsNever> extends true - ? '' - : '/'}${UnionPath}` - -type UnionPath = { - [K in keyof T]-?: PathConcat -}[keyof T] - -type MakeSureLeftSlash = T extends any - ? `/${TrimRightSlash}` - : never - -// exclude `/*`, because it always at the top of the IDE tip list -type Path> = Exclude, '/*'> | IndexRoutePathname diff --git a/dashboard/.umi/core/plugin.ts b/dashboard/.umi/core/plugin.ts deleted file mode 100644 index 1db8c02..0000000 --- a/dashboard/.umi/core/plugin.ts +++ /dev/null @@ -1,40 +0,0 @@ -// @ts-nocheck -// This file is generated by Umi automatically -// DO NOT CHANGE IT MANUALLY! -import * as Plugin_0 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: Plugin_0, - 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; -} diff --git a/dashboard/.umi/core/pluginConfig.ts b/dashboard/.umi/core/pluginConfig.ts deleted file mode 100644 index 1c00a18..0000000 --- a/dashboard/.umi/core/pluginConfig.ts +++ /dev/null @@ -1,324 +0,0 @@ -// @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; - scripts: Array; - routes: Array<{ - component?: (string | undefined); - layout?: (false | undefined); - path?: (string | undefined); - redirect?: (string | undefined); - routes?: IConfigTypes['routes']; - wrappers?: (Array | undefined); -} | { [x: string]: any }>; - routeLoader: { - moduleType: "esm" | "cjs"; -}; - reactRouter5Compat: boolean | { - -}; - presets: Array; - plugins: Array; - 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; - esbuildMinifyIIFE: boolean; - conventionRoutes: { - base?: (string | undefined); - exclude?: (Array | 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; - postcssLoader: { [x: string]: any }; - outputPath: string; - normalCSSLoaderModules: { [x: string]: any }; - mfsu: { - cacheDirectory?: (string | undefined); - chainWebpack?: (((...args: any[]) => unknown) | undefined); - esbuild?: (boolean | undefined); - exclude?: (Array | undefined); - include?: (Array | undefined); - mfName?: (string | undefined); - remoteAliases?: (Array | 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 | undefined); - http2?: (boolean | undefined); - key?: (string | undefined); -}; - hash: boolean; - forkTSChecker: { [x: string]: any }; - fastRefresh: boolean; - extraPostCSSPlugins: Array; - extraBabelPresets: Array>; - extraBabelPlugins: Array>; - extraBabelIncludes: Array; - 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 | undefined); - failOnHint?: (boolean | undefined); - patterns?: (Array | 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 | undefined); -}; - esmi: { - cdnOrigin: string; - shimUrl?: (string | undefined); -}; - exportStatic: { - extraRoutePaths?: (((...args: any[]) => unknown) | Array | undefined); - ignorePreRenderError?: (boolean | undefined); -}; - favicons: Array; - helmet: boolean; - icons: { - autoInstall?: ({ - -} | undefined); - defaultComponentConfig?: ({ - -} | undefined); - alias?: ({ - -} | undefined); - include?: (Array | undefined); -}; - mock: { - exclude?: (Array | undefined); - include?: (Array | undefined); -}; - mpa: { - template?: (string | undefined); - layout?: (string | undefined); - getConfigFromEntryFile?: (boolean | undefined); - entry?: ({ - -} | undefined); -}; - phantomDependency: { - exclude?: (Array | undefined); -}; - polyfill: { - imports?: (Array | 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 | undefined); - css?: (string | undefined); -}; - vite: { - -}; - apiRoute: { - platform?: (string | undefined); -}; - monorepoRedirect: boolean | { - srcDir?: (Array | undefined); - exclude?: (Array | 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 | undefined); - propWhiteList?: (Array | undefined); - selectorBlackList?: (Array | undefined); - selectorWhiteList?: (Array | undefined); - selectorDoubleList?: (Array | undefined); -} | undefined); - experimental?: ({ - webpackSyntaxValidate?: (Array | undefined); -} | undefined); - flexBugs?: (boolean | undefined); - optimization?: ({ - skipModules?: (boolean | undefined); -} | undefined); -}; - utoopack: { - -}; - hmrGuardian: boolean; - forget: { - ReactCompilerConfig?: ({ - -} | undefined); -}; - verifyCommit: { - scope?: (Array | undefined); - allowEmoji?: (boolean | undefined); -}; - run: { - globals?: (Array | undefined); -}; -}; - -type PrettifyWithCloseable = { - [K in keyof T]: T[K] | false; -} & {}; - -export type IConfigFromPlugins = PrettifyWithCloseable< - IConfigFromPluginsJoi & Partial ->; diff --git a/dashboard/.umi/core/pluginConfigJoi.d.ts b/dashboard/.umi/core/pluginConfigJoi.d.ts deleted file mode 100644 index 7b16aec..0000000 --- a/dashboard/.umi/core/pluginConfigJoi.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -// This file is generated by Umi automatically -// DO NOT CHANGE IT MANUALLY! -// Created by Umi Plugin - -export interface IConfigFromPluginsJoi { -stagewise?: unknown -} diff --git a/dashboard/.umi/core/polyfill.ts b/dashboard/.umi/core/polyfill.ts deleted file mode 100644 index 14c870d..0000000 --- a/dashboard/.umi/core/polyfill.ts +++ /dev/null @@ -1,220 +0,0 @@ -// @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 {}; diff --git a/dashboard/.umi/core/route.tsx b/dashboard/.umi/core/route.tsx deleted file mode 100644 index 7ef3044..0000000 --- a/dashboard/.umi/core/route.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// @ts-nocheck -// This file is generated by Umi automatically -// DO NOT CHANGE IT MANUALLY! -import routeProps from './routeProps'; - -if (process.env.NODE_ENV === 'development') { - Object.entries(routeProps).forEach(([key, value]) => { - const internalProps = ['path', 'id', 'parentId', 'isLayout', 'isWrapper', 'layout', 'clientLoader']; - Object.keys(value).forEach((prop) => { - if (internalProps.includes(prop)) { - throw new Error( - `[UmiJS] route '${key}' should not have '${prop}' prop, please remove this property in 'routeProps'.` - ) - } - }) - }) -} - -import React from 'react'; - -export async function getRoutes() { - const routes = {} as const; - return { - routes, - routeComponents: { - -}, - }; -} diff --git a/dashboard/.umi/core/routeProps.ts b/dashboard/.umi/core/routeProps.ts deleted file mode 100644 index 0a8457e..0000000 --- a/dashboard/.umi/core/routeProps.ts +++ /dev/null @@ -1,6 +0,0 @@ -// @ts-nocheck -// This file is generated by Umi automatically -// DO NOT CHANGE IT MANUALLY! -export default { - -}; diff --git a/dashboard/.umi/core/terminal.ts b/dashboard/.umi/core/terminal.ts deleted file mode 100644 index b07942d..0000000 --- a/dashboard/.umi/core/terminal.ts +++ /dev/null @@ -1,37 +0,0 @@ -// @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 }; diff --git a/dashboard/.umi/exports.ts b/dashboard/.umi/exports.ts deleted file mode 100644 index f0e0291..0000000 --- a/dashboard/.umi/exports.ts +++ /dev/null @@ -1,19 +0,0 @@ -// @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'; diff --git a/dashboard/.umi/testBrowser.tsx b/dashboard/.umi/testBrowser.tsx deleted file mode 100644 index 53a3c66..0000000 --- a/dashboard/.umi/testBrowser.tsx +++ /dev/null @@ -1,88 +0,0 @@ -// @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; - historyRef?: React.MutableRefObject; -}; - -export function TestBrowser(props: TestBrowserProps) { - const pluginManager = createPluginManager(); - const [context, setContext] = useState( - 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
; - } - - const Children = renderClient(context); - return ( - - - - ); -} diff --git a/dashboard/.umi/tsconfig.json b/dashboard/.umi/tsconfig.json deleted file mode 100644 index 0d3dba8..0000000 --- a/dashboard/.umi/tsconfig.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "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": { - "@/*": [ - "*" - ], - "@@/*": [ - ".umi/*" - ], - "umi": [ - "../node_modules/umi" - ], - "umi/typings": [ - ".umi/typings" - ] - } - }, - "include": [ - "../.umirc.ts", - "../.umirc.*.ts", - "../**/*.d.ts", - "../**/*.ts", - "../**/*.tsx" - ] -} diff --git a/dashboard/.umi/typings.d.ts b/dashboard/.umi/typings.d.ts deleted file mode 100644 index 19725a3..0000000 --- a/dashboard/.umi/typings.d.ts +++ /dev/null @@ -1,136 +0,0 @@ -// 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 & { 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 - 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 -} diff --git a/dashboard/.umi/umi.ts b/dashboard/.umi/umi.ts deleted file mode 100644 index 2099bb1..0000000 --- a/dashboard/.umi/umi.ts +++ /dev/null @@ -1,81 +0,0 @@ -// @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', - }; - } diff --git a/dashboard/src/.umi/appData.json b/dashboard/src/.umi/appData.json index 0bfe41e..c734430 100644 --- a/dashboard/src/.umi/appData.json +++ b/dashboard/src/.umi/appData.json @@ -40,7 +40,7 @@ "config": {}, "time": { "hooks": {}, - "register": 1 + "register": 3 }, "enableBy": "register" }, @@ -53,7 +53,7 @@ "config": {}, "time": { "hooks": {}, - "register": 22 + "register": 31 }, "enableBy": "register" }, @@ -70,7 +70,7 @@ 0 ] }, - "register": 4 + "register": 5 }, "enableBy": "register" }, @@ -84,10 +84,10 @@ "time": { "hooks": { "onStart": [ - 2 + 4 ] }, - "register": 3 + "register": 4 }, "enableBy": "register" }, @@ -101,10 +101,10 @@ "time": { "hooks": { "modifyRoutes": [ - 1 + 0 ] }, - "register": 1 + "register": 2 }, "enableBy": "register" }, @@ -117,7 +117,7 @@ "config": {}, "time": { "hooks": {}, - "register": 1 + "register": 3 }, "enableBy": "register" }, @@ -131,10 +131,10 @@ "time": { "hooks": { "modifyAppData": [ - 291 + 518 ] }, - "register": 28 + "register": 51 }, "enableBy": "register" }, @@ -184,7 +184,7 @@ 0 ] }, - "register": 0 + "register": 1 }, "enableBy": "register" }, @@ -197,7 +197,7 @@ "config": {}, "time": { "hooks": {}, - "register": 3 + "register": 1 }, "enableBy": "config" }, @@ -214,7 +214,7 @@ 0 ] }, - "register": 15 + "register": 16 }, "enableBy": "register" }, @@ -1080,10 +1080,10 @@ "time": { "hooks": { "onStart": [ - 1 + 0 ] }, - "register": 1 + "register": 3 }, "enableBy": "register" }, @@ -1096,7 +1096,7 @@ "config": {}, "time": { "hooks": {}, - "register": 2 + "register": 3 }, "enableBy": "register" }, @@ -1109,7 +1109,7 @@ "config": {}, "time": { "hooks": {}, - "register": 93 + "register": 165 }, "enableBy": "register" }, @@ -1122,7 +1122,7 @@ "config": {}, "time": { "hooks": {}, - "register": 51 + "register": 112 }, "enableBy": "config" }, @@ -1135,7 +1135,7 @@ "config": {}, "time": { "hooks": {}, - "register": 24 + "register": 35 }, "enableBy": "config" }, @@ -1178,7 +1178,7 @@ "config": {}, "time": { "hooks": {}, - "register": 2 + "register": 4 }, "enableBy": "config" }, @@ -1192,10 +1192,10 @@ "time": { "hooks": { "onStart": [ - 1 + 3 ] }, - "register": 51 + "register": 74 } }, "./node_modules/@umijs/preset-umi/dist/features/mpa/mpa": { @@ -1220,7 +1220,7 @@ "config": {}, "time": { "hooks": {}, - "register": 2 + "register": 1 } }, "./node_modules/@umijs/preset-umi/dist/features/overrides/overrides": { @@ -1262,7 +1262,7 @@ 1 ] }, - "register": 4 + "register": 6 } }, "./node_modules/@umijs/preset-umi/dist/features/polyfill/publicPathPolyfill": { @@ -1287,7 +1287,7 @@ "config": {}, "time": { "hooks": {}, - "register": 3 + "register": 2 }, "enableBy": "register" }, @@ -1326,7 +1326,7 @@ "config": {}, "time": { "hooks": {}, - "register": 1 + "register": 2 }, "enableBy": "register" }, @@ -1339,7 +1339,7 @@ "config": {}, "time": { "hooks": {}, - "register": 11 + "register": 18 }, "enableBy": "register" }, @@ -1352,7 +1352,7 @@ "config": {}, "time": { "hooks": {}, - "register": 2 + "register": 8 }, "enableBy": "config" }, @@ -1377,7 +1377,7 @@ "config": {}, "time": { "hooks": {}, - "register": 3 + "register": 5 }, "enableBy": "config" }, @@ -1390,7 +1390,7 @@ "config": {}, "time": { "hooks": {}, - "register": 4 + "register": 15 }, "enableBy": "register" }, @@ -1403,7 +1403,7 @@ "config": {}, "time": { "hooks": {}, - "register": 4 + "register": 6 }, "enableBy": "register" }, @@ -1442,7 +1442,7 @@ "config": {}, "time": { "hooks": {}, - "register": 8 + "register": 12 } }, "./node_modules/@umijs/preset-umi/dist/features/monorepo/redirect": { @@ -1454,7 +1454,7 @@ "config": {}, "time": { "hooks": {}, - "register": 26 + "register": 44 }, "enableBy": "config" }, @@ -1505,7 +1505,7 @@ "config": {}, "time": { "hooks": {}, - "register": 1 + "register": 4 }, "enableBy": "config" }, @@ -1518,7 +1518,7 @@ "config": {}, "time": { "hooks": {}, - "register": 1 + "register": 2 } }, "./node_modules/@umijs/preset-umi/dist/features/swc/swc": { @@ -1547,7 +1547,7 @@ "config": {}, "time": { "hooks": {}, - "register": 3 + "register": 7 } }, "./node_modules/@umijs/preset-umi/dist/features/mako/mako": { @@ -1559,7 +1559,7 @@ "config": {}, "time": { "hooks": {}, - "register": 1 + "register": 2 }, "enableBy": "config" }, @@ -1584,7 +1584,7 @@ "config": {}, "time": { "hooks": {}, - "register": 3 + "register": 5 } }, "./node_modules/@umijs/preset-umi/dist/features/routePreloadOnLoad/routePreloadOnLoad": { @@ -1596,7 +1596,7 @@ "config": {}, "time": { "hooks": {}, - "register": 42 + "register": 44 } }, "./node_modules/@umijs/preset-umi/dist/features/forget/forget": { @@ -1608,7 +1608,7 @@ "config": {}, "time": { "hooks": {}, - "register": 2 + "register": 4 }, "enableBy": "config" }, @@ -1621,7 +1621,7 @@ "config": {}, "time": { "hooks": {}, - "register": 2 + "register": 6 }, "enableBy": "register" }, @@ -1634,7 +1634,7 @@ "config": {}, "time": { "hooks": {}, - "register": 8 + "register": 12 }, "enableBy": "register" }, @@ -1647,7 +1647,7 @@ "config": {}, "time": { "hooks": {}, - "register": 39 + "register": 53 }, "enableBy": "register" }, @@ -1661,10 +1661,10 @@ "time": { "hooks": { "modifyAppData": [ - 15 + 33 ] }, - "register": 61 + "register": 120 } }, "./node_modules/@umijs/preset-umi/dist/commands/help": { @@ -1689,7 +1689,7 @@ "config": {}, "time": { "hooks": {}, - "register": 1 + "register": 0 }, "enableBy": "register" }, @@ -1702,7 +1702,7 @@ "config": {}, "time": { "hooks": {}, - "register": 0 + "register": 1 }, "enableBy": "register" }, @@ -1741,7 +1741,7 @@ "config": {}, "time": { "hooks": {}, - "register": 4 + "register": 5 }, "enableBy": "register" }, @@ -1754,7 +1754,7 @@ "config": {}, "time": { "hooks": {}, - "register": 0 + "register": 1 }, "enableBy": "register" }, @@ -1819,7 +1819,7 @@ "config": {}, "time": { "hooks": {}, - "register": 1 + "register": 2 }, "enableBy": "register" }, @@ -1858,7 +1858,7 @@ "config": {}, "time": { "hooks": {}, - "register": 1 + "register": 2 }, "enableBy": "register" }, @@ -1897,7 +1897,7 @@ "config": {}, "time": { "hooks": {}, - "register": 1 + "register": 2 }, "enableBy": "register" }, @@ -1923,7 +1923,7 @@ "config": {}, "time": { "hooks": {}, - "register": 2 + "register": 3 }, "enableBy": "register" }, @@ -1936,7 +1936,7 @@ "config": {}, "time": { "hooks": {}, - "register": 6 + "register": 10 }, "enableBy": "register" }, @@ -1993,6 +1993,42 @@ } }, "routes": { + "IndependentSite/IndependentSiteAnalytics": { + "path": "IndependentSite/IndependentSiteAnalytics", + "id": "IndependentSite/IndependentSiteAnalytics", + "file": "IndependentSite/IndependentSiteAnalytics.tsx", + "absPath": "/IndependentSite/IndependentSiteAnalytics", + "__content": "import React, { useState, useEffect } from 'react';\nimport { Card, DatePicker, Select, Spin, Statistic, Row, Col, Tabs, Button } from 'antd';\nimport { Area, AreaChart, Bar, BarChart, Line, LineChart, Pie, PieChart, ResponsiveContainer, Tooltip, XAxis, YAxis, CartesianGrid, Legend } from 'recharts';\nimport { useParams } from 'react-router-dom';\n\nconst { RangePicker } = DatePicker;\nconst { Option } = Select;\nconst { TabPane } = Tabs;\n\ninterface SalesData {\n date: string;\n sales: number;\n orders: number;\n customers: number;\n}\n\ninterface ProductData {\n name: string;\n sales: number;\n quantity: number;\n}\n\ninterface TrafficData {\n date: string;\n visitors: number;\n pageViews: number;\n bounceRate: number;\n}\n\ninterface ConversionData {\n name: string;\n value: number;\n}\n\nconst IndependentSiteAnalytics: React.FC = () => {\n const { id } = useParams<{ id: string }>();\n const [loading, setLoading] = useState(false);\n const [dateRange, setDateRange] = useState(null);\n const [timeRange, setTimeRange] = useState('30d');\n const [salesData, setSalesData] = useState([]);\n const [productData, setProductData] = useState([]);\n const [trafficData, setTrafficData] = useState([]);\n const [conversionData, setConversionData] = useState([]);\n const [summary, setSummary] = useState({\n totalSales: 0,\n totalOrders: 0,\n totalCustomers: 0,\n conversionRate: 0,\n });\n\n useEffect(() => {\n fetchAnalyticsData();\n }, [id, timeRange, dateRange]);\n\n const fetchAnalyticsData = async () => {\n setLoading(true);\n // 模拟API调用\n setTimeout(() => {\n // 模拟销售数据\n const mockSalesData: SalesData[] = Array.from({ length: 30 }, (_, i) => ({\n date: `2026-03-${String(i + 1).padStart(2, '0')}`,\n sales: Math.random() * 1000 + 500,\n orders: Math.random() * 50 + 10,\n customers: Math.random() * 30 + 5,\n }));\n\n // 模拟商品数据\n const mockProductData: ProductData[] = [\n { name: 'Product 1', sales: 1500, quantity: 15 },\n { name: 'Product 2', sales: 2000, quantity: 20 },\n { name: 'Product 3', sales: 1000, quantity: 10 },\n { name: 'Product 4', sales: 500, quantity: 5 },\n { name: 'Product 5', sales: 800, quantity: 8 },\n ];\n\n // 模拟流量数据\n const mockTrafficData: TrafficData[] = Array.from({ length: 30 }, (_, i) => ({\n date: `2026-03-${String(i + 1).padStart(2, '0')}`,\n visitors: Math.random() * 500 + 100,\n pageViews: Math.random() * 1000 + 500,\n bounceRate: Math.random() * 50 + 20,\n }));\n\n // 模拟转化数据\n const mockConversionData: ConversionData[] = [\n { name: '已转化', value: 20 },\n { name: '未转化', value: 80 },\n ];\n\n // 模拟汇总数据\n const mockSummary = {\n totalSales: 5800,\n totalOrders: 78,\n totalCustomers: 55,\n conversionRate: 20,\n };\n\n setSalesData(mockSalesData);\n setProductData(mockProductData);\n setTrafficData(mockTrafficData);\n setConversionData(mockConversionData);\n setSummary(mockSummary);\n setLoading(false);\n }, 1000);\n };\n\n const handleTimeRangeChange = (value: string) => {\n setTimeRange(value);\n };\n\n const handleDateRangeChange = (dates: any) => {\n setDateRange(dates);\n };\n\n return (\n
\n
\n

独立站数据分析

\n
\n \n \n \n \n \n \n \n \n
\n
\n\n {loading ? (\n
\n \n
\n ) : (\n <>\n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n `${name}: ${(percent * 100).toFixed(0)}%`}\n outerRadius={150}\n fill=\"#8884d8\"\n dataKey=\"value\"\n />\n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n
\n

地域分布图表

\n
\n
\n \n
\n \n
\n

购买行为图表

\n
\n
\n \n \n \n \n \n )}\n \n );\n};\n\nexport default IndependentSiteAnalytics;", + "__isJSFile": true, + "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/IndependentSite/IndependentSiteAnalytics.tsx" + }, + "IndependentSite/IndependentSiteProduct": { + "path": "IndependentSite/IndependentSiteProduct", + "id": "IndependentSite/IndependentSiteProduct", + "file": "IndependentSite/IndependentSiteProduct.tsx", + "absPath": "/IndependentSite/IndependentSiteProduct", + "__content": "import React, { useState, useEffect } from 'react';\nimport { Table, Button, Input, Select, message, Upload, Modal, Form } from 'antd';\nimport { PlusOutlined, EditOutlined, DeleteOutlined, UploadOutlined } from '@ant-design/icons';\nimport { useParams } from 'react-router-dom';\n\nconst { Option } = Select;\nconst { Search } = Input;\n\ninterface Product {\n id: string;\n name: string;\n sku: string;\n price: number;\n stock: number;\n status: 'published' | 'draft' | 'unpublished';\n createdAt: string;\n lastUpdated: string;\n}\n\nconst IndependentSiteProduct: React.FC = () => {\n const { id } = useParams<{ id: string }>();\n const [products, setProducts] = useState([]);\n const [loading, setLoading] = useState(false);\n const [filters, setFilters] = useState({\n status: '',\n search: '',\n });\n const [modalVisible, setModalVisible] = useState(false);\n const [form] = Form.useForm();\n\n useEffect(() => {\n fetchProducts();\n }, [id, filters]);\n\n const fetchProducts = async () => {\n setLoading(true);\n // 模拟API调用\n setTimeout(() => {\n const mockProducts: Product[] = [\n {\n id: '1',\n name: 'Test Product 1',\n sku: 'TP-001',\n price: 99.99,\n stock: 100,\n status: 'published',\n createdAt: '2026-03-01',\n lastUpdated: '2026-03-15',\n },\n {\n id: '2',\n name: 'Test Product 2',\n sku: 'TP-002',\n price: 199.99,\n stock: 50,\n status: 'draft',\n createdAt: '2026-03-05',\n lastUpdated: '2026-03-10',\n },\n {\n id: '3',\n name: 'Test Product 3',\n sku: 'TP-003',\n price: 299.99,\n stock: 25,\n status: 'unpublished',\n createdAt: '2026-03-10',\n lastUpdated: '2026-03-18',\n },\n ];\n setProducts(mockProducts);\n setLoading(false);\n }, 500);\n };\n\n const handleAddProduct = () => {\n form.resetFields();\n setModalVisible(true);\n };\n\n const handleEditProduct = (record: Product) => {\n form.setFieldsValue(record);\n setModalVisible(true);\n };\n\n const handleDeleteProduct = (id: string) => {\n message.success('商品已删除');\n fetchProducts();\n };\n\n const handlePublishProduct = (id: string) => {\n message.success('商品已发布');\n fetchProducts();\n };\n\n const handleUnpublishProduct = (id: string) => {\n message.success('商品已下架');\n fetchProducts();\n };\n\n const handleSubmit = async (values: any) => {\n setLoading(true);\n // 模拟API调用\n setTimeout(() => {\n message.success('商品保存成功');\n setLoading(false);\n setModalVisible(false);\n fetchProducts();\n }, 1000);\n };\n\n const columns = [\n {\n title: '商品名称',\n dataIndex: 'name',\n key: 'name',\n },\n {\n title: 'SKU',\n dataIndex: 'sku',\n key: 'sku',\n },\n {\n title: '价格',\n dataIndex: 'price',\n key: 'price',\n render: (price: number) => `$${price.toFixed(2)}`,\n },\n {\n title: '库存',\n dataIndex: 'stock',\n key: 'stock',\n },\n {\n title: '状态',\n dataIndex: 'status',\n key: 'status',\n render: (status: string) => {\n const statusMap = {\n published: '已发布',\n draft: '草稿',\n unpublished: '未发布',\n };\n return statusMap[status] || status;\n },\n },\n {\n title: '创建时间',\n dataIndex: 'createdAt',\n key: 'createdAt',\n },\n {\n title: '最后更新',\n dataIndex: 'lastUpdated',\n key: 'lastUpdated',\n },\n {\n title: '操作',\n key: 'action',\n render: (_: any, record: Product) => (\n
\n }\n onClick={() => handleEditProduct(record)}\n >\n 编辑\n \n }\n onClick={() => handleDeleteProduct(record.id)}\n >\n 删除\n \n {record.status !== 'published' && (\n handlePublishProduct(record.id)}\n >\n 发布\n \n )}\n {record.status === 'published' && (\n handleUnpublishProduct(record.id)}\n >\n 下架\n \n )}\n
\n ),\n },\n ];\n\n return (\n
\n
\n

独立站商品管理

\n }\n onClick={handleAddProduct}\n >\n 添加商品\n \n
\n\n
\n setFilters({ ...filters, search: e.target.value })}\n />\n setFilters({ ...filters, status: value })}\n >\n \n \n \n \n \n
\n\n \n\n setModalVisible(false)}\n footer={null}\n >\n \n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n \n \n\n \n \n \n\n \n \n \n \n \n \n
\n );\n};\n\nexport default IndependentSiteProduct;", + "__isJSFile": true, + "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/IndependentSite/IndependentSiteProduct.tsx" + }, + "IndependentSite/IndependentSiteConfig": { + "path": "IndependentSite/IndependentSiteConfig", + "id": "IndependentSite/IndependentSiteConfig", + "file": "IndependentSite/IndependentSiteConfig.tsx", + "absPath": "/IndependentSite/IndependentSiteConfig", + "__content": "import React, { useState, useEffect } from 'react';\nimport { Form, Input, Select, Button, message, Switch, Card, Tabs } from 'antd';\nimport { useNavigate, useParams } from 'react-router-dom';\n\nconst { Option } = Select;\nconst { TabPane } = Tabs;\n\nconst IndependentSiteConfig: React.FC = () => {\n const navigate = useNavigate();\n const { id } = useParams<{ id: string }>();\n const [form] = Form.useForm();\n const [loading, setLoading] = useState(false);\n const [siteData, setSiteData] = useState({});\n\n useEffect(() => {\n fetchSiteData();\n }, [id]);\n\n const fetchSiteData = async () => {\n setLoading(true);\n // 模拟API调用\n setTimeout(() => {\n const mockData = {\n id: id,\n name: 'Test Store 1',\n url: 'https://test-store-1.com',\n platform: 'Shopify',\n apiKey: 'test-api-key',\n apiSecret: 'test-api-secret',\n webhookUrl: 'https://webhook.example.com',\n theme: 'default',\n description: 'Test store for demonstration',\n isActive: true,\n notes: 'This is a test store',\n settings: {\n inventorySync: true,\n orderSync: true,\n pricingSync: true,\n autoPublish: false,\n currency: 'USD',\n language: 'en',\n },\n shipping: {\n freeShipping: true,\n freeShippingThreshold: 50,\n shippingZones: ['US', 'CA', 'EU'],\n },\n payment: {\n paypal: true,\n stripe: true,\n creditCard: true,\n applePay: false,\n },\n };\n setSiteData(mockData);\n form.setFieldsValue(mockData);\n setLoading(false);\n }, 500);\n };\n\n const onFinish = async (values: any) => {\n setLoading(true);\n // 模拟API调用\n setTimeout(() => {\n message.success('配置保存成功');\n setLoading(false);\n }, 1000);\n };\n\n const handleCancel = () => {\n navigate('/independent-site');\n };\n\n return (\n
\n
\n

独立站配置 - {siteData.name}

\n
\n\n \n \n \n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n \n\n \n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n \n\n \n \n \n \n\n \n \n \n\n \n \n \n \n\n \n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n \n \n\n \n \n \n \n \n
\n );\n};\n\nexport default IndependentSiteConfig;", + "__isJSFile": true, + "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/IndependentSite/IndependentSiteConfig.tsx" + }, + "IndependentSite/IndependentSiteCreate": { + "path": "IndependentSite/IndependentSiteCreate", + "id": "IndependentSite/IndependentSiteCreate", + "file": "IndependentSite/IndependentSiteCreate.tsx", + "absPath": "/IndependentSite/IndependentSiteCreate", + "__content": "import React, { useState } from 'react';\nimport { Form, Input, Select, Button, message, Upload, Checkbox } from 'antd';\nimport { UploadOutlined } from '@ant-design/icons';\nimport { useNavigate } from 'react-router-dom';\n\nconst { Option } = Select;\n\nconst IndependentSiteCreate: React.FC = () => {\n const navigate = useNavigate();\n const [form] = Form.useForm();\n const [loading, setLoading] = useState(false);\n\n const onFinish = async (values: any) => {\n setLoading(true);\n // 模拟API调用\n setTimeout(() => {\n message.success('独立站创建成功');\n setLoading(false);\n navigate('/independent-site');\n }, 1000);\n };\n\n const handleCancel = () => {\n navigate('/independent-site');\n };\n\n return (\n
\n
\n

创建独立站

\n
\n\n \n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n \n \n\n \n \n \n\n \n 创建后立即启用\n \n\n \n \n \n\n \n \n \n \n \n
\n );\n};\n\nexport default IndependentSiteCreate;", + "__isJSFile": true, + "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/IndependentSite/IndependentSiteCreate.tsx" + }, "Compliance/CertificateExpiryReminder": { "path": "Compliance/CertificateExpiryReminder", "id": "Compliance/CertificateExpiryReminder", @@ -2002,6 +2038,24 @@ "__isJSFile": true, "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/Compliance/CertificateExpiryReminder.tsx" }, + "IndependentSite/IndependentSiteOrder": { + "path": "IndependentSite/IndependentSiteOrder", + "id": "IndependentSite/IndependentSiteOrder", + "file": "IndependentSite/IndependentSiteOrder.tsx", + "absPath": "/IndependentSite/IndependentSiteOrder", + "__content": "import React, { useState, useEffect } from 'react';\nimport { Table, Button, Input, Select, DatePicker, message, Modal, Form } from 'antd';\nimport { EyeOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';\nimport { useParams } from 'react-router-dom';\n\nconst { Option } = Select;\nconst { RangePicker } = DatePicker;\nconst { Search } = Input;\n\ninterface Order {\n id: string;\n orderNumber: string;\n customerName: string;\n total: number;\n status: 'pending' | 'processing' | 'shipped' | 'delivered' | 'cancelled' | 'refunded';\n paymentMethod: string;\n createdAt: string;\n updatedAt: string;\n}\n\nconst IndependentSiteOrder: React.FC = () => {\n const { id } = useParams<{ id: string }>();\n const [orders, setOrders] = useState([]);\n const [loading, setLoading] = useState(false);\n const [filters, setFilters] = useState({\n status: '',\n paymentMethod: '',\n search: '',\n dateRange: null as any,\n });\n const [modalVisible, setModalVisible] = useState(false);\n const [selectedOrder, setSelectedOrder] = useState(null);\n const [form] = Form.useForm();\n\n useEffect(() => {\n fetchOrders();\n }, [id, filters]);\n\n const fetchOrders = async () => {\n setLoading(true);\n // 模拟API调用\n setTimeout(() => {\n const mockOrders: Order[] = [\n {\n id: '1',\n orderNumber: 'ORD-2026-001',\n customerName: 'John Doe',\n total: 199.99,\n status: 'processing',\n paymentMethod: 'PayPal',\n createdAt: '2026-03-15',\n updatedAt: '2026-03-16',\n },\n {\n id: '2',\n orderNumber: 'ORD-2026-002',\n customerName: 'Jane Smith',\n total: 299.99,\n status: 'shipped',\n paymentMethod: 'Stripe',\n createdAt: '2026-03-16',\n updatedAt: '2026-03-17',\n },\n {\n id: '3',\n orderNumber: 'ORD-2026-003',\n customerName: 'Bob Johnson',\n total: 99.99,\n status: 'delivered',\n paymentMethod: 'Credit Card',\n createdAt: '2026-03-17',\n updatedAt: '2026-03-18',\n },\n {\n id: '4',\n orderNumber: 'ORD-2026-004',\n customerName: 'Alice Brown',\n total: 499.99,\n status: 'cancelled',\n paymentMethod: 'PayPal',\n createdAt: '2026-03-18',\n updatedAt: '2026-03-18',\n },\n ];\n setOrders(mockOrders);\n setLoading(false);\n }, 500);\n };\n\n const handleViewOrder = (order: Order) => {\n setSelectedOrder(order);\n form.setFieldsValue(order);\n setModalVisible(true);\n };\n\n const handleUpdateOrder = async (values: any) => {\n setLoading(true);\n // 模拟API调用\n setTimeout(() => {\n message.success('订单状态更新成功');\n setLoading(false);\n setModalVisible(false);\n fetchOrders();\n }, 1000);\n };\n\n const handleCancelOrder = (id: string) => {\n message.success('订单已取消');\n fetchOrders();\n };\n\n const handleRefundOrder = (id: string) => {\n message.success('订单已退款');\n fetchOrders();\n };\n\n const columns = [\n {\n title: '订单号',\n dataIndex: 'orderNumber',\n key: 'orderNumber',\n },\n {\n title: '客户名称',\n dataIndex: 'customerName',\n key: 'customerName',\n },\n {\n title: '总金额',\n dataIndex: 'total',\n key: 'total',\n render: (total: number) => `$${total.toFixed(2)}`,\n },\n {\n title: '状态',\n dataIndex: 'status',\n key: 'status',\n render: (status: string) => {\n const statusMap = {\n pending: '待处理',\n processing: '处理中',\n shipped: '已发货',\n delivered: '已送达',\n cancelled: '已取消',\n refunded: '已退款',\n };\n return statusMap[status] || status;\n },\n },\n {\n title: '支付方式',\n dataIndex: 'paymentMethod',\n key: 'paymentMethod',\n },\n {\n title: '创建时间',\n dataIndex: 'createdAt',\n key: 'createdAt',\n },\n {\n title: '更新时间',\n dataIndex: 'updatedAt',\n key: 'updatedAt',\n },\n {\n title: '操作',\n key: 'action',\n render: (_: any, record: Order) => (\n
\n }\n onClick={() => handleViewOrder(record)}\n >\n 查看\n \n }\n onClick={() => handleViewOrder(record)}\n >\n 编辑\n \n {record.status !== 'cancelled' && record.status !== 'refunded' && (\n <>\n handleCancelOrder(record.id)}\n >\n 取消\n \n handleRefundOrder(record.id)}\n >\n 退款\n \n \n )}\n
\n ),\n },\n ];\n\n return (\n
\n
\n

独立站订单管理

\n
\n\n
\n setFilters({ ...filters, search: e.target.value })}\n />\n setFilters({ ...filters, status: value })}\n >\n \n \n \n \n \n \n \n \n setFilters({ ...filters, paymentMethod: value })}\n >\n \n \n \n \n \n \n setFilters({ ...filters, dateRange: dates })}\n />\n
\n\n \n\n {selectedOrder && (\n setModalVisible(false)}\n footer={null}\n width={800}\n >\n \n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n \n \n \n )}\n
\n );\n};\n\nexport default IndependentSiteOrder;", + "__isJSFile": true, + "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/IndependentSite/IndependentSiteOrder.tsx" + }, + "IndependentSite/IndependentSiteList": { + "path": "IndependentSite/IndependentSiteList", + "id": "IndependentSite/IndependentSiteList", + "file": "IndependentSite/IndependentSiteList.tsx", + "absPath": "/IndependentSite/IndependentSiteList", + "__content": "import React, { useState, useEffect } from 'react';\nimport { Table, Button, Input, Select, DatePicker, message } from 'antd';\nimport { PlusOutlined, EditOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons';\nimport { useNavigate } from 'react-router-dom';\n\nconst { Option } = Select;\nconst { RangePicker } = DatePicker;\nconst { Search } = Input;\n\ninterface Site {\n id: string;\n name: string;\n url: string;\n status: 'active' | 'inactive' | 'building';\n platform: string;\n createdAt: string;\n lastUpdated: string;\n}\n\nconst IndependentSiteList: React.FC = () => {\n const navigate = useNavigate();\n const [sites, setSites] = useState([]);\n const [loading, setLoading] = useState(false);\n const [filters, setFilters] = useState({\n status: '',\n platform: '',\n search: '',\n dateRange: null as any,\n });\n\n useEffect(() => {\n fetchSites();\n }, [filters]);\n\n const fetchSites = async () => {\n setLoading(true);\n // 模拟API调用\n setTimeout(() => {\n const mockSites: Site[] = [\n {\n id: '1',\n name: 'Test Store 1',\n url: 'https://test-store-1.com',\n status: 'active',\n platform: 'Shopify',\n createdAt: '2026-03-01',\n lastUpdated: '2026-03-15',\n },\n {\n id: '2',\n name: 'Test Store 2',\n url: 'https://test-store-2.com',\n status: 'inactive',\n platform: 'WooCommerce',\n createdAt: '2026-03-05',\n lastUpdated: '2026-03-10',\n },\n {\n id: '3',\n name: 'Test Store 3',\n url: 'https://test-store-3.com',\n status: 'building',\n platform: 'Shopify',\n createdAt: '2026-03-10',\n lastUpdated: '2026-03-18',\n },\n ];\n setSites(mockSites);\n setLoading(false);\n }, 500);\n };\n\n const handleCreate = () => {\n navigate('/independent-site/create');\n };\n\n const handleEdit = (id: string) => {\n navigate(`/independent-site/config/${id}`);\n };\n\n const handleView = (id: string) => {\n navigate(`/independent-site/config/${id}`);\n };\n\n const handleDelete = (id: string) => {\n message.success('站点已删除');\n fetchSites();\n };\n\n const handleProductManage = (id: string) => {\n navigate(`/independent-site/product/${id}`);\n };\n\n const handleOrderManage = (id: string) => {\n navigate(`/independent-site/order/${id}`);\n };\n\n const handleAnalytics = (id: string) => {\n navigate(`/independent-site/analytics/${id}`);\n };\n\n const columns = [\n {\n title: '站点名称',\n dataIndex: 'name',\n key: 'name',\n },\n {\n title: 'URL',\n dataIndex: 'url',\n key: 'url',\n render: (url: string) => {url},\n },\n {\n title: '状态',\n dataIndex: 'status',\n key: 'status',\n render: (status: string) => {\n const statusMap = {\n active: '启用',\n inactive: '停用',\n building: '建设中',\n };\n return statusMap[status] || status;\n },\n },\n {\n title: '平台',\n dataIndex: 'platform',\n key: 'platform',\n },\n {\n title: '创建时间',\n dataIndex: 'createdAt',\n key: 'createdAt',\n },\n {\n title: '最后更新',\n dataIndex: 'lastUpdated',\n key: 'lastUpdated',\n },\n {\n title: '操作',\n key: 'action',\n render: (_: any, record: Site) => (\n
\n }\n onClick={() => handleView(record.id)}\n >\n 查看\n \n }\n onClick={() => handleEdit(record.id)}\n >\n 配置\n \n handleProductManage(record.id)}\n >\n 商品管理\n \n handleOrderManage(record.id)}\n >\n 订单管理\n \n handleAnalytics(record.id)}\n >\n 数据分析\n \n }\n onClick={() => handleDelete(record.id)}\n >\n 删除\n \n
\n ),\n },\n ];\n\n return (\n
\n
\n

独立站管理

\n }\n onClick={handleCreate}\n >\n 创建独立站\n \n
\n\n
\n setFilters({ ...filters, search: e.target.value })}\n />\n setFilters({ ...filters, status: value })}\n >\n \n \n \n \n \n setFilters({ ...filters, platform: value })}\n >\n \n \n \n \n \n setFilters({ ...filters, dateRange: dates })}\n />\n
\n\n \n
\n );\n};\n\nexport default IndependentSiteList;", + "__isJSFile": true, + "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/IndependentSite/IndependentSiteList.tsx" + }, "Merchant/MerchantSettlementManage": { "path": "Merchant/MerchantSettlementManage", "id": "Merchant/MerchantSettlementManage", @@ -2029,6 +2083,15 @@ "__isJSFile": true, "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/Merchant/MerchantOrderManage.tsx" }, + "Inventory/InventoryForecast": { + "path": "Inventory/InventoryForecast", + "id": "Inventory/InventoryForecast", + "file": "Inventory/InventoryForecast.tsx", + "absPath": "/Inventory/InventoryForecast", + "__content": "import React, { useState, useEffect } from 'react';\nimport { Card, Row, Col, Select, DatePicker, Button, Table } from 'antd';\nimport { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, BarChart, Bar } from 'recharts';\n\nconst { Option } = Select;\nconst { RangePicker } = DatePicker;\n\ninterface ForecastData {\n date: string;\n demand: number;\n supply: number;\n stock: number;\n}\n\ninterface ProductForecast {\n id: string;\n sku: string;\n name: string;\n currentStock: number;\n forecastedDemand: number;\n recommendedOrder: number;\n leadTime: number;\n riskLevel: 'low' | 'medium' | 'high';\n}\n\nconst InventoryForecast: React.FC = () => {\n const [forecastData, setForecastData] = useState([]);\n const [productForecasts, setProductForecasts] = useState([]);\n const [loading, setLoading] = useState(false);\n const [selectedProduct, setSelectedProduct] = useState('all');\n const [dateRange, setDateRange] = useState(null);\n\n useEffect(() => {\n fetchForecastData();\n }, [selectedProduct, dateRange]);\n\n const fetchForecastData = async () => {\n setLoading(true);\n // 模拟API调用\n setTimeout(() => {\n // 模拟预测数据\n const mockForecastData: ForecastData[] = Array.from({ length: 30 }, (_, i) => ({\n date: `2026-04-${String(i + 1).padStart(2, '0')}`,\n demand: Math.random() * 50 + 20,\n supply: Math.random() * 30 + 10,\n stock: Math.random() * 100 + 50,\n }));\n\n // 模拟产品预测数据\n const mockProductForecasts: ProductForecast[] = [\n {\n id: '1',\n sku: 'SKU-001',\n name: 'Product 1',\n currentStock: 100,\n forecastedDemand: 150,\n recommendedOrder: 100,\n leadTime: 7,\n riskLevel: 'low',\n },\n {\n id: '2',\n sku: 'SKU-002',\n name: 'Product 2',\n currentStock: 15,\n forecastedDemand: 50,\n recommendedOrder: 40,\n leadTime: 10,\n riskLevel: 'high',\n },\n {\n id: '3',\n sku: 'SKU-003',\n name: 'Product 3',\n currentStock: 0,\n forecastedDemand: 30,\n recommendedOrder: 30,\n leadTime: 5,\n riskLevel: 'high',\n },\n {\n id: '4',\n sku: 'SKU-004',\n name: 'Product 4',\n currentStock: 50,\n forecastedDemand: 60,\n recommendedOrder: 20,\n leadTime: 3,\n riskLevel: 'medium',\n },\n ];\n\n setForecastData(mockForecastData);\n setProductForecasts(mockProductForecasts);\n setLoading(false);\n }, 500);\n };\n\n const columns = [\n {\n title: 'SKU',\n dataIndex: 'sku',\n key: 'sku',\n },\n {\n title: '商品名称',\n dataIndex: 'name',\n key: 'name',\n },\n {\n title: '当前库存',\n dataIndex: 'currentStock',\n key: 'currentStock',\n },\n {\n title: '预测需求',\n dataIndex: 'forecastedDemand',\n key: 'forecastedDemand',\n },\n {\n title: '建议订购量',\n dataIndex: 'recommendedOrder',\n key: 'recommendedOrder',\n },\n {\n title: '交货期(天)',\n dataIndex: 'leadTime',\n key: 'leadTime',\n },\n {\n title: '风险等级',\n dataIndex: 'riskLevel',\n key: 'riskLevel',\n render: (riskLevel: string) => {\n const riskMap = {\n low: { text: '低', color: '#3f8600' },\n medium: { text: '中', color: '#fa8c16' },\n high: { text: '高', color: '#cf1322' },\n };\n const riskInfo = riskMap[riskLevel as keyof typeof riskMap] || { text: riskLevel, color: '#000' };\n return {riskInfo.text};\n },\n },\n ];\n\n return (\n
\n
\n

库存预测

\n
\n\n
\n \n \n \n \n \n \n \n \n
\n\n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n );\n};\n\nexport default InventoryForecast;", + "__isJSFile": true, + "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/Inventory/InventoryForecast.tsx" + }, "Merchant/MerchantShopManage": { "path": "Merchant/MerchantShopManage", "id": "Merchant/MerchantShopManage", @@ -2038,6 +2101,15 @@ "__isJSFile": true, "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/Merchant/MerchantShopManage.tsx" }, + "Product/ProfitMonitor/index": { + "path": "Product/ProfitMonitor", + "id": "Product/ProfitMonitor/index", + "file": "Product/ProfitMonitor/index.tsx", + "absPath": "/Product/ProfitMonitor", + "__content": "import React, { useState, useEffect } from 'react';\nimport { Card, Layout, Typography, Row, Col, Select, Button, Table, Statistic, Spin, message, Alert, Badge } from 'antd';\nimport { LineChart, Line, AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';\nimport { AlertOutlined, TrendingUpOutlined, TrendingDownOutlined, ReloadOutlined, EyeOutlined } from '@ant-design/icons';\nimport { Link } from 'umi';\n\nconst { Content } = Layout;\nconst { Title, Text, Paragraph } = Typography;\nconst { Option } = Select;\n\ninterface ProfitData {\n id: string;\n date: string;\n profit: number;\n sales: number;\n cost: number;\n roi: number;\n}\n\ninterface AlertItem {\n id: string;\n productId: string;\n productName: string;\n type: string;\n message: string;\n severity: 'info' | 'warning' | 'error';\n date: string;\n}\n\ninterface ProductProfit {\n id: string;\n productId: string;\n productName: string;\n currentProfit: number;\n previousProfit: number;\n change: number;\n roi: number;\n status: 'up' | 'down' | 'stable';\n}\n\nconst ProfitMonitor: React.FC = () => {\n const [loading, setLoading] = useState(false);\n const [profitData, setProfitData] = useState([]);\n const [alerts, setAlerts] = useState([]);\n const [productProfits, setProductProfits] = useState([]);\n const [selectedProduct, setSelectedProduct] = useState('');\n const [timeRange, setTimeRange] = useState('7d');\n\n const mockProfitData: ProfitData[] = [\n { id: '1', date: '2026-03-12', profit: 14900, sales: 12000, cost: 8000, roi: 99.33 },\n { id: '2', date: '2026-03-13', profit: 15200, sales: 12500, cost: 8200, roi: 100.67 },\n { id: '3', date: '2026-03-14', profit: 14800, sales: 11800, cost: 8100, roi: 98.67 },\n { id: '4', date: '2026-03-15', profit: 16500, sales: 13500, cost: 8500, roi: 103.33 },\n { id: '5', date: '2026-03-16', profit: 17200, sales: 14000, cost: 8800, roi: 105.33 },\n { id: '6', date: '2026-03-17', profit: 16800, sales: 13800, cost: 8700, roi: 104.00 },\n { id: '7', date: '2026-03-18', profit: 18500, sales: 15000, cost: 9200, roi: 108.33 },\n ];\n\n const mockAlerts: AlertItem[] = [\n {\n id: '1',\n productId: 'P001',\n productName: '智能手表',\n type: '利润下降',\n message: '连续3天利润下降,当前利润低于预期15%',\n severity: 'warning',\n date: '2026-03-18 10:30',\n },\n {\n id: '2',\n productId: 'P002',\n productName: '无线耳机',\n type: 'ROI异常',\n message: 'ROI突然上升30%,可能存在定价问题',\n severity: 'info',\n date: '2026-03-18 09:15',\n },\n {\n id: '3',\n productId: 'P003',\n productName: '智能音箱',\n type: '成本上升',\n message: '成本上升10%,建议调整售价',\n severity: 'error',\n date: '2026-03-17 16:45',\n },\n ];\n\n const mockProductProfits: ProductProfit[] = [\n {\n id: '1',\n productId: 'P001',\n productName: '智能手表',\n currentProfit: 14900,\n previousProfit: 15200,\n change: -2.0,\n roi: 99.33,\n status: 'down',\n },\n {\n id: '2',\n productId: 'P002',\n productName: '无线耳机',\n currentProfit: 23800,\n previousProfit: 21500,\n change: 10.7,\n roi: 148.75,\n status: 'up',\n },\n {\n id: '3',\n productId: 'P003',\n productName: '智能音箱',\n currentProfit: 9500,\n previousProfit: 9400,\n change: 1.1,\n roi: 86.36,\n status: 'stable',\n },\n ];\n\n const fetchProfitData = () => {\n setLoading(true);\n // 模拟API请求\n setTimeout(() => {\n setProfitData(mockProfitData);\n setAlerts(mockAlerts);\n setProductProfits(mockProductProfits);\n setLoading(false);\n }, 1000);\n };\n\n useEffect(() => {\n fetchProfitData();\n }, []);\n\n const handleProductChange = (value: string) => {\n setSelectedProduct(value);\n };\n\n const handleTimeRangeChange = (value: string) => {\n setTimeRange(value);\n };\n\n const handleRefresh = () => {\n fetchProfitData();\n };\n\n const columns = [\n {\n title: '商品ID',\n dataIndex: 'productId',\n key: 'productId',\n },\n {\n title: '商品名称',\n dataIndex: 'productName',\n key: 'productName',\n },\n {\n title: '当前利润',\n dataIndex: 'currentProfit',\n key: 'currentProfit',\n render: (text: number) => `¥${text}`,\n },\n {\n title: '变化率',\n dataIndex: 'change',\n key: 'change',\n render: (text: number) => (\n 0 ? '#52c41a' : text < 0 ? '#ff4d4f' : '#1890ff' }}>\n {text > 0 ? '+' : ''}{text}%\n \n ),\n },\n {\n title: 'ROI',\n dataIndex: 'roi',\n key: 'roi',\n render: (text: number) => `${text}%`,\n },\n {\n title: '状态',\n dataIndex: 'status',\n key: 'status',\n render: (status: string) => (\n \n ),\n },\n ];\n\n const alertColumns = [\n {\n title: '商品ID',\n dataIndex: 'productId',\n key: 'productId',\n },\n {\n title: '商品名称',\n dataIndex: 'productName',\n key: 'productName',\n },\n {\n title: '类型',\n dataIndex: 'type',\n key: 'type',\n },\n {\n title: '消息',\n dataIndex: 'message',\n key: 'message',\n },\n {\n title: '严重程度',\n dataIndex: 'severity',\n key: 'severity',\n render: (severity: string) => (\n \n ),\n },\n {\n title: '时间',\n dataIndex: 'date',\n key: 'date',\n },\n ];\n\n return (\n \n
\n 商品利润监控\n
\n \n \n \n \n \n \n \n \n \n \n \n \n
\n
\n\n {/* 利润概览 */}\n \n
\n \n sum + item.currentProfit, 0)}\n prefix=\"¥\"\n valueStyle={{ color: '#3f8600' }}\n />\n \n \n \n \n sum + item.roi, 0) / mockProductProfits.length}\n suffix=\"%\"\n valueStyle={{ color: '#3f8600' }}\n />\n \n \n \n \n }\n valueStyle={{ color: '#faad14' }}\n />\n \n \n \n \n }\n valueStyle={{ color: '#1890ff' }}\n />\n \n \n \n\n {/* 利润趋势图表 */}\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n {/* 商品利润列表 */}\n \n \n
\n \n \n\n {/* 利润预警 */}\n \n \n
\n \n \n \n \n );\n};\n\nexport default ProfitMonitor;", + "__isJSFile": true, + "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/Product/ProfitMonitor/index.tsx" + }, "AfterSales/CustomerService": { "path": "AfterSales/CustomerService", "id": "AfterSales/CustomerService", @@ -2083,6 +2155,24 @@ "__isJSFile": true, "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/Logistics/LogisticsSelect.tsx" }, + "Product/ROIAnalysis/index": { + "path": "Product/ROIAnalysis", + "id": "Product/ROIAnalysis/index", + "file": "Product/ROIAnalysis/index.tsx", + "absPath": "/Product/ROIAnalysis", + "__content": "import React, { useState, useEffect } from 'react';\r\nimport { Card, Layout, Typography, Row, Col, DatePicker, Select, Button, Table, Statistic, Spin, message } from 'antd';\r\nimport { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, LineChart, Line } from 'recharts';\r\nimport { ArrowUpOutlined, ArrowDownOutlined, ReloadOutlined } from '@ant-design/icons';\r\nimport { Link } from 'umi';\r\n\r\nconst { Content } = Layout;\r\nconst { Title, Text } = Typography;\r\nconst { RangePicker } = DatePicker;\r\nconst { Option } = Select;\r\n\r\ninterface ROIItem {\r\n id: string;\r\n productId: string;\r\n productName: string;\r\n cost: number;\r\n price: number;\r\n profit: number;\r\n roi: number;\r\n salesVolume: number;\r\n date: string;\r\n}\r\n\r\nconst ROIAnalysis: React.FC = () => {\r\n const [loading, setLoading] = useState(false);\r\n const [roiData, setRoiData] = useState([]);\r\n const [timeRange, setTimeRange] = useState(null);\r\n const [productId, setProductId] = useState('');\r\n const [summary, setSummary] = useState<{\r\n totalSales: number;\r\n totalProfit: number;\r\n averageROI: number;\r\n bestProduct: string;\r\n }>({\r\n totalSales: 0,\r\n totalProfit: 0,\r\n averageROI: 0,\r\n bestProduct: '',\r\n });\r\n\r\n const mockROIData: ROIItem[] = [\r\n {\r\n id: '1',\r\n productId: 'P001',\r\n productName: '智能手表',\r\n cost: 150,\r\n price: 299,\r\n profit: 149,\r\n roi: 99.33,\r\n salesVolume: 120,\r\n date: '2026-03-01',\r\n },\r\n {\r\n id: '2',\r\n productId: 'P001',\r\n productName: '智能手表',\r\n cost: 150,\r\n price: 299,\r\n profit: 149,\r\n roi: 99.33,\r\n salesVolume: 110,\r\n date: '2026-03-02',\r\n },\r\n {\r\n id: '3',\r\n productId: 'P001',\r\n productName: '智能手表',\r\n cost: 150,\r\n price: 299,\r\n profit: 149,\r\n roi: 99.33,\r\n salesVolume: 130,\r\n date: '2026-03-03',\r\n },\r\n {\r\n id: '4',\r\n productId: 'P002',\r\n productName: '无线耳机',\r\n cost: 80,\r\n price: 199,\r\n profit: 119,\r\n roi: 148.75,\r\n salesVolume: 200,\r\n date: '2026-03-01',\r\n },\r\n {\r\n id: '5',\r\n productId: 'P002',\r\n productName: '无线耳机',\r\n cost: 80,\r\n price: 199,\r\n profit: 119,\r\n roi: 148.75,\r\n salesVolume: 210,\r\n date: '2026-03-02',\r\n },\r\n {\r\n id: '6',\r\n productId: 'P002',\r\n productName: '无线耳机',\r\n cost: 80,\r\n price: 199,\r\n profit: 119,\r\n roi: 148.75,\r\n salesVolume: 190,\r\n date: '2026-03-03',\r\n },\r\n ];\r\n\r\n const fetchROIData = () => {\r\n setLoading(true);\r\n // 模拟API请求\r\n setTimeout(() => {\r\n setRoiData(mockROIData);\r\n // 计算汇总数据\r\n const totalSales = mockROIData.reduce((sum, item) => sum + item.salesVolume, 0);\r\n const totalProfit = mockROIData.reduce((sum, item) => sum + item.profit * item.salesVolume, 0);\r\n const averageROI = mockROIData.reduce((sum, item) => sum + item.roi, 0) / mockROIData.length;\r\n const bestProduct = mockROIData.reduce((best, current) => \r\n current.roi > best.roi ? current : best\r\n ).productName;\r\n\r\n setSummary({\r\n totalSales,\r\n totalProfit,\r\n averageROI: parseFloat(averageROI.toFixed(2)),\r\n bestProduct,\r\n });\r\n setLoading(false);\r\n }, 1000);\r\n };\r\n\r\n useEffect(() => {\r\n fetchROIData();\r\n }, []);\r\n\r\n const handleTimeRangeChange = (dates: any) => {\r\n setTimeRange(dates);\r\n };\r\n\r\n const handleProductChange = (value: string) => {\r\n setProductId(value);\r\n };\r\n\r\n const handleRefresh = () => {\r\n fetchROIData();\r\n };\r\n\r\n const columns = [\r\n {\r\n title: '商品ID',\r\n dataIndex: 'productId',\r\n key: 'productId',\r\n },\r\n {\r\n title: '商品名称',\r\n dataIndex: 'productName',\r\n key: 'productName',\r\n },\r\n {\r\n title: '成本',\r\n dataIndex: 'cost',\r\n key: 'cost',\r\n render: (text: number) => `¥${text}`,\r\n },\r\n {\r\n title: '售价',\r\n dataIndex: 'price',\r\n key: 'price',\r\n render: (text: number) => `¥${text}`,\r\n },\r\n {\r\n title: '利润',\r\n dataIndex: 'profit',\r\n key: 'profit',\r\n render: (text: number) => `¥${text}`,\r\n },\r\n {\r\n title: 'ROI',\r\n dataIndex: 'roi',\r\n key: 'roi',\r\n render: (text: number) => `${text}%`,\r\n },\r\n {\r\n title: '销量',\r\n dataIndex: 'salesVolume',\r\n key: 'salesVolume',\r\n },\r\n {\r\n title: '日期',\r\n dataIndex: 'date',\r\n key: 'date',\r\n },\r\n ];\r\n\r\n // 准备图表数据\r\n const chartData = mockROIData.map(item => ({\r\n date: item.date,\r\n 销量: item.salesVolume,\r\n 利润: item.profit * item.salesVolume,\r\n }));\r\n\r\n const roiTrendData = mockROIData.map(item => ({\r\n date: item.date,\r\n ROI: item.roi,\r\n }));\r\n\r\n return (\r\n \r\n
\r\n 商品ROI分析\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n\r\n {/* 汇总统计 */}\r\n \r\n
\r\n \r\n }\r\n suffix=\"件\"\r\n valueStyle={{ color: '#3f8600' }}\r\n />\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n {/* 图表区域 */}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n {/* 详细数据表格 */}\r\n \r\n
\r\n \r\n \r\n );\r\n};\r\n\r\nexport default ROIAnalysis;", + "__isJSFile": true, + "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/Product/ROIAnalysis/index.tsx" + }, + "Reports/PerformanceReport": { + "path": "Reports/PerformanceReport", + "id": "Reports/PerformanceReport", + "file": "Reports/PerformanceReport.tsx", + "absPath": "/Reports/PerformanceReport", + "__content": "import React, { useState, useEffect } from 'react';\nimport { Card, Row, Col, Select, DatePicker, Button, Table } from 'antd';\nimport { BarChart, Bar, LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';\nimport { DownloadOutlined, RefreshOutlined } from '@ant-design/icons';\n\nconst { Option } = Select;\nconst { RangePicker } = DatePicker;\n\ninterface PerformanceData {\n date: string;\n sales: number;\n orders: number;\n conversionRate: number;\n averageOrderValue: number;\n customers: number;\n}\n\ninterface ChannelPerformance {\n id: string;\n name: string;\n sales: number;\n orders: number;\n conversionRate: number;\n ctr: number;\n cpc: number;\n roi: number;\n}\n\nconst PerformanceReport: React.FC = () => {\n const [performanceData, setPerformanceData] = useState([]);\n const [channelPerformance, setChannelPerformance] = useState([]);\n const [loading, setLoading] = useState(false);\n const [timeRange, setTimeRange] = useState('month');\n const [dateRange, setDateRange] = useState(null);\n const [selectedChannel, setSelectedChannel] = useState('all');\n\n useEffect(() => {\n fetchPerformanceData();\n }, [timeRange, dateRange, selectedChannel]);\n\n const fetchPerformanceData = async () => {\n setLoading(true);\n // 模拟API调用\n setTimeout(() => {\n // 模拟绩效数据\n const mockPerformanceData: PerformanceData[] = Array.from({ length: 12 }, (_, i) => {\n const month = i + 1;\n const sales = Math.random() * 100000 + 50000;\n const orders = Math.random() * 500 + 100;\n const conversionRate = Math.random() * 5 + 2;\n const averageOrderValue = sales / orders;\n const customers = Math.random() * 300 + 50;\n return {\n date: `2026-${String(month).padStart(2, '0')}`,\n sales,\n orders,\n conversionRate,\n averageOrderValue,\n customers,\n };\n });\n\n // 模拟渠道绩效数据\n const mockChannelPerformance: ChannelPerformance[] = [\n {\n id: '1',\n name: 'Facebook',\n sales: 30000,\n orders: 150,\n conversionRate: 3.5,\n ctr: 2.5,\n cpc: 1.5,\n roi: 3.0,\n },\n {\n id: '2',\n name: 'Google',\n sales: 25000,\n orders: 125,\n conversionRate: 4.0,\n ctr: 1.8,\n cpc: 2.0,\n roi: 2.5,\n },\n {\n id: '3',\n name: 'Instagram',\n sales: 20000,\n orders: 100,\n conversionRate: 3.0,\n ctr: 3.0,\n cpc: 1.2,\n roi: 3.5,\n },\n {\n id: '4',\n name: 'TikTok',\n sales: 15000,\n orders: 75,\n conversionRate: 2.5,\n ctr: 4.0,\n cpc: 0.8,\n roi: 4.0,\n },\n ];\n\n setPerformanceData(mockPerformanceData);\n setChannelPerformance(mockChannelPerformance);\n setLoading(false);\n }, 500);\n };\n\n const handleExport = () => {\n // 模拟导出功能\n alert('报表已导出');\n };\n\n const columns = [\n {\n title: '渠道',\n dataIndex: 'name',\n key: 'name',\n },\n {\n title: '销售',\n dataIndex: 'sales',\n key: 'sales',\n render: (sales: number) => `$${sales.toFixed(2)}`,\n },\n {\n title: '订单数',\n dataIndex: 'orders',\n key: 'orders',\n },\n {\n title: '转化率',\n dataIndex: 'conversionRate',\n key: 'conversionRate',\n render: (rate: number) => `${rate.toFixed(2)}%`,\n },\n {\n title: '点击率',\n dataIndex: 'ctr',\n key: 'ctr',\n render: (rate: number) => `${rate.toFixed(2)}%`,\n },\n {\n title: '点击成本',\n dataIndex: 'cpc',\n key: 'cpc',\n render: (cpc: number) => `$${cpc.toFixed(2)}`,\n },\n {\n title: 'ROI',\n dataIndex: 'roi',\n key: 'roi',\n render: (roi: number) => `${roi.toFixed(2)}x`,\n },\n ];\n\n const totalSales = performanceData.reduce((sum, item) => sum + item.sales, 0);\n const totalOrders = performanceData.reduce((sum, item) => sum + item.orders, 0);\n const totalCustomers = performanceData.reduce((sum, item) => sum + item.customers, 0);\n const averageOrderValue = totalOrders > 0 ? totalSales / totalOrders : 0;\n const averageConversionRate = performanceData.length > 0 ? \n performanceData.reduce((sum, item) => sum + item.conversionRate, 0) / performanceData.length : 0;\n\n return (\n
\n
\n

绩效报表

\n }\n onClick={handleExport}\n >\n 导出\n \n
\n\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n }\n onClick={fetchPerformanceData}\n >\n 刷新\n \n
\n\n \n
\n \n

总销售

\n

${totalSales.toFixed(2)}

\n
\n \n
\n \n

总订单

\n

{totalOrders}

\n
\n \n
\n \n

平均订单价值

\n

${averageOrderValue.toFixed(2)}

\n
\n \n
\n \n

平均转化率

\n

{averageConversionRate.toFixed(2)}%

\n
\n \n \n\n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n );\n};\n\nexport default PerformanceReport;", + "__isJSFile": true, + "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/Reports/PerformanceReport.tsx" + }, "AfterSales/RefundProcess": { "path": "AfterSales/RefundProcess", "id": "AfterSales/RefundProcess", @@ -2110,6 +2200,42 @@ "__isJSFile": true, "__absFile": "D:/trae_projects/makemd/makemd/dashboard/src/pages/Logistics/LogisticsTrack.tsx" }, + "Settings/ProfileSettings": { + "path": "Settings/ProfileSettings", + "id": "Settings/ProfileSettings", + "file": "Settings/ProfileSettings.tsx", + "absPath": "/Settings/ProfileSettings", + "__content": "import React, { useState } from 'react';\nimport { Card, Form, Input, Button, Upload, Avatar, message } from 'antd';\nimport { UserOutlined, SaveOutlined, ArrowLeftOutlined } from '@ant-design/icons';\nimport { useNavigate } from 'react-router-dom';\n\nconst { TextArea } = Input;\n\ninterface ProfileData {\n name: string;\n email: string;\n phone: string;\n position: string;\n department: string;\n bio: string;\n avatar: string;\n}\n\nconst ProfileSettings: React.FC = () => {\n const navigate = useNavigate();\n const [loading, setLoading] = useState(false);\n const [form] = Form.useForm();\n const [avatar, setAvatar] = useState('https://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50');\n\n const initialProfile: ProfileData = {\n name: 'John Doe',\n email: 'john.doe@example.com',\n phone: '+1 (123) 456-7890',\n position: 'Product Manager',\n department: 'Marketing',\n bio: 'Product manager with 5 years of experience in e-commerce.',\n avatar: 'https://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50',\n };\n\n const handleSubmit = async (values: any) => {\n setLoading(true);\n // 模拟API调用\n setTimeout(() => {\n message.success('个人设置已更新');\n setLoading(false);\n }, 1000);\n };\n\n const handleBack = () => {\n navigate('/settings');\n };\n\n const handleAvatarChange = (info: any) => {\n if (info.file.status === 'done') {\n // 模拟上传成功\n setAvatar('https://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50');\n message.success('头像上传成功');\n } else if (info.file.status === 'error') {\n message.error('头像上传失败');\n }\n };\n\n return (\n
\n
\n

个人设置

\n }\n onClick={handleBack}\n >\n 返回\n \n
\n\n \n \n
\n \n } src={avatar} />\n \n
\n

点击头像上传新的头像

\n

支持 JPG, PNG 格式,最大 2MB

\n
\n
\n\n
\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n
\n\n \n