SmailParks_visitoer_H5/pages/sys/msg/index.vue
2025-08-14 14:27:26 +08:00

638 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>
<scroll-view class="container" scroll-y>
<view class="form-card">
<view class="form-title">访客预约表单</view>
<!-- 基本信息 -->
<view class="section-title">基本信息</view>
<view class="form-item">
<text class="label required">访客姓名</text>
<view class="input-wrapper">
<input type="text" placeholder="请输入您的姓名" v-model="formData.visitorName" />
</view>
</view>
<view class="form-item">
<text class="label">所属公司</text>
<view class="input-wrapper">
<input type="text" placeholder="请输入您的公司名称" v-model="formData.visitorUnit" />
</view>
</view>
<view class="form-item">
<text class="label required">联系电话</text>
<view class="input-wrapper">
<input type="number" placeholder="请输入您的手机号码" v-model="formData.visitorPhone" />
</view>
</view>
<view class="form-item">
<text class="label required">拜访事由</text>
<view class="input-wrapper">
<input type="text" placeholder="请简要描述拜访目的" v-model="formData.visitingReason" />
</view>
</view>
<!-- 被访人信息 -->
<view class="section-title">被访人信息</view>
<view class="form-item">
<text class="label">被访人姓名</text>
<view class="input-wrapper">
<input type="text" placeholder="请输入被访人姓名" v-model="formData.interviewedPerson" />
</view>
</view>
<view class="form-item">
<text class="label">被访单位</text>
<view class="input-wrapper">
<input type="text" placeholder="请输入被访单位名称" v-model="formData.interviewedUnit" />
</view>
</view>
<view class="form-item">
<text class="label">被访人电话</text>
<view class="input-wrapper">
<input type="number" placeholder="请输入被访人联系电话" v-model="formData.interviewedPhone" />
</view>
</view>
<!-- 拜访时间 -->
<view class="section-title">拜访时间</view>
<view class="form-item">
<text class="label">开始时间</text>
<view class="picker-wrapper">
<picker mode="date" :value="formData.visitingBeginDate" start="2020-01-01" end="2030-12-31"
@change="onBeginDateChange">
<view class="picker-value">{{formData.visitingBeginDate}}</view>
</picker>
</view>
<view class="picker-wrapper time-picker">
<picker mode="time" :value="formData.visitingBeginTime" @change="onBeginTimeChange">
<view class="picker-value">{{formData.visitingBeginTime}}</view>
</picker>
</view>
</view>
<view class="form-item">
<text class="label">结束时间</text>
<view class="picker-wrapper">
<picker mode="date" :value="formData.visitingEndDate" start="2020-01-01" end="2030-12-31"
@change="onEndDateChange">
<view class="picker-value">{{formData.visitingEndDate}}</view>
</picker>
</view>
<view class="picker-wrapper time-picker">
<picker mode="time" :value="formData.visitingEndTime" @change="onEndTimeChange">
<view class="picker-value">{{formData.visitingEndTime}}</view>
</picker>
</view>
</view>
<!-- 预约信息 -->
<!-- <view class="section-title">预约信息</view>
<view class="form-item">
<text class="label">预约车位</text>
<view class="picker-wrapper">
<picker mode="selector" :range="parkingOptions" @change="handleParkingChange">
<view class="picker-value">{{formData.bookingParkingSpace ? '需要' : '不需要'}}</view>
</picker>
</view>
</view> -->
<!-- 条件显示:预约车位时显示车牌号 -->
<!-- <view class="form-item" v-if="formData.bookingParkingSpace">
<text class="label required">车牌号</text>
<view class="input-wrapper">
<input type="text" placeholder="请输入车牌号" v-model="formData.licensePlate" />
</view>
</view> -->
<view class="form-item">
<text class="label required">人脸照片</text>
<view class="upload-wrapper">
<view class="upload-btn" @click="takePhoto">
<text class="upload-text">+ 拍照上传</text>
</view>
<view class="preview-image" v-if="formData.facePictures">
<image :src="formData.facePictures" mode="aspectFill" @click="delimg"></image>
</view>
</view>
</view>
<!-- <view class="form-item">
<text class="label">预约状态</text>
<view class="picker-wrapper">
<picker mode="selector" :range="statusOptions" @change="handleStatusChange">
<view class="picker-value">{{statusMap[formData.serveStatus]}}</view>
</picker>
</view>
</view> -->
<!-- 提交按钮 -->
<view class="submit-wrapper">
<button class="submit-btn" @click="submitForm">确认提交</button>
</view>
</view>
</scroll-view>
</template>
<script>
export default {
data() {
const now = new Date();
const date = now.getFullYear() + '-' +
(now.getMonth() + 1).toString().padStart(2, '0') + '-' +
now.getDate().toString().padStart(2, '0');
const time = now.getHours().toString().padStart(2, '0') + ':' +
now.getMinutes().toString().padStart(2, '0');
return {
formData: {
visitorName: '1',
visitorUnit: '1',
visitorPhone: '15555555555',
visitingReason: '1',
interviewedPerson: '1',
interviewedUnit: '1',
interviewedPhone: '15555555555',
visitingBeginDate: date,
visitingBeginTime: time,
visitingEndDate: date,
visitingEndTime: time,
bookingParkingSpace: false,
licensePlate: '',
facePictures: '',
serveStatus: 0
},
parkingOptions: ['不需要', '需要'],
statusOptions: ['待确认', '已确认', '已取消', '已完成'],
statusMap: {
0: '待确认',
1: '已确认',
2: '已取消',
3: '已完成'
}
}
},
onLoad(options) {
// 新增获取url中的code参数并打印
if (options.code) {
console.log('从URL中获取到的code参数', options.code);
let p = {};
p.qrcode = options.code
this.formData.qrCodeId = options.code;
this.$u.api.codesub(p).then(res => {
console.log(res)
})
} else {
console.log('URL中未包含code参数');
uni.showToast({
title: '二维码失效,请重新扫描',
icon: 'success',
duration: 2000
});
}
// #ifdef APP-PLUS
plus.screen.lockOrientation('default');
// #endif
},
onReady() {
// #ifdef APP-PLUS
plus.screen.lockOrientation('landscape-primary');
// #endif
},
methods: {
// 处理日期时间选择
onBeginDateChange(e) {
this.formData.visitingBeginDate = e.detail.value;
},
onBeginTimeChange(e) {
this.formData.visitingBeginTime = e.detail.value;
},
onEndDateChange(e) {
this.formData.visitingEndDate = e.detail.value;
},
onEndTimeChange(e) {
this.formData.visitingEndTime = e.detail.value;
},
// 处理车位预约选择
// handleParkingChange(e) {
// this.formData.bookingParkingSpace = e.detail.value === 1;
// if (!this.formData.bookingParkingSpace) {
// this.formData.licensePlate = '';
// }
// },
// 处理状态选择
handleStatusChange(e) {
this.formData.serveStatus = e.detail.value;
},
// 拍照
takePhoto() {
uni.chooseImage({
count: 1,
sourceType: ['camera'], // 只允许使用相机
success: (res) => {
// console.log(res.tempFilePaths[0])
this.formData.facePictures = res.tempFilePaths[0];
},
fail: (err) => {
uni.showToast({
title: '拍照失败',
icon: 'none'
});
}
});
},
// 表单验证
validateForm() {
const {
qrCodeId,
visitorName,
visitorUnit,
visitorPhone,
visitingReason,
interviewedPerson,
bookingParkingSpace,
licensePlate,
facePictures,
visitingBeginDate,
visitingBeginTime,
visitingEndDate,
visitingEndTime
} = this.formData;
// 验证姓名
if (!visitorName) {
return '请输入访客姓名';
}
// 验证公司
if (!visitorUnit) {
return '请输入所属公司';
}
// 验证电话
if (!visitorPhone) {
return '请输入联系电话';
}
// 简单的手机号格式验证
if (!/^1[3-9]\d{9}$/.test(visitorPhone)) {
return '请输入正确的手机号码';
}
// 验证事由
if (!visitingReason) {
return '请输入拜访事由';
}
// 验证被访人
if (!interviewedPerson) {
return '请输入被访人姓名';
}
// 验证车牌号(如果需要预约车位)
// if (bookingParkingSpace && !licensePlate) {
// return '请输入车牌号';
// }
if (!facePictures) {
return '请拍照上传人脸照片';
}
// 验证时间逻辑
const beginDateTime = new Date(`${visitingBeginDate} ${visitingBeginTime}`);
const endDateTime = new Date(`${visitingEndDate} ${visitingEndTime}`);
if (beginDateTime >= endDateTime) {
return '开始时间必须早于结束时间';
}
return ''; // 验证通过
},
// 提交表单
submitForm() {
const errorMsg = this.validateForm();
if (errorMsg) {
uni.showToast({
title: errorMsg,
icon: 'none'
});
return;
}
// 合并日期和时间
this.formData.visitingBeginTime = `${this.formData.visitingBeginDate} ${this.formData.visitingBeginTime}`;
this.formData.visitingEndTime = `${this.formData.visitingEndDate} ${this.formData.visitingEndTime}`;
// 准备提交数据
const submitData = {
...this.formData,
bookingParkingSpace: this.formData.bookingParkingSpace ? 0 : 1
};
console.log(submitData)
// 显示加载提示
uni.showLoading({
title: '提交中...',
mask: true
});
// 模拟API请求
setTimeout(() => {
uni.request({url:this.formData.facePictures})
// .then(response => response.blob())
.then(blob => {
// 此时得到了原始Blob对象
console.log(blob);
const file = new File([blob], 'filename.png', {
type: blob.type
});
// 构建FormData进行上传
const formData = new FormData();
formData.append('file', file);
console.log(formData)
// 发送上传请求
// this.$u.api.uploadimg()
// 接上面的代码假设Blob是图片类型
uni.uploadFile({
url: 'http://183.230.235.66:11010/api/resource/oss/qrupload', // 后端上传接口地址
filePath: file.filePath, // 要上传的文件路径
name: 'file', // 后端接收文件的参数名
// FormData中的其他参数
formData: {
'code': this.formData.qrCodeId // 示例:其他表单字段
},
// 上传进度回调
onProgressUpdate: (res) => {
this.progress = res.progress;
console.log('上传进度:' + res.progress);
},
// 上传成功回调
success: (res) => {
console.log('上传成功', res);
this.uploadResult = res.data;
uni.showToast({
title: '上传成功',
icon: 'success'
});
},
// 上传失败回调
fail: (err) => {
console.error('上传失败', err);
uni.showToast({
title: '上传失败',
icon: 'none'
});
},
// 无论成功失败都会执行
complete: () => {
this.progress = 0; // 重置进度
}
});
// this.$u.api.uploadimg(formData).then(res => {
// console.log(res)
// if (res.code == 200) {
// uni.showToast({
// title: "提交成功,请等待审核!",
// icon: "success"
// })
// } else {
// uni.showToast({
// title: "tp提交失败",
// icon: "error"
// })
// }
// })
});
this.$u.api.fksub(submitData).then(res => {
console.log(res)
if (res.code == 200) {
uni.showToast({
title: "提交成功,请等待审核!",
icon: "success"
})
} else {
uni.showToast({
title: "提交失败!",
icon: "error"
})
}
})
uni.hideLoading();
// 显示成功提示
uni.showToast({
title: '提交成功',
icon: 'success',
duration: 2000
});
// 提交成功后,可跳转到成功页面或重置表单
setTimeout(() => {
// 重置表单
this.resetForm();
// 返回到上一页或跳转到其他页面
// uni.navigateBack();
}, 2000);
}, 1500);
},
delimg() {
this.formData.facePictures = ''
},
// 重置表单
resetForm() {
const now = new Date();
const date = now.getFullYear() + '-' +
(now.getMonth() + 1).toString().padStart(2, '0') + '-' +
now.getDate().toString().padStart(2, '0');
const time = now.getHours().toString().padStart(2, '0') + ':' +
now.getMinutes().toString().padStart(2, '0');
this.formData = {
visitorName: '',
visitorUnit: '',
visitorPhone: '',
visitingReason: '',
interviewedPerson: '',
interviewedUnit: '',
interviewedPhone: '',
visitingBeginDate: date,
visitingBeginTime: time,
visitingEndDate: date,
visitingEndTime: time,
bookingParkingSpace: false,
licensePlate: '',
facePictures: '',
serveStatus: 0
};
}
}
}
</script>
<style scoped>
.container {
background-color: #f5f7fa;
min-height: 100vh;
}
.form-card {
background-color: #fff;
border-radius: 12px;
margin: 16px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}
.form-title {
font-size: 20px;
font-weight: bold;
color: #333;
text-align: center;
margin-bottom: 24px;
}
.section-title {
font-size: 16px;
font-weight: 600;
color: #333;
margin-top: 20px;
margin-bottom: 12px;
padding-left: 8px;
border-left: 3px solid #007aff;
}
.form-item {
display: flex;
align-items: center;
margin-bottom: 16px;
}
.label {
width: 96px;
font-size: 14px;
color: #666;
margin-right: 12px;
}
.label.required::before {
content: '*';
color: #ff4d4f;
margin-right: 4px;
}
.input-wrapper {
flex: 1;
height: 40px;
border: 1px solid #e5e6eb;
border-radius: 6px;
padding: 0 12px;
display: flex;
align-items: center;
}
.input-wrapper input {
flex: 1;
height: 100%;
font-size: 14px;
color: #333;
}
.picker-wrapper {
flex: 1;
height: 40px;
border: 1px solid #e5e6eb;
border-radius: 6px;
padding: 0 12px;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
}
.picker-wrapper::after {
content: '';
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 6px solid #999;
position: absolute;
right: 12px;
}
.time-picker {
margin-left: 10px;
}
.picker-value {
font-size: 14px;
color: #333;
flex: 1;
}
.upload-wrapper {
flex: 1;
display: flex;
align-items: center;
}
.upload-btn {
width: 80px;
height: 80px;
background-color: #f5f7fa;
border-radius: 6px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 1px dashed #e5e6eb;
}
.upload-text {
font-size: 12px;
color: #999;
margin-top: 4px;
}
.preview-image {
width: 80px;
height: 80px;
border-radius: 6px;
margin-left: 12px;
overflow: hidden;
border: 1px solid #e5e6eb;
}
.preview-image image {
width: 100%;
height: 100%;
}
.submit-wrapper {
margin-top: 32px;
}
.submit-btn {
width: 100%;
height: 44px;
background-color: #007aff;
color: #fff;
font-size: 16px;
font-weight: 500;
border-radius: 22px;
display: flex;
align-items: center;
justify-content: center;
}
</style>