@neatui/vue 2.4.0 → 2.5.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.
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="full-x" ui-flex="row xt">
3
- <div class="mr-mm-sub my-sm-sub" ui-flex="row lm :wrap">
3
+ <div class="flex-block mr-mm-sub my-sm-sub" ui-flex="row lm wrap">
4
4
  <template v-for="(item, idx) in state.limit" :key="idx">
5
5
  <div v-if="!item._close" ui-flex="row lm" v-bind="{ ...(item.attrs || {}) }">
6
6
  <span class="nr-sm flex-fixed o-ls">{{ item.label }}{{ item.label ? ':' : '' }}</span>
@@ -22,17 +22,17 @@
22
22
  </div>
23
23
  </template>
24
24
  </div>
25
- <div class="mr-sl-sub my-sm-sub nowrap" ui-flex="row rm" ui-hide="<pad">
26
- <IFollowView tipBoxClass="nr-no">
27
- <button ui-btn="@a s case :border">
28
- <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="co-read" style="width: 1em; height: 1em">
25
+ <div class="flex-fixed mr-sl-sub my-sm-sub nowrap" ui-flex="row rm" ui-hide="<pad">
26
+ <IFollowView v-if="tools" tipBoxClass="nr-no">
27
+ <button class="bg-fore" ui-btn="@a s case :border :square">
28
+ <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" class="co-read fs-ss" style="width: 1em; height: 1em">
29
29
  <path
30
30
  d="M372 981.6c-80 0-154.4-43.2-195.2-112L35.2 624.8c-40-68.8-40-155.2 0-224.8l141.6-244.8c40-69.6 115.2-112 195.2-112h282.4c80 0 154.4 43.2 195.2 112L991.2 400c40 68.8 40 155.2 0 224.8l-141.6 244.8c-40 69.6-115.2 112-195.2 112H372z m0-825.6c-39.2 0-76.8 21.6-96.8 56L134.4 456c-20 34.4-20 76.8 0 112l140.8 244.8c20 34.4 56.8 55.2 96.8 55.2h282.4c39.2 0 76.8-21.6 96.8-56l140.8-244.8c20-34.4 20-76.8 0-112L751.2 211.2c-20-34.4-56.8-55.2-96.8-55.2H372z m140.8 552.8c-108.8 0-196.8-88-196.8-196.8 0-108.8 88-196.8 196.8-196.8 108.8 0 196.8 88 196.8 196.8 0.8 108.8-88 196.8-196.8 196.8z m0-280c-45.6 0-83.2 37.6-83.2 83.2s37.6 83.2 83.2 83.2c22.4 0 43.2-8.8 59.2-24 16-16 24-36.8 24-59.2 0-45.6-37.6-83.2-83.2-83.2z"
31
- ></path>
31
+ />
32
32
  </svg>
33
33
  </button>
34
34
  <template v-if="state.limit.length" #tips>
35
- <div class="w-mm h-ls nr-sl" ui-scroll="x:hidden :y">
35
+ <div class="w-mm max-h-ls n-sl" ui-scroll="x:hidden :y">
36
36
  <div v-for="(item, idx) in state.limit" :key="idx" class="item ux-hover nowrap r-ss">
37
37
  <label class="ny-xs nx-sm" ui-form="@a type:checkbox">
38
38
  <input :checked="!item._close" type="checkbox" @change="item._close = item._close ? 0 : 1" />
@@ -42,25 +42,9 @@
42
42
  </div>
43
43
  </template>
44
44
  </IFollowView>
45
- <button ui-btn="@a s main" @click="fResetLimit">{{ words['common.reset'] || '重置' }}</button>
45
+ <button class="bg-fore" ui-btn="@a s case :border" @click="fResetLimit">{{ words['common.reset'] || '重置' }}</button>
46
46
  </div>
47
47
  </div>
48
- <div class="mr-sl-sub my-sm-sub nowrap" ui-hide=">mob">
49
- <IFollowView tipBoxClass="nr-no">
50
- <button ui-btn="@a s case :border"><i class="icon icon-add2 fs-xs"></i>添加条件</button>
51
- <template v-if="state.limit.length" #tips>
52
- <div class="w-mm h-ls nr-sl" ui-scroll="x:hidden :y">
53
- <div v-for="(item, idx) in state.limit" :key="idx" class="item ux-hover nowrap r-ss">
54
- <label class="ny-xs nx-sm" ui-form="@a type:checkbox">
55
- <input :checked="!item._close" type="checkbox" @change="item._close = item._close ? 0 : 1" />
56
- <span>{{ item.label }}</span>
57
- </label>
58
- </div>
59
- </div>
60
- </template>
61
- </IFollowView>
62
- <button ui-btn="@a s main" @click="fResetLimit">{{ words['common.reset'] || '重置' }}</button>
63
- </div>
64
48
  </template>
