@ebiz/designer-components 0.0.18 → 0.0.19

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 (99) hide show
  1. package/package.json +3 -2
  2. package/src/apiService/mockDataService.js +116 -0
  3. package/src/apiService/simpleDataService.js +186 -80
  4. package/src/components/Button.vue +72 -22
  5. package/src/components/EbizAvatar.vue +116 -0
  6. package/src/components/EbizCheckbox.vue +94 -0
  7. package/src/components/EbizCheckboxGroup.vue +70 -0
  8. package/src/components/EbizDetailBlock.vue +82 -0
  9. package/src/components/EbizDialog.vue +244 -56
  10. package/src/components/EbizEmployeeInfo.vue +139 -0
  11. package/src/components/EbizFileUpload.vue +202 -0
  12. package/src/components/EbizPageHeader.vue +96 -0
  13. package/src/components/EbizPagination.vue +163 -0
  14. package/src/components/EbizRadio.vue +87 -0
  15. package/src/components/EbizRadioGroup.vue +84 -0
  16. package/src/components/EbizRemoteSelect.vue +118 -40
  17. package/src/components/EbizSpace.vue +101 -0
  18. package/src/components/EbizStatistic.vue +150 -0
  19. package/src/components/EbizSwiper.vue +114 -0
  20. package/src/components/EbizSwiperItem.vue +14 -0
  21. package/src/components/EbizSwitch.vue +86 -0
  22. package/src/components/EbizTabHeader.vue +145 -0
  23. package/src/components/EbizTabPanel.vue +23 -0
  24. package/src/components/EbizTable.vue +466 -0
  25. package/src/components/EbizTableColumn.vue +117 -0
  26. package/src/components/EbizTableSort.vue +181 -0
  27. package/src/components/EbizTabs.vue +133 -91
  28. package/src/components/EbizTimePicker.vue +144 -0
  29. package/src/components/EbizTitle.vue +3 -10
  30. package/src/components/EbizTree.vue +153 -0
  31. package/src/components/EbizTreeSelector.vue +423 -0
  32. package/src/components/Home.vue +8 -0
  33. package/src/components/TdesignAlert.vue +116 -0
  34. package/src/components/TdesignButton.vue +130 -0
  35. package/src/components/TdesignCalendar/index.vue +146 -0
  36. package/src/components/TdesignCard.vue +196 -0
  37. package/src/components/TdesignCol.vue +102 -0
  38. package/src/components/TdesignCollapse.vue +143 -0
  39. package/src/components/TdesignCollapsePanel.vue +80 -0
  40. package/src/components/TdesignDatePicker.vue +125 -0
  41. package/src/components/TdesignDialog.vue +226 -0
  42. package/src/components/TdesignForm.vue +134 -0
  43. package/src/components/TdesignFormItem.vue +106 -0
  44. package/src/components/TdesignGrid.vue +56 -0
  45. package/src/components/TdesignIcon.vue +68 -0
  46. package/src/components/TdesignImage.vue +163 -0
  47. package/src/components/TdesignImageViewer.vue +201 -0
  48. package/src/components/TdesignInput.vue +243 -0
  49. package/src/components/TdesignSelect.vue +445 -0
  50. package/src/components/TdesignTag.vue +118 -0
  51. package/src/components/TdesignTextarea.vue +143 -0
  52. package/src/components/TdesignTimeline.vue +58 -0
  53. package/src/components/TdesignTimelineItem.vue +72 -0
  54. package/src/components/TdesignUpload.vue +757 -0
  55. package/src/components/TdesignWatermark.vue +108 -0
  56. package/src/index.js +130 -0
  57. package/src/main.js +20 -4
  58. package/src/router/index.js +244 -5
  59. package/src/views/Button.vue +7 -3
  60. package/src/views/CheckboxDemo.vue +105 -0
  61. package/src/views/DialogDemo.vue +126 -0
  62. package/src/views/EbizAvatar.vue +224 -0
  63. package/src/views/EbizDetailBlockDemo.vue +31 -0
  64. package/src/views/EbizEmployeeInfo.vue +250 -0
  65. package/src/views/EbizRadioDemo.vue +152 -0
  66. package/src/views/EbizSpace.vue +186 -0
  67. package/src/views/EbizSwiper.vue +158 -0
  68. package/src/views/GridDemo.vue +239 -0
  69. package/src/views/Home.vue +63 -2
  70. package/src/views/PageHeaderDemo.vue +105 -0
  71. package/src/views/PaginationDemo.vue +97 -0
  72. package/src/views/RemoteSelect.vue +336 -5
  73. package/src/views/StatisticDemo.vue +191 -0
  74. package/src/views/SwitchDemo.vue +80 -0
  75. package/src/views/TableDemo.vue +335 -0
  76. package/src/views/TableSortDemo.vue +144 -0
  77. package/src/views/TableView.vue +69 -0
  78. package/src/views/TabsDemo.vue +283 -0
  79. package/src/views/TagDemo.vue +102 -0
  80. package/src/views/TdesignAlert.vue +99 -0
  81. package/src/views/TdesignButton.vue +191 -0
  82. package/src/views/TdesignCalendar.vue +95 -0
  83. package/src/views/TdesignCard.vue +297 -0
  84. package/src/views/TdesignCollapse.vue +294 -0
  85. package/src/views/TdesignDatePicker.vue +188 -0
  86. package/src/views/TdesignForm.vue +249 -0
  87. package/src/views/TdesignIcon.vue +204 -0
  88. package/src/views/TdesignImage.vue +216 -0
  89. package/src/views/TdesignImageViewer.vue +199 -0
  90. package/src/views/TdesignInput.vue +253 -0
  91. package/src/views/TdesignSelect.vue +474 -0
  92. package/src/views/TdesignSwiper.vue +158 -0
  93. package/src/views/TextareaDemo.vue +94 -0
  94. package/src/views/TimePickerDemo.vue +147 -0
  95. package/src/views/TimelineDemo.vue +161 -0
  96. package/src/views/TreeDemo.vue +255 -0
  97. package/src/views/TreeSelectorDemo.vue +246 -0
  98. package/src/views/UploadDemo.vue +122 -0
  99. package/src/views/WatermarkDemo.vue +86 -0
