Showing
2 changed files
with
114 additions
and
84 deletions
| 1 | +<!-- | ||
| 2 | + * @Date: 2023-03-28 15:38:09 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2023-03-28 16:10:58 | ||
| 5 | + * @FilePath: /data-table/src/components/AppointmentField/MyComponent.vue | ||
| 6 | + * @Description: 自定义组件 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div style="width: 100%;"> | ||
| 10 | + <van-row v-for="(opt, index) in props.component_props.options" :key="index"> | ||
| 11 | + <van-col span="7"> | ||
| 12 | + <div style="font-size: 1rem; line-height: 3;">{{ opt.title }}</div> | ||
| 13 | + </van-col> | ||
| 14 | + <van-col span="17"> | ||
| 15 | + <van-field | ||
| 16 | + v-model="opt.value" | ||
| 17 | + is-link | ||
| 18 | + readonly | ||
| 19 | + :placeholder="opt.placeholder" | ||
| 20 | + @click="onClick(index, opt)" | ||
| 21 | + :border="false" | ||
| 22 | + /> | ||
| 23 | + </van-col> | ||
| 24 | + </van-row> | ||
| 25 | + </div> | ||
| 26 | + <van-popup v-model:show="showPicker" position="bottom"> | ||
| 27 | + <van-picker | ||
| 28 | + :title="props.component_props.appointment_title" | ||
| 29 | + :columns="columns" | ||
| 30 | + @confirm="onConfirm" | ||
| 31 | + @cancel="showPicker = false" | ||
| 32 | + /> | ||
| 33 | + </van-popup> | ||
| 34 | +</template> | ||
| 35 | + | ||
| 36 | +<script setup> | ||
| 37 | +import { inject, ref } from 'vue' | ||
| 38 | +import { useCustomFieldValue } from '@vant/use'; | ||
| 39 | +import { styleColor } from "@/constant.js"; | ||
| 40 | +import { showDialog } from 'vant'; | ||
| 41 | + | ||
| 42 | +// 获取父组件传值 | ||
| 43 | +const props = inject('props'); | ||
| 44 | + | ||
| 45 | +const showPicker = ref(false); | ||
| 46 | +const picker_value = ref(''); | ||
| 47 | +const columns = ref([]); | ||
| 48 | +const current_index = ref(0); | ||
| 49 | + | ||
| 50 | +const onClick = (index, opt) => { | ||
| 51 | + if (opt.disabled) { | ||
| 52 | + showDialog({ | ||
| 53 | + title: '温馨提示', | ||
| 54 | + message: '暂时不能预约!', | ||
| 55 | + theme: 'round-button', | ||
| 56 | + width: '320px', | ||
| 57 | + confirmButtonColor: styleColor.baseColor | ||
| 58 | + }).then(() => { | ||
| 59 | + // on close | ||
| 60 | + }); | ||
| 61 | + return false; | ||
| 62 | + } | ||
| 63 | + current_index.value = index; | ||
| 64 | + columns.value = props.component_props.options[index]['columns']; | ||
| 65 | + showPicker.value = true; | ||
| 66 | +} | ||
| 67 | + | ||
| 68 | +const onConfirm = ({ selectedOptions }) => { | ||
| 69 | + props.component_props.options.forEach(item => { | ||
| 70 | + item.value = '' | ||
| 71 | + }) | ||
| 72 | + props.component_props.options[current_index.value]['value'] = selectedOptions[0]?.text; | ||
| 73 | + picker_value.value = selectedOptions[0]?.value; | ||
| 74 | + showPicker.value = false; | ||
| 75 | +}; | ||
| 76 | + | ||
| 77 | +// 此处传入的值会替代 Field 组件内部的 value | ||
| 78 | +useCustomFieldValue(() => picker_value.value); | ||
| 79 | +</script> | ||
| 80 | + | ||
| 81 | +<style lang="less" scoped> | ||
| 82 | + | ||
| 83 | +:deep(.van-cell--clickable) { | ||
| 84 | + border: 1px solid #eaeaea; | ||
| 85 | + border-radius: 0.25rem; | ||
| 86 | + padding: 0.25rem 0.5rem; | ||
| 87 | + margin-top: 0.5rem; | ||
| 88 | +} | ||
| 89 | +</style> |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-29 14:31:20 | 2 | * @Date: 2022-08-29 14:31:20 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2023-03-27 17:52:50 | 4 | + * @LastEditTime: 2023-03-28 16:16:47 |
| 5 | * @FilePath: /data-table/src/components/AppointmentField/index.vue | 5 | * @FilePath: /data-table/src/components/AppointmentField/index.vue |
| 6 | - * @Description: 描述文本控件 | 6 | + * @Description: 预约时间控件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | <div class="Appointment-field-page"> | 9 | <div class="Appointment-field-page"> |
| ... | @@ -11,99 +11,46 @@ | ... | @@ -11,99 +11,46 @@ |
| 11 | <span v-if="item.component_props.required"> *</span> | 11 | <span v-if="item.component_props.required"> *</span> |
| 12 | {{ item.component_props.label }} | 12 | {{ item.component_props.label }} |
| 13 | </div> | 13 | </div> |
| 14 | - <van-row v-for="(opt, index) in item.component_props.options" :key="index" style="padding: 0 1rem 0rem 1rem;"> | 14 | + <van-field :name="item.name" :rules="rules"> |
| 15 | - <van-col span="6"> | 15 | + <template #input> |
| 16 | - <div style="font-size: 1rem; line-height: 3;">{{ opt.title }}</div> | 16 | + <my-component /> |
| 17 | - </van-col> | 17 | + </template> |
| 18 | - <van-col span="18"> | 18 | + </van-field> |
| 19 | - <van-field | ||
| 20 | - v-model="opt.value" | ||
| 21 | - is-link | ||
| 22 | - readonly | ||
| 23 | - :placeholder="opt.placeholder" | ||
| 24 | - @click="onClick(index, opt)" | ||
| 25 | - :border="false" | ||
| 26 | - style="width: 100%;" | ||
| 27 | - /> | ||
| 28 | - </van-col> | ||
| 29 | - </van-row> | ||
| 30 | - <div | ||
| 31 | - v-if="show_empty" | ||
| 32 | - class="van-field__error-message" | ||
| 33 | - style="padding: 0 1rem 1rem 1rem" | ||
| 34 | - > | ||
| 35 | - 预约时间不能为空 | ||
| 36 | </div> | 19 | </div> |
| 37 | - </div> | ||
| 38 | - <van-popup v-model:show="showPicker" position="bottom"> | ||
| 39 | - <van-picker | ||
| 40 | - :title="item.component_props.appointment_title" | ||
| 41 | - :columns="columns" | ||
| 42 | - @confirm="onConfirm" | ||
| 43 | - @cancel="showPicker = false" | ||
| 44 | - /> | ||
| 45 | - </van-popup> | ||
| 46 | </template> | 20 | </template> |
| 47 | 21 | ||
| 48 | <script setup> | 22 | <script setup> |
| 49 | -import { styleColor } from "@/constant.js"; | 23 | +import { provide } from 'vue' |
| 50 | -import { showDialog } from 'vant'; | 24 | +import MyComponent from './MyComponent.vue'; |
| 51 | 25 | ||
| 52 | const props = defineProps({ | 26 | const props = defineProps({ |
| 53 | item: Object, | 27 | item: Object, |
| 54 | }); | 28 | }); |
| 55 | -const emit = defineEmits(["active"]); | ||
| 56 | -const showPicker = ref(false); | ||
| 57 | -const picker_value = ref(props.item.component_props.default); | ||
| 58 | -const columns = ref([]) | ||
| 59 | -const current_index = ref(0) | ||
| 60 | -const show_empty = ref(false); | ||
| 61 | - | ||
| 62 | -const onClick = (index, opt) => { | ||
| 63 | - if (opt.disabled) { | ||
| 64 | - showDialog({ | ||
| 65 | - title: '温馨提示', | ||
| 66 | - message: '暂时不能预约!', | ||
| 67 | - theme: 'round-button', | ||
| 68 | - width: '320px', | ||
| 69 | - confirmButtonColor: styleColor.baseColor | ||
| 70 | - }).then(() => { | ||
| 71 | - // on close | ||
| 72 | - }); | ||
| 73 | - return false; | ||
| 74 | - } | ||
| 75 | - current_index.value = index; | ||
| 76 | - columns.value = props.item.component_props.options[index]['columns']; | ||
| 77 | - showPicker.value = true | ||
| 78 | -} | ||
| 79 | 29 | ||
| 80 | -const onConfirm = ({ selectedOptions }) => { | ||
| 81 | - props.item.component_props.options.forEach(item => { | ||
| 82 | - item.value = '' | ||
| 83 | - }) | ||
| 84 | - props.item.component_props.options[current_index.value]['value'] = selectedOptions[0]?.text; | ||
| 85 | - picker_value.value = selectedOptions[0]?.value; | ||
| 86 | - showPicker.value = false; | ||
| 87 | - // 触发点自定义监听事件,配合规则显示隐藏其他字段 | ||
| 88 | - props.item.value = { key: props.item.key, value: picker_value.value, type: "appointment" }; | ||
| 89 | - emit("active", props.item.value); | ||
| 90 | -}; | ||
| 91 | // 隐藏显示 | 30 | // 隐藏显示 |
| 92 | const HideShow = computed(() => { | 31 | const HideShow = computed(() => { |
| 93 | return !props.item.component_props.disabled | 32 | return !props.item.component_props.disabled |
| 94 | }) | 33 | }) |
| 95 | 34 | ||
| 96 | -const validAppointment = () => { | 35 | +// 注入子组件属性 |
| 97 | - // 必填项 | 36 | +provide('props', props.item); |
| 98 | - if (props.item.component_props.required && !picker_value.value) { | 37 | + |
| 99 | - show_empty.value = true; | 38 | +// 规则校验 |
| 39 | +const required = props.item.component_props.required; | ||
| 40 | +const validator = (val) => { | ||
| 41 | + if (required && !val) { | ||
| 42 | + return false; | ||
| 100 | } else { | 43 | } else { |
| 101 | - show_empty.value = false; | 44 | + return true; |
| 102 | } | 45 | } |
| 103 | - return !show_empty.value; | ||
| 104 | }; | 46 | }; |
| 105 | - | 47 | +// 错误提示文案 |
| 106 | -defineExpose({ validAppointment }); | 48 | +const validatorMessage = (val, rule) => { |
| 49 | + if (required && !val) { | ||
| 50 | + return "必填项不能为空"; | ||
| 51 | + } | ||
| 52 | +}; | ||
| 53 | +const rules = [{ validator, message: validatorMessage }]; | ||
| 107 | </script> | 54 | </script> |
| 108 | 55 | ||
| 109 | <style lang="less" scoped> | 56 | <style lang="less" scoped> |
| ... | @@ -123,10 +70,4 @@ defineExpose({ validAppointment }); | ... | @@ -123,10 +70,4 @@ defineExpose({ validAppointment }); |
| 123 | // border-radius: 0.25rem; | 70 | // border-radius: 0.25rem; |
| 124 | // padding: 0.25rem 0.5rem; | 71 | // padding: 0.25rem 0.5rem; |
| 125 | // } | 72 | // } |
| 126 | -:deep(.van-cell--clickable) { | ||
| 127 | - border: 1px solid #eaeaea; | ||
| 128 | - border-radius: 0.25rem; | ||
| 129 | - padding: 0.25rem 0.5rem; | ||
| 130 | - margin-top: 0.5rem; | ||
| 131 | -} | ||
| 132 | </style> | 73 | </style> | ... | ... |
-
Please register or login to post a comment