Showing
4 changed files
with
103 additions
and
30 deletions
| ... | @@ -36,6 +36,8 @@ declare module '@vue/runtime-core' { | ... | @@ -36,6 +36,8 @@ declare module '@vue/runtime-core' { |
| 36 | NutInput: typeof import('@nutui/nutui-taro')['Input'] | 36 | NutInput: typeof import('@nutui/nutui-taro')['Input'] |
| 37 | NutNoticebar: typeof import('@nutui/nutui-taro')['Noticebar'] | 37 | NutNoticebar: typeof import('@nutui/nutui-taro')['Noticebar'] |
| 38 | NutOverlay: typeof import('@nutui/nutui-taro')['Overlay'] | 38 | NutOverlay: typeof import('@nutui/nutui-taro')['Overlay'] |
| 39 | + NutPicker: typeof import('@nutui/nutui-taro')['Picker'] | ||
| 40 | + NutPopup: typeof import('@nutui/nutui-taro')['Popup'] | ||
| 39 | NutRadio: typeof import('@nutui/nutui-taro')['Radio'] | 41 | NutRadio: typeof import('@nutui/nutui-taro')['Radio'] |
| 40 | NutRadioGroup: typeof import('@nutui/nutui-taro')['RadioGroup'] | 42 | NutRadioGroup: typeof import('@nutui/nutui-taro')['RadioGroup'] |
| 41 | NutSwiper: typeof import('@nutui/nutui-taro')['Swiper'] | 43 | NutSwiper: typeof import('@nutui/nutui-taro')['Swiper'] | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-30 13:46:51 | 2 | * @Date: 2022-08-30 13:46:51 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2023-03-03 21:11:24 | 4 | + * @LastEditTime: 2023-04-06 13:34:46 |
| 5 | - * @FilePath: /data-table/src/components/PickerField/index.vue | 5 | + * @FilePath: /custom_form/src/components/PickerField/index.vue |
| 6 | * @Description: 单列选择器组件 | 6 | * @Description: 单列选择器组件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | <div v-if="HideShow" class="picker-field-page"> | 9 | <div v-if="HideShow" class="picker-field-page"> |
| 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 | + <div style="margin: 10px 20px;"> |
| 15 | + <nut-input | ||
| 15 | v-model="picker_value" | 16 | v-model="picker_value" |
| 16 | is-link | 17 | is-link |
| 17 | readonly | 18 | readonly |
| 18 | - :name="item.key" | 19 | + :label="item.key" |
| 19 | :required="item.component_props.required" | 20 | :required="item.component_props.required" |
| 20 | :placeholder="item.component_props.placeholder" | 21 | :placeholder="item.component_props.placeholder" |
| 21 | - :rules="item.rules" | 22 | + @click-input="onClick()" |
| 22 | - @click="showPicker = true" | ||
| 23 | :border="false" | 23 | :border="false" |
| 24 | - /> | 24 | + style="padding: 0px;" |
| 25 | + > | ||
| 26 | + <template #right> <RectRight color="#eaeaea"></RectRight></template> | ||
| 27 | + </nut-input> | ||
| 28 | + <div | ||
| 29 | + v-if="show_error" | ||
| 30 | + style="padding: 5px; color: red; font-size: 12px;" | ||
| 31 | + > | ||
| 32 | + {{ error_msg }} | ||
| 33 | + </div> | ||
| 34 | + </div> | ||
| 25 | <!-- <van-field v-if="has_add_info" :name="add_info_name" v-model="add_info" label="" placeholder="请输入补充信息" :border="false" style="border: 1px solid #eaeaea;border-radius: 0.25rem; padding: 0.25rem 0.5rem; margin-top: 0.25rem;" /> --> | 35 | <!-- <van-field v-if="has_add_info" :name="add_info_name" v-model="add_info" label="" placeholder="请输入补充信息" :border="false" style="border: 1px solid #eaeaea;border-radius: 0.25rem; padding: 0.25rem 0.5rem; margin-top: 0.25rem;" /> --> |
| 26 | - <van-popup v-model:show="showPicker" position="bottom"> | 36 | + <nut-popup v-model:visible="showPicker" position="bottom"> |
| 27 | - <van-picker | 37 | + <nut-picker |
| 28 | :columns="item.component_props.options" | 38 | :columns="item.component_props.options" |
| 29 | @confirm="onConfirm" | 39 | @confirm="onConfirm" |
| 30 | @cancel="showPicker = false" | 40 | @cancel="showPicker = false" |
| 31 | /> | 41 | /> |
| 32 | - </van-popup> | 42 | + </nut-popup> |
| 33 | </div> | 43 | </div> |
| 34 | </template> | 44 | </template> |
| 35 | 45 | ||
| 36 | <script setup> | 46 | <script setup> |
| 47 | +import { ref, computed, watch, onMounted, reactive } from "vue"; | ||
| 48 | +import { RectRight } from '@nutui/icons-vue-taro'; | ||
| 49 | + | ||
| 37 | const props = defineProps({ | 50 | const props = defineProps({ |
| 38 | item: Object, | 51 | item: Object, |
| 39 | }); | 52 | }); |
| ... | @@ -59,12 +72,21 @@ const selectedValues = ref(""); | ... | @@ -59,12 +72,21 @@ const selectedValues = ref(""); |
| 59 | const showPicker = ref(false); | 72 | const showPicker = ref(false); |
| 60 | const picker_value = ref(props.item.component_props.default); | 73 | const picker_value = ref(props.item.component_props.default); |
| 61 | 74 | ||
| 75 | +const onClick = () => { | ||
| 76 | + showPicker.value = true; | ||
| 77 | +} | ||
| 78 | + | ||
| 62 | const onConfirm = ({ selectedOptions }) => { | 79 | const onConfirm = ({ selectedOptions }) => { |
| 63 | picker_value.value = selectedOptions[0]?.value; | 80 | picker_value.value = selectedOptions[0]?.value; |
| 64 | showPicker.value = false; | 81 | showPicker.value = false; |
| 65 | // 触发点自定义监听事件,配合规则显示隐藏其他字段 | 82 | // 触发点自定义监听事件,配合规则显示隐藏其他字段 |
| 66 | - props.item.value = { key: props.item.key, value: picker_value.value, type: "picker" }; | 83 | + props.item.value = { |
| 84 | + key: "picker", | ||
| 85 | + filed_name: props.item.key, | ||
| 86 | + value: picker_value.value, | ||
| 87 | + }; | ||
| 67 | emit("active", props.item.value); | 88 | emit("active", props.item.value); |
| 89 | + validPicker(); | ||
| 68 | // if (add_info_key.value === props.item.value) { | 90 | // if (add_info_key.value === props.item.value) { |
| 69 | // has_add_info.value = true; | 91 | // has_add_info.value = true; |
| 70 | // } | 92 | // } |
| ... | @@ -73,26 +95,58 @@ const onConfirm = ({ selectedOptions }) => { | ... | @@ -73,26 +95,58 @@ const onConfirm = ({ selectedOptions }) => { |
| 73 | const HideShow = computed(() => { | 95 | const HideShow = computed(() => { |
| 74 | return !props.item.component_props.disabled | 96 | return !props.item.component_props.disabled |
| 75 | }) | 97 | }) |
| 98 | + | ||
| 99 | +// 错误提示 | ||
| 100 | +const show_error = ref(false); | ||
| 101 | +const error_msg = ref(''); | ||
| 102 | + | ||
| 103 | +// 校验模块 | ||
| 104 | +const validPicker = () => { | ||
| 105 | + // 必填项 | ||
| 106 | + if (props.item.component_props.required && !picker_value.value) { | ||
| 107 | + show_error.value = true; | ||
| 108 | + error_msg.value = '必填项不能为空' | ||
| 109 | + } else { | ||
| 110 | + show_error.value = false; | ||
| 111 | + error_msg.value = '' | ||
| 112 | + } | ||
| 113 | + return !show_error.value; | ||
| 114 | +}; | ||
| 115 | + | ||
| 116 | +defineExpose({ validPicker, id: props.item.key }); | ||
| 76 | </script> | 117 | </script> |
| 77 | 118 | ||
| 78 | -<style lang="less" scoped> | 119 | +<style lang="less"> |
| 79 | .picker-field-page { | 120 | .picker-field-page { |
| 80 | - margin: 1rem; | ||
| 81 | .label { | 121 | .label { |
| 82 | - // padding: 1rem 1rem 0 0; | 122 | + padding: 30px 30px 0 30px; |
| 83 | - font-size: 0.9rem; | 123 | + font-size: 26px; |
| 84 | font-weight: bold; | 124 | font-weight: bold; |
| 85 | - | 125 | + text { |
| 86 | - span { | ||
| 87 | color: red; | 126 | color: red; |
| 88 | } | 127 | } |
| 128 | + | ||
| 129 | + .note-wrapper { | ||
| 130 | + font-size: 24px; | ||
| 131 | + margin-left: 30px; | ||
| 132 | + color: gray; | ||
| 133 | + padding-bottom: 15px; | ||
| 134 | + padding-top: 7px; | ||
| 135 | + white-space: pre-wrap; | ||
| 136 | + } | ||
| 89 | } | 137 | } |
| 90 | -} | ||
| 91 | 138 | ||
| 92 | -:deep(.van-cell--clickable) { | 139 | + .nut-input { |
| 140 | + padding: 10px; | ||
| 93 | border: 1px solid #eaeaea; | 141 | border: 1px solid #eaeaea; |
| 94 | - border-radius: 0.25rem; | 142 | + border-radius: 8px; |
| 95 | - padding: 0.25rem 0.5rem; | 143 | + } |
| 96 | - margin-top: 0.5rem; | ||
| 97 | } | 144 | } |
| 145 | + | ||
| 146 | +// :deep(.van-cell--clickable) { | ||
| 147 | +// border: 1px solid #eaeaea; | ||
| 148 | +// border-radius: 0.25rem; | ||
| 149 | +// padding: 0.25rem 0.5rem; | ||
| 150 | +// margin-top: 0.5rem; | ||
| 151 | +// } | ||
| 98 | </style> | 152 | </style> | ... | ... |
| ... | @@ -3,7 +3,7 @@ import TextField from '@/components/TextField/index.vue' | ... | @@ -3,7 +3,7 @@ import TextField from '@/components/TextField/index.vue' |
| 3 | import TextareaField from '@/components/TextareaField/index.vue' | 3 | import TextareaField from '@/components/TextareaField/index.vue' |
| 4 | import RadioField from '@/components/RadioField/index.vue' | 4 | 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' |
| ... | @@ -90,9 +90,9 @@ export function createComponentType(data) { | ... | @@ -90,9 +90,9 @@ export function createComponentType(data) { |
| 90 | if (item.component_props.tag === 'checkbox') { | 90 | if (item.component_props.tag === 'checkbox') { |
| 91 | item.component = CheckboxField | 91 | item.component = CheckboxField |
| 92 | } | 92 | } |
| 93 | - // if (item.component_props.tag === 'select') { | 93 | + if (item.component_props.tag === 'select') { |
| 94 | - // item.component = PickerField | 94 | + item.component = PickerField |
| 95 | - // } | 95 | + } |
| 96 | // if (item.component_props.tag === 'address') { | 96 | // if (item.component_props.tag === 'address') { |
| 97 | // item.component = AreaPickerField | 97 | // item.component = AreaPickerField |
| 98 | // } | 98 | // } | ... | ... |
| 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-04 18:09:30 | 4 | + * @LastEditTime: 2023-04-06 13:37:04 |
| 5 | * @FilePath: /custom_form/src/pages/table/index.vue | 5 | * @FilePath: /custom_form/src/pages/table/index.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -131,6 +131,7 @@ const textarea = ref([]); | ... | @@ -131,6 +131,7 @@ const textarea = ref([]); |
| 131 | const radio = ref([]); | 131 | const radio = ref([]); |
| 132 | const checkbox = ref([]); | 132 | const checkbox = ref([]); |
| 133 | const multi_rule = ref([]); | 133 | const multi_rule = ref([]); |
| 134 | +const picker = ref([]); | ||
| 134 | const area_picker = ref([]); | 135 | const area_picker = ref([]); |
| 135 | const image_uploader = ref([]); | 136 | const image_uploader = ref([]); |
| 136 | const file_uploader = ref([]); | 137 | const file_uploader = ref([]); |
| ... | @@ -154,6 +155,9 @@ const setRefMap = (el, item) => { | ... | @@ -154,6 +155,9 @@ const setRefMap = (el, item) => { |
| 154 | if (item.component_props.tag === "multi_rule") { | 155 | if (item.component_props.tag === "multi_rule") { |
| 155 | multi_rule.value.push(el); | 156 | multi_rule.value.push(el); |
| 156 | } | 157 | } |
| 158 | + if (item.component_props.tag === "select") { | ||
| 159 | + picker.value.push(el); | ||
| 160 | + } | ||
| 157 | if (item.component_props.tag === "area_picker") { | 161 | if (item.component_props.tag === "area_picker") { |
| 158 | area_picker.value.push(el); | 162 | area_picker.value.push(el); |
| 159 | } | 163 | } |
| ... | @@ -425,8 +429,8 @@ const onActive = (item) => { | ... | @@ -425,8 +429,8 @@ const onActive = (item) => { |
| 425 | if (item.type === "rate") { | 429 | if (item.type === "rate") { |
| 426 | postData.value = _.assign(postData.value, { [item.key]: item.value }); | 430 | postData.value = _.assign(postData.value, { [item.key]: item.value }); |
| 427 | } | 431 | } |
| 428 | - if (item.type === "picker") { // 下拉框控件 | 432 | + if (item.key === "picker") { // 下拉框控件 |
| 429 | - postData.value = _.assign(postData.value, { [item.key]: item.value }); | 433 | + postData.value = Object.assign(postData.value, { [item.filed_name]: item.value }); |
| 430 | } | 434 | } |
| 431 | // 检查规则,会影响字段显示 | 435 | // 检查规则,会影响字段显示 |
| 432 | checkRules(); | 436 | checkRules(); |
| ... | @@ -504,6 +508,19 @@ const validOther = () => { | ... | @@ -504,6 +508,19 @@ const validOther = () => { |
| 504 | } | 508 | } |
| 505 | }); | 509 | }); |
| 506 | } | 510 | } |
| 511 | + if (picker.value) { | ||
| 512 | + // 下拉框 | ||
| 513 | + picker.value.forEach((item, index) => { | ||
| 514 | + if (!picker.value[index].validPicker()) { | ||
| 515 | + valid = { | ||
| 516 | + status: picker.value[index].validPicker(), | ||
| 517 | + key: "picker", | ||
| 518 | + id: picker.value[index]?.id | ||
| 519 | + }; | ||
| 520 | + return false; | ||
| 521 | + } | ||
| 522 | + }); | ||
| 523 | + } | ||
| 507 | if (area_picker.value) { | 524 | if (area_picker.value) { |
| 508 | // 省市区地址 | 525 | // 省市区地址 |
| 509 | area_picker.value.forEach((item, index) => { | 526 | area_picker.value.forEach((item, index) => { | ... | ... |
-
Please register or login to post a comment