65
49
  <script lang="ts" setup>
66
50
  import { computed, reactive, watch } from 'vue';
@@ -97,12 +81,14 @@
97
81
  words?: { [key: string | number]: any };
98
82
  limit: Array<LimitProps>;
99
83
  param: any;
84
+ tools: boolean;
100
85
  }
101
86
 
102
87
  const props: any = withDefaults(defineProps<Props>(), {
103
88
  words: () => ({}),
104
89
  limit: () => [],
105
- param: () => ({})
90
+ param: () => ({}),
91
+ tools: false
106
92
  });
107
93
 
108
94
  // 内部数据
@@ -111,6 +97,7 @@
111
97
  limit: [],
112
98
  param: {}
113
99
  });
100
+
114
101
  // 监听外部配置
115
102
  watch(
116
103
  () => props.limit,
@@ -152,6 +139,7 @@
152
139
  },
153
140
  { deep: true, immediate: true }
154
141
  );
142
+
155
143
  // 缓存交互配置
156
144
  watch(
157
145
  [() => state.limit],
@@ -0,0 +1,628 @@
1
+ <template>
2
+ <div id="layer-loader-root" :path="path" :class="`${!path ? '' : 'pr nl-ms'}`" :ui-lines="path ? line : null">
3
+ <template v-for="(item, idx) in data" :key="idx">
4
+ <div
5
+ ui-flex="row xm"
6
+ class="fekit-layer-loader-item ux-hover nx-ss r-ss pr z1"
7
+ :data-move="item._move"
8
+ :class="`${store.active === paths(idx) ? (store.error ? 'bg-risk+o-ss co-risk' : 'bg-main+o-ss co-main fekit-layer-node-active') : ''}${item?.attrs?.hide ? ' o-mm' : ''}`"
9
+ @mousedown="fMoveSta($event, data, idx, paths(idx))"
10
+ @mousemove="fMoveIng($event, item, paths(idx))"
11
+ @mouseout="fMoveOut($event, paths(idx))"
12
+ @mouseup="fMoveEnd($event, data, item, idx, paths(idx))"
13
+ >
14
+ <div :id="`LID${path.replace(/\./g, '')}-${idx}`" :path="paths(idx)" ui-flex="row lt" class="flex-block ny-ss" @click="store.active = paths(idx)">
15
+ <slot name="prefix" :item="item" :path="paths(idx)">
16
+ <i :class="`ml-ss mr-xs o-ms icon icon-model-${!path ? 'label' : item.model || 'null'}`"></i>
17
+ </slot>
18
+ <slot name="item" :item="item" :path="paths(idx)">
19
+ <span class="ux-none" ui-omit="1">
20
+ {{ (item.model === 'text' || !item.model ? item.value : null) || item.label || '‐‐' }}
21
+ </span>
22
+ </slot>
23
+ <slot name="suffix" :item="item" :path="paths(idx)"></slot>
24
+ </div>
25
+
26
+ <!-- Tools 区域 -->
27
+ <div class="move-tools">
28
+ <slot name="tools" :item="item" :path="paths(idx)" :moveUp="() => fMoveUp(data, idx)" :moveDown="() => fMoveDown(data, idx)">
29
+ <!-- 默认的上移下移按钮 -->
30
+ <button v-if="idx > 0" @click.stop="fMoveUp(data, idx)" class="move-btn" title="上移">↑</button>
31
+ <button v-if="idx < data.length - 1" @click.stop="fMoveDown(data, idx)" class="move-btn" title="下移">↓</button>
32
+ </slot>
33
+ </div>
34
+ </div>
35
+ </template>
36
+ </div>
37
+ </template>
38
+ <script setup lang="ts">
39
+ import { nextTick, reactive, ref, watch, onMounted } from 'vue';
40
+
41
+ // 事件定义
42
+ const store: any = reactive({
43
+ active: '',
44
+ error: false,
45
+ isMouseInLayer: false,
46
+ layer: {
47
+ moveing: false,
48
+ from: null,
49
+ correct: ''
50
+ }
51
+ });
52
+ const word: any = {};
53
+
54
+ // 类型定义
55
+ interface Props {
56
+ data?: Array<any>;
57
+ path?: string;
58
+ line?: boolean;
59
+ }
60
+ // 外部入参
61
+ const props: any = withDefaults(defineProps<Props>(), {
62
+ data: () => [],
63
+ path: '',
64
+ line: true
65
+ });
66
+
67
+ // 内部状态
68
+ const state: any = reactive({});
69
+ const tools: any = ref(null);
70
+
71
+ const ph = ref(0);
72
+ onMounted(() => {
73
+ const side = document.getElementById('side-layerloader');
74
+ ph.value = side?.clientHeight || 0;
75
+ });
76
+
77
+ // 计算路径
78
+ const paths = (idx: number) => {
79
+ return props.path ? `${props.path}-${idx}` : `${idx}`;
80
+ };
81
+
82
+ // 上移功能
83
+ const fMoveUp = (data: any[], idx: number) => {
84
+ if (idx > 0) {
85
+ const item = data.splice(idx, 1)[0];
86
+ data.splice(idx - 1, 0, item);
87
+ // 更新 active 路径
88
+ const currentPath = paths(idx);
89
+ const newPath = props.path ? `${props.path}-${idx - 1}` : `${idx - 1}`;
90
+ if (store.active === currentPath) {
91
+ store.active = newPath;
92
+ }
93
+ }
94
+ };
95
+
96
+ // 下移功能
97
+ const fMoveDown = (data: any[], idx: number) => {
98
+ if (idx < data.length - 1) {
99
+ const item = data.splice(idx, 1)[0];
100
+ data.splice(idx + 1, 0, item);
101
+ // 更新 active 路径
102
+ const currentPath = paths(idx);
103
+ const newPath = props.path ? `${props.path}-${idx + 1}` : `${idx + 1}`;
104
+ if (store.active === currentPath) {
105
+ store.active = newPath;
106
+ }
107
+ }
108
+ };
109
+
110
+ // 是否同祖
111
+ function inform(from: string, data: string) {
112
+ const _form = from.split('.');
113
+ const _data = data.split('.');
114
+ return _form.every((part, index) => part === _data[index]);
115
+ }
116
+
117
+ // 按住
118
+ const fMoveSta = (ev: any, data: any, idx: number, paths: any) => {
119
+ console.log('fMoveSta called:', { paths, pathsLength: paths.length });
120
+ store.layer.moveing = true;
121
+ store.layer.from = { data, idx, dom: ev?.currentTarget, y: ev.clientY, paths };
122
+
123
+ // 添加拖拽样式
124
+ ev?.currentTarget?.setAttribute('data-move', 'true');
125
+ document.body.classList.add('dragging');
126
+
127
+ console.log('Drag started:', store.layer.from);
128
+ };
129
+
130
+ const fMoveIng = (ev: any, item: any, paths: any) => {
131
+ if (!store.layer.moveing) return;
132
+ console.log('fMoveIng called:', { paths, moveing: store.layer.moveing });
133
+ const dom = ev?.currentTarget;
134
+ if (!dom || dom === store.layer.from.dom) return;
135
+ const rect = dom.getBoundingClientRect();
136
+ const halfHeight = rect.height / 2 || 1;
137
+ const offsetY = ev?.layerY ?? ev?.offsetY ?? 0;
138
+ const mode = offsetY > halfHeight ? 'next' : 'prev';
139
+
140
+ store.layer.correct = mode;
141
+ dom.setAttribute('data-ins', mode);
142
+ console.log('Move mode:', mode);
143
+ };
144
+
145
+ // 移出
146
+ const fMoveOut = (ev: any, paths: any) => {
147
+ if (store.layer.moveing) {
148
+ ev?.currentTarget?.removeAttribute('data-ins');
149
+ }
150
+ };
151
+
152
+ // 松开
153
+ const fMoveEnd = (ev: any, data: any, item: any, idx: number, paths: any) => {
154
+ console.log('fMoveEnd called:', { paths, moveing: store.layer.moveing });
155
+ if (store.layer.moveing && !inform(store.layer.from.paths, paths)) {
156
+ const from = store.layer.from;
157
+ if (from.data && from.dom !== ev?.currentTarget) {
158
+ const isAdjacent =
159
+ (store.layer.correct === 'prev' && from.dom?.nextElementSibling === ev?.currentTarget) ||
160
+ (store.layer.correct === 'next' && from.dom?.previousElementSibling === ev?.currentTarget);
161
+
162
+ if (!isAdjacent) {
163
+ const [node] = from.data.splice(from.idx, 1);
164
+ let newPath = paths;
165
+
166
+ // Adjust target index if it's after the removed item in the same array
167
+ let targetIdx = idx;
168
+ if (from.data === data && from.idx < idx) {
169
+ targetIdx -= 1;
170
+ }
171
+
172
+ if (store.layer.correct === 'prev') {
173
+ data.splice(targetIdx, 0, node);
174
+ newPath = props.path ? `${props.path}-${targetIdx}` : `${targetIdx}`;
175
+ } else if (store.layer.correct === 'next') {
176
+ const insertIndex = targetIdx + 1;
177
+ data.splice(insertIndex, 0, node);
178
+ newPath = props.path ? `${props.path}-${insertIndex}` : `${insertIndex}`;
179
+ }
180
+
181
+ console.log('Move completed:', { from: from.paths, to: newPath });
182
+ requestAnimationFrame(() => {
183
+ store.active = newPath;
184
+ });
185
+ }
186
+ }
187
+ }
188
+
189
+ // 清理拖拽样式
190
+ ev?.currentTarget?.removeAttribute('data-ins');
191
+ store.layer.from?.dom?.removeAttribute('data-move');
192
+ document.body.classList.remove('dragging');
193
+
194
+ store.layer.moveing = false;
195
+ };
196
+ </script>
197
+ <style lang="scss">
198
+ .fekit-json-tree {
199
+ &,
200
+ * {
201
+ user-select: none;
202
+ }
203
+
204
+ &[data-item-moveing='1'] {
205
+ * {
206
+ pointer-events: none;
207
+ }
208
+ .drag-item-move {
209
+ pointer-events: auto !important;
210
+ & > dt:hover {
211
+ opacity: 0;
212
+ }
213
+ }
214
+ }
215
+ &[data-page-moveing='1'] {
216
+ * {
217
+ pointer-events: none;
218
+ }
219
+ .drag-page-move {
220
+ pointer-events: auto !important;
221
+ & > dt:hover {
222
+ opacity: 0;
223
+ }
224
+ }
225
+ }
226
+ &[data-rows-moveing='1'] {
227
+ * {
228
+ pointer-events: none;
229
+ }
230
+ .drag-rows-move {
231
+ pointer-events: auto !important;
232
+ & > dt:hover {
233
+ opacity: 0;
234
+ }
235
+ }
236
+ }
237
+ &[data-opts-moveing='1'] {
238
+ * {
239
+ pointer-events: none;
240
+ }
241
+ .drag-opts-move {
242
+ pointer-events: auto !important;
243
+ & > dt:hover {
244
+ opacity: 0;
245
+ }
246
+ }
247
+ }
248
+
249
+ & > dl {
250
+ position: relative;
251
+ padding-left: 0.6em;
252
+ &::before {
253
+ left: 0.2em !important;
254
+ }
255
+ dl {
256
+ position: relative;
257
+ padding-left: 1em;
258
+ }
259
+ }
260
+
261
+ dl {
262
+ &::before {
263
+ position: absolute;
264
+ display: block;
265
+ content: '';
266
+ width: 1px;
267
+ top: 1.5em;
268
+ bottom: 0.5em;
269
+ left: 0.6em;
270
+ background-color: var(--co-line-ls);
271
+ }
272
+ }
273
+
274
+ dt {
275
+ display: flex;
276
+ position: relative;
277
+ cursor: pointer;
278
+ justify-content: flex-start;
279
+ align-items: baseline;
280
+ align-content: baseline;
281
+ border-radius: 0.3em;
282
+ padding: 0 0.3em;
283
+ &:hover {
284
+ background-color: var(--co-weak);
285
+ }
286
+
287
+ // 图标
288
+ &::after {
289
+ position: absolute;
290
+ display: inline-block;
291
+ content: '';
292
+ width: 0;
293
+ height: 0;
294
+ border-width: 0.25em 0 0.25em 0.25em;
295
+ border-style: solid;
296
+ border-color: transparent;
297
+ border-left-color: var(--co-read);
298
+ top: 0.65em;
299
+ // margin-top: -0.3em;
300
+ left: -0.5em;
301
+ transform: rotate(90deg);
302
+ border-radius: 30%;
303
+ }
304
+
305
+ &[data-sign]::before {
306
+ display: inline-block;
307
+ position: relative;
308
+ min-width: 1.2em;
309
+ height: 1.2em;
310
+ content: attr(data-sign);
311
+ text-align: center;
312
+ line-height: 1.2em;
313
+ font-weight: bold;
314
+ transform: rotate(0deg) !important;
315
+ opacity: 0.7;
316
+ margin-right: 0.3em;
317
+ font-style: italic;
318
+ border-radius: 1px;
319
+ left: 0;
320
+ top: -0.45em;
321
+ box-sizing: content-box;
322
+ padding: 1px;
323
+ font-size: 0.5em;
324
+ border: 1px dotted;
325
+ flex-shrink: 0;
326
+ }
327
+
328
+ &[select='1'] {
329
+ color: var(--co-main);
330
+ }
331
+
332
+ &.fekit-json-tree-end {
333
+ &::after {
334
+ display: none;
335
+ }
336
+ }
337
+
338
+ &[data-hide='1'] {
339
+ &::after {
340
+ transform: rotate(0deg);
341
+ }
342
+ & + dd {
343
+ display: none;
344
+ }
345
+ }
346
+ }
347
+ }
348
+
349
+ .omit-1 {
350
+ display: block;
351
+ overflow: hidden;
352
+ text-align: justify;
353
+ text-overflow: ellipsis;
354
+ white-space: nowrap;
355
+ }
356
+
357
+ .fekit-json-tree-menu {
358
+ position: absolute;
359
+ height: 1em;
360
+ line-height: 1em;
361
+ right: 0;
362
+ top: 50%;
363
+ margin-top: -0.5em;
364
+ opacity: 0;
365
+ pointer-events: none;
366
+
367
+ & > * {
368
+ margin: 0 0.25em;
369
+ }
370
+ }
371
+
372
+ dt:hover {
373
+ .fekit-json-tree-menu {
374
+ transition: opacity 1s;
375
+ opacity: 1;
376
+ pointer-events: auto;
377
+ }
378
+ }
379
+
380
+ .fekit-json-tree-switch {
381
+ position: absolute;
382
+ width: 1em;
383
+ height: 1em;
384
+ top: 0.65em;
385
+ // margin-top: -0.6em;
386
+ left: -0.9em;
387
+ z-index: 2;
388
+ }
389
+
390
+ [data-selected='true'] {
391
+ background: var(--co-main-ss) !important;
392
+ }
393
+
394
+ .fekit-json-tree-tools {
395
+ display: flex;
396
+ position: relative;
397
+ cursor: pointer;
398
+ justify-content: flex-end;
399
+ align-items: center;
400
+ align-content: center;
401
+ flex-wrap: nowrap;
402
+ flex-shrink: 0;
403
+ font-size: 0.85em;
404
+ // width: 1px;
405
+ opacity: 0;
406
+ transition: all 0.25s;
407
+ // & > * {
408
+ // transform: scale(0.8);
409
+ // transition: all 0.5s;
410
+ // }
411
+ }
412
+ .drag-page-move,
413
+ .drag-item-move,
414
+ .drag-rows-move,
415
+ .drag-opts-move {
416
+ cursor: pointer;
417
+ &:hover {
418
+ & dt {
419
+ &:hover {
420
+ .fekit-json-tree-tools {
421
+ width: auto;
422
+ opacity: 1;
423
+ // & > * {
424
+ // transform: scale(1);
425
+ // }
426
+ }
427
+ }
428
+ }
429
+ }
430
+ }
431
+
432
+ [data-ins] {
433
+ position: relative;
434
+ &:hover {
435
+ box-shadow: inset 0 0 0 100em var(--co-fore) !important;
436
+
437
+ & > .parent-hover\:show {
438
+ opacity: 0 !important;
439
+ }
440
+ }
441
+ }
442
+ // 插入前面
443
+ [data-ins='prev'] {
444
+ &::before {
445
+ pointer-events: none;
446
+ position: absolute;
447
+ display: block;
448
+ content: '';
449
+ width: 100%;
450
+ height: 100%;
451
+ left: 0;
452
+ top: 0;
453
+ z-index: 1;
454
+ box-shadow: inset 0 1px 0 0 var(--co-main-ls);
455
+ }
456
+
457
+ // &[tree-level='2'] {
458
+ // &::after {
459
+ // position: absolute;
460
+ // display: block;
461
+ // content: '组内';
462
+ // left: -2rem;
463
+ // top: -0.25em;
464
+ // font-size: 0.6em;
465
+ // font-weight: bold;
466
+ // }
467
+ // }
468
+ }
469
+ // 插入内部
470
+ [data-ins='inset'] {
471
+ &::after {
472
+ pointer-events: none;
473
+ position: absolute;
474
+ display: block;
475
+ content: '';
476
+ width: 100%;
477
+ height: 100%;
478
+ left: 0;
479
+ top: 0;
480
+ z-index: 1;
481
+ box-shadow: inset 0 0 0 1px var(--co-main-ls);
482
+ }
483
+ }
484
+ // 插入后面
485
+ [data-ins='next'] {
486
+ &::after {
487
+ pointer-events: none;
488
+ position: absolute;
489
+ display: block;
490
+ content: '';
491
+ width: 100%;
492
+ height: 100%;
493
+ left: 0;
494
+ top: 0;
495
+ z-index: 1;
496
+ box-shadow: inset 0 -1px 0 0 var(--co-main-ls);
497
+ }
498
+
499
+ // &[tree-level='2'] {
500
+ // &::after {
501
+ // position: absolute;
502
+ // display: block;
503
+ // content: '组内';
504
+ // left: -2rem;
505
+ // bottom: -0.25em;
506
+ // font-size: 0.6em;
507
+ // font-weight: bold;
508
+ // }
509
+ // }
510
+ }
511
+
512
+ .fekit-json-tree-button {
513
+ &:hover {
514
+ background: none !important;
515
+ }
516
+
517
+ &::before {
518
+ display: none !important;
519
+ }
520
+ }
521
+
522
+ .editing {
523
+ pointer-events: auto !important;
524
+ }
525
+
526
+ .fekit-json-tree-value {
527
+ position: relative;
528
+ padding: 0.25em 0.5em;
529
+ border-radius: 0.3em;
530
+ border: 1px solid var(--co-case);
531
+ }
532
+
533
+ .edit-logic-json-tree {
534
+ & {
535
+ min-height: 2.5em;
536
+ border: 1px solid var(--co-case);
537
+ padding: 0.25em;
538
+ border-radius: 0.3em;
539
+ }
540
+
541
+ & > dl {
542
+ position: relative;
543
+ padding-left: 0.6em;
544
+
545
+ &::before {
546
+ opacity: 0;
547
+ }
548
+
549
+ &[data-group='1'] {
550
+ &::before {
551
+ opacity: 1;
552
+ left: 0.3em !important;
553
+ width: 5px;
554
+ top: 0.75em;
555
+ bottom: 0.75em;
556
+ background-color: transparent;
557
+ border: 1px solid var(--co-note);
558
+
559
+ border-right: none !important;
560
+ }
561
+ }
562
+
563
+ dl {
564
+ position: relative;
565
+ padding-left: 0;
566
+ &::before {
567
+ opacity: 0;
568
+ }
569
+ }
570
+ }
571
+
572
+ dt {
573
+ align-items: baseline;
574
+ align-content: baseline;
575
+
576
+ &[data-sign]::before {
577
+ position: relative;
578
+ min-width: 1.2em;
579
+ height: 1.2em;
580
+ top: -0.35em;
581
+ }
582
+
583
+ &::after {
584
+ display: none;
585
+ }
586
+ }
587
+ }
588
+
589
+ /* 新增的 MoveLoader 工具样式 */
590
+ .move-tools {
591
+ display: flex;
592
+ align-items: center;
593
+ gap: 4px;
594
+ opacity: 0;
595
+ transition: opacity 0.2s ease;
596
+ margin-left: 8px;
597
+ }
598
+
599
+ .fekit-layer-loader-item:hover .move-tools {
600
+ opacity: 1;
601
+ }
602
+
603
+ .move-btn {
604
+ display: inline-flex;
605
+ align-items: center;
606
+ justify-content: center;
607
+ width: 20px;
608
+ height: 20px;
609
+ border: 1px solid var(--co-line);
610
+ background: var(--co-back);
611
+ color: var(--co-text);
612
+ border-radius: 3px;
613
+ cursor: pointer;
614
+ font-size: 12px;
615
+ line-height: 1;
616
+ transition: all 0.2s ease;
617
+
618
+ &:hover {
619
+ background: var(--co-main);
620
+ color: var(--co-back);
621
+ border-color: var(--co-main);
622
+ }
623
+
624
+ &:active {
625
+ transform: scale(0.95);
626
+ }
627
+ }
628
+ </style>
@@ -0,0 +1,2 @@
1
+ import LayerLoader from './LayerLoader.vue';
2
+ export default LayerLoader;