hookehuyr

✨ feat(地址控件): 自定义表单钩子函数调整

1 +<template>
2 + <div style="width: 100%;">
3 + <van-field
4 + v-model="fieldValue"
5 + is-link
6 + readonly
7 + :required="props.component_props.required"
8 + placeholder="请选择省市区"
9 + @click="showPicker = true"
10 + :border="show_address ? true : false"
11 + />
12 + <van-field
13 + v-if="show_address"
14 + v-model="address"
15 + placeholder="请填写详细地址"
16 + :border="false"
17 + />
18 + <van-divider />
19 +
20 + <van-popup v-model:show="showPicker" position="bottom">
21 + <van-area
22 + v-model="props.city_code"
23 + title=""
24 + :area-list="areaList"
25 + @confirm="onConfirm"
26 + @cancel="showPicker = false"
27 + />
28 + </van-popup>
29 + </div>
30 +</template>
31 +
32 +<script setup>
33 +import { ref } from 'vue'
34 +import { areaList } from "@vant/area-data";
35 +import { useCustomFieldValue } from '@vant/use';
36 +
37 +// 获取父组件传值
38 +const props = inject('props');
39 +const show_address = ref(!props.component_props.no_street)
40 +
41 +const address = ref("");
42 +const city_code = ref("");
43 +const showPicker = ref(false);
44 +let fieldValue = ref("");
45 +const result_value = computed(() => {
46 + return {
47 + address: fieldValue.value + ' ' + address.value,
48 + city_code: city_code.value,
49 + picker_value: fieldValue.value,
50 + input_value: address.value
51 + }
52 +})
53 +
54 +const onConfirm = ({ selectedOptions }) => {
55 + fieldValue.value = selectedOptions.map((option) => option.text).join(" ");
56 + city_code.value = selectedOptions[2]?.value;
57 + showPicker.value = false;
58 +};
59 +
60 +// 此处传入的值会替代 Field 组件内部的 value
61 +useCustomFieldValue(() => result_value.value);
62 +</script>
63 +
64 +<style lang="less" scoped>
65 +
66 +</style>
1 <!-- 1 <!--
2 * @Date: 2022-08-30 14:32:11 2 * @Date: 2022-08-30 14:32:11
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2023-02-14 14:37:45 4 + * @LastEditTime: 2023-03-29 16:18:53
5 * @FilePath: /data-table/src/components/AreaPickerField/index.vue 5 * @FilePath: /data-table/src/components/AreaPickerField/index.vue
6 * @Description: 省市区选择控件 6 * @Description: 省市区选择控件
7 --> 7 -->
8 <template> 8 <template>
9 <div v-if="HideShow" class="area-picker-field"> 9 <div v-if="HideShow" class="area-picker-field">
10 - <div class="label"><span v-if="item.component_props.required">&nbsp;*</span>{{ item.component_props.label }}</div> 10 + <div class="label">
11 - <van-field 11 + <span v-if="item.component_props.required">&nbsp;*</span>
12 - name="ignore" 12 + {{ item.component_props.label }}
13 - v-model="fieldValue" 13 + </div>
14 - is-link 14 + <van-field :name="item.key" :rules="rules" style="padding: 0;">
15 - readonly 15 + <template #input>
16 - :required="item.component_props.required" 16 + <my-component />
17 - placeholder="请选择省市区" 17 + </template>
18 - :rules="item.rules" 18 + </van-field>
19 - @click="showPicker = true"
20 - :border="show_address ? true : false"
21 - />
22 - <van-field
23 - v-if="show_address"
24 - name="ignore"
25 - v-model="address"
26 - placeholder="请填写详细地址"
27 - @blur="onBlur"
28 - :rules="item.rules"
29 - :border="false"
30 - />
31 - <!-- <div
32 - v-if="show_empty"
33 - class="van-field__error-message"
34 - style="padding: 0 1rem 1rem 1rem"
35 - >
36 - 地址不能为空
37 - </div> -->
38 - <van-divider />
39 -
40 - <van-popup v-model:show="showPicker" position="bottom">
41 - <van-area
42 - v-model="item.city_code"
43 - title=""
44 - :area-list="areaList"
45 - @confirm="onConfirm"
46 - @cancel="showPicker = false"
47 - />
48 - </van-popup>
49 </div> 19 </div>
50 </template> 20 </template>
51 21
52 <script setup> 22 <script setup>
53 -import { areaList } from "@vant/area-data"; 23 +import MyComponent from './MyComponent.vue';
54 24
55 const props = defineProps({ 25 const props = defineProps({
56 item: Object, 26 item: Object,
57 }); 27 });
28 +// 注入子组件属性
29 +provide('props', props.item);
58 // 隐藏显示 30 // 隐藏显示
59 const HideShow = computed(() => { 31 const HideShow = computed(() => {
60 return !props.item.component_props.disabled 32 return !props.item.component_props.disabled
61 }) 33 })
62 -const emit = defineEmits(["active"]);
63 -const show_empty = ref(false);
64 -
65 -const show_address = ref(!props.item.component_props.no_street)
66 -
67 -const address = ref("");
68 -const city_code = ref("");
69 -const showPicker = ref(false);
70 -let fieldValue = ref("");
71 -
72 -const onConfirm = ({ selectedOptions }) => {
73 - fieldValue.value = selectedOptions.map((option) => option.text).join(" ");
74 - city_code.value = selectedOptions[2]?.value;
75 - props.item.value = {
76 - key: "area_picker",
77 - filed_name: props.item.key,
78 - value: {
79 - address: fieldValue.value + ' ' + address.value,
80 - city_code: city_code.value
81 - },
82 - };
83 - emit("active", props.item.value);
84 - showPicker.value = false;
85 -};
86 -
87 -const onBlur = () => {
88 - props.item.value = {
89 - key: "area_picker",
90 - filed_name: props.item.key,
91 - value: {
92 - address: fieldValue.value + ' ' + address.value,
93 - city_code: city_code.value
94 - },
95 - };
96 - emit("active", props.item.value);
97 -}
98 34
99 -// 校验模块 35 +// 规则校验
100 -const validAreaPicker = () => { 36 +const required = props.item.component_props.required;
101 - // 必填项 37 +const show_street = !props.item.component_props.no_street; // 显示详细地址
102 - if (props.item.component_props.required && !fieldValue.value) { 38 +const validator = (val) => {
103 - show_empty.value = true; 39 + if (required && show_street && (!val.picker_value || !val.input_value)) {
104 - } else if (props.item.component_props.required && !address.value) { 40 + return false;
105 - show_empty.value = true; 41 + } else if (required && !show_street && !val.picker_value) {
42 + return false;
106 } else { 43 } else {
107 - show_empty.value = false; 44 + return true;
108 } 45 }
109 - return !show_empty.value;
110 }; 46 };
111 - 47 +// 错误提示文案
112 -defineExpose({ validAreaPicker }); 48 +const validatorMessage = (val, rule) => {
49 + if (required && show_street && (!val.picker_value || !val.input_value)) {
50 + return "必填项不能为空";
51 + } else if (required && !show_street && !val.picker_value) {
52 + return "必填项不能为空";
53 + }
54 +};
55 +const rules = [{ validator, message: validatorMessage }];
113 </script> 56 </script>
114 57
115 <style lang="less" scoped> 58 <style lang="less" scoped>
...@@ -125,4 +68,8 @@ defineExpose({ validAreaPicker }); ...@@ -125,4 +68,8 @@ defineExpose({ validAreaPicker });
125 } 68 }
126 } 69 }
127 70
71 +:deep(.van-field__error-message) {
72 + padding-left: 1rem;
73 +}
74 +
128 </style> 75 </style>
......