Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Hooke
/
custom_form
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Graphs
Network
Create a new issue
Commits
Issue Boards
Authored by
hookehuyr
2023-04-10 15:22:42 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
f31de36862e0ffba5a06dc4b9636343926872c6d
f31de368
1 parent
0182ccb7
✨ feat(身份证控件): 样式和功能调整
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
157 additions
and
110 deletions
components.d.ts
src/components/IdentityField/index.vue
src/hooks/useComponentType.js
src/pages/table/index.vue
components.d.ts
View file @
f31de36
...
...
@@ -35,7 +35,6 @@ declare module '@vue/runtime-core' {
NutDatePicker
:
typeof
import
(
'@nutui/nutui-taro'
)[
'DatePicker'
]
NutDialog
:
typeof
import
(
'@nutui/nutui-taro'
)[
'Dialog'
]
NutDivider
:
typeof
import
(
'@nutui/nutui-taro'
)[
'Divider'
]
NutField
:
typeof
import
(
'@nutui/nutui-taro'
)[
'Field'
]
NutForm
:
typeof
import
(
'@nutui/nutui-taro'
)[
'Form'
]
NutFormItem
:
typeof
import
(
'@nutui/nutui-taro'
)[
'FormItem'
]
NutInput
:
typeof
import
(
'@nutui/nutui-taro'
)[
'Input'
]
...
...
src/components/IdentityField/index.vue
View file @
f31de36
<!--
* @Date: 2022-09-14 14:44:30
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2023-04-
07 09:30:49
* @LastEditTime: 2023-04-
10 15:09:13
* @FilePath: /custom_form/src/components/IdentityField/index.vue
* @Description: 身份证输入控件
-->
<template>
<div v-if="HideShow" class="identity-page">
<div class="label">
<
span v-if="item.component_props.required"> *</span
>
<
text v-if="item.component_props.required"> *</text
>
{{ item.component_props.label }}
</div>
<!-- <div v-if="item.component_props.readonly" style="padding: 0.5rem 1rem;">{{ item.value }}</div> -->
...
...
@@ -27,20 +27,34 @@
:border="false"
>
</van-field> -->
<van-field ref="fieldRef" v-model="item.value" :id="item.name" :name="item.name"
:placeholder="item.component_props.placeholder" :rules="rules" :required="item.component_props.required"
:disabled="item.component_props.readonly" :border="false">
</van-field>
<nut-form-item>
<nut-input
ref="fieldRef"
v-model="input_value"
:placeholder="item.component_props.placeholder"
:disabled="item.component_props.readonly"
:border="false"
@blur="onBlur"
style="border: 1px solid #eaeaea; border-radius: 0.25rem; padding: 0.25rem 0.5rem;">
</nut-input>
<div
v-if="show_error"
style="padding: 5px; color: red; font-size: 12px;"
>
{{ error_msg }}
</div>
</nut-form-item>
<!-- <div v-if="gender" class="gender"><span>性别:</span>{{ gender }}</div> -->
<van-number-keyboard v-model="item.value" :show="show" extra-key="X" close-button-text="完成" @blur="blurKeyboard()"
@input="onInput" @delete="onDelete" safe-area-inset-bottom />
<
!-- <
van-number-keyboard v-model="item.value" :show="show" extra-key="X" close-button-text="完成" @blur="blurKeyboard()"
@input="onInput" @delete="onDelete" safe-area-inset-bottom />
-->
</div>
</template>
<script setup>
import $ from "jquery";
import { storeToRefs, mainStore } from "@/utils/generatePackage";
import { showSuccessToast, showFailToast } from "vant";
import { ref, computed, watch, onMounted, reactive } from "vue";
// import $ from "jquery";
// import { storeToRefs, mainStore } from "@/utils/generatePackage";
// import { showSuccessToast, showFailToast } from "vant";
const props = defineProps({
...
...
@@ -50,105 +64,119 @@ const props = defineProps({
const HideShow = computed(() => {
return !props.item.component_props.disabled
})
const emit = defineEmits(["active"]);
const input_value = ref(props.item.component_props.default);
const show = ref(false);
let content = "";
const store = mainStore();
const { fieldName } = storeToRefs(store);
// 监听字段变化
watch(
() => fieldName.value,
(v) => {
// 如果不是点击本输入框
if (v !== props.item.name) {
// 还原border颜色
$(`#${props.item.name}`).parent().css("border-color", "#eaeaea");
show.value = false;
document.getElementById("app").style.paddingBottom = "0";
}
}
);
//
const store = mainStore();
//
const { fieldName } = storeToRefs(store);
//
//
监听字段变化
//
watch(
//
() => fieldName.value,
//
(v) => {
//
// 如果不是点击本输入框
//
if (v !== props.item.name) {
//
// 还原border颜色
//
$(`#${props.item.name}`).parent().css("border-color", "#eaeaea");
//
show.value = false;
//
document.getElementById("app").style.paddingBottom = "0";
//
}
//
}
//
);
const readonly = props.item.component_props.readonly;
const fieldRef = ref(null);
const edit_mode = ref(false);
const clickRightIcon = () => { // 编辑模式
edit_mode.value = true;
nextTick(() => {
fieldRef.value?.focus();
})
}
const openKeyboard = (e) => {
if (readonly || e.target.className.indexOf('edit') > 0 || edit_mode.value) return false; // 如果为只读或者编辑模式,不能设置
// // 键盘上移动
// const target_to_view_height = window.innerHeight - e.target.getBoundingClientRect().y; // 元素到适口高度
// const target_top = document.body.scrollHeight - $(e.target).offset().top; // 元素到正文高度
// let scroll_height = "";
// console.warn(target_top);
// if (target_top < 250) {
// document.getElementById("app").style.paddingBottom = "250px";
// window.scrollTo(0, $("#app").height());
// } else {
// // 向上滚动位置
// document.documentElement.scrollTop = (target_top > 250 ? 0 : target_top) + 250;
// }
// 键盘上移动
const target_to_view_height =
window.innerHeight - e.target.getBoundingClientRect().bottom; // 元素到适口高度
const target_top = document.body.scrollHeight - $(e.target).offset().top; // 元素到正文高度
let scroll_height = "";
if (target_to_view_height <= 250) {
document.getElementById("app").style.paddingBottom = "250px";
// 向上滚动位置
document.documentElement.scrollTop = $(e.target).offset().top - 244;
}
// 选中添加border颜色
content = $(e.target).parent();
// TAG: 自定义主题颜色
content.css("border-color", "#c2915f");
setTimeout(() => {
show.value = true;
}, 300);
// 记录点击field名
store.changeFieldName(props.item.name);
};
const blurKeyboard = () => {
show.value = false;
document.getElementById("app").style.paddingBottom = "0";
// 还原border颜色
content.css("border-color", "#eaeaea");
// 键盘失焦检查输入和添加性别显示
const input_val = props.item.value;
if (required && !input_val) {
showFailToast("身份证号码不能为空");
} else if (input_val && !/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(input_val)) {
showFailToast("请输入正确身份证号码");
} else {
// gender.value = getGenderByIdNumber(input_val)
}
};
// const clickRightIcon = () => { // 编辑模式
// edit_mode.value = true;
// nextTick(() => {
// fieldRef.value?.focus();
// })
// }
// const openKeyboard = (e) => {
// if (readonly || e.target.className.indexOf('edit') > 0 || edit_mode.value) return false; // 如果为只读或者编辑模式,不能设置
// // // 键盘上移动
// // const target_to_view_height = window.innerHeight - e.target.getBoundingClientRect().y; // 元素到适口高度
// // const target_top = document.body.scrollHeight - $(e.target).offset().top; // 元素到正文高度
// // let scroll_height = "";
// // console.warn(target_top);
// // if (target_top < 250) {
// // document.getElementById("app").style.paddingBottom = "250px";
// // window.scrollTo(0, $("#app").height());
// // } else {
// // // 向上滚动位置
// // document.documentElement.scrollTop = (target_top > 250 ? 0 : target_top) + 250;
// // }
// // 键盘上移动
// const target_to_view_height =
// window.innerHeight - e.target.getBoundingClientRect().bottom; // 元素到适口高度
// const target_top = document.body.scrollHeight - $(e.target).offset().top; // 元素到正文高度
// let scroll_height = "";
// if (target_to_view_height <= 250) {
// document.getElementById("app").style.paddingBottom = "250px";
// // 向上滚动位置
// document.documentElement.scrollTop = $(e.target).offset().top - 244;
// }
// // 选中添加border颜色
// content = $(e.target).parent();
// // TAG: 自定义主题颜色
// content.css("border-color", "#c2915f");
// setTimeout(() => {
// show.value = true;
// }, 300);
// // 记录点击field名
// store.changeFieldName(props.item.name);
// };
// const blurKeyboard = () => {
// show.value = false;
// document.getElementById("app").style.paddingBottom = "0";
// // 还原border颜色
// content.css("border-color", "#eaeaea");
// // 键盘失焦检查输入和添加性别显示
// const input_val = props.item.value;
// if (required && !input_val) {
// showFailToast("身份证号码不能为空");
// } else if (input_val && !/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(input_val)) {
// showFailToast("请输入正确身份证号码");
// } else {
// // gender.value = getGenderByIdNumber(input_val)
// }
// };
// 错误提示
const show_error = ref(false);
const error_msg = ref('');
// 校验
函数返回 true 表示校验通过,false 表示不通过
// 校验
模块
// 身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X
const required = props.item.component_props.required;
const validator = (val) => {
if (required && !val) {
return false;
} else if (val && !/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(val)) {
return false;
const validIdCard = () => {
// 必填项
if (props.item.component_props.required && !input_value.value) {
show_error.value = true;
error_msg.value = '必填项不能为空'
} else if (input_value.value && !/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(input_value.value)) {
show_error.value = true;
error_msg.value = '请输入正确身份证号码'
} else {
return true;
}
};
// 错误提示文案
const validatorMessage = (val, rule) => {
if (required && !val) {
return "身份证号码不能为空";
} else if (val && !/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(val)) {
return "请输入正确身份证号码";
show_error.value = false;
error_msg.value = ''
}
return !show_error.value;
};
const rules = [{ validator, message: validatorMessage }];
defineExpose({ validIdCard, id: props.item.key });
const onBlur = () => {
validIdCard()
props.item.value = {
key: "id_card",
filed_name: props.item.key,
value: input_value.value,
};
emit("active", props.item.value);
}
const onInput = (value) => { };
const onDelete = () => { };
...
...
@@ -179,14 +207,14 @@ const getGenderByIdNumber = (idNumber) => {
}
</script>
<style lang="less"
scoped
>
<style lang="less">
.identity-page {
.label {
padding:
1rem 1rem 0 1rem
;
font-size:
0.9rem
;
padding:
0 30px 0 45px
;
font-size:
26px
;
font-weight: bold;
span
{
text
{
color: red;
}
}
...
...
src/hooks/useComponentType.js
View file @
f31de36
...
...
@@ -15,7 +15,7 @@ import EmailField from '@/components/EmailField/index.vue'
// import SignField from '@/components/SignField/index.vue'
// import RatePickerField from '@/components/RatePickerField/index.vue'
// import CalendarField from '@/components/CalendarField/index.vue'
//
import IdentityField from '@/components/IdentityField/index.vue'
import
IdentityField
from
'@/components/IdentityField/index.vue'
import
NumberField
from
'@/components/NumberField/index.vue'
// import DesField from '@/components/DesField/index.vue'
// import DividerField from '@/components/DividerField/index.vue'
...
...
@@ -131,10 +131,10 @@ export function createComponentType(data) {
// item.name = item.key
// item.component = CalendarField
// }
//
if (item.component_props.tag === 'id_card') {
//
item.name = item.key
//
item.component = IdentityField
//
}
if
(
item
.
component_props
.
tag
===
'id_card'
)
{
item
.
name
=
item
.
key
item
.
component
=
IdentityField
}
// if (item.component_props.tag === 'desc') {
// item.name = item.key
// item.component = DesField
...
...
src/pages/table/index.vue
View file @
f31de36
<!--
* @Date: 2023-03-24 09:19:27
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2023-04-
07 17:26:0
7
* @LastEditTime: 2023-04-
10 14:38:5
7
* @FilePath: /custom_form/src/pages/table/index.vue
* @Description: 文件描述
-->
...
...
@@ -139,6 +139,7 @@ const address = ref([]);
const date = ref([]);
const time = ref([]);
const datetime = ref([]);
const id_card = ref([]);
const area_picker = ref([]);
const image_uploader = ref([]);
const file_uploader = ref([]);
...
...
@@ -186,6 +187,9 @@ const setRefMap = (el, item) => {
if (item.component_props.tag === "datetime") {
datetime.value.push(el);
}
if (item.component_props.tag === "id_card") {
id_card.value.push(el);
}
if (item.component_props.tag === "area_picker") {
area_picker.value.push(el);
}
...
...
@@ -466,6 +470,9 @@ const onActive = (item) => {
if (item.key === "datetime") {
postData.value[item.filed_name] = item.value;
}
if (item.key === "id_card") {
postData.value[item.filed_name] = item.value;
}
if (item.key === "image_uploader") {
postData.value[item.filed_name] = item.value;
}
...
...
@@ -661,6 +668,19 @@ const validOther = () => {
}
});
}
if (id_card.value) {
// 身份证控件
id_card.value.forEach((item, index) => {
if (!id_card.value[index].validIdCard()) {
valid = {
status: id_card.value[index].validIdCard(),
key: "id_card",
id: id_card.value[index]?.id
};
return false;
}
});
}
if (area_picker.value) {
// 省市区地址
area_picker.value.forEach((item, index) => {
...
...
Please
register
or
login
to post a comment