uview-plus 3.5.25 → 3.5.32
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/changelog.md +24 -0
- package/components/u-cascader/u-cascader.vue +309 -0
- package/components/u-cate-tab/u-cate-tab.vue +34 -23
- package/components/u-choose/u-choose.vue +109 -0
- package/components/u-popover/props.js +59 -0
- package/components/u-popover/u-popover.vue +95 -0
- package/components/u-tooltip/u-tooltip.vue +15 -15
- package/libs/i18n/index.js +5 -1
- package/libs/i18n/locales/th.json +80 -0
- package/package.json +1 -1
package/changelog.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
## 3.5.32(2025-09-01)
|
|
2
|
+
feat: cate-tab支持非联动跟随的单一切换模式
|
|
3
|
+
|
|
4
|
+
feat: choose组件示例使用cate-tab的单一切换模式
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## 3.5.31(2025-09-01)
|
|
8
|
+
feat: 新增choose通用选项选择器组件
|
|
9
|
+
|
|
10
|
+
## 3.5.30(2025-08-31)
|
|
11
|
+
fix: 修复缺失cascader级联选择器
|
|
12
|
+
|
|
13
|
+
## 3.5.29(2025-08-30)
|
|
14
|
+
feat: 新增cascader级联选择器
|
|
15
|
+
|
|
16
|
+
## 3.5.28(2025-08-29)
|
|
17
|
+
feat: 多语言增加泰语
|
|
18
|
+
|
|
19
|
+
## 3.5.27(2025-08-29)
|
|
20
|
+
feat: 新增基于tooltip的popover组件
|
|
21
|
+
|
|
22
|
+
## 3.5.26(2025-08-29)
|
|
23
|
+
improvment: 增强多语言兼容性
|
|
24
|
+
|
|
1
25
|
## 3.5.25(2025-08-28)
|
|
2
26
|
fix: 修复左侧与右侧弹出时页面打开闪现问题
|
|
3
27
|
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<up-popup :show="popupShow" mode="bottom" :popup="false"
|
|
3
|
+
:mask="true" :closeable="true" :safe-area-inset-bottom="true"
|
|
4
|
+
close-icon-color="#ffffff" :z-index="uZIndex"
|
|
5
|
+
:maskCloseAble="maskCloseAble" @close="close">
|
|
6
|
+
<up-tabs v-if="popupShow" :list="genTabsList"
|
|
7
|
+
:scrollable="true" v-model:current="tabsIndex" @change="tabsChange" ref="tabs"></up-tabs>
|
|
8
|
+
<view class="area-box">
|
|
9
|
+
<view class="u-flex" :class="{ 'change':isChange }">
|
|
10
|
+
<view class="area-item" v-for="(levelData, levelIndex) in levelList" :key="levelIndex">
|
|
11
|
+
<view class="u-padding-10 u-bg-gray" style="height: 100%;">
|
|
12
|
+
<scroll-view :scroll-y="true" style="height: 100%">
|
|
13
|
+
<up-cell-group v-if="levelIndex === 0 || selectedValueIndexs[levelIndex - 1] !== undefined">
|
|
14
|
+
<up-cell v-for="(item,index) in levelData"
|
|
15
|
+
:title="item[labelKey]" :arrow="false"
|
|
16
|
+
:index="index" :key="index"
|
|
17
|
+
@click="levelChange(levelIndex, index)">
|
|
18
|
+
<template v-slot:right-icon>
|
|
19
|
+
<up-icon v-if="selectedValueIndexs[levelIndex] === index"
|
|
20
|
+
size="17" name="checkbox-mark"></up-icon>
|
|
21
|
+
</template>
|
|
22
|
+
</up-cell>
|
|
23
|
+
</up-cell-group>
|
|
24
|
+
</scroll-view>
|
|
25
|
+
</view>
|
|
26
|
+
</view>
|
|
27
|
+
</view>
|
|
28
|
+
</view>
|
|
29
|
+
<!-- 添加按钮区域 -->
|
|
30
|
+
<view class="u-cascader-action up-flex up-flex-between">
|
|
31
|
+
<view class="u-padding-20 up-flex-fill">
|
|
32
|
+
<up-button @click="handleCancel" type="default">取消</up-button>
|
|
33
|
+
</view>
|
|
34
|
+
<view class="u-padding-20 up-flex-fill">
|
|
35
|
+
<up-button @click="handleConfirm" type="primary">确认</up-button>
|
|
36
|
+
</view>
|
|
37
|
+
</view>
|
|
38
|
+
</up-popup>
|
|
39
|
+
</template>
|
|
40
|
+
|
|
41
|
+
<script>
|
|
42
|
+
/**
|
|
43
|
+
* u-cascader 通用无限级联选择器
|
|
44
|
+
* @property {String Number} z-index 弹出时的z-index值(默认1075)
|
|
45
|
+
* @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭Picker(默认true)
|
|
46
|
+
* @property {Array} data 级联数据
|
|
47
|
+
* @property {Array} default-value 默认选中的值
|
|
48
|
+
* @property {String} valueKey 指定选项的值为选项对象中的哪个属性值
|
|
49
|
+
* @property {String} labelKey 指定选项标签为选项对象中的哪个属性值
|
|
50
|
+
* @property {String} childrenKey 指定选项的子选项为选项对象中的哪个属性值
|
|
51
|
+
* @property {Boolean} autoClose 是否在选择最后一级时自动关闭并触发confirm(默认false)
|
|
52
|
+
*/
|
|
53
|
+
export default {
|
|
54
|
+
name: 'up-cascader',
|
|
55
|
+
props: {
|
|
56
|
+
// 通过双向绑定控制组件的弹出与收起
|
|
57
|
+
show: {
|
|
58
|
+
type: Boolean,
|
|
59
|
+
default: false
|
|
60
|
+
},
|
|
61
|
+
// 级联数据
|
|
62
|
+
data: {
|
|
63
|
+
type: Array,
|
|
64
|
+
default() {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
// 默认选中的值
|
|
69
|
+
modelValue: {
|
|
70
|
+
type: Array,
|
|
71
|
+
default() {
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
// 指定选项的值为选项对象中的哪个属性值
|
|
76
|
+
valueKey: {
|
|
77
|
+
type: String,
|
|
78
|
+
default: 'value'
|
|
79
|
+
},
|
|
80
|
+
// 指定选项标签为选项对象中的哪个属性值
|
|
81
|
+
labelKey: {
|
|
82
|
+
type: String,
|
|
83
|
+
default: 'label'
|
|
84
|
+
},
|
|
85
|
+
// 指定选项的子选项为选项对象中的哪个属性值
|
|
86
|
+
childrenKey: {
|
|
87
|
+
type: String,
|
|
88
|
+
default: 'children'
|
|
89
|
+
},
|
|
90
|
+
// 是否允许通过点击遮罩关闭Picker
|
|
91
|
+
maskCloseAble: {
|
|
92
|
+
type: Boolean,
|
|
93
|
+
default: true
|
|
94
|
+
},
|
|
95
|
+
// 弹出的z-index值
|
|
96
|
+
zIndex: {
|
|
97
|
+
type: [String, Number],
|
|
98
|
+
default: 0
|
|
99
|
+
},
|
|
100
|
+
// 是否在选择最后一级时自动关闭并触发confirm
|
|
101
|
+
autoClose: {
|
|
102
|
+
type: Boolean,
|
|
103
|
+
default: false
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
data() {
|
|
107
|
+
return {
|
|
108
|
+
// 存储每一级的数据
|
|
109
|
+
levelList: [],
|
|
110
|
+
// 存储每一级选中的索引
|
|
111
|
+
selectedValueIndexs: [],
|
|
112
|
+
tabsIndex: 0,
|
|
113
|
+
popupShow: false,
|
|
114
|
+
// 新增confirmValues用于存储确认的值
|
|
115
|
+
confirmValues: []
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
watch: {
|
|
119
|
+
data: {
|
|
120
|
+
handler() {
|
|
121
|
+
this.initLevelList();
|
|
122
|
+
},
|
|
123
|
+
immediate: true
|
|
124
|
+
},
|
|
125
|
+
show() {
|
|
126
|
+
this.popupShow = this.show;
|
|
127
|
+
},
|
|
128
|
+
modelValue: {
|
|
129
|
+
handler() {
|
|
130
|
+
this.init();
|
|
131
|
+
},
|
|
132
|
+
immediate: true
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
computed: {
|
|
136
|
+
isChange() {
|
|
137
|
+
return this.tabsIndex > 1;
|
|
138
|
+
},
|
|
139
|
+
genTabsList() {
|
|
140
|
+
let tabsList = [{
|
|
141
|
+
name: "请选择"
|
|
142
|
+
}];
|
|
143
|
+
|
|
144
|
+
// 根据选中的值动态生成tabs
|
|
145
|
+
for (let i = 0; i < this.selectedValueIndexs.length; i++) {
|
|
146
|
+
if (this.selectedValueIndexs[i] !== undefined && this.levelList[i]) {
|
|
147
|
+
const selectedItem = this.levelList[i][this.selectedValueIndexs[i]];
|
|
148
|
+
if (selectedItem) {
|
|
149
|
+
tabsList[i] = {
|
|
150
|
+
name: selectedItem[this.labelKey]
|
|
151
|
+
};
|
|
152
|
+
// 如果还有下一级,则添加"请选择"
|
|
153
|
+
if (i === this.selectedValueIndexs.length - 1 &&
|
|
154
|
+
selectedItem[this.childrenKey] &&
|
|
155
|
+
selectedItem[this.childrenKey].length > 0) {
|
|
156
|
+
tabsList.push({
|
|
157
|
+
name: "请选择"
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return tabsList;
|
|
165
|
+
},
|
|
166
|
+
uZIndex() {
|
|
167
|
+
// 如果用户有传递z-index值,优先使用
|
|
168
|
+
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
// 新增confirm事件
|
|
172
|
+
emits: ['update:modelValue', 'change', 'confirm'],
|
|
173
|
+
methods: {
|
|
174
|
+
init() {
|
|
175
|
+
// 初始化选中值
|
|
176
|
+
if (this.modelValue && this.modelValue.length > 0) {
|
|
177
|
+
this.setDefaultValue();
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
initLevelList() {
|
|
181
|
+
// 初始化第一级数据
|
|
182
|
+
if (this.data && this.data.length > 0) {
|
|
183
|
+
this.levelList = [this.data];
|
|
184
|
+
this.selectedValueIndexs = [];
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
setDefaultValue() {
|
|
188
|
+
// 根据默认值设置选中项
|
|
189
|
+
// 根据modelValue获取indexs给selectedValueIndexs
|
|
190
|
+
this.selectedValueIndexs = [];
|
|
191
|
+
let currentLevelData = this.data;
|
|
192
|
+
|
|
193
|
+
for (let i = 0; i < this.modelValue.length; i++) {
|
|
194
|
+
const value = this.modelValue[i];
|
|
195
|
+
const index = currentLevelData.findIndex(item => item[this.valueKey] === value);
|
|
196
|
+
|
|
197
|
+
if (index !== -1) {
|
|
198
|
+
this.selectedValueIndexs.push(index);
|
|
199
|
+
// 更新下一级的数据
|
|
200
|
+
if (currentLevelData[index][this.childrenKey]) {
|
|
201
|
+
currentLevelData = currentLevelData[index][this.childrenKey];
|
|
202
|
+
} else {
|
|
203
|
+
// 如果没有子级数据,则停止处理
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
// 如果找不到匹配项,则停止处理
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
close() {
|
|
213
|
+
this.$emit('update:show', false);
|
|
214
|
+
},
|
|
215
|
+
tabsChange(item) {
|
|
216
|
+
},
|
|
217
|
+
levelChange(levelIndex, index) {
|
|
218
|
+
// 设置当前级的选中值
|
|
219
|
+
this.$set(this.selectedValueIndexs, levelIndex, index);
|
|
220
|
+
|
|
221
|
+
// 清除后续级别的选中值
|
|
222
|
+
for (let i = levelIndex + 1; i < this.selectedValueIndexs.length; i++) {
|
|
223
|
+
this.$set(this.selectedValueIndexs, i, undefined);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// 获取当前选中项
|
|
227
|
+
const currentItem = this.levelList[levelIndex][index];
|
|
228
|
+
|
|
229
|
+
// 如果有子级数据,则初始化下一级
|
|
230
|
+
if (currentItem && currentItem[this.childrenKey] && currentItem[this.childrenKey].length > 0) {
|
|
231
|
+
// 确保levelList数组足够长
|
|
232
|
+
if (this.levelList.length <= levelIndex + 1) {
|
|
233
|
+
this.levelList.push(currentItem[this.childrenKey]);
|
|
234
|
+
} else {
|
|
235
|
+
this.$set(this.levelList, levelIndex + 1, currentItem[this.childrenKey]);
|
|
236
|
+
}
|
|
237
|
+
// 切换到下一级tab
|
|
238
|
+
this.tabsIndex = levelIndex + 1;
|
|
239
|
+
} else {
|
|
240
|
+
// 没有子级数据,说明是最后一级
|
|
241
|
+
if (this.autoClose) {
|
|
242
|
+
// 如果启用自动关闭,则触发change事件并关闭
|
|
243
|
+
this.emitChange();
|
|
244
|
+
} else {
|
|
245
|
+
// 否则只触发change事件,不关闭
|
|
246
|
+
this.emitChange(false);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
// 修改emitChange方法,增加closePopup参数
|
|
251
|
+
emitChange(closePopup = true) {
|
|
252
|
+
// 构造选中结果
|
|
253
|
+
const result = [];
|
|
254
|
+
for (let i = 0; i < this.selectedValueIndexs.length; i++) {
|
|
255
|
+
if (this.selectedValueIndexs[i] !== undefined && this.levelList[i]) {
|
|
256
|
+
result.push(this.levelList[i][this.selectedValueIndexs[i]][this.valueKey]);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// 更新confirmValues
|
|
261
|
+
this.confirmValues = [...result];
|
|
262
|
+
|
|
263
|
+
// 触发change事件,返回value数组
|
|
264
|
+
this.$emit('change', this.confirmValues);
|
|
265
|
+
|
|
266
|
+
// 根据参数决定是否关闭弹窗
|
|
267
|
+
if (closePopup) {
|
|
268
|
+
this.close();
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
handleCancel() {
|
|
272
|
+
this.close();
|
|
273
|
+
},
|
|
274
|
+
handleConfirm() {
|
|
275
|
+
// 确认时触发confirm事件
|
|
276
|
+
this.$emit('update:modelValue', this.confirmValues);
|
|
277
|
+
this.$emit('confirm', this.confirmValues);
|
|
278
|
+
this.close();
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
</script>
|
|
283
|
+
<style lang="scss">
|
|
284
|
+
.area-box {
|
|
285
|
+
width: 100%;
|
|
286
|
+
overflow: hidden;
|
|
287
|
+
height: 800rpx;
|
|
288
|
+
|
|
289
|
+
>view {
|
|
290
|
+
width: 150%;
|
|
291
|
+
transition: transform 0.3s ease-in-out 0s;
|
|
292
|
+
transform: translateX(0);
|
|
293
|
+
|
|
294
|
+
&.change {
|
|
295
|
+
transform: translateX(-33.3333333%);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.area-item {
|
|
300
|
+
width: 33.3333333%;
|
|
301
|
+
height: 800rpx;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// 添加按钮区域样式
|
|
306
|
+
.u-cascader-action {
|
|
307
|
+
border-top: 1px solid #eee;
|
|
308
|
+
}
|
|
309
|
+
</style>
|
|
@@ -19,26 +19,28 @@
|
|
|
19
19
|
</slot>
|
|
20
20
|
</view>
|
|
21
21
|
<view class="u-cate-tab__page-view">
|
|
22
|
-
<
|
|
23
|
-
v-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
22
|
+
<template :key="index" v-for="(item , index) in tabList">
|
|
23
|
+
<view v-if="mode == 'follow' || ( mode == 'tab' && index == innerCurrent)"
|
|
24
|
+
class="u-cate-tab__page-item" :id="'item' + index">
|
|
25
|
+
<slot name="itemList" :item="item">
|
|
26
|
+
</slot>
|
|
27
|
+
<template v-if="!$slots['itemList']">
|
|
28
|
+
<view class="item-title">
|
|
29
|
+
<text>{{item[tabKeyName]}}</text>
|
|
30
|
+
</view>
|
|
31
|
+
<view class="item-container">
|
|
32
|
+
<template v-for="(item1, index1) in item.children" :key="index1">
|
|
33
|
+
<slot name="pageItem" :pageItem="item1">
|
|
34
|
+
<view class="thumb-box" >
|
|
35
|
+
<image class="item-menu-image" :src="item1.icon" mode=""></image>
|
|
36
|
+
<view class="item-menu-name">{{item1[itemKeyName]}}</view>
|
|
37
|
+
</view>
|
|
38
|
+
</slot>
|
|
39
|
+
</template>
|
|
40
|
+
</view>
|
|
41
|
+
</template>
|
|
42
|
+
</view>
|
|
43
|
+
</template>
|
|
42
44
|
</view>
|
|
43
45
|
</scroll-view>
|
|
44
46
|
</view>
|
|
@@ -49,6 +51,10 @@
|
|
|
49
51
|
export default {
|
|
50
52
|
name: 'up-cate-tab',
|
|
51
53
|
props: {
|
|
54
|
+
mode: {
|
|
55
|
+
type: String,
|
|
56
|
+
default: 'follow' // follo跟随联动, tab单一显示。
|
|
57
|
+
},
|
|
52
58
|
height: {
|
|
53
59
|
type: String,
|
|
54
60
|
default: '100%'
|
|
@@ -119,10 +125,13 @@
|
|
|
119
125
|
addUnit,
|
|
120
126
|
// 点击左边的栏目切换
|
|
121
127
|
async swichMenu(index) {
|
|
122
|
-
if(this.
|
|
123
|
-
|
|
128
|
+
if (this.mode == 'follow') {
|
|
129
|
+
if(this.arr.length == 0) {
|
|
130
|
+
await this.getMenuItemTop();
|
|
131
|
+
}
|
|
132
|
+
this.scrollIntoView = 'item' + index;
|
|
124
133
|
}
|
|
125
|
-
|
|
134
|
+
|
|
126
135
|
if (index == this.innerCurrent) return;
|
|
127
136
|
this.$nextTick(function(){
|
|
128
137
|
this.innerCurrent = index;
|
|
@@ -216,6 +225,7 @@
|
|
|
216
225
|
},
|
|
217
226
|
// 右边菜单滚动
|
|
218
227
|
async rightScroll(e) {
|
|
228
|
+
if (this.mode !== 'follow') return;
|
|
219
229
|
this.oldScrollTop = e.detail.scrollTop;
|
|
220
230
|
// console.log(e.detail.scrollTop)
|
|
221
231
|
// console.log(JSON.stringify(this.arr))
|
|
@@ -261,6 +271,7 @@
|
|
|
261
271
|
.u-cate-tab__wrap {
|
|
262
272
|
flex: 1;
|
|
263
273
|
display: flex;
|
|
274
|
+
flex-direction: row;
|
|
264
275
|
overflow: hidden;
|
|
265
276
|
}
|
|
266
277
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<style scoped lang="scss">
|
|
2
|
+
.up-choose {
|
|
3
|
+
::v-deep .up-tag {
|
|
4
|
+
font-weight: 600;
|
|
5
|
+
}
|
|
6
|
+
&:last-child {
|
|
7
|
+
margin-right: 0;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.up-choose-wrap {
|
|
12
|
+
flex-wrap: wrap;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.up-choose-nowrap {
|
|
16
|
+
flex-wrap: nowrap;
|
|
17
|
+
white-space: nowrap;
|
|
18
|
+
}
|
|
19
|
+
</style>
|
|
20
|
+
|
|
21
|
+
<template>
|
|
22
|
+
<scroll-view
|
|
23
|
+
:scroll-x="wrap === false"
|
|
24
|
+
:class="['up-choose', wrap ? 'up-choose-wrap' : 'up-choose-nowrap']">
|
|
25
|
+
<template :key="item.id" v-for="(item,index) in options">
|
|
26
|
+
<view :style="{width: width, display: 'inline-block'}">
|
|
27
|
+
<slot :item="item" :index="index">
|
|
28
|
+
<up-tag :type="index == currentIndex ? 'primary' : 'info'"
|
|
29
|
+
size="large" :plain="index == currentIndex ? false : true"
|
|
30
|
+
:class="currentIndex === index ? 'active': ''" :height="itemHeight"
|
|
31
|
+
:style="{width: itemWidth, padding: itemPadding}"
|
|
32
|
+
@click="change(index)">
|
|
33
|
+
{{item[labelName]}}
|
|
34
|
+
</up-tag>
|
|
35
|
+
</slot>
|
|
36
|
+
</view>
|
|
37
|
+
</template>
|
|
38
|
+
</scroll-view>
|
|
39
|
+
</template>
|
|
40
|
+
|
|
41
|
+
<script>
|
|
42
|
+
export default {
|
|
43
|
+
name: 'up-choose',
|
|
44
|
+
props: {
|
|
45
|
+
options:{
|
|
46
|
+
type: Array,
|
|
47
|
+
default: ()=>{
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
modelValue: {
|
|
52
|
+
type: [Number,String,Array],
|
|
53
|
+
default: false
|
|
54
|
+
},
|
|
55
|
+
type: {
|
|
56
|
+
type: [String],
|
|
57
|
+
default: 'radio'
|
|
58
|
+
},
|
|
59
|
+
itemWidth: {
|
|
60
|
+
type: [String],
|
|
61
|
+
default: 'auto'
|
|
62
|
+
},
|
|
63
|
+
itemHeight: {
|
|
64
|
+
type: [String],
|
|
65
|
+
default: '50px'
|
|
66
|
+
},
|
|
67
|
+
itemPadding: {
|
|
68
|
+
type: [String],
|
|
69
|
+
default: '8px'
|
|
70
|
+
},
|
|
71
|
+
labelName: {
|
|
72
|
+
type: String,
|
|
73
|
+
default: 'title'
|
|
74
|
+
},
|
|
75
|
+
valueName: {
|
|
76
|
+
type: String,
|
|
77
|
+
default: 'value'
|
|
78
|
+
},
|
|
79
|
+
customClick: {
|
|
80
|
+
type: Boolean,
|
|
81
|
+
default: false
|
|
82
|
+
},
|
|
83
|
+
// 是否换行
|
|
84
|
+
wrap: {
|
|
85
|
+
type: Boolean,
|
|
86
|
+
default: true
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
data() {
|
|
90
|
+
return {
|
|
91
|
+
currentIndex: ''
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
created: function () {
|
|
95
|
+
this.currentIndex = this.modelValue;
|
|
96
|
+
},
|
|
97
|
+
emits: ['update:modelValue', 'custom-click'],
|
|
98
|
+
methods: {
|
|
99
|
+
change(index){
|
|
100
|
+
if (this.customClick) {
|
|
101
|
+
this.$emit('custom-click', index);
|
|
102
|
+
} else {
|
|
103
|
+
this.currentIndex = index;
|
|
104
|
+
this.$emit('update:modelValue', index);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
</script>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { defineMixin } from '../../libs/vue'
|
|
2
|
+
import defProps from '../../libs/config/props.js'
|
|
3
|
+
|
|
4
|
+
export const props = defineMixin({
|
|
5
|
+
props: {
|
|
6
|
+
// 显示的文字内容
|
|
7
|
+
text: {
|
|
8
|
+
type: [String, Number],
|
|
9
|
+
default: ''
|
|
10
|
+
},
|
|
11
|
+
// 文字颜色
|
|
12
|
+
color: {
|
|
13
|
+
type: String,
|
|
14
|
+
default: '#333'
|
|
15
|
+
},
|
|
16
|
+
// 背景颜色
|
|
17
|
+
bgColor: {
|
|
18
|
+
type: String,
|
|
19
|
+
default: '#f7f7f7'
|
|
20
|
+
},
|
|
21
|
+
// 弹出框背景颜色
|
|
22
|
+
popupBgColor: {
|
|
23
|
+
type: String,
|
|
24
|
+
default: '#f7f7f7'
|
|
25
|
+
},
|
|
26
|
+
// 弹出框位置
|
|
27
|
+
placement: {
|
|
28
|
+
type: String,
|
|
29
|
+
default: 'top'
|
|
30
|
+
},
|
|
31
|
+
// 触发方式
|
|
32
|
+
triggerMode: {
|
|
33
|
+
type: String,
|
|
34
|
+
default: 'click'
|
|
35
|
+
},
|
|
36
|
+
// 是否显示 (manual模式下使用)
|
|
37
|
+
show: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
default: false
|
|
40
|
+
},
|
|
41
|
+
// z-index值
|
|
42
|
+
zIndex: {
|
|
43
|
+
type: [Number, String],
|
|
44
|
+
default: 10070
|
|
45
|
+
},
|
|
46
|
+
// 强制定位
|
|
47
|
+
forcePosition: {
|
|
48
|
+
type: Object,
|
|
49
|
+
default() {
|
|
50
|
+
return {}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
// 弹出方向
|
|
54
|
+
direction: {
|
|
55
|
+
type: String,
|
|
56
|
+
default: 'top'
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
})
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="up-popover">
|
|
3
|
+
<up-tooltip
|
|
4
|
+
ref="tooltip"
|
|
5
|
+
:text="text"
|
|
6
|
+
:color="color"
|
|
7
|
+
:bg-color="bgColor"
|
|
8
|
+
:popup-bg-color="popupBgColor"
|
|
9
|
+
:placement="placement"
|
|
10
|
+
:trigger-mode="triggerMode"
|
|
11
|
+
:show="show"
|
|
12
|
+
:z-index="zIndex"
|
|
13
|
+
:force-position="forcePosition"
|
|
14
|
+
:direction="direction"
|
|
15
|
+
@open="onOpen"
|
|
16
|
+
@close="onClose"
|
|
17
|
+
@click="onClick"
|
|
18
|
+
>
|
|
19
|
+
<template #trigger>
|
|
20
|
+
<slot name="trigger"></slot>
|
|
21
|
+
</template>
|
|
22
|
+
<template #content>
|
|
23
|
+
<view class="up-popover__content">
|
|
24
|
+
<slot name="content">
|
|
25
|
+
<text>{{text}}</text>
|
|
26
|
+
</slot>
|
|
27
|
+
</view>
|
|
28
|
+
</template>
|
|
29
|
+
</up-tooltip>
|
|
30
|
+
</view>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script>
|
|
34
|
+
import { props } from './props';
|
|
35
|
+
import { mpMixin } from '../../libs/mixin/mpMixin';
|
|
36
|
+
import { mixin } from '../../libs/mixin/mixin';
|
|
37
|
+
/**
|
|
38
|
+
* popover 气泡弹出框
|
|
39
|
+
* @description 基于tooltip二次封装的popover组件,用于展示更丰富的内容
|
|
40
|
+
* @tutorial https://www.uviewui.com/components/popover.html
|
|
41
|
+
* @property {String | Number} text 显示的文字内容
|
|
42
|
+
* @property {String} color 文字颜色
|
|
43
|
+
* @property {String} bgColor 背景颜色
|
|
44
|
+
* @property {String} popupBgColor 弹出框背景颜色
|
|
45
|
+
* @property {String} placement 弹出框位置 (top, bottom, left, right)
|
|
46
|
+
* @property {String} triggerMode 触发方式 (hover, click, manual)
|
|
47
|
+
* @property {Boolean} show 是否显示 (manual模式下使用)
|
|
48
|
+
* @property {Number | String} zIndex z-index值
|
|
49
|
+
* @property {Object} forcePosition 强制定位 {top, left, right, bottom}
|
|
50
|
+
* @property {String} direction 弹出方向 (top, bottom, left, right)
|
|
51
|
+
* @event {Function} open 弹出框打开时触发
|
|
52
|
+
* @event {Function} close 弹出框关闭时触发
|
|
53
|
+
* @event {Function} click 点击触发器时触发
|
|
54
|
+
* @example <up-popover text="提示内容"><template #trigger><up-button>点击</up-button></template></up-popover>
|
|
55
|
+
*/
|
|
56
|
+
export default {
|
|
57
|
+
name: 'up-popover',
|
|
58
|
+
mixins: [mpMixin, mixin, props],
|
|
59
|
+
data() {
|
|
60
|
+
return {
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
methods: {
|
|
65
|
+
onOpen() {
|
|
66
|
+
this.$emit('open');
|
|
67
|
+
},
|
|
68
|
+
onClose() {
|
|
69
|
+
this.$emit('close');
|
|
70
|
+
},
|
|
71
|
+
onClick() {
|
|
72
|
+
this.$emit('click');
|
|
73
|
+
},
|
|
74
|
+
// 打开popover
|
|
75
|
+
open() {
|
|
76
|
+
this.$refs.tooltip && this.$refs.tooltip.open();
|
|
77
|
+
},
|
|
78
|
+
// 关闭popover
|
|
79
|
+
close() {
|
|
80
|
+
this.$refs.tooltip && this.$refs.tooltip.close();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<style lang="scss" scoped>
|
|
87
|
+
.up-popover {
|
|
88
|
+
|
|
89
|
+
&__content {
|
|
90
|
+
@include flex;
|
|
91
|
+
align-items: center;
|
|
92
|
+
padding: 12px 16px;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
</style>
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
left: 0
|
|
146
146
|
},
|
|
147
147
|
// 文本的位置信息
|
|
148
|
-
|
|
148
|
+
triggerInfo: {
|
|
149
149
|
width: 0,
|
|
150
150
|
left: 0
|
|
151
151
|
},
|
|
@@ -182,8 +182,8 @@
|
|
|
182
182
|
// 右侧显示逻辑
|
|
183
183
|
style.transform = ``
|
|
184
184
|
// 垂直居中对齐
|
|
185
|
-
style.top = '-' + addUnit((this.
|
|
186
|
-
style.right = addUnit(this.
|
|
185
|
+
style.top = '-' + addUnit((this.triggerInfo.height - this.tooltipInfo.height) / 2, 'px')
|
|
186
|
+
style.right = addUnit(this.triggerInfo.width + this.indicatorWidth, 'px')
|
|
187
187
|
this.indicatorStyle = {}
|
|
188
188
|
this.indicatorStyle.right = '-4px'
|
|
189
189
|
this.indicatorStyle.top = addUnit((this.tooltipInfo.height - this.indicatorWidth) / 2, 'px')
|
|
@@ -191,27 +191,27 @@
|
|
|
191
191
|
// 右侧显示逻辑
|
|
192
192
|
style.transform = ``
|
|
193
193
|
// 垂直居中对齐
|
|
194
|
-
style.top = '-' + addUnit((this.
|
|
195
|
-
style.left = addUnit(this.
|
|
194
|
+
style.top = '-' + addUnit((this.triggerInfo.height - this.tooltipInfo.height) / 2, 'px')
|
|
195
|
+
style.left = addUnit(this.triggerInfo.width + this.indicatorWidth, 'px')
|
|
196
196
|
this.indicatorStyle = {}
|
|
197
197
|
this.indicatorStyle.left = '-4px'
|
|
198
|
-
this.indicatorStyle.top = addUnit((this.
|
|
198
|
+
this.indicatorStyle.top = addUnit((this.triggerInfo.height - this.indicatorWidth) / 2, 'px')
|
|
199
199
|
} else if (this.direction === 'top' || this.direction === 'bottom') {
|
|
200
200
|
style.transform = `translateY(${this.direction === 'top' ? '-100%' : '100%'})`
|
|
201
|
-
if (this.tooltipInfo.width / 2 > this.
|
|
201
|
+
if (this.tooltipInfo.width / 2 > this.triggerInfo.left + this.triggerInfo.width / 2 - this.screenGap) {
|
|
202
202
|
this.indicatorStyle = {}
|
|
203
|
-
style.left = `-${addUnit(this.
|
|
204
|
-
this.indicatorStyle.left = addUnit(this.
|
|
203
|
+
style.left = `-${addUnit(this.triggerInfo.left - this.screenGap)}`
|
|
204
|
+
this.indicatorStyle.left = addUnit(this.triggerInfo.width / 2 - getPx(style.left) - this.indicatorWidth /
|
|
205
205
|
2, 'px')
|
|
206
|
-
} else if (this.tooltipInfo.width / 2 > sysInfo.windowWidth - this.
|
|
206
|
+
} else if (this.tooltipInfo.width / 2 > sysInfo.windowWidth - this.triggerInfo.right + this.triggerInfo.width / 2 -
|
|
207
207
|
this.screenGap) {
|
|
208
208
|
this.indicatorStyle = {}
|
|
209
|
-
style.right = `-${addUnit(sysInfo.windowWidth - this.
|
|
210
|
-
this.indicatorStyle.right = addUnit(this.
|
|
209
|
+
style.right = `-${addUnit(sysInfo.windowWidth - this.triggerInfo.right - this.screenGap)}`
|
|
210
|
+
this.indicatorStyle.right = addUnit(this.triggerInfo.width / 2 - getPx(style.right) - this
|
|
211
211
|
.indicatorWidth / 2)
|
|
212
212
|
} else {
|
|
213
|
-
const left = Math.abs(this.
|
|
214
|
-
style.left = this.
|
|
213
|
+
const left = Math.abs(this.triggerInfo.width / 2 - this.tooltipInfo.width / 2)
|
|
214
|
+
style.left = this.triggerInfo.width > this.tooltipInfo.width ? addUnit(left) : -addUnit(left)
|
|
215
215
|
this.indicatorStyle = {}
|
|
216
216
|
}
|
|
217
217
|
if (this.direction === 'top') {
|
|
@@ -296,7 +296,7 @@
|
|
|
296
296
|
this.tooltipInfo = await this.queryRect(this.tooltipId)
|
|
297
297
|
// 获取气泡尺寸之后,将其隐藏,为了让下次切换气泡显示与隐藏时,有淡入淡出的效果
|
|
298
298
|
this.showTooltip = false
|
|
299
|
-
this.
|
|
299
|
+
this.triggerInfo = await this.queryRect(this.textId)
|
|
300
300
|
sleep(500).then(() => {
|
|
301
301
|
this.calcReacted = true
|
|
302
302
|
})
|
package/libs/i18n/index.js
CHANGED
|
@@ -33,7 +33,11 @@ uni.onLocaleChange((locale) => {
|
|
|
33
33
|
export function t(value, params = {}) {
|
|
34
34
|
// console.log(settings.locales[settings.lang])
|
|
35
35
|
if (value) {
|
|
36
|
-
let
|
|
36
|
+
let lang = settings.lang
|
|
37
|
+
if (!settings.locales[settings.lang]) {
|
|
38
|
+
lang = 'zh-Hans'
|
|
39
|
+
}
|
|
40
|
+
let result = settings.locales[lang][value] || value;
|
|
37
41
|
// 替换{xxx}格式的变量
|
|
38
42
|
Object.keys(params).forEach(key => {
|
|
39
43
|
const reg = new RegExp(`{${key}}`, 'g');
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"up.common.cancel": "ยกเลิก",
|
|
3
|
+
"up.common.confirm": "ยืนยัน",
|
|
4
|
+
"up.common.start": "เริ่มต้น",
|
|
5
|
+
"up.common.end": "สิ้นสุด",
|
|
6
|
+
"up.common.stop": "หยุด",
|
|
7
|
+
"up.common.copy": "คัดลอก",
|
|
8
|
+
"up.common.none": "ไม่มี",
|
|
9
|
+
"up.common.tip": "คำแนะนำ",
|
|
10
|
+
"up.common.success": "สำเร็จ",
|
|
11
|
+
"up.common.fail": "ล้มเหลว",
|
|
12
|
+
"up.common.close": "ปิด",
|
|
13
|
+
"up.common.preview": "ดูตัวอย่าง",
|
|
14
|
+
"up.common.re-select": "เลือกใหม่",
|
|
15
|
+
"up.common.rotate": "หมุน",
|
|
16
|
+
"up.common.pleaseChoose": "กรุณาเลือก",
|
|
17
|
+
"up.common.loading": "กำลังโหลด",
|
|
18
|
+
"up.common.loading2": "กำลังโหลด",
|
|
19
|
+
"up.common.inOperation": "กำลังดำเนินการ",
|
|
20
|
+
"up.common.settings": "การตั้งค่า",
|
|
21
|
+
"up.common.retry": "ลองใหม่",
|
|
22
|
+
"up.common.search": "ค้นหา",
|
|
23
|
+
"up.common.more": "เพิ่มเติม",
|
|
24
|
+
"up.common.video": "วิดีโอ",
|
|
25
|
+
"up.common.file": "ไฟล์",
|
|
26
|
+
"up.week.one": "จันทร์",
|
|
27
|
+
"up.week.two": "อังคาร",
|
|
28
|
+
"up.week.three": "พุธ",
|
|
29
|
+
"up.week.four": "พฤหัสบดี",
|
|
30
|
+
"up.week.five": "ศุกร์",
|
|
31
|
+
"up.week.six": "เสาร์",
|
|
32
|
+
"up.week.seven": "อาทิตย์",
|
|
33
|
+
"up.barcode.error": "สร้างบาร์โค้ดไม่สำเร็จ",
|
|
34
|
+
"up.calendar.chooseDates": "เลือกวันที่",
|
|
35
|
+
"up.calendar.disabled": "วันที่นี้ถูกปิดการใช้งาน",
|
|
36
|
+
"up.calendar.daysExceed": "จำนวนวันที่เลือกต้องไม่เกิน {days} วัน",
|
|
37
|
+
"up.cityLocate.locateCity": "ระบุตำแหน่งเมือง",
|
|
38
|
+
"up.cityLocate.fail": "การระบุตำแหน่งล้มเหลว กรุณาคลิกเพื่อลองใหม่",
|
|
39
|
+
"up.cityLocate.locating": "กำลังระบุตำแหน่ง",
|
|
40
|
+
"up.code.send": "รับรหัสยืนยัน",
|
|
41
|
+
"up.code.resendAfter": "ส่งใหม่ใน X วินาที",
|
|
42
|
+
"up.code.resend": "ส่งใหม่",
|
|
43
|
+
"up.cropper.emptyWidhtOrHeight": "ไม่ได้ตั้งค่าความกว้างหรือความสูงของกรอบตัดภาพ",
|
|
44
|
+
"up.empty.car": "รถเข็นว่างเปล่า",
|
|
45
|
+
"up.empty.page": "ไม่มีหน้านี้",
|
|
46
|
+
"up.empty.search": "ไม่มีผลลัพธ์การค้นหา",
|
|
47
|
+
"up.empty.address": "ไม่มีที่อยู่จัดส่ง",
|
|
48
|
+
"up.empty.wifi": "ไม่มี WiFi",
|
|
49
|
+
"up.empty.order": "ไม่มีคำสั่งซื้อ",
|
|
50
|
+
"up.empty.coupon": "ไม่มีคูปอง",
|
|
51
|
+
"up.empty.favor": "ไม่มีรายการโปรด",
|
|
52
|
+
"up.empty.permission": "ไม่มีสิทธิ์",
|
|
53
|
+
"up.empty.history": "ไม่มีประวัติ",
|
|
54
|
+
"up.empty.news": "ไม่มีรายการข่าว",
|
|
55
|
+
"up.empty.message": "รายการข้อความว่างเปล่า",
|
|
56
|
+
"up.empty.list": "รายการว่างเปล่า",
|
|
57
|
+
"up.empty.data": "ข้อมูลว่างเปล่า",
|
|
58
|
+
"up.empty.comment": "ไม่มีความคิดเห็น",
|
|
59
|
+
"up.link.copyed": "คัดลอกลิงก์แล้ว กรุณาเปิดในเบราว์เซอร์",
|
|
60
|
+
"up.loadmoe.loadmore": "โหลดเพิ่มเติม",
|
|
61
|
+
"up.loadmoe.nomore": "ไม่มีข้อมูลเพิ่มเติม",
|
|
62
|
+
"up.noNetwork.text": "อ๊ะ ขาดการเชื่อมต่อเครือข่าย",
|
|
63
|
+
"up.noNetwork.pleaseCheck": "กรุณาตรวจสอบเครือข่าย หรือไปที่",
|
|
64
|
+
"up.noNetwork.connect": "เชื่อมต่อเครือข่ายแล้ว",
|
|
65
|
+
"up.noNetwork.disconnect": "ไม่มีการเชื่อมต่อเครือข่าย",
|
|
66
|
+
"up.pagination.previous": "หน้าก่อนหน้า",
|
|
67
|
+
"up.pagination.next": "หน้าถัดไป",
|
|
68
|
+
"up.pullRefresh.pull": "ดึงเพื่อรีเฟรช",
|
|
69
|
+
"up.pullRefresh.release": "ปล่อยเพื่อรีเฟรช",
|
|
70
|
+
"up.pullRefresh.refreshing": "กำลังรีเฟรช",
|
|
71
|
+
"up.readMore.expand": "ขยายเพื่ออ่านทั้งหมด",
|
|
72
|
+
"up.readMore.fold": "ย่อ",
|
|
73
|
+
"up.search.placeholder": "กรุณาใส่คำสำคัญ",
|
|
74
|
+
"up.signature.penSize": "ขนาดเส้น",
|
|
75
|
+
"up.signature.penColor": "สีเส้น",
|
|
76
|
+
"up.upload.sizeExceed": "เกินขนาดที่กำหนด",
|
|
77
|
+
"up.upload.uploading": "กำลังอัปโหลด",
|
|
78
|
+
"up.upload.previewImageFail": "ดูตัวอย่างภาพไม่สำเร็จ",
|
|
79
|
+
"up.upload.previewVideoFail": "ดูตัวอย่างวิดีโอไม่สำเร็จ"
|
|
80
|
+
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "uview-plus",
|
|
3
3
|
"name": "uview-plus",
|
|
4
4
|
"displayName": "零云®uview-plus3.0重磅发布,全面的Vue3鸿蒙跨端移动组件库,组件丰富维护更新稳定。",
|
|
5
|
-
"version": "3.5.
|
|
5
|
+
"version": "3.5.32",
|
|
6
6
|
"description": "零云®uview-plus已兼容vue3支持多语言,100+全面的组件和便捷的工具会让您信手拈来。近期新增拖动排序、条码、图片裁剪、下拉刷新、虚拟列表、签名、Markdown等。",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"uview",
|