// pageage/mobile_attendance/attendance_config/add/index.js import { getToken, getUserInfo } from "../../../../utils/auth"; import { uploadFiles } from "../../../utils/upload.js"; import { tryToJson } from "../../../utils/tools"; import { findSubGroupsList, subdeptsList, addMobileAttendanceConfig, } from "../../../../api/project"; import { findDictCache } from "../../../../api/publics"; const app = getApp(); // 添加防抖变量,避免频繁请求API let lastRequestTime = 0; const REQUEST_INTERVAL = 1000; // 1秒间隔 Page({ /** * 页面的初始数据 */ data: { maxDate: new Date(2088, 1, 1).getTime(), minDate: new Date().getTime(), projectUserInfo: {}, projectId: "", projectName: "", initData: {}, form: { title: "", startDate: "", endDate: "", longitude: 0, latitude: 0, range: 50, address: "", subGroup: [], groupIds: "", groupNames: [], }, markers: [], // 全屏地图相关数据 showFullScreenMap: false, mapLongitude: 0, mapLatitude: 0, fullScreenMarkers: [], selectedAddress: "", // 搜索相关数据 searchKeyword: "", searchResults: [], subGroupList: [], groupList: [], subDeptTypeList: [], // 添加成功标识 isAddSuccess: false, }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { if (!getToken()) { wx.redirectTo({ url: "../../../pages/login/login", }); } const proUserInfo = getUserInfo(); this.setData({ projectUserInfo: proUserInfo.projectUserInfo, projectId: app.globalData.useProjectId, projectName: app.globalData.useProjectName, initData: { id: app.globalData.useProjectId, text: app.globalData.useProjectName, }, }); // 获取当前位置作为初始位置 this.getUserLocation(); this.getSubGroupList(); }, getSubGroupList() { findDictCache("sub_dept_type").then((dict) => { this.setData({ subDeptTypeList: dict.data, }); findSubGroupsList({ projectId: app.globalData.useProjectId, pageNum: 1, pageSize: 1000, }).then((res) => { if (res.code == 200) { let tmps = res.rows || []; this.setData({ groupList: tmps, }); let obj = {}; tmps.forEach((it) => { let name = it.subDeptType == 1 ? "施工单位" : it.subDeptName; if (!obj[name]) { obj[name] = [it]; } else { obj[name].push(it); } }); let subGroupList = []; for (let key in obj) { let val = obj[key][0]; let deptType = this.data.subDeptTypeList.find( (dict) => dict.dictValue == val.subDeptType ); subGroupList.push({ subDeptId: val.subDeptId, subDeptName: val.subDeptName, subDeptType: val.subDeptType, subDeptTypeName: deptType?.dictLabel || "", userList: obj[key].map((it) => { it.status = false; it.userId = it.id; it.userName = it.groupName; return it; }), }); } this.setData({ subGroupList: subGroupList, }); } }); }); }, // 获取用户当前位置 getUserLocation() { wx.getLocation({ type: "gcj02", // 腾讯地图坐标系 success: (res) => { const { latitude, longitude } = res; // 设置地图初始位置 this.setData({ mapLatitude: latitude, mapLongitude: longitude, "form.latitude": latitude, "form.longitude": longitude, }); // 获取地址信息 this.getAddressInfo(latitude, longitude); }, fail: (err) => { console.error("获取位置失败", err); wx.showToast({ title: "请允许位置权限", icon: "none", }); // 引导用户开启权限 setTimeout(() => { wx.openSetting({ success: (setting) => { if (setting.authSetting["scope.userLocation"]) { this.getUserLocation(); } }, }); }, 1500); }, }); }, // 获取地址信息(逆地理编码)- 带重试机制 getAddressInfo(latitude, longitude, isFullScreen = false) { const now = Date.now(); // 检查请求间隔,避免频繁请求 if (now - lastRequestTime < REQUEST_INTERVAL) { console.log("请求过于频繁,跳过本次请求"); return; } lastRequestTime = now; // 使用腾讯地图API进行逆地理编码 // 注意:需要替换为你自己的腾讯地图API密钥 const apiKey = "NUQBZ-UIYCW-H7GRI-YXOXA-WNZB7-IGFLY"; const url = `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=${apiKey}&get_poi=0`; // 添加重试机制 this.requestWithRetry(url, 3, (success, data) => { if (success) { const address = data.result.address || "获取地址失败"; if (isFullScreen) { // 全屏地图模式下更新选中地址 this.setData({ selectedAddress: address, }); } else { // 普通模式下更新表单地址 this.setData({ "form.address": address, }); } } else { console.error("逆地理编码失败", data); const errorMsg = "获取地址失败"; if (isFullScreen) { this.setData({ selectedAddress: errorMsg, }); } else { this.setData({ "form.address": errorMsg, }); } wx.showToast({ title: "地址获取失败,请手动输入", icon: "none", }); } }); }, // 带重试机制的请求方法 requestWithRetry(url, maxRetries, callback, retryCount = 0) { wx.request({ url: url, success: (res) => { if (res.data.status === 0) { callback(true, res.data); } else { // 如果是因为请求频率限制导致的失败,进行重试 if ( res.data.message && res.data.message.includes("请求量") && retryCount < maxRetries ) { console.log( `请求失败,${(retryCount + 1) * 1000}ms后进行第${ retryCount + 1 }次重试` ); setTimeout(() => { this.requestWithRetry(url, maxRetries, callback, retryCount + 1); }, (retryCount + 1) * 1000); // 递增延迟重试 } else { callback(false, res.data); } } }, fail: (err) => { // 网络错误时进行重试 if (retryCount < maxRetries) { console.log( `网络请求失败,${(retryCount + 1) * 1000}ms后进行第${ retryCount + 1 }次重试` ); setTimeout(() => { this.requestWithRetry(url, maxRetries, callback, retryCount + 1); }, (retryCount + 1) * 1000); // 递增延迟重试 } else { callback(false, err); } }, }); }, // 显示全屏地图 showFullScreenMap() { this.setData({ showFullScreenMap: true, mapLatitude: this.data.form.latitude || this.data.mapLatitude, mapLongitude: this.data.form.longitude || this.data.mapLongitude, fullScreenMarkers: this.data.form.latitude && this.data.form.longitude ? [ { id: 1, latitude: this.data.form.latitude, longitude: this.data.form.longitude, title: "考勤点", iconPath: "/images/location-marker.png", width: 30, height: 30, }, ] : [], }); // 如果已有坐标,获取地址信息 if (this.data.form.latitude && this.data.form.longitude) { this.getAddressInfo( this.data.form.latitude, this.data.form.longitude, true ); } }, // 隐藏全屏地图 hideFullScreenMap() { this.setData({ showFullScreenMap: false, searchKeyword: "", searchResults: [], }); }, // 全屏地图点击事件 onFullScreenMapTap(e) { const { latitude, longitude } = e.detail; this.setData({ mapLatitude: latitude, mapLongitude: longitude, fullScreenMarkers: [ { id: 1, latitude: latitude, longitude: longitude, title: "考勤点", iconPath: "/images/location-marker.png", width: 30, height: 30, }, ], }); // 获取点击位置的地址信息 this.getAddressInfo(latitude, longitude, true); }, // 确认选择的位置 confirmLocation() { this.setData({ "form.latitude": this.data.mapLatitude, "form.longitude": this.data.mapLongitude, "form.address": this.data.selectedAddress, showFullScreenMap: false, markers: [ { id: 1, latitude: this.data.mapLatitude, longitude: this.data.mapLongitude, title: "考勤点", iconPath: "/images/location-marker.png", width: 30, height: 30, }, ], searchKeyword: "", searchResults: [], }); }, // 搜索输入事件 onSearchInput(e) { this.setData({ searchKeyword: e.detail.value, }); }, // 搜索确认事件 onSearchConfirm() { const keyword = this.data.searchKeyword.trim(); if (!keyword) { wx.showToast({ title: "请输入搜索关键词", icon: "none", }); return; } // 使用腾讯地图API进行地址搜索 const apiKey = "NUQBZ-UIYCW-H7GRI-YXOXA-WNZB7-IGFLY"; const url = `https://apis.map.qq.com/ws/place/v1/suggestion/?keyword=${encodeURIComponent( keyword )}&key=${apiKey}®ion=全国`; wx.request({ url: url, success: (res) => { if ( res.data.status === 0 && res.data.data && res.data.data.length > 0 ) { // 更新搜索结果 this.setData({ searchResults: res.data.data, }); } else { wx.showToast({ title: "未找到相关地址", icon: "none", }); } }, fail: (err) => { console.error("搜索地址失败", err); wx.showToast({ title: "搜索失败,请重试", icon: "none", }); }, }); }, // 选择搜索结果 onSelectSearchResult(e) { const item = e.currentTarget.dataset.item; const { lat, lng } = item.location; // 更新地图位置 this.setData({ mapLatitude: lat, mapLongitude: lng, fullScreenMarkers: [ { id: 1, latitude: lat, longitude: lng, title: item.title, iconPath: "/images/location-marker.png", width: 30, height: 30, }, ], searchResults: [], // 清空搜索结果 searchKeyword: item.title, // 更新搜索框内容 }); // 获取地址信息 this.getAddressInfo(lat, lng, true); }, onTitleInput(e) { this.setData({ "form.title": e.detail.value, }); }, onStartDateInput(e) { this.setData({ "form.startDate": e.detail, }); }, onEndDateInput(e) { this.setData({ "form.endDate": e.detail, }); }, onAddGroupList(e) { if (e.detail.length > 0) { let _userIds = ""; let _userNames = ""; let groups = []; e.detail.forEach((it) => { let item = this.data.groupList.find((item) => item.id == it.userId); groups.push(item); _userIds += "," + item.id; _userNames += "," + item.userName; //+ `[${item.subDeptName}]`; }); this.setData({ "form.subGroup": groups, "form.groupIds": _userIds.substring(1), "form.groupNames": _userNames.substring(1), }); } else { this.setData({ "form.subGroup": [], "form.groupIds": "", "form.groupNames": "", }); } }, onRangeChange(e) { // 正确处理步进器的值变化 this.setData({ "form.range": e.detail.value, }); }, //项目切换 返回值 onProjectSelect(e) { let projectId = e.detail.id; let projectName = e.detail.text; app.globalData.useProjectId = projectId; app.globalData.useProjectName = projectName; this.onLoad(); }, doBack(isRefresh) { /*返回列表页面并刷新*/ if (isRefresh) { wx.redirectTo({ url: "../list/index", }); } else { wx.redirectTo({ url: "../list/index", }); } }, returnToPage: function () { this.doBack(false); }, submitSave() { // 数据验证 if (!this.validateForm()) { return; } let postData = { projectId: app.globalData.useProjectId, comId: app.globalData.userData.activeComId, title: this.data.form.title, startDate: this.data.form.startDate, endDate: this.data.form.endDate, address: this.data.form.address, longitude: this.data.form.longitude, latitude: this.data.form.latitude, valid: 0, range: this.data.form.range, state: 0, remark: "", groupList: this.data.form.subGroup.map((it) => { return { groupId: it.id, groupName: it.userName, cfgId: -1, }; }), }; addMobileAttendanceConfig(postData).then((res) => { if (res.code == 200) { app.toast("保存成功!"); this.doBack(true); } else { app.toast("保存失败,请重试"); } }); }, /** * 表单数据验证 */ validateForm() { const form = this.data.form; // 验证考勤标题 if (!form.title || form.title.trim() === "") { wx.showToast({ title: "请输入考勤标题", icon: "none", duration: 2000, }); return false; } // 验证开始时间 if (!form.startDate) { wx.showToast({ title: "请选择开始时间", icon: "none", duration: 2000, }); return false; } // 验证结束时间 if (!form.endDate) { wx.showToast({ title: "请选择结束时间", icon: "none", duration: 2000, }); return false; } // 验证结束时间是否晚于开始时间 if (form.startDate && form.endDate && form.startDate > form.endDate) { wx.showToast({ title: "结束时间必须晚于开始时间", icon: "none", duration: 2000, }); return false; } // 验证考勤地点 if (!form.address || form.address.trim() === "") { wx.showToast({ title: "请选择考勤地点", icon: "none", duration: 2000, }); return false; } return true; }, });