stellar-ui-plus 1.24.26 → 1.24.27

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 (39) hide show
  1. package/components/ste-app-update/method.ts +1 -0
  2. package/components/ste-app-update/ste-app-update.vue +2 -7
  3. package/components/ste-select-seat/ATTRIBUTES.md +18 -0
  4. package/components/ste-select-seat/README.md +280 -0
  5. package/components/ste-select-seat/canvasUtils.ts +42 -0
  6. package/components/ste-select-seat/config.json +5 -0
  7. package/components/ste-select-seat/internals/gridUtils.ts +23 -0
  8. package/components/ste-select-seat/internals/seatLayout.ts +169 -0
  9. package/components/ste-select-seat/internals/useSeatInteraction.ts +540 -0
  10. package/components/ste-select-seat/props.ts +37 -0
  11. package/components/ste-select-seat/ste-select-seat.easycom.json +62 -0
  12. package/components/ste-select-seat/ste-select-seat.vue +517 -0
  13. package/components/ste-select-seat/types.d.ts +33 -0
  14. package/components/ste-select-seat/useData.ts +179 -0
  15. package/components/ste-select-seat/useTouchCompat.ts +89 -0
  16. package/components/ste-simple-calendar/ATTRIBUTES.md +17 -0
  17. package/components/ste-simple-calendar/README.md +112 -0
  18. package/components/ste-simple-calendar/config.json +5 -0
  19. package/components/ste-simple-calendar/props.ts +32 -0
  20. package/components/ste-simple-calendar/ste-simple-calendar.easycom.json +60 -0
  21. package/components/ste-simple-calendar/ste-simple-calendar.vue +265 -0
  22. package/components/ste-simple-calendar/type.d.ts +30 -0
  23. package/components/ste-simple-calendar/useData.ts +60 -0
  24. package/components/ste-skeleton/README.md +45 -0
  25. package/components/ste-skeleton/config.json +5 -0
  26. package/components/ste-skeleton/props.ts +7 -0
  27. package/components/ste-skeleton/ste-skeleton.json +38 -0
  28. package/components/ste-skeleton/ste-skeleton.vue +108 -0
  29. package/components/ste-slide-verify/ATTRIBUTES.md +27 -0
  30. package/components/ste-slide-verify/README.md +118 -0
  31. package/components/ste-slide-verify/config.json +5 -0
  32. package/components/ste-slide-verify/props.ts +43 -0
  33. package/components/ste-slide-verify/ste-slide-verify.easycom.json +119 -0
  34. package/components/ste-slide-verify/ste-slide-verify.vue +535 -0
  35. package/index.ts +8 -0
  36. package/package.json +1 -1
  37. package/types/components.d.ts +8 -0
  38. package/types/index.d.ts +2 -0
  39. package/types/refComponents.d.ts +8 -0
