zant-admin 1.0.4 → 2.0.1

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 (94) hide show
  1. package/README.en.md +414 -25
  2. package/README.md +460 -285
  3. package/bin/cli.js +3 -3
  4. package/bin/generator.js +502 -502
  5. package/bin/prompts.js +158 -158
  6. package/bin/utils.js +133 -133
  7. package/package.json +2 -2
  8. package/public/logo.png +0 -0
  9. package/src/App.vue +16 -16
  10. package/src/api/methods/department.js +36 -0
  11. package/src/api/methods/employee.js +22 -0
  12. package/src/api/methods/logError.js +8 -8
  13. package/src/api/methods/logOperation.js +8 -8
  14. package/src/api/methods/login.js +6 -6
  15. package/src/api/methods/position.js +26 -0
  16. package/src/api/methods/quartz.js +36 -36
  17. package/src/api/methods/region.js +16 -16
  18. package/src/api/methods/sysAccount.js +29 -29
  19. package/src/api/methods/sysDict.js +29 -29
  20. package/src/api/methods/sysDictItem.js +26 -26
  21. package/src/api/methods/sysMenu.js +42 -42
  22. package/src/api/methods/sysRole.js +35 -35
  23. package/src/api/methods/sysUser.js +25 -25
  24. package/src/api/methods/system.js +15 -15
  25. package/src/api/request.js +225 -225
  26. package/src/assets/css/style.css +2 -2
  27. package/src/assets/css/zcui.css +1023 -1023
  28. package/src/assets/imgs/logo.png +0 -0
  29. package/src/assets/imgs/md/console.png +0 -0
  30. package/src/assets/imgs/md/login.png +0 -0
  31. package/src/assets/imgs/md/menu.png +0 -0
  32. package/src/assets/imgs/md/serviceMonitoring.png +0 -0
  33. package/src/assets/imgs/md/statistics.png +0 -0
  34. package/src/components/FormTable.vue +5 -19
  35. package/src/components/IconPicker.vue +351 -351
  36. package/src/components/MainPage.vue +838 -838
  37. package/src/components/details/logErrorDetails.vue +58 -58
  38. package/src/components/details/logOperationDetails.vue +76 -76
  39. package/src/components/edit/QuartzEdit.vue +221 -221
  40. package/src/components/edit/SysAccountEdit.vue +185 -185
  41. package/src/components/edit/SysDictEdit.vue +116 -116
  42. package/src/components/edit/SysDictItemEdit.vue +136 -136
  43. package/src/components/edit/SysRoleEdit.vue +111 -111
  44. package/src/components/edit/organizationalStructure/DepartmentEdit.vue +162 -0
  45. package/src/components/edit/organizationalStructure/EmployeeEdit.vue +295 -0
  46. package/src/components/edit/organizationalStructure/PositionEdit.vue +166 -0
  47. package/src/components/edit/sysMenuEdit.vue +2 -1
  48. package/src/config/index.js +74 -74
  49. package/src/directives/permission.js +49 -49
  50. package/src/main.js +37 -37
  51. package/src/router/index.js +4 -6
  52. package/src/stores/config.js +43 -43
  53. package/src/stores/dict.js +33 -33
  54. package/src/stores/menu.js +81 -81
  55. package/src/stores/user.js +21 -21
  56. package/src/utils/baseEcharts.js +661 -661
  57. package/src/utils/dictTemplate.js +26 -26
  58. package/src/utils/regionUtils.js +173 -173
  59. package/src/utils/useFormCRUD.js +59 -59
  60. package/src/views/baiscstatis/center.vue +474 -474
  61. package/src/views/baiscstatis/iframePage.vue +29 -29
  62. package/src/views/baiscstatis/notFound.vue +192 -192
  63. package/src/views/console.vue +821 -821
  64. package/src/views/demo/button.vue +269 -269
  65. package/src/views/demo/importexport.vue +119 -119
  66. package/src/views/demo/region.vue +322 -322
  67. package/src/views/demo/statistics.vue +214 -214
  68. package/src/views/home.vue +6 -6
  69. package/src/views/login.vue +264 -149
  70. package/src/views/operations/log/logError.vue +78 -78
  71. package/src/views/operations/log/logLogin.vue +66 -66
  72. package/src/views/operations/log/logOperation.vue +103 -103
  73. package/src/views/operations/log/logQuartz.vue +56 -56
  74. package/src/views/operations/quartz.vue +179 -179
  75. package/src/views/operations/serviceMonitoring.vue +134 -134
  76. package/src/views/organizationalStructure/department.vue +194 -0
  77. package/src/views/organizationalStructure/employee.vue +234 -0
  78. package/src/views/organizationalStructure/position.vue +196 -0
  79. package/src/views/system/sysAccount.vue +128 -128
  80. package/src/views/system/sysDict.vue +159 -159
  81. package/src/views/system/sysDictItem.vue +118 -118
  82. package/src/views/system/sysMenu.vue +225 -225
  83. package/src/views/system/sysRole.vue +207 -207
  84. package/src/assets/imgs/md/1.png +0 -0
  85. package/src/assets/imgs/md/10.png +0 -0
  86. package/src/assets/imgs/md/11.png +0 -0
  87. package/src/assets/imgs/md/2.png +0 -0
  88. package/src/assets/imgs/md/3.png +0 -0
  89. package/src/assets/imgs/md/4.png +0 -0
  90. package/src/assets/imgs/md/5.png +0 -0
  91. package/src/assets/imgs/md/6.png +0 -0
  92. package/src/assets/imgs/md/7.png +0 -0
  93. package/src/assets/imgs/md/8.png +0 -0
  94. package/src/assets/imgs/md/9.png +0 -0
