From ff8c9ef1805ce1a6a47991862358adc4f55e9aa2 Mon Sep 17 00:00:00 2001 From: lijun Date: Fri, 31 Oct 2025 14:18:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=B0=8F=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yanzhu-ui-app/miniprogram/config.js | 8 +- .../mobile_attendance/attendance/add/index.js | 54 +++---- .../attendance/list/index.js | 17 +- .../attendance_config/add/index.js | 34 ++-- yanzhu-ui-app/miniprogram/project.config.json | 2 +- .../miniprogram/utils/CONFIG_SYNC.md | 46 ++++++ yanzhu-ui-app/miniprogram/utils/config.wxs | 7 + yanzhu-ui-app/miniprogram/utils/format.wxs | 40 ++--- .../miniprogram/utils/locationPermission.js | 147 ++++++++++++++++++ 9 files changed, 268 insertions(+), 87 deletions(-) create mode 100644 yanzhu-ui-app/miniprogram/utils/CONFIG_SYNC.md create mode 100644 yanzhu-ui-app/miniprogram/utils/config.wxs create mode 100644 yanzhu-ui-app/miniprogram/utils/locationPermission.js diff --git a/yanzhu-ui-app/miniprogram/config.js b/yanzhu-ui-app/miniprogram/config.js index 071cc4f1..e3b3ac1e 100644 --- a/yanzhu-ui-app/miniprogram/config.js +++ b/yanzhu-ui-app/miniprogram/config.js @@ -2,11 +2,11 @@ module.exports = { timeout: 60000, appId: "wx007a8fd50dc185b2", - baseUrl: "https://xiangguan.sxyanzhu.com/wechat", - //baseUrl: "https://jaszpt.crfeb.com.cn/wechat", + //baseUrl: "https://xiangguan.sxyanzhu.com/wechat", + baseUrl: "https://jaszpt.crfeb.com.cn/wechat", //baseUrl: "http://127.0.0.1:8080", - baseImgUrl: "https://xiangguan.sxyanzhu.com", - //baseImgUrl: "https://jaszpt.crfeb.com.cn", + //baseImgUrl: "https://xiangguan.sxyanzhu.com", + baseImgUrl: "https://jaszpt.crfeb.com.cn", //baseImgUrl: 'http://127.0.0.1:9300', noSecuritys: [ "/code", 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 60299937..2a5fc099 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,10 +1,12 @@ import fmt from "../../../utils/date.js"; import { getToken, getUserInfo } from "../../../../utils/auth.js"; -import { securityFileUpload } from "../../../../utils/request.js"; // 导入文件上传工具 +import { securityFileUpload } from "../../../../utils/request.js"; const app = getApp(); import { mobileAttendance } from "../../../../api/project.js"; -import { calculateDistance } from "../../../../utils/location.js"; // 导入计算距离的工具函数 +import { calculateDistance } from "../../../../utils/location.js"; +import { checkAndRequestLocationPermission } from "../../../../utils/locationPermission.js"; // 引入位置权限工具函数 import config from "../../../../config.js"; + Page({ /** * 页面的初始数据 @@ -234,9 +236,8 @@ Page({ // 获取当前位置并计算距离 getCurrentLocationAndCalculateDistance() { - wx.getLocation({ - type: "gcj02", // 使用国测局坐标系 - success: (res) => { + checkAndRequestLocationPermission( + (res) => { const { longitude, latitude } = res; const cfgData = this.data.cfgData; @@ -250,7 +251,12 @@ Page({ // 检查是否超出考勤范围 if (distance > cfgData.range) { - app.toast("超出考勤范围!"); + wx.showModal({ + title: "考勤范围提醒", + content: `您当前位置距离考勤点${distance}米,已超出${cfgData.range}米的考勤范围,请移动到考勤点范围内再进行打卡。`, + showCancel: false, + confirmText: "我知道了", + }); return; } @@ -271,36 +277,14 @@ Page({ this.doSaveAttendance(); }); }, - fail: (err) => { + (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("获取位置失败,请检查定位权限"); - } - }, - }); + wx.showToast({ + title: "获取位置失败", + icon: "none", + }); + } + ); }, // 更新用户位置标记 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 a768d641..74dc95c7 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 @@ -1,6 +1,7 @@ import { getToken, getUserInfo } from "../../../../utils/auth.js"; import { getMobileAttendanceConfig } from "../../../../api/project.js"; import { calculateDistance } from "../../../../utils/location.js"; +import { checkAndRequestLocationPermission } from "../../../../utils/locationPermission.js"; // 引入位置权限工具函数 import cfg from "../../../../config.js"; const app = getApp(); @@ -50,9 +51,8 @@ Page({ * 获取用户当前位置 */ getUserLocation() { - wx.getLocation({ - type: "gcj02", // 使用国测局坐标 - success: (res) => { + checkAndRequestLocationPermission( + (res) => { this.setData({ userLongitude: res.longitude, userLatitude: res.latitude, @@ -73,12 +73,17 @@ Page({ this.getListData(); }); }, - fail: (err) => { + (err) => { console.error("获取位置失败", err); // 即使获取位置失败,也继续加载列表数据 this.getListData(); - }, - }); + // 提示用户位置获取失败 + wx.showToast({ + title: "位置获取失败,距离计算不可用", + icon: "none", + }); + } + ); }, getListData() { diff --git a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance_config/add/index.js b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance_config/add/index.js index d4272f64..9ffedbcd 100644 --- a/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance_config/add/index.js +++ b/yanzhu-ui-app/miniprogram/pageage/mobile_attendance/attendance_config/add/index.js @@ -9,6 +9,7 @@ import { updateMobileAttendanceConfig, } from "../../../../api/project"; import { findDictCache } from "../../../../api/publics"; +import { getCurrentLocationWithAddress } from "../../../../utils/locationPermission.js"; // 引入位置权限工具函数 const app = getApp(); // 添加防抖变量,避免频繁请求API @@ -173,39 +174,26 @@ Page({ }, // 获取用户当前位置 getUserLocation() { - wx.getLocation({ - type: "gcj02", // 腾讯地图坐标系 - success: (res) => { - const { latitude, longitude } = res; - // 设置地图初始位置 + getCurrentLocationWithAddress( + (res) => { + const { latitude, longitude, address } = res; + // 设置地图初始位置和地址 this.setData({ mapLatitude: latitude, mapLongitude: longitude, "form.latitude": latitude, "form.longitude": longitude, + "form.address": address, }); - - // 获取地址信息 - this.getAddressInfo(latitude, longitude); }, - fail: (err) => { - console.error("获取位置失败", err); + (err) => { + console.error("获取位置和地址失败", err); wx.showToast({ - title: "请允许位置权限", + title: "获取位置失败", icon: "none", }); - // 引导用户开启权限 - setTimeout(() => { - wx.openSetting({ - success: (setting) => { - if (setting.authSetting["scope.userLocation"]) { - this.getUserLocation(); - } - }, - }); - }, 1500); - }, - }); + } + ); }, // 获取地址信息(逆地理编码)- 带重试机制 getAddressInfo(latitude, longitude, isFullScreen = false) { diff --git a/yanzhu-ui-app/miniprogram/project.config.json b/yanzhu-ui-app/miniprogram/project.config.json index bed0f59f..8201a339 100644 --- a/yanzhu-ui-app/miniprogram/project.config.json +++ b/yanzhu-ui-app/miniprogram/project.config.json @@ -1,5 +1,5 @@ { - "appid": "wx46466c7828eede2b", + "appid": "wx007a8fd50dc185b2", "compileType": "miniprogram", "libVersion": "3.8.9", "packOptions": { diff --git a/yanzhu-ui-app/miniprogram/utils/CONFIG_SYNC.md b/yanzhu-ui-app/miniprogram/utils/CONFIG_SYNC.md new file mode 100644 index 00000000..4c7cae2a --- /dev/null +++ b/yanzhu-ui-app/miniprogram/utils/CONFIG_SYNC.md @@ -0,0 +1,46 @@ +# 配置文件同步说明 + +## 概述 + +由于小程序的技术限制,WXS 模块无法直接引入 JS 配置文件,因此需要维护两套配置文件: + +- `config.js` - 用于逻辑层(JS) +- `config.wxs` - 用于视图层(WXS) + +## 同步规则 + +当需要修改配置时,请确保同时更新两个文件中的相应配置项: + +### 1. Base URL 配置同步 + +#### JS 配置文件 (config.js) + +```javascript +module.exports = { + // ... + baseImgUrl: "https://jaszpt.crfeb.com.cn", + // ... +}; +``` + +#### WXS 配置文件 (utils/config.wxs) + +```javascript +var config = { + baseImgUrl: "https://jaszpt.crfeb.com.cn", +}; + +module.exports = config; +``` + +## 维护建议 + +1. 修改配置时,请同时更新两个文件中的对应项 +2. 建议在修改后进行充分测试,确保两个配置文件的一致性 +3. 可以通过代码审查来确保配置同步 + +## 注意事项 + +- 不要删除 config.js,它是整个应用的核心配置文件 +- WXS 配置文件仅包含视图层需要的简单配置项 +- 复杂的配置逻辑应保留在 config.js 中 diff --git a/yanzhu-ui-app/miniprogram/utils/config.wxs b/yanzhu-ui-app/miniprogram/utils/config.wxs new file mode 100644 index 00000000..2174d135 --- /dev/null +++ b/yanzhu-ui-app/miniprogram/utils/config.wxs @@ -0,0 +1,7 @@ +// WXS 配置文件 +var config = { + // 与 config.js 中的 baseImgUrl 保持同步 + baseImgUrl: "https://jaszpt.crfeb.com.cn", +}; + +module.exports = config; diff --git a/yanzhu-ui-app/miniprogram/utils/format.wxs b/yanzhu-ui-app/miniprogram/utils/format.wxs index 52dbc156..840ce5ac 100644 --- a/yanzhu-ui-app/miniprogram/utils/format.wxs +++ b/yanzhu-ui-app/miniprogram/utils/format.wxs @@ -1,6 +1,9 @@ +// 引入 WXS 配置文件 +var config = require("./config.wxs"); + /** * 序号格式化 - * @param num + * @param num */ function indexNumFormat(num) { switch (num) { @@ -37,41 +40,41 @@ function indexNumFormat(num) { /** * 计算时长 - * @param val + * @param val */ function findDurationDate(val) { // 计算出相差天数 - let days = Math.floor(val / (24 * 3600 * 1000)) + let days = Math.floor(val / (24 * 3600 * 1000)); // 计算出小时数 - let leave1 = val % (24 * 3600 * 1000) // 计算天数后剩余的毫秒数 - let hours = Math.floor(leave1 / (3600 * 1000)) + let leave1 = val % (24 * 3600 * 1000); // 计算天数后剩余的毫秒数 + let hours = Math.floor(leave1 / (3600 * 1000)); // 计算相差分钟数 - let leave2 = leave1 % (3600 * 1000) // 计算小时数后剩余的毫秒数 - let minutes = Math.floor(leave2 / (60 * 1000)) + let leave2 = leave1 % (3600 * 1000); // 计算小时数后剩余的毫秒数 + let minutes = Math.floor(leave2 / (60 * 1000)); // 计算相差秒数 - let leave3 = leave2 % (60 * 1000) // 计算分钟数后剩余的毫秒数 - let seconds = Math.round(leave3 / 1000) + let leave3 = leave2 % (60 * 1000); // 计算分钟数后剩余的毫秒数 + let seconds = Math.round(leave3 / 1000); if (days > 0) { if (days < 10) days = "0" + days; if (hours < 10) hours = "0" + hours; if (minutes < 10) minutes = "0" + minutes; if (seconds < 10) seconds = "0" + seconds; - return days + '天' + hours + '小时' + minutes + '分钟' + seconds + '秒'; + return days + "天" + hours + "小时" + minutes + "分钟" + seconds + "秒"; } if (hours > 0) { if (hours < 10) hours = "0" + hours; if (minutes < 10) minutes = "0" + minutes; if (seconds < 10) seconds = "0" + seconds; - return hours + '小时' + minutes + '分钟' + seconds + '秒'; + return hours + "小时" + minutes + "分钟" + seconds + "秒"; } if (minutes > 0) { if (minutes < 10) minutes = "0" + minutes; if (seconds < 10) seconds = "0" + seconds; - return minutes + '分钟' + seconds + '秒'; + return minutes + "分钟" + seconds + "秒"; } if (seconds > 0) { if (seconds < 10) seconds = "0" + seconds; - return seconds + '秒'; + return seconds + "秒"; } } @@ -117,19 +120,20 @@ module.exports = { if (str.indexOf("https:") > -1) { return str; } else { - return "https://xiangguan.sxyanzhu.com" + str; + // 使用 WXS 配置文件中的 baseImgUrl,确保与 JS 配置同步 + return config.baseImgUrl + str; } }, birthDate: function (timestamp) { var date = getDate(parseInt(timestamp)); var mm = date.getMonth() + 1; if (mm < 10) { - mm = '0' + mm; + mm = "0" + mm; } var dd = date.getDate(); if (dd < 10) { - dd = '0' + dd; + dd = "0" + dd; } return date.getFullYear() + "-" + mm + "-" + dd; - } -} \ No newline at end of file + }, +}; diff --git a/yanzhu-ui-app/miniprogram/utils/locationPermission.js b/yanzhu-ui-app/miniprogram/utils/locationPermission.js new file mode 100644 index 00000000..f6e879d3 --- /dev/null +++ b/yanzhu-ui-app/miniprogram/utils/locationPermission.js @@ -0,0 +1,147 @@ +/** + * 位置权限处理工具函数 + */ + +/** + * 检查并请求位置权限 + * @param {Function} successCallback - 获取位置成功回调 + * @param {Function} failCallback - 获取位置失败回调 + */ +function checkAndRequestLocationPermission(successCallback, failCallback) { + wx.getLocation({ + type: "gcj02", + success: (res) => { + successCallback && successCallback(res); + }, + fail: (err) => { + console.error("获取位置失败", err); + + // 分析错误原因 + let errMsg = "获取位置失败"; + if (err.errMsg && err.errMsg.includes("auth deny")) { + errMsg = "未授权位置权限"; + } else if (err.errMsg && err.errMsg.includes("auth denied")) { + errMsg = "位置权限被拒绝"; + } else if ( + err.errMsg && + err.errMsg.includes("fail system permission denied") + ) { + errMsg = "系统未开启定位服务"; + } else if ( + err.errMsg && + err.errMsg.includes("fail url not in domain list") + ) { + errMsg = "请求域名未配置,请联系管理员"; + } + + // 显示详细错误信息和解决方案 + wx.showModal({ + title: "位置权限申请", + content: `${errMsg},需要获取您的位置信息。请确保: +1. 已授权位置权限 +2. 手机定位服务已开启 +3. 在设置中开启位置权限 +4. 使用最新版本小程序`, + showCancel: true, + confirmText: "去设置", + cancelText: "稍后再说", + success: (res) => { + if (res.confirm) { + wx.openSetting({ + success: (setting) => { + if (setting.authSetting["scope.userLocation"]) { + // 用户开启了权限,重新获取位置 + checkAndRequestLocationPermission( + successCallback, + failCallback + ); + } else { + failCallback && failCallback(err); + } + }, + fail: (error) => { + console.error("打开设置失败", error); + wx.showToast({ + title: "打开设置失败", + icon: "none", + }); + failCallback && failCallback(error); + }, + }); + } else { + failCallback && failCallback(err); + } + }, + }); + }, + }); +} + +/** + * 获取当前位置并返回详细地址信息 + * @param {Function} successCallback - 成功回调,包含位置和地址信息 + * @param {Function} failCallback - 失败回调 + */ +function getCurrentLocationWithAddress(successCallback, failCallback) { + checkAndRequestLocationPermission( + (locationRes) => { + // 获取位置成功,继续获取地址信息 + const { latitude, longitude } = locationRes; + + // 使用腾讯地图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`; + + wx.request({ + url: url, + success: (res) => { + if (res.data.status === 0) { + const address = res.data.result.address || "获取地址失败"; + successCallback && + successCallback({ + ...locationRes, + address: address, + }); + } else { + // 地址获取失败,但仍返回位置信息 + successCallback && + successCallback({ + ...locationRes, + address: "地址获取失败", + }); + } + }, + fail: (err) => { + console.error("获取地址信息失败", err); + // 检查是否是域名问题 + if ( + err.errMsg && + err.errMsg.includes("fail url not in domain list") + ) { + wx.showModal({ + title: "配置错误", + content: + "请求域名未在后台配置,请联系管理员配置 https://apis.map.qq.com 域名", + showCancel: false, + confirmText: "我知道了", + }); + } + // 地址获取失败,但仍返回位置信息 + successCallback && + successCallback({ + ...locationRes, + address: "地址获取失败", + }); + }, + }); + }, + (err) => { + failCallback && failCallback(err); + } + ); +} + +module.exports = { + checkAndRequestLocationPermission: checkAndRequestLocationPermission, + getCurrentLocationWithAddress: getCurrentLocationWithAddress, +};