@@ -0,0 +1,540 @@
1
+ import { ref } from 'vue'
2
+ import type { ComponentPublicInstance } from 'vue'
3
+ import type { UniTouch, UniTouchEvent } from '../../../types/event'
4
+ import type { SteSelectSeatItem, SteSelectSeatValue } from '../types'
5
+ import { getTouchCenter, getTouchDistance, getTouchIdentifier, getTouchX, getTouchY, toTouchArray } from '../useTouchCompat'
6
+
7
+ interface UseSeatInteractionOptions {
8
+ instance: ComponentPublicInstance
9
+ canvasId: string
10
+ getShowRowLabels: () => boolean
11
+ touchHandler: {
12
+ scale: number
13
+ baseScale: number
14
+ translateX: number
15
+ translateY: number
16
+ baseTranslateX: number
17
+ baseTranslateY: number
18
+ reset: () => void
19
+ }
20
+ clampScale: (scale: number) => number
21
+ applyTranslateResistance: (x: number, y: number, scale?: number) => { x: number; y: number }
22
+ clampTranslate: (x: number, y: number, scale?: number) => { x: number; y: number }
23
+ getTouchSeat: (touchX: number, touchY: number) => SteSelectSeatItem | null
24
+ getTouchLocalPoint: (touch: UniTouch | undefined | null, rect?: { left?: number; top?: number } | null) => { x: number; y: number }
25
+ applyDefaultViewport: () => void
26
+ draw: () => void
27
+ emitMove: () => void
28
+ emitSeatClick: (seat: SteSelectSeatItem) => void
29
+ emitModelValue: (value: SteSelectSeatValue[]) => void
30
+ toggleSeat: (row: number, col: number) => SteSelectSeatValue[]
31
+ }
32
+
33
+ interface PointerEventLike {
34
+ clientX: number
35
+ clientY: number
36
+ target?: EventTarget | null
37
+ }
38
+
39
+ export function useSeatInteraction(options: UseSeatInteractionOptions) {
40
+ const {
41
+ instance,
42
+ canvasId,
43
+ getShowRowLabels,
44
+ touchHandler,
45
+ clampScale,
46
+ applyTranslateResistance,
47
+ clampTranslate,
48
+ getTouchSeat,
49
+ getTouchLocalPoint,
50
+ applyDefaultViewport,
51
+ draw,
52
+ emitMove,
53
+ emitSeatClick,
54
+ emitModelValue,
55
+ toggleSeat,
56
+ } = options
57
+
58
+ const panThreshold = 4
59
+ const reboundThreshold = 0.5
60
+ const reboundDuration = 180
61
+ const momentumMinVelocity = 0.02
62
+ const momentumDecayPerFrame = 0.92
63
+
64
+ const rowLabelsVisible = ref(getShowRowLabels())
65
+ const activeTouches = new Map<number | string, UniTouch>()
66
+
67
+ let dragMoved = false
68
+ let gestureMode: 'none' | 'pan' | 'pinch' = 'none'
69
+ let panStartX = 0
70
+ let panStartY = 0
71
+ let panBaseTranslateX = 0
72
+ let panBaseTranslateY = 0
73
+ let pinchStartDistance = 0
74
+ let pinchStartScale = 1
75
+ let pinchStartCenterX = 0
76
+ let pinchStartCenterY = 0
77
+ let pinchLockedTranslateX = 0
78
+ let pinchLockedTranslateY = 0
79
+ let reboundTimer: ReturnType<typeof setTimeout> | null = null
80
+ let momentumTimer: ReturnType<typeof setTimeout> | null = null
81
+ let rowLabelTimer: ReturnType<typeof setTimeout> | null = null
82
+ let lastPanSampleTime = 0
83
+ let lastPanSampleX = 0
84
+ let lastPanSampleY = 0
85
+ let panVelocityX = 0
86
+ let panVelocityY = 0
87
+ let mouseDown = false
88
+ let mouseStartX = 0
89
+ let mouseStartY = 0
90
+
91
+ // ─── Touch State Sync ─────────────────────────────────────────────────────
92
+
93
+ const syncActiveTouches = (touches: UniTouch[]) => {
94
+ activeTouches.clear()
95
+ touches.forEach((touch, index) => {
96
+ activeTouches.set(getTouchIdentifier(touch, index), touch)
97
+ })
98
+ }
99
+
100
+ const patchActiveTouches = (touches: UniTouch[]) => {
101
+ touches.forEach((touch, index) => {
102
+ activeTouches.set(getTouchIdentifier(touch, index), touch)
103
+ })
104
+ }
105
+
106
+ const removeActiveTouches = (touches: UniTouch[]) => {
107
+ touches.forEach((touch, index) => {
108
+ activeTouches.delete(getTouchIdentifier(touch, index))
109
+ })
110
+ }
111
+
112
+ const getEventTouches = (e: UniTouchEvent, phase: 'start' | 'move' | 'end') => {
113
+ const touches = toTouchArray(e.touches)
114
+ const changedTouches = toTouchArray(e.changedTouches)
115
+
116
+ if (phase === 'end') {
117
+ if (touches.length) {
118
+ syncActiveTouches(touches)
119
+ } else {
120
+ removeActiveTouches(changedTouches)
121
+ if (!activeTouches.size) {
122
+ activeTouches.clear()
123
+ }
124
+ }
125
+ return Array.from(activeTouches.values())
126
+ }
127
+
128
+ if (touches.length) {
129
+ syncActiveTouches(touches)
130
+ } else {
131
+ patchActiveTouches(changedTouches)
132
+ }
133
+ return Array.from(activeTouches.values())
134
+ }
135
+
136
+ const getChangedTouches = (e: UniTouchEvent) => toTouchArray(e.changedTouches)
137
+
138
+ // ─── Overlay State ────────────────────────────────────────────────────────
139
+
140
+ const clearRowLabelTimer = () => {
141
+ if (rowLabelTimer) {
142
+ clearTimeout(rowLabelTimer)
143
+ rowLabelTimer = null
144
+ }
145
+ }
146
+
147
+ const setRowLabelsVisible = (visible: boolean) => {
148
+ clearRowLabelTimer()
149
+ rowLabelsVisible.value = visible
150
+ }
151
+
152
+ const showRowLabelOverlay = () => {
153
+ clearRowLabelTimer()
154
+ rowLabelsVisible.value = getShowRowLabels()
155
+ }
156
+
157
+ // ─── Motion State ─────────────────────────────────────────────────────────
158
+
159
+ const resetPanVelocity = () => {
160
+ panVelocityX = 0
161
+ panVelocityY = 0
162
+ lastPanSampleTime = 0
163
+ lastPanSampleX = 0
164
+ lastPanSampleY = 0
165
+ }
166
+
167
+ const recordPanVelocity = (x: number, y: number) => {
168
+ const now = Date.now()
169
+ if (!lastPanSampleTime) {
170
+ lastPanSampleTime = now
171
+ lastPanSampleX = x
172
+ lastPanSampleY = y
173
+ return
174
+ }
175
+
176
+ const dt = Math.max(1, now - lastPanSampleTime)
177
+ const nextVelocityX = (x - lastPanSampleX) / dt
178
+ const nextVelocityY = (y - lastPanSampleY) / dt
179
+
180
+ panVelocityX = panVelocityX * 0.35 + nextVelocityX * 0.65
181
+ panVelocityY = panVelocityY * 0.35 + nextVelocityY * 0.65
182
+ lastPanSampleTime = now
183
+ lastPanSampleX = x
184
+ lastPanSampleY = y
185
+ }
186
+
187
+ const stopMomentum = () => {
188
+ if (!momentumTimer) return
189
+ clearTimeout(momentumTimer)
190
+ momentumTimer = null
191
+ }
192
+
193
+ const stopRebound = () => {
194
+ if (!reboundTimer) return
195
+ clearTimeout(reboundTimer)
196
+ reboundTimer = null
197
+ }
198
+
199
+ const stopMotion = () => {
200
+ stopMomentum()
201
+ stopRebound()
202
+ }
203
+
204
+ const updateBaseTransform = () => {
205
+ touchHandler.baseScale = touchHandler.scale
206
+ touchHandler.baseTranslateX = touchHandler.translateX
207
+ touchHandler.baseTranslateY = touchHandler.translateY
208
+ }
209
+
210
+ const applyTranslate = (x: number, y: number, scale = touchHandler.scale) => {
211
+ const nextTranslate = applyTranslateResistance(x, y, scale)
212
+ touchHandler.translateX = nextTranslate.x
213
+ touchHandler.translateY = nextTranslate.y
214
+ }
215
+
216
+ const beginPan = (touch: UniTouch, moved: boolean) => {
217
+ gestureMode = 'pan'
218
+ dragMoved = moved
219
+ panStartX = getTouchX(touch)
220
+ panStartY = getTouchY(touch)
221
+ panBaseTranslateX = touchHandler.translateX
222
+ panBaseTranslateY = touchHandler.translateY
223
+ resetPanVelocity()
224
+ recordPanVelocity(panStartX, panStartY)
225
+ }
226
+
227
+ const beginPinch = (touches: UniTouch[]) => {
228
+ gestureMode = 'pinch'
229
+ dragMoved = true
230
+ resetPanVelocity()
231
+ pinchStartDistance = getTouchDistance(touches)
232
+ pinchStartScale = touchHandler.scale
233
+ const center = getTouchCenter(touches)
234
+ pinchStartCenterX = center.x
235
+ pinchStartCenterY = center.y
236
+ pinchLockedTranslateX = touchHandler.translateX
237
+ pinchLockedTranslateY = touchHandler.translateY
238
+ }
239
+
240
+ // ─── Motion Animation ─────────────────────────────────────────────────────
241
+
242
+ const reboundToBounds = (onComplete?: () => void) => {
243
+ stopMomentum()
244
+ stopRebound()
245
+ const fromX = touchHandler.translateX
246
+ const fromY = touchHandler.translateY
247
+ const target = clampTranslate(fromX, fromY)
248
+
249
+ if (Math.abs(target.x - fromX) <= reboundThreshold && Math.abs(target.y - fromY) <= reboundThreshold) {
250
+ touchHandler.translateX = target.x
251
+ touchHandler.translateY = target.y
252
+ updateBaseTransform()
253
+ draw()
254
+ emitMove()
255
+ onComplete?.()
256
+ return
257
+ }
258
+
259
+ const startTime = Date.now()
260
+ const easeOutCubic = (t: number) => 1 - (1 - t) ** 3
261
+
262
+ const animate = () => {
263
+ const elapsed = Date.now() - startTime
264
+ const progress = Math.min(1, elapsed / reboundDuration)
265
+ const eased = easeOutCubic(progress)
266
+
267
+ touchHandler.translateX = fromX + (target.x - fromX) * eased
268
+ touchHandler.translateY = fromY + (target.y - fromY) * eased
269
+ updateBaseTransform()
270
+ draw()
271
+ emitMove()
272
+
273
+ if (progress >= 1) {
274
+ touchHandler.translateX = target.x
275
+ touchHandler.translateY = target.y
276
+ updateBaseTransform()
277
+ draw()
278
+ emitMove()
279
+ reboundTimer = null
280
+ onComplete?.()
281
+ return
282
+ }
283
+
284
+ reboundTimer = setTimeout(animate, 16)
285
+ }
286
+
287
+ animate()
288
+ }
289
+
290
+ const startMomentum = (onComplete?: () => void) => {
291
+ stopMomentum()
292
+
293
+ if (Math.abs(panVelocityX) < momentumMinVelocity && Math.abs(panVelocityY) < momentumMinVelocity) {
294
+ reboundToBounds(onComplete)
295
+ return
296
+ }
297
+
298
+ let velocityX = panVelocityX
299
+ let velocityY = panVelocityY
300
+ let lastTime = Date.now()
301
+
302
+ const animate = () => {
303
+ const now = Date.now()
304
+ const dt = Math.min(24, Math.max(8, now - lastTime))
305
+ lastTime = now
306
+
307
+ const decay = Math.pow(momentumDecayPerFrame, dt / 16)
308
+ velocityX *= decay
309
+ velocityY *= decay
310
+
311
+ const nextTranslate = applyTranslateResistance(
312
+ touchHandler.translateX + velocityX * dt,
313
+ touchHandler.translateY + velocityY * dt,
314
+ )
315
+
316
+ touchHandler.translateX = nextTranslate.x
317
+ touchHandler.translateY = nextTranslate.y
318
+ updateBaseTransform()
319
+ draw()
320
+ emitMove()
321
+
322
+ const clamped = clampTranslate(touchHandler.translateX, touchHandler.translateY)
323
+ const outOfBounds =
324
+ Math.abs(clamped.x - touchHandler.translateX) > reboundThreshold ||
325
+ Math.abs(clamped.y - touchHandler.translateY) > reboundThreshold
326
+
327
+ if ((Math.abs(velocityX) < momentumMinVelocity && Math.abs(velocityY) < momentumMinVelocity) || outOfBounds) {
328
+ momentumTimer = null
329
+ panVelocityX = velocityX
330
+ panVelocityY = velocityY
331
+ reboundToBounds(onComplete)
332
+ return
333
+ }
334
+
335
+ momentumTimer = setTimeout(animate, 16)
336
+ }
337
+
338
+ animate()
339
+ }
340
+
341
+ const emitSeatSelection = (seat: SteSelectSeatItem) => {
342
+ emitSeatClick(seat)
343
+ emitModelValue(toggleSeat(seat.row, seat.col))
344
+ }
345
+
346
+ const selectSeatByPoint = (x: number, y: number) => {
347
+ const seat = getTouchSeat(x, y)
348
+ if (seat && !seat.disabled && !seat.empty) {
349
+ emitSeatSelection(seat)
350
+ }
351
+ }
352
+
353
+ const selectSeatFromTouch = (touch: UniTouch) => {
354
+ uni.createSelectorQuery()
355
+ .in(instance)
356
+ .select(`#${canvasId}`)
357
+ .boundingClientRect((rect: any) => {
358
+ if (!rect) return
359
+ const { x: localX, y: localY } = getTouchLocalPoint(touch, rect)
360
+ selectSeatByPoint(localX, localY)
361
+ })
362
+ .exec()
363
+ }
364
+
365
+ const selectSeatFromMouse = (event: PointerEventLike) => {
366
+ const rect = (event.target as HTMLElement | null)?.getBoundingClientRect?.()
367
+ if (!rect) return
368
+ selectSeatByPoint(event.clientX - rect.left, event.clientY - rect.top)
369
+ }
370
+
371
+ // ─── Pointer Events ───────────────────────────────────────────────────────
372
+
373
+ const onTouchStart = (e: UniTouchEvent) => {
374
+ stopMotion()
375
+ const touches = getEventTouches(e, 'start')
376
+ const touchCount = touches.length
377
+
378
+ if (touchCount >= 2) {
379
+ beginPinch(touches)
380
+ return
381
+ }
382
+
383
+ beginPan(touches[0], false)
384
+ }
385
+
386
+ const onTouchMove = (e: UniTouchEvent) => {
387
+ const touches = getEventTouches(e, 'move')
388
+ const touchCount = touches.length
389
+
390
+ if (touchCount >= 2) {
391
+ if (!pinchStartDistance) {
392
+ beginPinch(touches)
393
+ }
394
+
395
+ const currentDistance = getTouchDistance(touches)
396
+ const currentCenter = getTouchCenter(touches)
397
+ if (pinchStartDistance > 0 && currentDistance > 0) {
398
+ const nextScale = clampScale((currentDistance / pinchStartDistance) * pinchStartScale)
399
+ touchHandler.scale = nextScale
400
+
401
+ const nextTranslateX = currentCenter.x / nextScale - pinchStartCenterX / pinchStartScale + pinchLockedTranslateX
402
+ const nextTranslateY = currentCenter.y / nextScale - pinchStartCenterY / pinchStartScale + pinchLockedTranslateY
403
+ applyTranslate(nextTranslateX, nextTranslateY, nextScale)
404
+ }
405
+ draw()
406
+ emitMove()
407
+ return
408
+ }
409
+
410
+ if (gestureMode !== 'pan' || touchCount !== 1) return
411
+
412
+ const touch = touches[0]
413
+ const currentX = getTouchX(touch)
414
+ const currentY = getTouchY(touch)
415
+ const dx = currentX - panStartX
416
+ const dy = currentY - panStartY
417
+
418
+ if (Math.abs(dx) > panThreshold || Math.abs(dy) > panThreshold) {
419
+ dragMoved = true
420
+ }
421
+
422
+ applyTranslate(panBaseTranslateX + dx, panBaseTranslateY + dy)
423
+ recordPanVelocity(currentX, currentY)
424
+ draw()
425
+ emitMove()
426
+ }
427
+
428
+ const onTouchEnd = (e: UniTouchEvent) => {
429
+ const touches = getEventTouches(e, 'end')
430
+ const changedTouches = getChangedTouches(e)
431
+ const touchCount = touches.length
432
+
433
+ if (gestureMode === 'pinch') {
434
+ touchHandler.scale = clampScale(touchHandler.scale)
435
+ applyTranslate(touchHandler.translateX, touchHandler.translateY, touchHandler.scale)
436
+ pinchStartDistance = 0
437
+ }
438
+
439
+ updateBaseTransform()
440
+
441
+ if (touchCount >= 2) {
442
+ beginPinch(touches)
443
+ draw()
444
+ return
445
+ }
446
+
447
+ if (touchCount === 1) {
448
+ beginPan(touches[0], true)
449
+ } else if (touchCount === 0) {
450
+ gestureMode = 'none'
451
+ }
452
+
453
+ draw()
454
+ if (touchCount === 0 && dragMoved) {
455
+ startMomentum(() => showRowLabelOverlay())
456
+ } else if (touchCount === 0 || gestureMode === 'pinch') {
457
+ reboundToBounds(() => {
458
+ if (touchCount === 0) showRowLabelOverlay()
459
+ })
460
+ }
461
+
462
+ if (!dragMoved && changedTouches.length === 1) {
463
+ selectSeatFromTouch(changedTouches[0])
464
+ }
465
+ }
466
+
467
+ const onMouseDown = (e: PointerEventLike) => {
468
+ stopMotion()
469
+ mouseDown = true
470
+ dragMoved = false
471
+ mouseStartX = e.clientX
472
+ mouseStartY = e.clientY
473
+ resetPanVelocity()
474
+ recordPanVelocity(mouseStartX, mouseStartY)
475
+ }
476
+
477
+ const onMouseMove = (e: PointerEventLike) => {
478
+ if (!mouseDown) return
479
+ const dx = e.clientX - mouseStartX
480
+ const dy = e.clientY - mouseStartY
481
+ if (Math.abs(dx) > 2 || Math.abs(dy) > 2) {
482
+ dragMoved = true
483
+ }
484
+ applyTranslate(touchHandler.baseTranslateX + dx, touchHandler.baseTranslateY + dy)
485
+ recordPanVelocity(e.clientX, e.clientY)
486
+ draw()
487
+ emitMove()
488
+ }
489
+
490
+ const onMouseUp = (e: PointerEventLike) => {
491
+ if (!mouseDown) return
492
+ mouseDown = false
493
+ updateBaseTransform()
494
+ if (dragMoved) {
495
+ startMomentum(() => showRowLabelOverlay())
496
+ } else {
497
+ reboundToBounds(() => showRowLabelOverlay())
498
+ }
499
+
500
+ if (!dragMoved) {
501
+ selectSeatFromMouse(e)
502
+ }
503
+ }
504
+
505
+ // ─── Public API ───────────────────────────────────────────────────────────
506
+
507
+ const reset = () => {
508
+ stopMotion()
509
+ showRowLabelOverlay()
510
+ activeTouches.clear()
511
+ touchHandler.reset()
512
+ gestureMode = 'none'
513
+ dragMoved = false
514
+ pinchStartDistance = 0
515
+ pinchStartScale = 1
516
+ pinchStartCenterX = 0
517
+ pinchStartCenterY = 0
518
+ pinchLockedTranslateX = 0
519
+ pinchLockedTranslateY = 0
520
+ panStartX = 0
521
+ panStartY = 0
522
+ panBaseTranslateX = 0
523
+ panBaseTranslateY = 0
524
+ resetPanVelocity()
525
+ applyDefaultViewport()
526
+ draw()
527
+ }
528
+
529
+ return {
530
+ rowLabelsVisible,
531
+ setShowRowLabelsVisible: setRowLabelsVisible,
532
+ onTouchStart,
533
+ onTouchMove,
534
+ onTouchEnd,
535
+ onMouseDown,
536
+ onMouseMove,
537
+ onMouseUp,
538
+ reset,
539
+ }
540
+ }
@@ -0,0 +1,37 @@
1
+ import type { PropType } from 'vue'
2
+ import type { SteSelectSeatItem, SteSelectSeatValue } from './types'
3
+
4
+ export default {
5
+ // 已选座位 v-model
6
+ modelValue: { type: Array as PropType<SteSelectSeatValue[]>, default: () => [] },
7
+ // 行数
8
+ rows: { type: Number, default: 0 },
9
+ // 列数
10
+ cols: { type: Number, default: 0 },
11
+ // 组件宽度(px)
12
+ width: { type: Number, default: 350 },
13
+ // 组件高度(px)
14
+ height: { type: Number, default: 400 },
15
+ // 自定义座位数据
16
+ seats: { type: Array as PropType<SteSelectSeatItem[]>, default: () => [] },
17
+ // 座位尺寸(rpx)
18
+ seatSize: { type: Number, default: 40 },
19
+ // 座位间距(rpx)
20
+ seatGap: { type: Number, default: 8 },
21
+ // 座位圆角(rpx)
22
+ borderRadius: { type: Number, default: 8 },
23
+ // 边框宽度
24
+ borderWidth: { type: Number, default: 1 },
25
+ // 座位背景色
26
+ bgColor: { type: String, default: '#ffffff' },
27
+ // 边框颜色
28
+ borderColor: { type: String, default: '#e5e5e5' },
29
+ // 选中背景色(默认用主题色)
30
+ selectedBgColor: { type: String, default: '' },
31
+ // 选中图标颜色
32
+ selectedColor: { type: String, default: '#ffffff' },
33
+ // 禁用背景色
34
+ disabledBgColor: { type: String, default: '#cccccc' },
35
+ // 显示行号
36
+ showRowLabels: { type: Boolean, default: true },
37
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "ste-select-seat",
3
+ "description": "基于 Canvas 的座位选择组件",
4
+ "example": "<ste-select-seat v-model='selected' :rows='5' :cols='10'></ste-select-seat>",
5
+ "tutorial": "https://stellar-ui.intecloud.com.cn/?projectName=stellar-ui-plus&menu=%E7%BB%84%E4%BB%B6&active=ste-select-seat",
6
+ "attributes": [
7
+ {
8
+ "name": "modelValue",
9
+ "description": "已选座位坐标列表(仅包含 row/col)",
10
+ "type": "SteSelectSeatValue[]"
11
+ },
12
+ {
13
+ "name": "rows",
14
+ "description": "行数",
15
+ "type": "number"
16
+ },
17
+ {
18
+ "name": "cols",
19
+ "description": "列数",
20
+ "type": "number"
21
+ },
22
+ {
23
+ "name": "width",
24
+ "description": "组件宽度(px)",
25
+ "type": "number",
26
+ "default": "350"
27
+ },
28
+ {
29
+ "name": "height",
30
+ "description": "组件高度(px)",
31
+ "type": "number",
32
+ "default": "400"
33
+ },
34
+ {
35
+ "name": "seats",
36
+ "description": "座位属性配置(未配置的位置会自动补齐为默认座位)",
37
+ "type": "SteSelectSeatItem[]"
38
+ },
39
+ {
40
+ "name": "seatSize",
41
+ "description": "座位尺寸(rpx)",
42
+ "type": "number",
43
+ "default": "40"
44
+ },
45
+ {
46
+ "name": "seatGap",
47
+ "description": "座位间距(rpx)",
48
+ "type": "number",
49
+ "default": "8"
50
+ },
51
+ {
52
+ "name": "[event]seat-click",
53
+ "description": "点击有效座位事件(empty/disabled 不触发)",
54
+ "type": "(seat: SteSelectSeatItem) => void"
55
+ },
56
+ {
57
+ "name": "[event]move",
58
+ "description": "拖动/缩放事件",
59
+ "type": "(data: { translateX, translateY, scale, screenTranslateX }) => void"
60
+ }
61
+ ]
62
+ }