hookehuyr

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

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">&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-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) => {
......