@@ -1,351 +1,351 @@
1
- <template>
2
- <div class="icon-picker">
3
- <a-input-group compact>
4
- <a-input
5
- v-model:value="selectedIconName"
6
- placeholder="请选择图标"
7
- readonly
8
- style="width: calc(100% - 40px)"
9
- />
10
- <a-button type="primary" @click="showPicker = true" style="width: 40px">
11
- <template #icon>
12
- <SearchOutlined />
13
- </template>
14
- </a-button>
15
- </a-input-group>
16
-
17
- <!-- 图标选择弹窗 -->
18
- <a-modal
19
- v-model:open="showPicker"
20
- title="选择图标"
21
- width="800px"
22
- :footer="null"
23
- @cancel="showPicker = false"
24
- >
25
- <div class="icon-picker-modal">
26
- <!-- 搜索框 -->
27
- <div class="search-section">
28
- <a-input
29
- v-model:value="searchText"
30
- placeholder="搜索图标名称"
31
- allow-clear
32
- @change="handleSearch"
33
- >
34
- <template #prefix>
35
- <SearchOutlined />
36
- </template>
37
- </a-input>
38
- </div>
39
-
40
- <!-- 图标分类 -->
41
- <div class="category-section">
42
- <a-radio-group
43
- v-model:value="selectedCategory"
44
- @change="handleCategoryChange"
45
- >
46
- <a-radio-button value="all">全部</a-radio-button>
47
- <a-radio-button value="outlined">线框风格</a-radio-button>
48
- <a-radio-button value="filled">实底风格</a-radio-button>
49
- <a-radio-button value="twoTone">双色风格</a-radio-button>
50
- </a-radio-group>
51
- </div>
52
-
53
- <!-- 图标列表 -->
54
- <div class="icon-list-section">
55
- <a-spin :spinning="loading">
56
- <div class="icon-grid">
57
- <div
58
- v-for="icon in filteredIcons"
59
- :key="icon.name"
60
- class="icon-item"
61
- :class="{
62
- 'icon-item-selected': selectedIconName === icon.name,
63
- }"
64
- @click="selectIcon(icon)"
65
- >
66
- <div class="icon-wrapper">
67
- <component :is="icon.component" class="icon-display" />
68
- </div>
69
- <div class="icon-name">{{ icon.displayName }}</div>
70
- </div>
71
- </div>
72
- </a-spin>
73
- </div>
74
-
75
- <!-- 选中的图标预览 -->
76
- <div v-if="selectedIconName" class="selected-preview">
77
- <div class="preview-title">当前选中:</div>
78
- <div class="preview-content">
79
- <component :is="selectedIconComponent" class="preview-icon" />
80
- <span class="preview-name">{{ selectedIconName }}</span>
81
- </div>
82
- </div>
83
-
84
- <!-- 操作按钮 -->
85
- <div class="action-section">
86
- <a-space>
87
- <a-button type="primary" @click="confirmSelection"
88
- >确认选择</a-button
89
- >
90
- <a-button @click="clearSelection">清空</a-button>
91
- <a-button @click="showPicker = false">取消</a-button>
92
- </a-space>
93
- </div>
94
- </div>
95
- </a-modal>
96
- </div>
97
- </template>
98
-
99
- <script setup>
100
- import { ref, computed, onMounted } from 'vue'
101
- import * as Icons from '@ant-design/icons-vue'
102
- import { SearchOutlined } from '@ant-design/icons-vue'
103
-
104
- // 定义 props
105
- const props = defineProps({
106
- value: {
107
- type: String,
108
- default: '',
109
- },
110
- })
111
-
112
- // 定义 emits
113
- const emit = defineEmits(['update:value', 'change'])
114
-
115
- // 响应式数据
116
- const showPicker = ref(false)
117
- const searchText = ref('')
118
- const selectedCategory = ref('all')
119
- const loading = ref(false)
120
- const selectedIconName = ref(props.value)
121
-
122
- // 图标数据
123
- const allIcons = ref([])
124
-
125
- // 过滤后的图标列表
126
- const filteredIcons = computed(() => {
127
- let icons = allIcons.value
128
-
129
- // 按分类过滤
130
- if (selectedCategory.value !== 'all') {
131
- icons = icons.filter(icon => {
132
- if (selectedCategory.value === 'outlined') {
133
- return icon.name.endsWith('Outlined')
134
- } else if (selectedCategory.value === 'filled') {
135
- return icon.name.endsWith('Filled')
136
- } else if (selectedCategory.value === 'twoTone') {
137
- return icon.name.endsWith('TwoTone')
138
- }
139
- return true
140
- })
141
- }
142
-
143
- // 按搜索文本过滤
144
- if (searchText.value) {
145
- const searchLower = searchText.value.toLowerCase()
146
- icons = icons.filter(
147
- icon =>
148
- icon.displayName.toLowerCase().includes(searchLower) ||
149
- icon.name.toLowerCase().includes(searchLower),
150
- )
151
- }
152
-
153
- return icons
154
- })
155
-
156
- // 选中的图标组件
157
- const selectedIconComponent = computed(() => {
158
- if (!selectedIconName.value) return null
159
- return (
160
- allIcons.value.find(icon => icon.name === selectedIconName.value)
161
- ?.component || null
162
- )
163
- })
164
-
165
- // 初始化图标数据
166
- const initIcons = () => {
167
- loading.value = true
168
-
169
- // 过滤掉一些不常用的图标
170
- const excludedIcons = ['IconProvider', 'createFromIconfontCN']
171
-
172
- const iconList = Object.keys(Icons)
173
- .filter(key => !excludedIcons.includes(key))
174
- .map(key => ({
175
- name: key,
176
- displayName: key.replace(/([A-Z])/g, ' $1').trim(),
177
- component: Icons[key],
178
- }))
179
- .sort((a, b) => a.displayName.localeCompare(b.displayName))
180
-
181
- allIcons.value = iconList
182
- loading.value = false
183
- }
184
-
185
- // 处理搜索
186
- const handleSearch = () => {
187
- // 搜索逻辑已在 computed 中处理
188
- }
189
-
190
- // 处理分类变化
191
- const handleCategoryChange = () => {
192
- // 分类逻辑已在 computed 中处理
193
- }
194
-
195
- // 选择图标
196
- const selectIcon = icon => {
197
- selectedIconName.value = icon.name
198
- }
199
-
200
- // 确认选择
201
- const confirmSelection = () => {
202
- emit('update:value', selectedIconName.value)
203
- emit('change', selectedIconName.value)
204
- showPicker.value = false
205
- }
206
-
207
- // 清空选择
208
- const clearSelection = () => {
209
- selectedIconName.value = ''
210
- emit('update:value', '')
211
- emit('change', '')
212
- showPicker.value = false
213
- }
214
-
215
- // 监听外部 value 变化
216
- const updateSelectedIcon = newValue => {
217
- selectedIconName.value = newValue
218
- }
219
-
220
- // 暴露方法给父组件
221
- defineExpose({
222
- updateSelectedIcon,
223
- })
224
-
225
- // 生命周期
226
- onMounted(() => {
227
- initIcons()
228
- })
229
- </script>
230
-
231
- <style scoped>
232
- .icon-picker {
233
- width: 100%;
234
- }
235
-
236
- .icon-picker-modal {
237
- max-height: 60vh;
238
- overflow-y: auto;
239
- }
240
-
241
- .search-section {
242
- margin-bottom: 16px;
243
- }
244
-
245
- .category-section {
246
- margin-bottom: 16px;
247
- }
248
-
249
- .icon-list-section {
250
- margin-bottom: 16px;
251
- }
252
-
253
- .icon-grid {
254
- display: grid;
255
- grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
256
- gap: 12px;
257
- max-height: 300px;
258
- overflow-y: auto;
259
- padding: 8px 0;
260
- }
261
-
262
- .icon-item {
263
- display: flex;
264
- flex-direction: column;
265
- align-items: center;
266
- padding: 12px 8px;
267
- border: 1px solid #d9d9d9;
268
- border-radius: 6px;
269
- cursor: pointer;
270
- transition: all 0.3s;
271
- background: #fff;
272
- }
273
-
274
- .icon-item:hover {
275
- border-color: #1890ff;
276
- box-shadow: 0 2px 8px rgba(24, 144, 255, 0.1);
277
- }
278
-
279
- .icon-item-selected {
280
- border-color: #1890ff;
281
- background-color: #f0f8ff;
282
- }
283
-
284
- .icon-wrapper {
285
- display: flex;
286
- align-items: center;
287
- justify-content: center;
288
- width: 40px;
289
- height: 40px;
290
- margin-bottom: 8px;
291
- }
292
-
293
- .icon-display {
294
- font-size: 24px;
295
- color: #666;
296
- }
297
-
298
- .icon-item:hover .icon-display,
299
- .icon-item-selected .icon-display {
300
- color: #1890ff;
301
- }
302
-
303
- .icon-name {
304
- font-size: 12px;
305
- color: #666;
306
- text-align: center;
307
- word-break: break-all;
308
- line-height: 1.2;
309
- }
310
-
311
- .selected-preview {
312
- padding: 16px;
313
- border-top: 1px solid #f0f0f0;
314
- margin-top: 16px;
315
- background: #fafafa;
316
- border-radius: 6px;
317
- }
318
-
319
- .preview-title {
320
- font-weight: 500;
321
- margin-bottom: 8px;
322
- color: #333;
323
- }
324
-
325
- .preview-content {
326
- display: flex;
327
- align-items: center;
328
- gap: 12px;
329
- }
330
-
331
- .preview-icon {
332
- font-size: 24px;
333
- color: #1890ff;
334
- }
335
-
336
- .preview-name {
337
- font-family: monospace;
338
- background: #f5f5f5;
339
- padding: 4px 8px;
340
- border-radius: 4px;
341
- font-size: 14px;
342
- }
343
-
344
- .action-section {
345
- display: flex;
346
- justify-content: flex-end;
347
- margin-top: 16px;
348
- padding-top: 16px;
349
- border-top: 1px solid #f0f0f0;
350
- }
351
- </style>
1
+ <template>
2
+ <div class="icon-picker">
3
+ <a-input-group compact>
4
+ <a-input
5
+ v-model:value="selectedIconName"
6
+ placeholder="请选择图标"
7
+ readonly
8
+ style="width: calc(100% - 40px)"
9
+ />
10
+ <a-button type="primary" @click="showPicker = true" style="width: 40px">
11
+ <template #icon>
12
+ <SearchOutlined />
13
+ </template>
14
+ </a-button>
15
+ </a-input-group>
16
+
17
+ <!-- 图标选择弹窗 -->
18
+ <a-modal
19
+ v-model:open="showPicker"
20
+ title="选择图标"
21
+ width="800px"
22
+ :footer="null"
23
+ @cancel="showPicker = false"
24
+ >
25
+ <div class="icon-picker-modal">
26
+ <!-- 搜索框 -->
27
+ <div class="search-section">
28
+ <a-input
29
+ v-model:value="searchText"
30
+ placeholder="搜索图标名称"
31
+ allow-clear
32
+ @change="handleSearch"
33
+ >
34
+ <template #prefix>
35
+ <SearchOutlined />
36
+ </template>
37
+ </a-input>
38
+ </div>
39
+
40
+ <!-- 图标分类 -->
41
+ <div class="category-section">
42
+ <a-radio-group
43
+ v-model:value="selectedCategory"
44
+ @change="handleCategoryChange"
45
+ >
46
+ <a-radio-button value="all">全部</a-radio-button>
47
+ <a-radio-button value="outlined">线框风格</a-radio-button>
48
+ <a-radio-button value="filled">实底风格</a-radio-button>
49
+ <a-radio-button value="twoTone">双色风格</a-radio-button>
50
+ </a-radio-group>
51
+ </div>
52
+
53
+ <!-- 图标列表 -->
54
+ <div class="icon-list-section">
55
+ <a-spin :spinning="loading">
56
+ <div class="icon-grid">
57
+ <div
58
+ v-for="icon in filteredIcons"
59
+ :key="icon.name"
60
+ class="icon-item"
61
+ :class="{
62
+ 'icon-item-selected': selectedIconName === icon.name,
63
+ }"
64
+ @click="selectIcon(icon)"
65
+ >
66
+ <div class="icon-wrapper">
67
+ <component :is="icon.component" class="icon-display" />
68
+ </div>
69
+ <div class="icon-name">{{ icon.displayName }}</div>
70
+ </div>
71
+ </div>
72
+ </a-spin>
73
+ </div>
74
+
75
+ <!-- 选中的图标预览 -->
76
+ <div v-if="selectedIconName" class="selected-preview">
77
+ <div class="preview-title">当前选中:</div>
78
+ <div class="preview-content">
79
+ <component :is="selectedIconComponent" class="preview-icon" />
80
+ <span class="preview-name">{{ selectedIconName }}</span>
81
+ </div>
82
+ </div>
83
+
84
+ <!-- 操作按钮 -->
85
+ <div class="action-section">
86
+ <a-space>
87
+ <a-button type="primary" @click="confirmSelection"
88
+ >确认选择</a-button
89
+ >
90
+ <a-button @click="clearSelection">清空</a-button>
91
+ <a-button @click="showPicker = false">取消</a-button>
92
+ </a-space>
93
+ </div>
94
+ </div>
95
+ </a-modal>
96
+ </div>
97
+ </template>
98
+
99
+ <script setup>
100
+ import { ref, computed, onMounted } from 'vue'
101
+ import * as Icons from '@ant-design/icons-vue'
102
+ import { SearchOutlined } from '@ant-design/icons-vue'
103
+
104
+ // 定义 props
105
+ const props = defineProps({
106
+ value: {
107
+ type: String,
108
+ default: '',
109
+ },
110
+ })
111
+
112
+ // 定义 emits
113
+ const emit = defineEmits(['update:value', 'change'])
114
+
115
+ // 响应式数据
116
+ const showPicker = ref(false)
117
+ const searchText = ref('')
118
+ const selectedCategory = ref('all')
119
+ const loading = ref(false)
120
+ const selectedIconName = ref(props.value)
121
+
122
+ // 图标数据
123
+ const allIcons = ref([])
124
+
125
+ // 过滤后的图标列表
126
+ const filteredIcons = computed(() => {
127
+ let icons = allIcons.value
128
+
129
+ // 按分类过滤
130
+ if (selectedCategory.value !== 'all') {
131
+ icons = icons.filter(icon => {
132
+ if (selectedCategory.value === 'outlined') {
133
+ return icon.name.endsWith('Outlined')
134
+ } else if (selectedCategory.value === 'filled') {
135
+ return icon.name.endsWith('Filled')
136
+ } else if (selectedCategory.value === 'twoTone') {
137
+ return icon.name.endsWith('TwoTone')
138
+ }
139
+ return true
140
+ })
141
+ }
142
+
143
+ // 按搜索文本过滤
144
+ if (searchText.value) {
145
+ const searchLower = searchText.value.toLowerCase()
146
+ icons = icons.filter(
147
+ icon =>
148
+ icon.displayName.toLowerCase().includes(searchLower) ||
149
+ icon.name.toLowerCase().includes(searchLower),
150
+ )
151
+ }
152
+
153
+ return icons
154
+ })
155
+
156
+ // 选中的图标组件
157
+ const selectedIconComponent = computed(() => {
158
+ if (!selectedIconName.value) return null
159
+ return (
160
+ allIcons.value.find(icon => icon.name === selectedIconName.value)
161
+ ?.component || null
162
+ )
163
+ })
164
+
165
+ // 初始化图标数据
166
+ const initIcons = () => {
167
+ loading.value = true
168
+
169
+ // 过滤掉一些不常用的图标
170
+ const excludedIcons = ['IconProvider', 'createFromIconfontCN']
171
+
172
+ const iconList = Object.keys(Icons)
173
+ .filter(key => !excludedIcons.includes(key))
174
+ .map(key => ({
175
+ name: key,
176
+ displayName: key.replace(/([A-Z])/g, ' $1').trim(),
177
+ component: Icons[key],
178
+ }))
179
+ .sort((a, b) => a.displayName.localeCompare(b.displayName))
180
+
181
+ allIcons.value = iconList
182
+ loading.value = false
183
+ }
184
+
185
+ // 处理搜索
186
+ const handleSearch = () => {
187
+ // 搜索逻辑已在 computed 中处理
188
+ }
189
+
190
+ // 处理分类变化
191
+ const handleCategoryChange = () => {
192
+ // 分类逻辑已在 computed 中处理
193
+ }
194
+
195
+ // 选择图标
196
+ const selectIcon = icon => {
197
+ selectedIconName.value = icon.name
198
+ }
199
+
200
+ // 确认选择
201
+ const confirmSelection = () => {
202
+ emit('update:value', selectedIconName.value)
203
+ emit('change', selectedIconName.value)
204
+ showPicker.value = false
205
+ }
206
+
207
+ // 清空选择
208
+ const clearSelection = () => {
209
+ selectedIconName.value = ''
210
+ emit('update:value', '')
211
+ emit('change', '')
212
+ showPicker.value = false
213
+ }
214
+
215
+ // 监听外部 value 变化
216
+ const updateSelectedIcon = newValue => {
217
+ selectedIconName.value = newValue
218
+ }
219
+
220
+ // 暴露方法给父组件
221
+ defineExpose({
222
+ updateSelectedIcon,
223
+ })
224
+
225
+ // 生命周期
226
+ onMounted(() => {
227
+ initIcons()
228
+ })
229
+ </script>
230
+
231
+ <style scoped>
232
+ .icon-picker {
233
+ width: 100%;
234
+ }
235
+
236
+ .icon-picker-modal {
237
+ max-height: 60vh;
238
+ overflow-y: auto;
239
+ }
240
+
241
+ .search-section {
242
+ margin-bottom: 16px;
243
+ }
244
+
245
+ .category-section {
246
+ margin-bottom: 16px;
247
+ }
248
+
249
+ .icon-list-section {
250
+ margin-bottom: 16px;
251
+ }
252
+
253
+ .icon-grid {
254
+ display: grid;
255
+ grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
256
+ gap: 12px;
257
+ max-height: 300px;
258
+ overflow-y: auto;
259
+ padding: 8px 0;
260
+ }
261
+
262
+ .icon-item {
263
+ display: flex;
264
+ flex-direction: column;
265
+ align-items: center;
266
+ padding: 12px 8px;
267
+ border: 1px solid #d9d9d9;
268
+ border-radius: 6px;
269
+ cursor: pointer;
270
+ transition: all 0.3s;
271
+ background: #fff;
272
+ }
273
+
274
+ .icon-item:hover {
275
+ border-color: #1890ff;
276
+ box-shadow: 0 2px 8px rgba(24, 144, 255, 0.1);
277
+ }
278
+
279
+ .icon-item-selected {
280
+ border-color: #1890ff;
281
+ background-color: #f0f8ff;
282
+ }
283
+
284
+ .icon-wrapper {
285
+ display: flex;
286
+ align-items: center;
287
+ justify-content: center;
288
+ width: 40px;
289
+ height: 40px;
290
+ margin-bottom: 8px;
291
+ }
292
+
293
+ .icon-display {
294
+ font-size: 24px;
295
+ color: #666;
296
+ }
297
+
298
+ .icon-item:hover .icon-display,
299
+ .icon-item-selected .icon-display {
300
+ color: #1890ff;
301
+ }
302
+
303
+ .icon-name {
304
+ font-size: 12px;
305
+ color: #666;
306
+ text-align: center;
307
+ word-break: break-all;
308
+ line-height: 1.2;
309
+ }
310
+
311
+ .selected-preview {
312
+ padding: 16px;
313
+ border-top: 1px solid #f0f0f0;
314
+ margin-top: 16px;
315
+ background: #fafafa;
316
+ border-radius: 6px;
317
+ }
318
+
319
+ .preview-title {
320
+ font-weight: 500;
321
+ margin-bottom: 8px;
322
+ color: #333;
323
+ }
324
+
325
+ .preview-content {
326
+ display: flex;
327
+ align-items: center;
328
+ gap: 12px;
329
+ }
330
+
331
+ .preview-icon {
332
+ font-size: 24px;
333
+ color: #1890ff;
334
+ }
335
+
336
+ .preview-name {
337
+ font-family: monospace;
338
+ background: #f5f5f5;
339
+ padding: 4px 8px;
340
+ border-radius: 4px;
341
+ font-size: 14px;
342
+ }
343
+
344
+ .action-section {
345
+ display: flex;
346
+ justify-content: flex-end;
347
+ margin-top: 16px;
348
+ padding-top: 16px;
349
+ border-top: 1px solid #f0f0f0;
350
+ }
351
+ </style>