@appthen/cli 1.2.11 → 1.2.13

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.
Files changed (59) hide show
  1. package/bin/main.js +47 -0
  2. package/dist/index.js +6185 -15001
  3. package/package.json +8 -4
  4. package/tests/test-app/.appthen/shadow-space-100001-test-app-e99876b1.json +1197 -741
  5. package/tests/test-app/.appthen/space-config.json +2 -2
  6. package/tests/test-app/src/components/MessageCenter.tsx +506 -0
  7. package/tests/test-app/src/pages/CustomerManagement.tsx +535 -0
  8. package/tests/test-app/src/pages/CyberpunkDashboard.tsx +348 -0
  9. package/tests/test-app/src/pages/CyberpunkProductManagement.tsx +637 -0
  10. package/tests/test-app/src/pages/CyberpunkUserList.tsx +316 -0
  11. package/tests/test-app/src/pages/DashboardV2.tsx +334 -0
  12. package/tests/test-app/src/pages/DataReport.tsx +298 -0
  13. package/tests/test-app/src/pages/DataStatistics.tsx +317 -0
  14. package/tests/test-app/src/pages/DepartmentManagement.tsx +503 -0
  15. package/tests/test-app/src/pages/FileExplorer.tsx +441 -0
  16. package/tests/test-app/src/pages/OrderDetail.tsx +393 -0
  17. package/tests/test-app/src/pages/ProductManagement.tsx +521 -0
  18. package/tests/test-app/src/pages/ProjectTimeline.tsx +395 -0
  19. package/tests/test-app/src/pages/RoleManagement.tsx +523 -0
  20. package/tests/test-app/src/pages/StaticCyberpunkDashboard.tsx +462 -0
  21. package/tests/test-app/src/pages/StaticCyberpunkUserList.tsx +567 -0
  22. package/tests/test-app/src/pages/StudentWeaknessList.tsx +547 -0
  23. package/tests/test-app/src/pages/SystemSettings.tsx +422 -0
  24. package/tests/test-app/src/pages/TaskManagement.tsx +467 -0
  25. package/tests/test-app/src/pages/TicketManagement.tsx +402 -0
  26. package/tests/test-app/src/pages/UserProfile.tsx +404 -0
  27. package/tests/test-app/src/pages/WorkflowDesigner.tsx +434 -0
  28. package/tests/test-app/src/pages/admin/dashboard.tsx +591 -0
  29. package/tests/test-app/src/pages/article-list.tsx +222 -0
  30. package/tests/test-app/src/pages/babyProductRecommendationPage.tsx +168 -0
  31. package/tests/test-app/src/pages/category-list.tsx +179 -0
  32. package/tests/test-app/src/pages/comment-list.tsx +194 -0
  33. package/tests/test-app/src/pages/cyberpunk/cyberpunkCRMPage.tsx +1299 -0
  34. package/tests/test-app/src/pages/data-analytics.tsx +1872 -0
  35. package/tests/test-app/src/pages/data-overview.tsx +600 -0
  36. package/tests/test-app/src/pages/demo-error-page.tsx +119 -0
  37. package/tests/test-app/src/pages/department-list.tsx +183 -0
  38. package/tests/test-app/src/pages/goods-list.tsx +233 -0
  39. package/tests/test-app/src/pages/housekeeping/adminDashboardPage.tsx +880 -0
  40. package/tests/test-app/src/pages/mobile_terminal/uiHandsOnPractice.tsx +1 -1
  41. package/tests/test-app/src/pages/notice-list.tsx +217 -0
  42. package/tests/test-app/src/pages/order-detail.tsx +330 -0
  43. package/tests/test-app/src/pages/order-list.tsx +195 -0
  44. package/tests/test-app/src/pages/order-management.tsx +563 -0
  45. package/tests/test-app/src/pages/page/OrderList.tsx +230 -0
  46. package/tests/test-app/src/pages/role-list.tsx +184 -0
  47. package/tests/test-app/src/pages/simple/simplePage.tsx +92 -0
  48. package/tests/test-app/src/pages/simple-page.tsx +43 -0
  49. package/tests/test-app/src/pages/test-destructure.tsx +44 -0
  50. package/tests/test-app/src/pages/test-error-page.tsx +75 -0
  51. package/tests/test-app/src/pages/test-page-with-errors.tsx +51 -0
  52. package/tests/test-app/src/pages/test-page.tsx +101 -0
  53. package/tests/test-app/src/pages/test-render.tsx +52 -0
  54. package/tests/test-app/src/pages/test-return-type.tsx +41 -0
  55. package/tests/test-app/src/pages/test-type-assertion.tsx +37 -0
  56. package/tests/test-app/src/pages/ui/styleSelectorPage.tsx +1554 -0
  57. package/tests/test-app/src/pages/user-list.tsx +212 -0
  58. package/tests/test-app/src/pages/wrong-page.tsx +50 -0
  59. package/tests/test-app/.appthen/shadow-space-unknown-user-test-app-e99876b1.json +0 -1060
