mall-components 1.0.0

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 (122) hide show
  1. package/README.md +128 -0
  2. package/build/_components-raw.css +791 -0
  3. package/build/_shims/antd.js +1 -0
  4. package/build/_shims/icons.js +1 -0
  5. package/build/_shims/moment.js +1 -0
  6. package/build/_shims/react-dom.js +1 -0
  7. package/build/_shims/react.js +1 -0
  8. package/build/adapters/DataSourceAdapter.d.ts +46 -0
  9. package/build/components/AdminLayout/AdminLayout.d.ts +5 -0
  10. package/build/components/AdminLayout/Breadcrumb.d.ts +8 -0
  11. package/build/components/AdminLayout/MainContent.d.ts +17 -0
  12. package/build/components/AdminLayout/Navbar.d.ts +10 -0
  13. package/build/components/AdminLayout/Sidebar.d.ts +14 -0
  14. package/build/components/AdminLayout/TabBar.d.ts +13 -0
  15. package/build/components/AdminLayout/TabPane.d.ts +4 -0
  16. package/build/components/AdminLayout/index.d.ts +3 -0
  17. package/build/components/AdminLayout/types.d.ts +42 -0
  18. package/build/components/CouponCard/CouponCard.d.ts +20 -0
  19. package/build/components/CouponCard/index.d.ts +1 -0
  20. package/build/components/OrderForm/OrderForm.d.ts +18 -0
  21. package/build/components/OrderForm/index.d.ts +1 -0
  22. package/build/components/OrderList/OrderList.d.ts +29 -0
  23. package/build/components/OrderList/index.d.ts +1 -0
  24. package/build/components/ProductForm/ProductForm.d.ts +18 -0
  25. package/build/components/ProductForm/index.d.ts +3 -0
  26. package/build/components/ProductList/ProductList.d.ts +47 -0
  27. package/build/components/ProductList/index.d.ts +3 -0
  28. package/build/components/PromotionCard/PromotionCard.d.ts +22 -0
  29. package/build/components/PromotionCard/index.d.ts +1 -0
  30. package/build/components/RoleCard/RoleCard.d.ts +18 -0
  31. package/build/components/RoleCard/index.d.ts +1 -0
  32. package/build/components/UserCard/UserCard.d.ts +17 -0
  33. package/build/components/UserCard/index.d.ts +1 -0
  34. package/build/entry-meta.d.ts +603 -0
  35. package/build/index.css +1 -0
  36. package/build/index.js +1 -0
  37. package/build/mall-components-meta.js +2563 -0
  38. package/build/mall-components.cdn.umd.css +1 -0
  39. package/build/mall-components.cdn.umd.js +8 -0
  40. package/build/mall-components.codesandbox.combined.js +1094 -0
  41. package/build/mall-components.codesandbox.css +401 -0
  42. package/build/mall-components.codesandbox.js +1080 -0
  43. package/build/mall-components.umd.css +1 -0
  44. package/build/mall-components.umd.js +8 -0
  45. package/build/meta/adminLayoutMeta.d.ts +3 -0
  46. package/build/meta/couponCardMeta.d.ts +128 -0
  47. package/build/meta/icons.d.ts +10 -0
  48. package/build/meta/orderFormMeta.d.ts +111 -0
  49. package/build/meta/orderListMeta.d.ts +170 -0
  50. package/build/meta/productFormMeta.d.ts +3 -0
  51. package/build/meta/productListMeta.d.ts +200 -0
  52. package/build/meta/promotionCardMeta.d.ts +129 -0
  53. package/build/meta/roleCardMeta.d.ts +3 -0
  54. package/build/meta/tabPaneMeta.d.ts +3 -0
  55. package/build/meta/userCardMeta.d.ts +3 -0
  56. package/build/meta.d.ts +605 -0
  57. package/build/setters/RestApiTester.d.ts +11 -0
  58. package/build/types/common.d.ts +17 -0
  59. package/build/types/marketing.d.ts +128 -0
  60. package/build/types/order.d.ts +174 -0
  61. package/build/types/permission.d.ts +101 -0
  62. package/build/types/product.d.ts +47 -0
  63. package/package.json +1 -0
  64. package/src/adapters/DataSourceAdapter.ts +445 -0
  65. package/src/components/AdminLayout/AdminLayout.scss +447 -0
  66. package/src/components/AdminLayout/AdminLayout.tsx +681 -0
  67. package/src/components/AdminLayout/Breadcrumb.tsx +60 -0
  68. package/src/components/AdminLayout/MainContent.tsx +54 -0
  69. package/src/components/AdminLayout/Navbar.tsx +76 -0
  70. package/src/components/AdminLayout/Sidebar.tsx +256 -0
  71. package/src/components/AdminLayout/TabBar.tsx +177 -0
  72. package/src/components/AdminLayout/TabPane.tsx +29 -0
  73. package/src/components/AdminLayout/index.ts +3 -0
  74. package/src/components/AdminLayout/types.ts +46 -0
  75. package/src/components/CouponCard/CouponCard.scss +55 -0
  76. package/src/components/CouponCard/CouponCard.tsx +687 -0
  77. package/src/components/CouponCard/index.ts +1 -0
  78. package/src/components/OrderForm/OrderForm.scss +148 -0
  79. package/src/components/OrderForm/OrderForm.tsx +503 -0
  80. package/src/components/OrderForm/index.ts +1 -0
  81. package/src/components/OrderList/OrderList.scss +160 -0
  82. package/src/components/OrderList/OrderList.tsx +885 -0
  83. package/src/components/OrderList/index.ts +1 -0
  84. package/src/components/ProductForm/ProductForm.scss +23 -0
  85. package/src/components/ProductForm/ProductForm.tsx +442 -0
  86. package/src/components/ProductForm/index.ts +3 -0
  87. package/src/components/ProductList/ProductList.scss +293 -0
  88. package/src/components/ProductList/ProductList.tsx +454 -0
  89. package/src/components/ProductList/index.ts +3 -0
  90. package/src/components/PromotionCard/PromotionCard.scss +71 -0
  91. package/src/components/PromotionCard/PromotionCard.tsx +579 -0
  92. package/src/components/PromotionCard/index.ts +1 -0
  93. package/src/components/RoleCard/RoleCard.scss +77 -0
  94. package/src/components/RoleCard/RoleCard.tsx +463 -0
  95. package/src/components/RoleCard/index.ts +1 -0
  96. package/src/components/UserCard/UserCard.scss +51 -0
  97. package/src/components/UserCard/UserCard.tsx +432 -0
  98. package/src/components/UserCard/index.ts +1 -0
  99. package/src/entry-components.ts +39 -0
  100. package/src/entry-meta.ts +23 -0
  101. package/src/index.scss +4 -0
  102. package/src/index.ts +36 -0
  103. package/src/index.tsx +17 -0
  104. package/src/meta/adminLayoutMeta.ts +154 -0
  105. package/src/meta/couponCardMeta.ts +287 -0
  106. package/src/meta/icons.ts +41 -0
  107. package/src/meta/orderFormMeta.ts +279 -0
  108. package/src/meta/orderListMeta.ts +443 -0
  109. package/src/meta/productFormMeta.ts +253 -0
  110. package/src/meta/productListMeta.ts +434 -0
  111. package/src/meta/promotionCardMeta.ts +276 -0
  112. package/src/meta/roleCardMeta.ts +142 -0
  113. package/src/meta/tabPaneMeta.ts +69 -0
  114. package/src/meta/userCardMeta.ts +128 -0
  115. package/src/meta.ts +25 -0
  116. package/src/setters/RestApiTester.tsx +219 -0
  117. package/src/shims/require.js +8 -0
  118. package/src/types/common.ts +19 -0
  119. package/src/types/marketing.ts +124 -0
  120. package/src/types/order.ts +169 -0
  121. package/src/types/permission.ts +102 -0
  122. package/src/types/product.ts +49 -0
