yh-mobile-components 1.0.1 → 1.0.3
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 +261 -0
- package/form/yhmCheckbox.vue +2 -2
- package/form/yhmDatetime.vue +2 -2
- package/form/yhmInput.vue +49 -4
- package/form/yhmPassword.vue +106 -0
- package/form/yhmRadio.vue +2 -2
- package/form/yhmSelect.vue +1 -2
- package/form/yhmSwitch.vue +2 -2
- package/index.ts +9 -0
- package/info/yhmInfoItem.vue +4 -2
- package/info/yhmList.vue +15 -5
- package/info/yhmTabs.vue +92 -0
- package/package.json +1 -1
- package/types.ts +14 -5
- package/readme.md +0 -47
package/README.md
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# PDA(移动端竖屏) 组件库
|
|
2
|
+
|
|
3
|
+
**此包依赖**
|
|
4
|
+
- vue 3.2.47
|
|
5
|
+
- pinia 2.0.35
|
|
6
|
+
- vant 4.8.1
|
|
7
|
+
|
|
8
|
+
## 愿景
|
|
9
|
+
|
|
10
|
+
提供一系列的列表、表单组件封装。基于封装的组件,提供一定程度的配置化
|
|
11
|
+
|
|
12
|
+
## 安装
|
|
13
|
+
|
|
14
|
+
初次安装以及升级版本都需要在命令行,运行下面的命令
|
|
15
|
+
```shell
|
|
16
|
+
npm install yh-mobile-components
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 使用
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
// ......
|
|
23
|
+
import yhMobileComponents from "yh-mobile-components";
|
|
24
|
+
|
|
25
|
+
// ......
|
|
26
|
+
async function main() {
|
|
27
|
+
// ......
|
|
28
|
+
const app = createApp(App);
|
|
29
|
+
app.use(yhMobileComponents);
|
|
30
|
+
// ......
|
|
31
|
+
}
|
|
32
|
+
main()
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 类型或枚举
|
|
36
|
+
|
|
37
|
+
###### 状态枚举 StatusType
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
export type StatusType = "primary" | "danger" | "success" | "warning" | "cyan" | "purple" | "yellow" | "pink";
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
|属性|说明|
|
|
44
|
+
|----|----|
|
|
45
|
+
|primary|表示主要内容,文字显示为蓝色|
|
|
46
|
+
|success|表示成功,文字显示为绿色|
|
|
47
|
+
|danger|表示危险,文字显示为红色|
|
|
48
|
+
|warning|表示警告,文字显示为橙色|
|
|
49
|
+
|cyan|文字显示为青色|
|
|
50
|
+
|purple|文字显示为紫色|
|
|
51
|
+
|yellow|文字显示为黄色|
|
|
52
|
+
|pink|文字显示为粉色|
|
|
53
|
+
|
|
54
|
+
###### 数据选项 VanOption
|
|
55
|
+
列表参数、下拉、单选、多选有用到
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
/** 下拉、单选、多选等组件的数据选项 */
|
|
59
|
+
export interface vanOption {
|
|
60
|
+
/** 选项的标签用来显示的 */
|
|
61
|
+
text: string;
|
|
62
|
+
/** 选项的值,用来赋值传递给后端的 */
|
|
63
|
+
value: string | number;
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
const optionData = reactive([{text:"一",value:1},{text:"二",value:2},{text:"三",value:3}])
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## 组件说明
|
|
72
|
+
|
|
73
|
+
###### yhm-list
|
|
74
|
+
使用下面的模板创建一个列表
|
|
75
|
+
|
|
76
|
+
```html
|
|
77
|
+
<template>
|
|
78
|
+
<yhm-list v-bind="configObj"></yhm-list>
|
|
79
|
+
</template>
|
|
80
|
+
|
|
81
|
+
<script setup lang="ts">
|
|
82
|
+
import { ref, reactive } from "vue";
|
|
83
|
+
import { ListConfig, ListConfigObject, ParamConfig } from "yh-mobile-components/types";
|
|
84
|
+
|
|
85
|
+
const listConfig = reactive<ListConfig<any>>({
|
|
86
|
+
btns: [
|
|
87
|
+
{
|
|
88
|
+
type: "primary",
|
|
89
|
+
text: "详情",
|
|
90
|
+
callback(row) {
|
|
91
|
+
console.log(row);
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
items: [
|
|
96
|
+
{
|
|
97
|
+
span: 12,
|
|
98
|
+
label: "标签名",
|
|
99
|
+
value: "name",
|
|
100
|
+
description: "标签描述",
|
|
101
|
+
status(row) {
|
|
102
|
+
return "primary";
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
span: 12,
|
|
107
|
+
label: "偶数显示",
|
|
108
|
+
value: "name",
|
|
109
|
+
description: "标签描述",
|
|
110
|
+
show(row) {
|
|
111
|
+
|
|
112
|
+
return row.status === 0;
|
|
113
|
+
},
|
|
114
|
+
status(row) {
|
|
115
|
+
return "primary";
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
span: 24,
|
|
120
|
+
label: "标签名",
|
|
121
|
+
value: "name",
|
|
122
|
+
description: "标签描述",
|
|
123
|
+
status(row) {
|
|
124
|
+
return "primary";
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
});
|
|
129
|
+
const paramConfig = reactive<ParamConfig[]>([
|
|
130
|
+
{
|
|
131
|
+
value: "param1",
|
|
132
|
+
optionData: [
|
|
133
|
+
{ text: "全部", value: "" },
|
|
134
|
+
{ text: "一", value: 1 },
|
|
135
|
+
{ text: "二", value: 2 },
|
|
136
|
+
],
|
|
137
|
+
defaultValue: "",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
value: "param2",
|
|
141
|
+
optionData: [
|
|
142
|
+
{ text: "全部", value: "" },
|
|
143
|
+
{ text: "一", value: 1 },
|
|
144
|
+
{ text: "二", value: 2 },
|
|
145
|
+
],
|
|
146
|
+
defaultValue: "",
|
|
147
|
+
},
|
|
148
|
+
]);
|
|
149
|
+
|
|
150
|
+
const configObj = reactive<ListConfigObject<any>>({
|
|
151
|
+
hasSearch: true,
|
|
152
|
+
searchPlaceholder: "关键词搜索",
|
|
153
|
+
paramConfig,
|
|
154
|
+
listConfig,
|
|
155
|
+
getData(pageIndex, pageSize, params, keyword) {
|
|
156
|
+
return new Promise((resolve, reject) => {
|
|
157
|
+
let arr: any = [];
|
|
158
|
+
for (let i = 0; i < 20; i++) {
|
|
159
|
+
arr.push({
|
|
160
|
+
name: `name${i}`,
|
|
161
|
+
status: i % 2,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
setTimeout(() => {
|
|
165
|
+
resolve({ data: arr, total: 20 });
|
|
166
|
+
}, 1000);
|
|
167
|
+
});
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
</script>
|
|
171
|
+
|
|
172
|
+
<style lang="scss"></style>
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
###### yhm-form
|
|
177
|
+
使用下面的模板创建一个列表
|
|
178
|
+
|
|
179
|
+
```html
|
|
180
|
+
<template>
|
|
181
|
+
<yhm-form
|
|
182
|
+
:options="options"
|
|
183
|
+
:formData="formData"
|
|
184
|
+
v-model:verification="verification">
|
|
185
|
+
<van-button
|
|
186
|
+
type="primary"
|
|
187
|
+
:disabled="!verification"
|
|
188
|
+
block
|
|
189
|
+
@click="submit">
|
|
190
|
+
确认
|
|
191
|
+
</van-button>
|
|
192
|
+
</yhm-form>
|
|
193
|
+
</template>
|
|
194
|
+
<script setup lang="ts">
|
|
195
|
+
import { ref, reactive } from "vue";
|
|
196
|
+
import { ConfigFormItem } from "yh-mobile-components/types";
|
|
197
|
+
|
|
198
|
+
const formData = reactive<any>({});
|
|
199
|
+
const options = reactive<ConfigFormItem[]>([
|
|
200
|
+
{
|
|
201
|
+
label: "数字",
|
|
202
|
+
type: "number",
|
|
203
|
+
name: "1",
|
|
204
|
+
defaultValue: "",
|
|
205
|
+
config: {},
|
|
206
|
+
itemChange(val, data) {
|
|
207
|
+
console.log(val, data);
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
]);
|
|
211
|
+
const verification = ref(false);
|
|
212
|
+
|
|
213
|
+
function submit() {
|
|
214
|
+
if (verification.value) {
|
|
215
|
+
// 表单验证通过
|
|
216
|
+
} else {
|
|
217
|
+
// 表单验证没通过此时按钮也处于无法点击状态
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
</script>
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
###### yhm-info
|
|
225
|
+
信息展示包裹组件,用来包裹 yhm-info-item。
|
|
226
|
+
|
|
227
|
+
|属性|必选|类型|说明|
|
|
228
|
+
|----|----|----|----|
|
|
229
|
+
|hasTop|否|boolean|是否在组件上方增加一个间隔|
|
|
230
|
+
|
|
231
|
+
###### yhm-info-item
|
|
232
|
+
信息展示元素组件,必须嵌入 yhm-info-item 使用。
|
|
233
|
+
|
|
234
|
+
|属性|必选|类型|说明|
|
|
235
|
+
|----|----|----|----|
|
|
236
|
+
|span|是|number| 1 - 24的数字|
|
|
237
|
+
|label|否|string|标签名|
|
|
238
|
+
|value|否|number|标签值|
|
|
239
|
+
|description|否|number|标签描述|
|
|
240
|
+
|regularValue|否|number| 是否让值显示黑色 |
|
|
241
|
+
|status|否|StatusType| 是否让值显示黑色 |
|
|
242
|
+
|
|
243
|
+
```html
|
|
244
|
+
<yhm-info has-top>
|
|
245
|
+
<yhm-info>
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
###### yhm-datetime
|
|
249
|
+
日期时间选择组件
|
|
250
|
+
|
|
251
|
+
###### yhm-switch
|
|
252
|
+
开关组件
|
|
253
|
+
|
|
254
|
+
###### yhm-select
|
|
255
|
+
下拉选择
|
|
256
|
+
|
|
257
|
+
###### yhm-radio
|
|
258
|
+
单选
|
|
259
|
+
|
|
260
|
+
###### yhm-checkbox
|
|
261
|
+
多选
|
package/form/yhmCheckbox.vue
CHANGED
package/form/yhmDatetime.vue
CHANGED
|
@@ -61,9 +61,9 @@ import { ref, computed, watch, nextTick } from "vue";
|
|
|
61
61
|
|
|
62
62
|
const props = withDefaults(
|
|
63
63
|
defineProps<{
|
|
64
|
-
error: boolean;
|
|
65
|
-
errorMessage: string;
|
|
66
64
|
type: "year" | "month" | "date" | "datetime" | "time";
|
|
65
|
+
error?: boolean;
|
|
66
|
+
errorMessage?: string;
|
|
67
67
|
format?: string;
|
|
68
68
|
disabled?: boolean;
|
|
69
69
|
modelValue?: any;
|
package/form/yhmInput.vue
CHANGED
|
@@ -4,28 +4,73 @@
|
|
|
4
4
|
v-bind="$attrs"
|
|
5
5
|
:model-value="modelValue"
|
|
6
6
|
@update:modelValue="changeHandler"
|
|
7
|
+
@keydown="keydownHandler"
|
|
8
|
+
:type="inputType"
|
|
7
9
|
:error="error"
|
|
8
|
-
:error-message="errorMessage"
|
|
10
|
+
:error-message="errorMessage">
|
|
11
|
+
<template
|
|
12
|
+
#right-icon
|
|
13
|
+
v-if="props.type === 'scan'">
|
|
14
|
+
<svg
|
|
15
|
+
width="20px"
|
|
16
|
+
height="20px"
|
|
17
|
+
style="vertical-align: middle"
|
|
18
|
+
viewBox="0 0 1000 1000"
|
|
19
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
20
|
+
<path
|
|
21
|
+
stroke="var(--van-field-right-icon-color)"
|
|
22
|
+
stroke-width="60"
|
|
23
|
+
stroke-linejoin="round"
|
|
24
|
+
fill="none"
|
|
25
|
+
d="M200,350 L200,200 L400,200 M600,200 L800,200 L800,400 M800,600 L800,800 L600,800 M400,800 L200,800 L200,600 M0,500 L1000,500"></path>
|
|
26
|
+
</svg>
|
|
27
|
+
</template>
|
|
28
|
+
</van-field>
|
|
9
29
|
</template>
|
|
10
30
|
<script setup lang="ts">
|
|
31
|
+
import { computed } from "vue";
|
|
11
32
|
const props = withDefaults(
|
|
12
33
|
defineProps<{
|
|
13
|
-
|
|
14
|
-
|
|
34
|
+
type?: string;
|
|
35
|
+
error?: boolean;
|
|
36
|
+
errorMessage?: string;
|
|
15
37
|
modelValue?: any;
|
|
38
|
+
scanCallback?: (val) => void;
|
|
16
39
|
}>(),
|
|
17
|
-
{
|
|
40
|
+
{
|
|
41
|
+
type: "text",
|
|
42
|
+
}
|
|
18
43
|
);
|
|
19
44
|
|
|
45
|
+
const inputType = computed(() => {
|
|
46
|
+
if (props.type === "scan") {
|
|
47
|
+
return "text";
|
|
48
|
+
} else {
|
|
49
|
+
return props.type;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
20
53
|
const emits = defineEmits<{
|
|
21
54
|
(e: "update:modelValue", val: any);
|
|
22
55
|
(e: "change", val: any);
|
|
56
|
+
(e: "scan", val: any);
|
|
23
57
|
}>();
|
|
24
58
|
|
|
25
59
|
function changeHandler(val) {
|
|
26
60
|
emits("update:modelValue", val);
|
|
27
61
|
emits("change", val);
|
|
28
62
|
}
|
|
63
|
+
|
|
64
|
+
function keydownHandler(e: KeyboardEvent) {
|
|
65
|
+
let key = e.key;
|
|
66
|
+
if (key === "Enter" && props.type === "scan") {
|
|
67
|
+
console.log("scan");
|
|
68
|
+
|
|
69
|
+
if (props.scanCallback && typeof props.scanCallback === "function") {
|
|
70
|
+
props.scanCallback(props.modelValue);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
29
74
|
</script>
|
|
30
75
|
<style lang="scss">
|
|
31
76
|
.yhm-input-container {
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<van-field
|
|
3
|
+
class="yhm-input-container"
|
|
4
|
+
v-bind="$attrs"
|
|
5
|
+
:model-value="modelValue"
|
|
6
|
+
@update:modelValue="changeHandler"
|
|
7
|
+
:type="inputType"
|
|
8
|
+
:error="error"
|
|
9
|
+
:error-message="errorMessage">
|
|
10
|
+
<template #right-icon>
|
|
11
|
+
<svg
|
|
12
|
+
width="40px"
|
|
13
|
+
height="20px"
|
|
14
|
+
style="vertical-align: middle"
|
|
15
|
+
viewBox="0 0 2000 1000"
|
|
16
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
+
@click="showPassword = !showPassword">
|
|
18
|
+
<path
|
|
19
|
+
d="M100,100 L1900,100 L1900,900 L100,900 Z"
|
|
20
|
+
stroke="var(--van-field-right-icon-color)"
|
|
21
|
+
stroke-width="60"
|
|
22
|
+
stroke-linejoin="round"
|
|
23
|
+
fill="none"></path>
|
|
24
|
+
<g v-if="!showPassword">
|
|
25
|
+
<circle
|
|
26
|
+
r="150"
|
|
27
|
+
stroke-width="0"
|
|
28
|
+
fill="var(--van-field-right-icon-color)"
|
|
29
|
+
cx="500"
|
|
30
|
+
cy="500"></circle>
|
|
31
|
+
<circle
|
|
32
|
+
r="150"
|
|
33
|
+
stroke-width="0"
|
|
34
|
+
fill="var(--van-field-right-icon-color)"
|
|
35
|
+
cx="1000"
|
|
36
|
+
cy="500"></circle>
|
|
37
|
+
<circle
|
|
38
|
+
r="150"
|
|
39
|
+
stroke-width="0"
|
|
40
|
+
fill="var(--van-field-right-icon-color)"
|
|
41
|
+
cx="1500"
|
|
42
|
+
cy="500"></circle>
|
|
43
|
+
</g>
|
|
44
|
+
<g v-else>
|
|
45
|
+
<polyline
|
|
46
|
+
points="350,300 650,300 500,300 500 700"
|
|
47
|
+
stroke="var(--van-field-right-icon-color)"
|
|
48
|
+
stroke-width="60"
|
|
49
|
+
stroke-linejoin="round"
|
|
50
|
+
fill="none"></polyline>
|
|
51
|
+
<polyline
|
|
52
|
+
points="850,300 1150,300 1000,300 1000 700"
|
|
53
|
+
stroke="var(--van-field-right-icon-color)"
|
|
54
|
+
stroke-width="60"
|
|
55
|
+
stroke-linejoin="round"
|
|
56
|
+
fill="none"></polyline>
|
|
57
|
+
<polyline
|
|
58
|
+
points="1350,300 1650,300 1500,300 1500 700"
|
|
59
|
+
stroke="var(--van-field-right-icon-color)"
|
|
60
|
+
stroke-width="60"
|
|
61
|
+
stroke-linejoin="round"
|
|
62
|
+
fill="none"></polyline>
|
|
63
|
+
</g>
|
|
64
|
+
</svg>
|
|
65
|
+
</template>
|
|
66
|
+
</van-field>
|
|
67
|
+
</template>
|
|
68
|
+
<script setup lang="ts">
|
|
69
|
+
import { computed, ref } from "vue";
|
|
70
|
+
const props = withDefaults(
|
|
71
|
+
defineProps<{
|
|
72
|
+
error?: boolean;
|
|
73
|
+
errorMessage?: string;
|
|
74
|
+
modelValue?: any;
|
|
75
|
+
scanCallback?: (val) => void;
|
|
76
|
+
}>(),
|
|
77
|
+
{}
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const showPassword = ref(false);
|
|
81
|
+
|
|
82
|
+
const inputType = computed(() => {
|
|
83
|
+
if (showPassword.value) {
|
|
84
|
+
return "text";
|
|
85
|
+
} else {
|
|
86
|
+
return "password";
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const emits = defineEmits<{
|
|
91
|
+
(e: "update:modelValue", val: any);
|
|
92
|
+
(e: "change", val: any);
|
|
93
|
+
}>();
|
|
94
|
+
|
|
95
|
+
function changeHandler(val) {
|
|
96
|
+
emits("update:modelValue", val);
|
|
97
|
+
emits("change", val);
|
|
98
|
+
}
|
|
99
|
+
</script>
|
|
100
|
+
<style lang="scss">
|
|
101
|
+
.yhm-input-container {
|
|
102
|
+
.van-field__control {
|
|
103
|
+
text-align: right;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
</style>
|
package/form/yhmRadio.vue
CHANGED
package/form/yhmSelect.vue
CHANGED
|
@@ -29,8 +29,7 @@
|
|
|
29
29
|
<script setup lang="ts">
|
|
30
30
|
import { ref, computed } from "vue";
|
|
31
31
|
|
|
32
|
-
const props = withDefaults(defineProps<{ error
|
|
33
|
-
type: "datetime",
|
|
32
|
+
const props = withDefaults(defineProps<{ error?: boolean; errorMessage?: string; modelValue?: any; disabled?: boolean; palceholder?: string; optionData: any[] }>(), {
|
|
34
33
|
disabled: false,
|
|
35
34
|
palceholder: "请选择",
|
|
36
35
|
});
|
package/form/yhmSwitch.vue
CHANGED
package/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import yhmList from "./info/yhmList.vue";
|
|
2
2
|
import yhmDropdownItem from "./info/yhmDropdownItem.vue";
|
|
3
|
+
import yhmTabs from "./info/yhmTabs.vue";
|
|
3
4
|
import yhmInfo from "./info/yhmInfo.vue";
|
|
4
5
|
import yhmInfoItem from "./info/yhmInfoItem.vue";
|
|
5
6
|
import yhmForm from "./form/yhm-form.vue";
|
|
@@ -9,10 +10,16 @@ import yhmCheckbox from "./form/yhmCheckbox.vue";
|
|
|
9
10
|
import yhmSelect from "./form/yhmSelect.vue";
|
|
10
11
|
import yhmInput from "./form/yhmInput.vue";
|
|
11
12
|
import yhmSwitch from "./form/yhmSwitch.vue";
|
|
13
|
+
import yhmPassword from "./form/yhmPassword.vue";
|
|
14
|
+
import vant from "vant";
|
|
15
|
+
import "vant/lib/index.css";
|
|
16
|
+
import "yh-mobile-components/custom.scss";
|
|
17
|
+
|
|
12
18
|
export default {
|
|
13
19
|
install(app) {
|
|
14
20
|
app.component("yhm-list", yhmList);
|
|
15
21
|
app.component("yhm-dropdown-item", yhmDropdownItem);
|
|
22
|
+
app.component("yhm-tabs", yhmTabs);
|
|
16
23
|
app.component("yhm-info", yhmInfo);
|
|
17
24
|
app.component("yhm-info-item", yhmInfoItem);
|
|
18
25
|
app.component("yhm-form", yhmForm);
|
|
@@ -22,5 +29,7 @@ export default {
|
|
|
22
29
|
app.component("yhm-input", yhmInput);
|
|
23
30
|
app.component("yhm-select", yhmSelect);
|
|
24
31
|
app.component("yhm-switch", yhmSwitch);
|
|
32
|
+
app.component("yhm-password", yhmPassword);
|
|
33
|
+
app.use(vant);
|
|
25
34
|
},
|
|
26
35
|
};
|
package/info/yhmInfoItem.vue
CHANGED
|
@@ -43,7 +43,8 @@ const widthCount = computed(() => {
|
|
|
43
43
|
margin-right: 8px;
|
|
44
44
|
.yhm-info-item {
|
|
45
45
|
display: flex;
|
|
46
|
-
|
|
46
|
+
padding: 4px 0;
|
|
47
|
+
line-height: 18px;
|
|
47
48
|
.yhm-info-item-value {
|
|
48
49
|
flex: 1;
|
|
49
50
|
text-align: right;
|
|
@@ -59,7 +60,8 @@ const widthCount = computed(() => {
|
|
|
59
60
|
}
|
|
60
61
|
.yhm-info-description {
|
|
61
62
|
color: var(--van-text-color-2);
|
|
62
|
-
|
|
63
|
+
padding: 2px 0;
|
|
64
|
+
line-height: 16px;
|
|
63
65
|
}
|
|
64
66
|
&.primary {
|
|
65
67
|
.yhm-info-item {
|
package/info/yhmList.vue
CHANGED
|
@@ -7,14 +7,23 @@
|
|
|
7
7
|
:placeholder="searchPlaceholder"
|
|
8
8
|
@update:model-value="getList(true)"
|
|
9
9
|
:clearable="false"></van-search>
|
|
10
|
-
<
|
|
11
|
-
<
|
|
10
|
+
<template v-if="paramConfig && paramConfig.length">
|
|
11
|
+
<van-dropdown-menu v-if="paramType === 'dropdown'">
|
|
12
|
+
<yhm-dropdown-item
|
|
13
|
+
:valueObj="params"
|
|
14
|
+
:value="conf.value"
|
|
15
|
+
:optionData="conf.optionData"
|
|
16
|
+
v-for="conf in paramConfig"
|
|
17
|
+
@change="getList(true)"></yhm-dropdown-item>
|
|
18
|
+
</van-dropdown-menu>
|
|
19
|
+
<yhm-tabs
|
|
20
|
+
v-else
|
|
12
21
|
:valueObj="params"
|
|
13
22
|
:value="conf.value"
|
|
14
23
|
:optionData="conf.optionData"
|
|
15
24
|
v-for="conf in paramConfig"
|
|
16
|
-
@change="getList(true)"></yhm-
|
|
17
|
-
</
|
|
25
|
+
@change="getList(true)"></yhm-tabs>
|
|
26
|
+
</template>
|
|
18
27
|
</section>
|
|
19
28
|
<van-pull-refresh
|
|
20
29
|
v-model="refreshing"
|
|
@@ -31,7 +40,7 @@
|
|
|
31
40
|
<yhm-info has-top>
|
|
32
41
|
<template v-for="item in listConfig?.items">
|
|
33
42
|
<yhm-info-item
|
|
34
|
-
v-if="!item.show || (item.show && item.show(row))"
|
|
43
|
+
v-if="!item.show || (item.show && item.show(row, params, keyword))"
|
|
35
44
|
:label="item.label"
|
|
36
45
|
:span="item.span"
|
|
37
46
|
:status="item.status && item.status(row)"
|
|
@@ -71,6 +80,7 @@ const props = withDefaults(
|
|
|
71
80
|
hasSearch?: boolean;
|
|
72
81
|
/** 关键字筛选提示语 */
|
|
73
82
|
searchPlaceholder?: string;
|
|
83
|
+
paramType?: "dropdown" | "tabs";
|
|
74
84
|
/** 下拉筛选条件配置 */
|
|
75
85
|
paramConfig?: ParamConfig[];
|
|
76
86
|
/** 列表项目筛选 */
|
package/info/yhmTabs.vue
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section
|
|
3
|
+
class="yhm-tabs"
|
|
4
|
+
ref="yhmTabsRef">
|
|
5
|
+
<div
|
|
6
|
+
class="yhm-tab-item"
|
|
7
|
+
:class="{ active: option.value === modelValue }"
|
|
8
|
+
@click="updateHandler($event, option.value)"
|
|
9
|
+
v-for="option in optionData">
|
|
10
|
+
{{ option.text }}
|
|
11
|
+
</div>
|
|
12
|
+
</section>
|
|
13
|
+
</template>
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
import type { vanOption } from "../types";
|
|
16
|
+
import { computed, watch, ref } from "vue";
|
|
17
|
+
|
|
18
|
+
const props = defineProps<{
|
|
19
|
+
valueObj: any;
|
|
20
|
+
value: string;
|
|
21
|
+
optionData: vanOption[];
|
|
22
|
+
}>();
|
|
23
|
+
|
|
24
|
+
const emits = defineEmits<{
|
|
25
|
+
(e: "change");
|
|
26
|
+
}>();
|
|
27
|
+
|
|
28
|
+
const modelValue = computed({
|
|
29
|
+
get() {
|
|
30
|
+
return props.valueObj[props.value];
|
|
31
|
+
},
|
|
32
|
+
set(val) {
|
|
33
|
+
props.valueObj[props.value] = val;
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
const yhmTabsRef = ref();
|
|
37
|
+
watch(
|
|
38
|
+
() => modelValue.value,
|
|
39
|
+
(val) => {
|
|
40
|
+
let optionVals = props.optionData.map((item) => item.value);
|
|
41
|
+
if (optionVals && optionVals.length && yhmTabsRef.value) {
|
|
42
|
+
let items: HTMLDivElement[] = Array.from(yhmTabsRef.value.querySelectorAll(".yhm-tab-item"));
|
|
43
|
+
let index = optionVals.indexOf(val);
|
|
44
|
+
items[index]?.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
function updateHandler(e, val: string | number) {
|
|
50
|
+
modelValue.value = val;
|
|
51
|
+
emits("change");
|
|
52
|
+
}
|
|
53
|
+
</script>
|
|
54
|
+
<style lang="scss">
|
|
55
|
+
.yhm-tabs {
|
|
56
|
+
display: flex;
|
|
57
|
+
background-color: var(--van-white);
|
|
58
|
+
padding-bottom: 5px;
|
|
59
|
+
padding-left: 5px;
|
|
60
|
+
padding-right: 5px;
|
|
61
|
+
width: 100%;
|
|
62
|
+
box-sizing: border-box;
|
|
63
|
+
overflow: auto;
|
|
64
|
+
&:first-child {
|
|
65
|
+
padding-top: 5px;
|
|
66
|
+
}
|
|
67
|
+
.yhm-tab-item {
|
|
68
|
+
flex: 1 0 auto;
|
|
69
|
+
text-align: center;
|
|
70
|
+
font-size: 14px;
|
|
71
|
+
line-height: 18px;
|
|
72
|
+
padding: 3px 15px;
|
|
73
|
+
color: var(--van-primary-color);
|
|
74
|
+
border: 1px solid var(--van-primary-color);
|
|
75
|
+
&:first-child {
|
|
76
|
+
border-top-left-radius: 6px;
|
|
77
|
+
border-bottom-left-radius: 6px;
|
|
78
|
+
}
|
|
79
|
+
&:last-child {
|
|
80
|
+
border-top-right-radius: 6px;
|
|
81
|
+
border-bottom-right-radius: 6px;
|
|
82
|
+
}
|
|
83
|
+
&.active {
|
|
84
|
+
color: var(--van-white);
|
|
85
|
+
background-color: var(--van-primary-color);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
.yhm-tab-item + .yhm-tab-item {
|
|
89
|
+
border-left: 0;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
</style>
|
package/package.json
CHANGED
package/types.ts
CHANGED
|
@@ -31,10 +31,18 @@ export interface ListItem<T> {
|
|
|
31
31
|
description: keyof T;
|
|
32
32
|
/** 自定义插槽,用来渲染自定义元素 */
|
|
33
33
|
slot?: string;
|
|
34
|
-
/** 值的样式,自定义不同的颜色
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
/** 值的样式,自定义不同的颜色
|
|
35
|
+
* @param row 当前行数据
|
|
36
|
+
* @param params 列表筛选数据
|
|
37
|
+
* @param keyword 列表筛选关键字
|
|
38
|
+
*/
|
|
39
|
+
status?: (row: T, parmas: any, keyword: string) => StatusType;
|
|
40
|
+
/** 是否显示
|
|
41
|
+
* @param row 当前行数据
|
|
42
|
+
* @param params 列表筛选数据
|
|
43
|
+
* @param keyword 列表筛选关键字
|
|
44
|
+
*/
|
|
45
|
+
show?: (row: T, parmas: any, keyword: string) => boolean;
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
/** 列表配置 */
|
|
@@ -48,6 +56,7 @@ export interface ListConfig<T> {
|
|
|
48
56
|
export interface ListConfigObject<T> {
|
|
49
57
|
hasSearch: boolean;
|
|
50
58
|
searchPlaceholder: string;
|
|
59
|
+
paramType: "dropdown" | "tabs";
|
|
51
60
|
paramConfig: ParamConfig[];
|
|
52
61
|
listConfig: ListConfig<T>;
|
|
53
62
|
getData: (pageIndex, pageSie, params, keyword) => Promise<{ data: any[]; total: number }>;
|
|
@@ -62,7 +71,7 @@ export interface vanOption {
|
|
|
62
71
|
}
|
|
63
72
|
|
|
64
73
|
export type DateTimeType = "year" | "month" | "datetime" | "date" | "time";
|
|
65
|
-
export type InputType = "color" | "email" | "number" | "tel" | "text" | "textarea" | "url" | "digit";
|
|
74
|
+
export type InputType = "color" | "email" | "number" | "tel" | "text" | "textarea" | "url" | "digit" | "scan";
|
|
66
75
|
export type OtherType = "checkbox" | "radio" | "select" | "switch" | "password" | "rate" | "signature" | "cascader" | "slider" | "stepper";
|
|
67
76
|
|
|
68
77
|
export type FromItemType = OtherType | InputType | DateTimeType;
|
package/readme.md
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# PDA(移动端竖屏) 组件库
|
|
2
|
-
|
|
3
|
-
**此包依赖**
|
|
4
|
-
- vue 3.2.47
|
|
5
|
-
- pinia 2.0.35
|
|
6
|
-
- vant 4.8.1
|
|
7
|
-
|
|
8
|
-
## 愿景
|
|
9
|
-
|
|
10
|
-
提供一系列的列表、表单组件封装。基于封装的组件,提供一定程度的配置化
|
|
11
|
-
|
|
12
|
-
###### 页面框架组件
|
|
13
|
-
- ⬜ yhm-list 可配置列表组件
|
|
14
|
-
- ⬜ yhm-form 可配置表单组件
|
|
15
|
-
|
|
16
|
-
###### 布局元素组件
|
|
17
|
-
- ⬜ yhm-info 信息展示包裹组件
|
|
18
|
-
- ⬜ yhm-info-item 信息展示元素组件
|
|
19
|
-
- 支持配置 span 来设定字段显示宽度
|
|
20
|
-
|
|
21
|
-
###### 补充表单组件
|
|
22
|
-
> 表单组件向 van-field 看齐,属性名称及含义尽量复用
|
|
23
|
-
|
|
24
|
-
- ⬜ yhm-datetime 时间日期选择 提供google设计规范的时间日期选择器
|
|
25
|
-
- ⬜ yhm-switch 开关组件封装
|
|
26
|
-
- ⬜ yhm-select 下拉选择组件(封装van-picker)
|
|
27
|
-
- ⬜ yhm-radio 单选组件
|
|
28
|
-
- ⬜ yhm-checkbox 多选组件
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
## 业务使用
|
|
32
|
-
|
|
33
|
-
使用组合式的方式来进行页面开发,并在后续的业务中逐步替代老的方式。
|
|
34
|
-
|
|
35
|
-
###### 列表页
|
|
36
|
-
```html
|
|
37
|
-
<template>
|
|
38
|
-
<yhm-list-page>
|
|
39
|
-
<yhm-info>
|
|
40
|
-
|
|
41
|
-
</yhm-info>
|
|
42
|
-
</yhm-list-page>
|
|
43
|
-
</template>
|
|
44
|
-
<script setup lange=ts>
|
|
45
|
-
import { yhm-list-page } from "yh-i18n-m";
|
|
46
|
-
</script>
|
|
47
|
-
```
|