Showing
3 changed files
with
100 additions
and
91 deletions
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-31 11:45:30 | 2 | * @Date: 2022-08-31 11:45:30 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2023-02-10 10:11:05 | 4 | + * @LastEditTime: 2023-04-07 16:41:40 |
| 5 | - * @FilePath: /data-table/src/components/TimePickerField/index.vue | 5 | + * @FilePath: /custom_form/src/components/TimePickerField/index.vue |
| 6 | * @Description: 时间选择组件 | 6 | * @Description: 时间选择组件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | <div v-if="HideShow" class="time-picker-field"> | 9 | <div v-if="HideShow" class="time-picker-field"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | - <span v-if="item.component_props.required"> *</span> | 11 | + <text v-if="item.component_props.required"> *</text> |
| 12 | {{ item.component_props.label }} | 12 | {{ item.component_props.label }} |
| 13 | </div> | 13 | </div> |
| 14 | - <van-field | 14 | + <nut-cell desc-text-align="left" :desc="popupDesc" @click="onTap" is-link style="border: 1px solid #eaeaea; border-radius: 0.25rem; padding: 0.25rem 0.5rem;"></nut-cell> |
| 15 | - v-model="item.value" | 15 | + <div |
| 16 | - is-link | 16 | + v-if="show_error" |
| 17 | - readonly | 17 | + style="padding: 5px; color: red; font-size: 12px;" |
| 18 | - :name="item.key" | 18 | + > |
| 19 | - :required="item.component_props.required" | 19 | + {{ error_msg }} |
| 20 | - :disabled="item.component_props.readonly" | 20 | + </div> |
| 21 | - :placeholder="item.component_props.placeholder ? item.component_props.placeholder : '请选择时间'" | 21 | + <nut-popup position="bottom" v-model:visible="showPicker"> |
| 22 | - :rules="rules" | 22 | + <nut-date-picker |
| 23 | - @click="onTap" | ||
| 24 | - :border="false" | ||
| 25 | - /> | ||
| 26 | - <van-popup v-model:show="showPicker" position="bottom"> | ||
| 27 | - <van-time-picker | ||
| 28 | v-model="currentTime" | 23 | v-model="currentTime" |
| 29 | - title="请选择时间" | 24 | + title="时间选择" |
| 30 | - :columns-type="columns_type" | 25 | + :type="columns_type" |
| 31 | @confirm="onConfirm" | 26 | @confirm="onConfirm" |
| 32 | @cancel="showPicker = false" | 27 | @cancel="showPicker = false" |
| 33 | - /> | 28 | + :is-show-chinese="true" |
| 34 | - </van-popup> | 29 | + > |
| 30 | + </nut-date-picker> | ||
| 31 | + </nut-popup> | ||
| 35 | </div> | 32 | </div> |
| 36 | </template> | 33 | </template> |
| 37 | 34 | ||
| 38 | <script setup> | 35 | <script setup> |
| 36 | +import { ref, computed, watch, onMounted, reactive } from "vue"; | ||
| 39 | import dayjs from "dayjs"; | 37 | import dayjs from "dayjs"; |
| 40 | 38 | ||
| 41 | const props = defineProps({ | 39 | const props = defineProps({ |
| ... | @@ -45,8 +43,12 @@ const props = defineProps({ | ... | @@ -45,8 +43,12 @@ const props = defineProps({ |
| 45 | const HideShow = computed(() => { | 43 | const HideShow = computed(() => { |
| 46 | return !props.item.component_props.disabled | 44 | return !props.item.component_props.disabled |
| 47 | }) | 45 | }) |
| 46 | + | ||
| 47 | +const emit = defineEmits(["active"]); | ||
| 48 | + | ||
| 48 | const showPicker = ref(false); | 49 | const showPicker = ref(false); |
| 49 | -const currentTime = ref([]); | 50 | +const popupDesc = ref(''); |
| 51 | +const currentTime = ref(''); | ||
| 50 | const readonly = props.item.component_props.readonly; | 52 | const readonly = props.item.component_props.readonly; |
| 51 | 53 | ||
| 52 | const onTap = () => { | 54 | const onTap = () => { |
| ... | @@ -55,94 +57,81 @@ const onTap = () => { | ... | @@ -55,94 +57,81 @@ const onTap = () => { |
| 55 | } | 57 | } |
| 56 | 58 | ||
| 57 | const onConfirm = ({ selectedValues, selectedOptions }) => { | 59 | const onConfirm = ({ selectedValues, selectedOptions }) => { |
| 58 | - props.item.value = selectedValues.join(":"); | 60 | + popupDesc.value = selectedOptions.map((val) => val.value).join(':'); |
| 61 | + props.item.value = { | ||
| 62 | + key: "date", | ||
| 63 | + filed_name: props.item.key, | ||
| 64 | + value: selectedOptions.map((val) => val.value).join(':'), | ||
| 65 | + }; | ||
| 66 | + emit("active", props.item.value); | ||
| 59 | showPicker.value = false; | 67 | showPicker.value = false; |
| 68 | + validTime() | ||
| 60 | }; | 69 | }; |
| 61 | 70 | ||
| 62 | -const columns_type = ref([]); | 71 | +const columns_type = ref('time'); |
| 63 | -const date_format = props.item.component_props.data_dateformat; // HH:mm=时分,HH:mm:ss=时分秒 | 72 | +// const date_format = props.item.component_props.data_dateformat; // HH:mm=时分,HH:mm:ss=时分秒 |
| 64 | onMounted(() => { | 73 | onMounted(() => { |
| 65 | // 根据默认值时间调整显示 | 74 | // 根据默认值时间调整显示 |
| 66 | - currentTime.value = props.item.component_props.default ? props.item.component_props.default.split(":") : props.item.value.split(":"); | 75 | + popupDesc.value = props.item.component_props.default ? props.item.component_props.default : '请选择'; |
| 67 | - let Hour = '' | 76 | + const default_time = props.item.component_props.default ? props.item.component_props.default.split(":") : [0 , 0]; |
| 68 | - let Minute = '' | 77 | + currentTime.value = new Date(2023, 1, 1, +default_time[0], +default_time[1]) |
| 69 | - let Second = '' | ||
| 70 | - if (!props.item.component_props.default) { | ||
| 71 | - Hour = String(dayjs().hour()); | ||
| 72 | - Minute = String(dayjs().minute()); | ||
| 73 | - Second = String(dayjs().second()); | ||
| 74 | - } else { | ||
| 75 | - Hour = currentTime.value[0]; | ||
| 76 | - Minute = currentTime.value[1]; | ||
| 77 | - Second = currentTime.value[2]; | ||
| 78 | - } | ||
| 79 | - switch (date_format) { | ||
| 80 | - case "HH:mm": | ||
| 81 | - columns_type.value = ['hour', 'minute']; | ||
| 82 | - // 设置默认值 | ||
| 83 | - currentTime.value = [Hour, Minute]; | ||
| 84 | - break; | ||
| 85 | - case "HH:mm:ss": | ||
| 86 | - columns_type.value = ['hour', 'minute', 'second']; | ||
| 87 | - // 设置默认值 | ||
| 88 | - currentTime.value = [Hour, Minute, Second]; | ||
| 89 | - break; | ||
| 90 | - } | ||
| 91 | }); | 78 | }); |
| 92 | 79 | ||
| 93 | const required = props.item.component_props.required; | 80 | const required = props.item.component_props.required; |
| 94 | const data_minvalue = props.item.component_props.data_minvalue; | 81 | const data_minvalue = props.item.component_props.data_minvalue; |
| 95 | const data_maxvalue = props.item.component_props.data_maxvalue; | 82 | const data_maxvalue = props.item.component_props.data_maxvalue; |
| 96 | -const validator = (val) => { | 83 | + |
| 97 | - if (required && !val) { | 84 | +// 错误提示 |
| 98 | - return false; | 85 | +const show_error = ref(false); |
| 99 | - } else if (val && data_minvalue && val < data_minvalue) { | 86 | +const error_msg = ref(''); |
| 100 | - return false; | 87 | +// 校验模块 |
| 101 | - } else if (val && data_maxvalue && val > data_maxvalue) { | 88 | +const validTime = () => { |
| 102 | - return false; | 89 | + // 必填项 |
| 90 | + if (required && !popupDesc.value) { | ||
| 91 | + show_error.value = true; | ||
| 92 | + error_msg.value = '必填项不能为空' | ||
| 93 | + } else if (required && popupDesc.value && data_minvalue && popupDesc.value < data_minvalue) { | ||
| 94 | + show_error.value = true; | ||
| 95 | + error_msg.value = "最小可选:" + data_minvalue; | ||
| 96 | + } else if (required && popupDesc.value && data_maxvalue && popupDesc.value > data_maxvalue) { | ||
| 97 | + show_error.value = true; | ||
| 98 | + error_msg.value = "最大可选:" + data_maxvalue; | ||
| 103 | } else { | 99 | } else { |
| 104 | - return true; | 100 | + show_error.value = false; |
| 101 | + error_msg.value = '' | ||
| 105 | } | 102 | } |
| 103 | + return !show_error.value; | ||
| 106 | }; | 104 | }; |
| 107 | -// 错误提示文案 | 105 | + |
| 108 | -const validatorMessage = (val, rule) => { | 106 | +defineExpose({ validTime, id: props.item.key }); |
| 109 | - if (required && !val) { | ||
| 110 | - return "必填项不能为空"; | ||
| 111 | - } else if (val && data_minvalue && val < data_minvalue) { | ||
| 112 | - return "最小可选:" + data_minvalue; | ||
| 113 | - } else if (val && data_maxvalue && val > data_maxvalue) { | ||
| 114 | - return "最大可选:" + data_maxvalue; | ||
| 115 | - } | ||
| 116 | -}; | ||
| 117 | -const rules = [{ validator, message: validatorMessage }]; | ||
| 118 | </script> | 107 | </script> |
| 119 | 108 | ||
| 120 | -<style lang="less" scoped> | 109 | +<style lang="less"> |
| 121 | .time-picker-field { | 110 | .time-picker-field { |
| 122 | margin: 1rem; | 111 | margin: 1rem; |
| 123 | .label { | 112 | .label { |
| 124 | - // padding: 1rem 1rem 0 1rem; | 113 | + padding-bottom: 20px; |
| 125 | - font-size: 0.9rem; | 114 | + font-size: 26px; |
| 126 | font-weight: bold; | 115 | font-weight: bold; |
| 127 | 116 | ||
| 128 | - span { | 117 | + text { |
| 129 | color: red; | 118 | color: red; |
| 130 | } | 119 | } |
| 131 | } | 120 | } |
| 132 | 121 | ||
| 133 | - :deep(.van-icon) { // 处理正式服务器上箭头上下位移问题 | 122 | + // :deep(.van-icon) { // 处理正式服务器上箭头上下位移问题 |
| 134 | - font-size: var(--van-cell-icon-size); | 123 | + // font-size: var(--van-cell-icon-size); |
| 135 | - line-height: var(--van-cell-line-height); | 124 | + // line-height: var(--van-cell-line-height); |
| 136 | - } | 125 | + // } |
| 137 | } | 126 | } |
| 138 | 127 | ||
| 139 | -:deep(.van-cell--clickable) { | 128 | +// :deep(.van-cell--clickable) { |
| 140 | - border: 1px solid #eaeaea; | 129 | +// border: 1px solid #eaeaea; |
| 141 | - border-radius: 0.25rem; | 130 | +// border-radius: 0.25rem; |
| 142 | - padding: 0.25rem 0.5rem; | 131 | +// padding: 0.25rem 0.5rem; |
| 143 | - margin-top: 0.5rem; | 132 | +// margin-top: 0.5rem; |
| 144 | - input { | 133 | +// input { |
| 145 | - color: #323233; | 134 | +// color: #323233; |
| 146 | - } | 135 | +// } |
| 147 | -} | 136 | +// } |
| 148 | </style> | 137 | </style> | ... | ... |
| ... | @@ -6,7 +6,7 @@ import CheckboxField from '@/components/CheckboxField/index.vue' | ... | @@ -6,7 +6,7 @@ import CheckboxField from '@/components/CheckboxField/index.vue' |
| 6 | import PickerField from '@/components/PickerField/index.vue' | 6 | import PickerField from '@/components/PickerField/index.vue' |
| 7 | import AreaPickerField from '@/components/AreaPickerField/index.vue' | 7 | import AreaPickerField from '@/components/AreaPickerField/index.vue' |
| 8 | import DatePickerField from '@/components/DatePickerField/index.vue' | 8 | import DatePickerField from '@/components/DatePickerField/index.vue' |
| 9 | -// import TimePickerField from '@/components/TimePickerField/index.vue' | 9 | +import TimePickerField from '@/components/TimePickerField/index.vue' |
| 10 | // import DateTimePickerField from '@/components/DateTimePickerField/index.vue' | 10 | // import DateTimePickerField from '@/components/DateTimePickerField/index.vue' |
| 11 | // import ImageUploaderField from '@/components/ImageUploaderField/index.vue' | 11 | // import ImageUploaderField from '@/components/ImageUploaderField/index.vue' |
| 12 | // import FileUploaderField from '@/components/FileUploaderField/index.vue' | 12 | // import FileUploaderField from '@/components/FileUploaderField/index.vue' |
| ... | @@ -99,9 +99,9 @@ export function createComponentType(data) { | ... | @@ -99,9 +99,9 @@ export function createComponentType(data) { |
| 99 | if (item.component_props.tag === 'date') { | 99 | if (item.component_props.tag === 'date') { |
| 100 | item.component = DatePickerField | 100 | item.component = DatePickerField |
| 101 | } | 101 | } |
| 102 | - // if (item.component_props.tag === 'time') { | 102 | + if (item.component_props.tag === 'time') { |
| 103 | - // item.component = TimePickerField | 103 | + item.component = TimePickerField |
| 104 | - // } | 104 | + } |
| 105 | // if (item.component_props.tag === 'datetime') { | 105 | // if (item.component_props.tag === 'datetime') { |
| 106 | // item.component = DateTimePickerField | 106 | // item.component = DateTimePickerField |
| 107 | // } | 107 | // } | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2023-03-24 09:19:27 | 2 | * @Date: 2023-03-24 09:19:27 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2023-04-07 14:30:33 | 4 | + * @LastEditTime: 2023-04-07 16:12:27 |
| 5 | * @FilePath: /custom_form/src/pages/table/index.vue | 5 | * @FilePath: /custom_form/src/pages/table/index.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -137,6 +137,7 @@ const phone = ref([]); | ... | @@ -137,6 +137,7 @@ const phone = ref([]); |
| 137 | const email = ref([]); | 137 | const email = ref([]); |
| 138 | const address = ref([]); | 138 | const address = ref([]); |
| 139 | const date = ref([]); | 139 | const date = ref([]); |
| 140 | +const time = ref([]); | ||
| 140 | const area_picker = ref([]); | 141 | const area_picker = ref([]); |
| 141 | const image_uploader = ref([]); | 142 | const image_uploader = ref([]); |
| 142 | const file_uploader = ref([]); | 143 | const file_uploader = ref([]); |
| ... | @@ -178,6 +179,9 @@ const setRefMap = (el, item) => { | ... | @@ -178,6 +179,9 @@ const setRefMap = (el, item) => { |
| 178 | if (item.component_props.tag === "date") { | 179 | if (item.component_props.tag === "date") { |
| 179 | date.value.push(el); | 180 | date.value.push(el); |
| 180 | } | 181 | } |
| 182 | + if (item.component_props.tag === "time") { | ||
| 183 | + time.value.push(el); | ||
| 184 | + } | ||
| 181 | if (item.component_props.tag === "area_picker") { | 185 | if (item.component_props.tag === "area_picker") { |
| 182 | area_picker.value.push(el); | 186 | area_picker.value.push(el); |
| 183 | } | 187 | } |
| ... | @@ -452,6 +456,9 @@ const onActive = (item) => { | ... | @@ -452,6 +456,9 @@ const onActive = (item) => { |
| 452 | if (item.key === "date") { | 456 | if (item.key === "date") { |
| 453 | postData.value[item.filed_name] = item.value; | 457 | postData.value[item.filed_name] = item.value; |
| 454 | } | 458 | } |
| 459 | + if (item.key === "time") { | ||
| 460 | + postData.value[item.filed_name] = item.value; | ||
| 461 | + } | ||
| 455 | if (item.key === "image_uploader") { | 462 | if (item.key === "image_uploader") { |
| 456 | postData.value[item.filed_name] = item.value; | 463 | postData.value[item.filed_name] = item.value; |
| 457 | } | 464 | } |
| ... | @@ -621,6 +628,19 @@ const validOther = () => { | ... | @@ -621,6 +628,19 @@ const validOther = () => { |
| 621 | } | 628 | } |
| 622 | }); | 629 | }); |
| 623 | } | 630 | } |
| 631 | + if (time.value) { | ||
| 632 | + // 日期选择器 | ||
| 633 | + time.value.forEach((item, index) => { | ||
| 634 | + if (!time.value[index].validTime()) { | ||
| 635 | + valid = { | ||
| 636 | + status: time.value[index].validTime(), | ||
| 637 | + key: "time", | ||
| 638 | + id: time.value[index]?.id | ||
| 639 | + }; | ||
| 640 | + return false; | ||
| 641 | + } | ||
| 642 | + }); | ||
| 643 | + } | ||
| 624 | if (area_picker.value) { | 644 | if (area_picker.value) { |
| 625 | // 省市区地址 | 645 | // 省市区地址 |
| 626 | area_picker.value.forEach((item, index) => { | 646 | area_picker.value.forEach((item, index) => { | ... | ... |
-
Please register or login to post a comment