@@ -0,0 +1,463 @@
1
+ import React, { useState, useEffect } from 'react'
2
+ import {
3
+ Card,
4
+ Button,
5
+ Tag,
6
+ Space,
7
+ Modal,
8
+ Form,
9
+ Input,
10
+ Select,
11
+ message,
12
+ Table,
13
+ Divider,
14
+ Switch,
15
+ Tree,
16
+ } from 'antd'
17
+ import type { ColumnsType } from 'antd/es/table'
18
+ import {
19
+ PlusOutlined,
20
+ EditOutlined,
21
+ DeleteOutlined,
22
+ TeamOutlined,
23
+ } from '@ant-design/icons'
24
+ import type { UmsRole } from '../../types/permission'
25
+ import { ROLE_STATUS, ROLE_STATUS_OPTIONS } from '../../types/permission'
26
+ import './RoleCard.scss'
27
+
28
+ interface RoleCardProps {
29
+ dataSource?: string
30
+ showCreateButton?: boolean
31
+ showFilter?: boolean
32
+ showStatistics?: boolean
33
+ showPermissionTree?: boolean
34
+ onCreateRole?: (role: Partial<UmsRole>) => void
35
+ onEditRole?: (id: number, role: Partial<UmsRole>) => void
36
+ onDeleteRole?: (id: number) => void
37
+ onToggleStatus?: (id: number, status: number) => void
38
+ style?: React.CSSProperties
39
+ className?: string
40
+ }
41
+
42
+ const RoleCard: React.FC<RoleCardProps> = ({
43
+ dataSource,
44
+ showCreateButton = true,
45
+ showFilter = true,
46
+ showStatistics = true,
47
+ showPermissionTree = true,
48
+ onCreateRole,
49
+ onEditRole,
50
+ onDeleteRole,
51
+ onToggleStatus,
52
+ style,
53
+ className,
54
+ }) => {
55
+ const [loading, setLoading] = useState(false)
56
+ const [data, setData] = useState<UmsRole[]>([])
57
+ const [total, setTotal] = useState(0)
58
+ const [currentPage, setCurrentPage] = useState(1)
59
+ const [pageSize, setPageSize] = useState(10)
60
+ const [filterName, setFilterName] = useState('')
61
+ const [filterStatus, setFilterStatus] = useState<number>()
62
+ const [modalVisible, setModalVisible] = useState(false)
63
+ const [editingRole, setEditingRole] = useState<UmsRole | null>(null)
64
+ const [form] = Form.useForm()
65
+
66
+ const mockData: UmsRole[] = [
67
+ {
68
+ id: 1,
69
+ name: '超级管理员',
70
+ description: '拥有所有权限',
71
+ adminCount: 2,
72
+ status: ROLE_STATUS.ENABLED,
73
+ sort: 0,
74
+ createTime: '2024-01-01 10:00:00',
75
+ },
76
+ {
77
+ id: 2,
78
+ name: '运营',
79
+ description: '负责商品和订单管理',
80
+ adminCount: 5,
81
+ status: ROLE_STATUS.ENABLED,
82
+ sort: 1,
83
+ createTime: '2024-01-15 14:00:00',
84
+ },
85
+ {
86
+ id: 3,
87
+ name: '客服',
88
+ description: '负责订单处理和客户服务',
89
+ adminCount: 3,
90
+ status: ROLE_STATUS.ENABLED,
91
+ sort: 2,
92
+ createTime: '2024-02-01 09:00:00',
93
+ },
94
+ {
95
+ id: 4,
96
+ name: '访客',
97
+ description: '只读权限',
98
+ adminCount: 10,
99
+ status: ROLE_STATUS.DISABLED,
100
+ sort: 3,
101
+ createTime: '2024-02-15 11:00:00',
102
+ },
103
+ ]
104
+
105
+ const permissionTreeData = [
106
+ {
107
+ title: '商品管理',
108
+ key: 'product',
109
+ children: [
110
+ { title: '商品列表', key: 'product:list' },
111
+ { title: '添加商品', key: 'product:create' },
112
+ { title: '编辑商品', key: 'product:edit' },
113
+ { title: '删除商品', key: 'product:delete' },
114
+ ],
115
+ },
116
+ {
117
+ title: '订单管理',
118
+ key: 'order',
119
+ children: [
120
+ { title: '订单列表', key: 'order:list' },
121
+ { title: '订单详情', key: 'order:detail' },
122
+ { title: '发货', key: 'order:deliver' },
123
+ { title: '关闭订单', key: 'order:close' },
124
+ ],
125
+ },
126
+ {
127
+ title: '营销管理',
128
+ key: 'marketing',
129
+ children: [
130
+ { title: '优惠券管理', key: 'marketing:coupon' },
131
+ { title: '促销活动', key: 'marketing:promotion' },
132
+ ],
133
+ },
134
+ {
135
+ title: '权限管理',
136
+ key: 'permission',
137
+ children: [
138
+ { title: '用户管理', key: 'permission:user' },
139
+ { title: '角色管理', key: 'permission:role' },
140
+ ],
141
+ },
142
+ ]
143
+
144
+ useEffect(() => {
145
+ fetchData()
146
+ }, [currentPage, pageSize])
147
+
148
+ const fetchData = async () => {
149
+ setLoading(true)
150
+ try {
151
+ await new Promise((resolve) => setTimeout(resolve, 500))
152
+ let filtered = [...mockData]
153
+ if (filterName) {
154
+ filtered = filtered.filter(
155
+ (item) =>
156
+ item.name.toLowerCase().includes(filterName.toLowerCase()) ||
157
+ item.description?.toLowerCase().includes(filterName.toLowerCase())
158
+ )
159
+ }
160
+ if (filterStatus !== undefined) {
161
+ filtered = filtered.filter((item) => item.status === filterStatus)
162
+ }
163
+ setData(filtered)
164
+ setTotal(filtered.length)
165
+ } catch (error) {
166
+ console.error('Failed to fetch role list:', error)
167
+ message.error('获取角色列表失败')
168
+ } finally {
169
+ setLoading(false)
170
+ }
171
+ }
172
+
173
+ const handleSearch = () => {
174
+ setCurrentPage(1)
175
+ fetchData()
176
+ }
177
+
178
+ const handleReset = () => {
179
+ setFilterName('')
180
+ setFilterStatus(undefined)
181
+ setCurrentPage(1)
182
+ fetchData()
183
+ }
184
+
185
+ const handleCreate = () => {
186
+ setEditingRole(null)
187
+ form.resetFields()
188
+ setModalVisible(true)
189
+ }
190
+
191
+ const handleEdit = (record: UmsRole) => {
192
+ setEditingRole(record)
193
+ form.setFieldsValue(record)
194
+ setModalVisible(true)
195
+ }
196
+
197
+ const handleDelete = (id: number) => {
198
+ Modal.confirm({
199
+ title: '确认删除',
200
+ content: '确定要删除该角色吗?',
201
+ onOk: () => {
202
+ onDeleteRole?.(id)
203
+ message.success('删除成功')
204
+ fetchData()
205
+ },
206
+ })
207
+ }
208
+
209
+ const handleToggleStatus = (record: UmsRole) => {
210
+ const newStatus =
211
+ record.status === ROLE_STATUS.ENABLED ? ROLE_STATUS.DISABLED : ROLE_STATUS.ENABLED
212
+ onToggleStatus?.(record.id, newStatus)
213
+ message.success(newStatus === ROLE_STATUS.ENABLED ? '已启用' : '已禁用')
214
+ fetchData()
215
+ }
216
+
217
+ const handleSubmit = async () => {
218
+ try {
219
+ const values = await form.validateFields()
220
+ if (editingRole) {
221
+ onEditRole?.(editingRole.id, values)
222
+ message.success('编辑成功')
223
+ } else {
224
+ onCreateRole?.(values)
225
+ message.success('创建成功')
226
+ }
227
+ setModalVisible(false)
228
+ fetchData()
229
+ } catch (error) {
230
+ console.error('Validation failed:', error)
231
+ }
232
+ }
233
+
234
+ const getStatusTag = (status: number) => {
235
+ const statusMap: Record<number, { color: string; text: string }> = {
236
+ [ROLE_STATUS.ENABLED]: { color: 'success', text: '已启用' },
237
+ [ROLE_STATUS.DISABLED]: { color: 'default', text: '已禁用' },
238
+ }
239
+ const { color, text } = statusMap[status] || { color: 'default', text: '未知' }
240
+ return <Tag color={color}>{text}</Tag>
241
+ }
242
+
243
+ const columns: ColumnsType<UmsRole> = [
244
+ {
245
+ title: '角色名称',
246
+ dataIndex: 'name',
247
+ key: 'name',
248
+ width: 150,
249
+ render: (text: string) => (
250
+ <Space>
251
+ <TeamOutlined style={{ color: '#1890ff' }} />
252
+ <span className="role-name">{text}</span>
253
+ </Space>
254
+ ),
255
+ },
256
+ {
257
+ title: '描述',
258
+ dataIndex: 'description',
259
+ key: 'description',
260
+ width: 200,
261
+ },
262
+ {
263
+ title: '用户数',
264
+ dataIndex: 'adminCount',
265
+ key: 'adminCount',
266
+ width: 80,
267
+ render: (count: number) => (
268
+ <Tag color="blue">{count} 人</Tag>
269
+ ),
270
+ },
271
+ {
272
+ title: '状态',
273
+ dataIndex: 'status',
274
+ key: 'status',
275
+ width: 80,
276
+ render: (status: number) => getStatusTag(status),
277
+ },
278
+ {
279
+ title: '排序',
280
+ dataIndex: 'sort',
281
+ key: 'sort',
282
+ width: 60,
283
+ },
284
+ {
285
+ title: '创建时间',
286
+ dataIndex: 'createTime',
287
+ key: 'createTime',
288
+ width: 160,
289
+ },
290
+ {
291
+ title: '操作',
292
+ key: 'action',
293
+ width: 180,
294
+ render: (_, record) => (
295
+ <Space>
296
+ <Button
297
+ type="link"
298
+ size="small"
299
+ icon={<EditOutlined />}
300
+ onClick={() => handleEdit(record)}
301
+ >
302
+ 编辑
303
+ </Button>
304
+ <Button type="link" size="small" onClick={() => handleToggleStatus(record)}>
305
+ {record.status === ROLE_STATUS.ENABLED ? '禁用' : '启用'}
306
+ </Button>
307
+ <Button
308
+ type="link"
309
+ size="small"
310
+ danger
311
+ icon={<DeleteOutlined />}
312
+ onClick={() => handleDelete(record.id)}
313
+ >
314
+ 删除
315
+ </Button>
316
+ </Space>
317
+ ),
318
+ },
319
+ ]
320
+
321
+ const statistics = {
322
+ totalRoles: mockData.length,
323
+ activeRoles: mockData.filter((r) => r.status === ROLE_STATUS.ENABLED).length,
324
+ totalAdmins: mockData.reduce((sum, r) => sum + r.adminCount, 0),
325
+ }
326
+
327
+ return (
328
+ <div className={`mall-role-card ${className || ''}`} style={style}>
329
+ <Card>
330
+ {showStatistics && (
331
+ <div className="statistics-section">
332
+ <Space size="large">
333
+ <div className="stat-item">
334
+ <div className="stat-value">{statistics.totalRoles}</div>
335
+ <div className="stat-label">角色总数</div>
336
+ </div>
337
+ <Divider type="vertical" style={{ height: 40 }} />
338
+ <div className="stat-item">
339
+ <div className="stat-value" style={{ color: '#52c41a' }}>
340
+ {statistics.activeRoles}
341
+ </div>
342
+ <div className="stat-label">启用角色</div>
343
+ </div>
344
+ <Divider type="vertical" style={{ height: 40 }} />
345
+ <div className="stat-item">
346
+ <div className="stat-value" style={{ color: '#1890ff' }}>
347
+ {statistics.totalAdmins}
348
+ </div>
349
+ <div className="stat-label">用户总数</div>
350
+ </div>
351
+ </Space>
352
+ </div>
353
+ )}
354
+
355
+ {showFilter && (
356
+ <div className="filter-section">
357
+ <Space wrap>
358
+ <Input
359
+ placeholder="角色名称/描述"
360
+ value={filterName}
361
+ onChange={(e) => setFilterName(e.target.value)}
362
+ style={{ width: 200 }}
363
+ />
364
+ <Select
365
+ placeholder="角色状态"
366
+ value={filterStatus}
367
+ onChange={setFilterStatus}
368
+ style={{ width: 120 }}
369
+ allowClear
370
+ >
371
+ {ROLE_STATUS_OPTIONS.map((option) => (
372
+ <Select.Option key={option.value} value={option.value}>
373
+ {option.label}
374
+ </Select.Option>
375
+ ))}
376
+ </Select>
377
+ <Button type="primary" onClick={handleSearch}>
378
+ 查询
379
+ </Button>
380
+ <Button onClick={handleReset}>重置</Button>
381
+ </Space>
382
+ </div>
383
+ )}
384
+
385
+ {showCreateButton && (
386
+ <div className="action-section">
387
+ <Button type="primary" icon={<PlusOutlined />} onClick={handleCreate}>
388
+ 创建角色
389
+ </Button>
390
+ </div>
391
+ )}
392
+
393
+ <div className="content-section">
394
+ <div className="table-section">
395
+ <Table
396
+ columns={columns}
397
+ dataSource={data}
398
+ rowKey="id"
399
+ loading={loading}
400
+ pagination={{
401
+ current: currentPage,
402
+ pageSize,
403
+ total,
404
+ showSizeChanger: true,
405
+ showQuickJumper: true,
406
+ showTotal: (total) => `共 ${total} 条`,
407
+ onChange: (page, pageSize) => {
408
+ setCurrentPage(page)
409
+ setPageSize(pageSize)
410
+ },
411
+ }}
412
+ />
413
+ </div>
414
+
415
+ {showPermissionTree && (
416
+ <div className="permission-section">
417
+ <Card title="权限树" size="small">
418
+ <Tree
419
+ checkable
420
+ defaultExpandedKeys={['product', 'order']}
421
+ treeData={permissionTreeData}
422
+ />
423
+ </Card>
424
+ </div>
425
+ )}
426
+ </div>
427
+ </Card>
428
+
429
+ <Modal
430
+ title={editingRole ? '编辑角色' : '创建角色'}
431
+ visible={modalVisible}
432
+ onOk={handleSubmit}
433
+ onCancel={() => setModalVisible(false)}
434
+ width={500}
435
+ >
436
+ <Form form={form} layout="vertical">
437
+ <Form.Item
438
+ name="name"
439
+ label="角色名称"
440
+ rules={[{ required: true, message: '请输入角色名称' }]}
441
+ >
442
+ <Input placeholder="请输入角色名称" />
443
+ </Form.Item>
444
+ <Form.Item name="description" label="描述">
445
+ <Input.TextArea rows={3} placeholder="请输入角色描述" />
446
+ </Form.Item>
447
+ <Form.Item name="sort" label="排序" initialValue={0}>
448
+ <Input type="number" placeholder="排序值" />
449
+ </Form.Item>
450
+ <Form.Item name="status" label="状态" initialValue={ROLE_STATUS.ENABLED}>
451
+ <Switch
452
+ checkedChildren="启用"
453
+ unCheckedChildren="禁用"
454
+ defaultChecked
455
+ />
456
+ </Form.Item>
457
+ </Form>
458
+ </Modal>
459
+ </div>
460
+ )
461
+ }
462
+
463
+ export default RoleCard
@@ -0,0 +1 @@
1
+ export { default } from './RoleCard'
@@ -0,0 +1,51 @@
1
+ .mall-user-card {
2
+ .statistics-section {
3
+ padding: 16px;
4
+ background: linear-gradient(135deg, #e6f7ff 0%, #f0f5ff 100%);
5
+ border-radius: 4px;
6
+ margin-bottom: 16px;
7
+
8
+ .stat-item {
9
+ text-align: center;
10
+
11
+ .stat-value {
12
+ font-size: 24px;
13
+ font-weight: 600;
14
+ color: #1890ff;
15
+ }
16
+
17
+ .stat-label {
18
+ font-size: 12px;
19
+ color: #8c8c8c;
20
+ margin-top: 4px;
21
+ }
22
+ }
23
+ }
24
+
25
+ .filter-section {
26
+ margin-bottom: 16px;
27
+ padding: 16px;
28
+ background: #fafafa;
29
+ border-radius: 4px;
30
+ }
31
+
32
+ .action-section {
33
+ margin-bottom: 16px;
34
+ }
35
+
36
+ .user-name {
37
+ font-weight: 500;
38
+ color: #262626;
39
+ }
40
+
41
+ .user-username {
42
+ font-size: 12px;
43
+ color: #8c8c8c;
44
+ }
45
+
46
+ .ant-table {
47
+ .ant-tag {
48
+ margin: 0;
49
+ }
50
+ }
51
+ }