Showing
2 changed files
with
101 additions
and
88 deletions
| 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"> *</span>{{ item.component_props.label }}</div> | 10 | + <div class="label"> |
| 11 | - <van-field | 11 | + <span v-if="item.component_props.required"> *</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 | 34 | ||
| 72 | -const onConfirm = ({ selectedOptions }) => { | 35 | +// 规则校验 |
| 73 | - fieldValue.value = selectedOptions.map((option) => option.text).join(" "); | 36 | +const required = props.item.component_props.required; |
| 74 | - city_code.value = selectedOptions[2]?.value; | 37 | +const show_street = !props.item.component_props.no_street; // 显示详细地址 |
| 75 | - props.item.value = { | 38 | +const validator = (val) => { |
| 76 | - key: "area_picker", | 39 | + if (required && show_street && (!val.picker_value || !val.input_value)) { |
| 77 | - filed_name: props.item.key, | 40 | + return false; |
| 78 | - value: { | 41 | + } else if (required && !show_street && !val.picker_value) { |
| 79 | - address: fieldValue.value + ' ' + address.value, | 42 | + return false; |
| 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 | - | ||
| 99 | -// 校验模块 | ||
| 100 | -const validAreaPicker = () => { | ||
| 101 | - // 必填项 | ||
| 102 | - if (props.item.component_props.required && !fieldValue.value) { | ||
| 103 | - show_empty.value = true; | ||
| 104 | - } else if (props.item.component_props.required && !address.value) { | ||
| 105 | - show_empty.value = true; | ||
| 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> | ... | ... |
-
Please register or login to post a comment