@@ -0,0 +1,316 @@
1
+ /**
2
+ * 赛博朋克用户列表
3
+ * 充满未来科技感的用户管理页面,采用霓虹配色和全息效果
4
+ *
5
+ * @type Page
6
+ * @route /cyberpunk-user-list-test112
7
+ * @screen 1920x1080 #0a0a0f
8
+ * @frames web
9
+ */
10
+ import React from 'react';
11
+
12
+
13
+
14
+ class IProps {
15
+ title?: string;
16
+ }
17
+
18
+ /*
19
+ * 数据与接口请求定义
20
+ */
21
+ class IState {
22
+ selectedUser?: any;
23
+ modalVisible?: boolean;
24
+ searchKeyword?: string;
25
+ statusFilter?: string;
26
+ users?: {
27
+ /* @example 1 */id?: number,
28
+ /* @example 霓虹行者 */name?: string,
29
+ /* @example neon@cyber.net */email?: string,
30
+ /* @example 管理员 */role?: string,
31
+ /* @example active */status?: string,
32
+ /* @example 99 */level?: number,
33
+ /* @example https://api.dicebear.com/7.x/bottts/svg?seed=neon */avatar?: string,
34
+ /* @example 2077-01-15 */joinDate?: string,
35
+ /* @example 2077-12-01 23:45:12 */lastLogin?: string,
36
+ }[];
37
+ loading?: boolean;
38
+ cyberMode?: boolean;
39
+ }
40
+
41
+ class Document extends React.Component<IProps, IState> {
42
+ state = {
43
+ selectedUser: null,
44
+ modalVisible: false,
45
+ searchKeyword: '',
46
+ statusFilter: 'all',
47
+ users: [
48
+ {
49
+ id: 1,
50
+ name: '霓虹行者',
51
+ email: 'neon@cyber.net',
52
+ role: '管理员',
53
+ status: 'active',
54
+ level: 99,
55
+ avatar: 'https://api.dicebear.com/7.x/bottts/svg?seed=neon',
56
+ joinDate: '2077-01-15',
57
+ lastLogin: '2077-12-01 23:45:12',
58
+ },
59
+ {
60
+ id: 2,
61
+ name: '数据幽灵',
62
+ email: 'ghost@cyber.net',
63
+ role: '开发者',
64
+ status: 'active',
65
+ level: 87,
66
+ avatar: 'https://api.dicebear.com/7.x/bottts/svg?seed=ghost',
67
+ joinDate: '2077-03-22',
68
+ lastLogin: '2077-12-01 22:30:45',
69
+ },
70
+ {
71
+ id: 3,
72
+ name: '赛博黑客',
73
+ email: 'hacker@cyber.net',
74
+ role: '操作员',
75
+ status: 'warning',
76
+ level: 72,
77
+ avatar: 'https://api.dicebear.com/7.x/bottts/svg?seed=hacker',
78
+ joinDate: '2077-05-10',
79
+ lastLogin: '2077-11-30 18:20:33',
80
+ },
81
+ {
82
+ id: 4,
83
+ name: '量子行者',
84
+ email: 'quantum@cyber.net',
85
+ role: '开发者',
86
+ status: 'active',
87
+ level: 95,
88
+ avatar: 'https://api.dicebear.com/7.x/bottts/svg?seed=quantum',
89
+ joinDate: '2077-02-28',
90
+ lastLogin: '2077-12-01 21:15:27',
91
+ },
92
+ {
93
+ id: 5,
94
+ name: '暗影猎手',
95
+ email: 'shadow@cyber.net',
96
+ role: '操作员',
97
+ status: 'offline',
98
+ level: 65,
99
+ avatar: 'https://api.dicebear.com/7.x/bottts/svg?seed=shadow',
100
+ joinDate: '2077-06-15',
101
+ lastLogin: '2077-11-25 10:45:00',
102
+ },
103
+ {
104
+ id: 6,
105
+ name: '网络守护者',
106
+ email: 'guardian@cyber.net',
107
+ role: '管理员',
108
+ status: 'active',
109
+ level: 91,
110
+ avatar: 'https://api.dicebear.com/7.x/bottts/svg?seed=guardian',
111
+ joinDate: '2077-01-08',
112
+ lastLogin: '2077-12-01 23:50:18',
113
+ },
114
+ {
115
+ id: 7,
116
+ name: '代码刺客',
117
+ email: 'assassin@cyber.net',
118
+ role: '开发者',
119
+ status: 'active',
120
+ level: 83,
121
+ avatar: 'https://api.dicebear.com/7.x/bottts/svg?seed=assassin',
122
+ joinDate: '2077-04-12',
123
+ lastLogin: '2077-12-01 20:10:55',
124
+ },
125
+ {
126
+ id: 8,
127
+ name: '数字浪人',
128
+ email: 'ronin@cyber.net',
129
+ role: '操作员',
130
+ status: 'warning',
131
+ level: 58,
132
+ avatar: 'https://api.dicebear.com/7.x/bottts/svg?seed=ronin',
133
+ joinDate: '2077-07-20',
134
+ lastLogin: '2077-11-28 14:30:22',
135
+ },
136
+ ],
137
+ loading: false,
138
+ cyberMode: true,
139
+ };
140
+
141
+ handleView(user) {
142
+ this.setState({
143
+ selectedUser: user,
144
+ modalVisible: true,
145
+ });
146
+ }
147
+
148
+ handleEdit(user) {
149
+ this.utils.showToast(`编辑用户: ${user.name}`);
150
+ }
151
+
152
+ handleDelete(user) {
153
+ this.utils.showToast(`删除用户: ${user.name}`);
154
+ }
155
+
156
+ handleAdd() {
157
+ this.utils.showToast('添加新用户');
158
+ }
159
+
160
+ toggleCyberMode() {
161
+ this.setState({
162
+ cyberMode: !this.state.cyberMode,
163
+ });
164
+ }
165
+
166
+ closeModal() {
167
+ this.setState({
168
+ modalVisible: false,
169
+ });
170
+ }
171
+
172
+ render() {
173
+ return (
174
+ <Page style={styles.container}>
175
+ <View style={styles.scanlines} />
176
+ <View style={styles.grid} />
177
+ <View style={styles.particles} />
178
+ <View style={styles.header}>
179
+ <View style={styles.headerLeft}>
180
+ <Text style={styles.title}>用户管理</Text>
181
+ <Text style={styles.subtitle}>USER MANAGEMENT SYSTEM</Text>
182
+ </View>
183
+ <View style={styles.headerRight}>
184
+ <Button
185
+ style={styles.cyberButton}
186
+ onClick={() => this.toggleCyberMode()}
187
+ >
188
+ <Text style={styles.buttonText}>
189
+ {this.state.cyberMode ? '关闭特效' : '开启特效'}
190
+ </Text>
191
+ </Button>
192
+ <Button
193
+ style={[styles.cyberButton, styles.primaryButton]}
194
+ onClick={() => this.handleAdd()}
195
+ >
196
+ <Text style={styles.buttonText}>+ 新增用户</Text>
197
+ </Button>
198
+ </View>
199
+ </View>
200
+ <View style={styles.mainContent}>
201
+ <ProTable
202
+ columns={this.columns}
203
+ dataSource={this.state.users}
204
+ rowKey="id"
205
+ loading={this.state.loading}
206
+ pagination={{
207
+ pageSize: 10,
208
+ showSizeChanger: true,
209
+ showQuickJumper: true,
210
+ }}
211
+ rowClassName={record =>
212
+ record.status === 'offline' ? styles.offlineRow : ''
213
+ }
214
+ toolBarRender={() => (
215
+ <Space>
216
+ <Text style={styles.totalText}>
217
+ 总计:{this.state.users?.length}位用户
218
+ </Text>
219
+ </Space>
220
+ )}
221
+ toolBarRenderOpen={true}
222
+ style={styles.tableContainer}
223
+ headerStyle={styles.tableHeader}
224
+ />
225
+ </View>
226
+ {!!this.state.modalVisible && (
227
+ <View style={styles.modalOverlay} onClick={() => this.closeModal()}>
228
+ <View style={styles.modal} onClick={e => e.stopPropagation()}>
229
+ <View style={styles.modalHeader}>
230
+ <Text style={styles.modalTitle}>用户详情</Text>
231
+ <Button
232
+ style={styles.closeButton}
233
+ onClick={() => this.closeModal()}
234
+ >
235
+ <Text style={styles.closeButtonText}>✕</Text>
236
+ </Button>
237
+ </View>
238
+ <View style={styles.modalContent}>
239
+ <View style={styles.modalAvatarSection}>
240
+ <Avatar
241
+ src={this.state.selectedUser?.avatar}
242
+ size={80}
243
+ style={styles.modalAvatar}
244
+ />
245
+ <Text style={styles.modalUserName}>
246
+ {this.state.selectedUser?.name}
247
+ </Text>
248
+ <Tag color="#ff00ff" style={styles.modalRoleTag}>
249
+ <Text>{this.state.selectedUser?.role}</Text>
250
+ </Tag>
251
+ </View>
252
+ <View style={styles.modalInfoGrid}>
253
+ <View style={styles.infoItem}>
254
+ <Text style={styles.infoLabel}>邮箱</Text>
255
+ <Text style={styles.infoValue}>
256
+ {this.state.selectedUser?.email}
257
+ </Text>
258
+ </View>
259
+ <View style={styles.infoItem}>
260
+ <Text style={styles.infoLabel}>等级</Text>
261
+ <Text style={styles.infoValue}>
262
+ LV.{this.state.selectedUser?.level}
263
+ </Text>
264
+ </View>
265
+ <View style={styles.infoItem}>
266
+ <Text style={styles.infoLabel}>状态</Text>
267
+ <Text
268
+ style={[
269
+ styles.infoValue,
270
+ styles[
271
+ 'infoValue' +
272
+ this.state.selectedUser?.status
273
+ .charAt(0)
274
+ .toUpperCase() +
275
+ this.state.selectedUser?.status.slice(1)
276
+ ],
277
+ ]}
278
+ >
279
+ {this.state.selectedUser?.status === 'active'
280
+ ? '在线'
281
+ : this.state.selectedUser?.status === 'warning'
282
+ ? '警告'
283
+ : '离线'}
284
+ </Text>
285
+ </View>
286
+ <View style={styles.infoItem}>
287
+ <Text style={styles.infoLabel}>加入时间</Text>
288
+ <Text style={styles.infoValue}>
289
+ {this.state.selectedUser?.joinDate}
290
+ </Text>
291
+ </View>
292
+ <View style={styles.infoItem}>
293
+ <Text style={styles.infoLabel}>最后登录</Text>
294
+ <Text style={styles.infoValue}>
295
+ {this.state.selectedUser?.lastLogin}
296
+ </Text>
297
+ </View>
298
+ </View>
299
+ </View>
300
+ <View style={styles.modalFooter}>
301
+ <Button
302
+ style={[styles.cyberButton, styles.modalButton]}
303
+ onClick={() => this.closeModal()}
304
+ >
305
+ <Text style={styles.buttonText}>关闭</Text>
306
+ </Button>
307
+ </View>
308
+ </View>
309
+ </View>
310
+ )}
311
+ </Page>
312
+ );
313
+ }
314
+ }
315
+
316
+ export default Document;
@@ -0,0 +1,334 @@
1
+ /**
2
+ * 仪表板 V2
3
+ * 数据可视化仪表板
4
+ *
5
+ * @type Page
6
+ * @route /dashboard/v2
7
+ * @screen 1920w
8
+ * @frames web
9
+ */
10
+ import React from 'react';
11
+
12
+
13
+
14
+ class IProps {
15
+ dashboardId?: number;
16
+ }
17
+
18
+ /*
19
+ * 数据与接口请求定义
20
+ */
21
+ class IState {
22
+ statistics?: any[];
23
+ loading?: boolean;
24
+ dateRange?: any[];
25
+ selectedMetric?: string;
26
+ refreshInterval?: number;
27
+ }
28
+
29
+ class Document extends React.Component<IProps, IState> {
30
+ state = {
31
+ statistics: [
32
+ {
33
+ id: 1,
34
+ name: '今日访问',
35
+ value: 12586,
36
+ trend: 12,
37
+ icon: '👀',
38
+ color: 'blue',
39
+ },
40
+ {
41
+ id: 2,
42
+ name: '新增用户',
43
+ value: 328,
44
+ trend: 8,
45
+ icon: '👤',
46
+ color: 'green',
47
+ },
48
+ {
49
+ id: 3,
50
+ name: '订单数',
51
+ value: 156,
52
+ trend: -5,
53
+ icon: '📦',
54
+ color: 'orange',
55
+ },
56
+ {
57
+ id: 4,
58
+ name: '收入',
59
+ value: 45680,
60
+ trend: 15,
61
+ icon: '💰',
62
+ color: 'red',
63
+ },
64
+ ],
65
+ loading: false,
66
+ dateRange: [
67
+ new Date().toISOString().split('T')[0],
68
+ new Date().toISOString().split('T')[0],
69
+ ],
70
+ selectedMetric: 'all',
71
+ refreshInterval: 30,
72
+ };
73
+
74
+ handleDateRangeChange(dates) {
75
+ this.setState({
76
+ dateRange: dates,
77
+ });
78
+ }
79
+
80
+ handleMetricChange(metric) {
81
+ this.setState({
82
+ selectedMetric: metric,
83
+ });
84
+ }
85
+
86
+ handleRefresh() {
87
+ this.setState({
88
+ loading: true,
89
+ });
90
+ setTimeout(() => {
91
+ this.setState({
92
+ loading: false,
93
+ });
94
+ }, 1000);
95
+ }
96
+
97
+ render() {
98
+ // 💀 死亡:变量声明 - 解构赋值
99
+ const { statistics, loading, dateRange, selectedMetric, refreshInterval } =
100
+ this.state;
101
+
102
+ // 💀 死亡:变量声明 - 计算属性
103
+ // 💀 死亡:变量声明 - 计算属性
104
+ const totalTrend = statistics.reduce((sum, stat) => sum + stat.trend, 0);
105
+ const avgTrend = Math.round(totalTrend / statistics.length);
106
+ const positiveCount = statistics.filter(s => s.trend > 0).length;
107
+ const negativeCount = statistics.filter(s => s.trend < 0).length;
108
+
109
+ // 💀 死亡:变量声明 - 过滤后的数据
110
+ // 💀 死亡:变量声明 - 过滤后的数据
111
+ const filteredStats =
112
+ selectedMetric === 'all'
113
+ ? statistics
114
+ : statistics.filter(s => s.id.toString() === selectedMetric);
115
+
116
+ // 💀 死亡:变量声明 - 日期范围文本
117
+ // 💀 死亡:变量声明 - 日期范围文本
118
+ const dateRangeText =
119
+ dateRange?.length === 2
120
+ ? `${dateRange[0]} 至 ${dateRange[1]}`
121
+ : '请选择日期范围';
122
+
123
+ // 💀 死亡:if 语句 - 条件渲染
124
+ // 💀 死亡:if 语句 - 条件渲染
125
+ if (loading) {
126
+ return <View className="p-6">加载中...</View>;
127
+ }
128
+
129
+ // 💀 死亡:变量声明 - 配置选项
130
+ // 💀 死亡:变量声明 - 配置选项
131
+ const metricOptions = [
132
+ {
133
+ label: '全部指标',
134
+ value: 'all',
135
+ },
136
+ {
137
+ label: '访问量',
138
+ value: '1',
139
+ },
140
+ {
141
+ label: '新增用户',
142
+ value: '2',
143
+ },
144
+ {
145
+ label: '订单数',
146
+ value: '3',
147
+ },
148
+ {
149
+ label: '收入',
150
+ value: '4',
151
+ },
152
+ ];
153
+
154
+ // 💀 死亡:变量声明 - 颜色配置
155
+ // 💀 死亡:变量声明 - 颜色配置
156
+ const trendColors = {
157
+ positive: '#52c41a',
158
+ negative: '#ff4d4f',
159
+ neutral: '#8c8c8c',
160
+ };
161
+
162
+ // 💀 死亡:变量声明 - JSX 片段函数
163
+ // 💀 死亡:变量声明 - JSX 片段函数
164
+ const statCard = stat => (
165
+ <Card key={stat.id} className="hover:shadow-lg transition-shadow">
166
+ <View className="flex items-center justify-between">
167
+ <View>
168
+ <Text className="text-4xl">{stat.icon}</Text>
169
+ <Text className="block text-gray-500 mt-2">{stat.name}</Text>
170
+ <Text className="text-2xl font-bold mt-1">
171
+ {stat.value.toLocaleString()}
172
+ </Text>
173
+ </View>
174
+ <View>
175
+ <Tag color={stat.trend > 0 ? 'green' : 'red'}>
176
+ {stat.trend > 0 ? '+' : ''}
177
+ {stat.trend}%
178
+ </Tag>
179
+ </View>
180
+ </View>
181
+ </Card>
182
+ );
183
+
184
+ // 💀 死亡:变量声明 - 进度数据
185
+ // 💀 死亡:变量声明 - 进度数据
186
+ const progressData = [
187
+ {
188
+ name: '目标完成度',
189
+ percent: 75,
190
+ color: '#1890ff',
191
+ },
192
+ {
193
+ name: '任务完成率',
194
+ percent: 60,
195
+ color: '#52c41a',
196
+ },
197
+ {
198
+ name: '用户满意度',
199
+ percent: 85,
200
+ color: '#faad14',
201
+ },
202
+ ];
203
+
204
+ // 💀 死亡:变量声明 - 快捷日期选项
205
+ // 💀 死亡:变量声明 - 快捷日期选项
206
+ const quickDateOptions = [
207
+ {
208
+ label: '今天',
209
+ value: 'today',
210
+ },
211
+ {
212
+ label: '昨天',
213
+ value: 'yesterday',
214
+ },
215
+ {
216
+ label: '最近7天',
217
+ value: '7days',
218
+ },
219
+ {
220
+ label: '最近30天',
221
+ value: '30days',
222
+ },
223
+ ];
224
+ return (
225
+ <Page className="p-[24px] bg-[var(--gray-50)] min-h-screen">
226
+ <View className="mb-[24px]">
227
+ <Text className="text-2xl font-bold text-[#1f2937]">仪表板 V2</Text>
228
+ <Text className="text-[#6b7280] text-sm mt-[4px]">
229
+ 数据可视化仪表板
230
+ </Text>
231
+ </View>
232
+ <Card className="mb-[24px]">
233
+ <View className="flex items-center justify-between">
234
+ <View className="gap-4 flex items-center">
235
+ <DatePicker.RangePicker
236
+ value={dateRange}
237
+ onChange={dates => this.handleDateRangeChange(dates)}
238
+ />
239
+ <Select
240
+ value={selectedMetric}
241
+ onChange={value => this.handleMetricChange(value)}
242
+ placeholder="选择指标"
243
+ className=""
244
+ >
245
+ {metricOptions.map((opt, index) => (
246
+ <Select.Option key={opt.value} value={opt.value}>
247
+ <Text>{opt.label}</Text>
248
+ </Select.Option>
249
+ ))}
250
+ </Select>
251
+ </View>
252
+ <View className="gap-2 flex items-center">
253
+ <Text className="text-[#6b7280] text-sm">
254
+ 自动刷新:{refreshInterval}秒
255
+ </Text>
256
+ <Button onClick={() => this.handleRefresh()}>刷新</Button>
257
+ <Button type="primary">导出报表</Button>
258
+ </View>
259
+ </View>
260
+ </Card>
261
+ <Card className="mb-[24px]">
262
+ <Row gutter={16}>
263
+ {filteredStats.map((stat, index) => (
264
+ <Col span={6} key={stat.id}>
265
+ <Text>{statCard(stat)}</Text>
266
+ </Col>
267
+ ))}
268
+ </Row>
269
+ </Card>
270
+ <Card className="mb-[24px]">
271
+ <Text className="block text-lg font-bold mb-[16px]">趋势分析</Text>
272
+ <Row gutter={16}>
273
+ <Col span={8}>
274
+ <Card className="bg-[var(--blue-50)]">
275
+ <Statistic
276
+ title="正向指标"
277
+ value={positiveCount}
278
+ suffix={`/ ${statistics.length}`}
279
+ valueStyle={{ color: trendColors.positive }}
280
+ />
281
+ </Card>
282
+ </Col>
283
+ <Col span={8}>
284
+ <Card className="bg-[var(--red-50)]">
285
+ <Statistic
286
+ title="负向指标"
287
+ value={negativeCount}
288
+ suffix={`/ ${statistics.length}`}
289
+ valueStyle={{ color: trendColors.negative }}
290
+ />
291
+ </Card>
292
+ </Col>
293
+ <Col span={8}>
294
+ <Card className="bg-[var(--gray-50)]">
295
+ <Statistic
296
+ title="平均趋势"
297
+ value={avgTrend}
298
+ suffix="%"
299
+ valueStyle={{ color: trendColors.neutral }}
300
+ />
301
+ </Card>
302
+ </Col>
303
+ </Row>
304
+ </Card>
305
+ <Card className="mb-[24px]">
306
+ <Text className="block text-lg font-bold mb-[16px]">目标进度</Text>
307
+ <View className="space-y-4">
308
+ {progressData.map((item, index) => (
309
+ <View key={index}>
310
+ <View className="flex justify-between mb-[8px]">
311
+ <Text>{item.name}</Text>
312
+ <Text>{item.percent}%</Text>
313
+ </View>
314
+ <Progress percent={item.percent} strokeColor={item.color} />
315
+ </View>
316
+ ))}
317
+ </View>
318
+ </Card>
319
+ <Card>
320
+ <Text className="block text-lg font-bold mb-[16px]">快捷日期</Text>
321
+ <View className="gap-2 flex">
322
+ {quickDateOptions.map((opt, index) => (
323
+ <Button key={opt.value} onClick={() => console.log(opt.value)}>
324
+ <Text>{opt.label}</Text>
325
+ </Button>
326
+ ))}
327
+ </View>
328
+ </Card>
329
+ </Page>
330
+ );
331
+ }
332
+ }
333
+
334
+ export default Document;