hookehuyr

✨ feat(评分控件): 自定义表单钩子函数改造

1 +<!--
2 + * @Date: 2023-03-29 13:09:02
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2023-03-29 13:22:01
5 + * @FilePath: /data-table/src/components/RatePickerField/MyComponent.vue
6 + * @Description: 文件描述
7 +-->
8 +<template>
9 + <div style="width: 100%;">
10 + <van-rate
11 + v-model="rate_value"
12 + :count="props.component_props.data_length"
13 + :readonly="props.component_props.readonly"
14 + :color="styleColor.baseColor"
15 + style="padding: 1rem"
16 + />
17 + <van-divider />
18 + </div>
19 +</template>
20 +
21 +<script setup>
22 +import { ref } from 'vue'
23 +import { useCustomFieldValue } from '@vant/use';
24 +import { styleColor } from "@/constant.js";
25 +
26 +// 获取父组件传值
27 +const props = inject('props');
28 +const rate_value = ref(props.component_props.default);
29 +
30 +// 此处传入的值会替代 Field 组件内部的 value
31 +useCustomFieldValue(() => rate_value.value);
32 +</script>
33 +
34 +<style lang="less" scoped>
35 +
36 +</style>
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-03-27 17:14:53 4 + * @LastEditTime: 2023-03-29 13:27:43
5 * @FilePath: /data-table/src/components/RatePickerField/index.vue 5 * @FilePath: /data-table/src/components/RatePickerField/index.vue
6 * @Description: 评分选择控件 6 * @Description: 评分选择控件
7 --> 7 -->
...@@ -11,27 +11,16 @@ ...@@ -11,27 +11,16 @@
11 <span v-if="item.component_props.required">&nbsp;*</span> 11 <span v-if="item.component_props.required">&nbsp;*</span>
12 {{ item.component_props.label }} 12 {{ item.component_props.label }}
13 </div> 13 </div>
14 - <van-rate 14 + <van-field :name="item.name" :rules="rules">
15 - v-model="rate_value" 15 + <template #input>
16 - :count="item.component_props.data_length" 16 + <my-component />
17 - :readonly="item.component_props.readonly" 17 + </template>
18 - :color="styleColor.baseColor" 18 + </van-field>
19 - @change="onChange"
20 - style="padding: 1rem"
21 - />
22 - <div
23 - v-if="show_empty"
24 - class="van-field__error-message"
25 - style="padding: 0 1rem 1rem 1rem"
26 - >
27 - 评分不能为空
28 - </div>
29 - <van-divider />
30 </div> 19 </div>
31 </template> 20 </template>
32 21
33 <script setup> 22 <script setup>
34 -import { styleColor } from "@/constant.js"; 23 +import MyComponent from './MyComponent.vue';
35 24
36 const props = defineProps({ 25 const props = defineProps({
37 item: Object, 26 item: Object,
...@@ -40,31 +29,26 @@ const props = defineProps({ ...@@ -40,31 +29,26 @@ const props = defineProps({
40 const HideShow = computed(() => { 29 const HideShow = computed(() => {
41 return !props.item.component_props.disabled 30 return !props.item.component_props.disabled
42 }) 31 })
43 -const emit = defineEmits(["active"]);
44 -const show_empty = ref(false);
45 -const rate_value = ref(props.item.component_props.default);
46 -
47 -const onChange = (value) => {
48 - props.item.value = { key: props.item.key, value, type: "rate" };
49 - emit("active", props.item.value);
50 -};
51 32
52 -onMounted(() => { 33 +// 注入子组件属性
53 - props.item.value = { key: props.item.key, value: rate_value.value, type: "rate" }; 34 +provide('props', props.item);
54 - emit("active", props.item.value);
55 -});
56 35
57 -const validRate = () => { 36 +// 规则校验
58 - // 必填项 37 +const required = props.item.component_props.required;
59 - if (props.item.component_props.required && !rate_value.value) { 38 +const validator = (val) => {
60 - show_empty.value = true; 39 + if (required && !+val) {
40 + return false;
61 } else { 41 } else {
62 - show_empty.value = false; 42 + return true;
63 } 43 }
64 - return !show_empty.value;
65 }; 44 };
66 - 45 +// 错误提示文案
67 -defineExpose({ validRate }); 46 +const validatorMessage = (val, rule) => {
47 + if (required && !+val) {
48 + return "必填项不能为空";
49 + }
50 +};
51 +const rules = [{ validator, message: validatorMessage }];
68 </script> 52 </script>
69 53
70 <style lang="less" scoped> 54 <style lang="less" scoped>
......
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-27 18:30:02 4 + * @LastEditTime: 2023-03-29 13:19:06
5 * @FilePath: /data-table/src/views/index.vue 5 * @FilePath: /data-table/src/views/index.vue
6 * @Description: 首页 6 * @Description: 首页
7 --> 7 -->
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
22 <div v-if="PHeader.label" class="table-title" v-html="PHeader.label" /> 22 <div v-if="PHeader.label" class="table-title" v-html="PHeader.label" />
23 <div v-if="PHeader.description" class="table-desc" v-html="PHeader.description" /> 23 <div v-if="PHeader.description" class="table-desc" v-html="PHeader.description" />
24 <van-config-provider :theme-vars="themeVars"> 24 <van-config-provider :theme-vars="themeVars">
25 - <van-form @submit="onSubmit" scroll-to-error="true"> 25 + <van-form @submit="onSubmit" :scroll-to-error="true">
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" />
...@@ -175,12 +175,6 @@ const setRefMap = (el, item) => { ...@@ -175,12 +175,6 @@ const setRefMap = (el, item) => {
175 if (item.component_props.tag === "sign") { 175 if (item.component_props.tag === "sign") {
176 sign.value.push(el); 176 sign.value.push(el);
177 } 177 }
178 - if (item.component_props.tag === "rate_picker") {
179 - rate_picker.value.push(el);
180 - }
181 - if (item.component_props.tag === "appointment") {
182 - appointment.value.push(el);
183 - }
184 } 178 }
185 }; 179 };
186 180
...@@ -250,6 +244,7 @@ onMounted(async () => { ...@@ -250,6 +244,7 @@ onMounted(async () => {
250 }; 244 };
251 } 245 }
252 formData.value = formatData(page_form); 246 formData.value = formatData(page_form);
247 + // TAG: mock数据
253 mockData.value = [ 248 mockData.value = [
254 { 249 {
255 key: "field_1", 250 key: "field_1",
...@@ -442,15 +437,9 @@ const onActive = (item) => { ...@@ -442,15 +437,9 @@ const onActive = (item) => {
442 if (item.key === "sign") { 437 if (item.key === "sign") {
443 postData.value[item.filed_name] = item.value; 438 postData.value[item.filed_name] = item.value;
444 } 439 }
445 - if (item.type === "rate") {
446 - postData.value = _.assign(postData.value, { [item.key]: item.value });
447 - }
448 if (item.type === "picker") { // 下拉框控件 440 if (item.type === "picker") { // 下拉框控件
449 postData.value = _.assign(postData.value, { [item.key]: item.value }); 441 postData.value = _.assign(postData.value, { [item.key]: item.value });
450 } 442 }
451 - if (item.type === "appointment") { // 预约控件
452 - postData.value = _.assign(postData.value, { [item.key]: item.value });
453 - }
454 if (item.type === "radio") { // 单选控件 443 if (item.type === "radio") { // 单选控件
455 postData.value = _.assign(postData.value, { [item.key]: item.affix ? item.affix : item.value }); 444 postData.value = _.assign(postData.value, { [item.key]: item.affix ? item.affix : item.value });
456 } 445 }
...@@ -523,30 +512,6 @@ const validOther = () => { ...@@ -523,30 +512,6 @@ const validOther = () => {
523 } 512 }
524 }); 513 });
525 } 514 }
526 - if (rate_picker.value) {
527 - // 评分组件
528 - rate_picker.value.forEach((item, index) => {
529 - if (!rate_picker.value[index].validRate()) {
530 - valid = {
531 - status: rate_picker.value[index].validRate(),
532 - key: "rate_picker",
533 - };
534 - return false;
535 - }
536 - });
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 - }
550 return valid; 515 return valid;
551 }; 516 };
552 517
......