Showing
6 changed files
with
234 additions
and
32 deletions
| ... | @@ -7,11 +7,14 @@ export {} | ... | @@ -7,11 +7,14 @@ export {} |
| 7 | 7 | ||
| 8 | declare module '@vue/runtime-core' { | 8 | declare module '@vue/runtime-core' { |
| 9 | export interface GlobalComponents { | 9 | export interface GlobalComponents { |
| 10 | + Appointment: typeof import('./src/components/Appointment/index.vue')['default'] | ||
| 11 | + AppointmentField: typeof import('./src/components/AppointmentField/index.vue')['default'] | ||
| 10 | AreaPickerField: typeof import('./src/components/AreaPickerField/index.vue')['default'] | 12 | AreaPickerField: typeof import('./src/components/AreaPickerField/index.vue')['default'] |
| 11 | ButtonField: typeof import('./src/components/ButtonField/index.vue')['default'] | 13 | ButtonField: typeof import('./src/components/ButtonField/index.vue')['default'] |
| 12 | CalendarField: typeof import('./src/components/CalendarField/index.vue')['default'] | 14 | CalendarField: typeof import('./src/components/CalendarField/index.vue')['default'] |
| 13 | CheckboxField: typeof import('./src/components/CheckboxField/index.vue')['default'] | 15 | CheckboxField: typeof import('./src/components/CheckboxField/index.vue')['default'] |
| 14 | ContactField: typeof import('./src/components/ContactField/index.vue')['default'] | 16 | ContactField: typeof import('./src/components/ContactField/index.vue')['default'] |
| 17 | + copy: typeof import('./src/components/DesField copy/index.vue')['default'] | ||
| 15 | DatePickerField: typeof import('./src/components/DatePickerField/index.vue')['default'] | 18 | DatePickerField: typeof import('./src/components/DatePickerField/index.vue')['default'] |
| 16 | DateTimePickerField: typeof import('./src/components/DateTimePickerField/index.vue')['default'] | 19 | DateTimePickerField: typeof import('./src/components/DateTimePickerField/index.vue')['default'] |
| 17 | DesField: typeof import('./src/components/DesField/index.vue')['default'] | 20 | DesField: typeof import('./src/components/DesField/index.vue')['default'] |
| ... | @@ -48,11 +51,13 @@ declare module '@vue/runtime-core' { | ... | @@ -48,11 +51,13 @@ declare module '@vue/runtime-core' { |
| 48 | VanCol: typeof import('vant/es')['Col'] | 51 | VanCol: typeof import('vant/es')['Col'] |
| 49 | VanConfigProvider: typeof import('vant/es')['ConfigProvider'] | 52 | VanConfigProvider: typeof import('vant/es')['ConfigProvider'] |
| 50 | VanDatePicker: typeof import('vant/es')['DatePicker'] | 53 | VanDatePicker: typeof import('vant/es')['DatePicker'] |
| 54 | + VanDialog: typeof import('vant/es')['Dialog'] | ||
| 51 | VanDivider: typeof import('vant/es')['Divider'] | 55 | VanDivider: typeof import('vant/es')['Divider'] |
| 52 | VanField: typeof import('vant/es')['Field'] | 56 | VanField: typeof import('vant/es')['Field'] |
| 53 | VanForm: typeof import('vant/es')['Form'] | 57 | VanForm: typeof import('vant/es')['Form'] |
| 54 | VanIcon: typeof import('vant/es')['Icon'] | 58 | VanIcon: typeof import('vant/es')['Icon'] |
| 55 | VanImage: typeof import('vant/es')['Image'] | 59 | VanImage: typeof import('vant/es')['Image'] |
| 60 | + VanInput: typeof import('vant/es')['Input'] | ||
| 56 | VanLoading: typeof import('vant/es')['Loading'] | 61 | VanLoading: typeof import('vant/es')['Loading'] |
| 57 | VanNoticeBar: typeof import('vant/es')['NoticeBar'] | 62 | VanNoticeBar: typeof import('vant/es')['NoticeBar'] |
| 58 | VanNumberKeyboard: typeof import('vant/es')['NumberKeyboard'] | 63 | VanNumberKeyboard: typeof import('vant/es')['NumberKeyboard'] | ... | ... |
src/components/AppointmentField/index.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2022-08-29 14:31:20 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2023-03-27 17:52:50 | ||
| 5 | + * @FilePath: /data-table/src/components/AppointmentField/index.vue | ||
| 6 | + * @Description: 描述文本控件 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div class="Appointment-field-page"> | ||
| 10 | + <div class="label"> | ||
| 11 | + <span v-if="item.component_props.required"> *</span> | ||
| 12 | + {{ item.component_props.label }} | ||
| 13 | + </div> | ||
| 14 | + <van-row v-for="(opt, index) in item.component_props.options" :key="index" style="padding: 0 1rem 0rem 1rem;"> | ||
| 15 | + <van-col span="6"> | ||
| 16 | + <div style="font-size: 1rem; line-height: 3;">{{ opt.title }}</div> | ||
| 17 | + </van-col> | ||
| 18 | + <van-col span="18"> | ||
| 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> | ||
| 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> | ||
| 47 | + | ||
| 48 | +<script setup> | ||
| 49 | +import { styleColor } from "@/constant.js"; | ||
| 50 | +import { showDialog } from 'vant'; | ||
| 51 | + | ||
| 52 | +const props = defineProps({ | ||
| 53 | + item: Object, | ||
| 54 | +}); | ||
| 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 | + | ||
| 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 | +// 隐藏显示 | ||
| 92 | +const HideShow = computed(() => { | ||
| 93 | + return !props.item.component_props.disabled | ||
| 94 | +}) | ||
| 95 | + | ||
| 96 | +const validAppointment = () => { | ||
| 97 | + // 必填项 | ||
| 98 | + if (props.item.component_props.required && !picker_value.value) { | ||
| 99 | + show_empty.value = true; | ||
| 100 | + } else { | ||
| 101 | + show_empty.value = false; | ||
| 102 | + } | ||
| 103 | + return !show_empty.value; | ||
| 104 | +}; | ||
| 105 | + | ||
| 106 | +defineExpose({ validAppointment }); | ||
| 107 | +</script> | ||
| 108 | + | ||
| 109 | +<style lang="less" scoped> | ||
| 110 | +.Appointment-field-page { | ||
| 111 | + .label { | ||
| 112 | + padding: 1rem 1rem 0 1rem; | ||
| 113 | + font-size: 0.9rem; | ||
| 114 | + font-weight: bold; | ||
| 115 | + span { | ||
| 116 | + color: red; | ||
| 117 | + } | ||
| 118 | + } | ||
| 119 | +} | ||
| 120 | + | ||
| 121 | +// :deep(.van-field__body) { | ||
| 122 | +// border: 1px solid #eaeaea; | ||
| 123 | +// border-radius: 0.25rem; | ||
| 124 | +// padding: 0.25rem 0.5rem; | ||
| 125 | +// } | ||
| 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> |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-30 13:46:51 | 2 | * @Date: 2022-08-30 13:46:51 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2023-03-03 21:11:24 | 4 | + * @LastEditTime: 2023-03-27 16:55:35 |
| 5 | * @FilePath: /data-table/src/components/PickerField/index.vue | 5 | * @FilePath: /data-table/src/components/PickerField/index.vue |
| 6 | * @Description: 单列选择器组件 | 6 | * @Description: 单列选择器组件 |
| 7 | --> | 7 | --> | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-09-08 15:47:54 | 2 | * @Date: 2022-09-08 15:47:54 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2023-01-31 22:57:40 | 4 | + * @LastEditTime: 2023-03-27 17:14:53 |
| 5 | * @FilePath: /data-table/src/components/RatePickerField/index.vue | 5 | * @FilePath: /data-table/src/components/RatePickerField/index.vue |
| 6 | * @Description: 评分选择控件 | 6 | * @Description: 评分选择控件 |
| 7 | --> | 7 | --> | ... | ... |
| ... | @@ -29,6 +29,7 @@ import ButtonField from '@/components/ButtonField/index.vue' | ... | @@ -29,6 +29,7 @@ import ButtonField from '@/components/ButtonField/index.vue' |
| 29 | import NoteField from '@/components/NoteField/index.vue'; | 29 | import NoteField from '@/components/NoteField/index.vue'; |
| 30 | import NameField from '@/components/NameField/index.vue'; | 30 | import NameField from '@/components/NameField/index.vue'; |
| 31 | import GenderField from '@/components/GenderField/index.vue'; | 31 | import GenderField from '@/components/GenderField/index.vue'; |
| 32 | +import AppointmentField from '@/components/AppointmentField/index.vue'; | ||
| 32 | 33 | ||
| 33 | /** | 34 | /** |
| 34 | * 生成自定义组件类型 | 35 | * 生成自定义组件类型 |
| ... | @@ -58,6 +59,7 @@ import GenderField from '@/components/GenderField/index.vue'; | ... | @@ -58,6 +59,7 @@ import GenderField from '@/components/GenderField/index.vue'; |
| 58 | * @type note 富文本控件 NoteField | 59 | * @type note 富文本控件 NoteField |
| 59 | * @type name 姓名控件 NameField | 60 | * @type name 姓名控件 NameField |
| 60 | * @type gender 性别控件 GenderField | 61 | * @type gender 性别控件 GenderField |
| 62 | + * @type appointment 预约控件 AppointmentField | ||
| 61 | */ | 63 | */ |
| 62 | export function createComponentType(data) { | 64 | export function createComponentType(data) { |
| 63 | // 判断类型和使用组件 | 65 | // 判断类型和使用组件 |
| ... | @@ -178,5 +180,9 @@ export function createComponentType(data) { | ... | @@ -178,5 +180,9 @@ export function createComponentType(data) { |
| 178 | item.name = item.key; | 180 | item.name = item.key; |
| 179 | item.component = GenderField; | 181 | item.component = GenderField; |
| 180 | } | 182 | } |
| 183 | + if (item.component_props.tag === 'appointment') { | ||
| 184 | + item.name = item.key; | ||
| 185 | + item.component = AppointmentField; | ||
| 186 | + } | ||
| 181 | }) | 187 | }) |
| 182 | } | 188 | } | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-07-18 10:22:22 | 2 | * @Date: 2022-07-18 10:22:22 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2023-03-14 14:41:17 | 4 | + * @LastEditTime: 2023-03-27 18:30:02 |
| 5 | * @FilePath: /data-table/src/views/index.vue | 5 | * @FilePath: /data-table/src/views/index.vue |
| 6 | * @Description: 首页 | 6 | * @Description: 首页 |
| 7 | --> | 7 | --> |
| ... | @@ -26,13 +26,13 @@ | ... | @@ -26,13 +26,13 @@ |
| 26 | <van-cell-group :border="false"> | 26 | <van-cell-group :border="false"> |
| 27 | <component v-for="(item, index) in formData" :id="item.key" :ref="(el) => setRefMap(el, item)" :key="index" | 27 | <component v-for="(item, index) in formData" :id="item.key" :ref="(el) => setRefMap(el, item)" :key="index" |
| 28 | :is="item.component" :item="item" @active="onActive" /> | 28 | :is="item.component" :item="item" @active="onActive" /> |
| 29 | - </van-cell-group> | 29 | + </van-cell-group> |
| 30 | - <div v-if="formData.length && PCommit.visible" style="margin: 16px"> | 30 | + <div v-if="formData.length && PCommit.visible" style="margin: 16px"> |
| 31 | - <van-button round block type="primary" native-type="submit"> | 31 | + <van-button round block type="primary" native-type="submit"> |
| 32 | - {{ PCommit.text ? PCommit.text : '提交' }} | 32 | + {{ PCommit.text ? PCommit.text : '提交' }} |
| 33 | - </van-button> | 33 | + </van-button> |
| 34 | - </div> | 34 | + </div> |
| 35 | - <!-- <van-cell-group :border="false"> | 35 | + <!-- <van-cell-group :border="false"> |
| 36 | <component | 36 | <component |
| 37 | v-for="(item, index) in mockData" | 37 | v-for="(item, index) in mockData" |
| 38 | :id="item.key" | 38 | :id="item.key" |
| ... | @@ -42,12 +42,12 @@ | ... | @@ -42,12 +42,12 @@ |
| 42 | :item="item" | 42 | :item="item" |
| 43 | @active="onActive" | 43 | @active="onActive" |
| 44 | /> | 44 | /> |
| 45 | - </van-cell-group> | 45 | + </van-cell-group> |
| 46 | - <div v-if="mockData.length && PCommit.visible" style="margin: 16px"> | 46 | + <div v-if="mockData.length && PCommit.visible" style="margin: 16px"> |
| 47 | - <van-button round block type="primary" native-type="submit"> | 47 | + <van-button round block type="primary" native-type="submit"> |
| 48 | - {{ PCommit.text ? PCommit.text : '提交' }} | 48 | + {{ PCommit.text ? PCommit.text : '提交' }} |
| 49 | - </van-button> | 49 | + </van-button> |
| 50 | - </div> --> | 50 | + </div> --> |
| 51 | </van-form> | 51 | </van-form> |
| 52 | </van-config-provider> | 52 | </van-config-provider> |
| 53 | </div> | 53 | </div> |
| ... | @@ -159,6 +159,7 @@ const image_uploader = ref([]); | ... | @@ -159,6 +159,7 @@ const image_uploader = ref([]); |
| 159 | const file_uploader = ref([]); | 159 | const file_uploader = ref([]); |
| 160 | const sign = ref([]); | 160 | const sign = ref([]); |
| 161 | const rate_picker = ref([]); | 161 | const rate_picker = ref([]); |
| 162 | +const appointment = ref([]); | ||
| 162 | // 动态绑定ref数据 | 163 | // 动态绑定ref数据 |
| 163 | const setRefMap = (el, item) => { | 164 | const setRefMap = (el, item) => { |
| 164 | if (el) { | 165 | if (el) { |
| ... | @@ -177,6 +178,9 @@ const setRefMap = (el, item) => { | ... | @@ -177,6 +178,9 @@ const setRefMap = (el, item) => { |
| 177 | if (item.component_props.tag === "rate_picker") { | 178 | if (item.component_props.tag === "rate_picker") { |
| 178 | rate_picker.value.push(el); | 179 | rate_picker.value.push(el); |
| 179 | } | 180 | } |
| 181 | + if (item.component_props.tag === "appointment") { | ||
| 182 | + appointment.value.push(el); | ||
| 183 | + } | ||
| 180 | } | 184 | } |
| 181 | }; | 185 | }; |
| 182 | 186 | ||
| ... | @@ -248,26 +252,66 @@ onMounted(async () => { | ... | @@ -248,26 +252,66 @@ onMounted(async () => { |
| 248 | formData.value = formatData(page_form); | 252 | formData.value = formatData(page_form); |
| 249 | mockData.value = [ | 253 | mockData.value = [ |
| 250 | { | 254 | { |
| 251 | - key: "111", | 255 | + key: "field_1", |
| 252 | - value: "", | ||
| 253 | - component: "", | ||
| 254 | - component_props: { | ||
| 255 | - name: "name", | ||
| 256 | - tag: "name", | ||
| 257 | - label: "姓名", | ||
| 258 | - required: true, | ||
| 259 | - }, | ||
| 260 | - }, | ||
| 261 | - { | ||
| 262 | - key: "222", | ||
| 263 | value: "", | 256 | value: "", |
| 264 | component: "", | 257 | component: "", |
| 265 | component_props: { | 258 | component_props: { |
| 266 | - name: "gender", | 259 | + name: "appointment", |
| 267 | - tag: "gender", | 260 | + tag: "appointment", |
| 268 | - label: "性别", | 261 | + label: "预约时间", |
| 269 | - default: '男', | 262 | + default: '', |
| 270 | required: true, | 263 | required: true, |
| 264 | + placeholder: '', | ||
| 265 | + appointment_title: '选择入寺时间', | ||
| 266 | + options: [{ | ||
| 267 | + title: '03月27日', | ||
| 268 | + placeholder: '剩余余量 9878', | ||
| 269 | + value: '', | ||
| 270 | + disabled: false, | ||
| 271 | + columns: [{ | ||
| 272 | + checked : false, | ||
| 273 | + disabled : false, | ||
| 274 | + value: '1', | ||
| 275 | + text : "16:00-17:30 余1399", | ||
| 276 | + }, { | ||
| 277 | + checked : false, | ||
| 278 | + disabled : true, | ||
| 279 | + value: '2', | ||
| 280 | + text : "18:00-19:30 余1399", | ||
| 281 | + }] | ||
| 282 | + }, { | ||
| 283 | + title: '03月28日', | ||
| 284 | + placeholder: '剩余余量 9878', | ||
| 285 | + value: '', | ||
| 286 | + disabled: false, | ||
| 287 | + columns: [{ | ||
| 288 | + checked : false, | ||
| 289 | + disabled : true, | ||
| 290 | + value: '3', | ||
| 291 | + text : "16:00-17:30 余1399", | ||
| 292 | + }, { | ||
| 293 | + checked : false, | ||
| 294 | + disabled : false, | ||
| 295 | + value: '4', | ||
| 296 | + text : "16:00-17:30 余1399", | ||
| 297 | + }] | ||
| 298 | + }, { | ||
| 299 | + title: '03月28日', | ||
| 300 | + placeholder: '等待预约(提前一天)', | ||
| 301 | + value: '', | ||
| 302 | + disabled: true, | ||
| 303 | + columns: [{ | ||
| 304 | + checked : false, | ||
| 305 | + disabled : true, | ||
| 306 | + value: '5', | ||
| 307 | + text : "12:00-13:30 余1399", | ||
| 308 | + }, { | ||
| 309 | + checked : false, | ||
| 310 | + disabled : false, | ||
| 311 | + value: '6', | ||
| 312 | + text : "14:00-15:30 余1399", | ||
| 313 | + }] | ||
| 314 | + }] | ||
| 271 | }, | 315 | }, |
| 272 | }, | 316 | }, |
| 273 | ]; | 317 | ]; |
| ... | @@ -404,6 +448,9 @@ const onActive = (item) => { | ... | @@ -404,6 +448,9 @@ const onActive = (item) => { |
| 404 | if (item.type === "picker") { // 下拉框控件 | 448 | if (item.type === "picker") { // 下拉框控件 |
| 405 | postData.value = _.assign(postData.value, { [item.key]: item.value }); | 449 | postData.value = _.assign(postData.value, { [item.key]: item.value }); |
| 406 | } | 450 | } |
| 451 | + if (item.type === "appointment") { // 预约控件 | ||
| 452 | + postData.value = _.assign(postData.value, { [item.key]: item.value }); | ||
| 453 | + } | ||
| 407 | if (item.type === "radio") { // 单选控件 | 454 | if (item.type === "radio") { // 单选控件 |
| 408 | postData.value = _.assign(postData.value, { [item.key]: item.affix ? item.affix : item.value }); | 455 | postData.value = _.assign(postData.value, { [item.key]: item.affix ? item.affix : item.value }); |
| 409 | } | 456 | } |
| ... | @@ -488,6 +535,18 @@ const validOther = () => { | ... | @@ -488,6 +535,18 @@ const validOther = () => { |
| 488 | } | 535 | } |
| 489 | }); | 536 | }); |
| 490 | } | 537 | } |
| 538 | + if (appointment.value) { | ||
| 539 | + // 预约时间控件 | ||
| 540 | + appointment.value.forEach((item, index) => { | ||
| 541 | + if (!appointment.value[index].validAppointment()) { | ||
| 542 | + valid = { | ||
| 543 | + status: appointment.value[index].validAppointment(), | ||
| 544 | + key: "appointment", | ||
| 545 | + }; | ||
| 546 | + return false; | ||
| 547 | + } | ||
| 548 | + }); | ||
| 549 | + } | ||
| 491 | return valid; | 550 | return valid; |
| 492 | }; | 551 | }; |
| 493 | 552 | ... | ... |
-
Please register or login to post a comment