uview-plus 3.4.46 → 3.4.48
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 +1 -1
- package/changelog.md +16 -0
- package/components/u-album/u-album.vue +15 -7
- package/components/u-datetime-picker/u-datetime-picker.vue +6 -0
- package/components/u-icon/u-icon.vue +2 -2
- package/components/u-safe-bottom/u-safe-bottom.vue +1 -1
- package/components/u-subsection/props.js +17 -6
- package/components/u-subsection/subsection.js +3 -1
- package/components/u-subsection/u-subsection.vue +34 -10
- package/components/u-tree/tree-node.vue +128 -0
- package/components/u-tree/u-tree.vue +117 -0
- package/package.json +1 -1
- package/types/comps/modal.d.ts +1 -1
- package/types/comps/subsection.d.ts +11 -0
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
## 说明
|
|
14
14
|
|
|
15
|
-
uview-plus,是uni-app全面兼容vue3/nvue/鸿蒙/uni-app-x的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水。uview-plus是基于uView2.x移植的支持vue3的版本,感谢uView。
|
|
15
|
+
uview-plus,是uni-app全面兼容vue3/nvue/鸿蒙/uni-app-x(即将发布)的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水。uview-plus是基于uView2.x移植的支持vue3的版本,感谢uView。
|
|
16
16
|
|
|
17
17
|
## 可视化设计
|
|
18
18
|
|
package/changelog.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## 3.4.48(2025-07-10)
|
|
2
|
+
fix: 官方文档Card示例组件多行显示省略号样式异常
|
|
3
|
+
|
|
4
|
+
feat: album组件支持自定义preview事件
|
|
5
|
+
|
|
6
|
+
## 3.4.47(2025-07-09)
|
|
7
|
+
fix: 修复datetime-picker打开时,数值可能出现对不上的问题
|
|
8
|
+
|
|
9
|
+
feat: Subsection 分段器添加支持从 list中读取激活文字颜色和未激活文字颜色
|
|
10
|
+
|
|
11
|
+
fix: 修复modal定义confirmButton
|
|
12
|
+
|
|
13
|
+
fix: safe-bottom底部安全距离在小程序优先用JS计算
|
|
14
|
+
|
|
15
|
+
feat: 新增tree树形组件
|
|
16
|
+
|
|
1
17
|
## 3.4.46(2025-07-08)
|
|
2
18
|
feat: 上传组件预览视频支持videoPreviewObjectFit参数
|
|
3
19
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
v-for="(item, index1) in arr"
|
|
14
14
|
:key="index1"
|
|
15
15
|
:style="[imageStyle(index + 1, index1 + 1)]"
|
|
16
|
-
@tap="
|
|
16
|
+
@tap="onPreviewTap($event, getSrc(item))"
|
|
17
17
|
>
|
|
18
18
|
<image
|
|
19
19
|
:src="getSrc(item)"
|
|
@@ -185,6 +185,7 @@ export default {
|
|
|
185
185
|
return width
|
|
186
186
|
}
|
|
187
187
|
},
|
|
188
|
+
emits: ['preview', 'albumWidth'],
|
|
188
189
|
methods: {
|
|
189
190
|
addUnit,
|
|
190
191
|
// 预览图片
|
|
@@ -192,12 +193,19 @@ export default {
|
|
|
192
193
|
const urls = this.urls.map((item) => {
|
|
193
194
|
return this.getSrc(item)
|
|
194
195
|
})
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
196
|
+
if (this.previewFullImage) {
|
|
197
|
+
uni.previewImage({
|
|
198
|
+
current: url,
|
|
199
|
+
urls
|
|
200
|
+
})
|
|
201
|
+
// 是否阻止事件传播
|
|
202
|
+
this.stop && this.preventEvent(e)
|
|
203
|
+
} else {
|
|
204
|
+
this.$emit('preview', {
|
|
205
|
+
urls,
|
|
206
|
+
currentIndex: urls.indexOf(url)
|
|
207
|
+
})
|
|
208
|
+
}
|
|
201
209
|
},
|
|
202
210
|
// 获取图片的路径
|
|
203
211
|
getSrc(item) {
|
|
@@ -109,6 +109,12 @@
|
|
|
109
109
|
watch: {
|
|
110
110
|
show(newValue, oldValue) {
|
|
111
111
|
if (newValue) {
|
|
112
|
+
// #ifdef VUE3
|
|
113
|
+
this.innerValue = this.correctValue(this.modelValue)
|
|
114
|
+
// #endif
|
|
115
|
+
// #ifdef VUE2
|
|
116
|
+
this.innerValue = this.correctValue(this.value)
|
|
117
|
+
// #endif
|
|
112
118
|
this.updateColumnValue(this.innerValue)
|
|
113
119
|
}
|
|
114
120
|
},
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
// console.log('内置字体图标加载成功');
|
|
96
96
|
},
|
|
97
97
|
fail() {
|
|
98
|
-
console.error('内置字体图标加载出错');
|
|
98
|
+
// console.error('内置字体图标加载出错');
|
|
99
99
|
}
|
|
100
100
|
});
|
|
101
101
|
if (config.customIcon.family) {
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
// console.log('扩展字体图标加载成功');
|
|
107
107
|
},
|
|
108
108
|
fail() {
|
|
109
|
-
console.error('扩展字体图标加载出错');
|
|
109
|
+
// console.error('扩展字体图标加载出错');
|
|
110
110
|
}
|
|
111
111
|
});
|
|
112
112
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {defineMixin} from '../../libs/vue'
|
|
2
2
|
import defProps from '../../libs/config/props.js'
|
|
3
|
+
|
|
3
4
|
export const props = defineMixin({
|
|
4
5
|
props: {
|
|
5
6
|
// tab的数据
|
|
@@ -42,10 +43,20 @@ export const props = defineMixin({
|
|
|
42
43
|
type: String,
|
|
43
44
|
default: () => defProps.subsection.bgColor
|
|
44
45
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
// 从list元素对象中读取的键名
|
|
47
|
+
keyName: {
|
|
48
|
+
type: String,
|
|
49
|
+
default: () => defProps.subsection.keyName
|
|
50
|
+
},
|
|
51
|
+
// 从`list`元素对象中读取激活时的颜色 如果存在字段 优先级大于 activeColor
|
|
52
|
+
activeColorKeyName: {
|
|
53
|
+
type: String,
|
|
54
|
+
default: () => defProps.subsection.activeColorKeyName
|
|
55
|
+
},
|
|
56
|
+
// 从`list`元素对象中读取未激活时的颜色 如果存在字段 优先级大于 inactiveColor
|
|
57
|
+
inactiveColorKeyName: {
|
|
58
|
+
type: String,
|
|
59
|
+
default: () => defProps.subsection.inactiveColorKeyName
|
|
60
|
+
}
|
|
50
61
|
}
|
|
51
62
|
})
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
>
|
|
41
41
|
<text
|
|
42
42
|
class="u-subsection__item__text"
|
|
43
|
-
:style="[textStyle(index)]"
|
|
43
|
+
:style="[textStyle(index,item)]"
|
|
44
44
|
>{{ getText(item) }}</text
|
|
45
45
|
>
|
|
46
46
|
</view>
|
|
@@ -158,22 +158,46 @@ export default {
|
|
|
158
158
|
};
|
|
159
159
|
},
|
|
160
160
|
// 分段器文字颜色
|
|
161
|
-
textStyle(index) {
|
|
162
|
-
return (index) => {
|
|
161
|
+
textStyle(index,item) {
|
|
162
|
+
return (index,item) => {
|
|
163
163
|
const style = {};
|
|
164
164
|
style.fontWeight =
|
|
165
165
|
this.bold && this.innerCurrent === index ? "bold" : "normal";
|
|
166
166
|
style.fontSize = addUnit(this.fontSize);
|
|
167
|
+
|
|
168
|
+
let activeColorTemp = null;
|
|
169
|
+
let inactiveColorTemp = null;
|
|
170
|
+
// 如果是对象并且设置了对应的背景色字段 则优先使用设置的字段
|
|
171
|
+
if(typeof item === 'object' && item[this.activeColorKeyName]){
|
|
172
|
+
activeColorTemp = item[this.activeColorKeyName];
|
|
173
|
+
}
|
|
174
|
+
if(typeof item === 'object' && item[this.inactiveColorKeyName]){
|
|
175
|
+
inactiveColorTemp = item[this.inactiveColorKeyName];
|
|
176
|
+
}
|
|
177
|
+
|
|
167
178
|
// subsection模式下,激活时默认为白色的文字
|
|
168
179
|
if (this.mode === "subsection") {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
180
|
+
// 判断当前是否激活
|
|
181
|
+
if(this.innerCurrent === index){
|
|
182
|
+
// 判断当前是否有自定义的颜色
|
|
183
|
+
style.color = activeColorTemp ? activeColorTemp : '#FFF'
|
|
184
|
+
// style.color = activeColorTemp ? activeColorTemp : this.activeColor
|
|
185
|
+
}
|
|
186
|
+
else{
|
|
187
|
+
// 判断当前是否有自定义的颜色
|
|
188
|
+
style.color = inactiveColorTemp ? inactiveColorTemp : this.inactiveColor;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
172
192
|
// button模式下,激活时文字颜色默认为activeColor
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
193
|
+
if(this.innerCurrent === index){
|
|
194
|
+
// 判断当前是否有自定义的颜色
|
|
195
|
+
style.color = activeColorTemp ? activeColorTemp : this.activeColor
|
|
196
|
+
}
|
|
197
|
+
else{
|
|
198
|
+
// 判断当前是否有自定义的颜色
|
|
199
|
+
style.color = inactiveColorTemp ? inactiveColorTemp : this.inactiveColor;
|
|
200
|
+
}
|
|
177
201
|
}
|
|
178
202
|
return style;
|
|
179
203
|
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="u-tree-node" :style="{ paddingLeft: depth * 20 + 'px' }">
|
|
3
|
+
<view class="u-tree-node-content" @click="toggle">
|
|
4
|
+
<!-- <text v-if="hasChildren" class="u-tree-node-toggle">
|
|
5
|
+
{{ node.expanded ? '▼' : '▶' }}
|
|
6
|
+
</text> -->
|
|
7
|
+
<up-icon v-if="hasChildren" class="u-tree-node-toggle"
|
|
8
|
+
:name="node.expanded ? 'arrow-down-fill' : 'play-right-fill'" size="12" />
|
|
9
|
+
<up-checkbox
|
|
10
|
+
v-if="showCheckbox"
|
|
11
|
+
usedAlone
|
|
12
|
+
:size="12"
|
|
13
|
+
:checked="node.checked"
|
|
14
|
+
@change="toggleCheck"
|
|
15
|
+
style="margin-right: 10px;"
|
|
16
|
+
/>
|
|
17
|
+
<slot :nodeData="node" :level="depth + 1">
|
|
18
|
+
{{ node[props.label] }}
|
|
19
|
+
</slot>
|
|
20
|
+
</view>
|
|
21
|
+
<view v-if="hasChildren && (node.expanded === undefined ? true : node.expanded)"
|
|
22
|
+
class="u-tree-node-children"
|
|
23
|
+
:style="{ paddingLeft: (depth + 1) * 20 + 'px' }">
|
|
24
|
+
<tree-node
|
|
25
|
+
v-for="child in node[props.children]"
|
|
26
|
+
:key="child[props.nodeKey]"
|
|
27
|
+
:node="child"
|
|
28
|
+
:props="props"
|
|
29
|
+
:show-checkbox="showCheckbox"
|
|
30
|
+
:check-strictly="checkStrictly"
|
|
31
|
+
:expand-on-click-node="expandOnClickNode"
|
|
32
|
+
:depth="depth + 1"
|
|
33
|
+
@node-click="$emit('node-click', $event)"
|
|
34
|
+
@check-change="$emit('check-change', $event)">
|
|
35
|
+
<template #default="{ nodeData, level }">
|
|
36
|
+
<slot name="default" :nodeData="nodeData" :level="level"></slot>
|
|
37
|
+
</template>
|
|
38
|
+
</tree-node>
|
|
39
|
+
</view>
|
|
40
|
+
</view>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<script>
|
|
44
|
+
export default {
|
|
45
|
+
name: 'tree-node',
|
|
46
|
+
props: {
|
|
47
|
+
node: {
|
|
48
|
+
type: Object,
|
|
49
|
+
required: true
|
|
50
|
+
},
|
|
51
|
+
props: {
|
|
52
|
+
type: Object,
|
|
53
|
+
required: true
|
|
54
|
+
},
|
|
55
|
+
showCheckbox: {
|
|
56
|
+
type: Boolean,
|
|
57
|
+
default: false
|
|
58
|
+
},
|
|
59
|
+
checkStrictly: {
|
|
60
|
+
type: Boolean,
|
|
61
|
+
default: false
|
|
62
|
+
},
|
|
63
|
+
expandOnClickNode: {
|
|
64
|
+
type: Boolean,
|
|
65
|
+
default: true
|
|
66
|
+
},
|
|
67
|
+
depth: {
|
|
68
|
+
type: Number,
|
|
69
|
+
default: 0
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
computed: {
|
|
73
|
+
hasChildren() {
|
|
74
|
+
return this.node[this.props.children] && this.node[this.props.children].length > 0;
|
|
75
|
+
},
|
|
76
|
+
isExpanded() {
|
|
77
|
+
return this.node.expanded === undefined ? false : this.node.expanded;
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
emits: ['node-click', 'check-change'],
|
|
81
|
+
methods: {
|
|
82
|
+
toggle() {
|
|
83
|
+
if (this.expandOnClickNode && this.hasChildren) {
|
|
84
|
+
this.node.expanded = !this.node.expanded;
|
|
85
|
+
}
|
|
86
|
+
this.$emit('node-click', this.node);
|
|
87
|
+
},
|
|
88
|
+
toggleCheck(checked) {
|
|
89
|
+
this.node.checked = checked;
|
|
90
|
+
if (!this.checkStrictly) {
|
|
91
|
+
this.updateChildCheckStatus(this.node, checked);
|
|
92
|
+
this.updateParentCheckStatus(this.node);
|
|
93
|
+
}
|
|
94
|
+
this.$emit('check-change', this.node);
|
|
95
|
+
},
|
|
96
|
+
updateChildCheckStatus(node, checked) {
|
|
97
|
+
if (node[this.props.children]) {
|
|
98
|
+
node[this.props.children].forEach(child => {
|
|
99
|
+
child.checked = checked;
|
|
100
|
+
this.updateChildCheckStatus(child, checked);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
updateParentCheckStatus(node) {
|
|
105
|
+
let parent = this.$parent;
|
|
106
|
+
while (parent && parent.node) {
|
|
107
|
+
const allChecked = parent.node[this.props.children].every(
|
|
108
|
+
child => child.checked
|
|
109
|
+
);
|
|
110
|
+
parent.node.checked = allChecked;
|
|
111
|
+
parent = parent.$parent;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
</script>
|
|
117
|
+
|
|
118
|
+
<style scoped>
|
|
119
|
+
.u-tree-node-content {
|
|
120
|
+
display: flex;
|
|
121
|
+
flex-direction: row;
|
|
122
|
+
align-items: center;
|
|
123
|
+
padding-left: 20px;
|
|
124
|
+
}
|
|
125
|
+
.u-tree-node-toggle {
|
|
126
|
+
margin-right: 5px;
|
|
127
|
+
}
|
|
128
|
+
</style>
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="u-tree">
|
|
3
|
+
<tree-node
|
|
4
|
+
v-for="node in treeData"
|
|
5
|
+
:key="node[props.nodeKey]"
|
|
6
|
+
:node="node"
|
|
7
|
+
:props="props"
|
|
8
|
+
:show-checkbox="showCheckbox"
|
|
9
|
+
:check-strictly="checkStrictly"
|
|
10
|
+
:expand-on-click-node="expandOnClickNode"
|
|
11
|
+
@node-click="handleNodeClick"
|
|
12
|
+
@check-change="$emit('check-change', $event)">
|
|
13
|
+
<template #default="{ nodeData, level }">
|
|
14
|
+
<slot :node="nodeData" :level="level"></slot>
|
|
15
|
+
</template>
|
|
16
|
+
</tree-node>
|
|
17
|
+
</view>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script>
|
|
21
|
+
import TreeNode from './tree-node.vue';
|
|
22
|
+
|
|
23
|
+
export default {
|
|
24
|
+
name: 'u-tree',
|
|
25
|
+
components: { TreeNode },
|
|
26
|
+
props: {
|
|
27
|
+
data: {
|
|
28
|
+
type: Array,
|
|
29
|
+
required: true
|
|
30
|
+
},
|
|
31
|
+
props: {
|
|
32
|
+
type: Object,
|
|
33
|
+
default: () => ({
|
|
34
|
+
label: 'label',
|
|
35
|
+
children: 'children',
|
|
36
|
+
nodeKey: 'id'
|
|
37
|
+
})
|
|
38
|
+
},
|
|
39
|
+
showCheckbox: {
|
|
40
|
+
type: Boolean,
|
|
41
|
+
default: false
|
|
42
|
+
},
|
|
43
|
+
defaultExpandAll: {
|
|
44
|
+
type: Boolean,
|
|
45
|
+
default: false
|
|
46
|
+
},
|
|
47
|
+
expandOnClickNode: {
|
|
48
|
+
type: Boolean,
|
|
49
|
+
default: true
|
|
50
|
+
},
|
|
51
|
+
checkStrictly: {
|
|
52
|
+
type: Boolean,
|
|
53
|
+
default: false
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
data() {
|
|
57
|
+
return {
|
|
58
|
+
treeData: []
|
|
59
|
+
};
|
|
60
|
+
},
|
|
61
|
+
created() {
|
|
62
|
+
this.initTree();
|
|
63
|
+
},
|
|
64
|
+
watch: {
|
|
65
|
+
data: {
|
|
66
|
+
handler(newVal) {
|
|
67
|
+
this.treeData = JSON.parse(JSON.stringify(newVal));
|
|
68
|
+
this.initExpandedState(this.treeData, this.defaultExpandAll);
|
|
69
|
+
},
|
|
70
|
+
deep: true,
|
|
71
|
+
immediate: true
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
emits: ['node-click', 'check-change'],
|
|
75
|
+
methods: {
|
|
76
|
+
initTree() {
|
|
77
|
+
this.treeData = JSON.parse(JSON.stringify(this.data));
|
|
78
|
+
this.initExpandedState(this.treeData, this.defaultExpandAll);
|
|
79
|
+
},
|
|
80
|
+
initExpandedState(nodes, expanded) {
|
|
81
|
+
nodes.forEach(node => {
|
|
82
|
+
node.expanded = expanded;
|
|
83
|
+
if (node[this.props.children]) {
|
|
84
|
+
this.initExpandedState(node[this.props.children], expanded);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
handleNodeClick(node) {
|
|
89
|
+
this.$emit('node-click', node);
|
|
90
|
+
},
|
|
91
|
+
/**
|
|
92
|
+
* 直接递归 treeData 获取所有 checked 的节点
|
|
93
|
+
*/
|
|
94
|
+
getCheckedNodes() {
|
|
95
|
+
const traverse = (nodes) => {
|
|
96
|
+
let result = [];
|
|
97
|
+
nodes.forEach(node => {
|
|
98
|
+
if (node.checked) {
|
|
99
|
+
result.push(node);
|
|
100
|
+
}
|
|
101
|
+
if (node[this.props.children] && node[this.props.children].length > 0) {
|
|
102
|
+
result = result.concat(traverse(node[this.props.children]));
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return result;
|
|
106
|
+
};
|
|
107
|
+
return traverse(this.treeData);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
<style scoped>
|
|
114
|
+
.u-tree {
|
|
115
|
+
font-size: 28rpx;
|
|
116
|
+
}
|
|
117
|
+
</style>
|
package/package.json
CHANGED
package/types/comps/modal.d.ts
CHANGED
|
@@ -46,6 +46,17 @@ declare interface SubsectionProps {
|
|
|
46
46
|
* @default "name"
|
|
47
47
|
*/
|
|
48
48
|
keyName?: string
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 从`list`元素对象中读取激活时的颜色 如果存在字段 优先级大于 activeColor
|
|
52
|
+
* @default activeColorKey
|
|
53
|
+
*/
|
|
54
|
+
activeColorKeyName?: string
|
|
55
|
+
/**
|
|
56
|
+
* 从`list`元素对象中读取未激活时的颜色 如果存在字段 优先级大于 inactiveColor
|
|
57
|
+
* @default inactiveColorKey
|
|
58
|
+
*/
|
|
59
|
+
inactiveColorKeyName?: string
|
|
49
60
|
/**
|
|
50
61
|
* 分段器选项发生改变时触发
|
|
51
62
|
* @param index 选项的index索引值,从0开始
|