sh_real_name_system_app/src/components/KeyInfoForm/index.vue

552 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 人员关键信息表单 -->
<view style="height: 100%">
<up-form
labelWidth="120"
labelPosition="left"
:model="keyInfoForm"
:rules="keyInfoFormRules"
ref="keyInfoFormRef"
>
<up-cell style="padding: 0 13px">
<template #icon>
<text class="red-text"> 此页面全部为必填项 </text>
</template>
</up-cell>
<up-form-item label="工种" prop="postName" :borderBottom="true">
<up-cell
isLink
size="large"
style="width: 100%"
@tap="onOpenPiker(1)"
:border="false"
:disabled="props.formType == 2"
>
<template #icon>
<text :class="{ 'color-text': keyInfoForm.postName }" class="time-text">
{{ keyInfoForm.postName || '选择工种' }}
</text>
</template>
</up-cell>
</up-form-item>
<up-form-item label="手机号" prop="phone" :borderBottom="true">
<up-input
clearable
border="none"
placeholder="请输入手机号"
v-model="keyInfoForm.phone"
:disabled="props.formType == 2"
/>
</up-form-item>
<up-form-item label="入场工程" prop="proName" :borderBottom="true">
<up-cell
isLink
size="large"
style="width: 100%"
@tap="onOpenPiker(2)"
:border="false"
:disabled="props.formType == 2"
>
<template #icon>
<text :class="{ 'color-text': keyInfoForm.proName }" class="time-text">
{{ keyInfoForm.proName || '选择入场工程' }}
</text>
</template>
</up-cell>
</up-form-item>
<up-form-item label="入场分包" prop="subName" :borderBottom="true">
<up-cell
isLink
size="large"
style="width: 100%"
@tap="onOpenPiker(3)"
:border="false"
:disabled="props.formType == 2"
>
<template #icon>
<text :class="{ 'color-text': keyInfoForm.subName }" class="time-text">
{{ keyInfoForm.subName || '选择入场分包' }}
</text>
</template>
</up-cell>
</up-form-item>
<up-form-item label="入场班组" prop="teamName" :borderBottom="true">
<up-cell
isLink
size="large"
style="width: 100%"
@tap="onOpenPiker(4)"
:border="false"
:disabled="props.formType == 2"
>
<template #icon>
<text :class="{ 'color-text': keyInfoForm.teamName }" class="time-text">
{{ keyInfoForm.teamName || '选择入场班组' }}
</text>
</template>
</up-cell>
</up-form-item>
<up-cell style="padding: 0 13px">
<template #icon>
<text class="red-text"> 特征信息采集 </text>
</template>
</up-cell>
<up-form-item label="人脸照片采集" prop="faceImg">
<up-upload
multiple
:maxCount="1"
name="faceImg"
accept="image"
@delete="deletePic"
@afterRead="afterRead"
:capture="['camera']"
:fileList="keyInfoForm.faceImg"
/>
</up-form-item>
</up-form>
<view class="red-text tip-container">
<text> 提醒事项 </text>
<text> 1 入场后即为入场即可考勤打卡</text>
<text> 2 手机号会自动创建施工人员级别APP帐号默认密码HDsbd@123456</text>
<text> 3 人脸照片采集用于考勤打卡APP打卡考勤机打卡 </text>
</view>
<!-- 工种 -->
<up-picker
:show="postPickerShow"
closeOnClickOverlay
@cancel="onCancelPost"
@confirm="onConfirmPost"
:columns="postPickerColumns"
@close="postPickerShow = false"
/>
<!-- 工程 -->
<up-picker
:show="proPickerShow"
@cancel="onCancelPro"
closeOnClickOverlay
@confirm="onConfirmPro"
:columns="proPickerColumns"
@close="proPickerShow = false"
/>
<!-- 分包 -->
<up-picker
:show="subPickerShow"
@cancel="onCancelSub"
closeOnClickOverlay
@confirm="onConfirmSub"
:columns="subPickerColumns"
@close="subPickerShow = false"
/>
<!-- 班组 -->
<up-picker
:show="teamPickerShow"
@cancel="onCancelTeam"
closeOnClickOverlay
@confirm="onConfirmTeam"
:columns="teamPickerColumns"
@close="teamPickerShow = false"
/>
</view>
</template>
<script setup name="keyInfoForm">
import { ref, onMounted, watch } from 'vue'
import {
getPostTypeSelectListAPI,
getSubSelectListByConditionAPI,
getTeamSelectListByConditionAPI,
getLotProjectSelectListByConditionAPI,
} from '@/services/common'
const keyInfoFormRef = ref(null) // 关键信息校验表单ref
const photoIds = ref('') // 上传文件列表 存储ID
const keyInfoForm = ref({
proId: '', // 入场工程
postId: '', // 工种
subId: '', // 入场分包
phone: '', // 手机号码
teamId: '', // 入场班组
proName: '', // 入场工程名称
subName: '', // 入场分包名称
teamName: '', // 入场班组名称
postName: '', // 工种名称
faceImg: [], // 人脸照片
}) // 身份证表单数据
const keyInfoFormRules = ref({
postName: [
{
type: 'string',
required: true,
message: '请选择工种',
},
],
phone: [
{
type: 'string',
required: true,
message: '请输入手机号',
},
{
pattern: /^1[3-9]\d{9}$/,
message: '请输入正确的手机号',
},
],
proName: [
{
type: 'string',
required: true,
message: '请选择入场工程',
},
],
subName: [
{
type: 'string',
required: true,
message: '请选择入场分包',
},
],
teamName: [
{
type: 'string',
required: true,
message: '请选择入场班组',
},
],
faceImg: [
{
type: 'array',
required: true,
message: '请上传人脸照片',
},
],
}) // 身份证表单规则
const postPickerShow = ref(false) // 工种选择器
const proPickerShow = ref(false) // 工程选择器
const subPickerShow = ref(false) // 分包选择器
const teamPickerShow = ref(false) // 班组选择器
const postPickerColumns = ref([[]]) // 工种选择器列
const proPickerColumns = ref([[]]) // 工程选择器列
const subPickerColumns = ref([[]]) // 分包选择器列
const teamPickerColumns = ref([[]]) // 班组选择器列
// 打开选择器
const onOpenPiker = (type) => {
switch (type) {
case 1:
postPickerShow.value = true
break
case 2:
proPickerShow.value = true
break
case 3:
subPickerShow.value = true
break
case 4:
teamPickerShow.value = true
break
}
}
// 工种确认
const onConfirmPost = (e) => {
keyInfoForm.value.postName = e.value[0].text
keyInfoForm.value.postId = e.value[0].value
postPickerShow.value = false
}
// 工种取消
const onCancelPost = () => {
keyInfoForm.value.postName = ''
keyInfoForm.value.postId = ''
postPickerShow.value = false
}
// 工程确认
const onConfirmPro = (e) => {
keyInfoForm.value.proName = e.value[0].text
keyInfoForm.value.proId = e.value[0].value
proPickerShow.value = false
getSubSelectListByCondition(e.value[0].value)
}
// 工程取消
const onCancelPro = () => {
keyInfoForm.value.proName = ''
keyInfoForm.value.proId = ''
keyInfoForm.value.subName = ''
keyInfoForm.value.subId = ''
keyInfoForm.value.teamName = ''
keyInfoForm.value.teamId = ''
proPickerShow.value = false
subPickerColumns.value[0] = []
teamPickerColumns.value[0] = []
}
// 分包确认
const onConfirmSub = (e) => {
keyInfoForm.value.subName = e.value[0].text
keyInfoForm.value.subId = e.value[0].value
subPickerShow.value = false
getTeamSelectListByCondition(e.value[0].value)
}
// 分包取消
const onCancelSub = () => {
keyInfoForm.value.subName = ''
keyInfoForm.value.subId = ''
keyInfoForm.value.teamName = ''
keyInfoForm.value.teamId = ''
subPickerShow.value = false
teamPickerColumns.value[0] = []
}
// 班组确认
const onConfirmTeam = (e) => {
keyInfoForm.value.teamName = e.value[0].text
keyInfoForm.value.teamId = e.value[0].value
teamPickerShow.value = false
}
// 班组取消
const onCancelTeam = () => {
keyInfoForm.value.teamName = ''
keyInfoForm.value.teamId = ''
teamPickerShow.value = false
}
// 删除图片
const deletePic = (e) => {
// console.log(e)
keyInfoForm.value.faceImg = []
}
// 上传图片
const afterRead = (e) => {
console.log(e, '选择的文件')
const type = e.file[0].type
if (!type.includes('image')) {
uni.$u.toast('请上传图片格式')
return
}
const files = [
{
file: e.file[0].url,
name: 'file',
uri: e.file[0].url,
},
]
uni.uploadFile({
url: '/bmw/worker/faceDetection',
files: files,
name: 'file',
isUploadFile: true,
success: (res) => {
const data = JSON.parse(res.data)
if (data.code === 200) {
uni.uploadFile({
url: '/bmw/app/uploadFile',
files: files,
name: 'file',
isUploadFile: true,
formData: {
type: 1,
},
success: (res) => {
const data = JSON.parse(res.data)
if (data.code === 200) {
keyInfoForm.value.faceImg.push({
...e.file[0],
})
// 走上传逻辑 上传成功后把ID插入到fileList中
// keyInfoForm.value.photoIds = data.data
photoIds.value = data.data
} else {
uni.$u.toast('上传失败')
}
},
fail: (err) => {
uni.$u.toast('上传失败,请重新上传')
},
})
} else {
uni.$u.toast('人脸识别失败')
keyInfoForm.value.faceImg = []
}
},
fail: (err) => {
uni.$u.toast('人脸识别失败')
},
})
//
}
// 表单校验
const validateKeyInfoForm = async () => {
return new Promise((resolve, reject) => {
keyInfoFormRef.value
.validate()
.then((valid) => {
if (valid) {
let data = {}
if (photoIds.value) {
data = { photoIds: photoIds.value, ...keyInfoForm.value }
} else {
data = { ...keyInfoForm.value }
}
let params = {
isValid: true,
data,
}
resolve(params)
}
})
.catch((err) => {
reject(false)
})
})
}
// 获取工种
const getPostTypeSelectList = async () => {
try {
const { rows: res } = await getPostTypeSelectListAPI()
if (res && res.length > 0) {
postPickerColumns.value[0] = res.map((item) => {
return {
text: item.postName,
value: item.id,
}
})
}
} catch (error) {}
}
// 获取工程
const getLotProjectSelectListByCondition = async () => {
try {
const { data: res } = await getLotProjectSelectListByConditionAPI({})
if (res && res.length > 0) {
proPickerColumns.value[0] = res.map((item) => {
return {
text: item.name,
value: item.id,
}
})
}
} catch (error) {}
}
// 获取分包
const getSubSelectListByCondition = async (proId) => {
try {
const { data: res } = await getSubSelectListByConditionAPI({ proId })
// console.log(res, 'res--9996')
if (res && res.length > 0) {
subPickerColumns.value[0] = res.map((item) => {
return {
text: item.name,
value: item.id,
}
})
}
} catch (error) {}
}
// 获取班组
const getTeamSelectListByCondition = async (subId) => {
try {
const { data: res } = await getTeamSelectListByConditionAPI({ subId })
if (res && res.length > 0) {
teamPickerColumns.value[0] = res.map((item) => {
return {
text: item.name,
value: item.id,
}
})
}
} catch (error) {}
}
onMounted(() => {
getPostTypeSelectList()
getLotProjectSelectListByCondition()
})
const props = defineProps({
keyInfo: {
type: Object,
default: () => {},
},
formType: {
type: [Number, String], // 表单类型
default: 1,
},
})
const updateKeyInfoInfo = () => {
Object.assign(keyInfoForm.value, props.keyInfo)
// console.log(keyInfoForm.value, 'keyInfoForm.value')
}
// 向父组件暴露方法
defineExpose({
validateKeyInfoForm,
updateKeyInfoInfo,
})
// 增加监听
watch(
props.keyInfo,
(newVal) => {
if (Object.keys(newVal).length > 0) {
Object.assign(keyInfoForm.value, newVal)
}
},
{
immediate: true,
},
)
</script>
<style scoped lang="scss">
@import '@/uni.scss';
.blue-text {
font-size: 14px;
color: $uni-color-primary;
}
.u-form-item {
padding: 0 15px;
}
::v-deep .u-cell__body {
padding: 13px 0;
}
.color-text {
color: rgb(48, 49, 51) !important;
}
.time-text {
color: rgb(192, 196, 204);
}
.tip-container {
padding: 0 13px;
margin-top: 30px;
display: flex;
flex-direction: column;
gap: 4px;
}
</style>