@@ -1,11 +1,11 @@
1
1
  <template>
2
2
  <div class="ebiz-title">
3
3
  <div class="color-block" :style="{ backgroundColor: color, width: `${blockWidth}px` }"></div>
4
- <h2 class="title-text">
4
+ <div class="title-text">
5
5
  <slot name="title">
6
6
  {{ displayTitle }}
7
7
  </slot>
8
- </h2>
8
+ </div>
9
9
  </div>
10
10
  </template>
11
11
 
@@ -19,13 +19,6 @@ import { defineProps, computed } from 'vue';
19
19
  * 支持通过插槽自定义标题内容
20
20
  */
21
21
  const props = defineProps({
22
- apiConfig: {
23
- type: Object,
24
- default: () => ({
25
- apiId: 0,
26
- apiType: 'select-list',
27
- })
28
- },
29
22
  /**
30
23
  * 标题文本 (当不使用插槽时显示)
31
24
  */
@@ -49,7 +42,7 @@ const props = defineProps({
49
42
  }
50
43
  });
51
44
 
52
- // 计算属性:根据点号数量生成显示的标题
45
+
53
46
  const displayTitle = computed(() => {
54
47
  return props.title;
55
48
  });
@@ -0,0 +1,153 @@
1
+ <template>
2
+ <t-tree
3
+ ref="treeRef"
4
+ v-bind="$attrs"
5
+ :data="data"
6
+ :value="modelValue"
7
+ :expanded="expandedModel"
8
+ :actived="activedModel"
9
+ :transition="transition"
10
+ :disable-check="disableCheck"
11
+ :keys="keys"
12
+ @change="handleChange"
13
+ @expand="handleExpand"
14
+ @active="handleActive"
15
+ @select="$emit('select', $event)"
16
+ @drag-start="$emit('drag-start', $event)"
17
+ @drag-end="$emit('drag-end', $event)"
18
+ @drag-over="$emit('drag-over', $event)"
19
+ @drag-leave="$emit('drag-leave', $event)"
20
+ @drag-drop="$emit('drag-drop', $event)"
21
+ @click="$emit('click', $event)"
22
+ @load="$emit('load', $event)"
23
+ >
24
+ <template v-if="$slots.default" #default="slotProps">
25
+ <slot :node="slotProps.node"></slot>
26
+ </template>
27
+ <template v-if="$slots.empty" #empty>
28
+ <slot name="empty"></slot>
29
+ </template>
30
+ <template v-if="$slots.icon" #icon="slotProps">
31
+ <slot name="icon" :node="slotProps.node"></slot>
32
+ </template>
33
+ <template v-if="$slots.label" #label="slotProps">
34
+ <slot name="label" :node="slotProps.node"></slot>
35
+ </template>
36
+ <template v-if="$slots.line" #line="slotProps">
37
+ <slot name="line" :node="slotProps.node"></slot>
38
+ </template>
39
+ <template v-if="$slots.operations" #operations="slotProps">
40
+ <slot name="operations" :node="slotProps.node"></slot>
41
+ </template>
42
+ </t-tree>
43
+ </template>
44
+
45
+ <script setup>
46
+ import { Tree as TTree } from 'tdesign-vue-next';
47
+ import { computed ,ref} from 'vue';
48
+
49
+ // 定义组件属性
50
+ const props = defineProps({
51
+ // 选中值
52
+ modelValue: {
53
+ type: Array,
54
+ default: () => []
55
+ },
56
+ // 展开节点
57
+ expanded: {
58
+ type: Array,
59
+ default: () => []
60
+ },
61
+ // 激活节点
62
+ actived: {
63
+ type: Array,
64
+ default: () => []
65
+ },
66
+ // 数据
67
+ items: {
68
+ type: Array,
69
+ default: () => []
70
+ },
71
+ // 是否启用过渡动画
72
+ transition: {
73
+ type: Boolean,
74
+ default: false
75
+ },
76
+ // 自定义节点禁用状态,返回true表示禁用
77
+ disableCheck: {
78
+ type: Function,
79
+ default: null
80
+ },
81
+ // 自定义节点数据中的字段名称
82
+ keys: {
83
+ type: Object,
84
+ default: () => ({
85
+ label: 'label',
86
+ value: 'value',
87
+ children: 'children'
88
+ })
89
+ }
90
+ });
91
+
92
+ const treeRef = ref();
93
+ // 定义组件事件
94
+ const emit = defineEmits([
95
+ 'update:modelValue',
96
+ 'update:expanded',
97
+ 'update:actived',
98
+ 'change',
99
+ 'expand',
100
+ 'active',
101
+ 'select',
102
+ 'click',
103
+ 'load',
104
+ 'drag-start',
105
+ 'drag-end',
106
+ 'drag-over',
107
+ 'drag-leave',
108
+ 'drag-drop'
109
+ ]);
110
+
111
+ // 处理items映射到data
112
+ const data = computed(() => props.items);
113
+
114
+ // 展开事件
115
+ const expandedModel = computed({
116
+ get: () => props.expanded,
117
+ set: (val) => emit('update:expanded', val)
118
+ });
119
+
120
+ // 激活节点
121
+ const activedModel = computed({
122
+ get: () => props.actived,
123
+ set: (val) => emit('update:actived', val)
124
+ });
125
+
126
+ // 值改变事件
127
+ const handleChange = (val, context) => {
128
+ emit('update:modelValue', val);
129
+ emit('change', val, context);
130
+ };
131
+
132
+ // 节点展开事件
133
+ const handleExpand = (val, context) => {
134
+ emit('update:expanded', val);
135
+ emit('expand', val, context);
136
+ };
137
+
138
+ // 节点激活事件
139
+ const handleActive = (val, context) => {
140
+ emit('update:actived', val);
141
+ emit('active', val, context);
142
+ };
143
+
144
+ defineExpose({
145
+ treeRef
146
+ });
147
+ </script>
148
+
149
+ <style>
150
+ .t-tree {
151
+ width: 100%;
152
+ }
153
+ </style>
@@ -0,0 +1,423 @@
1
+ <template>
2
+ <div class="ebiz-tree-selector">
3
+ <div class="selected-items" v-if="modelValue && modelValue.length">
4
+ <div v-for="(item, index) in modelValue" :key="index" class="selected-item">
5
+ <span class="item-text">{{ item.label }}</span>
6
+ <span class="item-remove" @click.stop="removeItem(index)">×</span>
7
+ </div>
8
+ </div>
9
+ <t-button @click="showDialog" variant="text" theme="primary" size="small"> 添加 </t-button>
10
+
11
+ <EbizDialog v-model:visible="dialogVisible" header="选择人员/部门" width="800px" placement="center" confirmBtn="确定"
12
+ cancelBtn="取消" @confirm="handleConfirm" @cancel="handleCancel">
13
+ <div class="selector-container">
14
+ <!-- 左侧选择区域 -->
15
+ <div class="left-panel">
16
+ <!-- 顶部搜索区域 -->
17
+ <div class="search-box">
18
+ <t-input v-model="searchText" placeholder="搜索成员、部门或标签" clearable>
19
+ <template #suffix-icon>
20
+ <t-icon name="search"></t-icon>
21
+ </template>
22
+ </t-input>
23
+ </div>
24
+
25
+ <!-- 选项卡 -->
26
+ <t-tabs v-model="activeTab" class="selector-tabs">
27
+ <t-tab-panel value="organization" label="组织架构" :destroyOnHide="false">
28
+
29
+ </t-tab-panel>
30
+ <!-- <t-tab-panel value="department" label="部门"></t-tab-panel> -->
31
+ <!-- <t-tab-panel value="position" label="岗位"></t-tab-panel> -->
32
+ <t-tab-panel value="employee" label="员工"></t-tab-panel>
33
+ </t-tabs>
34
+
35
+ <!-- 树形结构区域 -->
36
+ <div class="tree-content">
37
+ <div v-if="loading" class="loading-container">
38
+ <t-loading />
39
+ </div>
40
+ <EbizTree ref="organizationTree" v-show="activeTab === 'organization'" checkable :items="organizationData"
41
+ v-model="checkedNodes" v-model:expanded="expandedNodes" :disable-check="disableCheck"
42
+ :keys="{ label: 'name', value: 'id', children: 'childs' }" @change="handleChange" />
43
+ <!-- <EbizTree
44
+ v-else-if="activeTab === 'department'"
45
+ checkable
46
+ :items="filteredData."
47
+ v-model="checkedNodes"
48
+ :disable-check="disableCheck"
49
+ />
50
+ <EbizTree
51
+ v-else-if="activeTab === 'position'"
52
+ checkable
53
+ :items="filteredData.position"
54
+ v-model="checkedNodes"
55
+ :disable-check="disableCheck"
56
+ /> -->
57
+ <EbizTree ref="employeeTree" v-show="activeTab === 'employee'" checkable :items="employeeData"
58
+ :keys="{ label: 'label', value: 'bindid', children: 'childs' }" v-model="checkedUserNodes"
59
+ :disable-check="disableCheck" />
60
+ </div>
61
+ </div>
62
+
63
+ <!-- 右侧已选区域 -->
64
+ <div class="right-panel">
65
+ <div class="selected-title">已选择的部门、成员</div>
66
+ <div class="selected-count">共 {{ [...selectPreview, ...selectPreviewUser].length }} 项</div>
67
+ <div class="selected-list">
68
+ <div v-for="(item, index) in [...selectPreview,...selectPreviewUser]" :key="index"
69
+ class="selected-list-item">
70
+ <t-icon :name="getIconForType(item)" class="item-icon" />
71
+ <span class="selected-label">{{ item.label }}</span>
72
+ <t-icon name="close-circle" class="remove-icon" @click="removePreviewItem(item)" />
73
+ </div>
74
+ <div v-if="[...selectPreview, ...selectPreviewUser].length === 0" class="no-selection">
75
+ <t-icon name="info-circle" />
76
+ <span style="user-select: none">请在左侧选择部门或成员</span>
77
+ </div>
78
+ </div>
79
+ </div>
80
+ </div>
81
+ </EbizDialog>
82
+ </div>
83
+ </template>
84
+
85
+ <script setup>
86
+ import { onMounted, ref, watch } from 'vue'
87
+ import {
88
+ Button as TButton,
89
+ Icon as TIcon,
90
+ Input as TInput,
91
+ Loading as TLoading,
92
+ TabPanel as TTabPanel,
93
+ Tabs as TTabs
94
+ } from 'tdesign-vue-next'
95
+ import EbizDialog from './TdesignDialog.vue'
96
+ import EbizTree from './EbizTree.vue'
97
+ import dataService from '../apiService/simpleDataService'
98
+
99
+ const props = defineProps({
100
+ // 选中的数据,支持v-model
101
+ modelValue: {
102
+ type: Array,
103
+ default: () => []
104
+ },
105
+ // 树形数据,可以是单个数组或分类对象
106
+ data: {
107
+ type: [Array, Object],
108
+ default: () => []
109
+ },
110
+ // 禁用选择的节点
111
+ disableCheck: {
112
+ type: Function,
113
+ default: null
114
+ },
115
+ // 标题
116
+ title: {
117
+ type: String,
118
+ default: '选择人员/部门'
119
+ }
120
+ })
121
+
122
+ const emit = defineEmits(['update:modelValue', 'change'])
123
+
124
+ // 弹窗显示状态
125
+ const dialogVisible = ref(false)
126
+ // 搜索文本
127
+ const searchText = ref('')
128
+ // 选中的节点
129
+ const checkedNodes = ref([])
130
+ const checkedUserNodes = ref([]);
131
+ // 展开的节点
132
+ const expandedNodes = ref([])
133
+ // 当前活动的选项卡
134
+ const activeTab = ref('organization')
135
+ // 弹窗内预览的选中项
136
+ const selectPreview = ref([])
137
+ const selectPreviewUser = ref([])
138
+ // 加载状态
139
+ const loading = ref(false)
140
+ // API返回的数据
141
+ const organizationData = ref([])
142
+ const employeeData = ref([])
143
+ const organizationTree = ref()
144
+ const employeeTree = ref()
145
+
146
+ // 获取API数据
147
+ const fetchApiData = async () => {
148
+ loading.value = true
149
+ try {
150
+ organizationData.value = await dataService.fetch(
151
+ { keyWord: activeTab.value === 'organization' ? searchText.value : '' },
152
+ {},
153
+ '/appdata/execute/plugin?key=organizational_structure'
154
+ )
155
+ employeeData.value = (await dataService.fetch(
156
+ {keyWord:activeTab.value === 'employee' ? searchText.value : ''},
157
+ {},
158
+ "/appdata/execute/plugin?key=all_active_employesse"
159
+ )).map(i=>({
160
+ label:i.name,
161
+ bindid:i.id,
162
+ type:'employee'
163
+ }))
164
+ } catch (error) {
165
+ } finally {
166
+ loading.value = false
167
+ }
168
+ }
169
+
170
+ // 根据类型获取对应图标
171
+ const getIconForType = (item) => {
172
+ const iconMap = {
173
+ GS: 'internet',
174
+ DEPT: 'folder',
175
+ GW: 'user-list',
176
+ employee: 'user'
177
+ }
178
+ return iconMap[item.type] || 'user'
179
+ }
180
+
181
+ // 显示对话框
182
+ function showDialog() {
183
+ // 获取API数据
184
+ fetchApiData()
185
+ // 重置选中的节点
186
+ checkedNodes.value = props.modelValue.filter(i => i.type !== 'employee').map((item) => item.bindid);
187
+ checkedUserNodes.value = props.modelValue.filter(i => i.type === 'employee').map((item) => item.bindid);
188
+ dialogVisible.value = true
189
+ }
190
+
191
+ // 确认选择
192
+ function handleConfirm() {
193
+ const finalValue = [...selectPreview.value.map((item) => ({
194
+ label: item.label,
195
+ bindid: item.bindid,
196
+ type: item.type
197
+ })), ...selectPreviewUser.value];
198
+ emit(
199
+ 'update:modelValue', finalValue
200
+ )
201
+ emit('change', finalValue)
202
+ dialogVisible.value = false
203
+ }
204
+
205
+ // 取消选择
206
+ function handleCancel() {
207
+ dialogVisible.value = false
208
+ }
209
+
210
+ // 移除已选择预览中的项目
211
+ function removePreviewItem(item) {
212
+ const isUser = item.type == 'employee';
213
+ if(isUser){
214
+ let index = selectPreviewUser.value.findIndex(i=>i.bindid === item.bindid);
215
+ const removedUser = selectPreviewUser.value[index];
216
+ selectPreviewUser.value.splice(index,1);
217
+ checkedUserNodes.value = checkedUserNodes.value.filter((value) => value !== removedUser.bindid)
218
+ return
219
+ }
220
+ let index = selectPreview.value.findIndex(i => i.bindid === item.bindid);
221
+ const removedItem = selectPreview.value[index];
222
+ selectPreview.value.splice(index, 1)
223
+ checkedNodes.value = checkedNodes.value.filter((value) => value !== removedItem.bindid)
224
+ }
225
+
226
+ // 移除选中项
227
+ function removeItem(index) {
228
+ const newValue = [...props.modelValue]
229
+ newValue.splice(index, 1)
230
+ console.log(newValue,230)
231
+ emit('update:modelValue', newValue)
232
+ emit('change', newValue)
233
+ }
234
+
235
+ // 监听选中节点变化,同步到预览
236
+ watch(
237
+ checkedNodes,
238
+ (newValues) => {
239
+ if (!organizationTree.value.treeRef) return
240
+ selectPreview.value = newValues.map(organizationTree.value.treeRef.getItem).map((i) => ({
241
+ label: i?.label,
242
+ type: i?.data?.type || i.type,
243
+ bindid: i?.value
244
+ }))
245
+ },
246
+ { deep: true }
247
+ )
248
+ watch(checkedUserNodes,nVal=>{
249
+ selectPreviewUser.value = employeeData.value.filter(i=>nVal.includes(i.bindid))
250
+ },{deep:true})
251
+ // 监听modelValue变化,同步到选中节点
252
+ watch(
253
+ () => props.modelValue,
254
+ (newValue) => {
255
+ checkedNodes.value = newValue.filter(i=>i.type!=='employee').map((item) => item.bindid);
256
+ checkedUserNodes.value = newValue.filter(i => i.type === 'employee').map((item) => item.bindid);
257
+ console.log(newValue,checkedUserNodes.value,267)
258
+ },
259
+ { deep: true ,immediate:true}
260
+ )
261
+ watch(activeTab,nVal=>{
262
+ searchText.value = ''
263
+ })
264
+ watch(searchText,nVal=>{
265
+ fetchApiData()
266
+ })
267
+ // 组件挂载时,预加载数据
268
+ onMounted(() => {
269
+ showDialog()
270
+ })
271
+ </script>
272
+
273
+ <style scoped>
274
+ .ebiz-tree-selector {
275
+ display: flex;
276
+ flex-wrap: wrap;
277
+ align-items: center;
278
+ gap: 8px;
279
+ min-height: 32px;
280
+ }
281
+
282
+ .selected-items {
283
+ display: flex;
284
+ flex-wrap: wrap;
285
+ gap: 4px;
286
+ }
287
+
288
+ .selected-item {
289
+ display: flex;
290
+ align-items: center;
291
+ padding: 4px 8px;
292
+ background-color: #f0f0f0;
293
+ border-radius: 4px;
294
+ font-size: 14px;
295
+ }
296
+
297
+ .item-text {
298
+ margin-right: 4px;
299
+ }
300
+
301
+ .item-remove {
302
+ cursor: pointer;
303
+ color: #999;
304
+ font-size: 16px;
305
+ }
306
+
307
+ .item-remove:hover {
308
+ color: #ff4d4f;
309
+ }
310
+
311
+ .add-button {
312
+ display: flex;
313
+ align-items: center;
314
+ }
315
+
316
+ .selector-container {
317
+ display: flex;
318
+ height: 500px;
319
+ }
320
+
321
+ .left-panel {
322
+ flex: 1;
323
+ display: flex;
324
+ flex-direction: column;
325
+ border-right: 1px solid #e0e0e0;
326
+ padding-right: 16px;
327
+ }
328
+
329
+ .right-panel {
330
+ width: 280px;
331
+ display: flex;
332
+ flex-direction: column;
333
+ padding-left: 16px;
334
+ }
335
+
336
+ .search-box {
337
+ margin-bottom: 12px;
338
+ }
339
+
340
+ .selector-tabs {
341
+ margin-bottom: 12px;
342
+ }
343
+
344
+ .tree-content {
345
+ flex: 1;
346
+ overflow: auto;
347
+ border: 1px solid #e0e0e0;
348
+ border-radius: 4px;
349
+ padding: 12px;
350
+ position: relative;
351
+ }
352
+
353
+ .loading-container {
354
+ position: absolute;
355
+ top: 0;
356
+ left: 0;
357
+ right: 0;
358
+ bottom: 0;
359
+ display: flex;
360
+ align-items: center;
361
+ justify-content: center;
362
+ background-color: rgba(255, 255, 255, 0.7);
363
+ }
364
+
365
+ .selected-title {
366
+ font-weight: bold;
367
+ margin-bottom: 8px;
368
+ }
369
+
370
+ .selected-count {
371
+ color: #999;
372
+ font-size: 12px;
373
+ margin-bottom: 12px;
374
+ }
375
+
376
+ .selected-list {
377
+ flex: 1;
378
+ overflow: auto;
379
+ border: 1px solid #e0e0e0;
380
+ border-radius: 4px;
381
+ padding: 8px;
382
+ }
383
+
384
+ .selected-list-item {
385
+ display: flex;
386
+ align-items: center;
387
+ padding: 8px;
388
+ border-bottom: 1px solid #f0f0f0;
389
+ }
390
+
391
+ .selected-list-item:last-child {
392
+ border-bottom: none;
393
+ }
394
+
395
+ .item-icon {
396
+ color: #0052d9;
397
+ margin-right: 8px;
398
+ }
399
+
400
+ .selected-label {
401
+ flex: 1;
402
+ user-select: none;
403
+ }
404
+
405
+ .remove-icon {
406
+ color: #999;
407
+ cursor: pointer;
408
+ }
409
+
410
+ .remove-icon:hover {
411
+ color: #ff4d4f;
412
+ }
413
+
414
+ .no-selection {
415
+ display: flex;
416
+ flex-direction: column;
417
+ align-items: center;
418
+ justify-content: center;
419
+ height: 100%;
420
+ color: #999;
421
+ gap: 8px;
422
+ }
423
+ </style>
@@ -0,0 +1,8 @@
1
+ <div class="comp-item" @click="$router.push('/tdesign-button')">
2
+ <div class="comp-item-name">TDesign 按钮</div>
3
+ <div class="comp-item-desc">TDesign Button 组件封装</div>
4
+ </div>
5
+ <div class="comp-item" @click="$router.push('/tdesign-icon')">
6
+ <div class="comp-item-name">TDesign 图标</div>
7
+ <div class="comp-item-desc">TDesign Icon 组件封装</div>
8
+ </div>