Showing
5 changed files
with
202 additions
and
111 deletions
| ... | @@ -27,6 +27,8 @@ declare module '@vue/runtime-core' { | ... | @@ -27,6 +27,8 @@ declare module '@vue/runtime-core' { |
| 27 | NoteField: typeof import('./src/components/NoteField/index.vue')['default'] | 27 | NoteField: typeof import('./src/components/NoteField/index.vue')['default'] |
| 28 | NumberField: typeof import('./src/components/NumberField/index.vue')['default'] | 28 | NumberField: typeof import('./src/components/NumberField/index.vue')['default'] |
| 29 | NutButton: typeof import('@nutui/nutui-taro')['Button'] | 29 | NutButton: typeof import('@nutui/nutui-taro')['Button'] |
| 30 | + NutCheckbox: typeof import('@nutui/nutui-taro')['Checkbox'] | ||
| 31 | + NutCheckboxGroup: typeof import('@nutui/nutui-taro')['CheckboxGroup'] | ||
| 30 | NutConfigProvider: typeof import('@nutui/nutui-taro')['ConfigProvider'] | 32 | NutConfigProvider: typeof import('@nutui/nutui-taro')['ConfigProvider'] |
| 31 | NutDialog: typeof import('@nutui/nutui-taro')['Dialog'] | 33 | NutDialog: typeof import('@nutui/nutui-taro')['Dialog'] |
| 32 | NutField: typeof import('@nutui/nutui-taro')['Field'] | 34 | NutField: typeof import('@nutui/nutui-taro')['Field'] | ... | ... |
| 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 10:06:43 | 4 | + * @LastEditTime: 2023-04-04 11:03:21 |
| 5 | - * @FilePath: /data-table/src/components/CheckboxField/index.vue | 5 | + * @FilePath: /custom_form/src/components/CheckboxField/index.vue |
| 6 | * @Description: 多项选择控件 | 6 | * @Description: 多项选择控件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | <div v-if="HideShow" class="checkbox-field-page"> | 9 | <div v-if="HideShow" class="checkbox-field-page"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | - <span v-if="item.component_props.required" style="color: red"> *</span> | 11 | + <text v-if="item.component_props.required" style="color: red"> *</text> |
| 12 | {{ item.component_props.label }} | 12 | {{ item.component_props.label }} |
| 13 | - <span v-if="item.component_props.max" style="color: gray"> | 13 | + <text v-if="item.component_props.max" style="color: gray"> |
| 14 | (最多可选数: {{ item.component_props.max }}) | 14 | (最多可选数: {{ item.component_props.max }}) |
| 15 | - </span> | 15 | + </text> |
| 16 | </div> | 16 | </div> |
| 17 | <div v-if="item.component_props.note" class="note" v-html="item.component_props.note" /> | 17 | <div v-if="item.component_props.note" class="note" v-html="item.component_props.note" /> |
| 18 | - <van-field :rules="item.rules" :border="false"> | 18 | + <nut-checkbox-group v-model="checkbox_value" :direction="item.component_props.direction" |
| 19 | - <template #input> | 19 | + :max="item.component_props.max" style="width: 100%"> |
| 20 | - <van-checkbox-group v-model="checkbox_value" :direction="item.component_props.direction" | 20 | + <div v-for="x in item.component_props.options" :key="x.title" class="checkbox-wrapper"> |
| 21 | - :max="item.component_props.max" style="width: 100%"> | 21 | + <nut-checkbox @click="onClick(x)" :label="x.title" icon-size="16" style="margin-bottom: 0.25rem">{{ x.title }}</nut-checkbox> |
| 22 | - <div v-for="x in item.component_props.options" :key="x.title" class="checkbox-wrapper"> | 22 | + <nut-input |
| 23 | - <van-checkbox @click="onClick(x)" :name="x.title" icon-size="1rem" shape="square" | 23 | + v-if="checkbox_value.includes(x.value) && x.is_input" |
| 24 | - :checked-color="themeVars.radioColor" style="margin-bottom: 0.25rem">{{ x.title }}</van-checkbox> | 24 | + @blur="onBlur(x)" |
| 25 | - <van-field v-if="checkbox_value.includes(x.value) && x.is_input" @blur="onBlur(x)" v-model="x.affix" | 25 | + v-model="x.affix" |
| 26 | - label=" " label-width="5px" :placeholder="x.input_placeholder" :rules="x.input_required ? rules : ''" | 26 | + label=" " label-width="5px" :placeholder="x.input_placeholder" :border="false" |
| 27 | - :required="x.input_required" class="affix-input" /> | 27 | + :required="x.input_required" class="affix-input" /> |
| 28 | - </div> | 28 | + <div |
| 29 | - </van-checkbox-group> | 29 | + v-if="x.show_error" |
| 30 | - </template> | 30 | + style="padding: 5px 20px; color: red; font-size: 12px;" |
| 31 | - </van-field> | 31 | + > |
| 32 | + {{ x.error_msg }} | ||
| 33 | + </div> | ||
| 34 | + </div> | ||
| 35 | + </nut-checkbox-group> | ||
| 36 | + <div | ||
| 37 | + v-if="show_error" | ||
| 38 | + style="padding: 5px 20px; color: red; font-size: 12px;" | ||
| 39 | + > | ||
| 40 | + {{ error_msg }} | ||
| 41 | + </div> | ||
| 32 | </div> | 42 | </div> |
| 33 | </template> | 43 | </template> |
| 34 | 44 | ||
| 35 | <script setup> | 45 | <script setup> |
| 46 | +import { ref, computed, watch, onMounted, reactive } from "vue"; | ||
| 36 | import { styleColor } from "@/constant.js"; | 47 | import { styleColor } from "@/constant.js"; |
| 37 | 48 | ||
| 38 | const props = defineProps({ | 49 | const props = defineProps({ |
| ... | @@ -51,30 +62,29 @@ const HideShow = computed(() => { | ... | @@ -51,30 +62,29 @@ const HideShow = computed(() => { |
| 51 | return !props.item.component_props.disabled | 62 | return !props.item.component_props.disabled |
| 52 | }) | 63 | }) |
| 53 | 64 | ||
| 54 | -// TODO: 等待数据结构更新,看看怎么判断必填 | ||
| 55 | -// 校验函数返回 true 表示校验通过,false 表示不通过 | ||
| 56 | -const validator = (val) => { | ||
| 57 | - if (!val) { | ||
| 58 | - return false; | ||
| 59 | - } else { | ||
| 60 | - return true; | ||
| 61 | - } | ||
| 62 | -}; | ||
| 63 | -// 错误提示文案 | ||
| 64 | -const validatorMessage = (val, rule) => { | ||
| 65 | - if (!val) { | ||
| 66 | - return "补充信息不能为空"; | ||
| 67 | - } | ||
| 68 | -}; | ||
| 69 | -const rules = [{ validator, message: validatorMessage }]; | ||
| 70 | - | ||
| 71 | const emit = defineEmits(["active"]); | 65 | const emit = defineEmits(["active"]); |
| 72 | const checkbox_value = ref(props.item.component_props.default); | 66 | const checkbox_value = ref(props.item.component_props.default); |
| 73 | const affix_value = ref({}); | 67 | const affix_value = ref({}); |
| 68 | +const options = props.item.component_props.options; | ||
| 69 | + | ||
| 70 | +const clearAffix = () => { | ||
| 71 | + // 为选中项目的补充清空 | ||
| 72 | + options.forEach(element => { | ||
| 73 | + if (!checkbox_value.value.includes(element.value)) { | ||
| 74 | + element.affix = '' | ||
| 75 | + } | ||
| 76 | + element.show_error = false; | ||
| 77 | + element.error_msg = ''; | ||
| 78 | + }); | ||
| 79 | +} | ||
| 74 | 80 | ||
| 75 | const onClick = (item) => { | 81 | const onClick = (item) => { |
| 76 | item.checked = !item.checked; | 82 | item.checked = !item.checked; |
| 77 | - handleEmit(item) | 83 | + handleEmit(item); |
| 84 | + // 清空错误提示 | ||
| 85 | + clearAffix(); | ||
| 86 | + // 校验输入项数据 | ||
| 87 | + validCheckbox(); | ||
| 78 | } | 88 | } |
| 79 | const onBlur = (item) => { | 89 | const onBlur = (item) => { |
| 80 | handleEmit(item) | 90 | handleEmit(item) |
| ... | @@ -91,34 +101,71 @@ const handleEmit = (item) => { | ... | @@ -91,34 +101,71 @@ const handleEmit = (item) => { |
| 91 | props.item.value = { key: props.item.key, value: checkbox_value.value, affix: affix_value.value, type: "checkbox" }; | 101 | props.item.value = { key: props.item.key, value: checkbox_value.value, affix: affix_value.value, type: "checkbox" }; |
| 92 | emit("active", props.item.value); | 102 | emit("active", props.item.value); |
| 93 | } | 103 | } |
| 104 | + | ||
| 94 | onMounted(() => { | 105 | onMounted(() => { |
| 106 | + // 新增错误提示标识 | ||
| 107 | + options.forEach(element => { | ||
| 108 | + element.show_error = false; | ||
| 109 | + element.error_msg = ''; | ||
| 110 | + }); | ||
| 95 | // 发送自定义数据结构 | 111 | // 发送自定义数据结构 |
| 96 | props.item.value = { key: props.item.key, value: checkbox_value.value, affix: affix_value.value, type: "checkbox" }; | 112 | props.item.value = { key: props.item.key, value: checkbox_value.value, affix: affix_value.value, type: "checkbox" }; |
| 97 | emit("active", props.item.value); | 113 | emit("active", props.item.value); |
| 98 | -}) | 114 | +}); |
| 115 | + | ||
| 116 | +const show_error = ref(false); | ||
| 117 | +const error_msg = ref(''); | ||
| 118 | +// 校验模块 | ||
| 119 | +const validCheckbox = () => { | ||
| 120 | + // 必填项 | ||
| 121 | + props.item.component_props.options.some(item => { | ||
| 122 | + // 必选项勾选校验 | ||
| 123 | + if (!checkbox_value.value.length && item.input_required) { | ||
| 124 | + show_error.value = true; | ||
| 125 | + error_msg.value = '必填项不能为空'; | ||
| 126 | + return true; | ||
| 127 | + } | ||
| 128 | + // 必选项勾选,校验补充信息填写情况校验 | ||
| 129 | + else if (checkbox_value.value.includes(item.value) && item.is_input && item.input_required && !item.affix) { | ||
| 130 | + show_error.value = true; | ||
| 131 | + error_msg.value = ''; | ||
| 132 | + item.show_error = true; | ||
| 133 | + item.error_msg = '补充信息不能为空'; | ||
| 134 | + return true; | ||
| 135 | + } else { | ||
| 136 | + show_error.value = false; | ||
| 137 | + error_msg.value = ''; | ||
| 138 | + item.show_error = false; | ||
| 139 | + item.error_msg = ''; | ||
| 140 | + } | ||
| 141 | + }); | ||
| 142 | + return !show_error.value; | ||
| 143 | +}; | ||
| 144 | + | ||
| 145 | +defineExpose({ validCheckbox }); | ||
| 99 | </script> | 146 | </script> |
| 100 | 147 | ||
| 101 | -<style lang="less" scoped> | 148 | +<style lang="less"> |
| 102 | .checkbox-field-page { | 149 | .checkbox-field-page { |
| 103 | .label { | 150 | .label { |
| 104 | - padding: 1rem 1rem 0 1rem; | 151 | + padding: 30px 30px 0 30px; |
| 105 | - font-size: 0.9rem; | 152 | + font-size: 26px; |
| 106 | font-weight: bold; | 153 | font-weight: bold; |
| 107 | } | 154 | } |
| 108 | 155 | ||
| 109 | .note { | 156 | .note { |
| 110 | - font-size: 0.9rem; | 157 | + font-size: 30px; |
| 111 | margin-left: 1rem; | 158 | margin-left: 1rem; |
| 112 | color: gray; | 159 | color: gray; |
| 113 | - padding-bottom: 0.5rem; | 160 | + padding-bottom: 0; |
| 114 | white-space: pre-wrap; | 161 | white-space: pre-wrap; |
| 115 | } | 162 | } |
| 116 | 163 | ||
| 117 | .checkbox-wrapper { | 164 | .checkbox-wrapper { |
| 118 | border: 1px solid #eaeaea; | 165 | border: 1px solid #eaeaea; |
| 119 | border-radius: 0.25rem; | 166 | border-radius: 0.25rem; |
| 120 | - padding: 0.25rem 0.5rem; | 167 | + padding: 25px; |
| 121 | - margin-bottom: 0.25rem; | 168 | + margin: 25px; |
| 122 | } | 169 | } |
| 123 | .affix-input { | 170 | .affix-input { |
| 124 | border: 1px solid #eaeaea; | 171 | border: 1px solid #eaeaea; | ... | ... |
| ... | @@ -2,7 +2,7 @@ import _ from '@/utils/lodash' | ... | @@ -2,7 +2,7 @@ import _ from '@/utils/lodash' |
| 2 | import TextField from '@/components/TextField/index.vue' | 2 | 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' |
| ... | @@ -87,9 +87,9 @@ export function createComponentType(data) { | ... | @@ -87,9 +87,9 @@ export function createComponentType(data) { |
| 87 | if (item.component_props.tag === 'radio') { | 87 | if (item.component_props.tag === 'radio') { |
| 88 | item.component = RadioField | 88 | item.component = RadioField |
| 89 | } | 89 | } |
| 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 | // } | ... | ... |
| 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-03 16:52:30 | 4 | + * @LastEditTime: 2023-04-04 10:21:43 |
| 5 | * @FilePath: /custom_form/src/pages/table/index.vue | 5 | * @FilePath: /custom_form/src/pages/table/index.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -63,7 +63,7 @@ import { storeToRefs } from 'pinia' | ... | @@ -63,7 +63,7 @@ import { storeToRefs } from 'pinia' |
| 63 | import { mainStore } from '@/stores' | 63 | import { mainStore } from '@/stores' |
| 64 | import { queryFormAPI, postVerifyPasswordAPI } from "@/api/form.js"; | 64 | import { queryFormAPI, postVerifyPasswordAPI } from "@/api/form.js"; |
| 65 | import { addFormDataAPI } from "@/api/data.js"; | 65 | import { addFormDataAPI } from "@/api/data.js"; |
| 66 | -import { wxInfo, getUrlParams } from "@/utils/tools"; | 66 | +import { wxInfo, getUrlParams, deepClone } from "@/utils/tools"; |
| 67 | import { styleColor } from "@/constant.js"; | 67 | import { styleColor } from "@/constant.js"; |
| 68 | import { sharePage } from '@/composables/useShare.js' | 68 | import { sharePage } from '@/composables/useShare.js' |
| 69 | // 初始化WX环境 | 69 | // 初始化WX环境 |
| ... | @@ -129,6 +129,7 @@ const formatData = (data) => { | ... | @@ -129,6 +129,7 @@ const formatData = (data) => { |
| 129 | const input = ref([]); | 129 | 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 area_picker = ref([]); | 133 | const area_picker = ref([]); |
| 133 | const image_uploader = ref([]); | 134 | const image_uploader = ref([]); |
| 134 | const file_uploader = ref([]); | 135 | const file_uploader = ref([]); |
| ... | @@ -146,6 +147,9 @@ const setRefMap = (el, item) => { | ... | @@ -146,6 +147,9 @@ const setRefMap = (el, item) => { |
| 146 | if (item.component_props.tag === "radio") { | 147 | if (item.component_props.tag === "radio") { |
| 147 | radio.value.push(el); | 148 | radio.value.push(el); |
| 148 | } | 149 | } |
| 150 | + if (item.component_props.tag === "checkbox") { | ||
| 151 | + checkbox.value.push(el); | ||
| 152 | + } | ||
| 149 | if (item.component_props.tag === "area_picker") { | 153 | if (item.component_props.tag === "area_picker") { |
| 150 | area_picker.value.push(el); | 154 | area_picker.value.push(el); |
| 151 | } | 155 | } |
| ... | @@ -378,6 +382,17 @@ const onActive = (item) => { | ... | @@ -378,6 +382,17 @@ const onActive = (item) => { |
| 378 | if (item.type === "radio") { // 单选控件 | 382 | if (item.type === "radio") { // 单选控件 |
| 379 | postData.value = Object.assign(postData.value, { [item.key]: item.affix ? item.affix : item.value }); | 383 | postData.value = Object.assign(postData.value, { [item.key]: item.affix ? item.affix : item.value }); |
| 380 | } | 384 | } |
| 385 | + if (item.type === "checkbox") { // 多选控件 | ||
| 386 | + const checkbox_value = deepClone(item.value) | ||
| 387 | + checkbox_value.forEach((element, index) => { | ||
| 388 | + for (const key in item.affix) { | ||
| 389 | + if (item.affix[key] && element === key) { | ||
| 390 | + checkbox_value[index] = item.affix[key] | ||
| 391 | + } | ||
| 392 | + } | ||
| 393 | + }); | ||
| 394 | + postData.value = Object.assign(postData.value, { [item.key]: checkbox_value }); | ||
| 395 | + } | ||
| 381 | if (item.key === "area_picker") { | 396 | if (item.key === "area_picker") { |
| 382 | postData.value[item.filed_name] = item.value; | 397 | postData.value[item.filed_name] = item.value; |
| 383 | } | 398 | } |
| ... | @@ -396,17 +411,6 @@ const onActive = (item) => { | ... | @@ -396,17 +411,6 @@ const onActive = (item) => { |
| 396 | if (item.type === "picker") { // 下拉框控件 | 411 | if (item.type === "picker") { // 下拉框控件 |
| 397 | postData.value = _.assign(postData.value, { [item.key]: item.value }); | 412 | postData.value = _.assign(postData.value, { [item.key]: item.value }); |
| 398 | } | 413 | } |
| 399 | - if (item.type === "checkbox") { // 多选控件 | ||
| 400 | - const checkbox_value = _.cloneDeep(item.value) | ||
| 401 | - checkbox_value.forEach((element, index) => { | ||
| 402 | - for (const key in item.affix) { | ||
| 403 | - if (item.affix[key] && element === key) { | ||
| 404 | - checkbox_value[index] = item.affix[key] | ||
| 405 | - } | ||
| 406 | - } | ||
| 407 | - }); | ||
| 408 | - postData.value = _.assign(postData.value, { [item.key]: checkbox_value }); | ||
| 409 | - } | ||
| 410 | // 检查规则,会影响字段显示 | 414 | // 检查规则,会影响字段显示 |
| 411 | checkRules(); | 415 | checkRules(); |
| 412 | }; | 416 | }; |
| ... | @@ -453,6 +457,18 @@ const validOther = () => { | ... | @@ -453,6 +457,18 @@ const validOther = () => { |
| 453 | } | 457 | } |
| 454 | }); | 458 | }); |
| 455 | } | 459 | } |
| 460 | + if (checkbox.value) { | ||
| 461 | + // 单选框 | ||
| 462 | + checkbox.value.forEach((item, index) => { | ||
| 463 | + if (!checkbox.value[index].validCheckbox()) { | ||
| 464 | + valid = { | ||
| 465 | + status: checkbox.value[index].validCheckbox(), | ||
| 466 | + key: "checkbox", | ||
| 467 | + }; | ||
| 468 | + return false; | ||
| 469 | + } | ||
| 470 | + }); | ||
| 471 | + } | ||
| 456 | if (area_picker.value) { | 472 | if (area_picker.value) { |
| 457 | // 省市区地址 | 473 | // 省市区地址 |
| 458 | area_picker.value.forEach((item, index) => { | 474 | area_picker.value.forEach((item, index) => { | ... | ... |
| 1 | /* | 1 | /* |
| 2 | * @Date: 2022-04-18 15:59:42 | 2 | * @Date: 2022-04-18 15:59:42 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2023-02-24 16:13:06 | 4 | + * @LastEditTime: 2023-04-04 10:21:01 |
| 5 | - * @FilePath: /data-table/src/utils/tools.js | 5 | + * @FilePath: /custom_form/src/utils/tools.js |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | */ | 7 | */ |
| 8 | -import dayjs from 'dayjs'; | 8 | +import dayjs from 'dayjs' |
| 9 | 9 | ||
| 10 | // 格式化时间 | 10 | // 格式化时间 |
| 11 | const formatDate = (date) => { | 11 | const formatDate = (date) => { |
| 12 | - return dayjs(date).format('YYYY-MM-DD HH:mm'); | 12 | + return dayjs(date).format('YYYY-MM-DD HH:mm') |
| 13 | -}; | 13 | +} |
| 14 | 14 | ||
| 15 | /** | 15 | /** |
| 16 | * @description 判断浏览器属于平台 | 16 | * @description 判断浏览器属于平台 |
| 17 | * @returns | 17 | * @returns |
| 18 | */ | 18 | */ |
| 19 | const wxInfo = () => { | 19 | const wxInfo = () => { |
| 20 | - let u = navigator.userAgent; | 20 | + let u = navigator.userAgent |
| 21 | - let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //android终端或者uc浏览器 | 21 | + let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1 //android终端或者uc浏览器 |
| 22 | - let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端 | 22 | + let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) //ios终端 |
| 23 | - let isMobile = u.indexOf('Android') > -1 || u.indexOf('iPhone') > -1 || u.indexOf('iPad') > -1; // 移动端平台 | 23 | + let isMobile = |
| 24 | - let isIpad = u.indexOf('iPad') > -1; // iPad平台 | 24 | + u.indexOf('Android') > -1 || |
| 25 | - let uAgent = navigator.userAgent.toLowerCase(); | 25 | + u.indexOf('iPhone') > -1 || |
| 26 | - let isWeiXin = (uAgent.match(/MicroMessenger/i) == 'micromessenger') ? true : false; | 26 | + u.indexOf('iPad') > -1 // 移动端平台 |
| 27 | - let isPC = (uAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone|micromessenger)/i)) ? false : true; | 27 | + let isIpad = u.indexOf('iPad') > -1 // iPad平台 |
| 28 | + let uAgent = navigator.userAgent.toLowerCase() | ||
| 29 | + let isWeiXin = | ||
| 30 | + uAgent.match(/MicroMessenger/i) == 'micromessenger' ? true : false | ||
| 31 | + let isPC = uAgent.match( | ||
| 32 | + /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone|micromessenger)/i, | ||
| 33 | + ) | ||
| 34 | + ? false | ||
| 35 | + : true | ||
| 28 | return { | 36 | return { |
| 29 | isAndroid, | 37 | isAndroid, |
| 30 | isiOS, | 38 | isiOS, |
| 31 | isWeiXin, | 39 | isWeiXin, |
| 32 | isMobile, | 40 | isMobile, |
| 33 | isIpad, | 41 | isIpad, |
| 34 | - isPC | 42 | + isPC, |
| 35 | - }; | 43 | + } |
| 36 | -}; | 44 | +} |
| 37 | 45 | ||
| 38 | /** | 46 | /** |
| 39 | * @description 判断多行省略文本 | 47 | * @description 判断多行省略文本 |
| ... | @@ -41,8 +49,8 @@ const wxInfo = () => { | ... | @@ -41,8 +49,8 @@ const wxInfo = () => { |
| 41 | * @returns | 49 | * @returns |
| 42 | */ | 50 | */ |
| 43 | const hasEllipsis = (id) => { | 51 | const hasEllipsis = (id) => { |
| 44 | - let oDiv = document.getElementById(id); | 52 | + let oDiv = document.getElementById(id) |
| 45 | - let flag = false; | 53 | + let flag = false |
| 46 | if (oDiv.scrollHeight > oDiv.clientHeight) { | 54 | if (oDiv.scrollHeight > oDiv.clientHeight) { |
| 47 | flag = true | 55 | flag = true |
| 48 | } | 56 | } |
| ... | @@ -54,14 +62,15 @@ const hasEllipsis = (id) => { | ... | @@ -54,14 +62,15 @@ const hasEllipsis = (id) => { |
| 54 | * @param {*} url | 62 | * @param {*} url |
| 55 | * @returns | 63 | * @returns |
| 56 | */ | 64 | */ |
| 57 | -const parseQueryString = url => { | 65 | +const parseQueryString = (url) => { |
| 58 | - var json = {}; | 66 | + var json = {} |
| 59 | - var arr = url.indexOf('?') >= 0 ? url.substr(url.indexOf('?') + 1).split('&') : []; | 67 | + var arr = |
| 60 | - arr.forEach(item => { | 68 | + url.indexOf('?') >= 0 ? url.substr(url.indexOf('?') + 1).split('&') : [] |
| 61 | - var tmp = item.split('='); | 69 | + arr.forEach((item) => { |
| 62 | - json[tmp[0]] = decodeURIComponent(tmp[1]); | 70 | + var tmp = item.split('=') |
| 63 | - }); | 71 | + json[tmp[0]] = decodeURIComponent(tmp[1]) |
| 64 | - return json; | 72 | + }) |
| 73 | + return json | ||
| 65 | } | 74 | } |
| 66 | 75 | ||
| 67 | /** | 76 | /** |
| ... | @@ -71,8 +80,8 @@ const parseQueryString = url => { | ... | @@ -71,8 +80,8 @@ const parseQueryString = url => { |
| 71 | * @returns 包含状态 | 80 | * @returns 包含状态 |
| 72 | */ | 81 | */ |
| 73 | const strExist = (array, str) => { | 82 | const strExist = (array, str) => { |
| 74 | - const exist = array.filter(arr => { | 83 | + const exist = array.filter((arr) => { |
| 75 | - if (str.indexOf(arr) >= 0) return str; | 84 | + if (str.indexOf(arr) >= 0) return str |
| 76 | }) | 85 | }) |
| 77 | return exist.length > 0 | 86 | return exist.length > 0 |
| 78 | } | 87 | } |
| ... | @@ -85,45 +94,61 @@ const strExist = (array, str) => { | ... | @@ -85,45 +94,61 @@ const strExist = (array, str) => { |
| 85 | * @returns | 94 | * @returns |
| 86 | */ | 95 | */ |
| 87 | const changeURLArg = (url, arg, arg_val) => { | 96 | const changeURLArg = (url, arg, arg_val) => { |
| 88 | - var pattern = arg + '=([^&]*)'; | 97 | + var pattern = arg + '=([^&]*)' |
| 89 | - var replaceText = arg + '=' + arg_val; | 98 | + var replaceText = arg + '=' + arg_val |
| 90 | if (url.match(pattern)) { | 99 | if (url.match(pattern)) { |
| 91 | - var tmp = '/(' + arg + '=)([^&]*)/gi'; | 100 | + var tmp = '/(' + arg + '=)([^&]*)/gi' |
| 92 | - tmp = url.replace(eval(tmp), replaceText); | 101 | + tmp = url.replace(eval(tmp), replaceText) |
| 93 | - return tmp; | 102 | + return tmp |
| 94 | } else { | 103 | } else { |
| 95 | - if (url.match('[\?]')) { | 104 | + if (url.match('[?]')) { |
| 96 | - return url + '&' + replaceText; | 105 | + return url + '&' + replaceText |
| 97 | } else { | 106 | } else { |
| 98 | - return url + '?' + replaceText; | 107 | + return url + '?' + replaceText |
| 99 | } | 108 | } |
| 100 | } | 109 | } |
| 101 | - return url + '\n' + arg + '\n' + arg_val; | 110 | + return url + '\n' + arg + '\n' + arg_val |
| 102 | } | 111 | } |
| 103 | 112 | ||
| 104 | // 获取参数key/value值对 | 113 | // 获取参数key/value值对 |
| 105 | const getUrlParams = (url) => { | 114 | const getUrlParams = (url) => { |
| 106 | // 没有参数处理 | 115 | // 没有参数处理 |
| 107 | - if (url.split('?').length === 1) return false; | 116 | + if (url.split('?').length === 1) return false |
| 108 | - let arr = url.split('?'); | 117 | + let arr = url.split('?') |
| 109 | - let res = arr[1].split('&'); | 118 | + let res = arr[1].split('&') |
| 110 | - let items = {}; | 119 | + let items = {} |
| 111 | for (let i = 0; i < res.length; i++) { | 120 | for (let i = 0; i < res.length; i++) { |
| 112 | - let [key, value] = res[i].split('='); | 121 | + let [key, value] = res[i].split('=') |
| 113 | - items[key] = value; | 122 | + items[key] = value |
| 114 | } | 123 | } |
| 115 | return items | 124 | return items |
| 116 | } | 125 | } |
| 117 | 126 | ||
| 118 | // 格式化URL参数为字符串 | 127 | // 格式化URL参数为字符串 |
| 119 | const stringifyQuery = (params) => { | 128 | const stringifyQuery = (params) => { |
| 120 | - const queryString = []; | 129 | + const queryString = [] |
| 121 | Object.keys(params || {}).forEach((k) => { | 130 | Object.keys(params || {}).forEach((k) => { |
| 122 | - queryString.push(k + '=' + params[k]); | 131 | + queryString.push(k + '=' + params[k]) |
| 123 | - }); | 132 | + }) |
| 133 | + | ||
| 134 | + return '?' + queryString.join('&') | ||
| 135 | +} | ||
| 124 | 136 | ||
| 125 | - return '?' + queryString.join('&'); | 137 | +// 深克隆 |
| 126 | -}; | 138 | +const deepClone = (val) => { |
| 139 | + if (val.constructor == Object) { | ||
| 140 | + let obj = {}, | ||
| 141 | + keys = Object.keys(val) | ||
| 142 | + for (let i = 0; i < keys.length; i++) { | ||
| 143 | + obj[keys[i]] = deepClone(val[keys[i]]) | ||
| 144 | + } | ||
| 145 | + return obj | ||
| 146 | + } else if (Array.isArray(val)) { | ||
| 147 | + return [].concat(val) | ||
| 148 | + } else { | ||
| 149 | + return val | ||
| 150 | + } | ||
| 151 | +} | ||
| 127 | 152 | ||
| 128 | export { | 153 | export { |
| 129 | formatDate, | 154 | formatDate, |
| ... | @@ -134,4 +159,5 @@ export { | ... | @@ -134,4 +159,5 @@ export { |
| 134 | changeURLArg, | 159 | changeURLArg, |
| 135 | getUrlParams, | 160 | getUrlParams, |
| 136 | stringifyQuery, | 161 | stringifyQuery, |
| 137 | -}; | 162 | + deepClone, |
| 163 | +} | ... | ... |
-
Please register or login to post a comment