hookehuyr

✨ feat(选择日期控件): 样式和功能调整

...@@ -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">&nbsp;*</span> 11 + <text v-if="item.component_props.required">&nbsp;*</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) => {
......