Showing
21 changed files
with
566 additions
and
295 deletions
| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | * @Author: hookehuyr hookehuyr@gmail.com | 2 | * @Author: hookehuyr hookehuyr@gmail.com |
| 3 | * @Date: 2022-05-26 23:52:36 | 3 | * @Date: 2022-05-26 23:52:36 |
| 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 5 | - * @LastEditTime: 2022-12-09 14:20:44 | 5 | + * @LastEditTime: 2022-12-28 11:02:30 |
| 6 | * @FilePath: /data-table/src/App.vue | 6 | * @FilePath: /data-table/src/App.vue |
| 7 | * @Description: | 7 | * @Description: |
| 8 | --> | 8 | --> |
| ... | @@ -76,16 +76,7 @@ onMounted(async () => { | ... | @@ -76,16 +76,7 @@ onMounted(async () => { |
| 76 | const { data } = await getFormSettingAPI({ form_code: code }); | 76 | const { data } = await getFormSettingAPI({ form_code: code }); |
| 77 | const form_setting = {}; | 77 | const form_setting = {}; |
| 78 | if (data.length) { | 78 | if (data.length) { |
| 79 | - data[0].property_list.forEach((prop) => { | 79 | + Object.assign(form_setting, data[0]['property_list'], data[0]['extend']); |
| 80 | - const key = prop["property_code"]; | ||
| 81 | - const obj = { | ||
| 82 | - [key]: | ||
| 83 | - prop["setting_value"].length > 1 | ||
| 84 | - ? prop["setting_value"] | ||
| 85 | - : prop["setting_value"][0], | ||
| 86 | - }; | ||
| 87 | - Object.assign(form_setting, obj, data[0]['extend']); | ||
| 88 | - }); | ||
| 89 | } | 80 | } |
| 90 | // 缓存表单设置 | 81 | // 缓存表单设置 |
| 91 | store.changeFormSetting(form_setting); | 82 | store.changeFormSetting(form_setting); | ... | ... |
| 1 | /* | 1 | /* |
| 2 | * @Date: 2022-06-17 14:54:29 | 2 | * @Date: 2022-06-17 14:54:29 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-12-06 11:22:36 | 4 | + * @LastEditTime: 2022-12-16 15:57:01 |
| 5 | * @FilePath: /data-table/src/api/form.js | 5 | * @FilePath: /data-table/src/api/form.js |
| 6 | * @Description: 表单接口 | 6 | * @Description: 表单接口 |
| 7 | */ | 7 | */ |
| ... | @@ -9,7 +9,7 @@ import { fn, fetch } from '@/api/fn'; | ... | @@ -9,7 +9,7 @@ import { fn, fetch } from '@/api/fn'; |
| 9 | 9 | ||
| 10 | const Api = { | 10 | const Api = { |
| 11 | FORM_ADD: '/srv/?a=add_form', | 11 | FORM_ADD: '/srv/?a=add_form', |
| 12 | - FORM_QUERY: '/srv/?a=query_form', | 12 | + FORM_QUERY: '/srv/?a=query_form_all_field', |
| 13 | ADD_FORM_FIELD: '/srv/?a=add_form_field', | 13 | ADD_FORM_FIELD: '/srv/?a=add_form_field', |
| 14 | ADD_FORM_SETTING: '/srv/?a=add_form_setting', | 14 | ADD_FORM_SETTING: '/srv/?a=add_form_setting', |
| 15 | QUERY_FORM_SETTING: '/srv/?a=query_form_setting', | 15 | QUERY_FORM_SETTING: '/srv/?a=query_form_setting', | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-30 14:32:11 | 2 | * @Date: 2022-08-30 14:32:11 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-12-08 14:57:16 | 4 | + * @LastEditTime: 2022-12-29 15:42:46 |
| 5 | * @FilePath: /data-table/src/components/AreaPickerField/index.vue | 5 | * @FilePath: /data-table/src/components/AreaPickerField/index.vue |
| 6 | * @Description: 省市区选择控件 | 6 | * @Description: 省市区选择控件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="area-picker-field"> | 9 | + <div v-if="HideShow" class="area-picker-field"> |
| 10 | <div class="label">{{ item.component_props.label }}<span v-if="item.component_props.required"> *</span></div> | 10 | <div class="label">{{ item.component_props.label }}<span v-if="item.component_props.required"> *</span></div> |
| 11 | <van-field | 11 | <van-field |
| 12 | name="ignore" | 12 | name="ignore" |
| ... | @@ -22,7 +22,7 @@ | ... | @@ -22,7 +22,7 @@ |
| 22 | <van-field | 22 | <van-field |
| 23 | name="ignore" | 23 | name="ignore" |
| 24 | v-model="address" | 24 | v-model="address" |
| 25 | - :placeholder="item.component_props.placeholder" | 25 | + placeholder="请填写详细地址" |
| 26 | @blur="onBlur" | 26 | @blur="onBlur" |
| 27 | :rules="item.rules" | 27 | :rules="item.rules" |
| 28 | :border="false" | 28 | :border="false" |
| ... | @@ -54,7 +54,10 @@ import { areaList } from "@vant/area-data"; | ... | @@ -54,7 +54,10 @@ import { areaList } from "@vant/area-data"; |
| 54 | const props = defineProps({ | 54 | const props = defineProps({ |
| 55 | item: Object, | 55 | item: Object, |
| 56 | }); | 56 | }); |
| 57 | - | 57 | +// 隐藏显示 |
| 58 | +const HideShow = computed(() => { | ||
| 59 | + return !props.item.component_props.disabled | ||
| 60 | +}) | ||
| 58 | const emit = defineEmits(["active"]); | 61 | const emit = defineEmits(["active"]); |
| 59 | const show_empty = ref(false); | 62 | const show_empty = ref(false); |
| 60 | 63 | ... | ... |
| 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: 2022-11-21 14:42:00 | 4 | + * @LastEditTime: 2022-12-29 11:34:14 |
| 5 | * @FilePath: /data-table/src/components/CheckboxField/index.vue | 5 | * @FilePath: /data-table/src/components/CheckboxField/index.vue |
| 6 | * @Description: 多项选择控件 | 6 | * @Description: 多项选择控件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="checkbox-field-page"> | 9 | + <div v-if="HideShow" class="checkbox-field-page"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label }} | 11 | {{ item.component_props.label }} |
| 12 | <span v-if="item.component_props.required" style="color: red"> *</span> | 12 | <span v-if="item.component_props.required" style="color: red"> *</span> |
| ... | @@ -14,6 +14,9 @@ | ... | @@ -14,6 +14,9 @@ |
| 14 | (最多可选数: {{ item.component_props.max }}) | 14 | (最多可选数: {{ item.component_props.max }}) |
| 15 | </span> | 15 | </span> |
| 16 | </div> | 16 | </div> |
| 17 | + <div v-if="item.component_props.note" class="note"> | ||
| 18 | + {{ item.component_props.note }} | ||
| 19 | + </div> | ||
| 17 | <van-field :name="item.key" :rules="item.rules" :border="false"> | 20 | <van-field :name="item.key" :rules="item.rules" :border="false"> |
| 18 | <template #input> | 21 | <template #input> |
| 19 | <van-checkbox-group | 22 | <van-checkbox-group |
| ... | @@ -24,13 +27,13 @@ | ... | @@ -24,13 +27,13 @@ |
| 24 | > | 27 | > |
| 25 | <van-checkbox | 28 | <van-checkbox |
| 26 | v-for="x in item.component_props.options" | 29 | v-for="x in item.component_props.options" |
| 27 | - :key="index" | 30 | + :key="x.value" |
| 28 | - :name="x" | 31 | + :name="x.value" |
| 29 | icon-size="1rem" | 32 | icon-size="1rem" |
| 30 | shape="square" | 33 | shape="square" |
| 31 | :checked-color="themeVars.radioColor" | 34 | :checked-color="themeVars.radioColor" |
| 32 | style="margin-bottom: 0.25rem" | 35 | style="margin-bottom: 0.25rem" |
| 33 | - >{{ x }}</van-checkbox | 36 | + >{{ x.title }}</van-checkbox |
| 34 | > | 37 | > |
| 35 | </van-checkbox-group> | 38 | </van-checkbox-group> |
| 36 | </template> | 39 | </template> |
| ... | @@ -52,6 +55,10 @@ onMounted(() => { | ... | @@ -52,6 +55,10 @@ onMounted(() => { |
| 52 | // 默认值为数组 | 55 | // 默认值为数组 |
| 53 | props.item.value = []; | 56 | props.item.value = []; |
| 54 | }); | 57 | }); |
| 58 | +// 隐藏显示 | ||
| 59 | +const HideShow = computed(() => { | ||
| 60 | + return !props.item.component_props.disabled | ||
| 61 | +}) | ||
| 55 | </script> | 62 | </script> |
| 56 | 63 | ||
| 57 | <style lang="less" scoped> | 64 | <style lang="less" scoped> |
| ... | @@ -61,6 +68,12 @@ onMounted(() => { | ... | @@ -61,6 +68,12 @@ onMounted(() => { |
| 61 | font-size: 0.9rem; | 68 | font-size: 0.9rem; |
| 62 | font-weight: bold; | 69 | font-weight: bold; |
| 63 | } | 70 | } |
| 71 | + .note { | ||
| 72 | + font-size: 0.9rem; | ||
| 73 | + margin-left: 1rem; | ||
| 74 | + color: gray; | ||
| 75 | + padding-bottom: 0.5rem | ||
| 76 | + } | ||
| 64 | } | 77 | } |
| 65 | 78 | ||
| 66 | :deep(.van-checkbox) { | 79 | :deep(.van-checkbox) { | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-31 11:45:30 | 2 | * @Date: 2022-08-31 11:45:30 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-11-21 14:43:16 | 4 | + * @LastEditTime: 2022-12-29 11:45:54 |
| 5 | * @FilePath: /data-table/src/components/DatePickerField/index.vue | 5 | * @FilePath: /data-table/src/components/DatePickerField/index.vue |
| 6 | * @Description: 日期选择组件 | 6 | * @Description: 日期选择组件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="date-picker-field"> | 9 | + <div v-if="HideShow" class="date-picker-field"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label }} | 11 | {{ item.component_props.label }} |
| 12 | <span v-if="item.component_props.required"> *</span> | 12 | <span v-if="item.component_props.required"> *</span> |
| ... | @@ -17,17 +17,17 @@ | ... | @@ -17,17 +17,17 @@ |
| 17 | readonly | 17 | readonly |
| 18 | :name="item.key" | 18 | :name="item.key" |
| 19 | :required="item.component_props.required" | 19 | :required="item.component_props.required" |
| 20 | - :placeholder="item.component_props.placeholder" | 20 | + disabled="item.component_props.readonly" |
| 21 | - :rules="item.rules" | 21 | + :placeholder="item.component_props.placeholder ? item.component_props.placeholder : '请选择日期'" |
| 22 | - @click="showPicker = true" | 22 | + :rules="rules" |
| 23 | + @click="onTap" | ||
| 24 | + :border="false" | ||
| 23 | /> | 25 | /> |
| 24 | <van-popup v-model:show="showPicker" position="bottom"> | 26 | <van-popup v-model:show="showPicker" position="bottom"> |
| 25 | <van-date-picker | 27 | <van-date-picker |
| 26 | v-model="currentDate" | 28 | v-model="currentDate" |
| 27 | - :title="item.component_props.title" | 29 | + title="日期选择" |
| 28 | - :min-date="item.component_props.min_date" | 30 | + :columns-type="columns_type" |
| 29 | - :max-date="item.component_props.max_date" | ||
| 30 | - :columns-type="item.component_props.columns_type" | ||
| 31 | @confirm="onConfirm" | 31 | @confirm="onConfirm" |
| 32 | @cancel="showPicker = false" | 32 | @cancel="showPicker = false" |
| 33 | /> | 33 | /> |
| ... | @@ -41,24 +41,69 @@ import dayjs from "dayjs"; | ... | @@ -41,24 +41,69 @@ import dayjs from "dayjs"; |
| 41 | const props = defineProps({ | 41 | const props = defineProps({ |
| 42 | item: Object, | 42 | item: Object, |
| 43 | }); | 43 | }); |
| 44 | - | 44 | +// 隐藏显示 |
| 45 | +const HideShow = computed(() => { | ||
| 46 | + return !props.item.component_props.disabled | ||
| 47 | +}) | ||
| 45 | const showPicker = ref(false); | 48 | const showPicker = ref(false); |
| 46 | const currentDate = ref([]); | 49 | const currentDate = ref([]); |
| 50 | +const readonly = props.item.component_props.readonly; | ||
| 47 | 51 | ||
| 52 | +const onTap = () => { | ||
| 53 | + if (readonly) return false; // 如果为只读,不能设置 | ||
| 54 | + showPicker.value = true | ||
| 55 | +} | ||
| 48 | const onConfirm = ({ selectedValues, selectedOptions }) => { | 56 | const onConfirm = ({ selectedValues, selectedOptions }) => { |
| 49 | - props.item.value = selectedValues[0] + "-" + selectedValues[1]; | 57 | + props.item.value = selectedValues.join("-"); |
| 50 | showPicker.value = false; | 58 | showPicker.value = false; |
| 51 | }; | 59 | }; |
| 52 | 60 | ||
| 61 | +const columns_type = ref([]); | ||
| 62 | +const date_format = props.item.component_props.data_dateformat; // YYYY-MM=年月,YYYY-MM-DD=年月日 | ||
| 53 | onMounted(() => { | 63 | onMounted(() => { |
| 54 | currentDate.value = props.item.value.split("-"); | 64 | currentDate.value = props.item.value.split("-"); |
| 65 | + switch (date_format) { | ||
| 66 | + case "YYYY-MM": | ||
| 67 | + columns_type.value = ['year', 'month'] | ||
| 68 | + break; | ||
| 69 | + case "YYYY-MM-DD": | ||
| 70 | + columns_type.value = ['year', 'month', 'day'] | ||
| 71 | + break; | ||
| 72 | + } | ||
| 55 | }); | 73 | }); |
| 74 | + | ||
| 75 | +const required = props.item.component_props.required; | ||
| 76 | +const data_minvalue = props.item.component_props.data_minvalue; | ||
| 77 | +const data_maxvalue = props.item.component_props.data_maxvalue; | ||
| 78 | +const validator = (val) => { | ||
| 79 | + if (required && !val) { | ||
| 80 | + return false; | ||
| 81 | + } else if (val && data_minvalue && val < data_minvalue) { | ||
| 82 | + return false; | ||
| 83 | + } else if (val && data_maxvalue && val > data_maxvalue) { | ||
| 84 | + return false; | ||
| 85 | + } else { | ||
| 86 | + return true; | ||
| 87 | + } | ||
| 88 | +}; | ||
| 89 | +// 错误提示文案 | ||
| 90 | +const validatorMessage = (val, rule) => { | ||
| 91 | + if (required && !val) { | ||
| 92 | + return "必填项不能为空"; | ||
| 93 | + } else if (val && data_minvalue && val < data_minvalue) { | ||
| 94 | + return "最小可选:" + data_minvalue; | ||
| 95 | + } else if (val && data_maxvalue && val > data_maxvalue) { | ||
| 96 | + return "最大可选:" + data_maxvalue; | ||
| 97 | + } | ||
| 98 | +}; | ||
| 99 | +const rules = [{ validator, message: validatorMessage }]; | ||
| 56 | </script> | 100 | </script> |
| 57 | 101 | ||
| 58 | <style lang="less" scoped> | 102 | <style lang="less" scoped> |
| 59 | .date-picker-field { | 103 | .date-picker-field { |
| 104 | + margin: 1rem; | ||
| 60 | .label { | 105 | .label { |
| 61 | - padding: 1rem 1rem 0 1rem; | 106 | + // padding: 1rem 1rem 0 1rem; |
| 62 | font-size: 0.9rem; | 107 | font-size: 0.9rem; |
| 63 | font-weight: bold; | 108 | font-weight: bold; |
| 64 | 109 | ||
| ... | @@ -67,4 +112,11 @@ onMounted(() => { | ... | @@ -67,4 +112,11 @@ onMounted(() => { |
| 67 | } | 112 | } |
| 68 | } | 113 | } |
| 69 | } | 114 | } |
| 115 | + | ||
| 116 | +:deep(.van-cell--clickable) { | ||
| 117 | + border: 1px solid #eaeaea; | ||
| 118 | + border-radius: 0.25rem; | ||
| 119 | + padding: 0.25rem 0.5rem; | ||
| 120 | + margin-top: 0.5rem; | ||
| 121 | +} | ||
| 70 | </style> | 122 | </style> | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-09-08 15:02:45 | 2 | * @Date: 2022-09-08 15:02:45 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-11-21 14:47:52 | 4 | + * @LastEditTime: 2022-12-29 11:44:54 |
| 5 | * @FilePath: /data-table/src/components/DateTimePickerField/index.vue | 5 | * @FilePath: /data-table/src/components/DateTimePickerField/index.vue |
| 6 | * @Description: 日期时间选择器 | 6 | * @Description: 日期时间选择器 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="datetime-picker"> | 9 | + <div v-if="HideShow" class="datetime-picker"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label }} | 11 | {{ item.component_props.label }} |
| 12 | <span v-if="item.component_props.required"> *</span> | 12 | <span v-if="item.component_props.required"> *</span> |
| ... | @@ -17,22 +17,21 @@ | ... | @@ -17,22 +17,21 @@ |
| 17 | readonly | 17 | readonly |
| 18 | :name="item.key" | 18 | :name="item.key" |
| 19 | :required="item.component_props.required" | 19 | :required="item.component_props.required" |
| 20 | - :placeholder="item.component_props.placeholder" | 20 | + disabled="item.component_props.readonly" |
| 21 | - :rules="item.rules" | 21 | + :placeholder="item.component_props.placeholder ? item.component_props.placeholder : '请选择日期时间'" |
| 22 | - @click="showPicker = true" | 22 | + :rules="rules" |
| 23 | + @click="onTap" | ||
| 24 | + :border="false" | ||
| 23 | /> | 25 | /> |
| 24 | <van-popup v-model:show="showPicker" position="bottom"> | 26 | <van-popup v-model:show="showPicker" position="bottom"> |
| 25 | <van-picker-group | 27 | <van-picker-group |
| 26 | - :title="item.component_props.title" | 28 | + title="请选择日期时间" |
| 27 | :tabs="['选择日期', '选择时间']" | 29 | :tabs="['选择日期', '选择时间']" |
| 28 | @confirm="onConfirm" | 30 | @confirm="onConfirm" |
| 29 | @cancel="onCancel" | 31 | @cancel="onCancel" |
| 30 | > | 32 | > |
| 31 | - <van-date-picker | 33 | + <van-date-picker v-model="currentDate" :columns-type="columns_date_type" /> |
| 32 | - v-model="currentDate" | 34 | + <van-time-picker v-model="currentTime" :columns-type="columns_time_type" /> |
| 33 | - :min-date="item.component_props.min_date" | ||
| 34 | - /> | ||
| 35 | - <van-time-picker v-model="currentTime" /> | ||
| 36 | </van-picker-group> | 35 | </van-picker-group> |
| 37 | </van-popup> | 36 | </van-popup> |
| 38 | </div> | 37 | </div> |
| ... | @@ -45,8 +44,17 @@ import dayjs from "dayjs"; | ... | @@ -45,8 +44,17 @@ import dayjs from "dayjs"; |
| 45 | const props = defineProps({ | 44 | const props = defineProps({ |
| 46 | item: Object, | 45 | item: Object, |
| 47 | }); | 46 | }); |
| 47 | +// 隐藏显示 | ||
| 48 | +const HideShow = computed(() => { | ||
| 49 | + return !props.item.component_props.disabled | ||
| 50 | +}) | ||
| 48 | const showPicker = ref(false); | 51 | const showPicker = ref(false); |
| 52 | +const readonly = props.item.component_props.readonly; | ||
| 49 | 53 | ||
| 54 | +const onTap = () => { | ||
| 55 | + if (readonly) return false; // 如果为只读,不能设置 | ||
| 56 | + showPicker.value = true | ||
| 57 | +} | ||
| 50 | const currentDate = ref([]); | 58 | const currentDate = ref([]); |
| 51 | const currentTime = ref([]); | 59 | const currentTime = ref([]); |
| 52 | 60 | ||
| ... | @@ -58,18 +66,72 @@ const onCancel = () => { | ... | @@ -58,18 +66,72 @@ const onCancel = () => { |
| 58 | showPicker.value = false; | 66 | showPicker.value = false; |
| 59 | }; | 67 | }; |
| 60 | 68 | ||
| 69 | +const columns_date_type = ref([]); | ||
| 70 | +const columns_time_type = ref([]); | ||
| 71 | +const date_format = props.item.component_props.data_dateformat; | ||
| 61 | onMounted(() => { | 72 | onMounted(() => { |
| 62 | // 获取值定位显示 | 73 | // 获取值定位显示 |
| 63 | const datetime = props.item.value.split(" "); | 74 | const datetime = props.item.value.split(" "); |
| 64 | currentDate.value = datetime[0]?.split("-"); | 75 | currentDate.value = datetime[0]?.split("-"); |
| 65 | currentTime.value = datetime[1]?.split(":"); | 76 | currentTime.value = datetime[1]?.split(":"); |
| 77 | + // YYYY=年,YYYY-MM=年月,YYYY-MM-DD=年月日,YYYY-MM-DD HH=年月日时,YYYY-MM-DD HH:mm=年月日时分,YYYY-MM-DD HH:mm:ss=年月日时分秒 | ||
| 78 | + switch (date_format) { | ||
| 79 | + case "YYYY": | ||
| 80 | + columns_date_type.value = ['year'] | ||
| 81 | + break; | ||
| 82 | + case "YYYY-MM": | ||
| 83 | + columns_date_type.value = ['year', 'month'] | ||
| 84 | + break; | ||
| 85 | + case "YYYY-MM-DD": | ||
| 86 | + columns_date_type.value = ['year', 'month', 'day'] | ||
| 87 | + break; | ||
| 88 | + case "YYYY-MM-DD HH": | ||
| 89 | + columns_date_type.value = ['year', 'month', 'day'] | ||
| 90 | + columns_time_type.value = ['hour'] | ||
| 91 | + break; | ||
| 92 | + case "YYYY-MM-DD HH:mm": | ||
| 93 | + columns_date_type.value = ['year', 'month', 'day'] | ||
| 94 | + columns_time_type.value = ['hour', 'minute'] | ||
| 95 | + break; | ||
| 96 | + case "YYYY-MM-DD HH:mm:ss": | ||
| 97 | + columns_date_type.value = ['year', 'month', 'day'] | ||
| 98 | + columns_time_type.value = ['hour', 'minute', 'second'] | ||
| 99 | + break; | ||
| 100 | + } | ||
| 66 | }); | 101 | }); |
| 102 | + | ||
| 103 | +const required = props.item.component_props.required; | ||
| 104 | +const data_minvalue = props.item.component_props.data_minvalue; | ||
| 105 | +const data_maxvalue = props.item.component_props.data_maxvalue; | ||
| 106 | +const validator = (val) => { | ||
| 107 | + if (required && !val) { | ||
| 108 | + return false; | ||
| 109 | + } else if (val && data_minvalue && val < data_minvalue) { | ||
| 110 | + return false; | ||
| 111 | + } else if (val && data_maxvalue && val > data_maxvalue) { | ||
| 112 | + return false; | ||
| 113 | + } else { | ||
| 114 | + return true; | ||
| 115 | + } | ||
| 116 | +}; | ||
| 117 | +// 错误提示文案 | ||
| 118 | +const validatorMessage = (val, rule) => { | ||
| 119 | + if (required && !val) { | ||
| 120 | + return "必填项不能为空"; | ||
| 121 | + } else if (val && data_minvalue && val < data_minvalue) { | ||
| 122 | + return "最小可选:" + data_minvalue; | ||
| 123 | + } else if (val && data_maxvalue && val > data_maxvalue) { | ||
| 124 | + return "最大可选:" + data_maxvalue; | ||
| 125 | + } | ||
| 126 | +}; | ||
| 127 | +const rules = [{ validator, message: validatorMessage }]; | ||
| 67 | </script> | 128 | </script> |
| 68 | 129 | ||
| 69 | <style lang="less" scoped> | 130 | <style lang="less" scoped> |
| 70 | .datetime-picker { | 131 | .datetime-picker { |
| 132 | + margin: 1rem; | ||
| 71 | .label { | 133 | .label { |
| 72 | - padding: 1rem 1rem 0 1rem; | 134 | + // padding: 1rem 1rem 0 1rem; |
| 73 | font-size: 0.9rem; | 135 | font-size: 0.9rem; |
| 74 | font-weight: bold; | 136 | font-weight: bold; |
| 75 | 137 | ||
| ... | @@ -78,4 +140,11 @@ onMounted(() => { | ... | @@ -78,4 +140,11 @@ onMounted(() => { |
| 78 | } | 140 | } |
| 79 | } | 141 | } |
| 80 | } | 142 | } |
| 143 | + | ||
| 144 | +:deep(.van-cell--clickable) { | ||
| 145 | + border: 1px solid #eaeaea; | ||
| 146 | + border-radius: 0.25rem; | ||
| 147 | + padding: 0.25rem 0.5rem; | ||
| 148 | + margin-top: 0.5rem; | ||
| 149 | +} | ||
| 81 | </style> | 150 | </style> | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-29 14:31:20 | 2 | * @Date: 2022-08-29 14:31:20 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-11-21 16:08:20 | 4 | + * @LastEditTime: 2022-12-22 13:17:34 |
| 5 | * @FilePath: /data-table/src/components/EmailField/index.vue | 5 | * @FilePath: /data-table/src/components/EmailField/index.vue |
| 6 | * @Description: 邮箱输入框 | 6 | * @Description: 邮箱输入框 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="text-field-page"> | 9 | + <div v-if="HideShow" class="text-field-page"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label | 11 | {{ item.component_props.label |
| 12 | }}<span v-if="item.component_props.required"> *</span> | 12 | }}<span v-if="item.component_props.required"> *</span> |
| ... | @@ -18,6 +18,7 @@ | ... | @@ -18,6 +18,7 @@ |
| 18 | :placeholder="item.component_props.placeholder" | 18 | :placeholder="item.component_props.placeholder" |
| 19 | :rules="rules" | 19 | :rules="rules" |
| 20 | :required="item.component_props.required" | 20 | :required="item.component_props.required" |
| 21 | + disabled="item.component_props.readonly" | ||
| 21 | clearable | 22 | clearable |
| 22 | /> | 23 | /> |
| 23 | </div> | 24 | </div> |
| ... | @@ -27,16 +28,29 @@ | ... | @@ -27,16 +28,29 @@ |
| 27 | const props = defineProps({ | 28 | const props = defineProps({ |
| 28 | item: Object, | 29 | item: Object, |
| 29 | }); | 30 | }); |
| 30 | - | 31 | +// 隐藏显示 |
| 32 | +const HideShow = computed(() => { | ||
| 33 | + return !props.item.component_props.disabled | ||
| 34 | +}) | ||
| 35 | +const required = props.item.component_props.required; | ||
| 31 | const validator = (val) => { | 36 | const validator = (val) => { |
| 32 | - if (!props.item.component_props.required) { | 37 | + if (required && !val) { |
| 33 | - // 非必填 | 38 | + return false; |
| 34 | - return true; | 39 | + } else if (val && !/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test(val)) { |
| 40 | + return false; | ||
| 35 | } else { | 41 | } else { |
| 36 | - return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test(val); | 42 | + return true; |
| 43 | + } | ||
| 44 | +}; | ||
| 45 | +// 错误提示文案 | ||
| 46 | +const validatorMessage = (val, rule) => { | ||
| 47 | + if (required && !val) { | ||
| 48 | + return "必填项不能为空"; | ||
| 49 | + } else if (val && !/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test(val)) { // 小于最小值 | ||
| 50 | + return "请输入正确邮箱"; | ||
| 37 | } | 51 | } |
| 38 | }; | 52 | }; |
| 39 | -const rules = [{ validator, message: "请输入正确邮箱" }]; | 53 | +const rules = [{ validator, message: validatorMessage }]; |
| 40 | </script> | 54 | </script> |
| 41 | 55 | ||
| 42 | <style lang="less" scoped> | 56 | <style lang="less" scoped> | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-31 16:16:49 | 2 | * @Date: 2022-08-31 16:16:49 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-11-21 14:54:30 | 4 | + * @LastEditTime: 2022-12-30 16:53:12 |
| 5 | - * @FilePath: /data-table/src/components/ImageUploaderField/index.vue | 5 | + * @FilePath: /data-table/src/components/FileUploaderField/index.vue |
| 6 | * @Description: 文件上传控件 | 6 | * @Description: 文件上传控件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="file-uploader-field"> | 9 | + <div v-if="HideShow" class="file-uploader-field"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label | 11 | {{ item.component_props.label |
| 12 | }}<span v-if="item.component_props.required"> *</span> | 12 | }}<span v-if="item.component_props.required"> *</span> |
| 13 | </div> | 13 | </div> |
| 14 | <div | 14 | <div |
| 15 | v-if="item.component_props.note" | 15 | v-if="item.component_props.note" |
| 16 | - style="font-size: 0.9rem; margin-left: 1rem; color: gray; padding-bottom: 0.5rem" | 16 | + style="font-size: 0.9rem; margin-left: 1rem; color: gray; padding-bottom: 0.5rem; padding-top: 0.25rem;" |
| 17 | > | 17 | > |
| 18 | {{ item.component_props.note }} | 18 | {{ item.component_props.note }} |
| 19 | </div> | 19 | </div> |
| 20 | <div> | 20 | <div> |
| 21 | <p | 21 | <p |
| 22 | - v-for="file in fileList" | 22 | + v-for="(file, index) in fileList" |
| 23 | :key="index" | 23 | :key="index" |
| 24 | style="padding-left: 1rem; margin-bottom: 0.5rem" | 24 | style="padding-left: 1rem; margin-bottom: 0.5rem" |
| 25 | > | 25 | > |
| 26 | - <span style="font-size: 1rem">{{ file.filename }}</span | 26 | + <p style="font-size: 1rem; word-break: break-all; margin-right: 0.75rem;"> |
| 27 | - > | 27 | + <span>{{ index + 1 }}. {{ file.filename }} {{ (file.size / 1024 / 1024).toFixed(2) }}MB</span> |
| 28 | - <span style="color: #e32525; font-size: 0.85rem" @click="beforeDelete(file)" | 28 | + |
| 29 | - >移除</span | 29 | + <span style="color: #e32525; font-size: 0.85rem" @click="beforeDelete(file)">移除</span> |
| 30 | - > | 30 | + </p> |
| 31 | </p> | 31 | </p> |
| 32 | </div> | 32 | </div> |
| 33 | <div style="padding: 1rem"> | 33 | <div style="padding: 1rem"> |
| ... | @@ -38,6 +38,7 @@ | ... | @@ -38,6 +38,7 @@ |
| 38 | :before-read="beforeRead" | 38 | :before-read="beforeRead" |
| 39 | :after-read="afterRead" | 39 | :after-read="afterRead" |
| 40 | :before-delete="beforeDelete" | 40 | :before-delete="beforeDelete" |
| 41 | + :multiple="item.component_props.max_size > 1" | ||
| 41 | > | 42 | > |
| 42 | <van-button icon="plus" type="primary">上传文件</van-button> | 43 | <van-button icon="plus" type="primary">上传文件</van-button> |
| 43 | </van-uploader> | 44 | </van-uploader> |
| ... | @@ -80,6 +81,10 @@ const $route = useRoute(); | ... | @@ -80,6 +81,10 @@ const $route = useRoute(); |
| 80 | const props = defineProps({ | 81 | const props = defineProps({ |
| 81 | item: Object, | 82 | item: Object, |
| 82 | }); | 83 | }); |
| 84 | +// 隐藏显示 | ||
| 85 | +const HideShow = computed(() => { | ||
| 86 | + return !props.item.component_props.disabled | ||
| 87 | +}) | ||
| 83 | const emit = defineEmits(["active"]); | 88 | const emit = defineEmits(["active"]); |
| 84 | const show_empty = ref(false); | 89 | const show_empty = ref(false); |
| 85 | 90 | ||
| ... | @@ -104,16 +109,21 @@ const beforeRead = (file) => { | ... | @@ -104,16 +109,21 @@ const beforeRead = (file) => { |
| 104 | // (item) => `video/${item}` | 109 | // (item) => `video/${item}` |
| 105 | // ); | 110 | // ); |
| 106 | let flag = true; | 111 | let flag = true; |
| 112 | + if (file.length + 1 > props.item.component_props.max_count) { | ||
| 113 | + // 数量限制 | ||
| 114 | + flag = false; | ||
| 115 | + showToast(`最大上传数量为${props.item.component_props.max_count}个`); | ||
| 116 | + } | ||
| 107 | if (fileList.value.length + 1 > props.item.component_props.max_count) { | 117 | if (fileList.value.length + 1 > props.item.component_props.max_count) { |
| 108 | // 数量限制 | 118 | // 数量限制 |
| 109 | flag = false; | 119 | flag = false; |
| 110 | showToast(`最大上传数量为${props.item.component_props.max_count}个`); | 120 | showToast(`最大上传数量为${props.item.component_props.max_count}个`); |
| 111 | } | 121 | } |
| 112 | - if (file.size > props.item.component_props.max_size) { | 122 | + if ((file.size / 1024 / 1024).toFixed(2) > props.item.component_props.max_size) { |
| 113 | // 体积限制 | 123 | // 体积限制 |
| 114 | flag = false; | 124 | flag = false; |
| 115 | showToast( | 125 | showToast( |
| 116 | - `最大文件体积为${(props.item.component_props.max_size / 1024 / 1024).toFixed(2)}MB` | 126 | + `最大文件体积为${props.item.component_props.max_size}MB` |
| 117 | ); | 127 | ); |
| 118 | } | 128 | } |
| 119 | // if (_.isArray(file)) { | 129 | // if (_.isArray(file)) { |
| ... | @@ -151,6 +161,7 @@ const afterRead = async (files) => { | ... | @@ -151,6 +161,7 @@ const afterRead = async (files) => { |
| 151 | // meta_id: imgUrl.meta_id, | 161 | // meta_id: imgUrl.meta_id, |
| 152 | filename: files.file.name, | 162 | filename: files.file.name, |
| 153 | url: imgUrl.src, | 163 | url: imgUrl.src, |
| 164 | + size: files.file.size | ||
| 154 | // isImage: true, | 165 | // isImage: true, |
| 155 | }); | 166 | }); |
| 156 | loading.value = false; | 167 | loading.value = false; |
| ... | @@ -249,6 +260,7 @@ var muliUpload = async (files) => { | ... | @@ -249,6 +260,7 @@ var muliUpload = async (files) => { |
| 249 | // meta_id: res.meta_id, | 260 | // meta_id: res.meta_id, |
| 250 | filename: item.file.name, | 261 | filename: item.file.name, |
| 251 | url: res.src, | 262 | url: res.src, |
| 263 | + size: files.file.size | ||
| 252 | // isImage: true, | 264 | // isImage: true, |
| 253 | }); | 265 | }); |
| 254 | loading.value = false; | 266 | loading.value = false; |
| ... | @@ -258,8 +270,9 @@ var muliUpload = async (files) => { | ... | @@ -258,8 +270,9 @@ var muliUpload = async (files) => { |
| 258 | 270 | ||
| 259 | // 生成数据库真实文件地址 | 271 | // 生成数据库真实文件地址 |
| 260 | const uploadQiniu = async (file, token, name, md5) => { | 272 | const uploadQiniu = async (file, token, name, md5) => { |
| 273 | + let suffix = /\.[^\.]+$/.exec(name); // 获取后缀 | ||
| 261 | // let affix = uuidv4(); | 274 | // let affix = uuidv4(); |
| 262 | - let fileName = `uploadForm/${formCode}/${md5}.${name.split(".")[1]}`; | 275 | + let fileName = `uploadForm/${formCode}/${md5}${suffix}`; |
| 263 | let formData = new FormData(); | 276 | let formData = new FormData(); |
| 264 | formData.append("file", file); // 通过append向form对象添加数据 | 277 | formData.append("file", file); // 通过append向form对象添加数据 |
| 265 | formData.append("token", token); | 278 | formData.append("token", token); | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-09-14 14:44:30 | 2 | * @Date: 2022-09-14 14:44:30 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-11-21 16:00:36 | 4 | + * @LastEditTime: 2022-12-29 11:32:10 |
| 5 | * @FilePath: /data-table/src/components/IdentityField/index.vue | 5 | * @FilePath: /data-table/src/components/IdentityField/index.vue |
| 6 | * @Description: 身份证输入控件 | 6 | * @Description: 身份证输入控件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="identity-page"> | 9 | + <div v-if="HideShow" class="identity-page"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label | 11 | {{ item.component_props.label |
| 12 | }}<span v-if="item.component_props.required"> *</span> | 12 | }}<span v-if="item.component_props.required"> *</span> |
| 13 | </div> | 13 | </div> |
| 14 | + <!-- <div v-if="item.component_props.readonly" style="padding: 0.5rem 1rem;">{{ item.value }}</div> --> | ||
| 14 | <van-field | 15 | <van-field |
| 15 | v-model="item.value" | 16 | v-model="item.value" |
| 16 | :id="item.name" | 17 | :id="item.name" |
| ... | @@ -18,6 +19,7 @@ | ... | @@ -18,6 +19,7 @@ |
| 18 | :placeholder="item.component_props.placeholder" | 19 | :placeholder="item.component_props.placeholder" |
| 19 | :rules="rules" | 20 | :rules="rules" |
| 20 | :required="item.component_props.required" | 21 | :required="item.component_props.required" |
| 22 | + :disabled="item.component_props.readonly" | ||
| 21 | readonly | 23 | readonly |
| 22 | @touchstart.stop="openKeyboard($event)" | 24 | @touchstart.stop="openKeyboard($event)" |
| 23 | :border="false" | 25 | :border="false" |
| ... | @@ -43,7 +45,10 @@ import { storeToRefs, mainStore } from "@/utils/generatePackage"; | ... | @@ -43,7 +45,10 @@ import { storeToRefs, mainStore } from "@/utils/generatePackage"; |
| 43 | const props = defineProps({ | 45 | const props = defineProps({ |
| 44 | item: Object, | 46 | item: Object, |
| 45 | }); | 47 | }); |
| 46 | - | 48 | +// 隐藏显示 |
| 49 | +const HideShow = computed(() => { | ||
| 50 | + return !props.item.component_props.disabled | ||
| 51 | +}) | ||
| 47 | const show = ref(false); | 52 | const show = ref(false); |
| 48 | let content = ""; | 53 | let content = ""; |
| 49 | 54 | ||
| ... | @@ -63,8 +68,9 @@ watch( | ... | @@ -63,8 +68,9 @@ watch( |
| 63 | } | 68 | } |
| 64 | } | 69 | } |
| 65 | ); | 70 | ); |
| 66 | - | 71 | +const readonly = props.item.component_props.readonly; |
| 67 | const openKeyboard = (e) => { | 72 | const openKeyboard = (e) => { |
| 73 | + if (readonly) return false; // 如果为只读,不能设置 | ||
| 68 | // // 键盘上移动 | 74 | // // 键盘上移动 |
| 69 | // const target_to_view_height = window.innerHeight - e.target.getBoundingClientRect().y; // 元素到适口高度 | 75 | // const target_to_view_height = window.innerHeight - e.target.getBoundingClientRect().y; // 元素到适口高度 |
| 70 | // const target_top = document.body.scrollHeight - $(e.target).offset().top; // 元素到正文高度 | 76 | // const target_top = document.body.scrollHeight - $(e.target).offset().top; // 元素到正文高度 |
| ... | @@ -106,19 +112,21 @@ const blurKeyboard = () => { | ... | @@ -106,19 +112,21 @@ const blurKeyboard = () => { |
| 106 | 112 | ||
| 107 | // 校验函数返回 true 表示校验通过,false 表示不通过 | 113 | // 校验函数返回 true 表示校验通过,false 表示不通过 |
| 108 | // 身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X | 114 | // 身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X |
| 115 | +const required = props.item.component_props.required; | ||
| 109 | const validator = (val) => { | 116 | const validator = (val) => { |
| 110 | - if (!props.item.component_props.required) { | 117 | + if (required && !val) { |
| 111 | - // 非必填 | 118 | + return false; |
| 112 | - return true; | 119 | + } else if (val && !/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(val)) { |
| 120 | + return false; | ||
| 113 | } else { | 121 | } else { |
| 114 | - return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(val); | 122 | + return true; |
| 115 | } | 123 | } |
| 116 | }; | 124 | }; |
| 117 | // 错误提示文案 | 125 | // 错误提示文案 |
| 118 | const validatorMessage = (val, rule) => { | 126 | const validatorMessage = (val, rule) => { |
| 119 | - if (!val) { | 127 | + if (required && !val) { |
| 120 | return "身份证号码不能为空"; | 128 | return "身份证号码不能为空"; |
| 121 | - } else if (!/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(val)) { | 129 | + } else if (val && !/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(val)) { |
| 122 | return "请输入正确身份证号码"; | 130 | return "请输入正确身份证号码"; |
| 123 | } | 131 | } |
| 124 | }; | 132 | }; | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-31 16:16:49 | 2 | * @Date: 2022-08-31 16:16:49 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-11-21 14:54:30 | 4 | + * @LastEditTime: 2022-12-30 10:31:02 |
| 5 | * @FilePath: /data-table/src/components/ImageUploaderField/index.vue | 5 | * @FilePath: /data-table/src/components/ImageUploaderField/index.vue |
| 6 | * @Description: 图片上传控件 | 6 | * @Description: 图片上传控件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="image-uploader-field"> | 9 | + <div v-if="HideShow" class="image-uploader-field"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label | 11 | {{ item.component_props.label |
| 12 | }}<span v-if="item.component_props.required"> *</span> | 12 | }}<span v-if="item.component_props.required"> *</span> |
| 13 | </div> | 13 | </div> |
| 14 | + <div | ||
| 15 | + v-if="item.component_props.note" | ||
| 16 | + style="font-size: 0.9rem; margin-left: 1rem; color: gray; padding-bottom: 0.5rem; padding-top: 0.25rem;" | ||
| 17 | + > | ||
| 18 | + {{ item.component_props.note }} | ||
| 19 | + </div> | ||
| 14 | <div style="padding: 1rem"> | 20 | <div style="padding: 1rem"> |
| 15 | <van-uploader | 21 | <van-uploader |
| 16 | :name="item.name" | 22 | :name="item.name" |
| ... | @@ -19,7 +25,7 @@ | ... | @@ -19,7 +25,7 @@ |
| 19 | :after-read="afterRead" | 25 | :after-read="afterRead" |
| 20 | :before-delete="beforeDelete" | 26 | :before-delete="beforeDelete" |
| 21 | v-model="fileList" | 27 | v-model="fileList" |
| 22 | - :multiple="item.component_props.multiple" | 28 | + :multiple="item.component_props.max_size > 1" |
| 23 | /> | 29 | /> |
| 24 | </div> | 30 | </div> |
| 25 | <div class="type-text">上传类型: {{ type_text }}</div> | 31 | <div class="type-text">上传类型: {{ type_text }}</div> |
| ... | @@ -60,6 +66,10 @@ const $route = useRoute(); | ... | @@ -60,6 +66,10 @@ const $route = useRoute(); |
| 60 | const props = defineProps({ | 66 | const props = defineProps({ |
| 61 | item: Object, | 67 | item: Object, |
| 62 | }); | 68 | }); |
| 69 | +// 隐藏显示 | ||
| 70 | +const HideShow = computed(() => { | ||
| 71 | + return !props.item.component_props.disabled | ||
| 72 | +}) | ||
| 63 | const emit = defineEmits(["active"]); | 73 | const emit = defineEmits(["active"]); |
| 64 | const show_empty = ref(false); | 74 | const show_empty = ref(false); |
| 65 | 75 | ||
| ... | @@ -111,13 +121,11 @@ const beforeRead = (file) => { | ... | @@ -111,13 +121,11 @@ const beforeRead = (file) => { |
| 111 | flag = false; | 121 | flag = false; |
| 112 | showToast(`最大上传数量为${props.item.component_props.max_count}张`); | 122 | showToast(`最大上传数量为${props.item.component_props.max_count}张`); |
| 113 | } | 123 | } |
| 114 | - if (file.size > props.item.component_props.max_size) { | 124 | + if ((file.size / 1024 / 1024).toFixed(2) > props.item.component_props.max_size) { |
| 115 | // 体积限制 | 125 | // 体积限制 |
| 116 | flag = false; | 126 | flag = false; |
| 117 | showToast( | 127 | showToast( |
| 118 | - `最大文件体积为${(props.item.component_props.max_size / 1024 / 1024).toFixed( | 128 | + `最大文件体积为${props.item.component_props.max_size}MB` |
| 119 | - 2 | ||
| 120 | - )}MB` | ||
| 121 | ); | 129 | ); |
| 122 | } | 130 | } |
| 123 | } | 131 | } |
| ... | @@ -259,10 +267,20 @@ var muliUpload = async (files) => { | ... | @@ -259,10 +267,20 @@ var muliUpload = async (files) => { |
| 259 | } | 267 | } |
| 260 | }; | 268 | }; |
| 261 | 269 | ||
| 270 | + | ||
| 271 | + | ||
| 272 | +const getType = (file, name) => { | ||
| 273 | + var index1 = name.lastIndexOf("."); | ||
| 274 | + var index2 = file.length; | ||
| 275 | + var type = file.substring(index1, index2).toUpperCase(); | ||
| 276 | + return type; | ||
| 277 | +} | ||
| 278 | + | ||
| 262 | // 生成数据库真实图片地址 | 279 | // 生成数据库真实图片地址 |
| 263 | const uploadQiniu = async (file, token, name, md5) => { | 280 | const uploadQiniu = async (file, token, name, md5) => { |
| 281 | + let suffix = /\.[^\.]+$/.exec(name); // 获取后缀 | ||
| 264 | // let affix = uuidv4(); | 282 | // let affix = uuidv4(); |
| 265 | - let fileName = `uploadForm/${formCode}/${md5}.${name.split(".")[1]}`; | 283 | + let fileName = `uploadForm/${formCode}/${md5}${suffix}`; |
| 266 | let formData = new FormData(); | 284 | let formData = new FormData(); |
| 267 | formData.append("file", file); // 通过append向form对象添加数据 | 285 | formData.append("file", file); // 通过append向form对象添加数据 |
| 268 | formData.append("token", token); | 286 | formData.append("token", token); | ... | ... |
| 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: 2022-11-24 14:33:47 | 4 | + * @LastEditTime: 2022-12-30 17:17:26 |
| 5 | - * @FilePath: /data-table/src/components/RuleField/index.vue | 5 | + * @FilePath: /data-table/src/components/MultiRuleField/index.vue |
| 6 | * @Description: 多选规则确认控件 | 6 | * @Description: 多选规则确认控件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="multi-rule-field-page"> | 9 | + <div v-if="HideShow" class="multi-rule-field-page"> |
| 10 | - <div class="label"> | 10 | + <div class="label"> {{ item.component_props.label }}<span v-if="item.component_props.required" class="required"> *</span> |
| 11 | - {{ item.component_props.label | 11 | + <span v-if="item.component_props.min_count" style="color: #999; font-size: 0.85rem;">(最少选{{ item.component_props.min_count }}项)</span> |
| 12 | - }}<span v-if="item.component_props.required"> *</span>(最少选{{ | ||
| 13 | - item.component_props.count | ||
| 14 | - }}项) | ||
| 15 | </div> | 12 | </div> |
| 16 | <van-field :name="item.key" :rules="rules" :border="false" style="padding-bottom: 0"> | 13 | <van-field :name="item.key" :rules="rules" :border="false" style="padding-bottom: 0"> |
| 17 | <template #input> | 14 | <template #input> |
| 18 | <van-checkbox-group v-model="item.value" style="width: 100%"> | 15 | <van-checkbox-group v-model="item.value" style="width: 100%"> |
| 19 | - <template v-for="(rule, idx) in item.component_props.rules" :key="idx"> | 16 | + <template v-for="(rule, idx) in item.component_props.options" :key="idx"> |
| 20 | <div class="multi-rule-field-box"> | 17 | <div class="multi-rule-field-box"> |
| 21 | <van-checkbox | 18 | <van-checkbox |
| 22 | - :name="idx" | 19 | + :name="rule.value" |
| 23 | shape="square" | 20 | shape="square" |
| 24 | :checked-color="themeVars.radioColor" | 21 | :checked-color="themeVars.radioColor" |
| 25 | - >{{ rule.rule_desc }}</van-checkbox | 22 | + >{{ rule.title }}</van-checkbox |
| 26 | > | 23 | > |
| 27 | - <div class="rule-box" @click="showRule(rule)"> | 24 | + <div class="van-multi-ellipsis--l3 rule-desc-text">{{ rule.desc_text }}</div> |
| 28 | - {{ rule.rule_link }} >> | 25 | + <div v-if="rule.desc_type === 'text'" class="rule-box" @click="showRule(rule)"> |
| 26 | + {{ rule.desc_btn_name }} >> | ||
| 27 | + </div> | ||
| 28 | + <div v-if="rule.desc_type === 'url'" class="rule-box" @click="showUrl(rule)"> | ||
| 29 | + {{ rule.desc_btn_name }} <van-icon name="link-o" /> | ||
| 29 | </div> | 30 | </div> |
| 30 | </div> | 31 | </div> |
| 31 | </template> | 32 | </template> |
| ... | @@ -56,7 +57,10 @@ import $ from "jquery"; | ... | @@ -56,7 +57,10 @@ import $ from "jquery"; |
| 56 | const props = defineProps({ | 57 | const props = defineProps({ |
| 57 | item: Object, | 58 | item: Object, |
| 58 | }); | 59 | }); |
| 59 | - | 60 | +// 隐藏显示 |
| 61 | +const HideShow = computed(() => { | ||
| 62 | + return !props.item.component_props.disabled | ||
| 63 | +}) | ||
| 60 | // TAG: 自定义主题颜色 | 64 | // TAG: 自定义主题颜色 |
| 61 | const themeVars = { | 65 | const themeVars = { |
| 62 | radioColor: styleColor.baseColor, | 66 | radioColor: styleColor.baseColor, |
| ... | @@ -68,28 +72,39 @@ const show = ref(false); | ... | @@ -68,28 +72,39 @@ const show = ref(false); |
| 68 | const checked = ref([]); | 72 | const checked = ref([]); |
| 69 | const showRule = (rule) => { | 73 | const showRule = (rule) => { |
| 70 | show.value = true; | 74 | show.value = true; |
| 71 | - rule_content.value = rule.rule_content; | 75 | + rule.desc_text = rule.desc_text.replace(/\\n/g, "<br>") |
| 76 | + rule_content.value = rule.desc_text; | ||
| 72 | }; | 77 | }; |
| 73 | const closeRule = () => { | 78 | const closeRule = () => { |
| 74 | show.value = false; | 79 | show.value = false; |
| 75 | rule_content.value = ""; | 80 | rule_content.value = ""; |
| 76 | }; | 81 | }; |
| 82 | +const showUrl = (rule) => { | ||
| 83 | + location.href = rule.desc_url | ||
| 84 | +} | ||
| 77 | const rule_content = ref(""); | 85 | const rule_content = ref(""); |
| 78 | - | 86 | +const required = props.item.component_props.required; |
| 87 | +const min_count = props.item.component_props.min_count; | ||
| 88 | +const max_count = props.item.component_props.max_count; | ||
| 79 | const validator = (val) => { | 89 | const validator = (val) => { |
| 80 | - if (!props.item.component_props.required) { | 90 | + if (required && !val.length) { |
| 81 | - // 非必填 | 91 | + return false; |
| 82 | - return true; | 92 | + } else if (min_count && props.item.value.length < min_count) { |
| 93 | + return false; | ||
| 94 | + } else if (max_count && props.item.value.length > max_count) { | ||
| 95 | + return false; | ||
| 83 | } else { | 96 | } else { |
| 84 | - return props.item.value.length >= props.item.component_props.count ? true : false; | 97 | + return true; |
| 85 | } | 98 | } |
| 86 | }; | 99 | }; |
| 87 | // 错误提示文案 | 100 | // 错误提示文案 |
| 88 | const validatorMessage = (val, rule) => { | 101 | const validatorMessage = (val, rule) => { |
| 89 | - if (!val) { | 102 | + if (required && !val.length) { |
| 90 | return "选择项不能为空"; | 103 | return "选择项不能为空"; |
| 91 | - } else if (props.item.value.length < props.item.component_props.count) { | 104 | + } else if (min_count && props.item.value.length < min_count) { |
| 92 | - return `最少选择${props.item.component_props.count}项`; | 105 | + return `最少选择${min_count}项`; |
| 106 | + } else if (max_count && props.item.value.length > max_count) { | ||
| 107 | + return `最多选择${max_count}项`; | ||
| 93 | } | 108 | } |
| 94 | }; | 109 | }; |
| 95 | const rules = [{ validator, message: validatorMessage }]; | 110 | const rules = [{ validator, message: validatorMessage }]; |
| ... | @@ -101,10 +116,15 @@ const rules = [{ validator, message: validatorMessage }]; | ... | @@ -101,10 +116,15 @@ const rules = [{ validator, message: validatorMessage }]; |
| 101 | padding: 1rem 1rem 0 1rem; | 116 | padding: 1rem 1rem 0 1rem; |
| 102 | font-size: 0.9rem; | 117 | font-size: 0.9rem; |
| 103 | font-weight: bold; | 118 | font-weight: bold; |
| 104 | - span { | 119 | + span.required { |
| 105 | color: red; | 120 | color: red; |
| 106 | } | 121 | } |
| 107 | } | 122 | } |
| 123 | + .rule-desc-text { | ||
| 124 | + margin: 0.35rem 0.5rem 0.5rem 1.75rem; | ||
| 125 | + font-size: 0.8rem; | ||
| 126 | + color: #808080; | ||
| 127 | + } | ||
| 108 | .rule-box { | 128 | .rule-box { |
| 109 | font-size: 0.85rem; | 129 | font-size: 0.85rem; |
| 110 | margin-left: 1.8rem; | 130 | margin-left: 1.8rem; | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-09-14 14:44:30 | 2 | * @Date: 2022-09-14 14:44:30 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-11-18 13:50:50 | 4 | + * @LastEditTime: 2022-12-29 11:29:46 |
| 5 | * @FilePath: /data-table/src/components/NumberField/index.vue | 5 | * @FilePath: /data-table/src/components/NumberField/index.vue |
| 6 | * @Description: 数字输入框 | 6 | * @Description: 数字输入框 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="number-page"> | 9 | + <div v-if="HideShow" class="number-page"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label }} | 11 | {{ item.component_props.label }} |
| 12 | <span v-if="item.component_props.required"> *</span> | 12 | <span v-if="item.component_props.required"> *</span> |
| ... | @@ -16,8 +16,9 @@ | ... | @@ -16,8 +16,9 @@ |
| 16 | :id="item.name" | 16 | :id="item.name" |
| 17 | :name="item.name" | 17 | :name="item.name" |
| 18 | :placeholder="item.component_props.placeholder" | 18 | :placeholder="item.component_props.placeholder" |
| 19 | - :rules="item.rules" | 19 | + :rules="rules" |
| 20 | :required="item.component_props.required" | 20 | :required="item.component_props.required" |
| 21 | + disabled="item.component_props.readonly" | ||
| 21 | readonly | 22 | readonly |
| 22 | @touchstart.stop="showKeyboard($event)" | 23 | @touchstart.stop="showKeyboard($event)" |
| 23 | :border="false" | 24 | :border="false" |
| ... | @@ -52,6 +53,10 @@ import { storeToRefs, mainStore } from "@/utils/generatePackage"; | ... | @@ -52,6 +53,10 @@ import { storeToRefs, mainStore } from "@/utils/generatePackage"; |
| 52 | const props = defineProps({ | 53 | const props = defineProps({ |
| 53 | item: Object, | 54 | item: Object, |
| 54 | }); | 55 | }); |
| 56 | +// 隐藏显示 | ||
| 57 | +const HideShow = computed(() => { | ||
| 58 | + return !props.item.component_props.disabled | ||
| 59 | +}) | ||
| 55 | let content = ""; | 60 | let content = ""; |
| 56 | 61 | ||
| 57 | const store = mainStore(); | 62 | const store = mainStore(); |
| ... | @@ -65,19 +70,20 @@ watch( | ... | @@ -65,19 +70,20 @@ watch( |
| 65 | if (v !== props.item.name) { | 70 | if (v !== props.item.name) { |
| 66 | // 还原border颜色 | 71 | // 还原border颜色 |
| 67 | $(`#${props.item.name}`).parent().css("border-color", "#eaeaea"); | 72 | $(`#${props.item.name}`).parent().css("border-color", "#eaeaea"); |
| 68 | - if (props.item.component_props.type === "decimal") { | 73 | + if (props.item.component_props.max_fraction_count === 0) { |
| 69 | - // 显示小数键盘 | ||
| 70 | - showDecimal.value = false; | ||
| 71 | - } else { | ||
| 72 | // 显示整数键盘 | 74 | // 显示整数键盘 |
| 73 | showInteger.value = false; | 75 | showInteger.value = false; |
| 76 | + } else { | ||
| 77 | + // 显示小数键盘 | ||
| 78 | + showDecimal.value = false; | ||
| 74 | } | 79 | } |
| 75 | document.getElementById("app").style.paddingBottom = "0"; | 80 | document.getElementById("app").style.paddingBottom = "0"; |
| 76 | } | 81 | } |
| 77 | } | 82 | } |
| 78 | ); | 83 | ); |
| 79 | - | 84 | +const readonly = props.item.component_props.readonly; |
| 80 | const showKeyboard = (e) => { | 85 | const showKeyboard = (e) => { |
| 86 | + if (readonly) return false; // 如果为只读,不能设置 | ||
| 81 | // 键盘上移动 | 87 | // 键盘上移动 |
| 82 | const target_to_view_height = | 88 | const target_to_view_height = |
| 83 | window.innerHeight - e.target.getBoundingClientRect().bottom; // 元素到适口高度 | 89 | window.innerHeight - e.target.getBoundingClientRect().bottom; // 元素到适口高度 |
| ... | @@ -99,24 +105,24 @@ const showKeyboard = (e) => { | ... | @@ -99,24 +105,24 @@ const showKeyboard = (e) => { |
| 99 | // TAG: 自定义主题颜色 | 105 | // TAG: 自定义主题颜色 |
| 100 | content.css("border-color", "#c2915f"); | 106 | content.css("border-color", "#c2915f"); |
| 101 | setTimeout(() => { | 107 | setTimeout(() => { |
| 102 | - if (props.item.component_props.type === "decimal") { | 108 | + if (props.item.component_props.max_fraction_count === 0) { |
| 103 | - // 显示小数键盘 | ||
| 104 | - showDecimal.value = true; | ||
| 105 | - } else { | ||
| 106 | // 显示整数键盘 | 109 | // 显示整数键盘 |
| 107 | showInteger.value = true; | 110 | showInteger.value = true; |
| 111 | + } else { | ||
| 112 | + // 显示小数键盘 | ||
| 113 | + showDecimal.value = true; | ||
| 108 | } | 114 | } |
| 109 | }, 300); | 115 | }, 300); |
| 110 | // 记录点击field名 | 116 | // 记录点击field名 |
| 111 | store.changeFieldName(props.item.name); | 117 | store.changeFieldName(props.item.name); |
| 112 | }; | 118 | }; |
| 113 | const blurKeyboard = () => { | 119 | const blurKeyboard = () => { |
| 114 | - if (props.item.component_props.type === "decimal") { | 120 | + if (props.item.component_props.max_fraction_count === 0) { |
| 115 | - // 显示小数键盘 | ||
| 116 | - showDecimal.value = false; | ||
| 117 | - } else { | ||
| 118 | // 显示整数键盘 | 121 | // 显示整数键盘 |
| 119 | showInteger.value = false; | 122 | showInteger.value = false; |
| 123 | + } else { | ||
| 124 | + // 显示小数键盘 | ||
| 125 | + showDecimal.value = false; | ||
| 120 | } | 126 | } |
| 121 | document.getElementById("app").style.paddingBottom = "0"; | 127 | document.getElementById("app").style.paddingBottom = "0"; |
| 122 | // 还原border颜色 | 128 | // 还原border颜色 |
| ... | @@ -126,25 +132,38 @@ const blurKeyboard = () => { | ... | @@ -126,25 +132,38 @@ const blurKeyboard = () => { |
| 126 | const showDecimal = ref(false); | 132 | const showDecimal = ref(false); |
| 127 | const showInteger = ref(false); | 133 | const showInteger = ref(false); |
| 128 | 134 | ||
| 129 | -// // 校验函数返回 true 表示校验通过,false 表示不通过 | 135 | +// 校验函数返回 true 表示校验通过,false 表示不通过 |
| 130 | -// // 身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X | 136 | +const required = props.item.component_props.required; |
| 131 | -// const validator = (val) => { | 137 | +const min = props.item.component_props.min; |
| 132 | -// if (!props.item.component_props.required) { | 138 | +const max = props.item.component_props.max; |
| 133 | -// // 非必填 | 139 | +const max_count = props.item.component_props.max_fraction_count; // 保留小数个数 null=不限,0=没有小数,大于0=最多只能输入的小数个数 |
| 134 | -// return true; | 140 | +const reg = new RegExp("^([0-9]+)(\\.(\\d){" + max_count +"," + max_count +"})$", "g"); |
| 135 | -// } else { | 141 | +const validator = (val) => { |
| 136 | -// return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(val); | 142 | + if (required && !val) { // 必填 |
| 137 | -// } | 143 | + return false; |
| 138 | -// }; | 144 | + } else if (val && min && (val < min)) { // 小于最小值 |
| 139 | -// // 错误提示文案 | 145 | + return false; |
| 140 | -// const validatorMessage = (val, rule) => { | 146 | + } else if (val && max && (val > max)) { // 大于最大值 |
| 141 | -// if (!val) { | 147 | + return false; |
| 142 | -// return "身份证号码不能为空"; | 148 | + } else if (val && max_count && !reg.test(val)) { // 不符合保留小数个数 |
| 143 | -// } else if (!/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(val)) { | 149 | + return false; |
| 144 | -// return "请输入正确身份证号码"; | 150 | + } else { |
| 145 | -// } | 151 | + return true; |
| 146 | -// }; | 152 | + } |
| 147 | -// const rules = [{ validator, message: validatorMessage }]; | 153 | +}; |
| 154 | +// 错误提示文案 | ||
| 155 | +const validatorMessage = (val, rule) => { | ||
| 156 | + if (required && !val) { | ||
| 157 | + return "必填项不能为空"; | ||
| 158 | + } else if (val && min && (val < min)) { // 小于最小值 | ||
| 159 | + return "最小值为" + min; | ||
| 160 | + } else if (val && max && (val > max)) { // 大于最大值 | ||
| 161 | + return "最大值为" + max; | ||
| 162 | + } else if (val && max_count && !reg.test(val)) { // 不符合保留小数个数 | ||
| 163 | + return "保留小数点后" + max_count + "位"; | ||
| 164 | + } | ||
| 165 | +}; | ||
| 166 | +const rules = [{ validator, message: validatorMessage }]; | ||
| 148 | 167 | ||
| 149 | const onInput = (value) => {}; | 168 | const onInput = (value) => {}; |
| 150 | const onDelete = () => {}; | 169 | const onDelete = () => {}; | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-09-02 10:46:03 | 2 | * @Date: 2022-09-02 10:46:03 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-12-09 13:34:21 | 4 | + * @LastEditTime: 2022-12-29 11:39:40 |
| 5 | * @FilePath: /data-table/src/components/PhoneField/index.vue | 5 | * @FilePath: /data-table/src/components/PhoneField/index.vue |
| 6 | * @Description: 手机输入框 | 6 | * @Description: 手机输入框 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="phone-field-page"> | 9 | + <div v-if="HideShow" class="phone-field-page"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label }} | 11 | {{ item.component_props.label }} |
| 12 | <span v-if="item.component_props.required"> *</span> | 12 | <span v-if="item.component_props.required"> *</span> |
| ... | @@ -20,6 +20,7 @@ | ... | @@ -20,6 +20,7 @@ |
| 20 | :placeholder="item.component_props.placeholder ? item.component_props.placeholder : '请输入手机号码'" | 20 | :placeholder="item.component_props.placeholder ? item.component_props.placeholder : '请输入手机号码'" |
| 21 | :rules="rules" | 21 | :rules="rules" |
| 22 | :required="item.component_props.required" | 22 | :required="item.component_props.required" |
| 23 | + disabled="item.component_props.readonly" | ||
| 23 | :readonly="readonly" | 24 | :readonly="readonly" |
| 24 | @touchstart.stop="openKeyboard($event)" | 25 | @touchstart.stop="openKeyboard($event)" |
| 25 | :border="false" | 26 | :border="false" |
| ... | @@ -57,7 +58,10 @@ import { storeToRefs, mainStore } from "@/utils/generatePackage"; | ... | @@ -57,7 +58,10 @@ import { storeToRefs, mainStore } from "@/utils/generatePackage"; |
| 57 | const props = defineProps({ | 58 | const props = defineProps({ |
| 58 | item: Object, | 59 | item: Object, |
| 59 | }); | 60 | }); |
| 60 | - | 61 | +// 隐藏显示 |
| 62 | +const HideShow = computed(() => { | ||
| 63 | + return !props.item.component_props.disabled | ||
| 64 | +}) | ||
| 61 | // web端判断 | 65 | // web端判断 |
| 62 | const readonly = computed(() => wxInfo().isMobile); | 66 | const readonly = computed(() => wxInfo().isMobile); |
| 63 | // 打开短信验证模式 | 67 | // 打开短信验证模式 |
| ... | @@ -65,18 +69,19 @@ const is_sms = ref(false); | ... | @@ -65,18 +69,19 @@ const is_sms = ref(false); |
| 65 | 69 | ||
| 66 | // 校验函数返回 true 表示校验通过,false 表示不通过 | 70 | // 校验函数返回 true 表示校验通过,false 表示不通过 |
| 67 | const validator = (val) => { | 71 | const validator = (val) => { |
| 68 | - if (!props.item.component_props.required) { | 72 | + if (props.item.component_props.required && !val) { |
| 69 | - // 非必填 | 73 | + return false; |
| 70 | - return true; | 74 | + } else if (val && !/1\d{10}/.test(val)) { |
| 75 | + return false; | ||
| 71 | } else { | 76 | } else { |
| 72 | - return /1\d{10}/.test(val); | 77 | + return true; |
| 73 | } | 78 | } |
| 74 | }; | 79 | }; |
| 75 | // 错误提示文案 | 80 | // 错误提示文案 |
| 76 | const validatorMessage = (val, rule) => { | 81 | const validatorMessage = (val, rule) => { |
| 77 | - if (!val) { | 82 | + if (props.item.component_props.required && !val) { |
| 78 | return "手机号码不能为空"; | 83 | return "手机号码不能为空"; |
| 79 | - } else if (!/1\d{10}/.test(val)) { | 84 | + } else if (val && !/1\d{10}/.test(val)) { |
| 80 | return "请输入正确手机号码"; | 85 | return "请输入正确手机号码"; |
| 81 | } | 86 | } |
| 82 | }; | 87 | }; |
| ... | @@ -103,6 +108,7 @@ watch( | ... | @@ -103,6 +108,7 @@ watch( |
| 103 | ); | 108 | ); |
| 104 | 109 | ||
| 105 | const openKeyboard = (e) => { | 110 | const openKeyboard = (e) => { |
| 111 | + if (props.item.component_props.readonly) return false; // 如果为只读,不能设置 | ||
| 106 | // 键盘上移动 | 112 | // 键盘上移动 |
| 107 | const target_to_view_height = | 113 | const target_to_view_height = |
| 108 | window.innerHeight - e.target.getBoundingClientRect().bottom; // 元素到适口高度 | 114 | window.innerHeight - e.target.getBoundingClientRect().bottom; // 元素到适口高度 | ... | ... |
| 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: 2022-08-30 14:23:32 | 4 | + * @LastEditTime: 2022-12-21 11:25:55 |
| 5 | * @FilePath: /data-table/src/components/PickerField/index.vue | 5 | * @FilePath: /data-table/src/components/PickerField/index.vue |
| 6 | * @Description: 单列选择器组件 | 6 | * @Description: 单列选择器组件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="picker-field-page"> | 9 | + <div v-if="HideShow" class="picker-field-page"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label | 11 | {{ item.component_props.label |
| 12 | }}<span v-if="item.component_props.required"> *</span> | 12 | }}<span v-if="item.component_props.required"> *</span> |
| ... | @@ -20,6 +20,7 @@ | ... | @@ -20,6 +20,7 @@ |
| 20 | :placeholder="item.component_props.placeholder" | 20 | :placeholder="item.component_props.placeholder" |
| 21 | :rules="item.rules" | 21 | :rules="item.rules" |
| 22 | @click="showPicker = true" | 22 | @click="showPicker = true" |
| 23 | + :border="false" | ||
| 23 | /> | 24 | /> |
| 24 | <van-popup v-model:show="showPicker" position="bottom"> | 25 | <van-popup v-model:show="showPicker" position="bottom"> |
| 25 | <van-picker | 26 | <van-picker |
| ... | @@ -37,12 +38,12 @@ const props = defineProps({ | ... | @@ -37,12 +38,12 @@ const props = defineProps({ |
| 37 | }); | 38 | }); |
| 38 | 39 | ||
| 39 | onMounted(() => { | 40 | onMounted(() => { |
| 40 | - props.item.component_props.options = props.item.component_props.options.map((opt) => { | 41 | + // props.item.component_props.options = props.item.component_props.options.map((opt) => { |
| 41 | - return { | 42 | + // return { |
| 42 | - text: opt, | 43 | + // text: opt, |
| 43 | - value: opt, | 44 | + // value: opt, |
| 44 | - }; | 45 | + // }; |
| 45 | - }); | 46 | + // }); |
| 46 | }); | 47 | }); |
| 47 | 48 | ||
| 48 | const selectedValues = ref(""); | 49 | const selectedValues = ref(""); |
| ... | @@ -52,12 +53,17 @@ const onConfirm = ({ selectedOptions }) => { | ... | @@ -52,12 +53,17 @@ const onConfirm = ({ selectedOptions }) => { |
| 52 | props.item.value = selectedOptions[0]?.value; | 53 | props.item.value = selectedOptions[0]?.value; |
| 53 | showPicker.value = false; | 54 | showPicker.value = false; |
| 54 | }; | 55 | }; |
| 56 | +// 隐藏显示 | ||
| 57 | +const HideShow = computed(() => { | ||
| 58 | + return !props.item.component_props.disabled | ||
| 59 | +}) | ||
| 55 | </script> | 60 | </script> |
| 56 | 61 | ||
| 57 | <style lang="less" scoped> | 62 | <style lang="less" scoped> |
| 58 | .picker-field-page { | 63 | .picker-field-page { |
| 64 | + margin: 1rem; | ||
| 59 | .label { | 65 | .label { |
| 60 | - padding: 1rem 1rem 0 1rem; | 66 | + // padding: 1rem 1rem 0 0; |
| 61 | font-size: 0.9rem; | 67 | font-size: 0.9rem; |
| 62 | font-weight: bold; | 68 | font-weight: bold; |
| 63 | 69 | ||
| ... | @@ -66,4 +72,11 @@ const onConfirm = ({ selectedOptions }) => { | ... | @@ -66,4 +72,11 @@ const onConfirm = ({ selectedOptions }) => { |
| 66 | } | 72 | } |
| 67 | } | 73 | } |
| 68 | } | 74 | } |
| 75 | + | ||
| 76 | +:deep(.van-cell--clickable) { | ||
| 77 | + border: 1px solid #eaeaea; | ||
| 78 | + border-radius: 0.25rem; | ||
| 79 | + padding: 0.25rem 0.5rem; | ||
| 80 | + margin-top: 0.5rem; | ||
| 81 | +} | ||
| 69 | </style> | 82 | </style> | ... | ... |
| 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: 2022-12-09 15:54:52 | 4 | + * @LastEditTime: 2022-12-29 11:14:20 |
| 5 | * @FilePath: /data-table/src/components/RadioField/index.vue | 5 | * @FilePath: /data-table/src/components/RadioField/index.vue |
| 6 | * @Description: 单项选择控件 | 6 | * @Description: 单项选择控件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="radio-field-page"> | 9 | + <div v-if="HideShow" class="radio-field-page"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label | 11 | {{ item.component_props.label |
| 12 | }}<span v-if="item.component_props.required"> *</span> | 12 | }}<span v-if="item.component_props.required"> *</span> |
| 13 | </div> | 13 | </div> |
| 14 | - <div | 14 | + <div v-if="item.component_props.note" class="note"> |
| 15 | - v-if="item.component_props.note" | ||
| 16 | - style="font-size: 0.9rem; margin-left: 1rem; color: gray; margin-top: 0.25rem;" | ||
| 17 | - > | ||
| 18 | {{ item.component_props.note }} | 15 | {{ item.component_props.note }} |
| 19 | </div> | 16 | </div> |
| 20 | <van-field :name="item.key" :rules="item.rules"> | 17 | <van-field :name="item.key" :rules="item.rules"> |
| ... | @@ -26,12 +23,12 @@ | ... | @@ -26,12 +23,12 @@ |
| 26 | > | 23 | > |
| 27 | <van-radio | 24 | <van-radio |
| 28 | v-for="x in item.component_props.options" | 25 | v-for="x in item.component_props.options" |
| 29 | - :key="index" | 26 | + :key="x.value" |
| 30 | - :name="x" | 27 | + :name="x.value" |
| 31 | icon-size="1rem" | 28 | icon-size="1rem" |
| 32 | :checked-color="themeVars.radioColor" | 29 | :checked-color="themeVars.radioColor" |
| 33 | style="margin-bottom: 0.25rem" | 30 | style="margin-bottom: 0.25rem" |
| 34 | - >{{ x }}</van-radio | 31 | + >{{ x.title }}</van-radio |
| 35 | > | 32 | > |
| 36 | </van-radio-group> | 33 | </van-radio-group> |
| 37 | </template> | 34 | </template> |
| ... | @@ -50,6 +47,10 @@ const props = defineProps({ | ... | @@ -50,6 +47,10 @@ const props = defineProps({ |
| 50 | const themeVars = { | 47 | const themeVars = { |
| 51 | radioColor: styleColor.baseColor, | 48 | radioColor: styleColor.baseColor, |
| 52 | }; | 49 | }; |
| 50 | +// 隐藏显示 | ||
| 51 | +const HideShow = computed(() => { | ||
| 52 | + return !props.item.component_props.disabled | ||
| 53 | +}) | ||
| 53 | </script> | 54 | </script> |
| 54 | 55 | ||
| 55 | <style lang="less" scoped> | 56 | <style lang="less" scoped> |
| ... | @@ -62,6 +63,12 @@ const themeVars = { | ... | @@ -62,6 +63,12 @@ const themeVars = { |
| 62 | color: red; | 63 | color: red; |
| 63 | } | 64 | } |
| 64 | } | 65 | } |
| 66 | + .note { | ||
| 67 | + font-size: 0.9rem; | ||
| 68 | + margin-left: 1rem; | ||
| 69 | + color: gray; | ||
| 70 | + padding-bottom: 0.5rem | ||
| 71 | + } | ||
| 65 | } | 72 | } |
| 66 | 73 | ||
| 67 | :deep(.van-radio) { | 74 | :deep(.van-radio) { | ... | ... |
| 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: 2022-11-21 15:16:10 | 4 | + * @LastEditTime: 2022-12-28 18:51:11 |
| 5 | * @FilePath: /data-table/src/components/RatePickerField/index.vue | 5 | * @FilePath: /data-table/src/components/RatePickerField/index.vue |
| 6 | * @Description: 评分选择控件 | 6 | * @Description: 评分选择控件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="rate-field"> | 9 | + <div v-if="HideShow" class="rate-field"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label | 11 | {{ item.component_props.label |
| 12 | }}<span v-if="item.component_props.required"> *</span> | 12 | }}<span v-if="item.component_props.required"> *</span> |
| 13 | </div> | 13 | </div> |
| 14 | <van-rate | 14 | <van-rate |
| 15 | v-model="rate_value" | 15 | v-model="rate_value" |
| 16 | - :count="item.component_props.count" | 16 | + :count="item.component_props.data_length" |
| 17 | + :readonly="item.component_props.readonly" | ||
| 17 | :color="styleColor.baseColor" | 18 | :color="styleColor.baseColor" |
| 18 | @change="onChange" | 19 | @change="onChange" |
| 19 | style="padding: 1rem" | 20 | style="padding: 1rem" |
| ... | @@ -35,9 +36,13 @@ import { styleColor } from "@/constant.js"; | ... | @@ -35,9 +36,13 @@ import { styleColor } from "@/constant.js"; |
| 35 | const props = defineProps({ | 36 | const props = defineProps({ |
| 36 | item: Object, | 37 | item: Object, |
| 37 | }); | 38 | }); |
| 39 | +// 隐藏显示 | ||
| 40 | +const HideShow = computed(() => { | ||
| 41 | + return !props.item.component_props.disabled | ||
| 42 | +}) | ||
| 38 | const emit = defineEmits(["active"]); | 43 | const emit = defineEmits(["active"]); |
| 39 | const show_empty = ref(false); | 44 | const show_empty = ref(false); |
| 40 | -const rate_value = ref(0); | 45 | +const rate_value = ref(props.item.component_props.default); |
| 41 | 46 | ||
| 42 | const onChange = (value) => { | 47 | const onChange = (value) => { |
| 43 | props.item.value = { key: props.item.key, value, type: "rate" }; | 48 | props.item.value = { key: props.item.key, value, type: "rate" }; | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-29 14:31:20 | 2 | * @Date: 2022-08-29 14:31:20 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-12-09 15:33:56 | 4 | + * @LastEditTime: 2022-12-29 11:13:58 |
| 5 | * @FilePath: /data-table/src/components/TextField/index.vue | 5 | * @FilePath: /data-table/src/components/TextField/index.vue |
| 6 | * @Description: 单行文本输入框 | 6 | * @Description: 单行文本输入框 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="text-field-page"> | 9 | + <div v-if="HideShow" class="text-field-page"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label | 11 | {{ item.component_props.label |
| 12 | }}<span v-if="item.component_props.required"> *</span> | 12 | }}<span v-if="item.component_props.required"> *</span> |
| ... | @@ -29,6 +29,10 @@ | ... | @@ -29,6 +29,10 @@ |
| 29 | const props = defineProps({ | 29 | const props = defineProps({ |
| 30 | item: Object, | 30 | item: Object, |
| 31 | }); | 31 | }); |
| 32 | +// 隐藏显示 | ||
| 33 | +const HideShow = computed(() => { | ||
| 34 | + return !props.item.component_props.disabled | ||
| 35 | +}) | ||
| 32 | </script> | 36 | </script> |
| 33 | 37 | ||
| 34 | <style lang="less" scoped> | 38 | <style lang="less" scoped> | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-29 14:31:20 | 2 | * @Date: 2022-08-29 14:31:20 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-12-09 15:37:59 | 4 | + * @LastEditTime: 2022-12-29 11:25:54 |
| 5 | * @FilePath: /data-table/src/components/TextareaField/index.vue | 5 | * @FilePath: /data-table/src/components/TextareaField/index.vue |
| 6 | * @Description: 多行文本输入框 | 6 | * @Description: 多行文本输入框 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="textarea-field-page"> | 9 | + <div v-if="HideShow" class="textarea-field-page"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label | 11 | {{ item.component_props.label |
| 12 | }}<span v-if="item.component_props.required"> *</span> | 12 | }}<span v-if="item.component_props.required"> *</span> |
| ... | @@ -18,10 +18,11 @@ | ... | @@ -18,10 +18,11 @@ |
| 18 | :placeholder="item.component_props.placeholder ? item.component_props.placeholder : '请输入'" | 18 | :placeholder="item.component_props.placeholder ? item.component_props.placeholder : '请输入'" |
| 19 | :rules="item.rules" | 19 | :rules="item.rules" |
| 20 | :required="item.component_props.required" | 20 | :required="item.component_props.required" |
| 21 | + :readonly="item.component_props.readonly" | ||
| 21 | :rows="item.component_props.rows" | 22 | :rows="item.component_props.rows" |
| 22 | autosize | 23 | autosize |
| 23 | - :maxlength="item.component_props.maxlength" | 24 | + :maxlength="item.component_props.maxlength ? item.component_props.maxlength : null" |
| 24 | - show-word-limit | 25 | + :show-word-limit="item.component_props.maxlength" |
| 25 | /> | 26 | /> |
| 26 | </div> | 27 | </div> |
| 27 | </template> | 28 | </template> |
| ... | @@ -30,6 +31,10 @@ | ... | @@ -30,6 +31,10 @@ |
| 30 | const props = defineProps({ | 31 | const props = defineProps({ |
| 31 | item: Object, | 32 | item: Object, |
| 32 | }); | 33 | }); |
| 34 | +// 隐藏显示 | ||
| 35 | +const HideShow = computed(() => { | ||
| 36 | + return !props.item.component_props.disabled | ||
| 37 | +}) | ||
| 33 | </script> | 38 | </script> |
| 34 | 39 | ||
| 35 | <style lang="less" scoped> | 40 | <style lang="less" scoped> | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-08-31 11:45:30 | 2 | * @Date: 2022-08-31 11:45:30 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-11-21 15:21:56 | 4 | + * @LastEditTime: 2022-12-29 11:46:19 |
| 5 | * @FilePath: /data-table/src/components/TimePickerField/index.vue | 5 | * @FilePath: /data-table/src/components/TimePickerField/index.vue |
| 6 | * @Description: 时间选择组件 | 6 | * @Description: 时间选择组件 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="time-picker-field"> | 9 | + <div v-if="HideShow" class="time-picker-field"> |
| 10 | <div class="label"> | 10 | <div class="label"> |
| 11 | {{ item.component_props.label | 11 | {{ item.component_props.label |
| 12 | }}<span v-if="item.component_props.required"> *</span> | 12 | }}<span v-if="item.component_props.required"> *</span> |
| ... | @@ -17,15 +17,17 @@ | ... | @@ -17,15 +17,17 @@ |
| 17 | readonly | 17 | readonly |
| 18 | :name="item.key" | 18 | :name="item.key" |
| 19 | :required="item.component_props.required" | 19 | :required="item.component_props.required" |
| 20 | - :placeholder="item.component_props.placeholder" | 20 | + disabled="item.component_props.readonly" |
| 21 | - :rules="item.rules" | 21 | + :placeholder="item.component_props.placeholder ? item.component_props.placeholder : '请选择时间'" |
| 22 | - @click="showPicker = true" | 22 | + :rules="rules" |
| 23 | + @click="onTap" | ||
| 24 | + :border="false" | ||
| 23 | /> | 25 | /> |
| 24 | <van-popup v-model:show="showPicker" position="bottom"> | 26 | <van-popup v-model:show="showPicker" position="bottom"> |
| 25 | <van-time-picker | 27 | <van-time-picker |
| 26 | v-model="currentTime" | 28 | v-model="currentTime" |
| 27 | - :title="item.component_props.title" | 29 | + title="请选择时间" |
| 28 | - :columns-type="item.component_props.columns_type" | 30 | + :columns-type="columns_type" |
| 29 | @confirm="onConfirm" | 31 | @confirm="onConfirm" |
| 30 | @cancel="showPicker = false" | 32 | @cancel="showPicker = false" |
| 31 | /> | 33 | /> |
| ... | @@ -39,24 +41,70 @@ import dayjs from "dayjs"; | ... | @@ -39,24 +41,70 @@ import dayjs from "dayjs"; |
| 39 | const props = defineProps({ | 41 | const props = defineProps({ |
| 40 | item: Object, | 42 | item: Object, |
| 41 | }); | 43 | }); |
| 42 | - | 44 | +// 隐藏显示 |
| 45 | +const HideShow = computed(() => { | ||
| 46 | + return !props.item.component_props.disabled | ||
| 47 | +}) | ||
| 43 | const showPicker = ref(false); | 48 | const showPicker = ref(false); |
| 44 | const currentTime = ref([]); | 49 | const currentTime = ref([]); |
| 50 | +const readonly = props.item.component_props.readonly; | ||
| 51 | + | ||
| 52 | +const onTap = () => { | ||
| 53 | + if (readonly) return false; // 如果为只读,不能设置 | ||
| 54 | + showPicker.value = true | ||
| 55 | +} | ||
| 45 | 56 | ||
| 46 | const onConfirm = ({ selectedValues, selectedOptions }) => { | 57 | const onConfirm = ({ selectedValues, selectedOptions }) => { |
| 47 | - props.item.value = selectedValues[0] + ":" + selectedValues[1]; | 58 | + props.item.value = selectedValues.join(":"); |
| 48 | showPicker.value = false; | 59 | showPicker.value = false; |
| 49 | }; | 60 | }; |
| 50 | 61 | ||
| 62 | +const columns_type = ref([]); | ||
| 63 | +const date_format = props.item.component_props.data_dateformat; // HH:mm=时分,HH:mm:ss=时分秒 | ||
| 51 | onMounted(() => { | 64 | onMounted(() => { |
| 52 | currentTime.value = props.item.value.split(":"); | 65 | currentTime.value = props.item.value.split(":"); |
| 66 | + switch (date_format) { | ||
| 67 | + case "HH:mm": | ||
| 68 | + columns_type.value = ['hour', 'minute'] | ||
| 69 | + break; | ||
| 70 | + case "HH:mm:ss": | ||
| 71 | + columns_type.value = ['hour', 'minute', 'second'] | ||
| 72 | + break; | ||
| 73 | + } | ||
| 53 | }); | 74 | }); |
| 75 | + | ||
| 76 | +const required = props.item.component_props.required; | ||
| 77 | +const data_minvalue = props.item.component_props.data_minvalue; | ||
| 78 | +const data_maxvalue = props.item.component_props.data_maxvalue; | ||
| 79 | +const validator = (val) => { | ||
| 80 | + if (required && !val) { | ||
| 81 | + return false; | ||
| 82 | + } else if (val && data_minvalue && val < data_minvalue) { | ||
| 83 | + return false; | ||
| 84 | + } else if (val && data_maxvalue && val > data_maxvalue) { | ||
| 85 | + return false; | ||
| 86 | + } else { | ||
| 87 | + return true; | ||
| 88 | + } | ||
| 89 | +}; | ||
| 90 | +// 错误提示文案 | ||
| 91 | +const validatorMessage = (val, rule) => { | ||
| 92 | + if (required && !val) { | ||
| 93 | + return "必填项不能为空"; | ||
| 94 | + } else if (val && data_minvalue && val < data_minvalue) { | ||
| 95 | + return "最小可选:" + data_minvalue; | ||
| 96 | + } else if (val && data_maxvalue && val > data_maxvalue) { | ||
| 97 | + return "最大可选:" + data_maxvalue; | ||
| 98 | + } | ||
| 99 | +}; | ||
| 100 | +const rules = [{ validator, message: validatorMessage }]; | ||
| 54 | </script> | 101 | </script> |
| 55 | 102 | ||
| 56 | <style lang="less" scoped> | 103 | <style lang="less" scoped> |
| 57 | .time-picker-field { | 104 | .time-picker-field { |
| 105 | + margin: 1rem; | ||
| 58 | .label { | 106 | .label { |
| 59 | - padding: 1rem 1rem 0 1rem; | 107 | + // padding: 1rem 1rem 0 1rem; |
| 60 | font-size: 0.9rem; | 108 | font-size: 0.9rem; |
| 61 | font-weight: bold; | 109 | font-weight: bold; |
| 62 | 110 | ||
| ... | @@ -65,4 +113,11 @@ onMounted(() => { | ... | @@ -65,4 +113,11 @@ onMounted(() => { |
| 65 | } | 113 | } |
| 66 | } | 114 | } |
| 67 | } | 115 | } |
| 116 | + | ||
| 117 | +:deep(.van-cell--clickable) { | ||
| 118 | + border: 1px solid #eaeaea; | ||
| 119 | + border-radius: 0.25rem; | ||
| 120 | + padding: 0.25rem 0.5rem; | ||
| 121 | + margin-top: 0.5rem; | ||
| 122 | +} | ||
| 68 | </style> | 123 | </style> | ... | ... |
| ... | @@ -30,11 +30,11 @@ import ButtonField from '@/components/ButtonField/index.vue' | ... | @@ -30,11 +30,11 @@ import ButtonField from '@/components/ButtonField/index.vue' |
| 30 | /** | 30 | /** |
| 31 | * 生成自定义组件类型 | 31 | * 生成自定义组件类型 |
| 32 | * @param {*} data | 32 | * @param {*} data |
| 33 | - * @type text 单行文本 TextField | 33 | + * @type input 单行文本 TextField |
| 34 | * @type textarea 多行文本 TextareaField | 34 | * @type textarea 多行文本 TextareaField |
| 35 | * @type radio 单项选择 RadioField | 35 | * @type radio 单项选择 RadioField |
| 36 | * @type checkbox 多项选择 CheckboxField | 36 | * @type checkbox 多项选择 CheckboxField |
| 37 | - * @type picker 单列选择器 PickerField | 37 | + * @type select 单列选择器 PickerField |
| 38 | * @type area_picker 地址选择器 AreaPickerField | 38 | * @type area_picker 地址选择器 AreaPickerField |
| 39 | * @type date_picker 日期选择器 DatePickerField | 39 | * @type date_picker 日期选择器 DatePickerField |
| 40 | * @type time_picker 时间选择器 TimePickerField | 40 | * @type time_picker 时间选择器 TimePickerField |
| ... | @@ -60,102 +60,102 @@ export function createComponentType(data) { | ... | @@ -60,102 +60,102 @@ export function createComponentType(data) { |
| 60 | if (item.component_props.required) { | 60 | if (item.component_props.required) { |
| 61 | item.rules = [{ required: true, message: item.placeholder ? item.placeholder : '必填项不能为空' }] | 61 | item.rules = [{ required: true, message: item.placeholder ? item.placeholder : '必填项不能为空' }] |
| 62 | } | 62 | } |
| 63 | - if (item.component_props.name === 'text') { | 63 | + if (item.component_props.tag === 'input') { |
| 64 | item.type = 'text'; | 64 | item.type = 'text'; |
| 65 | item.name = item.key; | 65 | item.name = item.key; |
| 66 | item.component = TextField; | 66 | item.component = TextField; |
| 67 | } | 67 | } |
| 68 | - if (item.component_props.name === 'textarea') { | 68 | + if (item.component_props.tag === 'textarea') { |
| 69 | item.type = 'textarea'; | 69 | item.type = 'textarea'; |
| 70 | item.name = item.key; | 70 | item.name = item.key; |
| 71 | // item.rows = 10; | 71 | // item.rows = 10; |
| 72 | item.autosize = true; | 72 | item.autosize = true; |
| 73 | item.component = TextareaField; | 73 | item.component = TextareaField; |
| 74 | } | 74 | } |
| 75 | - if (item.component_props.name === 'number') { | 75 | + if (item.component_props.tag === 'number') { |
| 76 | item.name = item.key; | 76 | item.name = item.key; |
| 77 | item.component = NumberField; | 77 | item.component = NumberField; |
| 78 | } | 78 | } |
| 79 | - if (item.component_props.name === 'radio') { | 79 | + if (item.component_props.tag === 'radio') { |
| 80 | item.component = RadioField; | 80 | item.component = RadioField; |
| 81 | } | 81 | } |
| 82 | - if (item.component_props.name === 'checkbox') { | 82 | + if (item.component_props.tag === 'checkbox') { |
| 83 | item.component = CheckboxField; | 83 | item.component = CheckboxField; |
| 84 | } | 84 | } |
| 85 | - if (item.component_props.name === 'picker') { | 85 | + if (item.component_props.tag === 'select') { |
| 86 | item.component = PickerField; | 86 | item.component = PickerField; |
| 87 | } | 87 | } |
| 88 | - if (item.component_props.name === 'area_picker') { | 88 | + if (item.component_props.tag === 'address') { |
| 89 | item.component = AreaPickerField; | 89 | item.component = AreaPickerField; |
| 90 | } | 90 | } |
| 91 | - if (item.component_props.name === 'date_picker') { | 91 | + if (item.component_props.tag === 'date') { |
| 92 | item.component = DatePickerField; | 92 | item.component = DatePickerField; |
| 93 | } | 93 | } |
| 94 | - if (item.component_props.name === 'time_picker') { | 94 | + if (item.component_props.tag === 'time') { |
| 95 | item.component = TimePickerField; | 95 | item.component = TimePickerField; |
| 96 | } | 96 | } |
| 97 | - if (item.component_props.name === 'datetime_picker') { | 97 | + if (item.component_props.tag === 'datetime') { |
| 98 | item.component = DateTimePickerField; | 98 | item.component = DateTimePickerField; |
| 99 | } | 99 | } |
| 100 | - if (item.component_props.name === 'image_uploader') { | 100 | + if (item.component_props.tag === 'image_uploader') { |
| 101 | item.component = ImageUploaderField; | 101 | item.component = ImageUploaderField; |
| 102 | } | 102 | } |
| 103 | - if (item.component_props.name === 'file_uploader') { | 103 | + if (item.component_props.tag === 'file_uploader') { |
| 104 | item.component = FileUploaderField; | 104 | item.component = FileUploaderField; |
| 105 | } | 105 | } |
| 106 | - if (item.component_props.name === 'phone') { | 106 | + if (item.component_props.tag === 'phone') { |
| 107 | item.name = item.key; | 107 | item.name = item.key; |
| 108 | item.component = PhoneField; | 108 | item.component = PhoneField; |
| 109 | } | 109 | } |
| 110 | - if (item.component_props.name === 'email') { | 110 | + if (item.component_props.tag === 'email') { |
| 111 | item.name = item.key; | 111 | item.name = item.key; |
| 112 | item.component = EmailField; | 112 | item.component = EmailField; |
| 113 | } | 113 | } |
| 114 | - if (item.component_props.name === 'sign') { | 114 | + if (item.component_props.tag === 'sign') { |
| 115 | item.name = item.key; | 115 | item.name = item.key; |
| 116 | item.component = SignField; | 116 | item.component = SignField; |
| 117 | } | 117 | } |
| 118 | - if (item.component_props.name === 'rate_picker') { | 118 | + if (item.component_props.tag === 'rate') { |
| 119 | item.name = item.key; | 119 | item.name = item.key; |
| 120 | item.component = RatePickerField; | 120 | item.component = RatePickerField; |
| 121 | } | 121 | } |
| 122 | - if (item.component_props.name === 'calendar') { | 122 | + if (item.component_props.tag === 'calendar') { |
| 123 | item.name = item.key; | 123 | item.name = item.key; |
| 124 | item.component = CalendarField; | 124 | item.component = CalendarField; |
| 125 | } | 125 | } |
| 126 | - if (item.component_props.name === 'id_code') { | 126 | + if (item.component_props.tag === 'id_card') { |
| 127 | item.name = item.key; | 127 | item.name = item.key; |
| 128 | item.component = IdentityField; | 128 | item.component = IdentityField; |
| 129 | } | 129 | } |
| 130 | - if (item.component_props.name === 'desc') { | 130 | + if (item.component_props.tag === 'desc') { |
| 131 | item.name = item.key; | 131 | item.name = item.key; |
| 132 | item.component = DesField; | 132 | item.component = DesField; |
| 133 | } | 133 | } |
| 134 | - if (item.component_props.name === 'divider') { | 134 | + if (item.component_props.tag === 'divider') { |
| 135 | item.name = item.key; | 135 | item.name = item.key; |
| 136 | item.component = DividerField; | 136 | item.component = DividerField; |
| 137 | } | 137 | } |
| 138 | - if (item.component_props.name === 'video') { | 138 | + if (item.component_props.tag === 'video') { |
| 139 | item.name = item.key; | 139 | item.name = item.key; |
| 140 | item.component = VideoField; | 140 | item.component = VideoField; |
| 141 | } | 141 | } |
| 142 | - if (item.component_props.name === 'marquee') { | 142 | + if (item.component_props.tag === 'marquee') { |
| 143 | item.name = item.key; | 143 | item.name = item.key; |
| 144 | item.component = MarqueeField; | 144 | item.component = MarqueeField; |
| 145 | } | 145 | } |
| 146 | - if (item.component_props.name === 'contact') { | 146 | + if (item.component_props.tag === 'contact') { |
| 147 | item.name = item.key; | 147 | item.name = item.key; |
| 148 | item.component = ContactField; | 148 | item.component = ContactField; |
| 149 | } | 149 | } |
| 150 | - if (item.component_props.name === 'rule') { | 150 | + if (item.component_props.tag === 'rule') { |
| 151 | item.name = item.key; | 151 | item.name = item.key; |
| 152 | item.component = RuleField; | 152 | item.component = RuleField; |
| 153 | } | 153 | } |
| 154 | - if (item.component_props.name === 'button') { | 154 | + if (item.component_props.tag === 'button') { |
| 155 | item.name = item.key; | 155 | item.name = item.key; |
| 156 | item.component = ButtonField; | 156 | item.component = ButtonField; |
| 157 | } | 157 | } |
| 158 | - if (item.component_props.name === 'multi_rule') { | 158 | + if (item.component_props.tag === 'multi_rule') { |
| 159 | item.name = item.key; | 159 | item.name = item.key; |
| 160 | item.value = []; | 160 | item.value = []; |
| 161 | item.component = MultiRuleField; | 161 | item.component = MultiRuleField; | ... | ... |
| 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: 2022-12-09 15:25:00 | 4 | + * @LastEditTime: 2022-12-28 10:46:29 |
| 5 | * @FilePath: /data-table/src/views/index.vue | 5 | * @FilePath: /data-table/src/views/index.vue |
| 6 | * @Description: 首页 | 6 | * @Description: 首页 |
| 7 | --> | 7 | --> |
| ... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
| 13 | scrollable | 13 | scrollable |
| 14 | mode="closeable" | 14 | mode="closeable" |
| 15 | /> | 15 | /> |
| 16 | - <div class="table-box" :style="{ margin: is_pc ? '1rem 0' : '1rem'}"> | 16 | + <div class="table-box" :style="{ margin: is_pc ? '1rem 0' : '1rem', overflow: 'auto'}"> |
| 17 | <van-image | 17 | <van-image |
| 18 | v-if="PHeader.type === '单张图'" | 18 | v-if="PHeader.type === '单张图'" |
| 19 | width="100%" | 19 | width="100%" |
| ... | @@ -31,7 +31,7 @@ | ... | @@ -31,7 +31,7 @@ |
| 31 | <div v-if="PHeader.label" class="table-title">{{ PHeader.label }}</div> | 31 | <div v-if="PHeader.label" class="table-title">{{ PHeader.label }}</div> |
| 32 | <div v-if="PHeader.description" class="table-desc" v-html="PHeader.description" /> | 32 | <div v-if="PHeader.description" class="table-desc" v-html="PHeader.description" /> |
| 33 | <van-config-provider :theme-vars="themeVars"> | 33 | <van-config-provider :theme-vars="themeVars"> |
| 34 | - <van-form @submit="onSubmit"> | 34 | + <van-form @submit="onSubmit" scroll-to-error="true"> |
| 35 | <van-cell-group :border="false"> | 35 | <van-cell-group :border="false"> |
| 36 | <component | 36 | <component |
| 37 | v-for="(item, index) in formData" | 37 | v-for="(item, index) in formData" |
| ... | @@ -122,40 +122,11 @@ const model = $route.query.model; | ... | @@ -122,40 +122,11 @@ const model = $route.query.model; |
| 122 | const formatData = (data) => { | 122 | const formatData = (data) => { |
| 123 | const arr = []; | 123 | const arr = []; |
| 124 | data.forEach((field) => { | 124 | data.forEach((field) => { |
| 125 | + const { interaction_type, data_type, field_id, field_name, ...component_props } = field; | ||
| 125 | // 生成组件属性 | 126 | // 生成组件属性 |
| 126 | - const component_props = { | ||
| 127 | - name: field.component_code, | ||
| 128 | - }; | ||
| 129 | - if (field.component_type === "h5edit") { | ||
| 130 | - // 编辑组件 | ||
| 131 | - field.property_list.forEach((prop) => { | ||
| 132 | - const key = prop["property_code"]; | ||
| 133 | - const obj = { | ||
| 134 | - [key]: | ||
| 135 | - prop["setting_value"].length > 1 | ||
| 136 | - ? prop["setting_value"] | ||
| 137 | - : prop["setting_value"][0], | ||
| 138 | - }; | ||
| 139 | - Object.assign(component_props, obj); | ||
| 140 | - }); | ||
| 141 | - } else { | ||
| 142 | - // 展示组件 | ||
| 143 | - field.property_list.forEach((prop) => { | ||
| 144 | - const key = prop["property_code"]; | ||
| 145 | - const obj = { | ||
| 146 | - [key]: | ||
| 147 | - key !== 'label' | ||
| 148 | - ? prop["setting_value"] | ||
| 149 | - : prop["setting_value"][0], | ||
| 150 | - }; | ||
| 151 | - Object.assign(component_props, obj); | ||
| 152 | - }); | ||
| 153 | - } | ||
| 154 | - // 绑定组件名称标识 | ||
| 155 | const temp = { | 127 | const temp = { |
| 156 | - key: field.field_name, | 128 | + key: field_name, |
| 157 | value: component_props.default ? component_props.default : "", | 129 | value: component_props.default ? component_props.default : "", |
| 158 | - component: field.component_code, | ||
| 159 | component_props, | 130 | component_props, |
| 160 | }; | 131 | }; |
| 161 | arr.push(temp); | 132 | arr.push(temp); |
| ... | @@ -173,19 +144,19 @@ const rate_picker = ref([]); | ... | @@ -173,19 +144,19 @@ const rate_picker = ref([]); |
| 173 | // 动态绑定ref数据 | 144 | // 动态绑定ref数据 |
| 174 | const setRefMap = (el, item) => { | 145 | const setRefMap = (el, item) => { |
| 175 | if (el) { | 146 | if (el) { |
| 176 | - if (item.component_props.name === "area_picker") { | 147 | + if (item.component_props.tag === "area_picker") { |
| 177 | area_picker.value.push(el); | 148 | area_picker.value.push(el); |
| 178 | } | 149 | } |
| 179 | - if (item.component_props.name === "image_uploader") { | 150 | + if (item.component_props.tag === "image_uploader") { |
| 180 | image_uploader.value.push(el); | 151 | image_uploader.value.push(el); |
| 181 | } | 152 | } |
| 182 | - if (item.component_props.name === "file_uploader") { | 153 | + if (item.component_props.tag === "file_uploader") { |
| 183 | file_uploader.value.push(el); | 154 | file_uploader.value.push(el); |
| 184 | } | 155 | } |
| 185 | - if (item.component_props.name === "sign") { | 156 | + if (item.component_props.tag === "sign") { |
| 186 | sign.value.push(el); | 157 | sign.value.push(el); |
| 187 | } | 158 | } |
| 188 | - if (item.component_props.name === "rate_picker") { | 159 | + if (item.component_props.tag === "rate_picker") { |
| 189 | rate_picker.value.push(el); | 160 | rate_picker.value.push(el); |
| 190 | } | 161 | } |
| 191 | } | 162 | } |
| ... | @@ -201,27 +172,20 @@ onMounted(async () => { | ... | @@ -201,27 +172,20 @@ onMounted(async () => { |
| 201 | .querySelector("body") | 172 | .querySelector("body") |
| 202 | .setAttribute("style", `background-color: ${styleColor.backgroundColor}`); | 173 | .setAttribute("style", `background-color: ${styleColor.backgroundColor}`); |
| 203 | const { data } = await queryFormAPI({ form_code: $route.query.code }); | 174 | const { data } = await queryFormAPI({ form_code: $route.query.code }); |
| 204 | - const form_data = data[0]; | 175 | + const form_data = data; |
| 176 | + // 表单网页标题 | ||
| 205 | useTitle(form_data.name); | 177 | useTitle(form_data.name); |
| 206 | // 重构数据结构 | 178 | // 重构数据结构 |
| 207 | let page_header = {}; | 179 | let page_header = {}; |
| 208 | let page_commit = {}; | 180 | let page_commit = {}; |
| 209 | let page_form = []; | 181 | let page_form = []; |
| 210 | form_data.field_list.forEach((element) => { | 182 | form_data.field_list.forEach((element) => { |
| 211 | - if (element.component_code === "page_header") { | 183 | + if (element.tag === "page_header") { |
| 212 | // 页眉组件 | 184 | // 页眉组件 |
| 213 | - const list = element.property_list; | 185 | + page_header = element; |
| 214 | - list.forEach((ele) => { | 186 | + } else if (element.tag === "page_commit") { |
| 215 | - page_header[ele["property_code"]] = | ||
| 216 | - ele.setting_value.length > 1 ? ele.setting_value : ele.setting_value[0]; | ||
| 217 | - }); | ||
| 218 | - } else if (element.component_code === "page_commit") { | ||
| 219 | // 提交按钮 | 187 | // 提交按钮 |
| 220 | - const list = element.property_list; | 188 | + page_commit = element; |
| 221 | - list.forEach((ele) => { | ||
| 222 | - page_commit[ele["property_code"]] = | ||
| 223 | - ele.setting_value.length > 1 ? ele.setting_value : ele.setting_value[0]; | ||
| 224 | - }); | ||
| 225 | } else { | 189 | } else { |
| 226 | page_form.push(element); | 190 | page_form.push(element); |
| 227 | } | 191 | } |
| ... | @@ -248,21 +212,22 @@ onMounted(async () => { | ... | @@ -248,21 +212,22 @@ onMounted(async () => { |
| 248 | }; | 212 | }; |
| 249 | } | 213 | } |
| 250 | formData.value = formatData(page_form); | 214 | formData.value = formatData(page_form); |
| 251 | - // mockData.value = [ | 215 | + mockData.value = [ |
| 252 | - // { | 216 | + { |
| 253 | - // key: "", | 217 | + key: "111", |
| 254 | - // value: "", | 218 | + value: "", |
| 255 | - // component: "", | 219 | + component: "", |
| 256 | - // component_props: { | 220 | + component_props: { |
| 257 | - // name: "multi_rule", | 221 | + name: "datetime", |
| 258 | - // label: "同意活动规则之后才可提交", | 222 | + tag: "datetime", |
| 259 | - // required: "1", | 223 | + label: "时间日期", |
| 260 | - // count: "2", | 224 | + data_dateformat: "YYYY-MM-DD HH:mm:ss", |
| 261 | - // }, | 225 | + required: true, |
| 262 | - // }, | 226 | + }, |
| 263 | - // ]; | 227 | + }, |
| 228 | + ]; | ||
| 264 | // 生成自定义组件 | 229 | // 生成自定义组件 |
| 265 | - // createComponentType(mockData.value); | 230 | + createComponentType(mockData.value); |
| 266 | createComponentType(formData.value); | 231 | createComponentType(formData.value); |
| 267 | // 过期时间显示 | 232 | // 过期时间显示 |
| 268 | notice_text.value = `表单报名将在 ${formSetting.value.sjsj_end_time} 后结束`; | 233 | notice_text.value = `表单报名将在 ${formSetting.value.sjsj_end_time} 后结束`; |
| ... | @@ -290,16 +255,7 @@ const checkUserSubscribe = async () => { | ... | @@ -290,16 +255,7 @@ const checkUserSubscribe = async () => { |
| 290 | const { data } = await getFormSettingAPI({ form_code: code }); | 255 | const { data } = await getFormSettingAPI({ form_code: code }); |
| 291 | const form_setting = {}; | 256 | const form_setting = {}; |
| 292 | if (data.length) { | 257 | if (data.length) { |
| 293 | - data[0].property_list.forEach((prop) => { | 258 | + Object.assign(form_setting, data[0]['property_list'], data[0]['extend']); |
| 294 | - const key = prop["property_code"]; | ||
| 295 | - const obj = { | ||
| 296 | - [key]: | ||
| 297 | - prop["setting_value"].length > 1 | ||
| 298 | - ? prop["setting_value"] | ||
| 299 | - : prop["setting_value"][0], | ||
| 300 | - }; | ||
| 301 | - Object.assign(form_setting, obj, data[0]['extend']); | ||
| 302 | - }); | ||
| 303 | } | 259 | } |
| 304 | // 判断是否需要关注公众号, 弹出二维码识别 | 260 | // 判断是否需要关注公众号, 弹出二维码识别 |
| 305 | if (form_setting.wxzq_must_follow && form_setting.x_field_weixin_subscribe) { | 261 | if (form_setting.wxzq_must_follow && form_setting.x_field_weixin_subscribe) { | ... | ... |
-
Please register or login to post a comment