officialblock 1.0.2 → 1.0.3

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.
@@ -0,0 +1,610 @@
1
+ <template>
2
+ <div class="drag-sort-demo">
3
+ <div class="demo-header">
4
+ <h1>拖拽排序演示</h1>
5
+ <p>展示如何使用 vuedraggable 实现列表项的拖拽排序功能</p>
6
+ </div>
7
+
8
+ <!-- 基础拖拽排序 -->
9
+ <a-card title="基础拖拽排序" class="demo-section">
10
+ <div class="basic-drag-demo">
11
+ <h3>简单列表拖拽</h3>
12
+ <draggable
13
+ v-model="basicList"
14
+ :component-data="{
15
+ tag: 'div',
16
+ type: 'transition-group',
17
+ name: !drag ? 'flip-list' : null
18
+ }"
19
+ v-bind="dragOptions"
20
+ @start="drag = true"
21
+ @end="drag = false"
22
+ item-key="id"
23
+ class="drag-area"
24
+ >
25
+ <template #item="{ element: item }">
26
+ <div class="drag-item" :key="item.id">
27
+ <div class="drag-handle">
28
+ <icon-drag-arrow class="drag-icon" />
29
+ </div>
30
+ <div class="item-content">
31
+ <span class="item-text">{{ item.name }}</span>
32
+ <span class="item-order">顺序: {{ item.order }}</span>
33
+ </div>
34
+ <button class="delete-btn" @click="removeItem(basicList, item.id)">
35
+ <icon-delete />
36
+ </button>
37
+ </div>
38
+ </template>
39
+ </draggable>
40
+
41
+ <button class="add-btn" @click="addBasicItem">
42
+ <icon-plus /> 添加项目
43
+ </button>
44
+ </div>
45
+ </a-card>
46
+
47
+ <!-- 复杂拖拽排序 -->
48
+ <a-card title="复杂拖拽排序" class="demo-section">
49
+ <div class="complex-drag-demo">
50
+ <h3>带表单的拖拽列表</h3>
51
+ <draggable
52
+ v-model="complexList"
53
+ :component-data="{
54
+ tag: 'div',
55
+ type: 'transition-group',
56
+ name: !drag ? 'flip-list' : null
57
+ }"
58
+ v-bind="dragOptions"
59
+ @start="drag = true"
60
+ @end="drag = false"
61
+ item-key="id"
62
+ class="drag-area"
63
+ >
64
+ <template #item="{ element: item }">
65
+ <div class="complex-drag-item" :key="item.id">
66
+ <div class="drag-handle">
67
+ <icon-drag-arrow class="drag-icon" />
68
+ </div>
69
+ <div class="item-form">
70
+ <div class="form-row">
71
+ <label>标题:</label>
72
+ <a-input v-model="item.title" placeholder="请输入标题" />
73
+ </div>
74
+ <div class="form-row">
75
+ <label>描述:</label>
76
+ <a-textarea v-model="item.description" placeholder="请输入描述" :rows="2" />
77
+ </div>
78
+ <div class="form-row">
79
+ <label>链接:</label>
80
+ <a-input v-model="item.url" placeholder="请输入链接" />
81
+ </div>
82
+ <div class="form-row">
83
+ <a-checkbox v-model="item.isActive">启用</a-checkbox>
84
+ </div>
85
+ </div>
86
+ <button class="delete-btn" @click="removeItem(complexList, item.id)">
87
+ <icon-delete />
88
+ </button>
89
+ </div>
90
+ </template>
91
+ </draggable>
92
+
93
+ <button class="add-btn" @click="addComplexItem">
94
+ <icon-plus /> 添加复杂项目
95
+ </button>
96
+ </div>
97
+ </a-card>
98
+
99
+ <!-- 分组拖拽排序 -->
100
+ <a-card title="分组拖拽排序" class="demo-section">
101
+ <div class="group-drag-demo">
102
+ <div class="drag-groups">
103
+ <div class="drag-group">
104
+ <h4>待办事项</h4>
105
+ <draggable
106
+ v-model="todoList"
107
+ :component-data="{
108
+ tag: 'div',
109
+ type: 'transition-group',
110
+ name: !drag ? 'flip-list' : null
111
+ }"
112
+ v-bind="groupDragOptions"
113
+ @start="drag = true"
114
+ @end="drag = false"
115
+ item-key="id"
116
+ class="drag-area group-area"
117
+ >
118
+ <template #item="{ element: item }">
119
+ <div class="group-drag-item todo-item" :key="item.id">
120
+ <div class="drag-handle">
121
+ <icon-drag-arrow class="drag-icon" />
122
+ </div>
123
+ <div class="item-content">
124
+ <span>{{ item.text }}</span>
125
+ </div>
126
+ </div>
127
+ </template>
128
+ </draggable>
129
+ </div>
130
+
131
+ <div class="drag-group">
132
+ <h4>进行中</h4>
133
+ <draggable
134
+ v-model="doingList"
135
+ :component-data="{
136
+ tag: 'div',
137
+ type: 'transition-group',
138
+ name: !drag ? 'flip-list' : null
139
+ }"
140
+ v-bind="groupDragOptions"
141
+ @start="drag = true"
142
+ @end="drag = false"
143
+ item-key="id"
144
+ class="drag-area group-area"
145
+ >
146
+ <template #item="{ element: item }">
147
+ <div class="group-drag-item doing-item" :key="item.id">
148
+ <div class="drag-handle">
149
+ <icon-drag-arrow class="drag-icon" />
150
+ </div>
151
+ <div class="item-content">
152
+ <span>{{ item.text }}</span>
153
+ </div>
154
+ </div>
155
+ </template>
156
+ </draggable>
157
+ </div>
158
+
159
+ <div class="drag-group">
160
+ <h4>已完成</h4>
161
+ <draggable
162
+ v-model="doneList"
163
+ :component-data="{
164
+ tag: 'div',
165
+ type: 'transition-group',
166
+ name: !drag ? 'flip-list' : null
167
+ }"
168
+ v-bind="groupDragOptions"
169
+ @start="drag = true"
170
+ @end="drag = false"
171
+ item-key="id"
172
+ class="drag-area group-area"
173
+ >
174
+ <template #item="{ element: item }">
175
+ <div class="group-drag-item done-item" :key="item.id">
176
+ <div class="drag-handle">
177
+ <icon-drag-arrow class="drag-icon" />
178
+ </div>
179
+ <div class="item-content">
180
+ <span>{{ item.text }}</span>
181
+ </div>
182
+ </div>
183
+ </template>
184
+ </draggable>
185
+ </div>
186
+ </div>
187
+ </div>
188
+ </a-card>
189
+
190
+ <!-- 使用说明 -->
191
+ <a-card title="使用说明" class="demo-section">
192
+ <div class="usage-guide">
193
+ <h3>如何使用拖拽排序</h3>
194
+ <ol>
195
+ <li>安装 vuedraggable: <code>npm install vuedraggable@next</code></li>
196
+ <li>在组件中导入: <code>import draggable from 'vuedraggable'</code></li>
197
+ <li>使用 draggable 组件包装列表</li>
198
+ <li>配置拖拽选项和事件处理</li>
199
+ <li>添加适当的样式和动画效果</li>
200
+ </ol>
201
+
202
+ <h3>主要配置选项</h3>
203
+ <ul>
204
+ <li><strong>v-model</strong>: 绑定的数组数据</li>
205
+ <li><strong>item-key</strong>: 列表项的唯一标识字段</li>
206
+ <li><strong>animation</strong>: 动画持续时间</li>
207
+ <li><strong>group</strong>: 分组名称,相同组可以互相拖拽</li>
208
+ <li><strong>disabled</strong>: 是否禁用拖拽</li>
209
+ <li><strong>ghostClass</strong>: 拖拽时的幽灵样式类</li>
210
+ </ul>
211
+ </div>
212
+ </a-card>
213
+ </div>
214
+ </template>
215
+
216
+ <script setup lang="ts">
217
+ import { ref, computed } from 'vue'
218
+ import draggable from 'vuedraggable'
219
+
220
+ // 拖拽状态
221
+ const drag = ref(false)
222
+
223
+ // 基础拖拽配置
224
+ const dragOptions = computed(() => ({
225
+ animation: 200,
226
+ group: 'description',
227
+ disabled: false,
228
+ ghostClass: 'ghost'
229
+ }))
230
+
231
+ // 分组拖拽配置
232
+ const groupDragOptions = computed(() => ({
233
+ animation: 200,
234
+ group: 'shared',
235
+ disabled: false,
236
+ ghostClass: 'ghost'
237
+ }))
238
+
239
+ // 基础列表数据
240
+ const basicList = ref([
241
+ { id: 1, name: '项目 1', order: 1 },
242
+ { id: 2, name: '项目 2', order: 2 },
243
+ { id: 3, name: '项目 3', order: 3 },
244
+ { id: 4, name: '项目 4', order: 4 }
245
+ ])
246
+
247
+ // 复杂列表数据
248
+ const complexList = ref([
249
+ {
250
+ id: 1,
251
+ title: '第一个项目',
252
+ description: '这是第一个项目的描述',
253
+ url: 'https://example.com/1',
254
+ isActive: true
255
+ },
256
+ {
257
+ id: 2,
258
+ title: '第二个项目',
259
+ description: '这是第二个项目的描述',
260
+ url: 'https://example.com/2',
261
+ isActive: false
262
+ }
263
+ ])
264
+
265
+ // 分组列表数据
266
+ const todoList = ref([
267
+ { id: 1, text: '学习 Vue 3' },
268
+ { id: 2, text: '完成项目文档' }
269
+ ])
270
+
271
+ const doingList = ref([
272
+ { id: 3, text: '开发新功能' },
273
+ { id: 4, text: '修复 Bug' }
274
+ ])
275
+
276
+ const doneList = ref([
277
+ { id: 5, text: '代码审查' },
278
+ { id: 6, text: '部署到生产环境' }
279
+ ])
280
+
281
+ // 添加基础项目
282
+ const addBasicItem = () => {
283
+ const newId = Math.max(...basicList.value.map(item => item.id)) + 1
284
+ basicList.value.push({
285
+ id: newId,
286
+ name: `项目 ${newId}`,
287
+ order: newId
288
+ })
289
+ }
290
+
291
+ // 添加复杂项目
292
+ const addComplexItem = () => {
293
+ const newId = Math.max(...complexList.value.map(item => item.id)) + 1
294
+ complexList.value.push({
295
+ id: newId,
296
+ title: `新项目 ${newId}`,
297
+ description: '请输入项目描述',
298
+ url: '',
299
+ isActive: true
300
+ })
301
+ }
302
+
303
+ // 删除项目
304
+ const removeItem = (list: any[], id: number) => {
305
+ const index = list.findIndex(item => item.id === id)
306
+ if (index > -1) {
307
+ list.splice(index, 1)
308
+ }
309
+ }
310
+ </script>
311
+
312
+ <style lang="scss" scoped>
313
+ .drag-sort-demo {
314
+ padding: 24px;
315
+ max-width: 1200px;
316
+ margin: 0 auto;
317
+ }
318
+
319
+ .demo-header {
320
+ margin-bottom: 32px;
321
+ text-align: center;
322
+
323
+ h1 {
324
+ font-size: 32px;
325
+ font-weight: bold;
326
+ color: #1f2937;
327
+ margin-bottom: 8px;
328
+ }
329
+
330
+ p {
331
+ font-size: 16px;
332
+ color: #6b7280;
333
+ }
334
+ }
335
+
336
+ .demo-section {
337
+ margin-bottom: 32px;
338
+ }
339
+
340
+ // 拖拽区域样式
341
+ .drag-area {
342
+ min-height: 100px;
343
+ padding: 16px;
344
+ border: 2px dashed #e5e7eb;
345
+ border-radius: 8px;
346
+ background-color: #f9fafb;
347
+ }
348
+
349
+ // 基础拖拽项样式
350
+ .drag-item {
351
+ display: flex;
352
+ align-items: center;
353
+ padding: 12px;
354
+ margin-bottom: 8px;
355
+ background: white;
356
+ border-radius: 6px;
357
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
358
+ cursor: move;
359
+ transition: all 0.3s ease;
360
+
361
+ &:hover {
362
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
363
+ transform: translateY(-1px);
364
+ }
365
+
366
+ .drag-handle {
367
+ margin-right: 12px;
368
+ cursor: grab;
369
+ color: #9ca3af;
370
+
371
+ &:active {
372
+ cursor: grabbing;
373
+ }
374
+
375
+ .drag-icon {
376
+ font-size: 16px;
377
+ }
378
+ }
379
+
380
+ .item-content {
381
+ flex: 1;
382
+ display: flex;
383
+ justify-content: space-between;
384
+ align-items: center;
385
+
386
+ .item-text {
387
+ font-weight: 500;
388
+ color: #1f2937;
389
+ }
390
+
391
+ .item-order {
392
+ font-size: 12px;
393
+ color: #6b7280;
394
+ }
395
+ }
396
+
397
+ .delete-btn {
398
+ background: none;
399
+ border: none;
400
+ color: #ef4444;
401
+ cursor: pointer;
402
+ padding: 4px;
403
+ border-radius: 4px;
404
+
405
+ &:hover {
406
+ background-color: #fee2e2;
407
+ }
408
+ }
409
+ }
410
+
411
+ // 复杂拖拽项样式
412
+ .complex-drag-item {
413
+ display: flex;
414
+ padding: 16px;
415
+ margin-bottom: 12px;
416
+ background: white;
417
+ border-radius: 8px;
418
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
419
+ cursor: move;
420
+ transition: all 0.3s ease;
421
+
422
+ &:hover {
423
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
424
+ transform: translateY(-1px);
425
+ }
426
+
427
+ .drag-handle {
428
+ margin-right: 16px;
429
+ cursor: grab;
430
+ color: #9ca3af;
431
+ align-self: flex-start;
432
+ margin-top: 8px;
433
+
434
+ &:active {
435
+ cursor: grabbing;
436
+ }
437
+ }
438
+
439
+ .item-form {
440
+ flex: 1;
441
+
442
+ .form-row {
443
+ display: flex;
444
+ align-items: center;
445
+ margin-bottom: 12px;
446
+
447
+ label {
448
+ width: 60px;
449
+ margin-right: 12px;
450
+ font-weight: 500;
451
+ color: #374151;
452
+ }
453
+
454
+ .arco-input,
455
+ .arco-textarea {
456
+ flex: 1;
457
+ }
458
+ }
459
+ }
460
+
461
+ .delete-btn {
462
+ background: none;
463
+ border: none;
464
+ color: #ef4444;
465
+ cursor: pointer;
466
+ padding: 4px;
467
+ border-radius: 4px;
468
+ align-self: flex-start;
469
+
470
+ &:hover {
471
+ background-color: #fee2e2;
472
+ }
473
+ }
474
+ }
475
+
476
+ // 分组拖拽样式
477
+ .drag-groups {
478
+ display: grid;
479
+ grid-template-columns: repeat(3, 1fr);
480
+ gap: 24px;
481
+
482
+ @media (max-width: 768px) {
483
+ grid-template-columns: 1fr;
484
+ }
485
+ }
486
+
487
+ .drag-group {
488
+ h4 {
489
+ margin-bottom: 16px;
490
+ font-weight: 600;
491
+ color: #1f2937;
492
+ text-align: center;
493
+ }
494
+
495
+ .group-area {
496
+ min-height: 200px;
497
+ }
498
+ }
499
+
500
+ .group-drag-item {
501
+ display: flex;
502
+ align-items: center;
503
+ padding: 12px;
504
+ margin-bottom: 8px;
505
+ border-radius: 6px;
506
+ cursor: move;
507
+ transition: all 0.3s ease;
508
+
509
+ &.todo-item {
510
+ background: #fef3c7;
511
+ border-left: 4px solid #f59e0b;
512
+ }
513
+
514
+ &.doing-item {
515
+ background: #dbeafe;
516
+ border-left: 4px solid #3b82f6;
517
+ }
518
+
519
+ &.done-item {
520
+ background: #d1fae5;
521
+ border-left: 4px solid #10b981;
522
+ }
523
+
524
+ &:hover {
525
+ transform: translateY(-1px);
526
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
527
+ }
528
+
529
+ .drag-handle {
530
+ margin-right: 8px;
531
+ cursor: grab;
532
+ color: #6b7280;
533
+
534
+ &:active {
535
+ cursor: grabbing;
536
+ }
537
+ }
538
+
539
+ .item-content {
540
+ flex: 1;
541
+ font-weight: 500;
542
+ }
543
+ }
544
+
545
+ // 添加按钮样式
546
+ .add-btn {
547
+ display: flex;
548
+ align-items: center;
549
+ gap: 8px;
550
+ padding: 8px 16px;
551
+ margin-top: 16px;
552
+ background: #3b82f6;
553
+ color: white;
554
+ border: none;
555
+ border-radius: 6px;
556
+ cursor: pointer;
557
+ font-weight: 500;
558
+ transition: background-color 0.3s ease;
559
+
560
+ &:hover {
561
+ background: #2563eb;
562
+ }
563
+ }
564
+
565
+ // 拖拽动画
566
+ .flip-list-move {
567
+ transition: transform 0.5s;
568
+ }
569
+
570
+ .no-move {
571
+ transition: transform 0s;
572
+ }
573
+
574
+ .ghost {
575
+ opacity: 0.5;
576
+ background: #c8ebfb;
577
+ }
578
+
579
+ // 使用说明样式
580
+ .usage-guide {
581
+ h3 {
582
+ margin-bottom: 16px;
583
+ font-weight: 600;
584
+ color: #1f2937;
585
+ }
586
+
587
+ ol, ul {
588
+ margin-bottom: 24px;
589
+ padding-left: 24px;
590
+
591
+ li {
592
+ margin-bottom: 8px;
593
+ line-height: 1.6;
594
+ }
595
+ }
596
+
597
+ code {
598
+ background: #f3f4f6;
599
+ padding: 2px 6px;
600
+ border-radius: 4px;
601
+ font-family: 'Monaco', 'Consolas', monospace;
602
+ font-size: 14px;
603
+ }
604
+
605
+ strong {
606
+ font-weight: 600;
607
+ color: #1f2937;
608
+ }
609
+ }
610
+ </style>