hw-cus-ui 1.0.23 → 1.0.25
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/HwBtn/HwBtn.vue +16 -16
- package/HwBtn/index.ts +10 -10
- package/HwCheckbox/HwCheckbox.vue +117 -0
- package/HwCheckbox/index.ts +10 -0
- package/HwDraggableBottomPopup/HwDraggableBottomPopup.vue +195 -0
- package/HwDraggableBottomPopup/index.ts +10 -0
- package/HwFileUpload/HwFileUpload.vue +412 -0
- package/HwFileUpload/index.ts +10 -0
- package/HwInput/HwInput.vue +120 -0
- package/HwInput/index.ts +10 -0
- package/HwPickerTree/HwPickerTree.vue +843 -0
- package/HwPickerTree/index.ts +10 -0
- package/HwSelect/HwSelect.vue +156 -0
- package/HwSelect/index.ts +10 -0
- package/index.d.ts +9 -3
- package/index.ts +9 -3
- package/package.json +1 -1
package/HwBtn/HwBtn.vue
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="btn">我的按钮</div>
|
|
3
|
-
</template>
|
|
4
|
-
|
|
5
|
-
<script setup lang="ts">
|
|
6
|
-
|
|
7
|
-
</script>
|
|
8
|
-
|
|
9
|
-
<style scoped>
|
|
10
|
-
.btn {
|
|
11
|
-
width: 100px;
|
|
12
|
-
height: 100px;
|
|
13
|
-
background-color: red;
|
|
14
|
-
color: #ffffff;
|
|
15
|
-
}
|
|
16
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<div class="btn">我的按钮</div>
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script setup lang="ts">
|
|
6
|
+
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<style scoped>
|
|
10
|
+
.btn {
|
|
11
|
+
width: 100px;
|
|
12
|
+
height: 100px;
|
|
13
|
+
background-color: red;
|
|
14
|
+
color: #ffffff;
|
|
15
|
+
}
|
|
16
|
+
</style>
|
package/HwBtn/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// index.ts
|
|
2
|
-
import type { App } from 'vue'
|
|
3
|
-
import HwBtn from "./HwBtn.vue"
|
|
4
|
-
|
|
5
|
-
// 使用install方法,在app.use挂载
|
|
6
|
-
HwBtn.install = (app: App) => {
|
|
7
|
-
app.component(HwBtn.__name as string, HwBtn) //注册组件
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default HwBtn
|
|
1
|
+
// index.ts
|
|
2
|
+
import type { App } from 'vue'
|
|
3
|
+
import HwBtn from "./HwBtn.vue"
|
|
4
|
+
|
|
5
|
+
// 使用install方法,在app.use挂载
|
|
6
|
+
HwBtn.install = (app: App) => {
|
|
7
|
+
app.component(HwBtn.__name as string, HwBtn) //注册组件
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default HwBtn
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="bn-select" :style="{ marginTop: marginTop }">
|
|
3
|
+
<view class="select-item">
|
|
4
|
+
<view>
|
|
5
|
+
<!-- 标签区域:显示字段标签和必填标识 -->
|
|
6
|
+
<view class="label" :style="{ color: types === 'detail' ? 'rgba(23, 26, 29, 0.6)' : 'rgba(23, 26, 29, 1)' }">
|
|
7
|
+
<text style="color: red" v-if="required">*</text>
|
|
8
|
+
{{ label }}
|
|
9
|
+
</view>
|
|
10
|
+
<!-- 编辑模式下显示复选框组件 -->
|
|
11
|
+
<slot>
|
|
12
|
+
<uni-data-checkbox
|
|
13
|
+
class="value"
|
|
14
|
+
v-if="pageType !== 'detail'"
|
|
15
|
+
v-model="value"
|
|
16
|
+
:localdata="localdata"
|
|
17
|
+
v-bind="$attrs"
|
|
18
|
+
/>
|
|
19
|
+
</slot>
|
|
20
|
+
|
|
21
|
+
<!-- 详情模式下显示选中项的文本 -->
|
|
22
|
+
<view
|
|
23
|
+
class="value"
|
|
24
|
+
v-if="pageType === 'detail'"
|
|
25
|
+
:style="{ color: types === 'detail' ? 'rgba(23, 26, 29, 0.6)' : 'rgba(23, 26, 29, 1)' }"
|
|
26
|
+
>
|
|
27
|
+
{{ getValue(value) }}
|
|
28
|
+
</view>
|
|
29
|
+
</view>
|
|
30
|
+
</view>
|
|
31
|
+
</view>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<script lang="ts" setup>
|
|
35
|
+
/**
|
|
36
|
+
* 双向绑定的值,可以是字符串或数字类型
|
|
37
|
+
*/
|
|
38
|
+
const value = defineModel<string | number>();
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 组件属性接口定义
|
|
42
|
+
*/
|
|
43
|
+
interface Props {
|
|
44
|
+
/**
|
|
45
|
+
* 上边距,默认为 20px
|
|
46
|
+
*/
|
|
47
|
+
marginTop?: string;
|
|
48
|
+
/**
|
|
49
|
+
* 页面类型,用于区分编辑页面还是详情页面
|
|
50
|
+
*/
|
|
51
|
+
pageType?: string;
|
|
52
|
+
/**
|
|
53
|
+
* 字段标签名称(必填)
|
|
54
|
+
*/
|
|
55
|
+
label: string;
|
|
56
|
+
/**
|
|
57
|
+
* 类型标识,用于控制样式显示
|
|
58
|
+
*/
|
|
59
|
+
types?: string;
|
|
60
|
+
/**
|
|
61
|
+
* 是否必填项,true时会显示红色星号
|
|
62
|
+
*/
|
|
63
|
+
required?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* 下拉选项数据列表,每项应包含value和text属性
|
|
66
|
+
*/
|
|
67
|
+
localdata?: any[];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 定义组件接收的属性
|
|
72
|
+
*/
|
|
73
|
+
const props = defineProps<Props>();
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 解构赋值设置默认值
|
|
77
|
+
*/
|
|
78
|
+
const { label = '', marginTop = '20px', pageType = 'checkbox', types = 'add' } = props;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 根据选中的值获取对应的文本显示
|
|
82
|
+
* @param val 当前选中的值
|
|
83
|
+
* @returns 对应的文本内容,未找到则返回空字符串
|
|
84
|
+
*/
|
|
85
|
+
const getValue = (val: any) => {
|
|
86
|
+
if (val) {
|
|
87
|
+
return props.localdata?.find((item) => item.value === val)?.text;
|
|
88
|
+
}
|
|
89
|
+
return '';
|
|
90
|
+
};
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<style lang="scss" scoped>
|
|
94
|
+
.bn-select {
|
|
95
|
+
width: 100%;
|
|
96
|
+
border-bottom: 1rpx solid rgba(17, 31, 44, 0.12);
|
|
97
|
+
.select-item {
|
|
98
|
+
.label {
|
|
99
|
+
font-size: 34rpx;
|
|
100
|
+
letter-spacing: 0px;
|
|
101
|
+
line-height: 44rpx;
|
|
102
|
+
height: 44rpx;
|
|
103
|
+
color: rgba(23, 26, 29, 1);
|
|
104
|
+
}
|
|
105
|
+
.value {
|
|
106
|
+
font-size: 34rpx;
|
|
107
|
+
padding: 20rpx 0;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
::v-deep .checklist-text {
|
|
111
|
+
font-size: 34rpx !important;
|
|
112
|
+
}
|
|
113
|
+
::v-deep .uni-data-checklist .checklist-group .checklist-box {
|
|
114
|
+
margin: 10rpx 40rpx 10rpx 0rpx !important;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// index.ts
|
|
2
|
+
import type { App } from 'vue';
|
|
3
|
+
import HwCheckbox from './HwCheckbox.vue';
|
|
4
|
+
|
|
5
|
+
// 使用install方法,在app.use挂载
|
|
6
|
+
HwCheckbox.install = (app: App) => {
|
|
7
|
+
app.component(HwCheckbox.__name as string, HwCheckbox); //注册组件
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default HwCheckbox;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="draggable-popup-mask">
|
|
3
|
+
<view
|
|
4
|
+
class="draggable-popup-container"
|
|
5
|
+
:style="{
|
|
6
|
+
top: popupTop + 'px',
|
|
7
|
+
position: isDrag ? 'fixed' : 'initial',
|
|
8
|
+
borderTopLeftRadius: isDrag ? '20rpx' : '0',
|
|
9
|
+
borderTopRightRadius: isDrag ? '20rpx' : '0'
|
|
10
|
+
}"
|
|
11
|
+
>
|
|
12
|
+
<view
|
|
13
|
+
v-if="isDrag"
|
|
14
|
+
class="draggable-popup-handle"
|
|
15
|
+
@touchstart="handleTouchStart"
|
|
16
|
+
@touchmove="handleTouchMove"
|
|
17
|
+
@touchend="handleTouchEnd"
|
|
18
|
+
@touchcancel="handleTouchEnd"
|
|
19
|
+
>
|
|
20
|
+
<view class="draggable-popup-handle-line"></view>
|
|
21
|
+
</view>
|
|
22
|
+
<view class="draggable-popup-content" :style="{ height: isDrag ? contentPopupTop + 'px' : 'auto' }">
|
|
23
|
+
<slot></slot>
|
|
24
|
+
</view>
|
|
25
|
+
</view>
|
|
26
|
+
</view>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<script>
|
|
30
|
+
import { useDebounceFn } from '@vueuse/core';
|
|
31
|
+
export default {
|
|
32
|
+
name: 'DraggableBottomPopup',
|
|
33
|
+
props: {
|
|
34
|
+
heightCalc: {
|
|
35
|
+
type: String,
|
|
36
|
+
default: '0.4'
|
|
37
|
+
},
|
|
38
|
+
isDrag: {
|
|
39
|
+
type: Boolean,
|
|
40
|
+
default: () => true
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
data() {
|
|
44
|
+
return {
|
|
45
|
+
startY: 0,
|
|
46
|
+
startTop: 0,
|
|
47
|
+
popupTop: 0,
|
|
48
|
+
windowHeight: 0,
|
|
49
|
+
contentPopupTop: 0,
|
|
50
|
+
isMoving: false,
|
|
51
|
+
containerHeight: 0, // 容器高度
|
|
52
|
+
updateContentPopupTop: null // 防抖函数
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
mounted() {
|
|
57
|
+
this.getWindowInfo();
|
|
58
|
+
this.initPopupPosition();
|
|
59
|
+
// 初始化防抖函数
|
|
60
|
+
this.updateContentPopupTop = useDebounceFn(() => {
|
|
61
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
62
|
+
}, 300);
|
|
63
|
+
},
|
|
64
|
+
methods: {
|
|
65
|
+
getWindowInfo() {
|
|
66
|
+
const systemInfo = uni.getSystemInfoSync();
|
|
67
|
+
this.windowHeight = systemInfo.windowHeight;
|
|
68
|
+
// 初始位置在屏幕外,隐藏状态
|
|
69
|
+
this.popupTop = this.windowHeight;
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
initPopupPosition() {
|
|
73
|
+
this.$nextTick(() => {
|
|
74
|
+
// 获取内容高度
|
|
75
|
+
const query = uni.createSelectorQuery().in(this);
|
|
76
|
+
query
|
|
77
|
+
.select('.draggable-popup-container')
|
|
78
|
+
.boundingClientRect((data) => {
|
|
79
|
+
if (data) {
|
|
80
|
+
this.containerHeight = data.height;
|
|
81
|
+
// 默认显示屏幕高度的60%
|
|
82
|
+
this.popupTop = this.windowHeight * this.heightCalc;
|
|
83
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
84
|
+
this.changeTop();
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
.exec();
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
handleTouchStart(e) {
|
|
92
|
+
this.isMoving = true;
|
|
93
|
+
this.startY = e.touches[0].clientY;
|
|
94
|
+
this.startTop = this.popupTop;
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
handleTouchMove(e) {
|
|
98
|
+
if (!this.isMoving) return;
|
|
99
|
+
|
|
100
|
+
const moveY = e.touches[0].clientY - this.startY;
|
|
101
|
+
let newTop = this.startTop + moveY;
|
|
102
|
+
|
|
103
|
+
// 限制拖动范围,但允许拖出屏幕一定距离
|
|
104
|
+
const maxDragDistance = 100; // 最大可拖出屏幕的距离
|
|
105
|
+
|
|
106
|
+
if (newTop < -maxDragDistance) {
|
|
107
|
+
newTop = -maxDragDistance;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 保留一部分在屏幕内,方便拖回
|
|
111
|
+
if (this.containerHeight > 0) {
|
|
112
|
+
const maxTop = this.windowHeight - 50; // 至少保留50px在屏幕内
|
|
113
|
+
if (newTop > maxTop) {
|
|
114
|
+
newTop = maxTop;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
this.popupTop = newTop;
|
|
118
|
+
this.changeTop();
|
|
119
|
+
// 调用防抖函数而不是创建它
|
|
120
|
+
this.updateContentPopupTop();
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
handleTouchEnd(e) {
|
|
124
|
+
if (!this.isMoving) return;
|
|
125
|
+
this.isMoving = false;
|
|
126
|
+
|
|
127
|
+
// 修改:拖动结束后停留在当前位置,不自动展开或收起
|
|
128
|
+
// 只要确保popupTop在有效范围内即可
|
|
129
|
+
|
|
130
|
+
if (this.popupTop < 0) {
|
|
131
|
+
this.popupTop = 110;
|
|
132
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
133
|
+
} else if (this.popupTop > this.windowHeight) {
|
|
134
|
+
this.popupTop = this.windowHeight - 60;
|
|
135
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
136
|
+
} else if (this.popupTop < 110) {
|
|
137
|
+
this.popupTop = 110;
|
|
138
|
+
this.contentPopupTop = this.windowHeight - this.popupTop - 25;
|
|
139
|
+
}
|
|
140
|
+
this.changeTop();
|
|
141
|
+
},
|
|
142
|
+
changeTop() {
|
|
143
|
+
this.$emit('changeTop', this.popupTop);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
</script>
|
|
148
|
+
|
|
149
|
+
<style lang="scss" scoped>
|
|
150
|
+
/* .draggable-popup-mask {
|
|
151
|
+
position: fixed;
|
|
152
|
+
top: 0;
|
|
153
|
+
left: 0;
|
|
154
|
+
right: 0;
|
|
155
|
+
bottom: 0;
|
|
156
|
+
background-color: rgba(0, 0, 0, 0.4);
|
|
157
|
+
z-index: 98;
|
|
158
|
+
} */
|
|
159
|
+
|
|
160
|
+
.draggable-popup-container {
|
|
161
|
+
position: fixed;
|
|
162
|
+
left: 0;
|
|
163
|
+
right: 0;
|
|
164
|
+
bottom: 0;
|
|
165
|
+
background-color: #ffffff;
|
|
166
|
+
border-top-left-radius: 20rpx;
|
|
167
|
+
border-top-right-radius: 20rpx;
|
|
168
|
+
transition: top 0.1s ease; /* 减少过渡时间使拖动更流畅 */
|
|
169
|
+
z-index: 99;
|
|
170
|
+
display: flex;
|
|
171
|
+
flex-direction: column;
|
|
172
|
+
overflow: auto;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.draggable-popup-handle {
|
|
176
|
+
display: flex;
|
|
177
|
+
justify-content: center;
|
|
178
|
+
align-items: center;
|
|
179
|
+
padding: 20rpx 0;
|
|
180
|
+
cursor: move;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.draggable-popup-handle-line {
|
|
184
|
+
width: 60rpx;
|
|
185
|
+
height: 8rpx;
|
|
186
|
+
border-radius: 4rpx;
|
|
187
|
+
background-color: rgba(23, 26, 29, 0.24);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.draggable-popup-content {
|
|
191
|
+
overflow: auto;
|
|
192
|
+
position: relative;
|
|
193
|
+
z-index: 100;
|
|
194
|
+
}
|
|
195
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// index.ts
|
|
2
|
+
import type { App } from 'vue';
|
|
3
|
+
import HwDraggableBottomPopup from './HwDraggableBottomPopup.vue';
|
|
4
|
+
|
|
5
|
+
// 使用install方法,在app.use挂载
|
|
6
|
+
HwDraggableBottomPopup.install = (app: App) => {
|
|
7
|
+
app.component(HwDraggableBottomPopup.__name as string, HwDraggableBottomPopup); //注册组件
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default HwDraggableBottomPopup;
|