Showing
3 changed files
with
117 additions
and
67 deletions
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-30 11:34:19 | 2 | * @Date: 2022-08-30 11:34:19 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2023-02-10 14:41:52 | 4 | + * @LastEditTime: 2023-04-04 15:00:16 |
| 5 | - * @FilePath: /data-table/src/components/MultiRuleField/index.vue | 5 | + * @FilePath: /custom_form/src/components/MultiRuleField/index.vue |
| 6 | * @Description: 多选规则确认控件 | 6 | * @Description: 多选规则确认控件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | <div v-if="HideShow" class="multi-rule-field-page"> | 9 | <div v-if="HideShow" class="multi-rule-field-page"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | - <span v-if="item.component_props.required" class="required"> *</span> | 11 | + <text v-if="item.component_props.required" class="required"> *</text> |
| 12 | {{ item.component_props.label }} | 12 | {{ item.component_props.label }} |
| 13 | - <span v-if="item.component_props.min_count" style="color: #999; font-size: 0.85rem;">(最少选{{ item.component_props.min_count }}项)</span> | 13 | + <text v-if="item.component_props.min_count" style="color: #999; font-size: 13px;">(最少选{{ item.component_props.min_count }}项)</text> |
| 14 | </div> | 14 | </div> |
| 15 | - <van-field :name="item.key" :rules="rules" :border="false" style="padding-bottom: 0"> | 15 | + <nut-checkbox-group v-model="checkbox_value" style="width: 100%"> |
| 16 | - <template #input> | ||
| 17 | - <van-checkbox-group v-model="item.value" style="width: 100%"> | ||
| 18 | <template v-for="(rule, idx) in item.component_props.options" :key="idx"> | 16 | <template v-for="(rule, idx) in item.component_props.options" :key="idx"> |
| 19 | <div class="multi-rule-field-box"> | 17 | <div class="multi-rule-field-box"> |
| 20 | - <van-checkbox | 18 | + <nut-checkbox @click="onClick(rule)" :label="rule.title">{{ rule.title }}</nut-checkbox> |
| 21 | - :name="rule.value" | 19 | + <div class="multi-ellipsis--l3 rule-desc-text">{{ rule.desc_text }}</div> |
| 22 | - shape="square" | ||
| 23 | - :checked-color="themeVars.radioColor" | ||
| 24 | - >{{ rule.title }}</van-checkbox | ||
| 25 | - > | ||
| 26 | - <div class="van-multi-ellipsis--l3 rule-desc-text">{{ rule.desc_text }}</div> | ||
| 27 | <div v-if="rule.desc_type === 'text'" class="rule-box" @click="showRule(rule)"> | 20 | <div v-if="rule.desc_type === 'text'" class="rule-box" @click="showRule(rule)"> |
| 28 | {{ rule.desc_btn_name }} >> | 21 | {{ rule.desc_btn_name }} >> |
| 29 | </div> | 22 | </div> |
| 30 | - <div v-if="rule.desc_type === 'url'" class="rule-box" @click="showUrl(rule)"> | 23 | + <div v-if="rule.desc_type === 'url' && h5" class="rule-box" @click="showUrl(rule)"> |
| 31 | - {{ rule.desc_btn_name }} <van-icon name="link-o" /> | 24 | + {{ rule.desc_btn_name }} <Link size="12" /> |
| 32 | </div> | 25 | </div> |
| 33 | </div> | 26 | </div> |
| 34 | </template> | 27 | </template> |
| 35 | - </van-checkbox-group> | 28 | + </nut-checkbox-group> |
| 36 | - </template> | 29 | + <div |
| 37 | - </van-field> | 30 | + v-if="show_error" |
| 31 | + style="padding: 5px 20px; color: red; font-size: 12px;" | ||
| 32 | + > | ||
| 33 | + {{ error_msg }} | ||
| 38 | </div> | 34 | </div> |
| 39 | - | 35 | + <nut-overlay v-model:visible="show" :lock-scroll="true"> |
| 40 | - <van-overlay :show="show" :lock-scroll="false"> | 36 | + <div class="rule-wrapper"> |
| 41 | - <div class="rule-wrapper" @click.stop> | ||
| 42 | <div class="rule-block"> | 37 | <div class="rule-block"> |
| 43 | - <div style="height: 70vh; min-height: 70vh; overflow: scroll; white-space: pre-wrap; line-height: 1.5;" v-html="rule_content"></div> | 38 | + <div style="height: 70vh; min-height: 70vh; overflow: scroll; white-space: pre-wrap; line-height: 1.5;font-size: 15px;" v-html="rule_content"></div> |
| 44 | <div class="close-btn"> | 39 | <div class="close-btn"> |
| 45 | - <van-button type="primary" block @click="closeRule" | 40 | + <nut-button type="primary" block @click="closeRule">关 闭</nut-button> |
| 46 | - >关 闭</van-button | ||
| 47 | - > | ||
| 48 | </div> | 41 | </div> |
| 49 | <div></div> | 42 | <div></div> |
| 50 | </div> | 43 | </div> |
| 51 | </div> | 44 | </div> |
| 52 | - </van-overlay> | 45 | + </nut-overlay> |
| 46 | + </div> | ||
| 53 | </template> | 47 | </template> |
| 54 | 48 | ||
| 55 | <script setup> | 49 | <script setup> |
| 50 | +import { ref, computed, watch, onMounted, reactive } from "vue"; | ||
| 56 | import { styleColor } from "@/constant.js"; | 51 | import { styleColor } from "@/constant.js"; |
| 57 | -import $ from "jquery"; | 52 | +import { $ } from '@tarojs/extend'; |
| 53 | +import { Link } from '@nutui/icons-vue-taro'; | ||
| 58 | 54 | ||
| 59 | const props = defineProps({ | 55 | const props = defineProps({ |
| 60 | item: Object, | 56 | item: Object, |
| ... | @@ -70,8 +66,28 @@ const themeVars = { | ... | @@ -70,8 +66,28 @@ const themeVars = { |
| 70 | onMounted(() => { | 66 | onMounted(() => { |
| 71 | $(".rule-box").css("color", themeVars.radioColor); | 67 | $(".rule-box").css("color", themeVars.radioColor); |
| 72 | }); | 68 | }); |
| 69 | + | ||
| 70 | +const emit = defineEmits(["active"]); | ||
| 73 | const show = ref(false); | 71 | const show = ref(false); |
| 74 | -const checked = ref([]); | 72 | +const checkbox_value = ref([]); |
| 73 | +const options = props.item.component_props.options; | ||
| 74 | + | ||
| 75 | +const onClick = (item) => { | ||
| 76 | + item.checked = !item.checked; | ||
| 77 | + // 校验输入项数据 | ||
| 78 | + validMultiRule(); | ||
| 79 | + // 发送自定义数据结构 | ||
| 80 | + props.item.value = { key: props.item.key, value: checkbox_value.value, type: "multi_rule" }; | ||
| 81 | + console.warn(props.item.value); | ||
| 82 | + emit("active", props.item.value); | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +onMounted(() => { | ||
| 86 | + // 发送自定义数据结构 | ||
| 87 | + props.item.value = { key: props.item.key, value: checkbox_value.value, type: "multi_rule" }; | ||
| 88 | + emit("active", props.item.value); | ||
| 89 | +}); | ||
| 90 | + | ||
| 75 | const showRule = (rule) => { | 91 | const showRule = (rule) => { |
| 76 | show.value = true; | 92 | show.value = true; |
| 77 | rule.desc_text = rule.desc_text.replace(/\\n/g, "<br>") | 93 | rule.desc_text = rule.desc_text.replace(/\\n/g, "<br>") |
| ... | @@ -81,55 +97,66 @@ const closeRule = () => { | ... | @@ -81,55 +97,66 @@ const closeRule = () => { |
| 81 | show.value = false; | 97 | show.value = false; |
| 82 | rule_content.value = ""; | 98 | rule_content.value = ""; |
| 83 | }; | 99 | }; |
| 84 | -const showUrl = (rule) => { | 100 | +const h5 = computed(() => { |
| 101 | + if (process.env.TARO_ENV === 'h5') { | ||
| 102 | + return true | ||
| 103 | + } else { | ||
| 104 | + return false; | ||
| 105 | + } | ||
| 106 | +}) | ||
| 107 | +const showUrl = (rule) => { // 跳转设置链接 | ||
| 108 | + if (process.env.TARO_ENV === 'h5') { | ||
| 85 | location.href = rule.desc_url | 109 | location.href = rule.desc_url |
| 110 | + } | ||
| 111 | + // 小程序需要配置制定域名内网页,功能无法实现。 | ||
| 86 | } | 112 | } |
| 87 | const rule_content = ref(""); | 113 | const rule_content = ref(""); |
| 88 | const required = props.item.component_props.required; | 114 | const required = props.item.component_props.required; |
| 89 | const min_count = props.item.component_props.min_count; | 115 | const min_count = props.item.component_props.min_count; |
| 90 | const max_count = props.item.component_props.max_count; | 116 | const max_count = props.item.component_props.max_count; |
| 91 | -const validator = (val) => { | 117 | + |
| 92 | - if (required && !val.length) { | 118 | +const show_error = ref(false); |
| 93 | - return false; | 119 | +const error_msg = ref(''); |
| 94 | - } else if (min_count && props.item.value.length < min_count) { | 120 | +// 校验模块 |
| 95 | - return false; | 121 | +const validMultiRule= () => { |
| 96 | - } else if (max_count && props.item.value.length > max_count) { | 122 | + // 必填项 |
| 97 | - return false; | 123 | + if (required && !checkbox_value.value.length) { |
| 124 | + show_error.value = true; | ||
| 125 | + error_msg.value = '选择项不能为空'; | ||
| 126 | + } else if (min_count && checkbox_value.value.length < min_count) { | ||
| 127 | + show_error.value = true; | ||
| 128 | + error_msg.value = `最少选择 ${min_count} 项`; | ||
| 129 | + } else if (max_count && checkbox_value.value.length > max_count) { | ||
| 130 | + show_error.value = true; | ||
| 131 | + error_msg.value = `最多选择 ${max_count} 项`; | ||
| 98 | } else { | 132 | } else { |
| 99 | - return true; | 133 | + show_error.value = false; |
| 100 | - } | 134 | + error_msg.value = ''; |
| 101 | -}; | ||
| 102 | -// 错误提示文案 | ||
| 103 | -const validatorMessage = (val, rule) => { | ||
| 104 | - if (required && !val.length) { | ||
| 105 | - return "选择项不能为空"; | ||
| 106 | - } else if (min_count && props.item.value.length < min_count) { | ||
| 107 | - return `最少选择${min_count}项`; | ||
| 108 | - } else if (max_count && props.item.value.length > max_count) { | ||
| 109 | - return `最多选择${max_count}项`; | ||
| 110 | } | 135 | } |
| 136 | + return !show_error.value; | ||
| 111 | }; | 137 | }; |
| 112 | -const rules = [{ validator, message: validatorMessage }]; | 138 | + |
| 139 | +defineExpose({ validMultiRule }); | ||
| 113 | </script> | 140 | </script> |
| 114 | 141 | ||
| 115 | -<style lang="less" scoped> | 142 | +<style lang="less"> |
| 116 | .multi-rule-field-page { | 143 | .multi-rule-field-page { |
| 117 | .label { | 144 | .label { |
| 118 | - padding: 1rem 1rem 0 1rem; | 145 | + padding: 30px 30px 0 30px; |
| 119 | - font-size: 0.9rem; | 146 | + font-size: 26px; |
| 120 | font-weight: bold; | 147 | font-weight: bold; |
| 121 | - span.required { | 148 | + text.required { |
| 122 | color: red; | 149 | color: red; |
| 123 | } | 150 | } |
| 124 | } | 151 | } |
| 125 | .rule-desc-text { | 152 | .rule-desc-text { |
| 126 | - margin: 0.35rem 0.5rem 0.5rem 1.75rem; | 153 | + margin: 0.35rem 0.5rem 0.5rem 60px; |
| 127 | - font-size: 0.8rem; | 154 | + font-size: 28px; |
| 128 | color: #808080; | 155 | color: #808080; |
| 129 | } | 156 | } |
| 130 | .rule-box { | 157 | .rule-box { |
| 131 | - font-size: 0.85rem; | 158 | + font-size: 28px; |
| 132 | - margin-left: 1.8rem; | 159 | + margin-left: 60px; |
| 133 | padding-bottom: 0.5rem; | 160 | padding-bottom: 0.5rem; |
| 134 | width: fit-content; | 161 | width: fit-content; |
| 135 | } | 162 | } |
| ... | @@ -158,8 +185,11 @@ const rules = [{ validator, message: validatorMessage }]; | ... | @@ -158,8 +185,11 @@ const rules = [{ validator, message: validatorMessage }]; |
| 158 | .multi-rule-field-box { | 185 | .multi-rule-field-box { |
| 159 | border: 1px solid #eaeaea; | 186 | border: 1px solid #eaeaea; |
| 160 | border-radius: 0.25rem; | 187 | border-radius: 0.25rem; |
| 161 | - padding: 1rem 0.5rem 0 0.5rem; | 188 | + padding: 25px; |
| 162 | - // width: 100vw; | 189 | + margin: 25px; |
| 163 | - margin-bottom: 0.5rem; | 190 | +} |
| 191 | + | ||
| 192 | +.nut-checkbox__label { | ||
| 193 | + margin-left: 20px; | ||
| 164 | } | 194 | } |
| 165 | </style> | 195 | </style> | ... | ... |
| ... | @@ -23,7 +23,7 @@ import CheckboxField from '@/components/CheckboxField/index.vue' | ... | @@ -23,7 +23,7 @@ import CheckboxField from '@/components/CheckboxField/index.vue' |
| 23 | // import MarqueeField from '@/components/MarqueeField/index.vue' | 23 | // import MarqueeField from '@/components/MarqueeField/index.vue' |
| 24 | // import ContactField from '@/components/ContactField/index.vue' | 24 | // import ContactField from '@/components/ContactField/index.vue' |
| 25 | // import RuleField from '@/components/RuleField/index.vue' | 25 | // import RuleField from '@/components/RuleField/index.vue' |
| 26 | -// import MultiRuleField from '@/components/MultiRuleField/index.vue' | 26 | +import MultiRuleField from '@/components/MultiRuleField/index.vue' |
| 27 | // import ButtonField from '@/components/ButtonField/index.vue' | 27 | // import ButtonField from '@/components/ButtonField/index.vue' |
| 28 | // import NoteField from '@/components/NoteField/index.vue' | 28 | // import NoteField from '@/components/NoteField/index.vue' |
| 29 | // import NameField from '@/components/NameField/index.vue' | 29 | // import NameField from '@/components/NameField/index.vue' |
| ... | @@ -163,11 +163,11 @@ export function createComponentType(data) { | ... | @@ -163,11 +163,11 @@ export function createComponentType(data) { |
| 163 | // item.name = item.key | 163 | // item.name = item.key |
| 164 | // item.component = ButtonField | 164 | // item.component = ButtonField |
| 165 | // } | 165 | // } |
| 166 | - // if (item.component_props.tag === 'multi_rule') { | 166 | + if (item.component_props.tag === 'multi_rule') { |
| 167 | - // item.name = item.key | 167 | + item.name = item.key |
| 168 | - // item.value = [] | 168 | + item.value = [] |
| 169 | - // item.component = MultiRuleField | 169 | + item.component = MultiRuleField |
| 170 | - // } | 170 | + } |
| 171 | // if (item.component_props.tag === 'note') { | 171 | // if (item.component_props.tag === 'note') { |
| 172 | // item.name = item.key | 172 | // item.name = item.key |
| 173 | // item.component = NoteField | 173 | // item.component = NoteField | ... | ... |
| 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 10:21:43 | 4 | + * @LastEditTime: 2023-04-04 14:38:13 |
| 5 | * @FilePath: /custom_form/src/pages/table/index.vue | 5 | * @FilePath: /custom_form/src/pages/table/index.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -130,6 +130,7 @@ const input = ref([]); | ... | @@ -130,6 +130,7 @@ const input = ref([]); |
| 130 | const textarea = ref([]); | 130 | 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 area_picker = ref([]); | 134 | const area_picker = ref([]); |
| 134 | const image_uploader = ref([]); | 135 | const image_uploader = ref([]); |
| 135 | const file_uploader = ref([]); | 136 | const file_uploader = ref([]); |
| ... | @@ -150,6 +151,9 @@ const setRefMap = (el, item) => { | ... | @@ -150,6 +151,9 @@ const setRefMap = (el, item) => { |
| 150 | if (item.component_props.tag === "checkbox") { | 151 | if (item.component_props.tag === "checkbox") { |
| 151 | checkbox.value.push(el); | 152 | checkbox.value.push(el); |
| 152 | } | 153 | } |
| 154 | + if (item.component_props.tag === "multi_rule") { | ||
| 155 | + multi_rule.value.push(el); | ||
| 156 | + } | ||
| 153 | if (item.component_props.tag === "area_picker") { | 157 | if (item.component_props.tag === "area_picker") { |
| 154 | area_picker.value.push(el); | 158 | area_picker.value.push(el); |
| 155 | } | 159 | } |
| ... | @@ -393,6 +397,10 @@ const onActive = (item) => { | ... | @@ -393,6 +397,10 @@ const onActive = (item) => { |
| 393 | }); | 397 | }); |
| 394 | postData.value = Object.assign(postData.value, { [item.key]: checkbox_value }); | 398 | postData.value = Object.assign(postData.value, { [item.key]: checkbox_value }); |
| 395 | } | 399 | } |
| 400 | + if (item.type === "multi_rule") { | ||
| 401 | + const checkbox_value = deepClone(item.value) | ||
| 402 | + postData.value = Object.assign(postData.value, { [item.key]: checkbox_value }); | ||
| 403 | + } | ||
| 396 | if (item.key === "area_picker") { | 404 | if (item.key === "area_picker") { |
| 397 | postData.value[item.filed_name] = item.value; | 405 | postData.value[item.filed_name] = item.value; |
| 398 | } | 406 | } |
| ... | @@ -469,6 +477,18 @@ const validOther = () => { | ... | @@ -469,6 +477,18 @@ const validOther = () => { |
| 469 | } | 477 | } |
| 470 | }); | 478 | }); |
| 471 | } | 479 | } |
| 480 | + if (multi_rule.value) { | ||
| 481 | + // 多选规则控件 | ||
| 482 | + multi_rule.value.forEach((item, index) => { | ||
| 483 | + if (!multi_rule.value[index].validMultiRule()) { | ||
| 484 | + valid = { | ||
| 485 | + status: multi_rule.value[index].validMultiRule(), | ||
| 486 | + key: "multi_rule", | ||
| 487 | + }; | ||
| 488 | + return false; | ||
| 489 | + } | ||
| 490 | + }); | ||
| 491 | + } | ||
| 472 | if (area_picker.value) { | 492 | if (area_picker.value) { |
| 473 | // 省市区地址 | 493 | // 省市区地址 |
| 474 | area_picker.value.forEach((item, index) => { | 494 | area_picker.value.forEach((item, index) => { | ... | ... |
-
Please register or login to post a comment