移动端考勤管理
parent
6fce3ed81b
commit
7b8ee3dc75
|
@ -2058,4 +2058,10 @@ swiper-item video {
|
|||
|
||||
.txtb {
|
||||
font-weight: 600;
|
||||
}
|
||||
.txt-blue{
|
||||
color: #728ce3;
|
||||
}
|
||||
.inline-block{
|
||||
display: inline-block;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
<svg class="icon" style="width: 1em;height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11345"><path d="M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z" fill="#07C160" p-id="11346"></path><path d="M234.549 484.627l161.554 125.136 402.358-360.365s27.008-23.954 50.566-5.27c6.999 5.653 15.081 21.559-3.154 46.567L425.871 769.106s-32.232 42.83-70.477-0.479L174.126 530.619s-21.488-32.194 5.421-51.549c9.069-6.42 29.768-16.481 55.002 5.557z" fill="#FFFFFF" p-id="11347"></path></svg>
|
After Width: | Height: | Size: 590 B |
|
@ -0,0 +1 @@
|
|||
<svg class="icon" style="width: 1em;height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8413"><path d="M893.44 341.12c-1.28-6.4-3.84-12.16-8.96-17.28l-185.6-184.96c-14.08-13.44-35.84-13.44-49.92 0-14.08 13.44-14.08 35.84 0 49.92l133.76 133.12L158.72 321.92C142.08 321.92 128 336 128 353.28S142.08 384 158.72 384l624 0-133.76 133.12c-14.08 13.44-14.08 35.84 0 49.92 14.08 13.44 35.84 13.44 49.92 0l185.6-184.96c5.12-5.12 7.68-10.88 8.96-17.28C895.36 361.6 896 357.12 896 353.28S895.36 344.32 893.44 341.12zM801.28 704 177.28 704l133.76-133.12c14.08-13.44 14.08-35.84 0-49.92-14.08-13.44-35.84-13.44-49.92 0l-185.6 184.96C70.4 710.4 67.84 716.8 66.56 722.56 64.64 726.4 64 730.88 64 734.72s0.64 8.32 2.56 12.16c1.28 6.4 3.84 12.16 8.96 17.28l185.6 184.96c14.08 13.44 35.84 13.44 49.92 0 14.08-13.44 14.08-35.84 0-49.92l-133.76-133.12 624 0c17.28 0 30.72-14.08 30.72-30.72S817.92 704 801.28 704z" p-id="8414" fill="#ccc"></path></svg>
|
After Width: | Height: | Size: 1.0 KiB |
|
@ -14,6 +14,7 @@ Page({
|
|||
initData: {},
|
||||
type: "",
|
||||
cfgData: null,
|
||||
arrSel: "in",
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -26,6 +27,11 @@ Page({
|
|||
});
|
||||
}
|
||||
const proUserInfo = getUserInfo();
|
||||
|
||||
// 根据当前时间设置arrSel的值:14点前为in,14点后为out
|
||||
const now = new Date();
|
||||
const arrSel = now.getHours() < 14 ? "in" : "out";
|
||||
|
||||
this.setData({
|
||||
projectUserInfo: proUserInfo.projectUserInfo,
|
||||
projectId: app.globalData.useProjectId,
|
||||
|
@ -35,6 +41,7 @@ Page({
|
|||
text: app.globalData.useProjectName,
|
||||
},
|
||||
type: options.type,
|
||||
arrSel: arrSel,
|
||||
});
|
||||
if (options.id) {
|
||||
this.loadData(options.id);
|
||||
|
@ -42,53 +49,25 @@ Page({
|
|||
app.toast("参数错误!");
|
||||
this.returnToPage();
|
||||
}
|
||||
//todo 14点前 arrSel=in,之后arrSel=out
|
||||
},
|
||||
loadData(id) {
|
||||
getMobileAttendanceConfigById(id).then((res) => {
|
||||
if (res.code == 200) {
|
||||
try {
|
||||
let cfgData = wx.getStorageSync("editAttCfg");
|
||||
if (cfgData) {
|
||||
this.setData({
|
||||
cfgData: res.data,
|
||||
cfgData: cfgData,
|
||||
});
|
||||
} else {
|
||||
app.toast("参数错误!");
|
||||
this.returnToPage();
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
app.toast("参数错误!");
|
||||
this.returnToPage();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady() {},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow() {},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide() {},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload() {},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh() {},
|
||||
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom() {},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage() {},
|
||||
onProjectSelect(e) {
|
||||
let projectId = e.detail.id;
|
||||
let projectName = e.detail.text;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
{
|
||||
"usingComponents": {},
|
||||
"usingComponents": {
|
||||
"svg-icon": "/pageage/components/svg-icon/index"
|
||||
},
|
||||
"navigationStyle": "custom",
|
||||
"styleIsolation": "apply-shared",
|
||||
"backgroundColor": "#191d28"
|
||||
|
|
|
@ -9,11 +9,28 @@
|
|||
</view>
|
||||
</van-col>
|
||||
<van-col span="15">
|
||||
<view class="header_name">移动考勤配置详情</view>
|
||||
<view class="header_name">创建移动考勤</view>
|
||||
</van-col>
|
||||
</van-row>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view class="max_content_scroll" type="list" scroll-y bindscrolltolower="onScrollToLower">
|
||||
<project-select init="{{ initData }}" bindchange="onProjectSelect" id="projectSel"></project-select>
|
||||
|
||||
<view class="content_box">
|
||||
<view class="content_box_title">
|
||||
<svg-icon src="switch" color="#9966CC" size="40" class="inline-block"/>
|
||||
<text class="txt-blue">请选择考勤方向</text>
|
||||
</view>
|
||||
<view class="content_box_content arrow_content">
|
||||
<view class="arrow_box {{arrSel=='in'?'is-active':''}}" bindtap="doSelectArr('in')">
|
||||
<svg-icon src="select" wx:if="{{arrSel=='in'}}" colors="{{['#07C160','#fff']}}" size="40" class="img-sel"/>
|
||||
<view>上班考勤打卡</view>
|
||||
</view>
|
||||
<view class="arrow_box {{arrSel=='out'?'is-active':''}}" bindtap="doSelectArr('out')">
|
||||
<svg-icon src="select" wx:if="{{arrSel=='out'}}" colors="{{['#07C160','#fff']}}" size="40" class="img-sel"/>
|
||||
<view>下班考勤打卡</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
|
@ -1 +1,31 @@
|
|||
/* pageage/mobile_attendance/attendance_config/info/index.wxss */
|
||||
.content_box{
|
||||
padding:20rpx 40rpx;
|
||||
}
|
||||
.content_box_title{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.arrow_content{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.arrow_box{
|
||||
background-color: #ccc;
|
||||
width:45%;
|
||||
margin:0 5%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.arrow_box .img-sel{
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left:-20rpx;
|
||||
top: 20rpx;
|
||||
}
|
||||
|
||||
.arrow_box view{
|
||||
height: 120rpx;
|
||||
line-height: 120rpx;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import { getToken, getUserInfo } from "../../../../utils/auth.js";
|
||||
import { getMobileAttendanceConfig } from "../../../../api/project.js";
|
||||
import { calculateDistance } from "../../../../utils/location.js";
|
||||
|
||||
const app = getApp();
|
||||
|
||||
|
@ -8,13 +9,16 @@ Page({
|
|||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
projectUserInfo: {},
|
||||
projectUserInfo: {},
|
||||
projectId: "",
|
||||
projectName: "",
|
||||
initData: {},
|
||||
total: 0,
|
||||
listData: [],
|
||||
userLongitude: undefined,
|
||||
userLatitude: undefined,
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -36,8 +40,31 @@ Page({
|
|||
text: app.globalData.useProjectName,
|
||||
},
|
||||
});
|
||||
this.getListData();
|
||||
// 先获取用户位置,再获取列表数据
|
||||
this.getUserLocation();
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取用户当前位置
|
||||
*/
|
||||
getUserLocation() {
|
||||
wx.getLocation({
|
||||
type: "gcj02", // 使用国测局坐标
|
||||
success: (res) => {
|
||||
this.setData({
|
||||
userLongitude: res.longitude,
|
||||
userLatitude: res.latitude,
|
||||
});
|
||||
this.getListData();
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error("获取位置失败", err);
|
||||
// 即使获取位置失败,也继续加载列表数据
|
||||
this.getListData();
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
getListData() {
|
||||
let postData = {
|
||||
pageNum: this.data.pageNum,
|
||||
|
@ -47,30 +74,63 @@ Page({
|
|||
};
|
||||
getMobileAttendanceConfig(postData).then((res) => {
|
||||
if (res.code == 200) {
|
||||
let tmps = (res.rows || []).map((it) => {
|
||||
// 如果有用户位置信息,则计算距离,否则设置为-1
|
||||
if (
|
||||
this.data.userLongitude !== undefined &&
|
||||
this.data.userLatitude !== undefined
|
||||
) {
|
||||
it.distance = calculateDistance(
|
||||
this.data.userLongitude,
|
||||
this.data.userLatitude,
|
||||
it.longitude,
|
||||
it.latitude
|
||||
);
|
||||
} else {
|
||||
it.distance = -1; // 无法计算距离
|
||||
}
|
||||
return it;
|
||||
});
|
||||
this.setData({
|
||||
total: res.total,
|
||||
listData: this.data.listData.concat(res.rows),
|
||||
listData: this.data.listData.concat(tmps),
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
getInfo(e) {
|
||||
let cfgData = e.currentTarget.dataset.set;
|
||||
wx.setStorageSync("editAttCfg", cfgData);
|
||||
wx.redirectTo({
|
||||
url: `../add/index?type=att&id=${cfgData.id}`,
|
||||
});
|
||||
},
|
||||
getDistance(longitude, latitude) {
|
||||
// 现在这个方法不再需要,因为距离计算已经在getListData中完成
|
||||
// 但为了保持接口兼容性,如果需要可以返回已计算的距离
|
||||
const item = this.data.listData.find(
|
||||
(it) => it.longitude === longitude && it.latitude === latitude
|
||||
);
|
||||
return item ? item.distance : -1;
|
||||
},
|
||||
//项目切换 返回值
|
||||
onProjectSelect(e) {
|
||||
let projectId = e.detail.id;
|
||||
let projectName = e.detail.text;
|
||||
app.globalData.useProjectId = projectId;
|
||||
app.globalData.useProjectName = projectName;
|
||||
this.onLoad();
|
||||
// 项目切换后重新获取用户位置和列表数据
|
||||
this.getUserLocation();
|
||||
},
|
||||
returnToPage: function () {
|
||||
/*关闭当前页面,跳转到其它页面。*/
|
||||
if (wx.getStorageSync("nav-menu") == "xmgl") {
|
||||
wx.redirectTo({
|
||||
url: "../../project_more/index",
|
||||
url: "../../../project_more/index",
|
||||
});
|
||||
} else {
|
||||
wx.redirectTo({
|
||||
url: "../../project_quality/index",
|
||||
url: "../../../project_quality/index",
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<wxs module="format" src="/utils/format.wxs"></wxs>
|
||||
<wxs module="distance" src="/utils/distance.wxs"></wxs>
|
||||
|
||||
<view class="header_title">
|
||||
<view class="header_title_row">
|
||||
|
@ -15,7 +16,7 @@
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view class="max_content_scroll" type="list" scroll-y bindscrolltolower="onScrollToLower">
|
||||
<scroll-view class="max_content_scroll" type="list" scroll-y bindscrolltolower="onScrollToLower">
|
||||
<project-select init="{{ initData }}" bindchange="onProjectSelect" id="projectSel"></project-select>
|
||||
|
||||
<view class="modify_video_nav" style="margin-top: 5rpx;">
|
||||
|
@ -39,12 +40,16 @@
|
|||
<view class="inspect_list_title_number">{{
|
||||
index < 10 ? "0" + (index + 1) : index + 1 }}</view>
|
||||
<view class="module_title">
|
||||
|
||||
<view class="content-distance">
|
||||
距离:
|
||||
<view class="inline-block"><rich-text nodes="{{distance.formatDistance(item.distance)}}"></rich-text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="inspect_list_content">
|
||||
<svg-icon src="position" color="#45affb" size="120" class="left-img"/>
|
||||
<svg-icon src="position" color="#45affb" size="120" class="left-img" />
|
||||
<view class="content-right">
|
||||
<view class="content-row first">
|
||||
考勤标题:
|
||||
|
@ -62,6 +67,11 @@
|
|||
考勤位置:
|
||||
{{item.address}}
|
||||
</view>
|
||||
<view class="content-row">
|
||||
距离:
|
||||
<view class="inline-block"><rich-text nodes="{{distance.formatDistance(item.distance)}}"></rich-text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
|
|
@ -25,4 +25,8 @@
|
|||
.left-img{
|
||||
position: relative;
|
||||
top:36rpx;
|
||||
}
|
||||
.module_title{
|
||||
flex-grow: 1;
|
||||
text-align: right;
|
||||
}
|
|
@ -108,6 +108,9 @@ Page({
|
|||
cfgData: cfgData,
|
||||
form: form,
|
||||
});
|
||||
} else {
|
||||
app.toast("参数错误!");
|
||||
this.returnToPage();
|
||||
}
|
||||
} catch (e) {
|
||||
app.toast("参数错误!");
|
||||
|
@ -560,6 +563,8 @@ Page({
|
|||
ajax.then((res) => {
|
||||
if (res.code == 200) {
|
||||
app.toast("保存成功!");
|
||||
// 清除editAttCfg
|
||||
wx.removeStorageSync("editAttCfg");
|
||||
this.doBack(true);
|
||||
} else {
|
||||
app.toast("保存失败,请重试");
|
||||
|
@ -665,4 +670,12 @@ Page({
|
|||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload() {
|
||||
// 页面卸载时清除editAttCfg
|
||||
wx.removeStorageSync("editAttCfg");
|
||||
},
|
||||
});
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
<view class="inspect_info_title">指定考勤班组</view>
|
||||
<view class="inspect_info_content">
|
||||
<select-group-person rectifierData="{{subGroupList}}" multiple="{{true}}" bindselected="onAddGroupList"
|
||||
index="3" :title="{{form.groupNames?form.groupNames:'请选择考勤班组'}}" choose="{{form.groupNames}}">
|
||||
index="3" title="{{form.groupNames?form.groupNames:'请选择考勤班组'}}" choose="{{form.groupNames}}">
|
||||
</select-group-person>
|
||||
</view>
|
||||
<view wx:if="{{form.subGroup && form.subGroup.length>0}}">
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
var formatDistance = function (distance) {
|
||||
if (distance < 0) {
|
||||
return "无法计算";
|
||||
}
|
||||
|
||||
if (distance > 1000) {
|
||||
// 保留两位小数
|
||||
var km = (distance / 1000).toString();
|
||||
var dotIndex = km.indexOf(".");
|
||||
if (dotIndex !== -1) {
|
||||
var decimalPart = km.substring(dotIndex + 1);
|
||||
if (decimalPart.length > 2) {
|
||||
km = km.substring(0, dotIndex + 3);
|
||||
}
|
||||
}
|
||||
return km + ' <span class="txt-blue">km</span>';
|
||||
} else {
|
||||
return distance + ' <span class="txt-blue">m</span>';
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
formatDistance: formatDistance,
|
||||
};
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* 计算两点间距离(单位:米)
|
||||
* @param {number} lon1 - 第一个点的经度
|
||||
* @param {number} lat1 - 第一个点的纬度
|
||||
* @param {number} lon2 - 第二个点的经度
|
||||
* @param {number} lat2 - 第二个点的纬度
|
||||
* @returns {number} 两点间距离(米)
|
||||
*/
|
||||
function calculateDistance(lon1, lat1, lon2, lat2) {
|
||||
// 将角度转换为弧度
|
||||
const radLat1 = (lat1 * Math.PI) / 180.0;
|
||||
const radLat2 = (lat2 * Math.PI) / 180.0;
|
||||
const deltaRadLat = radLat1 - radLat2;
|
||||
const deltaRadLon = ((lon1 - lon2) * Math.PI) / 180.0;
|
||||
|
||||
// Haversine公式计算距离
|
||||
const a =
|
||||
Math.sin(deltaRadLat / 2) * Math.sin(deltaRadLat / 2) +
|
||||
Math.cos(radLat1) *
|
||||
Math.cos(radLat2) *
|
||||
Math.sin(deltaRadLon / 2) *
|
||||
Math.sin(deltaRadLon / 2);
|
||||
const b = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
|
||||
// 地球半径(米)
|
||||
const earthRadius = 6371000;
|
||||
const distance = earthRadius * b;
|
||||
|
||||
return Math.round(distance);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
calculateDistance: calculateDistance,
|
||||
};
|
Loading…
Reference in New Issue