@didaoktv/didaoui-uniapp 1.3.3 → 1.3.5
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.
- package/README.md +3 -3
- package/components/dd-action-sheet/dd-action-sheet.vue +3 -0
- package/components/dd-alert/dd-alert.vue +3 -0
- package/components/dd-car-keyboard/carPlate.ts +47 -0
- package/components/dd-car-keyboard/dd-car-keyboard.vue +247 -285
- package/components/dd-date-picker/dd-date-picker.vue +3 -0
- package/components/dd-dialog/dd-dialog.vue +22 -13
- package/components/dd-drawer/dd-drawer.vue +3 -0
- package/components/dd-dropdown-item/dd-dropdown-item.vue +3 -0
- package/components/dd-dropdown-menu/dd-dropdown-menu.vue +3 -0
- package/components/dd-keyboard/dd-keyboard.vue +5 -14
- package/components/dd-keyboard/keyboard.js +1 -2
- package/components/dd-keyboard/props.js +0 -5
- package/components/dd-loading/dd-loading.vue +5 -1
- package/components/dd-modal/dd-modal.vue +3 -0
- package/components/dd-overlay/dd-overlay.vue +3 -0
- package/components/dd-picker/dd-picker.vue +26 -0
- package/components/dd-popup/dd-popup.vue +4 -0
- package/components/dd-portal/dd-portal.vue +22 -0
- package/components/dd-toast/dd-toast.vue +3 -0
- package/index.ts +4 -3
- package/libs/config/props.js +0 -1
- package/libs/config/zIndex.d.ts +14 -0
- package/libs/config/zIndex.js +3 -0
- package/package.json +1 -1
- package/components/dd-car-keyboard/carKeyboard.js +0 -6
- package/components/dd-car-keyboard/props.js +0 -19
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
# @didaoktv/didaoui-uniapp
|
|
2
2
|
|
|
3
3
|
专为 KTV 场景打造的 UniApp 组件库。
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
- **帝王级配色** — 帝王金 `#F5A623` + 皇家蓝 `#2D4BA0` 双主色,暗色主题默认
|
|
8
8
|
- **玻璃拟态设计** — 多层级玻璃拟态效果,打造高端夜店沉浸感
|
|
9
|
-
- **
|
|
9
|
+
- **90 个精心打磨的组件** — 覆盖表单、导航、布局卡片、数据展示、浮层反馈、交互、画布七大类,含 KTV 业务组件(房态卡、账单明细、工单卡、日历、二维码)
|
|
10
10
|
- **Vue3 + TypeScript** — 完整类型定义,Composition API
|
|
11
11
|
- **多端兼容** — H5 / 微信小程序 / 抖音小程序 / Android / iOS
|
|
12
12
|
|
|
@@ -54,7 +54,7 @@ import { DdButton, DdInput } from '@didaoktv/didaoui-uniapp'
|
|
|
54
54
|
| 导航 | 12 | Navigation, TopNavbar, SwipeableTab, SegmentedTab, Drawer, Tabbar, TabbarItem, Backtop, Collapse, CollapseItem, DropdownMenu, DropdownItem |
|
|
55
55
|
| 布局/卡片 | 8 | Card, RoomCard, FeatureGrid, Sticky, BillDetail, WorkorderCard, Calendar, Qrcode |
|
|
56
56
|
| 数据展示 | 24 | Tag, StatCard, ChampionCard, Avatar, AvatarGroup, Badge, ListCell, Cell, CellGroup, CountDown, Divider, Image, Progress, Skeleton, EmptyState, Step, Steps, Text, Link, Copy, Album, Coupon, Parse, Markdown |
|
|
57
|
-
| 浮层反馈 |
|
|
57
|
+
| 浮层反馈 | 11 | Modal, ActionSheet, Toast, Alert, Loading, Dialog, Overlay, Popup, Popover, PopoverItem, Portal |
|
|
58
58
|
| 交互 | 5 | SwipeAction, Swipe, SwipeItem, PullRefresh, Loadmore |
|
|
59
59
|
| 小程序专属 | 2 | CapsuleButton, MiniProgramNavbar |
|
|
60
60
|
| 画布 | 5 | Canvas, Barcode, Cropper, Signature, Poster |
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<dd-portal>
|
|
2
3
|
<view class="dd-action-sheet">
|
|
3
4
|
<view
|
|
4
5
|
class="dd-action-sheet__mask"
|
|
@@ -33,9 +34,11 @@
|
|
|
33
34
|
<view class="dd-action-sheet__safe-bottom"></view>
|
|
34
35
|
</view>
|
|
35
36
|
</view>
|
|
37
|
+
</dd-portal>
|
|
36
38
|
</template>
|
|
37
39
|
|
|
38
40
|
<script setup lang="ts">
|
|
41
|
+
import DdPortal from '../dd-portal/dd-portal.vue'
|
|
39
42
|
import DdIcon from '../dd-icon/dd-icon.vue'
|
|
40
43
|
|
|
41
44
|
interface ActionItem {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<dd-portal>
|
|
2
3
|
<view class="dd-alert">
|
|
3
4
|
<view
|
|
4
5
|
class="dd-alert__mask"
|
|
@@ -21,10 +22,12 @@
|
|
|
21
22
|
</view>
|
|
22
23
|
</view>
|
|
23
24
|
</view>
|
|
25
|
+
</dd-portal>
|
|
24
26
|
</template>
|
|
25
27
|
|
|
26
28
|
<script setup lang="ts">
|
|
27
29
|
import { computed } from 'vue'
|
|
30
|
+
import DdPortal from '../dd-portal/dd-portal.vue'
|
|
28
31
|
import DdIcon from '../dd-icon/dd-icon.vue'
|
|
29
32
|
|
|
30
33
|
type AlertType = 'info' | 'success' | 'warning' | 'error' | 'confirm'
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// 车牌号键盘纯逻辑:键位布局、按位锁键、光标推进(供 dd-car-keyboard.vue 消费)
|
|
2
|
+
export const MAX_LEN = 8
|
|
3
|
+
|
|
4
|
+
export interface KeyItem {
|
|
5
|
+
label: string
|
|
6
|
+
locked: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// 省份行(参考实现末行含字母 W 为笔误,此处修正为 港/澳)
|
|
10
|
+
export const PROVINCE_ROWS: string[][] = [
|
|
11
|
+
['京', '津', '晋', '冀', '蒙', '辽', '吉', '黑', '沪'],
|
|
12
|
+
['苏', '浙', '皖', '闽', '赣', '鲁', '豫', '鄂', '湘'],
|
|
13
|
+
['粤', '桂', '琼', '渝', '川', '贵', '云', '藏'],
|
|
14
|
+
['陕', '甘', '青', '宁', '新', '港', '澳']
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
const DIGIT_ROW = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
|
|
18
|
+
const EN_ROW2_DEFAULT = ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'O', 'P', '挂']
|
|
19
|
+
// 第 6 位(新能源序号位)去掉 O,追加 学/挂
|
|
20
|
+
const EN_ROW2_ENERGY = ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'P', '学', '挂']
|
|
21
|
+
const EN_ROW3 = ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '警']
|
|
22
|
+
const EN_ROW4 = ['Z', 'X', 'C', 'V', 'B', 'N', 'M', '港', '澳']
|
|
23
|
+
|
|
24
|
+
// 按位锁键:1 位禁数字与特殊字;2-5/7 位禁 O 与特殊字;6 位(新能源)仅禁 O
|
|
25
|
+
export function getLockedKeys(pos: number): string[] {
|
|
26
|
+
if (pos <= 0) return []
|
|
27
|
+
if (pos === 1) return [...DIGIT_ROW, '学', '挂', '警', '港', '澳']
|
|
28
|
+
if (pos === MAX_LEN - 2) return ['O']
|
|
29
|
+
return ['O', '学', '挂', '警', '港', '澳']
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// pos=0 返回省份键盘,其余位返回字母数字键盘(带锁定态)
|
|
33
|
+
export function getKeyRows(pos: number): KeyItem[][] {
|
|
34
|
+
if (pos === 0) {
|
|
35
|
+
return PROVINCE_ROWS.map((row) => row.map((label) => ({ label, locked: false })))
|
|
36
|
+
}
|
|
37
|
+
const row2 = pos === MAX_LEN - 2 ? EN_ROW2_ENERGY : EN_ROW2_DEFAULT
|
|
38
|
+
const locked = getLockedKeys(pos)
|
|
39
|
+
return [DIGIT_ROW, row2, EN_ROW3, EN_ROW4].map((row) =>
|
|
40
|
+
row.map((label) => ({ label, locked: locked.includes(label) }))
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 填完第 7 位后收起键盘(返回 -1),新能源位(第 8 位)由用户主动点选
|
|
45
|
+
export function nextPos(pos: number): number {
|
|
46
|
+
return pos < MAX_LEN - 2 ? pos + 1 : -1
|
|
47
|
+
}
|
|
@@ -1,315 +1,277 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<view
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
>
|
|
6
|
-
<view
|
|
7
|
-
v-for="(group, i) in abc ? engKeyBoardList : areaList"
|
|
8
|
-
:key="i"
|
|
9
|
-
class="dd-keyboard__button"
|
|
10
|
-
:index="i"
|
|
11
|
-
:class="[i + 1 === 4 && 'dd-keyboard__button--center']"
|
|
12
|
-
>
|
|
2
|
+
<view class="dd-car-keyboard" :class="customClass" :style="customStyle">
|
|
3
|
+
<!-- 车牌格子:7 位普通 + 第 8 位新能源(绿框) -->
|
|
4
|
+
<view class="dd-car-keyboard__boxes">
|
|
13
5
|
<view
|
|
14
|
-
v-
|
|
15
|
-
|
|
6
|
+
v-for="(char, index) in cells"
|
|
7
|
+
:key="index"
|
|
8
|
+
class="dd-car-keyboard__box"
|
|
9
|
+
:class="[
|
|
10
|
+
active === index && 'dd-car-keyboard__box--active',
|
|
11
|
+
index === 7 && 'dd-car-keyboard__box--energy'
|
|
12
|
+
]"
|
|
13
|
+
@tap="onBoxTap(index)"
|
|
16
14
|
>
|
|
17
15
|
<view
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
v-if="active === index"
|
|
17
|
+
class="dd-car-keyboard__box-line"
|
|
18
|
+
></view>
|
|
19
|
+
<view
|
|
20
|
+
v-if="index === 7"
|
|
21
|
+
class="dd-car-keyboard__badge"
|
|
22
22
|
>
|
|
23
|
-
<text
|
|
24
|
-
class="dd-keyboard__button__inner-wrapper__left__lang"
|
|
25
|
-
:class="[!abc && 'dd-keyboard__button__inner-wrapper__left__lang--active']"
|
|
26
|
-
>中</text>
|
|
27
|
-
<text class="dd-keyboard__button__inner-wrapper__left__line">/</text>
|
|
28
|
-
<text
|
|
29
|
-
class="dd-keyboard__button__inner-wrapper__left__lang"
|
|
30
|
-
:class="[abc && 'dd-keyboard__button__inner-wrapper__left__lang--active']"
|
|
31
|
-
>英</text>
|
|
23
|
+
<text class="dd-car-keyboard__badge-text">新能源</text>
|
|
32
24
|
</view>
|
|
25
|
+
<text class="dd-car-keyboard__box-text">{{ char }}</text>
|
|
26
|
+
</view>
|
|
27
|
+
</view>
|
|
28
|
+
|
|
29
|
+
<!-- 键盘弹层:0 位省份键盘,其余位字母数字键盘(按位锁键) -->
|
|
30
|
+
<view
|
|
31
|
+
v-if="active >= 0"
|
|
32
|
+
class="dd-car-keyboard__panel"
|
|
33
|
+
@touchmove.stop.prevent="noop"
|
|
34
|
+
>
|
|
35
|
+
<view class="dd-car-keyboard__close" @tap="closeKeyboard">
|
|
36
|
+
<text class="dd-car-keyboard__close-text">关闭</text>
|
|
33
37
|
</view>
|
|
34
38
|
<view
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
v-for="(row, rowIndex) in keyRows"
|
|
40
|
+
:key="rowIndex"
|
|
41
|
+
class="dd-car-keyboard__row"
|
|
38
42
|
>
|
|
39
43
|
<view
|
|
40
|
-
|
|
41
|
-
:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
v-for="item in row"
|
|
45
|
+
:key="item.label"
|
|
46
|
+
class="dd-car-keyboard__key"
|
|
47
|
+
:class="[item.locked && 'dd-car-keyboard__key--lock']"
|
|
48
|
+
hover-class="dd-car-keyboard__key--hover"
|
|
49
|
+
:hover-stay-time="100"
|
|
50
|
+
@tap="onKeyTap(item)"
|
|
44
51
|
>
|
|
45
|
-
<text class="dd-
|
|
52
|
+
<text class="dd-car-keyboard__key-text">{{ item.label }}</text>
|
|
46
53
|
</view>
|
|
47
|
-
</view>
|
|
48
|
-
<view
|
|
49
|
-
v-if="i === 3"
|
|
50
|
-
@touchstart="backspaceClick"
|
|
51
|
-
@touchend="clearTimer"
|
|
52
|
-
class="dd-keyboard__button__inner-wrapper"
|
|
53
|
-
>
|
|
54
54
|
<view
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
v-if="rowIndex === 3"
|
|
56
|
+
class="dd-car-keyboard__key dd-car-keyboard__key--del"
|
|
57
|
+
hover-class="dd-car-keyboard__key--hover"
|
|
58
|
+
:hover-stay-time="100"
|
|
59
|
+
@tap="onBackspaceTap"
|
|
58
60
|
>
|
|
59
|
-
<dd-icon
|
|
60
|
-
size="28"
|
|
61
|
-
name="backspace"
|
|
62
|
-
></dd-icon>
|
|
61
|
+
<dd-icon size="22" name="backspace"></dd-icon>
|
|
63
62
|
</view>
|
|
64
63
|
</view>
|
|
65
64
|
</view>
|
|
66
65
|
</view>
|
|
67
66
|
</template>
|
|
68
67
|
|
|
69
|
-
<script>
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
'Q',
|
|
154
|
-
'W',
|
|
155
|
-
'E',
|
|
156
|
-
'R',
|
|
157
|
-
'T',
|
|
158
|
-
'Y',
|
|
159
|
-
'U',
|
|
160
|
-
'I',
|
|
161
|
-
'O',
|
|
162
|
-
'P',
|
|
163
|
-
'A',
|
|
164
|
-
'S',
|
|
165
|
-
'D',
|
|
166
|
-
'F',
|
|
167
|
-
'G',
|
|
168
|
-
'H',
|
|
169
|
-
'J',
|
|
170
|
-
'K',
|
|
171
|
-
'L',
|
|
172
|
-
'Z',
|
|
173
|
-
'X',
|
|
174
|
-
'C',
|
|
175
|
-
'V',
|
|
176
|
-
'B',
|
|
177
|
-
'N',
|
|
178
|
-
'M'
|
|
179
|
-
];
|
|
180
|
-
let tmp = [];
|
|
181
|
-
if (this.random) data = randomArray(data);
|
|
182
|
-
tmp[0] = data.slice(0, 10);
|
|
183
|
-
tmp[1] = data.slice(10, 20);
|
|
184
|
-
tmp[2] = data.slice(20, 30);
|
|
185
|
-
tmp[3] = data.slice(30, 36);
|
|
186
|
-
return tmp;
|
|
187
|
-
}
|
|
188
|
-
},
|
|
189
|
-
emits: ["change", "backspace"],
|
|
190
|
-
methods: {
|
|
191
|
-
// 点击键盘按钮
|
|
192
|
-
carInputClick(i, j) {
|
|
193
|
-
let value = '';
|
|
194
|
-
// 不同模式,获取不同数组的值
|
|
195
|
-
if (this.abc) value = this.engKeyBoardList[i][j];
|
|
196
|
-
else value = this.areaList[i][j];
|
|
197
|
-
// 如果允许自动切换,则将中文状态切换为英文
|
|
198
|
-
if (!this.abc && this.autoChange) sleep(200).then(() => this.abc = true)
|
|
199
|
-
this.$emit('change', value);
|
|
200
|
-
},
|
|
201
|
-
// 修改汽车牌键盘的输入模式,中文|英文
|
|
202
|
-
changeCarInputMode() {
|
|
203
|
-
this.abc = !this.abc;
|
|
204
|
-
},
|
|
205
|
-
// 点击退格键
|
|
206
|
-
backspaceClick() {
|
|
207
|
-
this.$emit('backspace');
|
|
208
|
-
clearInterval(this.timer); //再次清空定时器,防止重复注册定时器
|
|
209
|
-
this.timer = null;
|
|
210
|
-
this.timer = setInterval(() => {
|
|
211
|
-
this.$emit('backspace');
|
|
212
|
-
}, 250);
|
|
213
|
-
},
|
|
214
|
-
clearTimer() {
|
|
215
|
-
clearInterval(this.timer);
|
|
216
|
-
this.timer = null;
|
|
217
|
-
},
|
|
218
|
-
}
|
|
219
|
-
};
|
|
68
|
+
<script setup lang="ts">
|
|
69
|
+
import { computed, ref, watch } from 'vue'
|
|
70
|
+
import DdIcon from '../dd-icon/dd-icon.vue'
|
|
71
|
+
import { MAX_LEN, getKeyRows, nextPos, type KeyItem } from './carPlate'
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* dd-car-keyboard 车牌号输入键盘
|
|
75
|
+
* 车牌格子 + 弹出键盘一体:0 位省份简称,其余位字母数字,按位锁键,末位为新能源(绿牌)位
|
|
76
|
+
* @property {String} modelValue 车牌号(v-model)
|
|
77
|
+
* @event {Function} update:modelValue 输入变化
|
|
78
|
+
* @event {Function} focus 键盘弹出
|
|
79
|
+
* @event {Function} blur 键盘收起
|
|
80
|
+
* @example <dd-car-keyboard v-model="plateNo" />
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
interface Props {
|
|
84
|
+
modelValue?: string
|
|
85
|
+
customClass?: string
|
|
86
|
+
customStyle?: string
|
|
87
|
+
}
|
|
88
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
89
|
+
modelValue: '',
|
|
90
|
+
customClass: '',
|
|
91
|
+
customStyle: ''
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
const emit = defineEmits<{
|
|
95
|
+
(e: 'update:modelValue', val: string): void
|
|
96
|
+
(e: 'focus', val: string): void
|
|
97
|
+
(e: 'blur', val: string): void
|
|
98
|
+
}>()
|
|
99
|
+
|
|
100
|
+
// 空位用空格占位(与退格逻辑配合:清当前位后停留在该位)
|
|
101
|
+
const cells = ref<string[]>(Array(MAX_LEN).fill(' '))
|
|
102
|
+
const active = ref(-1)
|
|
103
|
+
|
|
104
|
+
// 键位布局/按位锁键纯逻辑见 ./carPlate
|
|
105
|
+
const keyRows = computed(() => getKeyRows(active.value))
|
|
106
|
+
|
|
107
|
+
// 外部 v-model 同步到格子(支持清空与部分更新)
|
|
108
|
+
watch(
|
|
109
|
+
() => props.modelValue,
|
|
110
|
+
(val) => {
|
|
111
|
+
const list = (val || '').split('')
|
|
112
|
+
cells.value = Array.from({ length: MAX_LEN }, (_, i) => list[i] ?? ' ')
|
|
113
|
+
},
|
|
114
|
+
{ immediate: true }
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
const keyboardVisible = computed(() => active.value >= 0)
|
|
118
|
+
watch(keyboardVisible, (visible) => {
|
|
119
|
+
if (visible) emit('focus', props.modelValue)
|
|
120
|
+
else emit('blur', props.modelValue)
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
function noop() {}
|
|
124
|
+
|
|
125
|
+
function onBoxTap(index: number) {
|
|
126
|
+
active.value = index
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function onKeyTap(item: KeyItem) {
|
|
130
|
+
if (item.locked || active.value < 0) return
|
|
131
|
+
cells.value[active.value] = item.label
|
|
132
|
+
active.value = nextPos(active.value)
|
|
133
|
+
emitValue()
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function closeKeyboard() {
|
|
137
|
+
active.value = -1
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function onBackspaceTap() {
|
|
141
|
+
if (active.value < 0) return
|
|
142
|
+
if (cells.value[active.value] === ' ' && active.value > 0) {
|
|
143
|
+
active.value--
|
|
144
|
+
}
|
|
145
|
+
cells.value[active.value] = ' '
|
|
146
|
+
emitValue()
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function emitValue() {
|
|
150
|
+
emit('update:modelValue', cells.value.join('').trim())
|
|
151
|
+
}
|
|
220
152
|
</script>
|
|
221
153
|
|
|
222
154
|
<style lang="scss" scoped>
|
|
155
|
+
/* 头部固定引入;只消费 $dd-* token,样式值写 var(--dd-x, $dd-x) 兜底形式 */
|
|
223
156
|
@import '../../scss/variables';
|
|
224
157
|
@import '../../scss/dd-shared';
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
158
|
+
|
|
159
|
+
$dd-car-keyboard-gap: 8rpx !default;
|
|
160
|
+
$dd-car-keyboard-box-height: 76rpx !default;
|
|
161
|
+
$dd-car-keyboard-box-border: 1px solid var(--dd-border-default, #{$dd-border-default}) !default;
|
|
162
|
+
$dd-car-keyboard-key-height: 76rpx !default;
|
|
163
|
+
$dd-car-keyboard-panel-padding: 0 var(--dd-space-2, #{$dd-space-2}) var(--dd-space-2, #{$dd-space-2}) !default;
|
|
164
|
+
|
|
165
|
+
.dd-car-keyboard {
|
|
166
|
+
&__boxes {
|
|
167
|
+
@include flex;
|
|
168
|
+
gap: $dd-car-keyboard-gap;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
&__box {
|
|
172
|
+
@include flex;
|
|
173
|
+
position: relative;
|
|
174
|
+
justify-content: center;
|
|
175
|
+
align-items: center;
|
|
176
|
+
flex: 1;
|
|
177
|
+
height: $dd-car-keyboard-box-height;
|
|
178
|
+
border: $dd-car-keyboard-box-border;
|
|
179
|
+
border-radius: var(--dd-radius-md, #{$dd-radius-md});
|
|
180
|
+
|
|
181
|
+
&--active {
|
|
182
|
+
border-color: var(--dd-primary-400, #{$dd-primary-400});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
&--energy {
|
|
186
|
+
border-color: var(--dd-success-500, #{$dd-success-500});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
&__box-line {
|
|
191
|
+
position: absolute;
|
|
192
|
+
bottom: 6rpx;
|
|
193
|
+
left: 15%;
|
|
194
|
+
width: 70%;
|
|
195
|
+
height: 4rpx;
|
|
196
|
+
background-color: var(--dd-primary-400, #{$dd-primary-400});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
&__box-text {
|
|
200
|
+
font-size: 17px;
|
|
201
|
+
color: var(--dd-text-primary, #{$dd-text-primary});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
&__badge {
|
|
205
|
+
@include flex;
|
|
206
|
+
justify-content: center;
|
|
207
|
+
position: absolute;
|
|
208
|
+
top: -14rpx;
|
|
209
|
+
left: 50%;
|
|
210
|
+
transform: translateX(-50%);
|
|
211
|
+
padding: 0 6rpx;
|
|
212
|
+
background-color: var(--dd-success-500, #{$dd-success-500});
|
|
213
|
+
border-radius: var(--dd-radius-sm, #{$dd-radius-sm});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
&__badge-text {
|
|
217
|
+
font-size: 10px;
|
|
218
|
+
color: var(--dd-success-contrast, #{$dd-success-contrast});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
&__panel {
|
|
222
|
+
position: fixed;
|
|
223
|
+
right: 0;
|
|
224
|
+
bottom: 0;
|
|
225
|
+
left: 0;
|
|
226
|
+
z-index: 10075; // ponytail: 取 libs/config/zIndex.js popup 值,模板内不能用表达式故字面量
|
|
227
|
+
background-color: var(--dd-bg-section, #{$dd-bg-section});
|
|
228
|
+
padding: $dd-car-keyboard-panel-padding;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
&__close {
|
|
232
|
+
@include flex;
|
|
233
|
+
justify-content: flex-end;
|
|
234
|
+
padding: var(--dd-space-2, #{$dd-space-2}) 0;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
&__close-text {
|
|
238
|
+
padding: 0 var(--dd-space-2, #{$dd-space-2});
|
|
239
|
+
font-size: 13.5px;
|
|
240
|
+
color: var(--dd-text-secondary, #{$dd-text-secondary});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
&__row {
|
|
244
|
+
@include flex;
|
|
245
|
+
margin-top: var(--dd-space-2, #{$dd-space-2});
|
|
246
|
+
gap: $dd-car-keyboard-gap;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
&__key {
|
|
250
|
+
@include flex;
|
|
251
|
+
justify-content: center;
|
|
252
|
+
align-items: center;
|
|
253
|
+
flex: 1;
|
|
254
|
+
height: $dd-car-keyboard-key-height;
|
|
255
|
+
background-color: var(--dd-surface-container-high, #{$dd-surface-container-high});
|
|
256
|
+
border-radius: var(--dd-radius-md, #{$dd-radius-md});
|
|
257
|
+
|
|
258
|
+
&--lock {
|
|
259
|
+
opacity: 0.35;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
&--hover {
|
|
263
|
+
background-color: var(--dd-surface-hover, #{$dd-surface-hover});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
&--del {
|
|
267
|
+
flex: 2;
|
|
268
|
+
color: var(--dd-text-primary, #{$dd-text-primary}); // 图标 color=inherit,由此处控制
|
|
309
269
|
}
|
|
310
270
|
}
|
|
311
271
|
|
|
312
|
-
|
|
313
|
-
|
|
272
|
+
&__key-text {
|
|
273
|
+
font-size: 16px;
|
|
274
|
+
color: var(--dd-text-primary, #{$dd-text-primary});
|
|
314
275
|
}
|
|
276
|
+
}
|
|
315
277
|
</style>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<dd-portal>
|
|
2
3
|
<view class="dd-dp" :class="{ 'dd-dp--open': show }">
|
|
3
4
|
<view class="dd-dp__mask" @click="onMaskClick"></view>
|
|
4
5
|
<view class="dd-dp__sheet">
|
|
@@ -21,10 +22,12 @@
|
|
|
21
22
|
</picker-view>
|
|
22
23
|
</view>
|
|
23
24
|
</view>
|
|
25
|
+
</dd-portal>
|
|
24
26
|
</template>
|
|
25
27
|
|
|
26
28
|
<script setup lang="ts">
|
|
27
29
|
import { computed, ref, watch } from 'vue'
|
|
30
|
+
import DdPortal from '../dd-portal/dd-portal.vue'
|
|
28
31
|
|
|
29
32
|
interface Props {
|
|
30
33
|
show?: boolean
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
<!-- 内容经 portal 提升到页面根节点:规避 transform 祖先劫持 fixed 定位(详见 dd-portal 组件) -->
|
|
3
|
+
<dd-portal>
|
|
4
|
+
<view class="dd-dialog">
|
|
5
|
+
<view
|
|
6
|
+
class="dd-dialog__mask"
|
|
7
|
+
:class="{ 'dd-dialog__mask--show': modelValue }"
|
|
8
|
+
:style="{ zIndex: maskZIndex }"
|
|
9
|
+
@click="onOverlayClick"
|
|
10
|
+
></view>
|
|
11
|
+
<view
|
|
12
|
+
class="dd-dialog__card"
|
|
13
|
+
:class="[{ 'dd-dialog__card--show': modelValue }, `dd-dialog__card--${theme}`]"
|
|
14
|
+
:style="{ width: widthValue, maxWidth: '92vw', zIndex: cardZIndex }"
|
|
15
|
+
>
|
|
13
16
|
<view v-if="title" class="dd-dialog__header">
|
|
14
17
|
<text class="dd-dialog__title">{{ title }}</text>
|
|
15
18
|
</view>
|
|
@@ -55,10 +58,17 @@
|
|
|
55
58
|
</view>
|
|
56
59
|
</view>
|
|
57
60
|
</view>
|
|
61
|
+
</dd-portal>
|
|
58
62
|
</template>
|
|
59
63
|
|
|
60
64
|
<script setup lang="ts">
|
|
61
65
|
import { computed } from 'vue'
|
|
66
|
+
import zIndexConfig from '../../libs/config/zIndex.js'
|
|
67
|
+
import DdPortal from '../dd-portal/dd-portal.vue'
|
|
68
|
+
|
|
69
|
+
/* z-index 统一取 libs/config/zIndex.js(弹窗需压在 popup 面板之上、toast 之下) */
|
|
70
|
+
const maskZIndex = zIndexConfig.dialogMask
|
|
71
|
+
const cardZIndex = zIndexConfig.dialog
|
|
62
72
|
|
|
63
73
|
interface Props {
|
|
64
74
|
modelValue?: boolean
|
|
@@ -148,7 +158,7 @@ function onCancel() {
|
|
|
148
158
|
background: var(--dd-color-overlay-strong, #{$dd-color-overlay-strong});
|
|
149
159
|
opacity: 0;
|
|
150
160
|
visibility: hidden;
|
|
151
|
-
z-index
|
|
161
|
+
/* z-index 由 script 注入(libs/config/zIndex.js) */
|
|
152
162
|
@include dd-transition(opacity 0.3s ease, visibility 0.3s);
|
|
153
163
|
|
|
154
164
|
&--show {
|
|
@@ -164,7 +174,6 @@ function onCancel() {
|
|
|
164
174
|
transform: translate(-50%, -50%) scale(0.9);
|
|
165
175
|
opacity: 0;
|
|
166
176
|
visibility: hidden;
|
|
167
|
-
z-index: 2001;
|
|
168
177
|
background: var(--dd-bg-elevated, #{$dd-bg-elevated});
|
|
169
178
|
border: 1px solid var(--dd-border-default, #{$dd-border-default});
|
|
170
179
|
border-radius: $dd-radius-lg;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<dd-portal>
|
|
2
3
|
<view class="dd-drawer">
|
|
3
4
|
<view
|
|
4
5
|
class="dd-drawer__mask"
|
|
@@ -36,10 +37,12 @@
|
|
|
36
37
|
</scroll-view>
|
|
37
38
|
</view>
|
|
38
39
|
</view>
|
|
40
|
+
</dd-portal>
|
|
39
41
|
</template>
|
|
40
42
|
|
|
41
43
|
<script setup lang="ts">
|
|
42
44
|
import { watch } from 'vue'
|
|
45
|
+
import DdPortal from '../dd-portal/dd-portal.vue'
|
|
43
46
|
|
|
44
47
|
interface Props {
|
|
45
48
|
modelValue?: boolean
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
:class="{ 'dd-dropdown-item__arrow--open': isOpen }"
|
|
14
14
|
/>
|
|
15
15
|
</view>
|
|
16
|
+
<dd-portal>
|
|
16
17
|
<view
|
|
17
18
|
v-if="ctx"
|
|
18
19
|
class="dd-dropdown-item__panel"
|
|
@@ -41,11 +42,13 @@
|
|
|
41
42
|
</view>
|
|
42
43
|
</scroll-view>
|
|
43
44
|
</view>
|
|
45
|
+
</dd-portal>
|
|
44
46
|
</view>
|
|
45
47
|
</template>
|
|
46
48
|
|
|
47
49
|
<script setup lang="ts">
|
|
48
50
|
import { computed, inject, ref } from 'vue'
|
|
51
|
+
import DdPortal from '../dd-portal/dd-portal.vue'
|
|
49
52
|
import DdIcon from '../dd-icon/dd-icon.vue'
|
|
50
53
|
|
|
51
54
|
interface DropdownOption {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<view class="dd-dropdown__bar">
|
|
4
4
|
<slot></slot>
|
|
5
5
|
</view>
|
|
6
|
+
<dd-portal>
|
|
6
7
|
<view
|
|
7
8
|
v-if="overlay"
|
|
8
9
|
class="dd-dropdown__overlay"
|
|
@@ -10,6 +11,7 @@
|
|
|
10
11
|
:style="overlayStyle"
|
|
11
12
|
@click="onOverlayClick"
|
|
12
13
|
></view>
|
|
14
|
+
</dd-portal>
|
|
13
15
|
</view>
|
|
14
16
|
</template>
|
|
15
17
|
|
|
@@ -21,6 +23,7 @@ let activeMenuClose: (() => void) | null = null
|
|
|
21
23
|
|
|
22
24
|
<script setup lang="ts">
|
|
23
25
|
import { getCurrentInstance, onMounted, onUnmounted, provide, reactive, ref } from 'vue'
|
|
26
|
+
import DdPortal from '../dd-portal/dd-portal.vue'
|
|
24
27
|
|
|
25
28
|
interface Props {
|
|
26
29
|
activeColor?: string
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
<text
|
|
30
30
|
v-if="showTips"
|
|
31
31
|
class="dd-keyboard__tooltip__item dd-keyboard__tooltip__tips"
|
|
32
|
-
>{{tips ? tips : mode == 'number' ? '数字键盘' :
|
|
32
|
+
>{{tips ? tips : mode == 'number' ? '数字键盘' : '身份证键盘'}}</text>
|
|
33
33
|
</view>
|
|
34
34
|
<view
|
|
35
35
|
hover-class="dd-keyboard-hover"
|
|
@@ -42,23 +42,14 @@
|
|
|
42
42
|
>{{showConfirm && confirmText}}</text>
|
|
43
43
|
</view>
|
|
44
44
|
</view>
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
<!-- 车牌号输入已独立为 dd-car-keyboard(车牌格子+按位锁键键盘一体),此处仅保留 number/card 数字键盘 -->
|
|
46
|
+
<dd-number-keyboard
|
|
47
47
|
:random="random"
|
|
48
48
|
@backspace="backspace"
|
|
49
49
|
@change="change"
|
|
50
50
|
:mode="mode"
|
|
51
51
|
:dotDisabled="dotDisabled"
|
|
52
52
|
></dd-number-keyboard>
|
|
53
|
-
</template>
|
|
54
|
-
<template v-else>
|
|
55
|
-
<dd-car-keyboard
|
|
56
|
-
:random="random"
|
|
57
|
-
:autoChange="autoChange"
|
|
58
|
-
@backspace="backspace"
|
|
59
|
-
@change="change"
|
|
60
|
-
></dd-car-keyboard>
|
|
61
|
-
</template>
|
|
62
53
|
</view>
|
|
63
54
|
</dd-popup>
|
|
64
55
|
</template>
|
|
@@ -70,8 +61,8 @@
|
|
|
70
61
|
|
|
71
62
|
/**
|
|
72
63
|
* keyboard 键盘
|
|
73
|
-
* @description
|
|
74
|
-
* @property {String} mode
|
|
64
|
+
* @description 自定义的键盘面板,内含了数字键盘,身份证号键盘2种模式,都有可以打乱按键顺序的选项。车牌号输入请使用 dd-car-keyboard。
|
|
65
|
+
* @property {String} mode 键盘类型:number-数字键盘,card-身份证键盘 (默认 'number' )
|
|
75
66
|
* @property {Boolean} dotDisabled 是否显示"."按键,只在mode=number时有效 (默认 false )
|
|
76
67
|
* @property {Boolean} tooltip 是否显示键盘顶部工具条 (默认 true )
|
|
77
68
|
* @property {Boolean} showTips 是否显示工具条中间的提示 (默认 true )
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
2
|
+
<!-- 仅全屏分支传送;inline 分支必须留在原位(传送会破坏布局流) -->
|
|
3
|
+
<dd-portal v-if="fullscreen">
|
|
4
|
+
<view class="dd-loading dd-loading--fullscreen" :style="{ zIndex: 9999 }">
|
|
3
5
|
<view class="dd-loading__mask"></view>
|
|
4
6
|
<view class="dd-loading__box">
|
|
5
7
|
<view class="dd-loading__core" :class="[`dd-loading__core--${type}`, `dd-loading__core--${size}`]" :style="coreStyle">
|
|
@@ -17,6 +19,7 @@
|
|
|
17
19
|
<text v-if="text" class="dd-loading__text">{{ text }}</text>
|
|
18
20
|
</view>
|
|
19
21
|
</view>
|
|
22
|
+
</dd-portal>
|
|
20
23
|
<view v-else class="dd-loading" :class="[`dd-loading--inline`, `dd-loading--${type}`, `dd-loading--${size}`]">
|
|
21
24
|
<view class="dd-loading__core" :class="[`dd-loading__core--${type}`, `dd-loading__core--${size}`]" :style="coreStyle">
|
|
22
25
|
<template v-if="type === 'spinner'">
|
|
@@ -36,6 +39,7 @@
|
|
|
36
39
|
|
|
37
40
|
<script setup lang="ts">
|
|
38
41
|
import { computed } from 'vue'
|
|
42
|
+
import DdPortal from '../dd-portal/dd-portal.vue'
|
|
39
43
|
|
|
40
44
|
interface Props {
|
|
41
45
|
type?: 'spinner' | 'dots' | 'pulse'
|
|
@@ -4,6 +4,7 @@ let activeModalClose: (() => void) | null = null
|
|
|
4
4
|
</script>
|
|
5
5
|
|
|
6
6
|
<template>
|
|
7
|
+
<dd-portal>
|
|
7
8
|
<view class="dd-modal">
|
|
8
9
|
<view
|
|
9
10
|
v-if="visible"
|
|
@@ -56,10 +57,12 @@ let activeModalClose: (() => void) | null = null
|
|
|
56
57
|
<view class="dd-modal__safe-bottom"></view>
|
|
57
58
|
</view>
|
|
58
59
|
</view>
|
|
60
|
+
</dd-portal>
|
|
59
61
|
</template>
|
|
60
62
|
|
|
61
63
|
<script setup lang="ts">
|
|
62
64
|
import { computed, ref, watch, onUnmounted, nextTick } from 'vue'
|
|
65
|
+
import DdPortal from '../dd-portal/dd-portal.vue'
|
|
63
66
|
import DdIcon from '../dd-icon/dd-icon.vue'
|
|
64
67
|
|
|
65
68
|
interface Props {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<dd-portal>
|
|
2
3
|
<view
|
|
3
4
|
class="dd-overlay"
|
|
4
5
|
:class="{ 'dd-overlay--show': modelValue }"
|
|
@@ -9,10 +10,12 @@
|
|
|
9
10
|
>
|
|
10
11
|
<slot></slot>
|
|
11
12
|
</view>
|
|
13
|
+
</dd-portal>
|
|
12
14
|
</template>
|
|
13
15
|
|
|
14
16
|
<script setup lang="ts">
|
|
15
17
|
import { watch } from 'vue'
|
|
18
|
+
import DdPortal from '../dd-portal/dd-portal.vue'
|
|
16
19
|
|
|
17
20
|
interface Props {
|
|
18
21
|
modelValue?: boolean
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<dd-portal>
|
|
2
3
|
<view class="dd-picker" :class="{ 'dd-picker--open': show }">
|
|
3
4
|
<view class="dd-picker__mask" @click="onMaskClick"></view>
|
|
4
5
|
<view class="dd-picker__sheet">
|
|
@@ -26,10 +27,12 @@
|
|
|
26
27
|
</view>
|
|
27
28
|
</view>
|
|
28
29
|
</view>
|
|
30
|
+
</dd-portal>
|
|
29
31
|
</template>
|
|
30
32
|
|
|
31
33
|
<script setup lang="ts">
|
|
32
34
|
import { computed, ref, watch } from 'vue'
|
|
35
|
+
import DdPortal from '../dd-portal/dd-portal.vue'
|
|
33
36
|
|
|
34
37
|
interface PickerItem {
|
|
35
38
|
text: string
|
|
@@ -42,6 +45,8 @@ interface Props {
|
|
|
42
45
|
title?: string
|
|
43
46
|
loading?: boolean
|
|
44
47
|
readonly?: boolean
|
|
48
|
+
// 每次打开时各列定位到的索引(缺省/超界则回落到当前值或 0),用于回显已有选中项(如房型筛选当前值)
|
|
49
|
+
defaultIndexes?: number[]
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
const props = withDefaults(defineProps<Props>(), {
|
|
@@ -50,6 +55,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
50
55
|
title: '',
|
|
51
56
|
loading: false,
|
|
52
57
|
readonly: false,
|
|
58
|
+
defaultIndexes: () => [],
|
|
53
59
|
})
|
|
54
60
|
|
|
55
61
|
const emit = defineEmits<{
|
|
@@ -77,6 +83,21 @@ watch(
|
|
|
77
83
|
{ immediate: true }
|
|
78
84
|
)
|
|
79
85
|
|
|
86
|
+
// 打开时按 defaultIndexes 回显各列索引;非法值(超界/非数字)回落当前值或 0
|
|
87
|
+
watch(
|
|
88
|
+
() => props.show,
|
|
89
|
+
(v) => {
|
|
90
|
+
if (!v) return
|
|
91
|
+
const cols = normalizedColumns.value
|
|
92
|
+
const d = props.defaultIndexes
|
|
93
|
+
indexes.value = cols.map((_, i) => {
|
|
94
|
+
const preset = d[i]
|
|
95
|
+
if (typeof preset !== 'number' || preset < 0) return indexes.value[i] ?? 0
|
|
96
|
+
return Math.min(preset, Math.max(0, (cols[i]?.length || 1) - 1))
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
|
|
80
101
|
function emitChange() {
|
|
81
102
|
const items = normalizedColumns.value.map((col, i) => col[indexes.value[i] ?? 0] || { text: '', value: null })
|
|
82
103
|
return {
|
|
@@ -116,6 +137,11 @@ function onConfirm() {
|
|
|
116
137
|
background-image: linear-gradient(180deg, var(--dd-surface-container, #{$dd-surface-container}), transparent 60%),
|
|
117
138
|
linear-gradient(0deg, var(--dd-surface-container, #{$dd-surface-container}), transparent 60%);
|
|
118
139
|
}
|
|
140
|
+
// ponytail: H5 picker-view 吸附 itemSize 取 indicator 框高度(默认34px),必须与行高一致拖动松手才对齐。
|
|
141
|
+
// 需与下方 .dd-picker__item 的 88rpx 保持一致;改行高时必须同步改这里。小程序为原生组件此规则天然无效,安全。
|
|
142
|
+
:deep(.uni-picker-view-indicator) {
|
|
143
|
+
height: 88rpx;
|
|
144
|
+
}
|
|
119
145
|
.dd-picker {
|
|
120
146
|
&__mask {
|
|
121
147
|
position: fixed;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<!-- 内容经 portal 提升到页面根节点:popup 可安全嵌套进另一弹层/transform 祖先,不被其劫持 fixed 定位(详见 dd-portal 组件) -->
|
|
3
|
+
<dd-portal>
|
|
2
4
|
<view class="dd-popup" :style="{ '--dd-popup-duration': `${props.duration}s` }">
|
|
3
5
|
<view
|
|
4
6
|
v-if="visible && overlay"
|
|
@@ -24,11 +26,13 @@
|
|
|
24
26
|
<slot></slot>
|
|
25
27
|
</view>
|
|
26
28
|
</view>
|
|
29
|
+
</dd-portal>
|
|
27
30
|
</template>
|
|
28
31
|
|
|
29
32
|
<script setup lang="ts">
|
|
30
33
|
import { computed, ref, watch, onUnmounted, nextTick } from 'vue'
|
|
31
34
|
import DdIcon from '../dd-icon/dd-icon.vue'
|
|
35
|
+
import DdPortal from '../dd-portal/dd-portal.vue'
|
|
32
36
|
|
|
33
37
|
interface Props {
|
|
34
38
|
modelValue?: boolean
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- 弹层传送适配器:把插槽内容提升到页面根节点,规避 transform / filter / backdrop-filter 祖先
|
|
3
|
+
对 position:fixed 的包含块劫持(如弹层嵌在 dd-popup 面板内时,fixed 会被 popup 的
|
|
4
|
+
常驻 transform 捕获,导致弹窗相对面板而非视口定位、遮罩只盖住面板)。
|
|
5
|
+
库内消费方:dd-dialog / dd-popup / dd-modal / dd-alert / dd-action-sheet / dd-drawer /
|
|
6
|
+
dd-toast / dd-loading(全屏) / dd-overlay / dd-picker / dd-date-picker / dd-dropdown-menu / dd-dropdown-item -->
|
|
7
|
+
<!-- #ifdef H5 -->
|
|
8
|
+
<Teleport to="body">
|
|
9
|
+
<slot></slot>
|
|
10
|
+
</Teleport>
|
|
11
|
+
<!-- #endif -->
|
|
12
|
+
<!-- #ifdef MP-WEIXIN || MP-ALIPAY -->
|
|
13
|
+
<root-portal>
|
|
14
|
+
<slot></slot>
|
|
15
|
+
</root-portal>
|
|
16
|
+
<!-- #endif -->
|
|
17
|
+
<!-- #ifndef H5 || MP-WEIXIN || MP-ALIPAY -->
|
|
18
|
+
<!-- ponytail: 其余平台(App/抖音等)无等价传送能力,原位渲染保持旧行为;
|
|
19
|
+
这些平台上弹层勿嵌在 transform 祖先(如 dd-popup 面板)内 -->
|
|
20
|
+
<slot></slot>
|
|
21
|
+
<!-- #endif -->
|
|
22
|
+
</template>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<dd-portal>
|
|
2
3
|
<view class="dd-toast" :class="[`dd-toast--${toastState.position}`, { 'dd-toast--show': toastState.visible }]">
|
|
3
4
|
<view class="dd-toast__capsule">
|
|
4
5
|
<view v-if="showIcon" class="dd-toast__icon">
|
|
@@ -8,6 +9,7 @@
|
|
|
8
9
|
<text v-if="toastState.message" class="dd-toast__msg">{{ toastState.message }}</text>
|
|
9
10
|
</view>
|
|
10
11
|
</view>
|
|
12
|
+
</dd-portal>
|
|
11
13
|
</template>
|
|
12
14
|
|
|
13
15
|
<script lang="ts">
|
|
@@ -77,6 +79,7 @@ export function showError(message: string) {
|
|
|
77
79
|
|
|
78
80
|
<script setup lang="ts">
|
|
79
81
|
import { computed } from 'vue'
|
|
82
|
+
import DdPortal from '../dd-portal/dd-portal.vue'
|
|
80
83
|
import DdIcon from '../dd-icon/dd-icon.vue'
|
|
81
84
|
|
|
82
85
|
// text 类型强制隐藏图标
|
package/index.ts
CHANGED
|
@@ -75,7 +75,8 @@ import DdCoupon from './components/dd-coupon/dd-coupon.vue'
|
|
|
75
75
|
import DdParse from './components/dd-parse/dd-parse.vue'
|
|
76
76
|
import DdMarkdown from './components/dd-markdown/dd-markdown.vue'
|
|
77
77
|
|
|
78
|
-
// === Overlay (
|
|
78
|
+
// === Overlay (11) ===
|
|
79
|
+
import DdPortal from './components/dd-portal/dd-portal.vue'
|
|
79
80
|
import DdModal from './components/dd-modal/dd-modal.vue'
|
|
80
81
|
import DdActionSheet from './components/dd-action-sheet/dd-action-sheet.vue'
|
|
81
82
|
import DdToast from './components/dd-toast/dd-toast.vue'
|
|
@@ -119,7 +120,7 @@ const components = {
|
|
|
119
120
|
DdImage, DdProgress, DdSkeleton, DdEmptyState, DdStep, DdSteps,
|
|
120
121
|
DdText, DdLink, DdCopy, DdAlbum, DdCoupon, DdParse, DdMarkdown,
|
|
121
122
|
DdModal, DdActionSheet, DdToast, DdAlert, DdLoading,
|
|
122
|
-
DdDialog, DdOverlay, DdPopup, DdPopover, DdPopoverItem,
|
|
123
|
+
DdPortal, DdDialog, DdOverlay, DdPopup, DdPopover, DdPopoverItem,
|
|
123
124
|
DdSwipeAction, DdSwipe, DdSwipeItem, DdPullRefresh, DdLoadmore,
|
|
124
125
|
DdCapsuleButton, DdMiniProgramNavbar,
|
|
125
126
|
DdCanvas, DdBarcode, DdCropper, DdSignature, DdPoster,
|
|
@@ -149,7 +150,7 @@ export {
|
|
|
149
150
|
DdImage, DdProgress, DdSkeleton, DdEmptyState, DdStep, DdSteps,
|
|
150
151
|
DdText, DdLink, DdCopy, DdAlbum, DdCoupon, DdParse, DdMarkdown,
|
|
151
152
|
DdModal, DdActionSheet, DdToast, DdAlert, DdLoading,
|
|
152
|
-
DdDialog, DdOverlay, DdPopup, DdPopover, DdPopoverItem,
|
|
153
|
+
DdPortal, DdDialog, DdOverlay, DdPopup, DdPopover, DdPopoverItem,
|
|
153
154
|
DdSwipeAction, DdSwipe, DdSwipeItem, DdPullRefresh, DdLoadmore,
|
|
154
155
|
DdCapsuleButton, DdMiniProgramNavbar,
|
|
155
156
|
DdCanvas, DdBarcode, DdCropper, DdSignature, DdPoster,
|
package/libs/config/props.js
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// libs/config/zIndex.js 的类型声明(该库多为 JS 文件,allowJs 未开启,TS 侧导入需要此声明)
|
|
2
|
+
declare const zIndex: {
|
|
3
|
+
toast: number
|
|
4
|
+
noNetwork: number
|
|
5
|
+
popup: number
|
|
6
|
+
mask: number
|
|
7
|
+
dialogMask: number
|
|
8
|
+
dialog: number
|
|
9
|
+
navbar: number
|
|
10
|
+
topTips: number
|
|
11
|
+
sticky: number
|
|
12
|
+
indexListSticky: number
|
|
13
|
+
}
|
|
14
|
+
export default zIndex
|
package/libs/config/zIndex.js
CHANGED
|
@@ -13,6 +13,9 @@ export default {
|
|
|
13
13
|
// popup包含popup,actionsheet,keyboard,picker的值
|
|
14
14
|
popup: 10075,
|
|
15
15
|
mask: 10070,
|
|
16
|
+
// dialog 独立于 popup 体系:弹窗需压在 popup 面板(popup+1)之上,又不遮住 noNetwork/toast
|
|
17
|
+
dialogMask: 10077,
|
|
18
|
+
dialog: 10078,
|
|
16
19
|
navbar: 980,
|
|
17
20
|
topTips: 975,
|
|
18
21
|
sticky: 970,
|
package/package.json
CHANGED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { defineMixin } from '../../libs/vue'
|
|
2
|
-
import CarKeyboardDefaultProps from './carKeyboard'
|
|
3
|
-
import { registerComponentProps } from '../../libs/config/props.js'
|
|
4
|
-
|
|
5
|
-
const defProps = registerComponentProps(CarKeyboardDefaultProps)
|
|
6
|
-
export const props = defineMixin({
|
|
7
|
-
props: {
|
|
8
|
-
// 是否打乱键盘按键的顺序
|
|
9
|
-
random: {
|
|
10
|
-
type: Boolean,
|
|
11
|
-
default: false
|
|
12
|
-
},
|
|
13
|
-
// 输入一个中文后,是否自动切换到英文
|
|
14
|
-
autoChange: {
|
|
15
|
-
type: Boolean,
|
|
16
|
-
default: false
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
})
|