@appthen/cli 1.2.10 → 1.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitignore +1 -0
- package/bin/main.js +92 -0
- package/dist/index.js +7014 -14988
- package/package.json +8 -1
- package/tests/test-app/.appthen/shadow-space-100001-test-app-e99876b1.json +1862 -0
- package/tests/test-app/.appthen/space-config.json +8 -0
- package/tests/test-app/docs/AI-Workflow.flow +112 -0
- package/tests/test-app/docs/Logic-1.flow +16 -0
- package/tests/test-app/docs/Logic.flow +16 -0
- package/tests/test-app/docs/Project-Blueprint-1.flow +119 -0
- package/tests/test-app/docs/Project-Blueprint.flow +119 -0
- package/tests/test-app/docs/README.md +3 -0
- package/tests/test-app/docs/claude.md +194 -0
- package/tests/test-app/docs/page_requirement_analysis.md +149 -0
- package/tests/test-app/docs//345/267/245/345/215/225/347/256/241/347/220/206/347/263/273/347/273/237/350/257/246/347/273/206/350/256/276/350/256/241.md +377 -0
- package/tests/test-app/src/apis/AddTodoPost.api.ts +42 -0
- package/tests/test-app/src/apis/DeleteTodoPost.api.ts +32 -0
- package/tests/test-app/src/apis/GetListPost.api.ts +38 -0
- package/tests/test-app/src/apis/TicketAttachmentUploadPost.api.ts +42 -0
- package/tests/test-app/src/apis/UpdateTodoPost.api.ts +46 -0
- package/tests/test-app/src/app.css +15 -0
- package/tests/test-app/src/cloud_functions/ticket|attachment|upload.node.ts +86 -0
- package/tests/test-app/src/cloud_functions/ticket|comment|add.node.ts +65 -0
- package/tests/test-app/src/cloud_functions/types|entity|Ticket.node.ts +88 -0
- package/tests/test-app/src/cloud_functions/types|entity|TicketAttachment.node.ts +70 -0
- package/tests/test-app/src/cloud_functions/types|entity|TicketCategory.node.ts +56 -0
- package/tests/test-app/src/cloud_functions/types|entity|TicketComment.node.ts +62 -0
- package/tests/test-app/src/cloud_functions/types|entity|TicketHistory.node.ts +74 -0
- package/tests/test-app/src/cloud_functions/types|entity|TicketPriority.node.ts +68 -0
- package/tests/test-app/src/cloud_functions/types|entity|TicketStatus.node.ts +63 -0
- package/tests/test-app/src/cloud_functions/types|models|CreateTicketParams.node.ts +20 -0
- package/tests/test-app/src/cloud_functions/types|models|TicketListParams.node.ts +30 -0
- package/tests/test-app/src/cloud_functions/types|models|UpdateTicketParams.node.ts +22 -0
- package/tests/test-app/src/components/Button.js +11 -0
- package/tests/test-app/src/components/MessageCenter.tsx +506 -0
- package/tests/test-app/src/components/MouduleDemoNzp.tsx +40 -0
- package/tests/test-app/src/components/Timeline.tsx +145 -0
- package/tests/test-app/src/index.ts +2 -0
- package/tests/test-app/src/modules/work_order_module/apis/TicketCommentAddPost.api.ts +48 -0
- package/tests/test-app/src/modules/work_order_module/apis/TicketCreatePost.api.ts +52 -0
- package/tests/test-app/src/modules/work_order_module/apis/TicketDeleteDelete.api.ts +39 -0
- package/tests/test-app/src/modules/work_order_module/apis/TicketDetailGet.api.ts +39 -0
- package/tests/test-app/src/modules/work_order_module/apis/TicketListGet.api.ts +61 -0
- package/tests/test-app/src/modules/work_order_module/apis/TicketUpdatePut.api.ts +57 -0
- package/tests/test-app/src/modules/work_order_module/apis/TrainDoorFaultListGet.ts +76 -0
- package/tests/test-app/src/modules/work_order_module/apis/TrainDoorListGet.ts +76 -0
- package/tests/test-app/src/modules/work_order_module/apis/TrainDoorOperationRecordsGet.ts +284 -0
- package/tests/test-app/src/modules/work_order_module/apis/TrainDoorStatisticsGet.ts +96 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/category|list.node.ts +40 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/priority|list.node.ts +26 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/status|list.node.ts +26 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|create.node.ts +54 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|delete.node.ts +55 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|detail.node.ts +65 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|list.node.ts +85 -0
- package/tests/test-app/src/modules/work_order_module/cloud_function/ticket|update.node.ts +73 -0
- package/tests/test-app/src/modules/work_order_module/data_model/Ticket.m.ts +85 -0
- package/tests/test-app/src/modules/work_order_module/data_model/TicketCategory.m.ts +53 -0
- package/tests/test-app/src/modules/work_order_module/data_model/TicketStatus.m.ts +60 -0
- package/tests/test-app/src/modules/work_order_module//345/267/245/345/215/225/347/263/273/347/273/237/344/272/247/345/223/201/350/256/276/350/256/241/346/226/207/346/241/243.md +301 -0
- package/tests/test-app/src/modules/work_order_module//345/267/245/345/215/225/347/263/273/347/273/237/345/274/200/345/217/221/344/273/273/345/212/241/345/210/206/345/267/245/346/226/207/346/241/243.md +345 -0
- package/tests/test-app/src/pages/CustomerManagement.tsx +535 -0
- package/tests/test-app/src/pages/CyberpunkDashboard.tsx +348 -0
- package/tests/test-app/src/pages/CyberpunkProductManagement.tsx +637 -0
- package/tests/test-app/src/pages/CyberpunkUserList.tsx +316 -0
- package/tests/test-app/src/pages/DashboardV2.tsx +334 -0
- package/tests/test-app/src/pages/DataReport.tsx +298 -0
- package/tests/test-app/src/pages/DataStatistics.tsx +317 -0
- package/tests/test-app/src/pages/DepartmentManagement.tsx +503 -0
- package/tests/test-app/src/pages/FileExplorer.tsx +441 -0
- package/tests/test-app/src/pages/OrderDetail.tsx +393 -0
- package/tests/test-app/src/pages/ProductManagement.tsx +521 -0
- package/tests/test-app/src/pages/ProjectTimeline.tsx +395 -0
- package/tests/test-app/src/pages/RoleManagement.tsx +523 -0
- package/tests/test-app/src/pages/SLAManagement.tsx +668 -0
- package/tests/test-app/src/pages/StaticCyberpunkDashboard.tsx +462 -0
- package/tests/test-app/src/pages/StaticCyberpunkUserList.tsx +567 -0
- package/tests/test-app/src/pages/StudentWeaknessList.tsx +547 -0
- package/tests/test-app/src/pages/SystemSettings.tsx +422 -0
- package/tests/test-app/src/pages/TaskManagement.tsx +467 -0
- package/tests/test-app/src/pages/TicketCreate.tsx +27 -0
- package/tests/test-app/src/pages/TicketDetail.tsx +27 -0
- package/tests/test-app/src/pages/TicketList.tsx +27 -0
- package/tests/test-app/src/pages/TicketManagement.tsx +402 -0
- package/tests/test-app/src/pages/TicketManagementPage.tsx +1238 -0
- package/tests/test-app/src/pages/UserProfile.tsx +404 -0
- package/tests/test-app/src/pages/VisualAIIDEUpgrade.tsx +245 -0
- package/tests/test-app/src/pages/WorkflowDesigner.tsx +434 -0
- package/tests/test-app/src/pages/admin/dashboard.tsx +591 -0
- package/tests/test-app/src/pages/appthen_guide/ComponentTreeUnderstanding.tsx +26 -0
- package/tests/test-app/src/pages/appthen_guide/DataBindingLearning.tsx +26 -0
- package/tests/test-app/src/pages/article-list.tsx +222 -0
- package/tests/test-app/src/pages/babyProductRecommendationPage.tsx +168 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout.tsx +155 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout10.tsx +157 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout2.tsx +156 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout3.tsx +156 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout4.tsx +157 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout5.tsx +157 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout6.tsx +157 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout7.tsx +157 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout8.tsx +157 -0
- package/tests/test-app/src/pages/back-end/adminRootLayout9.tsx +157 -0
- package/tests/test-app/src/pages/back-end/backgroundManagementSystem.css +5 -0
- package/tests/test-app/src/pages/back-end/backgroundManagementSystem.tsx +1745 -0
- package/tests/test-app/src/pages/category-list.tsx +179 -0
- package/tests/test-app/src/pages/comment-list.tsx +194 -0
- package/tests/test-app/src/pages/component/WorkOrderCard.tsx +140 -0
- package/tests/test-app/src/pages/cover.tsx +42 -0
- package/tests/test-app/src/pages/cyberpunk/cyberpunkCRMPage.tsx +1299 -0
- package/tests/test-app/src/pages/data-analytics.tsx +1872 -0
- package/tests/test-app/src/pages/data-overview.tsx +600 -0
- package/tests/test-app/src/pages/data_dashboard/blueBrightGreenTechnologyWind.css +181 -0
- package/tests/test-app/src/pages/data_dashboard/blueBrightGreenTechnologyWind.tsx +225 -0
- package/tests/test-app/src/pages/data_dashboard/blueLargeScreen.css +181 -0
- package/tests/test-app/src/pages/data_dashboard/blueLargeScreen.tsx +138 -0
- package/tests/test-app/src/pages/data_dashboard/component_library/BlueBrightGreenBorder.tsx +47 -0
- package/tests/test-app/src/pages/data_dashboard/component_library/FullScreenContainer.tsx +133 -0
- package/tests/test-app/src/pages/demo-error-page.tsx +119 -0
- package/tests/test-app/src/pages/department-list.tsx +183 -0
- package/tests/test-app/src/pages/description_of_mock_interface.md +32 -0
- package/tests/test-app/src/pages/digitalLargeScreen.css +181 -0
- package/tests/test-app/src/pages/digitalLargeScreen.tsx +1417 -0
- package/tests/test-app/src/pages/goods-list.tsx +233 -0
- package/tests/test-app/src/pages/housekeeping/adminDashboardPage.tsx +880 -0
- package/tests/test-app/src/pages/mobile_terminal/PersonalCenter.css +3 -0
- package/tests/test-app/src/pages/mobile_terminal/PersonalCenter.tsx +362 -0
- package/tests/test-app/src/pages/mobile_terminal/WorkOrderHomepage.tsx +337 -0
- package/tests/test-app/src/pages/mobile_terminal/newWorkOrder.tsx +224 -0
- package/tests/test-app/src/pages/mobile_terminal/tabbar.tsx +67 -0
- package/tests/test-app/src/pages/mobile_terminal/uiHandsOnPractice.tsx +638 -0
- package/tests/test-app/src/pages/mobile_terminal/workOrderDetails.tsx +346 -0
- package/tests/test-app/src/pages/mobile_terminal/workOrderPage.tsx +345 -0
- package/tests/test-app/src/pages/notice-list.tsx +217 -0
- package/tests/test-app/src/pages/order-detail.tsx +330 -0
- package/tests/test-app/src/pages/order-list.tsx +195 -0
- package/tests/test-app/src/pages/order-management.tsx +563 -0
- package/tests/test-app/src/pages/page/OrderList.tsx +230 -0
- package/tests/test-app/src/pages/role-list.tsx +184 -0
- package/tests/test-app/src/pages/simple/simplePage.tsx +92 -0
- package/tests/test-app/src/pages/simple-page.tsx +43 -0
- package/tests/test-app/src/pages/test-destructure.tsx +44 -0
- package/tests/test-app/src/pages/test-error-page.tsx +75 -0
- package/tests/test-app/src/pages/test-page-with-errors.tsx +51 -0
- package/tests/test-app/src/pages/test-page.tsx +101 -0
- package/tests/test-app/src/pages/test-render.tsx +52 -0
- package/tests/test-app/src/pages/test-return-type.tsx +41 -0
- package/tests/test-app/src/pages/test-type-assertion.tsx +37 -0
- package/tests/test-app/src/pages/testPage.css +3 -0
- package/tests/test-app/src/pages/testPage.tsx +158 -0
- package/tests/test-app/src/pages/ui/styleSelectorPage.tsx +1554 -0
- package/tests/test-app/src/pages/user-list.tsx +212 -0
- package/tests/test-app/src/pages/web_version/website.css +205 -0
- package/tests/test-app/src/pages/web_version/website.tsx +1066 -0
- package/tests/test-app/src/pages/wrong-page.tsx +50 -0
- package/tests/test-app/src/pages//345/276/205/345/212/236.apidoc.json +336 -0
- package/tests/test-app/src/project.json +1120 -0
- package/tests/test-app/src/store/global.store.ts +10 -0
- package/tests/test-app/src/types/CreateTicketParams.m.ts +20 -0
- package/tests/test-app/src/types/SLAPolicy.ts +50 -0
- package/tests/test-app/src/types/Ticket.ts +68 -0
- package/tests/test-app/src/types/TicketAttachment.m.ts +67 -0
- package/tests/test-app/src/types/TicketComment.m.ts +59 -0
- package/tests/test-app/src/types/TicketEvaluation.ts +44 -0
- package/tests/test-app/src/types/TicketHistory.m.ts +71 -0
- package/tests/test-app/src/types/TicketListParams.m.ts +30 -0
- package/tests/test-app/src/types/TicketPriority.m.ts +65 -0
- package/tests/test-app/src/types/TicketRecord.ts +47 -0
- package/tests/test-app/src/types/TrainDoor.ts +284 -0
- package/tests/test-app/src/types/UpdateTicketParams.m.ts +22 -0
- package/tests/test-app/src/utils/__afterRequest.util.ts +3 -0
- package/tests/test-app/src/utils/__beforeRequest.util.ts +10 -0
- package/tests/test-app/src/utils/testGlobalAction.util.ts +7 -0
|
@@ -0,0 +1,1872 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 企业级数据分析平台2
|
|
3
|
+
* 提供全面的数据分析、实时监控和智能洞察
|
|
4
|
+
*
|
|
5
|
+
* @type Page
|
|
6
|
+
* @route /data-analytics
|
|
7
|
+
* @screen 1920w
|
|
8
|
+
* @frames web
|
|
9
|
+
*/
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import { Page, Text, View } from '@appthen/react';
|
|
12
|
+
import { Col, Row, Tabs, Tag } from '@appthen/antd';
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class IProps {
|
|
16
|
+
autoRefresh?: boolean;
|
|
17
|
+
refreshInterval?: number;
|
|
18
|
+
defaultTab?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
* 数据与接口请求定义
|
|
23
|
+
*/
|
|
24
|
+
class IState {
|
|
25
|
+
/* 当前选中的标签页 */
|
|
26
|
+
activeTab?: string;
|
|
27
|
+
/* 选中的时间范围 */
|
|
28
|
+
timeRange?: string;
|
|
29
|
+
/* 选中的地区 */
|
|
30
|
+
selectedRegion?: string;
|
|
31
|
+
/* 选中的产品类别 */
|
|
32
|
+
selectedCategory?: string;
|
|
33
|
+
/* 总销售额 */
|
|
34
|
+
totalSales?: number;
|
|
35
|
+
/* 今日访问 */
|
|
36
|
+
todayVisits?: number;
|
|
37
|
+
/* 新增用户 */
|
|
38
|
+
newUsers?: number;
|
|
39
|
+
/* 转化率 */
|
|
40
|
+
conversionRate?: number;
|
|
41
|
+
/* 平均客单价 */
|
|
42
|
+
avgOrderValue?: number;
|
|
43
|
+
/* 完成订单 */
|
|
44
|
+
completedOrders?: number;
|
|
45
|
+
/* 退款率 */
|
|
46
|
+
refundRate?: number;
|
|
47
|
+
/* 客户满意度 */
|
|
48
|
+
satisfactionRate?: number;
|
|
49
|
+
/* 复购率 */
|
|
50
|
+
repurchaseRate?: number;
|
|
51
|
+
/* 平均订单时长 */
|
|
52
|
+
avgOrderTime?: number;
|
|
53
|
+
/* 客户留存率 */
|
|
54
|
+
retentionRate?: number;
|
|
55
|
+
/* 月度销售数据 */
|
|
56
|
+
monthlySales?: any[];
|
|
57
|
+
/* 分类销售占比 */
|
|
58
|
+
categorySales?: {
|
|
59
|
+
/* @example 电子产品 */name?: string,
|
|
60
|
+
/* @example 38 */value?: number,
|
|
61
|
+
/* @example #3b82f6 */color?: string,
|
|
62
|
+
/* @example 📱 */icon?: string,
|
|
63
|
+
/* @example 1845670 */sales?: number,
|
|
64
|
+
}[];
|
|
65
|
+
/* 渠道流量 */
|
|
66
|
+
channelTraffic?: {
|
|
67
|
+
/* @example 直接访问 */name?: string,
|
|
68
|
+
/* @example 35 */value?: number,
|
|
69
|
+
/* @example #6366f1 */color?: string,
|
|
70
|
+
/* @example 99960 */visits?: number,
|
|
71
|
+
/* @example 6.8 */conversion?: number,
|
|
72
|
+
}[];
|
|
73
|
+
/* 热门地区 */
|
|
74
|
+
hotRegions?: {
|
|
75
|
+
/* @example 广东省 */name?: string,
|
|
76
|
+
/* @example 4580 */value?: number,
|
|
77
|
+
/* @example 22.5 */percentage?: number,
|
|
78
|
+
/* @example 15.2 */growth?: number,
|
|
79
|
+
cities?: string[],
|
|
80
|
+
}[];
|
|
81
|
+
/* 活跃时段 */
|
|
82
|
+
activeHours?: {
|
|
83
|
+
/* @example 0-2 */hour?: string,
|
|
84
|
+
/* @example 420 */value?: number,
|
|
85
|
+
/* @example 85 */orders?: number,
|
|
86
|
+
}[];
|
|
87
|
+
/* 最新活动 */
|
|
88
|
+
recentActivities?: {
|
|
89
|
+
/* @example order */type?: string,
|
|
90
|
+
/* @example 用户 38562 */user?: string,
|
|
91
|
+
/* @example 完成了一笔订单 */action?: string,
|
|
92
|
+
/* @example ¥12,580 */amount?: string,
|
|
93
|
+
/* @example 1分钟前 */time?: string,
|
|
94
|
+
/* @example iPhone 15 Pro ×1 */detail?: string,
|
|
95
|
+
}[];
|
|
96
|
+
/* 用户年龄段 */
|
|
97
|
+
userAgeDistribution?: {
|
|
98
|
+
/* @example 18-24 */range?: string,
|
|
99
|
+
/* @example 28 */value?: number,
|
|
100
|
+
/* @example #3b82f6 */color?: string,
|
|
101
|
+
}[];
|
|
102
|
+
/* 用户性别分布 */
|
|
103
|
+
userGenderDistribution?: {
|
|
104
|
+
/* @example 58 */male?: number,
|
|
105
|
+
/* @example 42 */female?: number,
|
|
106
|
+
};
|
|
107
|
+
/* 用户设备分布 */
|
|
108
|
+
userDeviceDistribution?: {
|
|
109
|
+
/* @example 手机 */name?: string,
|
|
110
|
+
/* @example 65 */value?: number,
|
|
111
|
+
/* @example #3b82f6 */color?: string,
|
|
112
|
+
}[];
|
|
113
|
+
/* 产品库存 */
|
|
114
|
+
productInventory?: {
|
|
115
|
+
/* @example iPhone 15 Pro */name?: string,
|
|
116
|
+
/* @example 2580 */stock?: number,
|
|
117
|
+
/* @example 1580 */sales?: number,
|
|
118
|
+
/* @example normal */status?: string,
|
|
119
|
+
}[];
|
|
120
|
+
/* 供应商表现 */
|
|
121
|
+
supplierPerformance?: {
|
|
122
|
+
/* @example 苹果官方 */name?: string,
|
|
123
|
+
/* @example 5680 */orders?: number,
|
|
124
|
+
/* @example 98.5 */onTime?: number,
|
|
125
|
+
/* @example 95 */score?: number,
|
|
126
|
+
/* @example excellent */status?: string,
|
|
127
|
+
}[];
|
|
128
|
+
/* 营销活动效果 */
|
|
129
|
+
marketingCampaigns?: {
|
|
130
|
+
/* @example 618大促 */name?: string,
|
|
131
|
+
/* @example 500000 */budget?: number,
|
|
132
|
+
/* @example 485000 */spent?: number,
|
|
133
|
+
/* @example 4.2 */roi?: number,
|
|
134
|
+
/* @example 12850 */conversions?: number,
|
|
135
|
+
/* @example active */status?: string,
|
|
136
|
+
}[];
|
|
137
|
+
/* 客服数据 */
|
|
138
|
+
customerService?: {
|
|
139
|
+
/* @example 856 */totalTickets?: number,
|
|
140
|
+
/* @example 728 */resolved?: number,
|
|
141
|
+
/* @example 95 */pending?: number,
|
|
142
|
+
/* @example 3.2 */avgResponseTime?: number,
|
|
143
|
+
/* @example 96.5 */satisfaction?: number,
|
|
144
|
+
};
|
|
145
|
+
/* 物流数据 */
|
|
146
|
+
logisticsData?: {
|
|
147
|
+
/* @example 顺丰速运 */name?: string,
|
|
148
|
+
/* @example 4580 */orders?: number,
|
|
149
|
+
/* @example 1.2 */avgTime?: number,
|
|
150
|
+
/* @example 98.5 */satisfaction?: number,
|
|
151
|
+
/* @example 99.2 */onTime?: number,
|
|
152
|
+
}[];
|
|
153
|
+
/* 风险预警 */
|
|
154
|
+
riskAlerts?: {
|
|
155
|
+
/* @example critical */type?: string,
|
|
156
|
+
/* @example 库存预警 */title?: string,
|
|
157
|
+
/* @example MacBook Pro 库存低于安全线(45台) */message?: string,
|
|
158
|
+
/* @example 刚刚 */time?: string,
|
|
159
|
+
}[];
|
|
160
|
+
/* 员工绩效 */
|
|
161
|
+
employeePerformance?: {
|
|
162
|
+
/* @example 张经理 */name?: string,
|
|
163
|
+
/* @example 销售一部 */team?: string,
|
|
164
|
+
/* @example 856000 */sales?: number,
|
|
165
|
+
/* @example 800000 */target?: number,
|
|
166
|
+
/* @example 107 */rate?: number,
|
|
167
|
+
}[];
|
|
168
|
+
/* 实时订单 */
|
|
169
|
+
realtimeOrders?: {
|
|
170
|
+
/* @example ORD-2024-1218-001 */id?: string,
|
|
171
|
+
/* @example 张** */user?: string,
|
|
172
|
+
/* @example 12999 */amount?: number,
|
|
173
|
+
/* @example 刚刚 */time?: string,
|
|
174
|
+
/* @example 广东省 */region?: string,
|
|
175
|
+
}[];
|
|
176
|
+
/* 热门搜索词 */
|
|
177
|
+
hotSearchKeywords?: {
|
|
178
|
+
/* @example iPhone 15 Pro */keyword?: string,
|
|
179
|
+
/* @example 15280 */searches?: number,
|
|
180
|
+
/* @example 25.6 */growth?: number,
|
|
181
|
+
}[];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
class Document extends React.Component<IProps, IState> {
|
|
185
|
+
state = {
|
|
186
|
+
activeTab: 'overview',
|
|
187
|
+
timeRange: 'today',
|
|
188
|
+
selectedRegion: 'all',
|
|
189
|
+
selectedCategory: 'all',
|
|
190
|
+
totalSales: 4856780,
|
|
191
|
+
todayVisits: 28560,
|
|
192
|
+
newUsers: 1856,
|
|
193
|
+
conversionRate: 5.8,
|
|
194
|
+
avgOrderValue: 458,
|
|
195
|
+
completedOrders: 10580,
|
|
196
|
+
refundRate: 1.8,
|
|
197
|
+
satisfactionRate: 97.2,
|
|
198
|
+
repurchaseRate: 42.5,
|
|
199
|
+
avgOrderTime: 3.2,
|
|
200
|
+
retentionRate: 78.5,
|
|
201
|
+
monthlySales: [
|
|
202
|
+
{ month: '1月', sales: 285000, target: 250000, growth: 12.5 },
|
|
203
|
+
{ month: '2月', sales: 323000, target: 250000, growth: 13.4 },
|
|
204
|
+
{ month: '3月', sales: 378000, target: 300000, growth: 17.2 },
|
|
205
|
+
{ month: '4月', sales: 345000, target: 300000, growth: -8.7 },
|
|
206
|
+
{ month: '5月', sales: 412000, target: 350000, growth: 19.4 },
|
|
207
|
+
{ month: '6月', sales: 456000, target: 400000, growth: 10.7 },
|
|
208
|
+
{ month: '7月', sales: 498000, target: 450000, growth: 9.2 },
|
|
209
|
+
{ month: '8月', sales: 525000, target: 450000, growth: 5.4 },
|
|
210
|
+
{ month: '9月', sales: 468000, target: 450000, growth: -10.9 },
|
|
211
|
+
{ month: '10月', sales: 489000, target: 450000, growth: 4.5 },
|
|
212
|
+
{ month: '11月', sales: 556000, target: 500000, growth: 13.7 },
|
|
213
|
+
{ month: '12月', sales: 612000, target: 600000, growth: 10.1 },
|
|
214
|
+
],
|
|
215
|
+
categorySales: [
|
|
216
|
+
{
|
|
217
|
+
name: '电子产品',
|
|
218
|
+
value: 38,
|
|
219
|
+
color: '#3b82f6',
|
|
220
|
+
icon: '📱',
|
|
221
|
+
sales: 1845670,
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
name: '服装服饰',
|
|
225
|
+
value: 26,
|
|
226
|
+
color: '#10b981',
|
|
227
|
+
icon: '👕',
|
|
228
|
+
sales: 1262763,
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
name: '家居生活',
|
|
232
|
+
value: 18,
|
|
233
|
+
color: '#f59e0b',
|
|
234
|
+
icon: '🏠',
|
|
235
|
+
sales: 874220,
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
name: '美妆个护',
|
|
239
|
+
value: 12,
|
|
240
|
+
color: '#ec4899',
|
|
241
|
+
icon: '💄',
|
|
242
|
+
sales: 582814,
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
name: '食品饮料',
|
|
246
|
+
value: 4,
|
|
247
|
+
color: '#ef4444',
|
|
248
|
+
icon: '🍔',
|
|
249
|
+
sales: 194271,
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: '运动户外',
|
|
253
|
+
value: 2,
|
|
254
|
+
color: '#8b5cf6',
|
|
255
|
+
icon: '🏃',
|
|
256
|
+
sales: 97135,
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
channelTraffic: [
|
|
260
|
+
{
|
|
261
|
+
name: '直接访问',
|
|
262
|
+
value: 35,
|
|
263
|
+
color: '#6366f1',
|
|
264
|
+
visits: 99960,
|
|
265
|
+
conversion: 6.8,
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
name: '搜索引擎',
|
|
269
|
+
value: 32,
|
|
270
|
+
color: '#ec4899',
|
|
271
|
+
visits: 91392,
|
|
272
|
+
conversion: 5.2,
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
name: '社交媒体',
|
|
276
|
+
value: 18,
|
|
277
|
+
color: '#14b8a6',
|
|
278
|
+
visits: 51408,
|
|
279
|
+
conversion: 4.8,
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
name: '广告投放',
|
|
283
|
+
value: 10,
|
|
284
|
+
color: '#f97316',
|
|
285
|
+
visits: 28560,
|
|
286
|
+
conversion: 5.5,
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
name: '邮件营销',
|
|
290
|
+
value: 3,
|
|
291
|
+
color: '#84cc16',
|
|
292
|
+
visits: 8568,
|
|
293
|
+
conversion: 8.2,
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
name: '其他',
|
|
297
|
+
value: 2,
|
|
298
|
+
color: '#06b6d4',
|
|
299
|
+
visits: 5712,
|
|
300
|
+
conversion: 3.5,
|
|
301
|
+
},
|
|
302
|
+
],
|
|
303
|
+
hotRegions: [
|
|
304
|
+
{
|
|
305
|
+
name: '广东省',
|
|
306
|
+
value: 4580,
|
|
307
|
+
percentage: 22.5,
|
|
308
|
+
growth: 15.2,
|
|
309
|
+
cities: ['广州', '深圳', '东莞'],
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
name: '浙江省',
|
|
313
|
+
value: 3860,
|
|
314
|
+
percentage: 17.2,
|
|
315
|
+
growth: 12.8,
|
|
316
|
+
cities: ['杭州', '宁波', '温州'],
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
name: '江苏省',
|
|
320
|
+
value: 3280,
|
|
321
|
+
percentage: 15.1,
|
|
322
|
+
growth: 10.5,
|
|
323
|
+
cities: ['南京', '苏州', '无锡'],
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
name: '北京市',
|
|
327
|
+
value: 2560,
|
|
328
|
+
percentage: 12.3,
|
|
329
|
+
growth: 8.7,
|
|
330
|
+
cities: ['北京市'],
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
name: '上海市',
|
|
334
|
+
value: 2420,
|
|
335
|
+
percentage: 11.2,
|
|
336
|
+
growth: 9.2,
|
|
337
|
+
cities: ['上海市'],
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
name: '四川省',
|
|
341
|
+
value: 1850,
|
|
342
|
+
percentage: 8.5,
|
|
343
|
+
growth: 18.5,
|
|
344
|
+
cities: ['成都', '绵阳'],
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
name: '湖北省',
|
|
348
|
+
value: 1520,
|
|
349
|
+
percentage: 6.2,
|
|
350
|
+
growth: 11.3,
|
|
351
|
+
cities: ['武汉', '宜昌'],
|
|
352
|
+
},
|
|
353
|
+
],
|
|
354
|
+
activeHours: [
|
|
355
|
+
{ hour: '0-2', value: 420, orders: 85 },
|
|
356
|
+
{ hour: '2-4', value: 280, orders: 56 },
|
|
357
|
+
{ hour: '4-6', value: 250, orders: 48 },
|
|
358
|
+
{ hour: '6-8', value: 680, orders: 135 },
|
|
359
|
+
{ hour: '8-10', value: 2850, orders: 586 },
|
|
360
|
+
{ hour: '10-12', value: 3680, orders: 742 },
|
|
361
|
+
{ hour: '12-14', value: 2850, orders: 586 },
|
|
362
|
+
{ hour: '14-16', value: 3250, orders: 665 },
|
|
363
|
+
{ hour: '16-18', value: 3850, orders: 780 },
|
|
364
|
+
{ hour: '18-20', value: 4580, orders: 928 },
|
|
365
|
+
{ hour: '20-22', value: 3850, orders: 785 },
|
|
366
|
+
{ hour: '22-24', value: 1280, orders: 265 },
|
|
367
|
+
],
|
|
368
|
+
recentActivities: [
|
|
369
|
+
{
|
|
370
|
+
type: 'order',
|
|
371
|
+
user: '用户 38562',
|
|
372
|
+
action: '完成了一笔订单',
|
|
373
|
+
amount: '¥12,580',
|
|
374
|
+
time: '1分钟前',
|
|
375
|
+
detail: 'iPhone 15 Pro ×1',
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
type: 'register',
|
|
379
|
+
user: '新用户',
|
|
380
|
+
action: '注册成功',
|
|
381
|
+
amount: '-',
|
|
382
|
+
time: '3分钟前',
|
|
383
|
+
detail: '来自微信',
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
type: 'refund',
|
|
387
|
+
user: '用户 28234',
|
|
388
|
+
action: '申请退款',
|
|
389
|
+
amount: '¥2,980',
|
|
390
|
+
time: '5分钟前',
|
|
391
|
+
detail: 'AirPods Pro',
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
type: 'review',
|
|
395
|
+
user: '用户 56921',
|
|
396
|
+
action: '发布了评价',
|
|
397
|
+
amount: '⭐⭐⭐⭐⭐',
|
|
398
|
+
time: '8分钟前',
|
|
399
|
+
detail: 'MacBook Air M2',
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
type: 'order',
|
|
403
|
+
user: '用户 78123',
|
|
404
|
+
action: '完成了一笔订单',
|
|
405
|
+
amount: '¥8,950',
|
|
406
|
+
time: '10分钟前',
|
|
407
|
+
detail: 'iPad Air ×1',
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
type: 'return',
|
|
411
|
+
user: '用户 45678',
|
|
412
|
+
action: '申请退货',
|
|
413
|
+
amount: '¥15,990',
|
|
414
|
+
time: '12分钟前',
|
|
415
|
+
detail: 'MacBook Pro',
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
type: 'order',
|
|
419
|
+
user: '用户 23456',
|
|
420
|
+
action: '完成了一笔订单',
|
|
421
|
+
amount: '¥3,280',
|
|
422
|
+
time: '15分钟前',
|
|
423
|
+
detail: 'Apple Watch ×1',
|
|
424
|
+
},
|
|
425
|
+
],
|
|
426
|
+
userAgeDistribution: [
|
|
427
|
+
{ range: '18-24', value: 28, color: '#3b82f6' },
|
|
428
|
+
{ range: '25-34', value: 35, color: '#10b981' },
|
|
429
|
+
{ range: '35-44', value: 22, color: '#f59e0b' },
|
|
430
|
+
{ range: '45-54', value: 10, color: '#ef4444' },
|
|
431
|
+
{ range: '55+', value: 5, color: '#8b5cf6' },
|
|
432
|
+
],
|
|
433
|
+
userGenderDistribution: { male: 58, female: 42 },
|
|
434
|
+
userDeviceDistribution: [
|
|
435
|
+
{ name: '手机', value: 65, color: '#3b82f6' },
|
|
436
|
+
{ name: '平板', value: 18, color: '#10b981' },
|
|
437
|
+
{ name: '电脑', value: 15, color: '#f59e0b' },
|
|
438
|
+
{ name: '其他', value: 2, color: '#ef4444' },
|
|
439
|
+
],
|
|
440
|
+
productInventory: [
|
|
441
|
+
{ name: 'iPhone 15 Pro', stock: 2580, sales: 1580, status: 'normal' },
|
|
442
|
+
{ name: 'MacBook Air M2', stock: 680, sales: 680, status: 'normal' },
|
|
443
|
+
{ name: 'AirPods Pro', stock: 2200, sales: 2200, status: 'normal' },
|
|
444
|
+
{ name: 'iPad Air', stock: 120, sales: 420, status: 'low' },
|
|
445
|
+
{ name: 'Apple Watch', stock: 860, sales: 860, status: 'normal' },
|
|
446
|
+
{ name: 'MacBook Pro', stock: 45, sales: 185, status: 'critical' },
|
|
447
|
+
],
|
|
448
|
+
supplierPerformance: [
|
|
449
|
+
{
|
|
450
|
+
name: '苹果官方',
|
|
451
|
+
orders: 5680,
|
|
452
|
+
onTime: 98.5,
|
|
453
|
+
score: 95,
|
|
454
|
+
status: 'excellent',
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
name: '华为供应链',
|
|
458
|
+
orders: 3250,
|
|
459
|
+
onTime: 96.2,
|
|
460
|
+
score: 92,
|
|
461
|
+
status: 'good',
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
name: '小米官方',
|
|
465
|
+
orders: 2850,
|
|
466
|
+
onTime: 94.8,
|
|
467
|
+
score: 89,
|
|
468
|
+
status: 'good',
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
name: '三星电子',
|
|
472
|
+
orders: 1920,
|
|
473
|
+
onTime: 92.5,
|
|
474
|
+
score: 86,
|
|
475
|
+
status: 'normal',
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
name: 'OPPO官方',
|
|
479
|
+
orders: 1680,
|
|
480
|
+
onTime: 89.2,
|
|
481
|
+
score: 82,
|
|
482
|
+
status: 'normal',
|
|
483
|
+
},
|
|
484
|
+
],
|
|
485
|
+
marketingCampaigns: [
|
|
486
|
+
{
|
|
487
|
+
name: '618大促',
|
|
488
|
+
budget: 500000,
|
|
489
|
+
spent: 485000,
|
|
490
|
+
roi: 4.2,
|
|
491
|
+
conversions: 12850,
|
|
492
|
+
status: 'active',
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
name: '新用户首单',
|
|
496
|
+
budget: 100000,
|
|
497
|
+
spent: 95600,
|
|
498
|
+
roi: 3.8,
|
|
499
|
+
conversions: 4580,
|
|
500
|
+
status: 'active',
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
name: '会员专享',
|
|
504
|
+
budget: 200000,
|
|
505
|
+
spent: 185000,
|
|
506
|
+
roi: 2.8,
|
|
507
|
+
conversions: 5860,
|
|
508
|
+
status: 'active',
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
name: '品牌推广',
|
|
512
|
+
budget: 300000,
|
|
513
|
+
spent: 250000,
|
|
514
|
+
roi: 1.5,
|
|
515
|
+
conversions: 1850,
|
|
516
|
+
status: 'paused',
|
|
517
|
+
},
|
|
518
|
+
],
|
|
519
|
+
customerService: {
|
|
520
|
+
totalTickets: 856,
|
|
521
|
+
resolved: 728,
|
|
522
|
+
pending: 95,
|
|
523
|
+
avgResponseTime: 3.2,
|
|
524
|
+
satisfaction: 96.5,
|
|
525
|
+
},
|
|
526
|
+
logisticsData: [
|
|
527
|
+
{
|
|
528
|
+
name: '顺丰速运',
|
|
529
|
+
orders: 4580,
|
|
530
|
+
avgTime: 1.2,
|
|
531
|
+
satisfaction: 98.5,
|
|
532
|
+
onTime: 99.2,
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
name: '京东物流',
|
|
536
|
+
orders: 3850,
|
|
537
|
+
avgTime: 1.5,
|
|
538
|
+
satisfaction: 97.8,
|
|
539
|
+
onTime: 98.8,
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
name: '中通快递',
|
|
543
|
+
orders: 2850,
|
|
544
|
+
avgTime: 2.8,
|
|
545
|
+
satisfaction: 94.5,
|
|
546
|
+
onTime: 95.2,
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
name: '圆通速递',
|
|
550
|
+
orders: 1920,
|
|
551
|
+
avgTime: 3.2,
|
|
552
|
+
satisfaction: 92.8,
|
|
553
|
+
onTime: 93.5,
|
|
554
|
+
},
|
|
555
|
+
],
|
|
556
|
+
riskAlerts: [
|
|
557
|
+
{
|
|
558
|
+
type: 'critical',
|
|
559
|
+
title: '库存预警',
|
|
560
|
+
message: 'MacBook Pro 库存低于安全线(45台)',
|
|
561
|
+
time: '刚刚',
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
type: 'warning',
|
|
565
|
+
title: '退款率上升',
|
|
566
|
+
message: '上周退款率较前周上升 0.5%',
|
|
567
|
+
time: '30分钟前',
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
type: 'info',
|
|
571
|
+
title: '流量高峰',
|
|
572
|
+
message: '预计18:00-20:00将迎来流量高峰',
|
|
573
|
+
time: '1小时前',
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
type: 'info',
|
|
577
|
+
title: '活动预热',
|
|
578
|
+
message: '双11活动预热开始,关注转化率变化',
|
|
579
|
+
time: '2小时前',
|
|
580
|
+
},
|
|
581
|
+
],
|
|
582
|
+
employeePerformance: [
|
|
583
|
+
{
|
|
584
|
+
name: '张经理',
|
|
585
|
+
team: '销售一部',
|
|
586
|
+
sales: 856000,
|
|
587
|
+
target: 800000,
|
|
588
|
+
rate: 107,
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
name: '李主管',
|
|
592
|
+
team: '销售二部',
|
|
593
|
+
sales: 728000,
|
|
594
|
+
target: 750000,
|
|
595
|
+
rate: 97,
|
|
596
|
+
},
|
|
597
|
+
{
|
|
598
|
+
name: '王总监',
|
|
599
|
+
team: '销售三部',
|
|
600
|
+
sales: 685000,
|
|
601
|
+
target: 600000,
|
|
602
|
+
rate: 114,
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
name: '赵经理',
|
|
606
|
+
team: '大客户部',
|
|
607
|
+
sales: 925000,
|
|
608
|
+
target: 900000,
|
|
609
|
+
rate: 103,
|
|
610
|
+
},
|
|
611
|
+
],
|
|
612
|
+
realtimeOrders: [
|
|
613
|
+
{
|
|
614
|
+
id: 'ORD-2024-1218-001',
|
|
615
|
+
user: '张**',
|
|
616
|
+
amount: 12999,
|
|
617
|
+
time: '刚刚',
|
|
618
|
+
region: '广东省',
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
id: 'ORD-2024-1218-002',
|
|
622
|
+
user: '李**',
|
|
623
|
+
amount: 5999,
|
|
624
|
+
time: '30秒前',
|
|
625
|
+
region: '浙江省',
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
id: 'ORD-2024-1218-003',
|
|
629
|
+
user: '王**',
|
|
630
|
+
amount: 8999,
|
|
631
|
+
time: '1分钟前',
|
|
632
|
+
region: '北京市',
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
id: 'ORD-2024-1218-004',
|
|
636
|
+
user: '赵**',
|
|
637
|
+
amount: 25999,
|
|
638
|
+
time: '2分钟前',
|
|
639
|
+
region: '上海市',
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
id: 'ORD-2024-1218-005',
|
|
643
|
+
user: '钱**',
|
|
644
|
+
amount: 799,
|
|
645
|
+
time: '3分钟前',
|
|
646
|
+
region: '江苏省',
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
id: 'ORD-2024-1218-006',
|
|
650
|
+
user: '孙**',
|
|
651
|
+
amount: 1599,
|
|
652
|
+
time: '4分钟前',
|
|
653
|
+
region: '四川省',
|
|
654
|
+
},
|
|
655
|
+
{
|
|
656
|
+
id: 'ORD-2024-1218-007',
|
|
657
|
+
user: '周**',
|
|
658
|
+
amount: 3299,
|
|
659
|
+
time: '5分钟前',
|
|
660
|
+
region: '湖北省',
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
id: 'ORD-2024-1218-008',
|
|
664
|
+
user: '吴**',
|
|
665
|
+
amount: 899,
|
|
666
|
+
time: '6分钟前',
|
|
667
|
+
region: '福建省',
|
|
668
|
+
},
|
|
669
|
+
],
|
|
670
|
+
hotSearchKeywords: [
|
|
671
|
+
{ keyword: 'iPhone 15 Pro', searches: 15280, growth: 25.6 },
|
|
672
|
+
{ keyword: 'MacBook Air', searches: 12850, growth: 18.2 },
|
|
673
|
+
{ keyword: 'AirPods Pro', searches: 9860, growth: 15.8 },
|
|
674
|
+
{ keyword: 'Apple Watch', searches: 8250, growth: 12.5 },
|
|
675
|
+
{ keyword: 'iPad Pro', searches: 6280, growth: 22.3 },
|
|
676
|
+
{ keyword: '华为 Mate 60', searches: 5850, growth: 45.2 },
|
|
677
|
+
{ keyword: '小米 14', searches: 4860, growth: 35.8 },
|
|
678
|
+
{ keyword: '三星 S24', searches: 3850, growth: 28.5 },
|
|
679
|
+
],
|
|
680
|
+
};
|
|
681
|
+
|
|
682
|
+
handleTabChange(key) {
|
|
683
|
+
this.setState({
|
|
684
|
+
activeTab: key,
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
handleTimeRangeChange(range) {
|
|
689
|
+
this.setState({
|
|
690
|
+
timeRange: range,
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
async loadData() {
|
|
695
|
+
// 数据加载逻辑
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
getActivityIcon(type) {
|
|
699
|
+
const icons = {
|
|
700
|
+
order: '🛒',
|
|
701
|
+
register: '👤',
|
|
702
|
+
refund: '↩️',
|
|
703
|
+
review: '⭐',
|
|
704
|
+
return: '📦',
|
|
705
|
+
};
|
|
706
|
+
return icons[type] || '📌';
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
getActivityColor(type) {
|
|
710
|
+
const colors = {
|
|
711
|
+
order: 'bg-green-100 text-green-700',
|
|
712
|
+
register: 'bg-blue-100 text-blue-700',
|
|
713
|
+
refund: 'bg-red-100 text-red-700',
|
|
714
|
+
review: 'bg-yellow-100 text-yellow-700',
|
|
715
|
+
return: 'bg-orange-100 text-orange-700',
|
|
716
|
+
};
|
|
717
|
+
return colors[type] || 'bg-gray-100 text-gray-700';
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
getRiskAlertStyle(type) {
|
|
721
|
+
const styles = {
|
|
722
|
+
critical: 'bg-red-500/20 border-red-500/50 text-red-400',
|
|
723
|
+
warning: 'bg-yellow-500/20 border-yellow-500/50 text-yellow-400',
|
|
724
|
+
info: 'bg-blue-500/20 border-blue-500/50 text-blue-400',
|
|
725
|
+
};
|
|
726
|
+
return styles[type] || styles.info;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
getStockStatus(status) {
|
|
730
|
+
const config = {
|
|
731
|
+
normal: {
|
|
732
|
+
text: '正常',
|
|
733
|
+
color: 'bg-green-500/20 text-green-400',
|
|
734
|
+
},
|
|
735
|
+
low: {
|
|
736
|
+
text: '偏低',
|
|
737
|
+
color: 'bg-yellow-500/20 text-yellow-400',
|
|
738
|
+
},
|
|
739
|
+
critical: {
|
|
740
|
+
text: '紧急',
|
|
741
|
+
color: 'bg-red-500/20 text-red-400',
|
|
742
|
+
},
|
|
743
|
+
};
|
|
744
|
+
return config[status] || config.normal;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
getPerformanceStatus(score) {
|
|
748
|
+
if (score >= 95)
|
|
749
|
+
return {
|
|
750
|
+
text: '优秀',
|
|
751
|
+
color: 'bg-green-500/20 text-green-400',
|
|
752
|
+
};
|
|
753
|
+
if (score >= 90)
|
|
754
|
+
return {
|
|
755
|
+
text: '良好',
|
|
756
|
+
color: 'bg-blue-500/20 text-blue-400',
|
|
757
|
+
};
|
|
758
|
+
if (score >= 85)
|
|
759
|
+
return {
|
|
760
|
+
text: '正常',
|
|
761
|
+
color: 'bg-yellow-500/20 text-yellow-400',
|
|
762
|
+
};
|
|
763
|
+
return {
|
|
764
|
+
text: '待改进',
|
|
765
|
+
color: 'bg-red-500/20 text-red-400',
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
render() {
|
|
770
|
+
return (
|
|
771
|
+
<Page className="bg-gradient-to-br from-[#0f172a] via-purple-900 to-[#0f172a] min-h-screen">
|
|
772
|
+
<View className="bg-slate-900/60 backdrop-blur-xl border-white/10 pl-[32px] pr-[32px] pt-[20px] pb-[20px] border-b-[1px] border-b-solid sticky top-[0px] z-50">
|
|
773
|
+
<View className="flex items-center justify-between ml-[auto] mr-[auto]">
|
|
774
|
+
<View>
|
|
775
|
+
<h1 className="bg-gradient-to-r from-blue-400 via-purple-400 to-[#f472b6] [WebkitBackgroundClip:text] [WebkitTextFillColor:transparent] [backgroundClip:text] [backgroundClip:text] [WebkitBackgroundClip:text] text-[transparent] text-3xl font-bold">
|
|
776
|
+
🎯 企业级数据分析平台
|
|
777
|
+
</h1>
|
|
778
|
+
<p className="text-[#9ca3af] mt-[4px] text-sm">
|
|
779
|
+
实时监控 · 智能分析 · 数据驱动决策
|
|
780
|
+
</p>
|
|
781
|
+
</View>
|
|
782
|
+
<View className="space-x-4 flex items-center">
|
|
783
|
+
<View className="space-x-2 bg-slate-800/50 flex items-center rounded-lg p-[4px]">
|
|
784
|
+
{['today', 'week', 'month', 'year'].map((range, index) => (
|
|
785
|
+
<button
|
|
786
|
+
key={range}
|
|
787
|
+
onClick={() => this.handleTimeRangeChange(range)}
|
|
788
|
+
className={`px-4 py-2 rounded-md text-sm font-medium transition-all duration-300 ${
|
|
789
|
+
this.state.timeRange === range
|
|
790
|
+
? 'bg-gradient-to-r from-purple-500 to-pink-500 text-white'
|
|
791
|
+
: 'text-gray-400 hover:text-white'
|
|
792
|
+
}`}
|
|
793
|
+
>
|
|
794
|
+
{range === 'today'
|
|
795
|
+
? '今日'
|
|
796
|
+
: range === 'week'
|
|
797
|
+
? '本周'
|
|
798
|
+
: range === 'month'
|
|
799
|
+
? '本月'
|
|
800
|
+
: '本年'}
|
|
801
|
+
</button>
|
|
802
|
+
))}
|
|
803
|
+
</View>
|
|
804
|
+
<View className="bg-green-500/20 border-green-500/30 pl-[16px] pr-[16px] pt-[8px] pb-[8px] rounded-full border border-solid">
|
|
805
|
+
<Text
|
|
806
|
+
_unsafe_MixedSetter_children_select="StringSetter"
|
|
807
|
+
className="text-[var(--green-400)] text-sm font-medium flex items-center"
|
|
808
|
+
>
|
|
809
|
+
1231232132133333
|
|
810
|
+
</Text>
|
|
811
|
+
</View>
|
|
812
|
+
<button
|
|
813
|
+
onClick={() => this.loadData()}
|
|
814
|
+
className="hover:shadow-lg hover:scale-105 transition-all duration-300 bg-gradient-to-r from-purple-500 to-[#ec4899] pl-[16px] pr-[16px] pt-[8px] pb-[8px] text-[#ffffff] rounded-lg font-medium"
|
|
815
|
+
>
|
|
816
|
+
🔄 刷新
|
|
817
|
+
</button>
|
|
818
|
+
</View>
|
|
819
|
+
</View>
|
|
820
|
+
</View>
|
|
821
|
+
<View className="p-[24px] ml-[auto] mr-[auto]">
|
|
822
|
+
<Row gutter={[16, 16]} className="mb-[24px]">
|
|
823
|
+
{this.state.riskAlerts?.slice(0, 2).map((alert, index) => (
|
|
824
|
+
<Col xs={24} sm={12} md={6} key={index}>
|
|
825
|
+
<View
|
|
826
|
+
className={`p-4 rounded-xl border backdrop-blur-sm ${this.getRiskAlertStyle(
|
|
827
|
+
alert.type
|
|
828
|
+
)} hover:scale-105 transition-transform duration-300`}
|
|
829
|
+
>
|
|
830
|
+
<View className="flex items-center justify-between mb-[8px]">
|
|
831
|
+
<Text className="font-bold">{alert.title}</Text>
|
|
832
|
+
<Text className="text-xs">{alert.time}</Text>
|
|
833
|
+
</View>
|
|
834
|
+
<p className="text-sm [opacity:0.9]">{alert.message}</p>
|
|
835
|
+
</View>
|
|
836
|
+
</Col>
|
|
837
|
+
))}
|
|
838
|
+
</Row>
|
|
839
|
+
<Row gutter={[20, 20]} className="mb-[32px]">
|
|
840
|
+
<Col xs={24} sm={12} lg={6}>
|
|
841
|
+
<View className="backdrop-blur-sm border-blue-500/30 hover:shadow-2xl hover:border-blue-400/50 transition-all duration-300 group bg-gradient-to-br from-[var(--blue-500/20)] to-[var(--blue-600/10)] border border-solid rounded-2xl p-[24px]">
|
|
842
|
+
<View className="flex items-center justify-between mb-[16px]">
|
|
843
|
+
<View className="group-hover:scale-110 transition-transform duration-300 text-4xl">
|
|
844
|
+
💰
|
|
845
|
+
</View>
|
|
846
|
+
<View className="space-x-2 flex items-center">
|
|
847
|
+
<Tag color="green">+15.2%</Tag>
|
|
848
|
+
</View>
|
|
849
|
+
</View>
|
|
850
|
+
<View className="text-[#9ca3af] text-sm mb-[4px]">
|
|
851
|
+
总销售额
|
|
852
|
+
</View>
|
|
853
|
+
<View className="text-3xl font-bold text-[#ffffff] mb-[8px]">
|
|
854
|
+
¥<Text>{this.state.totalSales?.toLocaleString()}</Text>
|
|
855
|
+
</View>
|
|
856
|
+
<View className="text-[#6b7280] text-xs">目标达成率 97.2%</View>
|
|
857
|
+
</View>
|
|
858
|
+
</Col>
|
|
859
|
+
<Col xs={24} sm={12} lg={6}>
|
|
860
|
+
<View className="backdrop-blur-sm border-purple-500/30 hover:shadow-2xl hover:border-purple-400/50 transition-all duration-300 group bg-gradient-to-br from-[var(--purple-500/20)] to-[var(--purple-600/10)] border border-solid rounded-2xl p-[24px]">
|
|
861
|
+
<View className="flex items-center justify-between mb-[16px]">
|
|
862
|
+
<View className="group-hover:scale-110 transition-transform duration-300 text-4xl">
|
|
863
|
+
👁️
|
|
864
|
+
</View>
|
|
865
|
+
<Tag color="green">+8.5%</Tag>
|
|
866
|
+
</View>
|
|
867
|
+
<View className="text-[#9ca3af] text-sm mb-[4px]">
|
|
868
|
+
今日访问
|
|
869
|
+
</View>
|
|
870
|
+
<View className="text-3xl font-bold text-[#ffffff] mb-[8px]">
|
|
871
|
+
<Text>{this.state.todayVisits?.toLocaleString()}</Text>
|
|
872
|
+
</View>
|
|
873
|
+
<View className="text-[#6b7280] text-xs">较昨日增加 2,230</View>
|
|
874
|
+
</View>
|
|
875
|
+
</Col>
|
|
876
|
+
<Col xs={24} sm={12} lg={6}>
|
|
877
|
+
<View className="backdrop-blur-sm border-pink-500/30 hover:shadow-2xl hover:border-pink-400/50 transition-all duration-300 group bg-gradient-to-br from-[var(--pink-500/20)] to-[var(--pink-600/10)] border border-solid rounded-2xl p-[24px]">
|
|
878
|
+
<View className="flex items-center justify-between mb-[16px]">
|
|
879
|
+
<View className="group-hover:scale-110 transition-transform duration-300 text-4xl">
|
|
880
|
+
👥
|
|
881
|
+
</View>
|
|
882
|
+
<Tag color="green">+12.3%</Tag>
|
|
883
|
+
</View>
|
|
884
|
+
<View className="text-[#9ca3af] text-sm mb-[4px]">
|
|
885
|
+
新增用户
|
|
886
|
+
</View>
|
|
887
|
+
<View className="text-3xl font-bold text-[#ffffff] mb-[8px]">
|
|
888
|
+
<Text>{this.state.newUsers?.toLocaleString()}</Text>
|
|
889
|
+
</View>
|
|
890
|
+
<View className="text-[#6b7280] text-xs">用户总数 42,852</View>
|
|
891
|
+
</View>
|
|
892
|
+
</Col>
|
|
893
|
+
<Col xs={24} sm={12} lg={6}>
|
|
894
|
+
<View className="backdrop-blur-sm border-cyan-500/30 hover:shadow-2xl hover:border-cyan-400/50 transition-all duration-300 group bg-gradient-to-br from-[var(--cyan-500/20)] to-[var(--cyan-600/10)] border border-solid rounded-2xl p-[24px]">
|
|
895
|
+
<View className="flex items-center justify-between mb-[16px]">
|
|
896
|
+
<View className="group-hover:scale-110 transition-transform duration-300 text-4xl">
|
|
897
|
+
📊
|
|
898
|
+
</View>
|
|
899
|
+
<Tag color="green">+0.8%</Tag>
|
|
900
|
+
</View>
|
|
901
|
+
<View className="text-[#9ca3af] text-sm mb-[4px]">转化率</View>
|
|
902
|
+
<View className="text-3xl font-bold text-[#ffffff] mb-[8px]">
|
|
903
|
+
<Text>{this.state.conversionRate}</Text>%
|
|
904
|
+
</View>
|
|
905
|
+
<View className="text-[#6b7280] text-xs">行业平均 3.5%</View>
|
|
906
|
+
</View>
|
|
907
|
+
</Col>
|
|
908
|
+
</Row>
|
|
909
|
+
<Row gutter={[16, 16]} className="mb-[32px]">
|
|
910
|
+
<Col xs={12} sm={8} md={4}>
|
|
911
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 hover:bg-slate-700/50 transition-all duration-300 border border-solid rounded-xl p-[16px]">
|
|
912
|
+
<View className="text-[#9ca3af] text-xs mb-[8px]">
|
|
913
|
+
平均客单价
|
|
914
|
+
</View>
|
|
915
|
+
<View className="text-xl font-bold text-[#ffffff]">
|
|
916
|
+
¥<Text>{this.state.avgOrderValue}</Text>
|
|
917
|
+
</View>
|
|
918
|
+
</View>
|
|
919
|
+
</Col>
|
|
920
|
+
<Col xs={12} sm={8} md={4}>
|
|
921
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 hover:bg-slate-700/50 transition-all duration-300 border border-solid rounded-xl p-[16px]">
|
|
922
|
+
<View className="text-[#9ca3af] text-xs mb-[8px]">
|
|
923
|
+
完成订单
|
|
924
|
+
</View>
|
|
925
|
+
<View className="text-xl font-bold text-[#ffffff]">
|
|
926
|
+
<Text>{this.state.completedOrders?.toLocaleString()}</Text>
|
|
927
|
+
</View>
|
|
928
|
+
</View>
|
|
929
|
+
</Col>
|
|
930
|
+
<Col xs={12} sm={8} md={4}>
|
|
931
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 hover:bg-slate-700/50 transition-all duration-300 border border-solid rounded-xl p-[16px]">
|
|
932
|
+
<View className="text-[#9ca3af] text-xs mb-[8px]">退款率</View>
|
|
933
|
+
<View className="text-xl font-bold text-[#ffffff]">
|
|
934
|
+
<Text>{this.state.refundRate}</Text>%
|
|
935
|
+
</View>
|
|
936
|
+
</View>
|
|
937
|
+
</Col>
|
|
938
|
+
<Col xs={12} sm={8} md={4}>
|
|
939
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 hover:bg-slate-700/50 transition-all duration-300 border border-solid rounded-xl p-[16px]">
|
|
940
|
+
<View className="text-[#9ca3af] text-xs mb-[8px]">
|
|
941
|
+
客户满意度
|
|
942
|
+
</View>
|
|
943
|
+
<View className="text-xl font-bold text-[var(--green-400)]">
|
|
944
|
+
<Text>{this.state.satisfactionRate}</Text>%
|
|
945
|
+
</View>
|
|
946
|
+
</View>
|
|
947
|
+
</Col>
|
|
948
|
+
<Col xs={12} sm={8} md={4}>
|
|
949
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 hover:bg-slate-700/50 transition-all duration-300 border border-solid rounded-xl p-[16px]">
|
|
950
|
+
<View className="text-[#9ca3af] text-xs mb-[8px]">复购率</View>
|
|
951
|
+
<View className="text-xl font-bold text-[#ffffff]">
|
|
952
|
+
<Text>{this.state.repurchaseRate}</Text>%
|
|
953
|
+
</View>
|
|
954
|
+
</View>
|
|
955
|
+
</Col>
|
|
956
|
+
<Col xs={12} sm={8} md={4}>
|
|
957
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 hover:bg-slate-700/50 transition-all duration-300 border border-solid rounded-xl p-[16px]">
|
|
958
|
+
<View className="text-[#9ca3af] text-xs mb-[8px]">
|
|
959
|
+
客户留存率
|
|
960
|
+
</View>
|
|
961
|
+
<View className="text-xl font-bold text-[#ffffff]">
|
|
962
|
+
<Text>{this.state.retentionRate}</Text>%
|
|
963
|
+
</View>
|
|
964
|
+
</View>
|
|
965
|
+
</Col>
|
|
966
|
+
</Row>
|
|
967
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 border border-solid rounded-2xl overflow-hidden mb-[32px]">
|
|
968
|
+
<Tabs
|
|
969
|
+
activeKey={this.state.activeTab}
|
|
970
|
+
onChange={this.handleTabChange}
|
|
971
|
+
items={[
|
|
972
|
+
{
|
|
973
|
+
key: 'overview',
|
|
974
|
+
label: (
|
|
975
|
+
<Text className="text-[#d1d5db]">
|
|
976
|
+
<Text className="mr-[8px]">📊</Text>数据概览
|
|
977
|
+
</Text>
|
|
978
|
+
),
|
|
979
|
+
children: (
|
|
980
|
+
<View className="p-[24px]">
|
|
981
|
+
<Row gutter={[24, 24]}>
|
|
982
|
+
<Col xs={24}>
|
|
983
|
+
<View className="mb-[24px]">
|
|
984
|
+
<h3 className="text-lg font-bold text-[#ffffff] mb-[16px]">
|
|
985
|
+
月度销售趋势
|
|
986
|
+
</h3>
|
|
987
|
+
<View className="space-y-3">
|
|
988
|
+
{this.state.monthlySales.map((item, index) => {
|
|
989
|
+
const actualPercent =
|
|
990
|
+
(item.sales / 620000) * 100;
|
|
991
|
+
const targetPercent =
|
|
992
|
+
(item.target / 620000) * 100;
|
|
993
|
+
const isOverTarget = item.sales >= item.target;
|
|
994
|
+
return (
|
|
995
|
+
<View
|
|
996
|
+
key={index}
|
|
997
|
+
className="flex items-center"
|
|
998
|
+
>
|
|
999
|
+
<View className="w-[56px] text-[#9ca3af] text-sm">
|
|
1000
|
+
<Text>{item.month}</Text>
|
|
1001
|
+
</View>
|
|
1002
|
+
<View className="space-x-2 flex-1 flex items-center">
|
|
1003
|
+
<View className="bg-slate-700/50 flex-1 rounded-full h-[24px] overflow-hidden relative">
|
|
1004
|
+
<View
|
|
1005
|
+
className="absolute top-0 left-0 h-full bg-gradient-to-r from-purple-500 to-pink-500 transition-all duration-500"
|
|
1006
|
+
style={{ width: `${actualPercent}%` }}
|
|
1007
|
+
/>
|
|
1008
|
+
<View
|
|
1009
|
+
className="absolute top-0 left-0 h-full border-2 border-dashed border-white/30 transition-all duration-500"
|
|
1010
|
+
style={{ width: `${targetPercent}%` }}
|
|
1011
|
+
/>
|
|
1012
|
+
</View>
|
|
1013
|
+
</View>
|
|
1014
|
+
<View className="w-[112px] text-[var(--right)]">
|
|
1015
|
+
<View
|
|
1016
|
+
className={`text-sm font-medium ${
|
|
1017
|
+
isOverTarget
|
|
1018
|
+
? 'text-green-400'
|
|
1019
|
+
: 'text-white'
|
|
1020
|
+
}`}
|
|
1021
|
+
>
|
|
1022
|
+
¥
|
|
1023
|
+
<Text>
|
|
1024
|
+
{(item.sales / 10000).toFixed(1)}
|
|
1025
|
+
</Text>
|
|
1026
|
+
万
|
|
1027
|
+
</View>
|
|
1028
|
+
<View
|
|
1029
|
+
className={`text-xs ${
|
|
1030
|
+
item.growth >= 0
|
|
1031
|
+
? 'text-green-400'
|
|
1032
|
+
: 'text-red-400'
|
|
1033
|
+
}`}
|
|
1034
|
+
>
|
|
1035
|
+
{item.growth >= 0 ? '↑' : '↓'}
|
|
1036
|
+
<Text>{Math.abs(item.growth)}</Text>%
|
|
1037
|
+
</View>
|
|
1038
|
+
</View>
|
|
1039
|
+
</View>
|
|
1040
|
+
);
|
|
1041
|
+
})}
|
|
1042
|
+
</View>
|
|
1043
|
+
</View>
|
|
1044
|
+
</Col>
|
|
1045
|
+
</Row>
|
|
1046
|
+
</View>
|
|
1047
|
+
),
|
|
1048
|
+
},
|
|
1049
|
+
{
|
|
1050
|
+
key: 'products',
|
|
1051
|
+
label: (
|
|
1052
|
+
<Text className="text-[#d1d5db]">
|
|
1053
|
+
<Text className="mr-[8px]">📦</Text>产品分析
|
|
1054
|
+
</Text>
|
|
1055
|
+
),
|
|
1056
|
+
children: (
|
|
1057
|
+
<View className="p-[24px]">
|
|
1058
|
+
<Row gutter={[24, 24]}>
|
|
1059
|
+
<Col xs={24} lg={12}>
|
|
1060
|
+
<h3 className="text-lg font-bold text-[#ffffff] mb-[16px]">
|
|
1061
|
+
分类销售占比
|
|
1062
|
+
</h3>
|
|
1063
|
+
<View className="space-y-4">
|
|
1064
|
+
{this.state.categorySales.map((item, index) => (
|
|
1065
|
+
<View key={index}>
|
|
1066
|
+
<View className="flex items-center justify-between mb-[8px]">
|
|
1067
|
+
<View className="flex items-center">
|
|
1068
|
+
<Text className="text-2xl mr-[12px]">
|
|
1069
|
+
{item.icon}
|
|
1070
|
+
</Text>
|
|
1071
|
+
<Text className="text-[#d1d5db] font-medium">
|
|
1072
|
+
{item.name}
|
|
1073
|
+
</Text>
|
|
1074
|
+
</View>
|
|
1075
|
+
<View className="text-[var(--right)]">
|
|
1076
|
+
<Text className="text-[#ffffff] font-bold">
|
|
1077
|
+
{item.value}%
|
|
1078
|
+
</Text>
|
|
1079
|
+
<View className="text-xs text-[#6b7280]">
|
|
1080
|
+
¥
|
|
1081
|
+
<Text>
|
|
1082
|
+
{(item.sales / 10000).toFixed(0)}
|
|
1083
|
+
</Text>
|
|
1084
|
+
万
|
|
1085
|
+
</View>
|
|
1086
|
+
</View>
|
|
1087
|
+
</View>
|
|
1088
|
+
<View className="bg-slate-700/50 w-full rounded-full h-[12px] overflow-hidden">
|
|
1089
|
+
<View
|
|
1090
|
+
className="h-full rounded-full transition-all duration-500"
|
|
1091
|
+
style={{
|
|
1092
|
+
width: `${item.value}%`,
|
|
1093
|
+
backgroundColor: item.color,
|
|
1094
|
+
}}
|
|
1095
|
+
/>
|
|
1096
|
+
</View>
|
|
1097
|
+
</View>
|
|
1098
|
+
))}
|
|
1099
|
+
</View>
|
|
1100
|
+
</Col>
|
|
1101
|
+
<Col xs={24} lg={12}>
|
|
1102
|
+
<h3 className="text-lg font-bold text-[#ffffff] mb-[16px]">
|
|
1103
|
+
库存状态监控
|
|
1104
|
+
</h3>
|
|
1105
|
+
<View className="space-y-3">
|
|
1106
|
+
{this.state.productInventory.map(
|
|
1107
|
+
(product, index) => {
|
|
1108
|
+
const status = this.getStockStatus(
|
|
1109
|
+
product.status
|
|
1110
|
+
);
|
|
1111
|
+
const stockPercent = Math.min(
|
|
1112
|
+
(product.stock / 3000) * 100,
|
|
1113
|
+
100
|
|
1114
|
+
);
|
|
1115
|
+
return (
|
|
1116
|
+
<View
|
|
1117
|
+
key={index}
|
|
1118
|
+
className="bg-slate-700/30 p-[16px] rounded-xl"
|
|
1119
|
+
>
|
|
1120
|
+
<View className="flex items-center justify-between mb-[8px]">
|
|
1121
|
+
<Text className="text-[#ffffff] font-medium">
|
|
1122
|
+
{product.name}
|
|
1123
|
+
</Text>
|
|
1124
|
+
<Text
|
|
1125
|
+
className={`px-2 py-1 text-xs rounded-full ${status.color}`}
|
|
1126
|
+
>
|
|
1127
|
+
{status.text}
|
|
1128
|
+
</Text>
|
|
1129
|
+
</View>
|
|
1130
|
+
<View className="space-x-4 flex items-center text-sm text-[#9ca3af]">
|
|
1131
|
+
<Text>库存:{product.stock}</Text>
|
|
1132
|
+
<Text>销量:{product.sales}</Text>
|
|
1133
|
+
<Text>
|
|
1134
|
+
周转:
|
|
1135
|
+
{(
|
|
1136
|
+
(product.sales / product.stock) *
|
|
1137
|
+
100
|
|
1138
|
+
).toFixed(0)}
|
|
1139
|
+
%
|
|
1140
|
+
</Text>
|
|
1141
|
+
</View>
|
|
1142
|
+
<View className="bg-slate-700/50 w-full rounded-full h-[8px] mt-[12px]">
|
|
1143
|
+
<View
|
|
1144
|
+
className="h-full rounded-full transition-all duration-500"
|
|
1145
|
+
style={{
|
|
1146
|
+
width: `${stockPercent}%`,
|
|
1147
|
+
backgroundColor:
|
|
1148
|
+
product.status === 'critical'
|
|
1149
|
+
? '#ef4444'
|
|
1150
|
+
: product.status === 'low'
|
|
1151
|
+
? '#f59e0b'
|
|
1152
|
+
: '#10b981',
|
|
1153
|
+
}}
|
|
1154
|
+
/>
|
|
1155
|
+
</View>
|
|
1156
|
+
</View>
|
|
1157
|
+
);
|
|
1158
|
+
}
|
|
1159
|
+
)}
|
|
1160
|
+
</View>
|
|
1161
|
+
</Col>
|
|
1162
|
+
</Row>
|
|
1163
|
+
</View>
|
|
1164
|
+
),
|
|
1165
|
+
},
|
|
1166
|
+
{
|
|
1167
|
+
key: 'users',
|
|
1168
|
+
label: (
|
|
1169
|
+
<Text className="text-[#d1d5db]">
|
|
1170
|
+
<Text className="mr-[8px]">👥</Text>用户画像
|
|
1171
|
+
</Text>
|
|
1172
|
+
),
|
|
1173
|
+
children: (
|
|
1174
|
+
<View className="p-[24px]">
|
|
1175
|
+
<Row gutter={[24, 24]}>
|
|
1176
|
+
<Col xs={24} lg={8}>
|
|
1177
|
+
<h3 className="text-lg font-bold text-[#ffffff] mb-[16px]">
|
|
1178
|
+
年龄段分布
|
|
1179
|
+
</h3>
|
|
1180
|
+
<View className="space-y-3">
|
|
1181
|
+
{this.state.userAgeDistribution.map(
|
|
1182
|
+
(item, index) => (
|
|
1183
|
+
<View key={index}>
|
|
1184
|
+
<View className="flex items-center justify-between mb-[8px]">
|
|
1185
|
+
<Text className="text-[#d1d5db]">
|
|
1186
|
+
{item.range}岁
|
|
1187
|
+
</Text>
|
|
1188
|
+
<Text className="text-[#ffffff] font-bold">
|
|
1189
|
+
{item.value}%
|
|
1190
|
+
</Text>
|
|
1191
|
+
</View>
|
|
1192
|
+
<View className="bg-slate-700/50 w-full rounded-full h-[12px] overflow-hidden">
|
|
1193
|
+
<View
|
|
1194
|
+
className="h-full rounded-full transition-all duration-500"
|
|
1195
|
+
style={{
|
|
1196
|
+
width: `${item.value}%`,
|
|
1197
|
+
backgroundColor: item.color,
|
|
1198
|
+
}}
|
|
1199
|
+
/>
|
|
1200
|
+
</View>
|
|
1201
|
+
</View>
|
|
1202
|
+
)
|
|
1203
|
+
)}
|
|
1204
|
+
</View>
|
|
1205
|
+
</Col>
|
|
1206
|
+
<Col xs={24} lg={8}>
|
|
1207
|
+
<h3 className="text-lg font-bold text-[#ffffff] mb-[16px]">
|
|
1208
|
+
性别分布
|
|
1209
|
+
</h3>
|
|
1210
|
+
<View className="flex items-center justify-center pt-[32px] pb-[32px]">
|
|
1211
|
+
<View className="relative w-[160px] h-[160px]">
|
|
1212
|
+
<svg
|
|
1213
|
+
viewBox="0 0 36 36"
|
|
1214
|
+
className="w-full h-full"
|
|
1215
|
+
>
|
|
1216
|
+
<path
|
|
1217
|
+
d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
|
|
1218
|
+
fill="none"
|
|
1219
|
+
stroke="#3b82f6"
|
|
1220
|
+
strokeWidth="3"
|
|
1221
|
+
strokeDasharray={`${this.state.userGenderDistribution?.male}, 100`}
|
|
1222
|
+
/>
|
|
1223
|
+
<path
|
|
1224
|
+
d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
|
|
1225
|
+
fill="none"
|
|
1226
|
+
stroke="#ec4899"
|
|
1227
|
+
strokeWidth="3"
|
|
1228
|
+
strokeDasharray={`${this.state.userGenderDistribution?.female}, 100`}
|
|
1229
|
+
strokeDashoffset={`-${this.state.userGenderDistribution?.male}`}
|
|
1230
|
+
/>
|
|
1231
|
+
</svg>
|
|
1232
|
+
<View className="inset-0 absolute flex items-center justify-center">
|
|
1233
|
+
<View className="text-[var(--center)]">
|
|
1234
|
+
<View className="text-2xl font-bold text-[#ffffff]">
|
|
1235
|
+
<Text>
|
|
1236
|
+
{this.state.userGenderDistribution?.male +
|
|
1237
|
+
this.state.userGenderDistribution
|
|
1238
|
+
?.female}
|
|
1239
|
+
</Text>
|
|
1240
|
+
%
|
|
1241
|
+
</View>
|
|
1242
|
+
<View className="text-xs text-[#9ca3af]">
|
|
1243
|
+
总用户
|
|
1244
|
+
</View>
|
|
1245
|
+
</View>
|
|
1246
|
+
</View>
|
|
1247
|
+
</View>
|
|
1248
|
+
<View className="space-y-3 ml-[32px]">
|
|
1249
|
+
<View className="flex items-center">
|
|
1250
|
+
<View className="w-[12px] h-[12px] bg-[#3b82f6] rounded-full mr-[8px]" />
|
|
1251
|
+
<Text className="text-[#d1d5db]">
|
|
1252
|
+
男性{this.state.userGenderDistribution?.male}%
|
|
1253
|
+
</Text>
|
|
1254
|
+
</View>
|
|
1255
|
+
<View className="flex items-center">
|
|
1256
|
+
<View className="w-[12px] h-[12px] bg-[#ec4899] rounded-full mr-[8px]" />
|
|
1257
|
+
<Text className="text-[#d1d5db]">
|
|
1258
|
+
女性
|
|
1259
|
+
{this.state.userGenderDistribution?.female}%
|
|
1260
|
+
</Text>
|
|
1261
|
+
</View>
|
|
1262
|
+
</View>
|
|
1263
|
+
</View>
|
|
1264
|
+
</Col>
|
|
1265
|
+
<Col xs={24} lg={8}>
|
|
1266
|
+
<h3 className="text-lg font-bold text-[#ffffff] mb-[16px]">
|
|
1267
|
+
设备分布
|
|
1268
|
+
</h3>
|
|
1269
|
+
<View className="space-y-3">
|
|
1270
|
+
{this.state.userDeviceDistribution.map(
|
|
1271
|
+
(item, index) => (
|
|
1272
|
+
<View key={index}>
|
|
1273
|
+
<View className="flex items-center justify-between mb-[8px]">
|
|
1274
|
+
<Text className="text-[#d1d5db]">
|
|
1275
|
+
{item.name}
|
|
1276
|
+
</Text>
|
|
1277
|
+
<Text className="text-[#ffffff] font-bold">
|
|
1278
|
+
{item.value}%
|
|
1279
|
+
</Text>
|
|
1280
|
+
</View>
|
|
1281
|
+
<View className="bg-slate-700/50 w-full rounded-full h-[12px] overflow-hidden">
|
|
1282
|
+
<View
|
|
1283
|
+
className="h-full rounded-full transition-all duration-500"
|
|
1284
|
+
style={{
|
|
1285
|
+
width: `${item.value}%`,
|
|
1286
|
+
backgroundColor: item.color,
|
|
1287
|
+
}}
|
|
1288
|
+
/>
|
|
1289
|
+
</View>
|
|
1290
|
+
</View>
|
|
1291
|
+
)
|
|
1292
|
+
)}
|
|
1293
|
+
</View>
|
|
1294
|
+
</Col>
|
|
1295
|
+
</Row>
|
|
1296
|
+
</View>
|
|
1297
|
+
),
|
|
1298
|
+
},
|
|
1299
|
+
{
|
|
1300
|
+
key: 'marketing',
|
|
1301
|
+
label: (
|
|
1302
|
+
<Text className="text-[#d1d5db]">
|
|
1303
|
+
<Text className="mr-[8px]">📣</Text>营销活动
|
|
1304
|
+
</Text>
|
|
1305
|
+
),
|
|
1306
|
+
children: (
|
|
1307
|
+
<View className="p-[24px]">
|
|
1308
|
+
<Row gutter={[24, 24]}>
|
|
1309
|
+
<Col xs={24}>
|
|
1310
|
+
<h3 className="text-lg font-bold text-[#ffffff] mb-[16px]">
|
|
1311
|
+
活动效果分析
|
|
1312
|
+
</h3>
|
|
1313
|
+
<View className="space-y-4">
|
|
1314
|
+
{this.state.marketingCampaigns.map(
|
|
1315
|
+
(campaign, index) => (
|
|
1316
|
+
<View
|
|
1317
|
+
key={index}
|
|
1318
|
+
className="bg-slate-700/30 p-[16px] rounded-xl"
|
|
1319
|
+
>
|
|
1320
|
+
<View className="flex items-center justify-between mb-[12px]">
|
|
1321
|
+
<View className="space-x-4 flex items-center">
|
|
1322
|
+
<Text className="text-[#ffffff] font-bold text-lg">
|
|
1323
|
+
{campaign.name}
|
|
1324
|
+
</Text>
|
|
1325
|
+
<Tag
|
|
1326
|
+
color={
|
|
1327
|
+
campaign.status === 'active'
|
|
1328
|
+
? 'green'
|
|
1329
|
+
: 'default'
|
|
1330
|
+
}
|
|
1331
|
+
>
|
|
1332
|
+
{campaign.status === 'active'
|
|
1333
|
+
? '进行中'
|
|
1334
|
+
: '已暂停'}
|
|
1335
|
+
</Tag>
|
|
1336
|
+
</View>
|
|
1337
|
+
<View className="text-[var(--right)]">
|
|
1338
|
+
<View className="text-[var(--green-400)] font-bold">
|
|
1339
|
+
ROI:<Text>{campaign.roi}</Text>x
|
|
1340
|
+
</View>
|
|
1341
|
+
<View className="text-xs text-[#6b7280]">
|
|
1342
|
+
转化:
|
|
1343
|
+
<Text>
|
|
1344
|
+
{campaign.conversions?.toLocaleString()}
|
|
1345
|
+
</Text>
|
|
1346
|
+
</View>
|
|
1347
|
+
</View>
|
|
1348
|
+
</View>
|
|
1349
|
+
<View className="gap-4 grid grid-cols-3 text-sm">
|
|
1350
|
+
<View>
|
|
1351
|
+
<View className="text-[#9ca3af]">
|
|
1352
|
+
预算
|
|
1353
|
+
</View>
|
|
1354
|
+
<View className="text-[#ffffff] font-medium">
|
|
1355
|
+
¥
|
|
1356
|
+
<Text>
|
|
1357
|
+
{campaign.budget?.toLocaleString()}
|
|
1358
|
+
</Text>
|
|
1359
|
+
</View>
|
|
1360
|
+
</View>
|
|
1361
|
+
<View>
|
|
1362
|
+
<View className="text-[#9ca3af]">
|
|
1363
|
+
已使用
|
|
1364
|
+
</View>
|
|
1365
|
+
<View className="text-[#ffffff] font-medium">
|
|
1366
|
+
¥
|
|
1367
|
+
<Text>
|
|
1368
|
+
{campaign.spent?.toLocaleString()}
|
|
1369
|
+
</Text>
|
|
1370
|
+
</View>
|
|
1371
|
+
</View>
|
|
1372
|
+
<View>
|
|
1373
|
+
<View className="text-[#9ca3af]">
|
|
1374
|
+
使用率
|
|
1375
|
+
</View>
|
|
1376
|
+
<View className="text-[#ffffff] font-medium">
|
|
1377
|
+
<Text>
|
|
1378
|
+
{(
|
|
1379
|
+
(campaign.spent / campaign.budget) *
|
|
1380
|
+
100
|
|
1381
|
+
).toFixed(0)}
|
|
1382
|
+
</Text>
|
|
1383
|
+
%
|
|
1384
|
+
</View>
|
|
1385
|
+
</View>
|
|
1386
|
+
</View>
|
|
1387
|
+
<View className="bg-slate-700/50 w-full rounded-full h-[8px] mt-[12px]">
|
|
1388
|
+
<View
|
|
1389
|
+
className="h-full rounded-full bg-gradient-to-r from-purple-500 to-pink-500"
|
|
1390
|
+
style={{
|
|
1391
|
+
width: `${
|
|
1392
|
+
(campaign.spent / campaign.budget) *
|
|
1393
|
+
100
|
|
1394
|
+
}%`,
|
|
1395
|
+
}}
|
|
1396
|
+
/>
|
|
1397
|
+
</View>
|
|
1398
|
+
</View>
|
|
1399
|
+
)
|
|
1400
|
+
)}
|
|
1401
|
+
</View>
|
|
1402
|
+
</Col>
|
|
1403
|
+
</Row>
|
|
1404
|
+
</View>
|
|
1405
|
+
),
|
|
1406
|
+
},
|
|
1407
|
+
{
|
|
1408
|
+
key: 'operations',
|
|
1409
|
+
label: (
|
|
1410
|
+
<Text className="text-[#d1d5db]">
|
|
1411
|
+
<Text className="mr-[8px]">⚙️</Text>运营监控
|
|
1412
|
+
</Text>
|
|
1413
|
+
),
|
|
1414
|
+
children: (
|
|
1415
|
+
<View className="p-[24px]">
|
|
1416
|
+
<Row gutter={[24, 24]}>
|
|
1417
|
+
<Col xs={24} lg={12}>
|
|
1418
|
+
<h3 className="text-lg font-bold text-[#ffffff] mb-[16px]">
|
|
1419
|
+
供应商表现
|
|
1420
|
+
</h3>
|
|
1421
|
+
<View className="space-y-3">
|
|
1422
|
+
{this.state.supplierPerformance.map(
|
|
1423
|
+
(supplier, index) => {
|
|
1424
|
+
const status = this.getPerformanceStatus(
|
|
1425
|
+
supplier.score
|
|
1426
|
+
);
|
|
1427
|
+
return (
|
|
1428
|
+
<View
|
|
1429
|
+
key={index}
|
|
1430
|
+
className="bg-slate-700/30 p-[16px] rounded-xl"
|
|
1431
|
+
>
|
|
1432
|
+
<View className="flex items-center justify-between mb-[8px]">
|
|
1433
|
+
<View className="flex items-center">
|
|
1434
|
+
<View
|
|
1435
|
+
className={`w-8 h-8 rounded-lg flex items-center justify-center mr-3 text-white text-sm font-bold ${
|
|
1436
|
+
index === 0
|
|
1437
|
+
? 'bg-gradient-to-br from-yellow-400 to-yellow-600'
|
|
1438
|
+
: index === 1
|
|
1439
|
+
? 'bg-gradient-to-br from-gray-400 to-gray-600'
|
|
1440
|
+
: index === 2
|
|
1441
|
+
? 'bg-gradient-to-br from-orange-400 to-orange-600'
|
|
1442
|
+
: 'bg-slate-600'
|
|
1443
|
+
}`}
|
|
1444
|
+
>
|
|
1445
|
+
<Text>{index + 1}</Text>
|
|
1446
|
+
</View>
|
|
1447
|
+
<View>
|
|
1448
|
+
<View className="text-[#ffffff] font-medium">
|
|
1449
|
+
<Text>{supplier.name}</Text>
|
|
1450
|
+
</View>
|
|
1451
|
+
<View className="text-xs text-[#6b7280]">
|
|
1452
|
+
订单:
|
|
1453
|
+
<Text>
|
|
1454
|
+
{supplier.orders?.toLocaleString()}
|
|
1455
|
+
</Text>
|
|
1456
|
+
</View>
|
|
1457
|
+
</View>
|
|
1458
|
+
</View>
|
|
1459
|
+
<View className="text-[var(--right)]">
|
|
1460
|
+
<View className="text-[#ffffff] font-bold">
|
|
1461
|
+
评分:<Text>{supplier.score}</Text>
|
|
1462
|
+
</View>
|
|
1463
|
+
<View
|
|
1464
|
+
className={`text-xs px-2 py-1 rounded-full ${status.color}`}
|
|
1465
|
+
>
|
|
1466
|
+
<Text>{status.text}</Text>
|
|
1467
|
+
</View>
|
|
1468
|
+
</View>
|
|
1469
|
+
</View>
|
|
1470
|
+
<View className="gap-2 grid grid-cols-2 text-xs text-[#9ca3af]">
|
|
1471
|
+
<View>
|
|
1472
|
+
准时率:<Text>{supplier.onTime}</Text>%
|
|
1473
|
+
</View>
|
|
1474
|
+
</View>
|
|
1475
|
+
</View>
|
|
1476
|
+
);
|
|
1477
|
+
}
|
|
1478
|
+
)}
|
|
1479
|
+
</View>
|
|
1480
|
+
</Col>
|
|
1481
|
+
<Col xs={24} lg={12}>
|
|
1482
|
+
<h3 className="text-lg font-bold text-[#ffffff] mb-[16px]">
|
|
1483
|
+
物流数据
|
|
1484
|
+
</h3>
|
|
1485
|
+
<View className="space-y-3">
|
|
1486
|
+
{this.state.logisticsData.map(
|
|
1487
|
+
(logistics, index) => (
|
|
1488
|
+
<View
|
|
1489
|
+
key={index}
|
|
1490
|
+
className="bg-slate-700/30 p-[16px] rounded-xl"
|
|
1491
|
+
>
|
|
1492
|
+
<View className="flex items-center justify-between mb-[8px]">
|
|
1493
|
+
<Text className="text-[#ffffff] font-medium">
|
|
1494
|
+
{logistics.name}
|
|
1495
|
+
</Text>
|
|
1496
|
+
<Text className="text-[#9ca3af] text-sm">
|
|
1497
|
+
{logistics.orders?.toLocaleString()}单
|
|
1498
|
+
</Text>
|
|
1499
|
+
</View>
|
|
1500
|
+
<View className="gap-2 grid grid-cols-3 text-sm text-[#9ca3af]">
|
|
1501
|
+
<View>
|
|
1502
|
+
<View className="text-xs">平均时效</View>
|
|
1503
|
+
<View className="text-[#ffffff]">
|
|
1504
|
+
<Text>{logistics.avgTime}</Text>天
|
|
1505
|
+
</View>
|
|
1506
|
+
</View>
|
|
1507
|
+
<View>
|
|
1508
|
+
<View className="text-xs">满意度</View>
|
|
1509
|
+
<View className="text-[#ffffff]">
|
|
1510
|
+
<Text>{logistics.satisfaction}</Text>%
|
|
1511
|
+
</View>
|
|
1512
|
+
</View>
|
|
1513
|
+
<View>
|
|
1514
|
+
<View className="text-xs">准时率</View>
|
|
1515
|
+
<View className="text-[#ffffff]">
|
|
1516
|
+
<Text>{logistics.onTime}</Text>%
|
|
1517
|
+
</View>
|
|
1518
|
+
</View>
|
|
1519
|
+
</View>
|
|
1520
|
+
</View>
|
|
1521
|
+
)
|
|
1522
|
+
)}
|
|
1523
|
+
</View>
|
|
1524
|
+
</Col>
|
|
1525
|
+
</Row>
|
|
1526
|
+
</View>
|
|
1527
|
+
),
|
|
1528
|
+
},
|
|
1529
|
+
]}
|
|
1530
|
+
/>
|
|
1531
|
+
</View>
|
|
1532
|
+
<Row gutter={[24, 24]} className="mb-[32px]">
|
|
1533
|
+
<Col xs={24} lg={14}>
|
|
1534
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 hover:border-green-500/30 transition-all duration-300 border border-solid rounded-2xl p-[24px]">
|
|
1535
|
+
<h2 className="text-xl font-bold text-[#ffffff] mb-[24px] flex items-center">{`热门地区 TOP 7`}</h2>
|
|
1536
|
+
<View className="space-y-4">
|
|
1537
|
+
{this.state.hotRegions.map((region, index) => (
|
|
1538
|
+
<View
|
|
1539
|
+
key={index}
|
|
1540
|
+
className="bg-slate-700/30 hover:bg-slate-700/50 transition-all duration-300 flex items-center justify-between p-[12px] rounded-xl"
|
|
1541
|
+
>
|
|
1542
|
+
<View className="flex items-center flex-1">
|
|
1543
|
+
<View
|
|
1544
|
+
className={`w-8 h-8 rounded-lg flex items-center justify-center mr-3 text-white font-bold text-sm ${
|
|
1545
|
+
index === 0
|
|
1546
|
+
? 'bg-gradient-to-br from-yellow-400 to-yellow-600'
|
|
1547
|
+
: index === 1
|
|
1548
|
+
? 'bg-gradient-to-br from-gray-400 to-gray-600'
|
|
1549
|
+
: index === 2
|
|
1550
|
+
? 'bg-gradient-to-br from-orange-400 to-orange-600'
|
|
1551
|
+
: 'bg-gradient-to-br from-slate-500 to-slate-600'
|
|
1552
|
+
}`}
|
|
1553
|
+
>
|
|
1554
|
+
<Text>{index + 1}</Text>
|
|
1555
|
+
</View>
|
|
1556
|
+
<View className="flex-1">
|
|
1557
|
+
<View className="text-[#ffffff] font-medium">
|
|
1558
|
+
<Text>{region.name}</Text>
|
|
1559
|
+
</View>
|
|
1560
|
+
<View className="text-xs text-[#6b7280]">
|
|
1561
|
+
<Text>{region.cities?.join('、')}</Text>
|
|
1562
|
+
</View>
|
|
1563
|
+
</View>
|
|
1564
|
+
</View>
|
|
1565
|
+
<View className="text-[var(--right)] ml-[16px]">
|
|
1566
|
+
<View className="text-[#ffffff] font-bold">
|
|
1567
|
+
<Text>{region.value?.toLocaleString()}</Text>
|
|
1568
|
+
</View>
|
|
1569
|
+
<View
|
|
1570
|
+
className={`text-xs font-medium ${
|
|
1571
|
+
region.growth >= 0
|
|
1572
|
+
? 'text-green-400'
|
|
1573
|
+
: 'text-red-400'
|
|
1574
|
+
}`}
|
|
1575
|
+
>
|
|
1576
|
+
{region.growth >= 0 ? '↑' : '↓'}
|
|
1577
|
+
<Text>{Math.abs(region.growth)}</Text>%
|
|
1578
|
+
</View>
|
|
1579
|
+
</View>
|
|
1580
|
+
<View className="ml-[16px] w-[64px] text-[var(--right)]">
|
|
1581
|
+
<View className="text-xs text-[#6b7280]">
|
|
1582
|
+
<Text>{region.percentage}</Text>%
|
|
1583
|
+
</View>
|
|
1584
|
+
</View>
|
|
1585
|
+
</View>
|
|
1586
|
+
))}
|
|
1587
|
+
</View>
|
|
1588
|
+
</View>
|
|
1589
|
+
</Col>
|
|
1590
|
+
<Col xs={24} lg={10}>
|
|
1591
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 hover:border-pink-500/30 transition-all duration-300 border border-solid rounded-2xl p-[24px]">
|
|
1592
|
+
<h2 className="text-xl font-bold text-[#ffffff] mb-[24px] flex items-center">{`渠道流量来源`}</h2>
|
|
1593
|
+
<View className="space-y-4">
|
|
1594
|
+
{this.state.channelTraffic.map((item, index) => (
|
|
1595
|
+
<View key={index}>
|
|
1596
|
+
<View className="flex items-center justify-between mb-[8px]">
|
|
1597
|
+
<Text className="text-[#d1d5db] font-medium">
|
|
1598
|
+
{item.name}
|
|
1599
|
+
</Text>
|
|
1600
|
+
<View className="text-[var(--right)]">
|
|
1601
|
+
<Text className="text-[#ffffff] font-bold">
|
|
1602
|
+
{item.value}%
|
|
1603
|
+
</Text>
|
|
1604
|
+
<View className="text-xs text-[#6b7280]">
|
|
1605
|
+
转化:<Text>{item.conversion}</Text>%
|
|
1606
|
+
</View>
|
|
1607
|
+
</View>
|
|
1608
|
+
</View>
|
|
1609
|
+
<View className="bg-slate-700/50 w-full rounded-full h-[12px] overflow-hidden">
|
|
1610
|
+
<View
|
|
1611
|
+
className="h-full rounded-full transition-all duration-500 hover:brightness-110"
|
|
1612
|
+
style={{
|
|
1613
|
+
width: `${item.value}%`,
|
|
1614
|
+
backgroundColor: item.color,
|
|
1615
|
+
}}
|
|
1616
|
+
/>
|
|
1617
|
+
</View>
|
|
1618
|
+
</View>
|
|
1619
|
+
))}
|
|
1620
|
+
</View>
|
|
1621
|
+
</View>
|
|
1622
|
+
</Col>
|
|
1623
|
+
</Row>
|
|
1624
|
+
<Row gutter={[24, 24]} className="mb-[32px]">
|
|
1625
|
+
<Col xs={24} lg={12}>
|
|
1626
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 hover:border-blue-500/30 transition-all duration-300 border border-solid rounded-2xl p-[24px]">
|
|
1627
|
+
<h2 className="text-xl font-bold text-[#ffffff] mb-[24px] flex items-center">{`实时订单流`}</h2>
|
|
1628
|
+
<View className="space-y-3 max-h-[320px] overflow-y-auto">
|
|
1629
|
+
{this.state.realtimeOrders.map((order, index) => (
|
|
1630
|
+
<View
|
|
1631
|
+
key={index}
|
|
1632
|
+
className="bg-slate-700/30 hover:bg-slate-700/50 transition-all duration-300 flex items-center justify-between p-[12px] rounded-xl cursor-pointer"
|
|
1633
|
+
>
|
|
1634
|
+
<View className="flex items-center flex-1">
|
|
1635
|
+
<View className="text-[var(--green-400)] mr-[12px] text-lg">
|
|
1636
|
+
💰
|
|
1637
|
+
</View>
|
|
1638
|
+
<View className="flex-1">
|
|
1639
|
+
<View className="text-[#ffffff] font-medium">
|
|
1640
|
+
<Text>{order.id}</Text>
|
|
1641
|
+
</View>
|
|
1642
|
+
<View className="text-xs text-[#6b7280]">
|
|
1643
|
+
<Text>{order.user}</Text>·
|
|
1644
|
+
<Text>{order.region}</Text>
|
|
1645
|
+
</View>
|
|
1646
|
+
</View>
|
|
1647
|
+
</View>
|
|
1648
|
+
<View className="text-[var(--right)] ml-[16px]">
|
|
1649
|
+
<View className="text-[#ffffff] font-bold">
|
|
1650
|
+
¥<Text>{order.amount?.toLocaleString()}</Text>
|
|
1651
|
+
</View>
|
|
1652
|
+
<View className="text-xs text-[#6b7280]">
|
|
1653
|
+
<Text>{order.time}</Text>
|
|
1654
|
+
</View>
|
|
1655
|
+
</View>
|
|
1656
|
+
</View>
|
|
1657
|
+
))}
|
|
1658
|
+
</View>
|
|
1659
|
+
</View>
|
|
1660
|
+
</Col>
|
|
1661
|
+
<Col xs={24} lg={12}>
|
|
1662
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 hover:border-orange-500/30 transition-all duration-300 border border-solid rounded-2xl p-[24px]">
|
|
1663
|
+
<h2 className="text-xl font-bold text-[#ffffff] mb-[24px] flex items-center">{`热门搜索词`}</h2>
|
|
1664
|
+
<View className="space-y-3">
|
|
1665
|
+
{this.state.hotSearchKeywords.map((item, index) => (
|
|
1666
|
+
<View
|
|
1667
|
+
key={index}
|
|
1668
|
+
className="bg-slate-700/30 hover:bg-slate-700/50 transition-all duration-300 flex items-center justify-between p-[12px] rounded-xl cursor-pointer"
|
|
1669
|
+
>
|
|
1670
|
+
<View className="flex items-center">
|
|
1671
|
+
<View
|
|
1672
|
+
className={`w-6 h-6 rounded-full flex items-center justify-center mr-3 text-white text-xs font-bold ${
|
|
1673
|
+
index < 3
|
|
1674
|
+
? 'bg-gradient-to-br from-orange-400 to-pink-500'
|
|
1675
|
+
: 'bg-slate-600'
|
|
1676
|
+
}`}
|
|
1677
|
+
>
|
|
1678
|
+
<Text>{index + 1}</Text>
|
|
1679
|
+
</View>
|
|
1680
|
+
<Text className="text-[#ffffff] font-medium">
|
|
1681
|
+
{item.keyword}
|
|
1682
|
+
</Text>
|
|
1683
|
+
</View>
|
|
1684
|
+
<View className="text-[var(--right)]">
|
|
1685
|
+
<View className="text-[#ffffff] font-bold">
|
|
1686
|
+
<Text>{item.searches?.toLocaleString()}</Text>
|
|
1687
|
+
</View>
|
|
1688
|
+
<View
|
|
1689
|
+
className={`text-xs ${
|
|
1690
|
+
item.growth >= 0 ? 'text-green-400' : 'text-red-400'
|
|
1691
|
+
}`}
|
|
1692
|
+
>
|
|
1693
|
+
{item.growth >= 0 ? '↑' : '↓'}
|
|
1694
|
+
<Text>{Math.abs(item.growth)}</Text>%
|
|
1695
|
+
</View>
|
|
1696
|
+
</View>
|
|
1697
|
+
</View>
|
|
1698
|
+
))}
|
|
1699
|
+
</View>
|
|
1700
|
+
</View>
|
|
1701
|
+
</Col>
|
|
1702
|
+
</Row>
|
|
1703
|
+
<Row gutter={[24, 24]} className="mb-[32px]">
|
|
1704
|
+
<Col xs={24} lg={12}>
|
|
1705
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 hover:border-purple-500/30 transition-all duration-300 border border-solid rounded-2xl p-[24px]">
|
|
1706
|
+
<h2 className="text-xl font-bold text-[#ffffff] mb-[24px] flex items-center">{`员工绩效排行`}</h2>
|
|
1707
|
+
<View className="space-y-4">
|
|
1708
|
+
{this.state.employeePerformance.map((employee, index) => (
|
|
1709
|
+
<View
|
|
1710
|
+
key={index}
|
|
1711
|
+
className="bg-slate-700/30 p-[16px] rounded-xl"
|
|
1712
|
+
>
|
|
1713
|
+
<View className="flex items-center justify-between mb-[8px]">
|
|
1714
|
+
<View className="flex items-center">
|
|
1715
|
+
<View
|
|
1716
|
+
className={`w-8 h-8 rounded-lg flex items-center justify-center mr-3 text-white text-sm font-bold ${
|
|
1717
|
+
index === 0
|
|
1718
|
+
? 'bg-gradient-to-br from-yellow-400 to-yellow-600'
|
|
1719
|
+
: index === 1
|
|
1720
|
+
? 'bg-gradient-to-br from-gray-400 to-gray-600'
|
|
1721
|
+
: index === 2
|
|
1722
|
+
? 'bg-gradient-to-br from-orange-400 to-orange-600'
|
|
1723
|
+
: 'bg-slate-600'
|
|
1724
|
+
}`}
|
|
1725
|
+
>
|
|
1726
|
+
<Text>{index + 1}</Text>
|
|
1727
|
+
</View>
|
|
1728
|
+
<View>
|
|
1729
|
+
<View className="text-[#ffffff] font-medium">
|
|
1730
|
+
<Text>{employee.name}</Text>
|
|
1731
|
+
</View>
|
|
1732
|
+
<View className="text-xs text-[#6b7280]">
|
|
1733
|
+
<Text>{employee.team}</Text>
|
|
1734
|
+
</View>
|
|
1735
|
+
</View>
|
|
1736
|
+
</View>
|
|
1737
|
+
<View className="text-[var(--right)]">
|
|
1738
|
+
<View className="text-[#ffffff] font-bold">
|
|
1739
|
+
¥<Text>{employee.sales?.toLocaleString()}</Text>
|
|
1740
|
+
</View>
|
|
1741
|
+
<View
|
|
1742
|
+
className={`text-xs px-2 py-1 rounded-full ${
|
|
1743
|
+
employee.rate >= 100
|
|
1744
|
+
? 'bg-green-500/20 text-green-400'
|
|
1745
|
+
: 'bg-yellow-500/20 text-yellow-400'
|
|
1746
|
+
}`}
|
|
1747
|
+
>
|
|
1748
|
+
{employee.rate >= 100 ? '↑' : '↓'}
|
|
1749
|
+
<Text>{Math.abs(employee.rate - 100)}</Text>%
|
|
1750
|
+
</View>
|
|
1751
|
+
</View>
|
|
1752
|
+
</View>
|
|
1753
|
+
<View className="flex items-center justify-between text-xs text-[#6b7280]">
|
|
1754
|
+
<Text>目标: ¥{employee.target?.toLocaleString()}</Text>
|
|
1755
|
+
<Text>完成率:{employee.rate}%</Text>
|
|
1756
|
+
</View>
|
|
1757
|
+
<View className="bg-slate-700/50 w-full rounded-full h-[8px] mt-[8px]">
|
|
1758
|
+
<View
|
|
1759
|
+
className={`h-full rounded-full transition-all duration-500 ${
|
|
1760
|
+
employee.rate >= 100
|
|
1761
|
+
? 'bg-gradient-to-r from-green-500 to-emerald-500'
|
|
1762
|
+
: 'bg-gradient-to-r from-yellow-500 to-orange-500'
|
|
1763
|
+
}`}
|
|
1764
|
+
style={{ width: `${Math.min(employee.rate, 100)}%` }}
|
|
1765
|
+
/>
|
|
1766
|
+
</View>
|
|
1767
|
+
</View>
|
|
1768
|
+
))}
|
|
1769
|
+
</View>
|
|
1770
|
+
</View>
|
|
1771
|
+
</Col>
|
|
1772
|
+
<Col xs={24} lg={12}>
|
|
1773
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 hover:border-cyan-500/30 transition-all duration-300 border border-solid rounded-2xl p-[24px]">
|
|
1774
|
+
<h2 className="text-xl font-bold text-[#ffffff] mb-[24px] flex items-center">{`客服数据`}</h2>
|
|
1775
|
+
<View className="gap-4 grid grid-cols-2 mb-[24px]">
|
|
1776
|
+
<View className="bg-slate-700/30 p-[16px] rounded-xl text-[var(--center)]">
|
|
1777
|
+
<View className="text-3xl font-bold text-[#ffffff] mb-[4px]">
|
|
1778
|
+
<Text>{this.state.customerService?.totalTickets}</Text>
|
|
1779
|
+
</View>
|
|
1780
|
+
<View className="text-xs text-[#6b7280]">总工单</View>
|
|
1781
|
+
</View>
|
|
1782
|
+
<View className="bg-green-500/20 p-[16px] rounded-xl text-[var(--center)]">
|
|
1783
|
+
<View className="text-3xl font-bold text-[var(--green-400)] mb-[4px]">
|
|
1784
|
+
<Text>{this.state.customerService?.resolved}</Text>
|
|
1785
|
+
</View>
|
|
1786
|
+
<View className="text-xs text-[#9ca3af]">已解决</View>
|
|
1787
|
+
</View>
|
|
1788
|
+
<View className="bg-yellow-500/20 p-[16px] rounded-xl text-[var(--center)]">
|
|
1789
|
+
<View className="text-3xl font-bold text-[var(--yellow-400)] mb-[4px]">
|
|
1790
|
+
<Text>{this.state.customerService?.pending}</Text>
|
|
1791
|
+
</View>
|
|
1792
|
+
<View className="text-xs text-[#9ca3af]">处理中</View>
|
|
1793
|
+
</View>
|
|
1794
|
+
<View className="bg-purple-500/20 p-[16px] rounded-xl text-[var(--center)]">
|
|
1795
|
+
<View className="text-3xl font-bold text-[var(--purple-400)] mb-[4px]">
|
|
1796
|
+
<Text>{this.state.customerService?.satisfaction}</Text>%
|
|
1797
|
+
</View>
|
|
1798
|
+
<View className="text-xs text-[#9ca3af]">满意度</View>
|
|
1799
|
+
</View>
|
|
1800
|
+
</View>
|
|
1801
|
+
<View className="bg-slate-700/30 p-[16px] rounded-xl">
|
|
1802
|
+
<View className="flex items-center justify-between">
|
|
1803
|
+
<Text className="text-[#9ca3af]">平均响应时间</Text>
|
|
1804
|
+
<Text className="text-[#ffffff] font-bold">
|
|
1805
|
+
{this.state.customerService?.avgResponseTime}分钟
|
|
1806
|
+
</Text>
|
|
1807
|
+
</View>
|
|
1808
|
+
<View className="bg-slate-700/50 w-full rounded-full h-[8px] mt-[8px]">
|
|
1809
|
+
<View className="h-full rounded-full bg-gradient-to-r from-cyan-500 to-blue-500 w-[64%]" />
|
|
1810
|
+
</View>
|
|
1811
|
+
<View className="text-xs text-[#6b7280] mt-[4px]">
|
|
1812
|
+
目标: <5 分钟
|
|
1813
|
+
</View>
|
|
1814
|
+
</View>
|
|
1815
|
+
</View>
|
|
1816
|
+
</Col>
|
|
1817
|
+
</Row>
|
|
1818
|
+
<Row gutter={[24, 24]}>
|
|
1819
|
+
<Col xs={24}>
|
|
1820
|
+
<View className="bg-slate-800/50 backdrop-blur-sm border-slate-700/50 hover:border-indigo-500/30 transition-all duration-300 border border-solid rounded-2xl p-[24px]">
|
|
1821
|
+
<h2 className="text-xl font-bold text-[#ffffff] mb-[24px] flex items-center">{`最新动态`}</h2>
|
|
1822
|
+
<View className="space-y-3">
|
|
1823
|
+
{this.state.recentActivities.map((activity, index) => (
|
|
1824
|
+
<View
|
|
1825
|
+
key={index}
|
|
1826
|
+
className="bg-slate-700/30 hover:bg-slate-700/50 transition-all duration-300 flex items-center justify-between p-[16px] rounded-xl cursor-pointer"
|
|
1827
|
+
>
|
|
1828
|
+
<View className="flex items-center flex-1">
|
|
1829
|
+
<View
|
|
1830
|
+
className={`w-10 h-10 rounded-full flex items-center justify-center mr-4 ${this.getActivityColor(
|
|
1831
|
+
activity.type
|
|
1832
|
+
)}`}
|
|
1833
|
+
>
|
|
1834
|
+
<Text className="text-lg">
|
|
1835
|
+
{this.getActivityIcon(activity.type)}
|
|
1836
|
+
</Text>
|
|
1837
|
+
</View>
|
|
1838
|
+
<View className="flex-1">
|
|
1839
|
+
<View className="space-x-2 flex items-center">
|
|
1840
|
+
<Text className="text-[#ffffff] font-medium">
|
|
1841
|
+
{activity.user}
|
|
1842
|
+
</Text>
|
|
1843
|
+
<Text className="text-[#9ca3af]">
|
|
1844
|
+
{activity.action}
|
|
1845
|
+
</Text>
|
|
1846
|
+
</View>
|
|
1847
|
+
<View className="text-sm text-[#6b7280] mt-[4px]">
|
|
1848
|
+
<Text>{activity.detail}</Text>
|
|
1849
|
+
</View>
|
|
1850
|
+
</View>
|
|
1851
|
+
</View>
|
|
1852
|
+
<View className="text-[var(--right)] ml-[16px]">
|
|
1853
|
+
<View className="text-[#ffffff] font-bold">
|
|
1854
|
+
<Text>{activity.amount}</Text>
|
|
1855
|
+
</View>
|
|
1856
|
+
<View className="text-xs text-[#6b7280]">
|
|
1857
|
+
<Text>{activity.time}</Text>
|
|
1858
|
+
</View>
|
|
1859
|
+
</View>
|
|
1860
|
+
</View>
|
|
1861
|
+
))}
|
|
1862
|
+
</View>
|
|
1863
|
+
</View>
|
|
1864
|
+
</Col>
|
|
1865
|
+
</Row>
|
|
1866
|
+
</View>
|
|
1867
|
+
</Page>
|
|
1868
|
+
);
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1872
|
+
export default Document;
|