hw-cus-ui 1.0.25 → 1.1.0
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/HwCheckbox/README.md +111 -0
- package/HwDraggableBottomPopup/README.md +127 -0
- package/HwFileUpload/README.md +119 -0
- package/HwInput/README.md +134 -0
- package/HwPickerTree/HwPickerTree.vue +212 -84
- package/HwPickerTree/README.md +190 -0
- package/HwSelect/README.md +122 -0
- package/package.json +2 -2
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# HwCheckbox 组件使用说明
|
|
2
|
+
|
|
3
|
+
HwCheckbox 是一个复选框组件,支持编辑模式和详情模式,可以显示复选框或只读文本。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- 支持编辑模式和详情模式
|
|
8
|
+
- 支持双向数据绑定
|
|
9
|
+
- 支持自定义选项数据
|
|
10
|
+
- 支持必填标识显示
|
|
11
|
+
- 支持自定义样式
|
|
12
|
+
|
|
13
|
+
## 属性 (Props)
|
|
14
|
+
|
|
15
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
16
|
+
|------|------|--------|------|
|
|
17
|
+
| [marginTop](file:///e:/temp/my-components/src/components/HwCheckbox/HwCheckbox.vue#L41-L43) | string | '20px' | 上边距 |
|
|
18
|
+
| [pageType](file:///e:/temp/my-components/src/components/HwCheckbox/HwCheckbox.vue#L44-L46) | string | 'checkbox' | 页面类型,用于区分编辑页面还是详情页面 |
|
|
19
|
+
| [label](file:///e:/temp/my-components/src/components/HwCheckbox/HwCheckbox.vue#L47-L49) | string | - | 字段标签名称(必填) |
|
|
20
|
+
| [types](file:///e:/temp/my-components/src/components/HwCheckbox/HwCheckbox.vue#L50-L52) | string | 'add' | 类型标识,用于控制样式显示 |
|
|
21
|
+
| [required](file:///e:/temp/my-components/src/components/HwCheckbox/HwCheckbox.vue#L53-L55) | boolean | false | 是否必填项,true时会显示红色星号 |
|
|
22
|
+
| [localdata](file:///e:/temp/my-components/src/components/HwCheckbox/HwCheckbox.vue#L56-L59) | Array<any> | - | 下拉选项数据列表,每项应包含value和text属性 |
|
|
23
|
+
|
|
24
|
+
## 事件 (Events)
|
|
25
|
+
|
|
26
|
+
| 事件名 | 参数 | 说明 |
|
|
27
|
+
|-------|------|------|
|
|
28
|
+
| update:modelValue | (value: string \| number) | 当值变化时触发 |
|
|
29
|
+
|
|
30
|
+
## 使用示例
|
|
31
|
+
|
|
32
|
+
### 基础用法
|
|
33
|
+
|
|
34
|
+
```vue
|
|
35
|
+
<template>
|
|
36
|
+
<HwCheckbox
|
|
37
|
+
v-model="checkboxValue"
|
|
38
|
+
label="选择项"
|
|
39
|
+
:localdata="checkboxOptions"
|
|
40
|
+
/>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<script setup>
|
|
44
|
+
import { ref } from 'vue';
|
|
45
|
+
import HwCheckbox from '@/components/HwCheckbox/HwCheckbox.vue';
|
|
46
|
+
|
|
47
|
+
const checkboxValue = ref('');
|
|
48
|
+
const checkboxOptions = [
|
|
49
|
+
{ value: 'option1', text: '选项1' },
|
|
50
|
+
{ value: 'option2', text: '选项2' },
|
|
51
|
+
{ value: 'option3', text: '选项3' }
|
|
52
|
+
];
|
|
53
|
+
</script>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 详情模式
|
|
57
|
+
|
|
58
|
+
```vue
|
|
59
|
+
<template>
|
|
60
|
+
<HwCheckbox
|
|
61
|
+
v-model="checkboxValue"
|
|
62
|
+
label="选择项"
|
|
63
|
+
:localdata="checkboxOptions"
|
|
64
|
+
pageType="detail"
|
|
65
|
+
/>
|
|
66
|
+
</template>
|
|
67
|
+
|
|
68
|
+
<script setup>
|
|
69
|
+
import { ref } from 'vue';
|
|
70
|
+
import HwCheckbox from '@/components/HwCheckbox/HwCheckbox.vue';
|
|
71
|
+
|
|
72
|
+
const checkboxValue = ref('option1');
|
|
73
|
+
const checkboxOptions = [
|
|
74
|
+
{ value: 'option1', text: '选项1' },
|
|
75
|
+
{ value: 'option2', text: '选项2' },
|
|
76
|
+
{ value: 'option3', text: '选项3' }
|
|
77
|
+
];
|
|
78
|
+
</script>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 必填项
|
|
82
|
+
|
|
83
|
+
```vue
|
|
84
|
+
<template>
|
|
85
|
+
<HwCheckbox
|
|
86
|
+
v-model="checkboxValue"
|
|
87
|
+
label="必填选择项"
|
|
88
|
+
:required="true"
|
|
89
|
+
:localdata="checkboxOptions"
|
|
90
|
+
/>
|
|
91
|
+
</template>
|
|
92
|
+
|
|
93
|
+
<script setup>
|
|
94
|
+
import { ref } from 'vue';
|
|
95
|
+
import HwCheckbox from '@/components/HwCheckbox/HwCheckbox.vue';
|
|
96
|
+
|
|
97
|
+
const checkboxValue = ref('');
|
|
98
|
+
const checkboxOptions = [
|
|
99
|
+
{ value: 'option1', text: '选项1' },
|
|
100
|
+
{ value: 'option2', text: '选项2' }
|
|
101
|
+
];
|
|
102
|
+
</script>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## 注意事项
|
|
106
|
+
|
|
107
|
+
1. 组件使用了 uni-data-checkbox 作为基础组件
|
|
108
|
+
2. 在详情模式下,组件只显示选中项的文本,不提供编辑功能
|
|
109
|
+
3. [localdata](file:///e:/temp/my-components/src/components/HwCheckbox/HwCheckbox.vue#L56-L59) 属性的每个选项对象需要包含 [value](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L35-L40) 和 text 属性
|
|
110
|
+
4. [pageType](file:///e:/temp/my-components/src/components/HwCheckbox/HwCheckbox.vue#L44-L46) 设置为 'detail' 时会显示为只读的详情模式
|
|
111
|
+
5. 组件支持通过插槽自定义内容
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# HwDraggableBottomPopup 组件使用说明
|
|
2
|
+
|
|
3
|
+
HwDraggableBottomPopup 是一个可拖拽的底部弹窗组件,支持触摸拖拽调整位置,适用于需要用户交互调整内容区域的场景。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- 支持触摸拖拽调整弹窗位置
|
|
8
|
+
- 可自定义弹窗高度
|
|
9
|
+
- 支持拖拽过程中实时调整内容区域高度
|
|
10
|
+
- 防抖处理确保性能
|
|
11
|
+
- 灵活的内容插槽
|
|
12
|
+
|
|
13
|
+
## 属性 (Props)
|
|
14
|
+
|
|
15
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
16
|
+
|------|------|--------|------|
|
|
17
|
+
| [heightCalc](file:///e:/temp/my-components/src/components/HwDraggableBottomPopup/HwDraggableBottomPopup.vue#L31-L35) | String | '0.4' | 弹窗高度计算比例,相对于屏幕高度的百分比 |
|
|
18
|
+
| [isDrag](file:///e:/temp/my-components/src/components/HwDraggableBottomPopup/HwDraggableBottomPopup.vue#L36-L40) | Boolean | true | 是否启用拖拽功能 |
|
|
19
|
+
|
|
20
|
+
## 事件 (Events)
|
|
21
|
+
|
|
22
|
+
| 事件名 | 参数 | 说明 |
|
|
23
|
+
|-------|------|------|
|
|
24
|
+
| changeTop | (top: number) | 拖拽过程中顶部位置变化时触发 |
|
|
25
|
+
|
|
26
|
+
## 插槽 (Slots)
|
|
27
|
+
|
|
28
|
+
| 插槽名 | 说明 |
|
|
29
|
+
|--------|------|
|
|
30
|
+
| default | 默认插槽,用于放置弹窗内容 |
|
|
31
|
+
|
|
32
|
+
## 使用示例
|
|
33
|
+
|
|
34
|
+
### 基础用法
|
|
35
|
+
|
|
36
|
+
```vue
|
|
37
|
+
<template>
|
|
38
|
+
<view>
|
|
39
|
+
<HwDraggableBottomPopup>
|
|
40
|
+
<view class="popup-content">
|
|
41
|
+
<p>这里是弹窗内容</p>
|
|
42
|
+
<p>可以放置任何内容</p>
|
|
43
|
+
</view>
|
|
44
|
+
</HwDraggableBottomPopup>
|
|
45
|
+
</view>
|
|
46
|
+
</template>
|
|
47
|
+
|
|
48
|
+
<script setup>
|
|
49
|
+
import HwDraggableBottomPopup from '@/components/HwDraggableBottomPopup/HwDraggableBottomPopup.vue';
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<style>
|
|
53
|
+
.popup-content {
|
|
54
|
+
padding: 20rpx;
|
|
55
|
+
height: 100%;
|
|
56
|
+
}
|
|
57
|
+
</style>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 自定义高度
|
|
61
|
+
|
|
62
|
+
```vue
|
|
63
|
+
<template>
|
|
64
|
+
<view>
|
|
65
|
+
<HwDraggableBottomPopup :heightCalc="'0.6'">
|
|
66
|
+
<view class="popup-content">
|
|
67
|
+
<p>初始高度为屏幕高度的60%</p>
|
|
68
|
+
</view>
|
|
69
|
+
</HwDraggableBottomPopup>
|
|
70
|
+
</view>
|
|
71
|
+
</template>
|
|
72
|
+
|
|
73
|
+
<script setup>
|
|
74
|
+
import HwDraggableBottomPopup from '@/components/HwDraggableBottomPopup/HwDraggableBottomPopup.vue';
|
|
75
|
+
</script>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 禁用拖拽
|
|
79
|
+
|
|
80
|
+
```vue
|
|
81
|
+
<template>
|
|
82
|
+
<view>
|
|
83
|
+
<HwDraggableBottomPopup :isDrag="false">
|
|
84
|
+
<view class="popup-content">
|
|
85
|
+
<p>此弹窗不可拖拽</p>
|
|
86
|
+
</view>
|
|
87
|
+
</HwDraggableBottomPopup>
|
|
88
|
+
</view>
|
|
89
|
+
</template>
|
|
90
|
+
|
|
91
|
+
<script setup>
|
|
92
|
+
import HwDraggableBottomPopup from '@/components/HwDraggableBottomPopup/HwDraggableBottomPopup.vue';
|
|
93
|
+
</script>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 监听位置变化
|
|
97
|
+
|
|
98
|
+
```vue
|
|
99
|
+
<template>
|
|
100
|
+
<view>
|
|
101
|
+
<HwDraggableBottomPopup @changeTop="onTopChange">
|
|
102
|
+
<view class="popup-content">
|
|
103
|
+
<p>拖拽弹窗查看位置变化</p>
|
|
104
|
+
</view>
|
|
105
|
+
</HwDraggableBottomPopup>
|
|
106
|
+
</view>
|
|
107
|
+
</template>
|
|
108
|
+
|
|
109
|
+
<script setup>
|
|
110
|
+
import { ref } from 'vue';
|
|
111
|
+
import HwDraggableBottomPopup from '@/components/HwDraggableBottomPopup/HwDraggableBottomPopup.vue';
|
|
112
|
+
|
|
113
|
+
const onTopChange = (top) => {
|
|
114
|
+
console.log('弹窗顶部位置:', top);
|
|
115
|
+
};
|
|
116
|
+
</script>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## 注意事项
|
|
120
|
+
|
|
121
|
+
1. 组件使用了 uni-app 的触摸事件和系统信息API
|
|
122
|
+
2. 弹窗默认从屏幕底部开始,初始位置在屏幕外
|
|
123
|
+
3. 拖拽功能通过触摸事件实现,支持触摸开始、移动和结束
|
|
124
|
+
4. 弹窗内容区域高度会根据拖拽位置自动调整
|
|
125
|
+
5. 组件使用了防抖函数优化性能,避免频繁更新内容区域高度
|
|
126
|
+
6. 当启用拖拽功能时,组件会添加圆角边框以提供更好的视觉效果
|
|
127
|
+
7. 组件内部使用了 flex 布局,内容区域会自动适应可用空间
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# HwFileUpload 组件使用说明
|
|
2
|
+
|
|
3
|
+
HwFileUpload 是一个文件上传组件,支持图片和文件上传、预览、下载和删除功能。可通过 [isImg](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L63-L63) 属性控制是图片模式还是文件模式展示。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- 支持图片和文件上传
|
|
8
|
+
- 支持图片预览功能
|
|
9
|
+
- 支持文件下载功能
|
|
10
|
+
- 支持文件删除功能
|
|
11
|
+
- 可切换图片模式和文件模式
|
|
12
|
+
- 支持多种文件类型的上传限制
|
|
13
|
+
- 支持详情模式和添加模式
|
|
14
|
+
|
|
15
|
+
## 属性 (Props)
|
|
16
|
+
|
|
17
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
18
|
+
|------|------|--------|------|
|
|
19
|
+
| [fileType](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L54-L54) | Array | ['pdf', 'xlsx', 'docx', 'doc', 'zip', 'rar', 'exe'] | 允许上传的文件类型列表 |
|
|
20
|
+
| [modelValue](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L55-L55) | Array | - | 绑定值,文件列表 |
|
|
21
|
+
| [isImg](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L63-L63) | boolean | false | 是否为图片模式 |
|
|
22
|
+
| [border](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L64-L64) | boolean | true | 是否显示下边框 |
|
|
23
|
+
| [marginTop](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L65-L65) | string | '20px' | 上边距 |
|
|
24
|
+
| [types](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L66-L66) | string | 'add' | 组件类型,'add' 为添加模式,'detail' 为详情模式 |
|
|
25
|
+
| [required](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L67-L67) | boolean | false | 是否必填 |
|
|
26
|
+
| [label](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L68-L68) | string | - | 标签文本 |
|
|
27
|
+
| [isLink](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L59-L59) | boolean | false | 是否为链接模式 |
|
|
28
|
+
| [baseUrl](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L60-L60) | string | '' | 基础URL |
|
|
29
|
+
| [apiUrl](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L61-L61) | string | '' | API上传地址 |
|
|
30
|
+
| [headers](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L62-L62) | object | {} | 上传请求头 |
|
|
31
|
+
|
|
32
|
+
## 事件 (Events)
|
|
33
|
+
|
|
34
|
+
| 事件名 | 参数 | 说明 |
|
|
35
|
+
|-------|------|------|
|
|
36
|
+
| update:modelValue | (value: any[]) | 当文件列表发生变化时触发 |
|
|
37
|
+
|
|
38
|
+
## 使用示例
|
|
39
|
+
|
|
40
|
+
### 图片上传模式
|
|
41
|
+
|
|
42
|
+
```vue
|
|
43
|
+
<template>
|
|
44
|
+
<HwFileUpload
|
|
45
|
+
v-model="imageList"
|
|
46
|
+
label="图片上传"
|
|
47
|
+
:isImg="true"
|
|
48
|
+
:fileType="['jpg', 'jpeg', 'png', 'gif']"
|
|
49
|
+
:required="true"
|
|
50
|
+
apiUrl="/api/upload"
|
|
51
|
+
:headers="headers"
|
|
52
|
+
/>
|
|
53
|
+
</template>
|
|
54
|
+
|
|
55
|
+
<script setup>
|
|
56
|
+
import { ref } from 'vue';
|
|
57
|
+
import HwFileUpload from '@/components/HwFileUpload/HwFileUpload.vue';
|
|
58
|
+
|
|
59
|
+
const imageList = ref([]);
|
|
60
|
+
const headers = { 'Authorization': 'Bearer token' };
|
|
61
|
+
</script>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 文件上传模式
|
|
65
|
+
|
|
66
|
+
```vue
|
|
67
|
+
<template>
|
|
68
|
+
<HwFileUpload
|
|
69
|
+
v-model="fileList"
|
|
70
|
+
label="附件上传"
|
|
71
|
+
:isImg="false"
|
|
72
|
+
:fileType="['pdf', 'doc', 'docx', 'xlsx']"
|
|
73
|
+
:required="true"
|
|
74
|
+
apiUrl="/api/upload"
|
|
75
|
+
:headers="headers"
|
|
76
|
+
/>
|
|
77
|
+
</template>
|
|
78
|
+
|
|
79
|
+
<script setup>
|
|
80
|
+
import { ref } from 'vue';
|
|
81
|
+
import HwFileUpload from '@/components/HwFileUpload/HwFileUpload.vue';
|
|
82
|
+
|
|
83
|
+
const fileList = ref([]);
|
|
84
|
+
const headers = { 'Authorization': 'Bearer token' };
|
|
85
|
+
</script>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 详情模式(只读)
|
|
89
|
+
|
|
90
|
+
```vue
|
|
91
|
+
<template>
|
|
92
|
+
<HwFileUpload
|
|
93
|
+
v-model="fileList"
|
|
94
|
+
label="附件列表"
|
|
95
|
+
:isImg="false"
|
|
96
|
+
types="detail"
|
|
97
|
+
:required="false"
|
|
98
|
+
/>
|
|
99
|
+
</template>
|
|
100
|
+
|
|
101
|
+
<script setup>
|
|
102
|
+
import { ref } from 'vue';
|
|
103
|
+
import HwFileUpload from '@/components/HwFileUpload/HwFileUpload.vue';
|
|
104
|
+
|
|
105
|
+
const fileList = ref([
|
|
106
|
+
{ name: 'example.pdf', url: '/path/to/example.pdf' },
|
|
107
|
+
{ name: 'document.docx', url: '/path/to/document.docx' }
|
|
108
|
+
]);
|
|
109
|
+
</script>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## 注意事项
|
|
113
|
+
|
|
114
|
+
1. 上传功能需要配置 [apiUrl](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L61-L61) 和 [baseUrl](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L60-L60) 属性
|
|
115
|
+
2. 文件类型限制通过 [fileType](file:///e:/temp/my-components/src/components/HwFileUpload/HwFileUpload.vue#L54-L54) 属性控制
|
|
116
|
+
3. 在详情模式下,组件只显示文件列表,不提供上传、删除等操作
|
|
117
|
+
4. 文件大小显示单位为KB
|
|
118
|
+
5. 图片上传使用 [uni.previewImage](file:///e:/temp/my-components/node_modules/@dcloudio/uni-app-plus/types/index.d.ts#L210-L216) 进行预览
|
|
119
|
+
6. 文件下载使用 [file-saver](file:///e:/temp/my-components/package.json#L24-L24) 库实现
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# HwInput 组件使用说明
|
|
2
|
+
|
|
3
|
+
HwInput 是一个输入框组件,支持编辑模式和详情模式,可以显示输入框或只读文本。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- 支持编辑模式和详情模式
|
|
8
|
+
- 支持双向数据绑定
|
|
9
|
+
- 支持自定义样式
|
|
10
|
+
- 支持必填标识显示
|
|
11
|
+
- 支持子值显示
|
|
12
|
+
|
|
13
|
+
## 属性 (Props)
|
|
14
|
+
|
|
15
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
16
|
+
|------|------|--------|------|
|
|
17
|
+
| [marginTop](file:///e:/temp/my-components/src/components/HwInput/HwInput.vue#L42-L42) | string | '20px' | 上边距 |
|
|
18
|
+
| [types](file:///e:/temp/my-components/src/components/HwInput/HwInput.vue#L43-L43) | string | 'add' | 组件类型,'add'为编辑模式,'detail'为详情模式 |
|
|
19
|
+
| [subValue](file:///e:/temp/my-components/src/components/HwInput/HwInput.vue#L44-L44) | string | '' | 子值,在详情模式下额外显示的信息 |
|
|
20
|
+
| [styles](file:///e:/temp/my-components/src/components/HwInput/HwInput.vue#L45-L45) | object | {} | 自定义样式对象 |
|
|
21
|
+
| [required](file:///e:/temp/my-components/src/components/HwInput/HwInput.vue#L46-L46) | boolean | false | 是否必填,为true时显示红色星号 |
|
|
22
|
+
| [borderBottom](file:///e:/temp/my-components/src/components/HwInput/HwInput.vue#L47-L47) | string | '1rpx solid rgba(17, 31, 44, 0.12)' | 设置下边框 |
|
|
23
|
+
| [label](file:///e:/temp/my-components/src/components/HwInput/HwInput.vue#L48-L48) | string | - | 标签文本,必填项 |
|
|
24
|
+
|
|
25
|
+
## 事件 (Events)
|
|
26
|
+
|
|
27
|
+
| 事件名 | 参数 | 说明 |
|
|
28
|
+
|-------|------|------|
|
|
29
|
+
| update:modelValue | (value: string \| number) | 当值变化时触发 |
|
|
30
|
+
|
|
31
|
+
## 使用示例
|
|
32
|
+
|
|
33
|
+
### 基础用法
|
|
34
|
+
|
|
35
|
+
```vue
|
|
36
|
+
<template>
|
|
37
|
+
<HwInput
|
|
38
|
+
v-model="inputValue"
|
|
39
|
+
label="姓名"
|
|
40
|
+
/>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<script setup>
|
|
44
|
+
import { ref } from 'vue';
|
|
45
|
+
import HwInput from '@/components/HwInput/HwInput.vue';
|
|
46
|
+
|
|
47
|
+
const inputValue = ref('');
|
|
48
|
+
</script>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 详情模式
|
|
52
|
+
|
|
53
|
+
```vue
|
|
54
|
+
<template>
|
|
55
|
+
<HwInput
|
|
56
|
+
v-model="inputValue"
|
|
57
|
+
label="姓名"
|
|
58
|
+
types="detail"
|
|
59
|
+
/>
|
|
60
|
+
</template>
|
|
61
|
+
|
|
62
|
+
<script setup>
|
|
63
|
+
import { ref } from 'vue';
|
|
64
|
+
import HwInput from '@/components/HwInput/HwInput.vue';
|
|
65
|
+
|
|
66
|
+
const inputValue = ref('张三');
|
|
67
|
+
</script>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 必填项
|
|
71
|
+
|
|
72
|
+
```vue
|
|
73
|
+
<template>
|
|
74
|
+
<HwInput
|
|
75
|
+
v-model="inputValue"
|
|
76
|
+
label="邮箱"
|
|
77
|
+
:required="true"
|
|
78
|
+
/>
|
|
79
|
+
</template>
|
|
80
|
+
|
|
81
|
+
<script setup>
|
|
82
|
+
import { ref } from 'vue';
|
|
83
|
+
import HwInput from '@/components/HwInput/HwInput.vue';
|
|
84
|
+
|
|
85
|
+
const inputValue = ref('');
|
|
86
|
+
</script>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 带子值的详情模式
|
|
90
|
+
|
|
91
|
+
```vue
|
|
92
|
+
<template>
|
|
93
|
+
<HwInput
|
|
94
|
+
v-model="inputValue"
|
|
95
|
+
label="价格"
|
|
96
|
+
types="detail"
|
|
97
|
+
subValue="元"
|
|
98
|
+
/>
|
|
99
|
+
</template>
|
|
100
|
+
|
|
101
|
+
<script setup>
|
|
102
|
+
import { ref } from 'vue';
|
|
103
|
+
import HwInput from '@/components/HwInput/HwInput.vue';
|
|
104
|
+
|
|
105
|
+
const inputValue = ref('100');
|
|
106
|
+
</script>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 自定义样式
|
|
110
|
+
|
|
111
|
+
```vue
|
|
112
|
+
<template>
|
|
113
|
+
<HwInput
|
|
114
|
+
v-model="inputValue"
|
|
115
|
+
label="描述"
|
|
116
|
+
:styles="{ color: 'blue', fontSize: '36rpx' }"
|
|
117
|
+
/>
|
|
118
|
+
</template>
|
|
119
|
+
|
|
120
|
+
<script setup>
|
|
121
|
+
import { ref } from 'vue';
|
|
122
|
+
import HwInput from '@/components/HwInput/HwInput.vue';
|
|
123
|
+
|
|
124
|
+
const inputValue = ref('');
|
|
125
|
+
</script>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 注意事项
|
|
129
|
+
|
|
130
|
+
1. 组件使用了 uni-easyinput 作为基础组件
|
|
131
|
+
2. 在详情模式下,组件只显示值,不提供编辑功能
|
|
132
|
+
3. [types](file:///e:/temp/my-components/src/components/HwInput/HwInput.vue#L43-L43) 设置为 'detail' 时会显示为只读的详情模式
|
|
133
|
+
4. 如果 [value](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L35-L40) 为空,在详情模式下会显示为 '-'
|
|
134
|
+
5. [subValue](file:///e:/temp/my-components/src/components/HwInput/HwInput.vue#L44-L44) 只在详情模式下且有值时显示
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
@click="_show"
|
|
5
5
|
v-if="isShowLabel"
|
|
6
6
|
class="label"
|
|
7
|
-
:style="{ color: curLabel ? 'rgba(23, 26, 29, 1)' : 'rgba(23, 26, 29, 0.4)' }"
|
|
7
|
+
:style="{ color: curLabel ? 'rgba(23, 26, 29, 1)' : 'rgba(23, 26, 29, 0.4)' }"
|
|
8
|
+
>
|
|
8
9
|
<slot name="title" :data="{ curLabel, placeholder }">
|
|
9
10
|
<view class="text">{{ curLabel ? curLabel : placeholder }}</view>
|
|
10
11
|
<view class="triangle"></view>
|
|
@@ -14,57 +15,76 @@
|
|
|
14
15
|
<view class="tki-tree-mask" :class="{ show: showTree }" @tap="_cancel" />
|
|
15
16
|
<view class="tki-tree-cnt" :class="{ show: showTree }">
|
|
16
17
|
<view class="tki-tree-bar">
|
|
17
|
-
<view class="tki-tree-bar-cancel" :style="{ color: cancelColor }" hover-class="hover-c" @tap="_cancel"
|
|
18
|
-
|
|
18
|
+
<view class="tki-tree-bar-cancel" :style="{ color: cancelColor }" hover-class="hover-c" @tap="_cancel">
|
|
19
|
+
取消
|
|
19
20
|
</view>
|
|
20
21
|
<view class="tki-tree-bar-title" :style="{ color: titleColor }">{{ title }}</view>
|
|
21
|
-
<view class="tki-tree-bar-confirm" :style="{ color: confirmColor }" hover-class="hover-c" @tap="_confirm"
|
|
22
|
-
|
|
23
|
-
>
|
|
22
|
+
<view class="tki-tree-bar-confirm" :style="{ color: confirmColor }" hover-class="hover-c" @tap="_confirm">
|
|
23
|
+
确定
|
|
24
|
+
</view>
|
|
24
25
|
</view>
|
|
26
|
+
|
|
25
27
|
<view class="tki-tree-view">
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
open: item.open,
|
|
41
|
-
}">
|
|
42
|
-
<view class="tki-tree-label" @tap.stop="_treeItemTap(item, index)">
|
|
43
|
-
<image
|
|
44
|
-
class="tki-tree-icon"
|
|
45
|
-
:src="item.lastRank ? lastIcon : item.showChild ? currentIcon : defaultIcon" />
|
|
46
|
-
{{ item.name }}
|
|
47
|
-
</view>
|
|
28
|
+
<uni-easyinput
|
|
29
|
+
v-if="isSearch"
|
|
30
|
+
class="search-input"
|
|
31
|
+
:styles="{
|
|
32
|
+
backgroundColor: 'rgba(126, 134, 142, 0.16)'
|
|
33
|
+
}"
|
|
34
|
+
prefixIcon="search"
|
|
35
|
+
placeholder="请输入"
|
|
36
|
+
v-model="searchName"
|
|
37
|
+
@input="changeSelect"
|
|
38
|
+
/>
|
|
39
|
+
<view class="tki-tree-view-sc" :scroll-y="true">
|
|
40
|
+
<z-paging ref="paging" :fixed="false" v-model="dataList" @query="queryList">
|
|
41
|
+
<block v-for="(item, index) in treeList" :key="index">
|
|
48
42
|
<view
|
|
49
|
-
class="tki-tree-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
43
|
+
class="tki-tree-item"
|
|
44
|
+
:style="[
|
|
45
|
+
{
|
|
46
|
+
paddingLeft: item.rank * 15 + 'px',
|
|
47
|
+
zIndex: item.rank * -1 + 50
|
|
48
|
+
}
|
|
49
|
+
]"
|
|
50
|
+
:class="{
|
|
51
|
+
show: item.show,
|
|
52
|
+
last: item.lastRank,
|
|
53
|
+
showchild: item.showChild,
|
|
54
|
+
open: item.open
|
|
55
|
+
}"
|
|
56
|
+
>
|
|
57
|
+
<view class="tki-tree-label" @tap.stop="_treeItemTap(item, index)">
|
|
58
|
+
<image
|
|
59
|
+
class="tki-tree-icon"
|
|
60
|
+
:src="item.lastRank ? lastIcon : item.showChild ? currentIcon : defaultIcon"
|
|
61
|
+
/>
|
|
62
|
+
{{ item.name }}
|
|
58
63
|
</view>
|
|
59
64
|
<view
|
|
60
|
-
class="tki-tree-check
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
class="tki-tree-check"
|
|
66
|
+
@tap.stop="_treeItemSelect(item, index)"
|
|
67
|
+
v-if="selectParent ? true : item.lastRank"
|
|
68
|
+
>
|
|
69
|
+
<view
|
|
70
|
+
class="tki-tree-check-yes"
|
|
71
|
+
v-if="item.checked"
|
|
72
|
+
:class="{ radio: !multiple }"
|
|
73
|
+
:style="{ 'border-color': confirmColor }"
|
|
74
|
+
>
|
|
75
|
+
<view class="tki-tree-check-yes-b" :style="{ color: confirmColor }" />
|
|
76
|
+
</view>
|
|
77
|
+
<view
|
|
78
|
+
class="tki-tree-check-no"
|
|
79
|
+
v-else
|
|
80
|
+
:class="{ radio: !multiple }"
|
|
81
|
+
:style="{ 'border-color': confirmColor }"
|
|
82
|
+
/>
|
|
83
|
+
</view>
|
|
64
84
|
</view>
|
|
65
|
-
</
|
|
66
|
-
</
|
|
67
|
-
</
|
|
85
|
+
</block>
|
|
86
|
+
</z-paging>
|
|
87
|
+
</view>
|
|
68
88
|
</view>
|
|
69
89
|
</view>
|
|
70
90
|
</view>
|
|
@@ -78,119 +98,160 @@ const props = defineProps({
|
|
|
78
98
|
type: Array,
|
|
79
99
|
default: function () {
|
|
80
100
|
return [];
|
|
81
|
-
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
rangeNext: {
|
|
104
|
+
type: Array,
|
|
105
|
+
default: function () {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
request: {
|
|
110
|
+
type: Function,
|
|
111
|
+
default: function () {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
82
114
|
},
|
|
83
115
|
idKey: {
|
|
84
116
|
//字段key值
|
|
85
117
|
type: String,
|
|
86
|
-
default: 'id'
|
|
118
|
+
default: 'id'
|
|
87
119
|
},
|
|
88
120
|
// 字符串或者字符串数组
|
|
89
121
|
modelValue: {
|
|
90
122
|
type: String,
|
|
91
|
-
default: ''
|
|
123
|
+
default: ''
|
|
92
124
|
},
|
|
93
125
|
nameKey: {
|
|
94
126
|
//字段value值
|
|
95
127
|
type: String,
|
|
96
|
-
default: 'name'
|
|
128
|
+
default: 'name'
|
|
97
129
|
},
|
|
98
130
|
allKey: {
|
|
99
131
|
//冗余字段
|
|
100
132
|
type: String,
|
|
101
|
-
default: 'value'
|
|
133
|
+
default: 'value'
|
|
102
134
|
},
|
|
103
135
|
placeholder: {
|
|
104
136
|
//冗余字段
|
|
105
137
|
type: String,
|
|
106
|
-
default: '请选择'
|
|
138
|
+
default: '请选择'
|
|
107
139
|
},
|
|
108
140
|
title: {
|
|
109
141
|
//头
|
|
110
142
|
type: String,
|
|
111
|
-
default: ''
|
|
143
|
+
default: ''
|
|
112
144
|
},
|
|
113
145
|
multiple: {
|
|
114
146
|
// 是否可以多选
|
|
115
147
|
type: Boolean,
|
|
116
|
-
default: true
|
|
148
|
+
default: true
|
|
117
149
|
// default: true
|
|
118
150
|
},
|
|
151
|
+
isSearch: {
|
|
152
|
+
type: Boolean,
|
|
153
|
+
default: false
|
|
154
|
+
},
|
|
119
155
|
disabled: {
|
|
120
156
|
// 是否禁用
|
|
121
157
|
type: Boolean,
|
|
122
|
-
default: false
|
|
158
|
+
default: false
|
|
123
159
|
},
|
|
124
160
|
cascade: {
|
|
125
161
|
// 是否级联选择
|
|
126
162
|
type: Boolean,
|
|
127
|
-
default: false
|
|
163
|
+
default: false
|
|
128
164
|
// default: true
|
|
129
165
|
},
|
|
130
166
|
isShowLabel: {
|
|
131
167
|
// 是否显示标题
|
|
132
168
|
type: Boolean,
|
|
133
|
-
default: true
|
|
169
|
+
default: true
|
|
134
170
|
},
|
|
135
171
|
selectParent: {
|
|
136
172
|
//是否可以选父级
|
|
137
173
|
type: Boolean,
|
|
138
|
-
default: true
|
|
174
|
+
default: true
|
|
139
175
|
},
|
|
140
176
|
foldAll: {
|
|
141
177
|
//折叠时关闭所有已经打开的子集,再次打开时需要一级一级打开
|
|
142
178
|
type: Boolean,
|
|
143
|
-
default: false
|
|
179
|
+
default: false
|
|
144
180
|
},
|
|
145
181
|
confirmColor: {
|
|
146
182
|
// 确定按钮颜色
|
|
147
183
|
type: String,
|
|
148
|
-
default: '#007aff'
|
|
184
|
+
default: '#007aff' // #1facac
|
|
149
185
|
},
|
|
150
186
|
cancelColor: {
|
|
151
187
|
// 取消按钮颜色
|
|
152
188
|
type: String,
|
|
153
|
-
default: '#757575'
|
|
189
|
+
default: '#757575' // #757575
|
|
154
190
|
},
|
|
155
191
|
titleColor: {
|
|
156
192
|
// 标题颜色
|
|
157
193
|
type: String,
|
|
158
|
-
default: '#757575'
|
|
194
|
+
default: '#757575' // #757575
|
|
159
195
|
},
|
|
160
196
|
currentIcon: {
|
|
161
197
|
// 展开时候的ic
|
|
162
198
|
type: String,
|
|
163
199
|
default:
|
|
164
|
-
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAABRCAYAAACqj0o2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MEQ0QTM0MzQ1Q0RBMTFFOUE0MjY4NzI1Njc1RjI1ODIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MEQ0QTM0MzU1Q0RBMTFFOUE0MjY4NzI1Njc1RjI1ODIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowRDRBMzQzMjVDREExMUU5QTQyNjg3MjU2NzVGMjU4MiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowRDRBMzQzMzVDREExMUU5QTQyNjg3MjU2NzVGMjU4MiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PidwepsAAAK0SURBVHja7JxbTsJAFIYHww7ciStgCeoGvGxAiOsgURegoL5720AXYLiIr0aJviq3Zx3PhIEnKG3ndtr+f3KixrSUj/ZjzjClIqUUiFm2gAAQAREQEUAEREAERAQQAREQAREBREAEREBEEqa67h9RFDWllDv0awWYlqlQHmu1WjMRRMoV1QFttA12y3xRtdNczq8EsE4/f8FumX2q77ROvNXk8UGMEKdUz6tYJHljaZAbuyUH+UR1to5BEohTuqwPCeS4pAA/qY6o/kyHOAMCeRK3owJnj+rH1jjxhqpVsstaebCz6TmnHWyXyY+xHjSBWBY/bvSgadtXBj9u9KCN3rnIfkzkQVsTEEX0Y2IP2oKo/HhMICcFAThUcwVZNGU6FdbX/XURzkbVF4+ybGhjPrFdgP66QdXNurGtSdk6Xdb9nAJ8oDo3OQlsQZzkdPw41ONBo6vI5scDefRjZg+6gpg3Pxp50CXEvPjR2IOuIXL3oxUPuobI3Y9WPOgDIlc/WvOgL4iL/vqFCcD7LH0xB4hj7cfQ/fWH9qCT+FhG0tN+DBk1PzjOM0SVllixcsBT1AvYc/kAPhc0hRg/3uvxoCgKRN9+dOrBUBB9+9GpB0NC9OVH5x4MDdG1H714kANEV3705kEOEBf9dcPi/lQnsuvLg1wgSu3Ha0v7Uh4MMgUXeuG71H407a+VBy9CPQkOdw+MtB+nGbd/D+FBbhBNxo9SjwcngJjNj0E9yBFiFj8G9SBXiGn8GNyDnCEm8SMLD3KHGOdHNh7kDjHOj2w8mAeIi/5arX+c6b/fxHz9oADEdGdjR/fXCw/OOB5oVfCOgnepz8IB14PMw03jCmTE+QBx5z0gAmKSqK9OUF+hcAeIhu/QYr4Qie8rjW83hhMBERARQAREQAREBBABERCLnH8BBgA+TQI7U4t53AAAAABJRU5ErkJggg=='
|
|
200
|
+
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAABRCAYAAACqj0o2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MEQ0QTM0MzQ1Q0RBMTFFOUE0MjY4NzI1Njc1RjI1ODIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MEQ0QTM0MzU1Q0RBMTFFOUE0MjY4NzI1Njc1RjI1ODIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowRDRBMzQzMjVDREExMUU5QTQyNjg3MjU2NzVGMjU4MiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowRDRBMzQzMzVDREExMUU5QTQyNjg3MjU2NzVGMjU4MiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PidwepsAAAK0SURBVHja7JxbTsJAFIYHww7ciStgCeoGvGxAiOsgURegoL5720AXYLiIr0aJviq3Zx3PhIEnKG3ndtr+f3KixrSUj/ZjzjClIqUUiFm2gAAQAREQEUAEREAERAQQAREQAREBREAEREBEEqa67h9RFDWllDv0awWYlqlQHmu1WjMRRMoV1QFttA12y3xRtdNczq8EsE4/f8FumX2q77ROvNXk8UGMEKdUz6tYJHljaZAbuyUH+UR1to5BEohTuqwPCeS4pAA/qY6o/kyHOAMCeRK3owJnj+rH1jjxhqpVsstaebCz6TmnHWyXyY+xHjSBWBY/bvSgadtXBj9u9KCN3rnIfkzkQVsTEEX0Y2IP2oKo/HhMICcFAThUcwVZNGU6FdbX/XURzkbVF4+ybGhjPrFdgP66QdXNurGtSdk6Xdb9nAJ8oDo3OQlsQZzkdPw41ONBo6vI5scDefRjZg+6gpg3Pxp50CXEvPjR2IOuIXL3oxUPuobI3Y9WPOgDIlc/WvOgL4iL/vqFCcD7LH0xB4hj7cfQ/fWH9qCT+FhG0tN+DBk1PzjOM0SVllixcsBT1AvYc/kAPhc0hRg/3uvxoCgKRN9+dOrBUBB9+9GpB0NC9OVH5x4MDdG1H714kANEV3705kEOEBf9dcPi/lQnsuvLg1wgSu3Ha0v7Uh4MMgUXeuG71H407a+VBy9CPQkOdw+MtB+nGbd/D+FBbhBNxo9SjwcngJjNj0E9yBFiFj8G9SBXiGn8GNyDnCEm8SMLD3KHGOdHNh7kDjHOj2w8mAeIi/5arX+c6b/fxHz9oADEdGdjR/fXCw/OOB5oVfCOgnepz8IB14PMw03jCmTE+QBx5z0gAmKSqK9OUF+hcAeIhu/QYr4Qie8rjW83hhMBERARQAREQAREBBABERCLnH8BBgA+TQI7U4t53AAAAABJRU5ErkJggg=='
|
|
165
201
|
},
|
|
166
202
|
defaultIcon: {
|
|
167
203
|
// 折叠时候的ic
|
|
168
204
|
type: String,
|
|
169
205
|
default:
|
|
170
|
-
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAABRCAYAAACqj0o2AAACE0lEQVR4Xu3c200DMRCF4XEltJAOkEugA+ggpUAHoQMqiFMCdEAJUMEiS4mEELlIO7bPOeN9i6K1rG/952myyea1WiCtXmEuYBPR4RBMxInoIOCwhOtJLKVszWyXc/5y2BvNEq6I+/3+kFK6M7OHnPM7jcLKjbZAvD/uaZtzflm5P4rbWyJWgDcze1LPuzVihfxUz7sH4ilJ2bx7Isrm3RtRMu8RiHJ5j0SUyXs0okTeCIj0eSMh0uaNhkiZNyIiXd7IiDR5oyNS5M2ACJ83EyJs3myIkHkzIsLlzYwIkzc7IkTeCojD81ZCHJa3GuKQvBURu+etjNgtb3XELnlHQGyedyTEZnlHQ2ySd0RE97wjI7rlHR3RJe+JeIrbLOecD6ePpZQ6W1kn2epo4MUrPOKyLN8ppYq1+y1VStncOjIdGnFZlo+U0uOtWOeOY2TE12Ouq//pEA7xXL7XfvcufR8K0Svfv6CREN3yDYfYIt9QiK3yjYTYLF95xB75SiP2ylcZsVu+cogj8pVCHJWvEuKwfOkREfKlRkTJlxkRJl86RMR8qRBR82VChM0XHpEhX2hElnyREWnyhUNkzBcKkTVfJETafIcjKuQ7FFEl35GIMvl2R1TMtyuiar49EWXzbY5oZpv/hibXTF2h3+s60FRKeT6+3TjMS3nrA3ZFRD8xrfY3ER1kJ+JEdBBwWGKeRAfEH1wS5WFZSDB/AAAAAElFTkSuQmCC'
|
|
206
|
+
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAABRCAYAAACqj0o2AAACE0lEQVR4Xu3c200DMRCF4XEltJAOkEugA+ggpUAHoQMqiFMCdEAJUMEiS4mEELlIO7bPOeN9i6K1rG/952myyea1WiCtXmEuYBPR4RBMxInoIOCwhOtJLKVszWyXc/5y2BvNEq6I+/3+kFK6M7OHnPM7jcLKjbZAvD/uaZtzflm5P4rbWyJWgDcze1LPuzVihfxUz7sH4ilJ2bx7Isrm3RtRMu8RiHJ5j0SUyXs0okTeCIj0eSMh0uaNhkiZNyIiXd7IiDR5oyNS5M2ACJ83EyJs3myIkHkzIsLlzYwIkzc7IkTeCojD81ZCHJa3GuKQvBURu+etjNgtb3XELnlHQGyedyTEZnlHQ2ySd0RE97wjI7rlHR3RJe+JeIrbLOecD6ePpZQ6W1kn2epo4MUrPOKyLN8ppYq1+y1VStncOjIdGnFZlo+U0uOtWOeOY2TE12Ouq//pEA7xXL7XfvcufR8K0Svfv6CREN3yDYfYIt9QiK3yjYTYLF95xB75SiP2ylcZsVu+cogj8pVCHJWvEuKwfOkREfKlRkTJlxkRJl86RMR8qRBR82VChM0XHpEhX2hElnyREWnyhUNkzBcKkTVfJETafIcjKuQ7FFEl35GIMvl2R1TMtyuiar49EWXzbY5oZpv/hibXTF2h3+s60FRKeT6+3TjMS3nrA3ZFRD8xrfY3ER1kJ+JEdBBwWGKeRAfEH1wS5WFZSDB/AAAAAElFTkSuQmCC'
|
|
171
207
|
},
|
|
172
208
|
lastIcon: {
|
|
173
209
|
// 没有子集的ic
|
|
174
210
|
type: String,
|
|
175
|
-
default: ''
|
|
176
|
-
}
|
|
211
|
+
default: ''
|
|
212
|
+
}
|
|
177
213
|
});
|
|
178
214
|
|
|
179
215
|
const emit = defineEmits(['cancel', 'confirm', 'update:modelValue']);
|
|
180
216
|
|
|
181
217
|
defineExpose({
|
|
182
218
|
_show,
|
|
183
|
-
_hide
|
|
219
|
+
_hide
|
|
184
220
|
});
|
|
221
|
+
const paging = ref(null);
|
|
185
222
|
|
|
186
223
|
const showTree = ref(false);
|
|
224
|
+
const dataList = ref([]);
|
|
225
|
+
const searchName = ref('');
|
|
187
226
|
const treeList = ref([]);
|
|
188
227
|
const returnedItem = ref([]);
|
|
189
228
|
const childNums = ref([]);
|
|
190
|
-
const curLabel =
|
|
229
|
+
const curLabel = defineModel('label', { default: '', type: String });
|
|
191
230
|
|
|
192
231
|
let val = [];
|
|
232
|
+
let temporarySelectedValue = [];
|
|
193
233
|
let label = [];
|
|
234
|
+
let originalTreeList = []; // 保存原始数据
|
|
235
|
+
|
|
236
|
+
const changeSelect = (val) => {
|
|
237
|
+
// 如果没有输入搜索内容,则恢复原始列表
|
|
238
|
+
if (props.request) {
|
|
239
|
+
paging.value && paging.value.reload();
|
|
240
|
+
} else {
|
|
241
|
+
if (!val) {
|
|
242
|
+
treeList.value = JSON.parse(JSON.stringify(originalTreeList));
|
|
243
|
+
// 确保所有节点都正确显示
|
|
244
|
+
treeList.value.forEach((item) => {
|
|
245
|
+
item.show = item.rank === 0 || item.show; // 根节点或原来就显示的节点
|
|
246
|
+
});
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
treeList.value = originalTreeList.filter(
|
|
251
|
+
(item) => item.name && item.name.toLowerCase().includes(val.toLowerCase())
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
194
255
|
|
|
195
256
|
/**
|
|
196
257
|
* 监听范围数据变化,重新初始化树结构
|
|
@@ -198,8 +259,29 @@ let label = [];
|
|
|
198
259
|
watch(
|
|
199
260
|
() => props.range,
|
|
200
261
|
(newVal) => {
|
|
201
|
-
|
|
202
|
-
|
|
262
|
+
if (!props.request) {
|
|
263
|
+
_initTree(newVal);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
);
|
|
267
|
+
watch(
|
|
268
|
+
() => dataList.value,
|
|
269
|
+
(newVal) => {
|
|
270
|
+
if (props.request) {
|
|
271
|
+
const data = newVal.map((item) => {
|
|
272
|
+
return {
|
|
273
|
+
...item,
|
|
274
|
+
label: item.resourceC,
|
|
275
|
+
value: item.resourceC
|
|
276
|
+
};
|
|
277
|
+
});
|
|
278
|
+
if (searchName.value) {
|
|
279
|
+
_initTree([...data]);
|
|
280
|
+
} else {
|
|
281
|
+
_initTree([...props.rangeNext, ...data]);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
203
285
|
);
|
|
204
286
|
/**
|
|
205
287
|
* 监听多选属性变化,重新设置树列表
|
|
@@ -208,7 +290,7 @@ watch(
|
|
|
208
290
|
() => props.multiple,
|
|
209
291
|
() => {
|
|
210
292
|
_reTreeList();
|
|
211
|
-
}
|
|
293
|
+
}
|
|
212
294
|
);
|
|
213
295
|
/**
|
|
214
296
|
* 监听父级选择属性变化,重新设置树列表
|
|
@@ -217,7 +299,7 @@ watch(
|
|
|
217
299
|
() => props.selectParent,
|
|
218
300
|
() => {
|
|
219
301
|
_reTreeList();
|
|
220
|
-
}
|
|
302
|
+
}
|
|
221
303
|
);
|
|
222
304
|
/**
|
|
223
305
|
* 监听模型值变化,处理默认选中项
|
|
@@ -225,24 +307,44 @@ watch(
|
|
|
225
307
|
watch(
|
|
226
308
|
() => props.modelValue,
|
|
227
309
|
(newVal) => {
|
|
228
|
-
if (newVal) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
310
|
+
if (!newVal) {
|
|
311
|
+
curLabel.value = '';
|
|
312
|
+
}
|
|
313
|
+
treeList.value = [];
|
|
314
|
+
val = [];
|
|
315
|
+
label = [];
|
|
316
|
+
if (props.request) {
|
|
317
|
+
paging.value && paging.value.reload();
|
|
318
|
+
} else {
|
|
232
319
|
_renderTreeList(props.range);
|
|
233
320
|
nextTick().then(() => {
|
|
234
321
|
_defaultSelect(props.range);
|
|
235
322
|
});
|
|
236
|
-
} else {
|
|
237
|
-
curLabel.value = '';
|
|
238
323
|
}
|
|
239
|
-
}
|
|
324
|
+
}
|
|
240
325
|
);
|
|
241
326
|
|
|
242
327
|
onMounted(() => {
|
|
243
|
-
|
|
328
|
+
if (!props.request) {
|
|
329
|
+
_initTree(newVal);
|
|
330
|
+
}
|
|
244
331
|
});
|
|
245
332
|
|
|
333
|
+
function queryList(pageNum, pageSize) {
|
|
334
|
+
props
|
|
335
|
+
.request({
|
|
336
|
+
pageSize,
|
|
337
|
+
pageNum,
|
|
338
|
+
resourceC: searchName.value
|
|
339
|
+
})
|
|
340
|
+
.then((res) => {
|
|
341
|
+
paging.value && paging.value.completeByTotal(res.rows || [], res?.total);
|
|
342
|
+
})
|
|
343
|
+
.catch(() => {
|
|
344
|
+
paging.value && paging.value.complete(false);
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
246
348
|
/**
|
|
247
349
|
* 显示树选择器
|
|
248
350
|
*/
|
|
@@ -255,6 +357,7 @@ function _show() {
|
|
|
255
357
|
* 隐藏树选择器
|
|
256
358
|
*/
|
|
257
359
|
function _hide() {
|
|
360
|
+
temporarySelectedValue = [];
|
|
258
361
|
showTree.value = false;
|
|
259
362
|
}
|
|
260
363
|
|
|
@@ -262,6 +365,16 @@ function _hide() {
|
|
|
262
365
|
* 取消选择操作
|
|
263
366
|
*/
|
|
264
367
|
function _cancel() {
|
|
368
|
+
if (!props.multiple) {
|
|
369
|
+
curLabel.value = '';
|
|
370
|
+
emit('update:modelValue', '');
|
|
371
|
+
emit('confirm', '');
|
|
372
|
+
} else {
|
|
373
|
+
val = val.filter((v) => !temporarySelectedValue.includes(v));
|
|
374
|
+
curLabel.value = val.join(',');
|
|
375
|
+
|
|
376
|
+
emit('update:modelValue', val);
|
|
377
|
+
}
|
|
265
378
|
_hide();
|
|
266
379
|
emit('cancel', []);
|
|
267
380
|
}
|
|
@@ -275,9 +388,10 @@ function _confirm() {
|
|
|
275
388
|
treeList.value.forEach((v, i) => {
|
|
276
389
|
if (treeList.value[i].checked) {
|
|
277
390
|
rt.push({
|
|
391
|
+
...treeList.value[i],
|
|
278
392
|
id: treeList.value[i].id,
|
|
279
393
|
name: treeList.value[i].name,
|
|
280
|
-
value: treeList.value[i].value
|
|
394
|
+
value: treeList.value[i].value
|
|
281
395
|
});
|
|
282
396
|
}
|
|
283
397
|
});
|
|
@@ -317,7 +431,11 @@ function _renderTreeList(list = [], rank = 0, parentId = [], parents = []) {
|
|
|
317
431
|
} else {
|
|
318
432
|
val = props.modelValue ? String(props.modelValue).split(',') : [];
|
|
319
433
|
}
|
|
434
|
+
val = [...val, ...temporarySelectedValue];
|
|
320
435
|
list.forEach((item) => {
|
|
436
|
+
if (label.includes(item[props.nameKey])) {
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
321
439
|
let checked = false;
|
|
322
440
|
if (val.includes(item[props.allKey]) || val.includes(item[props.nameKey])) {
|
|
323
441
|
checked = true;
|
|
@@ -337,7 +455,7 @@ function _renderTreeList(list = [], rank = 0, parentId = [], parents = []) {
|
|
|
337
455
|
hideArr: [],
|
|
338
456
|
orChecked: item.checked ? item.checked : false,
|
|
339
457
|
checked: checked,
|
|
340
|
-
childNum: 0
|
|
458
|
+
childNum: 0
|
|
341
459
|
});
|
|
342
460
|
|
|
343
461
|
if (Array.isArray(item.children) && item.children.length > 0) {
|
|
@@ -348,14 +466,14 @@ function _renderTreeList(list = [], rank = 0, parentId = [], parents = []) {
|
|
|
348
466
|
parentArr.push({
|
|
349
467
|
[props.idKey]: item[props.idKey],
|
|
350
468
|
[props.nameKey]: item[props.nameKey],
|
|
351
|
-
[props.allKey]: item[props.allKey]
|
|
469
|
+
[props.allKey]: item[props.allKey]
|
|
352
470
|
});
|
|
353
471
|
_renderTreeList(item.children, rank + 1, parentid, parentArr);
|
|
354
472
|
} else {
|
|
355
473
|
treeList.value[treeList.value.length - 1].lastRank = true;
|
|
356
474
|
}
|
|
357
475
|
});
|
|
358
|
-
|
|
476
|
+
originalTreeList = JSON.parse(JSON.stringify(treeList.value));
|
|
359
477
|
curLabel.value = label.join(',');
|
|
360
478
|
}
|
|
361
479
|
/**
|
|
@@ -460,7 +578,7 @@ function _treeItemTap(item, index) {
|
|
|
460
578
|
hideArr: [],
|
|
461
579
|
lastRank: itemC.children && itemC.children.length > 0 ? false : true,
|
|
462
580
|
orChecked: treeList.value[index].checked,
|
|
463
|
-
checked: props.cascade ? treeList.value[index].checked : false
|
|
581
|
+
checked: props.cascade ? treeList.value[index].checked : false
|
|
464
582
|
};
|
|
465
583
|
if (!treeList.value.some((itemT) => itemT.id === itemC[props.idKey])) {
|
|
466
584
|
treeList.value.splice(nextIndex + 1, 0, childObj);
|
|
@@ -565,6 +683,15 @@ function setAncestors(pids, checked) {
|
|
|
565
683
|
*/
|
|
566
684
|
function _treeItemSelect(item, index) {
|
|
567
685
|
treeList.value[index].checked = !treeList.value[index].checked;
|
|
686
|
+
|
|
687
|
+
if (treeList.value[index].checked) {
|
|
688
|
+
val = [...val, item.value];
|
|
689
|
+
temporarySelectedValue = [...temporarySelectedValue, item.value];
|
|
690
|
+
} else {
|
|
691
|
+
val = val.filter((v) => v !== item.value);
|
|
692
|
+
temporarySelectedValue = temporarySelectedValue.filter((v) => v !== item.value);
|
|
693
|
+
}
|
|
694
|
+
|
|
568
695
|
// 选父级, 子级自动全选
|
|
569
696
|
if (props.cascade) {
|
|
570
697
|
syncChecked(treeList.value, item.id, treeList.value[index].checked);
|
|
@@ -657,6 +784,7 @@ function _initTree(range = props.range) {
|
|
|
657
784
|
white-space: nowrap;
|
|
658
785
|
overflow: hidden;
|
|
659
786
|
text-overflow: ellipsis;
|
|
787
|
+
font-size: 34rpx;
|
|
660
788
|
width: calc(100% - 16rpx);
|
|
661
789
|
}
|
|
662
790
|
|
|
@@ -736,7 +864,7 @@ function _initTree(range = props.range) {
|
|
|
736
864
|
}
|
|
737
865
|
|
|
738
866
|
.tki-tree-view-sc {
|
|
739
|
-
height: 100
|
|
867
|
+
height: calc(100% - 70rpx);
|
|
740
868
|
overflow: hidden;
|
|
741
869
|
}
|
|
742
870
|
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# HwPickerTree 组件使用说明
|
|
2
|
+
|
|
3
|
+
HwPickerTree 是一个树形选择器组件,支持单选、多选、级联选择、搜索等功能,适用于复杂的层级数据选择场景。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- 支持单选和多选模式
|
|
8
|
+
- 支持级联选择
|
|
9
|
+
- 支持搜索功能
|
|
10
|
+
- 支持选择父级节点
|
|
11
|
+
- 支持自定义图标
|
|
12
|
+
- 支持异步数据加载
|
|
13
|
+
- 支持折叠/展开子节点
|
|
14
|
+
|
|
15
|
+
## 属性 (Props)
|
|
16
|
+
|
|
17
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
18
|
+
|------|------|--------|------|
|
|
19
|
+
| [range](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L14-L20) | Array | [] | 树形数据源 |
|
|
20
|
+
| [rangeNext](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L21-L27) | Array | [] | 额外的数据源(配合异步请求使用) |
|
|
21
|
+
| [request](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L28-L34) | Function | null | 异步请求函数 |
|
|
22
|
+
| [idKey](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L35-L40) | String | 'id' | 数据项的 ID 字段名 |
|
|
23
|
+
| [modelValue](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L43-L47) | String | '' | 绑定值 |
|
|
24
|
+
| [nameKey](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L48-L53) | String | 'name' | 数据项的名称字段名 |
|
|
25
|
+
| [allKey](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L54-L59) | String | 'value' | 数据项的值字段名 |
|
|
26
|
+
| [placeholder](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L60-L65) | String | '请选择' | 占位文本 |
|
|
27
|
+
| [title](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L66-L71) | String | '' | 选择器标题 |
|
|
28
|
+
| [multiple](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L72-L79) | Boolean | true | 是否多选 |
|
|
29
|
+
| [isSearch](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L80-L85) | Boolean | false | 是否显示搜索框 |
|
|
30
|
+
| [disabled](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L86-L91) | Boolean | false | 是否禁用 |
|
|
31
|
+
| [cascade](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L92-L99) | Boolean | false | 是否级联选择 |
|
|
32
|
+
| [isShowLabel](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L100-L105) | Boolean | true | 是否显示标签 |
|
|
33
|
+
| [selectParent](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L106-L111) | Boolean | true | 是否可以选择父级节点 |
|
|
34
|
+
| [foldAll](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L112-L117) | Boolean | false | 折叠时关闭所有子集 |
|
|
35
|
+
| [confirmColor](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L118-L123) | String | '#007aff' | 确认按钮颜色 |
|
|
36
|
+
| [cancelColor](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L124-L129) | String | '#757575' | 取消按钮颜色 |
|
|
37
|
+
| [titleColor](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L130-L135) | String | '#757575' | 标题颜色 |
|
|
38
|
+
| [currentIcon](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L136-L146) | String | 展开图标 | 展开时的图标 |
|
|
39
|
+
| [defaultIcon](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L147-L157) | String | 折叠图标 | 折叠时的图标 |
|
|
40
|
+
| [lastIcon](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L158-L163) | String | '' | 没有子集的图标 |
|
|
41
|
+
|
|
42
|
+
## 事件 (Events)
|
|
43
|
+
|
|
44
|
+
| 事件名 | 参数 | 说明 |
|
|
45
|
+
|-------|------|------|
|
|
46
|
+
| cancel | - | 取消选择时触发 |
|
|
47
|
+
| confirm | (selectedData: Array) | 确认选择时触发 |
|
|
48
|
+
| update:modelValue | (value: String/Array) | 值变化时触发 |
|
|
49
|
+
|
|
50
|
+
## 方法 (Methods)
|
|
51
|
+
|
|
52
|
+
| 方法名 | 参数 | 说明 |
|
|
53
|
+
|-------|------|------|
|
|
54
|
+
| _show | - | 显示选择器 |
|
|
55
|
+
| _hide | - | 隐藏选择器 |
|
|
56
|
+
|
|
57
|
+
## 使用示例
|
|
58
|
+
|
|
59
|
+
### 基础用法
|
|
60
|
+
|
|
61
|
+
```vue
|
|
62
|
+
<template>
|
|
63
|
+
<HwPickerTree
|
|
64
|
+
v-model="selectedValue"
|
|
65
|
+
:range="treeData"
|
|
66
|
+
placeholder="请选择"
|
|
67
|
+
title="选择节点"
|
|
68
|
+
/>
|
|
69
|
+
</template>
|
|
70
|
+
|
|
71
|
+
<script setup>
|
|
72
|
+
import { ref } from 'vue';
|
|
73
|
+
import HwPickerTree from '@/components/HwPickerTree/HwPickerTree.vue';
|
|
74
|
+
|
|
75
|
+
const selectedValue = ref('');
|
|
76
|
+
const treeData = ref([
|
|
77
|
+
{
|
|
78
|
+
id: 1,
|
|
79
|
+
name: '节点1',
|
|
80
|
+
value: 'node1',
|
|
81
|
+
children: [
|
|
82
|
+
{
|
|
83
|
+
id: 11,
|
|
84
|
+
name: '子节点1-1',
|
|
85
|
+
value: 'node1-1'
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: 12,
|
|
89
|
+
name: '子节点1-2',
|
|
90
|
+
value: 'node1-2'
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
id: 2,
|
|
96
|
+
name: '节点2',
|
|
97
|
+
value: 'node2'
|
|
98
|
+
}
|
|
99
|
+
]);
|
|
100
|
+
</script>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 多选模式
|
|
104
|
+
|
|
105
|
+
```vue
|
|
106
|
+
<template>
|
|
107
|
+
<HwPickerTree
|
|
108
|
+
v-model="selectedValue"
|
|
109
|
+
:range="treeData"
|
|
110
|
+
:multiple="true"
|
|
111
|
+
placeholder="请选择"
|
|
112
|
+
title="多选节点"
|
|
113
|
+
/>
|
|
114
|
+
</template>
|
|
115
|
+
|
|
116
|
+
<script setup>
|
|
117
|
+
import { ref } from 'vue';
|
|
118
|
+
import HwPickerTree from '@/components/HwPickerTree/HwPickerTree.vue';
|
|
119
|
+
|
|
120
|
+
const selectedValue = ref([]);
|
|
121
|
+
const treeData = ref([
|
|
122
|
+
// ... 同上
|
|
123
|
+
]);
|
|
124
|
+
</script>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### 级联选择
|
|
128
|
+
|
|
129
|
+
```vue
|
|
130
|
+
<template>
|
|
131
|
+
<HwPickerTree
|
|
132
|
+
v-model="selectedValue"
|
|
133
|
+
:range="treeData"
|
|
134
|
+
:multiple="true"
|
|
135
|
+
:cascade="true"
|
|
136
|
+
placeholder="请选择"
|
|
137
|
+
title="级联选择"
|
|
138
|
+
/>
|
|
139
|
+
</template>
|
|
140
|
+
|
|
141
|
+
<script setup>
|
|
142
|
+
import { ref } from 'vue';
|
|
143
|
+
import HwPickerTree from '@/components/HwPickerTree/HwPickerTree.vue';
|
|
144
|
+
|
|
145
|
+
const selectedValue = ref([]);
|
|
146
|
+
const treeData = ref([
|
|
147
|
+
// ... 同上
|
|
148
|
+
]);
|
|
149
|
+
</script>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 异步数据加载
|
|
153
|
+
|
|
154
|
+
```vue
|
|
155
|
+
<template>
|
|
156
|
+
<HwPickerTree
|
|
157
|
+
:request="fetchData"
|
|
158
|
+
placeholder="请选择"
|
|
159
|
+
title="异步数据"
|
|
160
|
+
/>
|
|
161
|
+
</template>
|
|
162
|
+
|
|
163
|
+
<script setup>
|
|
164
|
+
import { ref } from 'vue';
|
|
165
|
+
import HwPickerTree from '@/components/HwPickerTree/HwPickerTree.vue';
|
|
166
|
+
|
|
167
|
+
const fetchData = (params) => {
|
|
168
|
+
// 返回一个Promise
|
|
169
|
+
return new Promise((resolve) => {
|
|
170
|
+
setTimeout(() => {
|
|
171
|
+
resolve({
|
|
172
|
+
rows: [
|
|
173
|
+
{ id: 1, name: '选项1', value: 'value1' },
|
|
174
|
+
{ id: 2, name: '选项2', value: 'value2' }
|
|
175
|
+
],
|
|
176
|
+
total: 2
|
|
177
|
+
});
|
|
178
|
+
}, 1000);
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
</script>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 注意事项
|
|
185
|
+
|
|
186
|
+
1. 树形数据结构需要遵循 `{ id: '唯一标识', name: '显示名称', value: '值', children: [子节点数组] }` 的格式
|
|
187
|
+
2. 当使用异步数据加载时,需要提供 [request](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L28-L34) 函数
|
|
188
|
+
3. 级联选择模式下,选择父节点会自动选择所有子节点
|
|
189
|
+
4. [modelValue](file:///e:/temp/my-components/src/components/HwPickerTree/HwPickerTree.vue#L43-L47) 在多选模式下为数组,在单选模式下为字符串
|
|
190
|
+
5. 组件内部使用了 z-paging 分页组件来处理大量数据的展示
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# HwSelect 组件使用说明
|
|
2
|
+
|
|
3
|
+
HwSelect 是一个通用的选择器组件,支持选择和展示选项功能。可以根据传入的数组数据展示选项,并支持表单编辑和详情展示两种模式。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- 支持编辑模式和详情模式
|
|
8
|
+
- 支持自定义选项数据
|
|
9
|
+
- 支持必填标识显示
|
|
10
|
+
- 支持占位符文本
|
|
11
|
+
- 支持自定义背景颜色
|
|
12
|
+
- 支持双向数据绑定
|
|
13
|
+
|
|
14
|
+
## 属性 (Props)
|
|
15
|
+
|
|
16
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
17
|
+
|------|------|--------|------|
|
|
18
|
+
| [rangeKey](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L57-L57) | string | 'label' | 指定选项对象中用于显示的键名 |
|
|
19
|
+
| [rangeValue](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L58-L58) | string | 'value' | 指定选项对象中用于值的键名 |
|
|
20
|
+
| [marginTop](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L59-L59) | string | '20rpx' | 组件上边距 |
|
|
21
|
+
| [label](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L60-L60) | string | - | 选项标签文本 |
|
|
22
|
+
| [placeholder](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L61-L61) | string | '请选择' | 占位符文本 |
|
|
23
|
+
| [types](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L62-L62) | string | 'add' | 组件类型,'add' 为编辑模式,'detail' 为详情模式 |
|
|
24
|
+
| [isDetail](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L63-L63) | boolean | false | 是否为详情模式的标识 |
|
|
25
|
+
| [required](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L64-L64) | boolean | false | 是否必填项标识 |
|
|
26
|
+
| [backgroundColor](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L65-L65) | string | 'transparent' | 背景颜色 |
|
|
27
|
+
| [array](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L66-L66) | Array<any> | - | 选项数据数组 |
|
|
28
|
+
|
|
29
|
+
## 事件 (Events)
|
|
30
|
+
|
|
31
|
+
| 事件名 | 参数 | 说明 |
|
|
32
|
+
|-------|------|------|
|
|
33
|
+
| change | (selectedItem: any) | 当选择值变化时触发,返回选中的选项对象 |
|
|
34
|
+
|
|
35
|
+
## 使用示例
|
|
36
|
+
|
|
37
|
+
### 基础用法
|
|
38
|
+
|
|
39
|
+
```vue
|
|
40
|
+
<template>
|
|
41
|
+
<HwSelect
|
|
42
|
+
v-model="selectedValue"
|
|
43
|
+
label="选择项"
|
|
44
|
+
:array="options"
|
|
45
|
+
@change="handleChange"
|
|
46
|
+
/>
|
|
47
|
+
</template>
|
|
48
|
+
|
|
49
|
+
<script setup>
|
|
50
|
+
import { ref } from 'vue';
|
|
51
|
+
import HwSelect from '@/components/HwSelect/HwSelect.vue';
|
|
52
|
+
|
|
53
|
+
const selectedValue = ref('');
|
|
54
|
+
const options = [
|
|
55
|
+
{ label: '选项1', value: '1' },
|
|
56
|
+
{ label: '选项2', value: '2' },
|
|
57
|
+
{ label: '选项3', value: '3' }
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
const handleChange = (selectedItem) => {
|
|
61
|
+
console.log('选中的项:', selectedItem);
|
|
62
|
+
};
|
|
63
|
+
</script>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 详情模式
|
|
67
|
+
|
|
68
|
+
```vue
|
|
69
|
+
<template>
|
|
70
|
+
<HwSelect
|
|
71
|
+
v-model="selectedValue"
|
|
72
|
+
label="选择项"
|
|
73
|
+
:array="options"
|
|
74
|
+
types="detail"
|
|
75
|
+
/>
|
|
76
|
+
</template>
|
|
77
|
+
|
|
78
|
+
<script setup>
|
|
79
|
+
import { ref } from 'vue';
|
|
80
|
+
import HwSelect from '@/components/HwSelect/HwSelect.vue';
|
|
81
|
+
|
|
82
|
+
const selectedValue = ref('2');
|
|
83
|
+
const options = [
|
|
84
|
+
{ label: '选项1', value: '1' },
|
|
85
|
+
{ label: '选项2', value: '2' },
|
|
86
|
+
{ label: '选项3', value: '3' }
|
|
87
|
+
];
|
|
88
|
+
</script>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 必填项
|
|
92
|
+
|
|
93
|
+
```vue
|
|
94
|
+
<template>
|
|
95
|
+
<HwSelect
|
|
96
|
+
v-model="selectedValue"
|
|
97
|
+
label="必填选择项"
|
|
98
|
+
:required="true"
|
|
99
|
+
:array="options"
|
|
100
|
+
/>
|
|
101
|
+
</template>
|
|
102
|
+
|
|
103
|
+
<script setup>
|
|
104
|
+
import { ref } from 'vue';
|
|
105
|
+
import HwSelect from '@/components/HwSelect/HwSelect.vue';
|
|
106
|
+
|
|
107
|
+
const selectedValue = ref('');
|
|
108
|
+
const options = [
|
|
109
|
+
{ label: '选项1', value: '1' },
|
|
110
|
+
{ label: '选项2', value: '2' }
|
|
111
|
+
];
|
|
112
|
+
</script>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 注意事项
|
|
116
|
+
|
|
117
|
+
1. 组件基于 uni-app 的 picker 组件实现
|
|
118
|
+
2. [array](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L66-L66) 属性需要传入一个对象数组,每个对象需要包含 [rangeKey](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L57-L57) 和 [rangeValue](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L58-L58) 指定的属性
|
|
119
|
+
3. 在详情模式下,组件只显示选中项的文本,不提供编辑功能
|
|
120
|
+
4. [types](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L62-L62) 设置为 'detail' 时会显示为只读的详情模式
|
|
121
|
+
5. [rangeKey](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L57-L57) 默认为 'label',用于显示选项文本
|
|
122
|
+
6. [rangeValue](file:///e:/temp/my-components/src/components/HwSelect/HwSelect.vue#L58-L58) 默认为 'value',用于存储选项值
|
package/package.json
CHANGED