hookehuyr

✨ feat(多选框控件): 样式和组件逻辑修改

...@@ -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">&nbsp;*</span> 11 + <text v-if="item.component_props.required" style="color: red">&nbsp;*</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 (最多可选数:&nbsp;{{ item.component_props.max }}) 14 (最多可选数:&nbsp;{{ 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>
20 - <van-checkbox-group v-model="checkbox_value" :direction="item.component_props.direction"
21 :max="item.component_props.max" style="width: 100%"> 19 :max="item.component_props.max" style="width: 100%">
22 <div v-for="x in item.component_props.options" :key="x.title" class="checkbox-wrapper"> 20 <div v-for="x in item.component_props.options" :key="x.title" class="checkbox-wrapper">
23 - <van-checkbox @click="onClick(x)" :name="x.title" icon-size="1rem" shape="square" 21 + <nut-checkbox @click="onClick(x)" :label="x.title" icon-size="16" style="margin-bottom: 0.25rem">{{ x.title }}</nut-checkbox>
24 - :checked-color="themeVars.radioColor" style="margin-bottom: 0.25rem">{{ x.title }}</van-checkbox> 22 + <nut-input
25 - <van-field v-if="checkbox_value.includes(x.value) && x.is_input" @blur="onBlur(x)" v-model="x.affix" 23 + v-if="checkbox_value.includes(x.value) && x.is_input"
26 - label=" " label-width="5px" :placeholder="x.input_placeholder" :rules="x.input_required ? rules : ''" 24 + @blur="onBlur(x)"
25 + v-model="x.affix"
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
29 + v-if="x.show_error"
30 + style="padding: 5px 20px; color: red; font-size: 12px;"
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 }}
28 </div> 41 </div>
29 - </van-checkbox-group>
30 - </template>
31 - </van-field>
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 +}
......