YZProjectCloud/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/add/index.js

384 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import fmt from "../../../utils/date.js";
import { getToken, getUserInfo } from "../../../../utils/auth.js";
import { securityFileUpload } from "../../../../utils/request.js";
const app = getApp();
import { mobileAttendance } from "../../../../api/project.js";
import { calculateDistance } from "../../../../utils/location.js";
import { checkAndRequestLocationPermission } from "../../../../utils/locationPermission.js"; // 引入位置权限工具函数
import config from "../../../../config.js";
Page({
/**
* 页面的初始数据
*/
data: {
projectUserInfo: {},
projectUserInfo: {},
projectId: "",
projectName: "",
initData: {},
type: "",
cfgData: null,
arrSel: "in",
mapMarkers: [], // 地图标记
mapCircles: [], // 地图圆圈(用于显示考勤范围)
faceImage: "", // 人脸识别图片
faceImageUrl: "", // 上传后的人脸图片URL
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
if (!getToken()) {
wx.redirectTo({
url: "../../../pages/login/login",
});
}
const proUserInfo = getUserInfo();
// 根据当前时间设置arrSel的值14点前为in14点后为out
const now = new Date();
const arrSel = now.getHours() < 14 ? "in" : "out";
this.setData({
projectUserInfo: proUserInfo.projectUserInfo,
projectId: app.globalData.useProjectId,
projectName: app.globalData.useProjectName,
initData: {
id: app.globalData.useProjectId,
text: app.globalData.useProjectName,
},
type: options.type,
arrSel: arrSel,
});
if (options.id) {
this.loadData(options.id);
} else {
app.toast("参数错误!");
this.returnToPage();
}
//todo 14点前 arrSel=in,之后arrSel=out
},
loadData(id) {
try {
let cfgData = wx.getStorageSync("editAttCfg");
cfgData.attDate = fmt(new Date()).format("YYYY-MM-DD HH:mm:ss");
if (cfgData) {
this.setData({
cfgData: cfgData,
});
// 初始化地图标记
this.initMapMarkers(cfgData);
} else {
app.toast("参数错误!");
this.returnToPage();
}
} catch (e) {
app.toast("参数错误!");
this.returnToPage();
}
},
// 初始化地图标记
initMapMarkers(cfgData) {
// 考勤地点标记
const markers = [];
const circles = [];
// 用户当前位置标记(如果有的话)
if (cfgData.attLongitude && cfgData.attLatitude) {
markers.push({
id: 1,
longitude: cfgData.attLongitude,
latitude: cfgData.attLatitude,
title: cfgData.attAddress || "当前位置",
iconPath: "/images/location-marker.png", // 使用项目中已有的图标文件
width: 23,
height: 25,
callout: {
content: cfgData.attAddress || "当前位置",
display: "ALWAYS",
fontSize: 12,
borderRadius: 5,
padding: 5,
},
});
}
// 考勤地点标记和范围圆圈
if (cfgData.longitude && cfgData.latitude) {
// 考勤地点标记
markers.push({
id: 2,
longitude: cfgData.longitude,
latitude: cfgData.latitude,
title: cfgData.address || "考勤地点",
iconPath: "/images/marker_blue.png", // 使用项目中已有的图标文件
width: 20,
height: 32,
callout: {
content: cfgData.address || "考勤地点",
display: "ALWAYS",
fontSize: 12,
borderRadius: 5,
padding: 5,
},
});
// 考勤范围圆圈(如果设置了范围)
if (cfgData.range) {
circles.push({
id: 1,
longitude: cfgData.longitude,
latitude: cfgData.latitude,
radius: cfgData.range, // 范围半径(米)
strokeWidth: 2,
color: "#FF0000", // 红色边框,符合规范
fillColor: "#FF000033", // 带透明度的红色填充,符合规范
});
}
}
this.setData({
mapMarkers: markers,
mapCircles: circles,
});
},
// 打开摄像头进行人脸识别
openCamera() {
const that = this;
wx.chooseMedia({
count: 1,
mediaType: ["image"],
sourceType: ["camera"],
camera: "front", // 前置摄像头
success(res) {
console.log("chooseMedia success", res);
// 获取到图片临时路径
const tempImagePath = res.tempFiles[0].tempFilePath;
console.log("tempImagePath", tempImagePath);
// 在iPhone上可能需要特殊处理图片路径
that.setData(
{
faceImage: tempImagePath,
},
() => {
// setData完成后的回调
console.log("faceImage set successfully");
}
);
// 这里可以添加人脸识别的逻辑
// 由于项目中没有现成的人脸识别API这里只是演示如何获取图片
// 实际项目中可能需要调用后端的人脸识别接口
//that.performFaceRecognition(tempImagePath);
},
fail(err) {
console.error("打开摄像头失败", err);
app.toast("打开摄像头失败,请重试");
},
});
},
// 执行人脸识别(模拟)
performFaceRecognition() {
let imagePath = this.data.faceImage;
// 这里应该调用实际的人脸识别API
// 由于项目中没有现成的人脸识别功能,这里只是模拟
app.toast("正在识别中...");
// 上传图片到服务器
this.uploadFaceImage();
// 模拟识别过程
setTimeout(() => {
// 模拟识别成功
app.toast("人脸识别成功");
// 可以在这里设置识别成功的状态
this.setData({
isFaceRecognized: true,
});
}, 2000);
},
// 上传人脸图片到服务器
uploadFaceImage(cb) {
let imagePath = this.data.faceImage;
app.toast("正在上传图片...");
securityFileUpload(imagePath)
.then((res) => {
console.log("图片上传成功", res);
if (res.code == 200) {
app.toast("图片上传成功");
// 保存上传后的图片URL
this.setData({
faceImageUrl: res.data.url,
});
cb && cb();
} else {
app.toast("图片上传失败: " + res.msg);
}
})
.catch((err) => {
console.error("图片上传失败", err);
app.toast("图片上传失败");
});
},
doSave() {
if (!this.data.faceImage) {
app.toast("未获取到照片!");
return;
}
// 获取当前位置并计算距离
this.getCurrentLocationAndCalculateDistance();
},
// 获取当前位置并计算距离
getCurrentLocationAndCalculateDistance() {
checkAndRequestLocationPermission(
(res) => {
const { longitude, latitude } = res;
const cfgData = this.data.cfgData;
// 使用现有的工具函数计算距离
const distance = calculateDistance(
longitude,
latitude,
cfgData.longitude,
cfgData.latitude
);
// 检查是否超出考勤范围
if (distance > cfgData.range) {
wx.showModal({
title: "考勤范围提醒",
content: `您当前位置距离考勤点${distance}米,已超出${cfgData.range}米的考勤范围,请移动到考勤点范围内再进行打卡。`,
showCancel: false,
confirmText: "我知道了",
});
return;
}
// 更新考勤数据的位置信息
this.setData(
{
"cfgData.attLongitude": longitude,
"cfgData.attLatitude": latitude,
},
() => {
// 在数据更新完成后,更新地图上的用户位置标记
this.updateUserLocationMarker(longitude, latitude);
}
);
// 继续执行打卡操作
this.uploadFaceImage(() => {
this.doSaveAttendance();
});
},
(err) => {
console.error("获取位置失败", err);
wx.showToast({
title: "获取位置失败",
icon: "none",
});
}
);
},
// 更新用户位置标记
updateUserLocationMarker(longitude, latitude) {
// 创建新的标记数组
let markers = [...this.data.mapMarkers];
// 查找是否已存在用户位置标记id为1
let userMarkerIndex = markers.findIndex((marker) => marker.id === 1);
const userMarker = {
id: 1,
longitude: longitude,
latitude: latitude,
title: "当前位置",
iconPath: "/images/location-marker.png",
width: 23,
height: 25,
callout: {
content: "当前位置",
display: "ALWAYS",
fontSize: 12,
borderRadius: 5,
padding: 5,
},
};
if (userMarkerIndex !== -1) {
// 如果已存在用户位置标记,则更新它
markers[userMarkerIndex] = userMarker;
} else {
// 如果不存在用户位置标记,则添加它
markers.push(userMarker);
}
// 更新地图标记
this.setData({
mapMarkers: markers,
});
},
onProjectSelect(e) {
let projectId = e.detail.id;
let projectName = e.detail.text;
app.globalData.useProjectId = projectId;
app.globalData.useProjectName = projectName;
this.onLoad();
},
returnToPage() {
wx.redirectTo({
url: "../list/index",
});
},
doSelectArr(e) {
this.setData({
arrSel: e.currentTarget.dataset.set,
"cfgData.attDate": fmt(new Date()).format("YYYY-MM-DD HH:mm:ss"),
});
},
doSaveAttendance() {
let cfgData = this.data.cfgData;
let postData = {
userPicture: app.globalData.subDeptUserData.userPicture,
userId: app.globalData.subDeptUserData.userId,
projectId: app.globalData.useProjectId,
cfgId: cfgData.id,
inOut: this.data.arrSel,
longitude: cfgData.attLongitude,
latitude: cfgData.attLatitude,
attDate: cfgData.attDate,
attImg: this.data.faceImageUrl,
cfgInfo: cfgData,
basePath: config.baseImgUrl,
};
console.log("考勤数据", postData);
mobileAttendance(postData).then((res) => {
if (res.code == 200) {
app.toast("考勤成功");
this.returnToPage();
} else {
// 显示确认框,提供更友好的错误提示
wx.showModal({
title: "考勤失败",
content: res.msg || "考勤提交失败,请稍后重试",
showCancel: false, // 只显示确定按钮
confirmColor: "#ff0000", // 深色确认按钮
confirmText: "确定",
success: function (res) {
// 用户点击确定按钮后返回考勤列表页面
this.returnToPage();
}.bind(this),
});
}
});
},
});