From 6e3b63c1e40163512004304b15f46c44670872df Mon Sep 17 00:00:00 2001 From: "lj7788@126.com" Date: Wed, 3 Sep 2025 15:36:22 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E8=80=83=E5=8B=A4-=E8=80=83?= =?UTF-8?q?=E5=8B=A4=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yanzhu-bigscreen/public/index.html | 2 +- .../src/views/bim/briefingTools.js | 2 +- yanzhu-bigscreen/src/views/bimBriefing.vue | 2 +- .../domain/ProMobileAttendanceData.java | 187 +++++++++++ .../mapper/ProMobileAttendanceDataMapper.java | 61 ++++ .../manage/ProMobileAttendanceDataMapper.xml | 121 +++++++ .../ProMobileAttendanceConfigController.java | 12 + .../IProMobileAttendanceDataService.java | 61 ++++ .../ProMobileAttendanceDataServiceImpl.java | 100 ++++++ .../miniprogram/images/svg/signal.svg | 1 + .../mobile_attendance/attendance/add/index.js | 294 ++++++++++++++++++ .../attendance/add/index.wxml | 71 ++++- .../attendance/add/index.wxss | 78 ++++- .../attendance/list/index.js | 47 ++- .../attendance/list/index.wxml | 7 +- .../attendance/list/index.wxss | 21 ++ yanzhu-ui-vue3/index.html | 2 +- 17 files changed, 1044 insertions(+), 25 deletions(-) create mode 100644 yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/ProMobileAttendanceData.java create mode 100644 yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/mapper/ProMobileAttendanceDataMapper.java create mode 100644 yanzhu-common/yanzhu-common-mapper/src/main/resources/mapper/manage/ProMobileAttendanceDataMapper.xml create mode 100644 yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/IProMobileAttendanceDataService.java create mode 100644 yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/impl/ProMobileAttendanceDataServiceImpl.java create mode 100644 yanzhu-ui-app/miniprogram/images/svg/signal.svg diff --git a/yanzhu-bigscreen/public/index.html b/yanzhu-bigscreen/public/index.html index 081a3048..7007aee0 100644 --- a/yanzhu-bigscreen/public/index.html +++ b/yanzhu-bigscreen/public/index.html @@ -16,7 +16,7 @@ diff --git a/yanzhu-bigscreen/src/views/bim/briefingTools.js b/yanzhu-bigscreen/src/views/bim/briefingTools.js index 907e3d99..1966768b 100644 --- a/yanzhu-bigscreen/src/views/bim/briefingTools.js +++ b/yanzhu-bigscreen/src/views/bim/briefingTools.js @@ -293,13 +293,13 @@ function initClientClipping(that) { } //剖切 -- 服务端渲染 function initClipping(that) { + let api = bimBriefingApi; api.Public.clearHandler(); api.Measurement.clearAllTrace(); if(that.isClient){ initClientClipping(that); return; } - let api = bimBriefingApi; api.Model.clipByBox(getModels(that)); } diff --git a/yanzhu-bigscreen/src/views/bimBriefing.vue b/yanzhu-bigscreen/src/views/bimBriefing.vue index 98a1fda6..dd575c9d 100644 --- a/yanzhu-bigscreen/src/views/bimBriefing.vue +++ b/yanzhu-bigscreen/src/views/bimBriefing.vue @@ -370,7 +370,7 @@ export default { }, doSelectMenu(index) { this.selectMenu = index; - if (index == 0) { + if (index == this.selectMenu) { briefingTools.clearEvent(this); this.showClipping = false; briefingTools.clearSelectFeature(this); diff --git a/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/ProMobileAttendanceData.java b/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/ProMobileAttendanceData.java new file mode 100644 index 00000000..5f139c68 --- /dev/null +++ b/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/domain/ProMobileAttendanceData.java @@ -0,0 +1,187 @@ +package com.yanzhu.manage.domain; + +import java.math.BigDecimal; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.yanzhu.common.core.annotation.Excel; +import com.yanzhu.common.core.web.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + + +/** + * 移动考勤记录对象 pro_mobile_attendance_data + * + * @author yanzhu + * @date 2025-09-03 + */ +public class ProMobileAttendanceData extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** $column.columnComment */ + private Long id; + + /** 用户ID */ + @Excel(name = "用户ID") + private Long userId; + + /** 项目ID */ + @Excel(name = "项目ID") + private Long projectId; + + /** 配置ID */ + @Excel(name = "配置ID") + private Long cfgId; + + /** 进还是出 */ + @Excel(name = "进还是出") + private String inOut; + + /** 经度 */ + @Excel(name = "经度") + private BigDecimal longitude; + + /** 纬度 */ + @Excel(name = "纬度") + private BigDecimal latitude; + + /** 考勤时间 */ + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "考勤时间", width = 30, dateFormat = "yyyy-MM-dd") + private Date attDate; + + /** 考勤照片 */ + @Excel(name = "考勤照片") + private String attImg; + + /** $column.columnComment */ + @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") + private Long isDel; + + /** $column.columnComment */ + @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") + private Long state; + + public void setId(Long id) + { + this.id = id; + } + + public Long getId() + { + return id; + } + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getUserId() + { + return userId; + } + public void setProjectId(Long projectId) + { + this.projectId = projectId; + } + + public Long getProjectId() + { + return projectId; + } + public void setCfgId(Long cfgId) + { + this.cfgId = cfgId; + } + + public Long getCfgId() + { + return cfgId; + } + public void setInOut(String inOut) + { + this.inOut = inOut; + } + + public String getInOut() + { + return inOut; + } + public void setLongitude(BigDecimal longitude) + { + this.longitude = longitude; + } + + public BigDecimal getLongitude() + { + return longitude; + } + public void setLatitude(BigDecimal latitude) + { + this.latitude = latitude; + } + + public BigDecimal getLatitude() + { + return latitude; + } + public void setAttDate(Date attDate) + { + this.attDate = attDate; + } + + public Date getAttDate() + { + return attDate; + } + public void setAttImg(String attImg) + { + this.attImg = attImg; + } + + public String getAttImg() + { + return attImg; + } + public void setIsDel(Long isDel) + { + this.isDel = isDel; + } + + public Long getIsDel() + { + return isDel; + } + public void setState(Long state) + { + this.state = state; + } + + public Long getState() + { + return state; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("userId", getUserId()) + .append("projectId", getProjectId()) + .append("cfgId", getCfgId()) + .append("inOut", getInOut()) + .append("longitude", getLongitude()) + .append("latitude", getLatitude()) + .append("attDate", getAttDate()) + .append("attImg", getAttImg()) + .append("isDel", getIsDel()) + .append("remark", getRemark()) + .append("state", getState()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .toString(); + } +} diff --git a/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/mapper/ProMobileAttendanceDataMapper.java b/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/mapper/ProMobileAttendanceDataMapper.java new file mode 100644 index 00000000..90eb71b3 --- /dev/null +++ b/yanzhu-common/yanzhu-common-mapper/src/main/java/com/yanzhu/manage/mapper/ProMobileAttendanceDataMapper.java @@ -0,0 +1,61 @@ +package com.yanzhu.manage.mapper; + +import java.util.List; +import com.yanzhu.manage.domain.ProMobileAttendanceData; + +/** + * 移动考勤记录Mapper接口 + * + * @author yanzhu + * @date 2025-09-03 + */ +public interface ProMobileAttendanceDataMapper +{ + /** + * 查询移动考勤记录 + * + * @param id 移动考勤记录主键 + * @return 移动考勤记录 + */ + public ProMobileAttendanceData selectProMobileAttendanceDataById(Long id); + + /** + * 查询移动考勤记录列表 + * + * @param proMobileAttendanceData 移动考勤记录 + * @return 移动考勤记录集合 + */ + public List selectProMobileAttendanceDataList(ProMobileAttendanceData proMobileAttendanceData); + + /** + * 新增移动考勤记录 + * + * @param proMobileAttendanceData 移动考勤记录 + * @return 结果 + */ + public int insertProMobileAttendanceData(ProMobileAttendanceData proMobileAttendanceData); + + /** + * 修改移动考勤记录 + * + * @param proMobileAttendanceData 移动考勤记录 + * @return 结果 + */ + public int updateProMobileAttendanceData(ProMobileAttendanceData proMobileAttendanceData); + + /** + * 删除移动考勤记录 + * + * @param id 移动考勤记录主键 + * @return 结果 + */ + public int deleteProMobileAttendanceDataById(Long id); + + /** + * 批量删除移动考勤记录 + * + * @param ids 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteProMobileAttendanceDataByIds(Long[] ids); +} diff --git a/yanzhu-common/yanzhu-common-mapper/src/main/resources/mapper/manage/ProMobileAttendanceDataMapper.xml b/yanzhu-common/yanzhu-common-mapper/src/main/resources/mapper/manage/ProMobileAttendanceDataMapper.xml new file mode 100644 index 00000000..bc10dd24 --- /dev/null +++ b/yanzhu-common/yanzhu-common-mapper/src/main/resources/mapper/manage/ProMobileAttendanceDataMapper.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + select id, user_id, project_id, cfg_id, in_out, longitude, latitude, att_date, att_img, is_del, remark, state, create_by, create_time, update_by, update_time from pro_mobile_attendance_data + + + + + + + + insert into pro_mobile_attendance_data + + user_id, + project_id, + cfg_id, + in_out, + longitude, + latitude, + att_date, + att_img, + is_del, + remark, + state, + create_by, + create_time, + update_by, + update_time, + + + #{userId}, + #{projectId}, + #{cfgId}, + #{inOut}, + #{longitude}, + #{latitude}, + #{attDate}, + #{attImg}, + #{isDel}, + #{remark}, + #{state}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + + + + + update pro_mobile_attendance_data + + user_id = #{userId}, + project_id = #{projectId}, + cfg_id = #{cfgId}, + in_out = #{inOut}, + longitude = #{longitude}, + latitude = #{latitude}, + att_date = #{attDate}, + att_img = #{attImg}, + is_del = #{isDel}, + remark = #{remark}, + state = #{state}, + create_by = #{createBy}, + create_time = #{createTime}, + update_by = #{updateBy}, + update_time = #{updateTime}, + + where id = #{id} + + + + delete from pro_mobile_attendance_data where id = #{id} + + + + delete from pro_mobile_attendance_data where id in + + #{id} + + + \ No newline at end of file diff --git a/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/controller/remoteAttendance/ProMobileAttendanceConfigController.java b/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/controller/remoteAttendance/ProMobileAttendanceConfigController.java index 04d4e2d6..8f326348 100644 --- a/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/controller/remoteAttendance/ProMobileAttendanceConfigController.java +++ b/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/controller/remoteAttendance/ProMobileAttendanceConfigController.java @@ -113,4 +113,16 @@ public class ProMobileAttendanceConfigController extends BaseController { return toAjax(proMobileAttendanceConfigService.deleteProMobileAttendanceConfigByIds(ids)); } + + /** + * 移动考勤 + */ + @RequiresPermissions("manage:mobileAttendConfig:add") + @PostMapping("/attendance") + public AjaxResult attendance(@RequestBody ProMobileAttendanceConfig cfg){ + //根据用户上传的照片与用户信息的照片计算相似度 + //增加考勤数据 + //增加考勤历史记录 + return AjaxResult.success("OK"); + } } diff --git a/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/IProMobileAttendanceDataService.java b/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/IProMobileAttendanceDataService.java new file mode 100644 index 00000000..cc06bfaa --- /dev/null +++ b/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/IProMobileAttendanceDataService.java @@ -0,0 +1,61 @@ +package com.yanzhu.manage.service; + +import java.util.List; +import com.yanzhu.manage.domain.ProMobileAttendanceData; + +/** + * 移动考勤记录Service接口 + * + * @author yanzhu + * @date 2025-09-03 + */ +public interface IProMobileAttendanceDataService +{ + /** + * 查询移动考勤记录 + * + * @param id 移动考勤记录主键 + * @return 移动考勤记录 + */ + public ProMobileAttendanceData selectProMobileAttendanceDataById(Long id); + + /** + * 查询移动考勤记录列表 + * + * @param proMobileAttendanceData 移动考勤记录 + * @return 移动考勤记录集合 + */ + public List selectProMobileAttendanceDataList(ProMobileAttendanceData proMobileAttendanceData); + + /** + * 新增移动考勤记录 + * + * @param proMobileAttendanceData 移动考勤记录 + * @return 结果 + */ + public int insertProMobileAttendanceData(ProMobileAttendanceData proMobileAttendanceData); + + /** + * 修改移动考勤记录 + * + * @param proMobileAttendanceData 移动考勤记录 + * @return 结果 + */ + public int updateProMobileAttendanceData(ProMobileAttendanceData proMobileAttendanceData); + + /** + * 批量删除移动考勤记录 + * + * @param ids 需要删除的移动考勤记录主键集合 + * @return 结果 + */ + public int deleteProMobileAttendanceDataByIds(Long[] ids); + + /** + * 删除移动考勤记录信息 + * + * @param id 移动考勤记录主键 + * @return 结果 + */ + public int deleteProMobileAttendanceDataById(Long id); +} diff --git a/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/impl/ProMobileAttendanceDataServiceImpl.java b/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/impl/ProMobileAttendanceDataServiceImpl.java new file mode 100644 index 00000000..3b4afd49 --- /dev/null +++ b/yanzhu-modules/yanzhu-manage/src/main/java/com/yanzhu/manage/service/impl/ProMobileAttendanceDataServiceImpl.java @@ -0,0 +1,100 @@ +package com.yanzhu.manage.service.impl; + +import java.util.List; + +import com.yanzhu.common.core.context.SecurityContextHolder; +import com.yanzhu.common.core.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.yanzhu.manage.mapper.ProMobileAttendanceDataMapper; +import com.yanzhu.manage.domain.ProMobileAttendanceData; +import com.yanzhu.manage.service.IProMobileAttendanceDataService; + +/** + * 移动考勤记录Service业务层处理 + * + * @author yanzhu + * @date 2025-09-03 + */ +@Service +public class ProMobileAttendanceDataServiceImpl implements IProMobileAttendanceDataService +{ + @Autowired + private ProMobileAttendanceDataMapper proMobileAttendanceDataMapper; + + /** + * 查询移动考勤记录 + * + * @param id 移动考勤记录主键 + * @return 移动考勤记录 + */ + @Override + public ProMobileAttendanceData selectProMobileAttendanceDataById(Long id) + { + return proMobileAttendanceDataMapper.selectProMobileAttendanceDataById(id); + } + + /** + * 查询移动考勤记录列表 + * + * @param proMobileAttendanceData 移动考勤记录 + * @return 移动考勤记录 + */ + @Override + public List selectProMobileAttendanceDataList(ProMobileAttendanceData proMobileAttendanceData) + { + return proMobileAttendanceDataMapper.selectProMobileAttendanceDataList(proMobileAttendanceData); + } + + /** + * 新增移动考勤记录 + * + * @param proMobileAttendanceData 移动考勤记录 + * @return 结果 + */ + @Override + public int insertProMobileAttendanceData(ProMobileAttendanceData proMobileAttendanceData) + { + proMobileAttendanceData.setCreateBy(SecurityContextHolder.getUserName()); + proMobileAttendanceData.setCreateTime(DateUtils.getNowDate()); + return proMobileAttendanceDataMapper.insertProMobileAttendanceData(proMobileAttendanceData); + } + + /** + * 修改移动考勤记录 + * + * @param proMobileAttendanceData 移动考勤记录 + * @return 结果 + */ + @Override + public int updateProMobileAttendanceData(ProMobileAttendanceData proMobileAttendanceData) + { + proMobileAttendanceData.setUpdateBy(SecurityContextHolder.getUserName()); + proMobileAttendanceData.setUpdateTime(DateUtils.getNowDate()); + return proMobileAttendanceDataMapper.updateProMobileAttendanceData(proMobileAttendanceData); + } + + /** + * 批量删除移动考勤记录 + * + * @param ids 需要删除的移动考勤记录主键 + * @return 结果 + */ + @Override + public int deleteProMobileAttendanceDataByIds(Long[] ids) + { + return proMobileAttendanceDataMapper.deleteProMobileAttendanceDataByIds(ids); + } + + /** + * 删除移动考勤记录信息 + * + * @param id 移动考勤记录主键 + * @return 结果 + */ + @Override + public int deleteProMobileAttendanceDataById(Long id) + { + return proMobileAttendanceDataMapper.deleteProMobileAttendanceDataById(id); + } +} diff --git a/yanzhu-ui-app/miniprogram/images/svg/signal.svg b/yanzhu-ui-app/miniprogram/images/svg/signal.svg new file mode 100644 index 00000000..d0602752 --- /dev/null +++ b/yanzhu-ui-app/miniprogram/images/svg/signal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/add/index.js b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/add/index.js index 8156faf5..cca700c6 100644 --- a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/add/index.js +++ b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/add/index.js @@ -1,6 +1,9 @@ +import fmt from "../../../utils/date.js"; import { getToken, getUserInfo } from "../../../../utils/auth.js"; +import { securityFileUpload } from "../../../../utils/request.js"; // 导入文件上传工具 const app = getApp(); import { getMobileAttendanceConfigById } from "../../../../api/project.js"; +import { calculateDistance } from "../../../../utils/location.js"; // 导入计算距离的工具函数 Page({ /** @@ -15,6 +18,10 @@ Page({ type: "", cfgData: null, arrSel: "in", + mapMarkers: [], // 地图标记 + mapCircles: [], // 地图圆圈(用于显示考勤范围) + faceImage: "", // 人脸识别图片 + faceImageUrl: "", // 上传后的人脸图片URL }, /** @@ -54,10 +61,14 @@ Page({ 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(); @@ -67,7 +78,284 @@ Page({ 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: 30, + height: 30, + 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/location-marker.png", // 使用项目中已有的图标文件 + width: 30, + height: 30, + 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() { + debugger; + if (!this.data.faceImage) { + app.toast("未获取到照片!"); + return; + } + // 获取当前位置并计算距离 + this.getCurrentLocationAndCalculateDistance(); + }, + + // 获取当前位置并计算距离 + getCurrentLocationAndCalculateDistance() { + wx.getLocation({ + type: "gcj02", // 使用国测局坐标系 + success: (res) => { + const { longitude, latitude } = res; + const cfgData = this.data.cfgData; + + // 使用现有的工具函数计算距离 + const distance = calculateDistance( + longitude, + latitude, + cfgData.longitude, + cfgData.latitude + ); + + // 检查是否超出考勤范围 + if (distance > cfgData.range) { + app.toast("超出考勤范围!"); + return; + } + + // 更新考勤数据的位置信息 + this.setData( + { + "cfgData.attLongitude": longitude, + "cfgData.attLatitude": latitude, + }, + () => { + // 在数据更新完成后,更新地图上的用户位置标记 + this.updateUserLocationMarker(longitude, latitude); + } + ); + + // 继续执行打卡操作 + this.uploadFaceImage(() => { + console.log(this.data.faceImageUrl); + debugger; + }); + }, + fail: (err) => { + console.error("获取位置失败", err); + // 检查是否是权限问题 + if (err.errMsg && err.errMsg.includes("auth deny")) { + app.toast("请开启位置权限后再试"); + // 引导用户开启权限 + wx.showModal({ + title: "提示", + content: + "需要获取您的位置信息才能进行考勤打卡,请在设置中开启位置权限", + showCancel: true, + confirmText: "去设置", + success: (res) => { + if (res.confirm) { + wx.openSetting({ + success: (setting) => { + if (setting.authSetting["scope.userLocation"]) { + // 用户开启了权限,重新获取位置 + this.getCurrentLocationAndCalculateDistance(); + } + }, + }); + } + }, + }); + } else { + app.toast("获取位置失败,请检查定位权限"); + } + }, + }); + }, + + // 更新用户位置标记 + 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: 30, + height: 30, + callout: { + content: "当前位置", + display: "ALWAYS", + fontSize: 12, + borderRadius: 5, + padding: 5, + }, + }; + + if (userMarkerIndex !== -1) { + // 如果已存在用户位置标记,则更新它 + markers[userMarkerIndex] = userMarker; + } else { + // 如果不存在用户位置标记,则添加它 + markers.push(userMarker); + } + + // 更新地图标记 + this.setData({ + mapMarkers: markers, + }); + }, + + getDistance(longitude, latitude) { + // 获取当前位置计算距离 + // 这里直接计算给定坐标与考勤地点的距离 + const cfgData = this.data.cfgData; + if (!cfgData) return 0; + return calculateDistance( + longitude, + latitude, + cfgData.longitude, + cfgData.latitude + ); + }, onProjectSelect(e) { let projectId = e.detail.id; let projectName = e.detail.text; @@ -80,4 +368,10 @@ Page({ url: "../list/index", }); }, + doSelectArr(e) { + this.setData({ + arrSel: e.currentTarget.dataset.set, + "cfgData.attDate": fmt(new Date()).format("YYYY-MM-DD HH:mm:ss"), + }); + }, }); diff --git a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/add/index.wxml b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/add/index.wxml index d0f32eec..a6e058da 100644 --- a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/add/index.wxml +++ b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/add/index.wxml @@ -17,20 +17,65 @@ - - - - 请选择考勤方向 + + + + 请选择考勤方向 + + + + + 上班考勤打卡 - - - - 上班考勤打卡 - - - - 下班考勤打卡 - + + + 下班考勤打卡 + + + + + + 考勤信息 + + + + 考勤标题: + {{cfgData.title}} + + + 考勤时间: + {{cfgData.attDate}} + + + 考勤位置: + {{cfgData.attAddress}} + + + + + + + + + + + + 考勤人像刷脸 + + + + 拍照后显示图片 + + + + + + 打卡 + + 返回 + + \ No newline at end of file diff --git a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/add/index.wxss b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/add/index.wxss index 90c858bf..b6165d4c 100644 --- a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/add/index.wxss +++ b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/add/index.wxss @@ -4,19 +4,26 @@ .content_box_title{ display: flex; align-items: center; + margin-bottom: 20rpx; +} +.content_box_title text{ + margin-left:10rpx; } - .arrow_content{ display: flex; } .arrow_box{ - background-color: #ccc; + background-color: #626262; width:45%; margin:0 5%; position: relative; - display: flex; - align-items: center; + border-radius: 10rpx; + color: #aaa; +} +.arrow_box.is-active{ + background-color: #37BBDE; + color:#000; } .arrow_box .img-sel{ position: absolute; @@ -26,6 +33,65 @@ } .arrow_box view{ - height: 120rpx; - line-height: 120rpx; + height: 160rpx; + line-height: 160rpx; + width:100% ; + text-align: center; +} + +/* 地图样式 */ +#attendanceMap { + width: 100%; + height: 300rpx; + border-radius: 10rpx; +} +.box_row{ + display: flex; + line-height: 50rpx; +} +.att-info{ + padding-left:40rpx; +} +.att-info .row-content{ + padding-left:10rpx; +} +.box_map{ + margin-top: 20rpx; +} +/* 人脸识别区域样式 */ +.att-img { + display: flex; + flex-direction: column; + align-items: center; + padding: 20rpx 0; +} + +.att-img image { + width: 400rpx; + height: 400rpx; + margin-bottom: 20rpx; + border-radius: 10rpx; + background-color: #1E2737; +} + +.att-img .placeholder-text { + width: 400rpx; + height: 400rpx; + margin-bottom: 20rpx; + border-radius: 10rpx; + background-color: #1E2737; + display: flex; + align-items: center; + justify-content: center; + color: #999; + font-size: 24rpx; +} + +.att-img button { + background-color: #07C160; + color: white; + border: none; + padding: 20rpx 20rpx; + border-radius: 10rpx; + font-size: 28rpx; } \ No newline at end of file diff --git a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/list/index.js b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/list/index.js index 646fb50a..a307dff4 100644 --- a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/list/index.js +++ b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/list/index.js @@ -17,6 +17,7 @@ Page({ listData: [], userLongitude: undefined, userLatitude: undefined, + currentAddress: "", // 当前位置地址 pageNum: 1, pageSize: 10, }, @@ -48,6 +49,7 @@ Page({ * 获取用户当前位置 */ getUserLocation() { + debugger; wx.getLocation({ type: "gcj02", // 使用国测局坐标 success: (res) => { @@ -55,7 +57,21 @@ Page({ userLongitude: res.longitude, userLatitude: res.latitude, }); - this.getListData(); + // 获取当前位置的地址信息 + this.getCurrentAddress(res.longitude, res.latitude) + .then((address) => { + this.setData({ + currentAddress: address, + }); + this.getListData(); + }) + .catch((err) => { + console.error("获取当前位置地址失败", err); + this.setData({ + currentAddress: "地址获取失败", + }); + this.getListData(); + }); }, fail: (err) => { console.error("获取位置失败", err); @@ -86,6 +102,9 @@ Page({ it.longitude, it.latitude ); + it.attLongitude = this.data.userLongitude; + it.attLatitude = this.data.userLatitude; + it.attAddress = this.data.currentAddress; } else { it.distance = -1; // 无法计算距离 } @@ -98,6 +117,32 @@ Page({ } }); }, + getCurrentAddress(longitude, latitude) { + // 使用腾讯地图API获取地址信息 + const apiKey = "NUQBZ-UIYCW-H7GRI-YXOXA-WNZB7-IGFLY"; // 使用项目中已有的API密钥 + const url = `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=${apiKey}&get_poi=1`; + + return new Promise((resolve, reject) => { + wx.request({ + url: url, + method: "GET", + success: (res) => { + if (res.statusCode === 200 && res.data.status === 0) { + // 成功获取地址信息 + const address = res.data.result.address || "未知地址"; + resolve(address); + } else { + // API调用失败 + reject(new Error(res.data.message || "获取地址失败")); + } + }, + fail: (err) => { + // 网络请求失败 + reject(new Error("网络请求失败")); + }, + }); + }); + }, getInfo(e) { let cfgData = e.currentTarget.dataset.set; wx.setStorageSync("editAttCfg", cfgData); diff --git a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/list/index.wxml b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/list/index.wxml index 11f12876..d5cd6c3e 100644 --- a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/list/index.wxml +++ b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/list/index.wxml @@ -19,11 +19,11 @@ + 生效中的考勤点({{total}}) - @@ -72,6 +72,11 @@ + + + 当前位置: + {{item.attAddress}} + diff --git a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/list/index.wxss b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/list/index.wxss index c1842a31..696a4ef8 100644 --- a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/list/index.wxss +++ b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance/list/index.wxss @@ -29,4 +29,25 @@ .module_title{ flex-grow: 1; text-align: right; +} + +/* 用户位置信息样式 */ +.user-location-info { + background-color: #f0f8ff; + padding: 20rpx 30rpx; + margin: 20rpx 30rpx; + border-radius: 10rpx; + border: 1px solid #45affb; +} + +.location-title { + font-weight: bold; + color: #45affb; + margin-bottom: 10rpx; +} + +.location-address { + font-size: 26rpx; + color: #333; + word-wrap: break-word; } \ No newline at end of file diff --git a/yanzhu-ui-vue3/index.html b/yanzhu-ui-vue3/index.html index 12dbfe52..a9cb0a38 100644 --- a/yanzhu-ui-vue3/index.html +++ b/yanzhu-ui-vue3/index.html @@ -15,7 +15,7 @@ 数字建安施工