Showing
4 changed files
with
108 additions
and
98 deletions
| ... | @@ -32,6 +32,7 @@ declare module '@vue/runtime-core' { | ... | @@ -32,6 +32,7 @@ declare module '@vue/runtime-core' { |
| 32 | NutCheckbox: typeof import('@nutui/nutui-taro')['Checkbox'] | 32 | NutCheckbox: typeof import('@nutui/nutui-taro')['Checkbox'] |
| 33 | NutCheckboxGroup: typeof import('@nutui/nutui-taro')['CheckboxGroup'] | 33 | NutCheckboxGroup: typeof import('@nutui/nutui-taro')['CheckboxGroup'] |
| 34 | NutConfigProvider: typeof import('@nutui/nutui-taro')['ConfigProvider'] | 34 | NutConfigProvider: typeof import('@nutui/nutui-taro')['ConfigProvider'] |
| 35 | + NutDatePicker: typeof import('@nutui/nutui-taro')['DatePicker'] | ||
| 35 | NutDialog: typeof import('@nutui/nutui-taro')['Dialog'] | 36 | NutDialog: typeof import('@nutui/nutui-taro')['Dialog'] |
| 36 | NutDivider: typeof import('@nutui/nutui-taro')['Divider'] | 37 | NutDivider: typeof import('@nutui/nutui-taro')['Divider'] |
| 37 | NutField: typeof import('@nutui/nutui-taro')['Field'] | 38 | NutField: typeof import('@nutui/nutui-taro')['Field'] | ... | ... |
| 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:07:31 | 4 | + * @LastEditTime: 2023-04-07 15:51:31 |
| 5 | - * @FilePath: /data-table/src/components/DatePickerField/index.vue | 5 | + * @FilePath: /custom_form/src/components/DatePickerField/index.vue |
| 6 | * @Description: 日期选择组件 | 6 | * @Description: 日期选择组件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | <div v-if="HideShow" class="date-picker-field"> | 9 | <div v-if="HideShow" class="date-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-date-picker | ||
| 28 | v-model="currentDate" | 23 | v-model="currentDate" |
| 29 | title="日期选择" | 24 | title="日期选择" |
| 25 | + :type="columns_type" | ||
| 30 | :min-date="minDate" | 26 | :min-date="minDate" |
| 31 | :max-date="maxDate" | 27 | :max-date="maxDate" |
| 32 | - :columns-type="columns_type" | ||
| 33 | @confirm="onConfirm" | 28 | @confirm="onConfirm" |
| 34 | @cancel="showPicker = false" | 29 | @cancel="showPicker = false" |
| 35 | - /> | 30 | + :is-show-chinese="true" |
| 36 | - </van-popup> | 31 | + > |
| 32 | + </nut-date-picker> | ||
| 33 | + </nut-popup> | ||
| 37 | </div> | 34 | </div> |
| 38 | </template> | 35 | </template> |
| 39 | 36 | ||
| 40 | <script setup> | 37 | <script setup> |
| 38 | +import { ref, computed, watch, onMounted, reactive } from "vue"; | ||
| 41 | import dayjs from "dayjs"; | 39 | import dayjs from "dayjs"; |
| 42 | 40 | ||
| 43 | const props = defineProps({ | 41 | const props = defineProps({ |
| 44 | item: Object, | 42 | item: Object, |
| 45 | }); | 43 | }); |
| 46 | 44 | ||
| 45 | +const emit = defineEmits(["active"]); | ||
| 46 | + | ||
| 47 | // 隐藏显示 | 47 | // 隐藏显示 |
| 48 | const HideShow = computed(() => { | 48 | const HideShow = computed(() => { |
| 49 | return !props.item.component_props.disabled | 49 | return !props.item.component_props.disabled |
| 50 | }) | 50 | }) |
| 51 | + | ||
| 51 | const showPicker = ref(false); | 52 | const showPicker = ref(false); |
| 52 | -const currentDate = ref([]); | 53 | +const popupDesc = ref('请选择'); |
| 54 | +let minDate = new Date(2020, 0, 1); | ||
| 55 | +let maxDate = new Date(2035, 10, 1); | ||
| 56 | +const currentDate = ref(''); | ||
| 53 | const readonly = props.item.component_props.readonly; | 57 | const readonly = props.item.component_props.readonly; |
| 54 | 58 | ||
| 55 | const onTap = () => { | 59 | const onTap = () => { |
| ... | @@ -57,113 +61,98 @@ const onTap = () => { | ... | @@ -57,113 +61,98 @@ const onTap = () => { |
| 57 | showPicker.value = true | 61 | showPicker.value = true |
| 58 | } | 62 | } |
| 59 | const onConfirm = ({ selectedValues, selectedOptions }) => { | 63 | const onConfirm = ({ selectedValues, selectedOptions }) => { |
| 60 | - props.item.value = selectedValues.join("-"); | 64 | + popupDesc.value = selectedOptions.map((val) => val.value).join('-'); |
| 65 | + props.item.value = { | ||
| 66 | + key: "date", | ||
| 67 | + filed_name: props.item.key, | ||
| 68 | + value: selectedOptions.map((val) => val.value).join('-'), | ||
| 69 | + }; | ||
| 70 | + emit("active", props.item.value); | ||
| 61 | showPicker.value = false; | 71 | showPicker.value = false; |
| 72 | + validDate() | ||
| 62 | }; | 73 | }; |
| 63 | 74 | ||
| 64 | -const columns_type = ref([]); | 75 | +const columns_type = ref('date'); |
| 65 | const date_format = props.item.component_props.data_dateformat; // YYYY-MM=年月,YYYY-MM-DD=年月日 | 76 | const date_format = props.item.component_props.data_dateformat; // YYYY-MM=年月,YYYY-MM-DD=年月日 |
| 66 | -// 数字前面补位 | ||
| 67 | -const formatZero = (num, len) => { | ||
| 68 | - if (String(num).length > len) { | ||
| 69 | - return num; | ||
| 70 | - } | ||
| 71 | - return (Array(len).join(0) + num).slice(-len) | ||
| 72 | -} | ||
| 73 | - | ||
| 74 | -const minDate = ref() | ||
| 75 | -const maxDate = ref() | ||
| 76 | 77 | ||
| 77 | onMounted(() => { | 78 | onMounted(() => { |
| 78 | // 根据默认值时间调整显示 | 79 | // 根据默认值时间调整显示 |
| 79 | - currentDate.value = props.item.component_props.default ? props.item.component_props.default.split("-") : props.item.value.split("-"); | 80 | + currentDate.value = new Date(props.item.component_props.default); |
| 80 | - let Year = ''; | ||
| 81 | - let Month = ''; | ||
| 82 | - let Day = ''; | ||
| 83 | - if (!props.item.component_props.default) { | ||
| 84 | - Year = String(dayjs().year()); | ||
| 85 | - Month = formatZero(dayjs().month(), 2); | ||
| 86 | - Day = formatZero(dayjs().date(), 2); | ||
| 87 | - } else { | ||
| 88 | - Year = currentDate.value[0]; | ||
| 89 | - Month = formatZero(currentDate.value[1], 2); | ||
| 90 | - Day = formatZero(currentDate.value[2], 2); | ||
| 91 | - } | ||
| 92 | switch (date_format) { | 81 | switch (date_format) { |
| 93 | case "YYYY-MM": | 82 | case "YYYY-MM": |
| 94 | - columns_type.value = ['year', 'month'] | 83 | + columns_type.value = 'year-month' |
| 95 | - // 设置默认值 | ||
| 96 | - currentDate.value = [Year, Month]; | ||
| 97 | break; | 84 | break; |
| 98 | case "YYYY-MM-DD": | 85 | case "YYYY-MM-DD": |
| 99 | - columns_type.value = ['year', 'month', 'day'] | 86 | + columns_type.value = 'date' |
| 100 | - // 设置默认值 | ||
| 101 | - currentDate.value = [Year, Month, Day]; | ||
| 102 | break; | 87 | break; |
| 103 | } | 88 | } |
| 104 | // 设置默认最大最小日期 | 89 | // 设置默认最大最小日期 |
| 105 | - if (data_minvalue.length) { | 90 | + if (data_minvalue) { |
| 106 | - const min = data_minvalue.split("-") | 91 | + const min = data_minvalue.split("-"); |
| 107 | - minDate.value = new Date(+min[0], +min[1] - 1, +min[2]) | 92 | + minDate = new Date(+min[0], +min[1] - 1, +min[2]) |
| 108 | } | 93 | } |
| 109 | - if (data_maxvalue.length) { | 94 | + if (data_maxvalue) { |
| 110 | const max = data_maxvalue.split("-") | 95 | const max = data_maxvalue.split("-") |
| 111 | - maxDate.value = new Date(+max[0], +max[1] - 1, +max[2]) | 96 | + maxDate = new Date(+max[0], +max[1] - 1, +max[2]) |
| 112 | } | 97 | } |
| 113 | }); | 98 | }); |
| 114 | 99 | ||
| 115 | const required = props.item.component_props.required; | 100 | const required = props.item.component_props.required; |
| 116 | const data_minvalue = props.item.component_props.data_minvalue; | 101 | const data_minvalue = props.item.component_props.data_minvalue; |
| 117 | const data_maxvalue = props.item.component_props.data_maxvalue; | 102 | const data_maxvalue = props.item.component_props.data_maxvalue; |
| 118 | -const validator = (val) => { | 103 | +// 错误提示 |
| 119 | - if (required && !val) { | 104 | +const show_error = ref(false); |
| 120 | - return false; | 105 | +const error_msg = ref(''); |
| 121 | - } else if (val && data_minvalue && val < data_minvalue) { | 106 | +// 校验模块 |
| 122 | - return false; | 107 | +const validDate = () => { |
| 123 | - } else if (val && data_maxvalue && val > data_maxvalue) { | 108 | + // 必填项 |
| 124 | - return false; | 109 | + if (required && !popupDesc.value) { |
| 110 | + show_error.value = true; | ||
| 111 | + error_msg.value = '必填项不能为空' | ||
| 112 | + } else if (required && popupDesc.value && data_minvalue && popupDesc.value < data_minvalue) { | ||
| 113 | + show_error.value = true; | ||
| 114 | + error_msg.value = "最小可选:" + data_minvalue; | ||
| 115 | + } else if (required && popupDesc.value && data_maxvalue && popupDesc.value > data_maxvalue) { | ||
| 116 | + show_error.value = true; | ||
| 117 | + error_msg.value = "最大可选:" + data_maxvalue; | ||
| 125 | } else { | 118 | } else { |
| 126 | - return true; | 119 | + show_error.value = false; |
| 127 | - } | 120 | + error_msg.value = '' |
| 128 | -}; | ||
| 129 | -// 错误提示文案 | ||
| 130 | -const validatorMessage = (val, rule) => { | ||
| 131 | - if (required && !val) { | ||
| 132 | - return "必填项不能为空"; | ||
| 133 | - } else if (val && data_minvalue && val < data_minvalue) { | ||
| 134 | - return "最小可选:" + data_minvalue; | ||
| 135 | - } else if (val && data_maxvalue && val > data_maxvalue) { | ||
| 136 | - return "最大可选:" + data_maxvalue; | ||
| 137 | } | 121 | } |
| 122 | + return !show_error.value; | ||
| 138 | }; | 123 | }; |
| 139 | -const rules = [{ validator, message: validatorMessage }]; | 124 | + |
| 125 | +defineExpose({ validDate, id: props.item.key }); | ||
| 140 | </script> | 126 | </script> |
| 141 | 127 | ||
| 142 | -<style lang="less" scoped> | 128 | +<style lang="less"> |
| 143 | .date-picker-field { | 129 | .date-picker-field { |
| 144 | margin: 1rem; | 130 | margin: 1rem; |
| 145 | .label { | 131 | .label { |
| 146 | - // padding: 1rem 1rem 0 1rem; | 132 | + padding-bottom: 20px; |
| 147 | - font-size: 0.9rem; | 133 | + font-size: 26px; |
| 148 | font-weight: bold; | 134 | font-weight: bold; |
| 149 | 135 | ||
| 150 | - span { | 136 | + text { |
| 151 | color: red; | 137 | color: red; |
| 152 | } | 138 | } |
| 153 | } | 139 | } |
| 154 | - :deep(.van-icon) { // 处理正式服务器上箭头上下位移问题 | 140 | + // :deep(.van-icon) { // 处理正式服务器上箭头上下位移问题 |
| 155 | - font-size: var(--van-cell-icon-size); | 141 | + // font-size: var(--van-cell-icon-size); |
| 156 | - line-height: var(--van-cell-line-height); | 142 | + // line-height: var(--van-cell-line-height); |
| 157 | - } | 143 | + // } |
| 158 | -} | 144 | + .nut-cell { |
| 159 | 145 | ||
| 160 | -:deep(.van-cell--clickable) { | ||
| 161 | - border: 1px solid #eaeaea; | ||
| 162 | - border-radius: 0.25rem; | ||
| 163 | - padding: 0.25rem 0.5rem; | ||
| 164 | - margin-top: 0.5rem; | ||
| 165 | - input { | ||
| 166 | - color: #323233; | ||
| 167 | } | 146 | } |
| 168 | } | 147 | } |
| 148 | + | ||
| 149 | +// :deep(.van-cell--clickable) { | ||
| 150 | +// border: 1px solid #eaeaea; | ||
| 151 | +// border-radius: 0.25rem; | ||
| 152 | +// padding: 0.25rem 0.5rem; | ||
| 153 | +// margin-top: 0.5rem; | ||
| 154 | +// input { | ||
| 155 | +// color: #323233; | ||
| 156 | +// } | ||
| 157 | +// } | ||
| 169 | </style> | 158 | </style> | ... | ... |
| ... | @@ -5,7 +5,7 @@ import RadioField from '@/components/RadioField/index.vue' | ... | @@ -5,7 +5,7 @@ import RadioField from '@/components/RadioField/index.vue' |
| 5 | import CheckboxField from '@/components/CheckboxField/index.vue' | 5 | 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' |
| ... | @@ -60,7 +60,7 @@ import MultiRuleField from '@/components/MultiRuleField/index.vue' | ... | @@ -60,7 +60,7 @@ import MultiRuleField from '@/components/MultiRuleField/index.vue' |
| 60 | */ | 60 | */ |
| 61 | export function createComponentType(data) { | 61 | export function createComponentType(data) { |
| 62 | // 判断类型和使用组件 | 62 | // 判断类型和使用组件 |
| 63 | - _.each(data, (item, index) => { | 63 | + _.each(data, (item) => { |
| 64 | // 必填项规则添加 | 64 | // 必填项规则添加 |
| 65 | if (item.component_props.required) { | 65 | if (item.component_props.required) { |
| 66 | item.rules = [ | 66 | item.rules = [ |
| ... | @@ -96,9 +96,9 @@ export function createComponentType(data) { | ... | @@ -96,9 +96,9 @@ export function createComponentType(data) { |
| 96 | if (item.component_props.tag === 'address') { | 96 | if (item.component_props.tag === 'address') { |
| 97 | item.component = AreaPickerField | 97 | item.component = AreaPickerField |
| 98 | } | 98 | } |
| 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 | // } | ... | ... |
| 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 13:07:06 | 4 | + * @LastEditTime: 2023-04-07 14:30:33 |
| 5 | * @FilePath: /custom_form/src/pages/table/index.vue | 5 | * @FilePath: /custom_form/src/pages/table/index.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -136,6 +136,7 @@ const number = ref([]); | ... | @@ -136,6 +136,7 @@ const number = ref([]); |
| 136 | const phone = ref([]); | 136 | 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 area_picker = ref([]); | 140 | const area_picker = ref([]); |
| 140 | const image_uploader = ref([]); | 141 | const image_uploader = ref([]); |
| 141 | const file_uploader = ref([]); | 142 | const file_uploader = ref([]); |
| ... | @@ -174,6 +175,9 @@ const setRefMap = (el, item) => { | ... | @@ -174,6 +175,9 @@ const setRefMap = (el, item) => { |
| 174 | if (item.component_props.tag === "address") { | 175 | if (item.component_props.tag === "address") { |
| 175 | address.value.push(el); | 176 | address.value.push(el); |
| 176 | } | 177 | } |
| 178 | + if (item.component_props.tag === "date") { | ||
| 179 | + date.value.push(el); | ||
| 180 | + } | ||
| 177 | if (item.component_props.tag === "area_picker") { | 181 | if (item.component_props.tag === "area_picker") { |
| 178 | area_picker.value.push(el); | 182 | area_picker.value.push(el); |
| 179 | } | 183 | } |
| ... | @@ -445,6 +449,9 @@ const onActive = (item) => { | ... | @@ -445,6 +449,9 @@ const onActive = (item) => { |
| 445 | if (item.key === "address") { | 449 | if (item.key === "address") { |
| 446 | postData.value[item.filed_name] = item.value; | 450 | postData.value[item.filed_name] = item.value; |
| 447 | } | 451 | } |
| 452 | + if (item.key === "date") { | ||
| 453 | + postData.value[item.filed_name] = item.value; | ||
| 454 | + } | ||
| 448 | if (item.key === "image_uploader") { | 455 | if (item.key === "image_uploader") { |
| 449 | postData.value[item.filed_name] = item.value; | 456 | postData.value[item.filed_name] = item.value; |
| 450 | } | 457 | } |
| ... | @@ -601,6 +608,19 @@ const validOther = () => { | ... | @@ -601,6 +608,19 @@ const validOther = () => { |
| 601 | } | 608 | } |
| 602 | }); | 609 | }); |
| 603 | } | 610 | } |
| 611 | + if (date.value) { | ||
| 612 | + // 日期选择器 | ||
| 613 | + date.value.forEach((item, index) => { | ||
| 614 | + if (!date.value[index].validDate()) { | ||
| 615 | + valid = { | ||
| 616 | + status: date.value[index].validDate(), | ||
| 617 | + key: "date", | ||
| 618 | + id: date.value[index]?.id | ||
| 619 | + }; | ||
| 620 | + return false; | ||
| 621 | + } | ||
| 622 | + }); | ||
| 623 | + } | ||
| 604 | if (area_picker.value) { | 624 | if (area_picker.value) { |
| 605 | // 省市区地址 | 625 | // 省市区地址 |
| 606 | area_picker.value.forEach((item, index) => { | 626 | area_picker.value.forEach((item, index) => { | ... | ... |
-
Please register or login to post a comment