390 lines
9.4 KiB
Vue
390 lines
9.4 KiB
Vue
<template>
|
||
<view class="cancel-leave">
|
||
<!-- 显示定位信息 -->
|
||
<view class="content">
|
||
<!-- 地图展示 -->
|
||
<map style="width: 100%; height: 300px;" :latitude="latitude" :longitude="longitude" :markers="covers"
|
||
show-location></map>
|
||
<!-- 重新定位按钮 -->
|
||
<button class="refresh-location" @tap="getLocation">重新获取定位</button>
|
||
</view>
|
||
<!-- 确定销假按钮 -->
|
||
<button class="confirm-cancel" @tap="confirm">确定销假</button>
|
||
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
getLeaveApplicationByProcInsId,
|
||
complete,
|
||
reject
|
||
} from "@/api/task.js";
|
||
import {
|
||
editApply
|
||
} from "@/api/applyleave/applyleave.js";
|
||
import {
|
||
getWxConfig
|
||
} from "@/api/common/wechat";
|
||
import wx from "weixin-js-sdk"; // 引入微信 JS-SDK
|
||
import * as ww from '@wecom/jssdk'
|
||
export default {
|
||
data() {
|
||
return {
|
||
address: "", // 地址信息
|
||
latitude: 108.31019592285156, // 纬度
|
||
longitude: 22.90125274658203, // 经度
|
||
covers: [{
|
||
latitude: 108.31019592285156,
|
||
longitude: 22.90125274658203,
|
||
iconPath: '../../static/images/applyrelieve/location.png'
|
||
}],
|
||
distanceThreshold: 1000, // 距离阈值
|
||
isLeave: true, // 销假按钮状态
|
||
taskForm: {},
|
||
};
|
||
},
|
||
async onLoad(option) {
|
||
console.log(this.role)
|
||
let query = JSON.parse(option.query);
|
||
this.taskForm.deployId = query.deployId;
|
||
this.taskForm.instanceId = query.procInsId
|
||
this.taskForm.procInsId = query.procInsId
|
||
this.taskForm.executionId = query.executionId
|
||
this.taskForm.taskId = query.taskId
|
||
this.getTaskDetail();
|
||
await this.initWxConfig(); // 初始化微信配置
|
||
this.getLocation();
|
||
},
|
||
methods: {
|
||
async initWxConfig() {
|
||
let that = this;
|
||
let res = await that.getConfigSignature();
|
||
ww.register({
|
||
corpId: 'wx129e6bf0f36b8b3d', // 必填,当前用户企业所属企业ID
|
||
agentId: 1000093, // 必填,当前应用的AgentID
|
||
jsApiList: ["getLocation", "openLocation"], // 必填,需要使用的JSAPI列表
|
||
// getAgentConfigSignature: that.getAgentConfigSignature, // 必填,根据url生成应用签名的回调函数
|
||
getConfigSignature() {
|
||
return res
|
||
}
|
||
})
|
||
},
|
||
// 初始化微信 JS-SDK
|
||
async getConfigSignature() {
|
||
return new Promise((resolve, reject) => {
|
||
// 调用后端接口获取签名信息(需要后端支持)
|
||
getWxConfig("corpId").then(res => {
|
||
const {
|
||
timestamp,
|
||
nonceStr,
|
||
signature
|
||
} = res;
|
||
resolve({
|
||
timestamp,
|
||
nonceStr,
|
||
signature
|
||
});
|
||
}).catch(err => {
|
||
reject(err);
|
||
});
|
||
});
|
||
},
|
||
// 初始化微信 JS-SDK,应用
|
||
async getAgentConfigSignature() {
|
||
return new Promise((resolve, reject) => {
|
||
// 调用后端接口获取签名信息(需要后端支持)
|
||
getWxConfig("agentId").then(res => {
|
||
const {
|
||
timestamp,
|
||
nonceStr,
|
||
signature
|
||
} = res;
|
||
resolve({
|
||
timestamp,
|
||
nonceStr,
|
||
signature
|
||
});
|
||
}).catch(err => {
|
||
reject(err);
|
||
});
|
||
});
|
||
},
|
||
// 获取当前位置
|
||
getLocation() {
|
||
let that = this;
|
||
ww.getLocation({
|
||
type: 'gcj02',
|
||
success(res) {
|
||
that.latitude = res.latitude
|
||
that.longitude = res.longitude
|
||
that.covers[0].latitude = res.latitude
|
||
that.covers[0].longitude = res.longitude
|
||
},
|
||
fail(err) {
|
||
uni.showToast({
|
||
title: "获取定位失败",
|
||
icon: 'fail'
|
||
})
|
||
}
|
||
});
|
||
},
|
||
openLocation() {
|
||
let that = this;
|
||
ww.openLocation({
|
||
latitude: that.latitude,
|
||
longitude: that.longitude,
|
||
name: 'name',
|
||
address: 'address',
|
||
scale: 1,
|
||
success(res) {},
|
||
fail(err) {
|
||
console.log('定位失败:', err)
|
||
},
|
||
complete(err) {
|
||
console.log('定位失败:', err)
|
||
}
|
||
})
|
||
},
|
||
// 通过经纬度反向解析地址(需要后端支持或使用第三方 API,如高德地图 API)
|
||
reverseGeocode(lat, lng) {
|
||
const amapKey = "your-amap-key"; // 替换为高德地图的 API Key
|
||
this.$http
|
||
.get(
|
||
`https://restapi.amap.com/v3/geocode/regeo?key=${amapKey}&location=${lng},${lat}`
|
||
)
|
||
.then(res => {
|
||
if (res.data.regeocode && res.data.regeocode.formatted_address) {
|
||
this.address = res.data.regeocode.formatted_address;
|
||
} else {
|
||
this.address = "未知地址";
|
||
}
|
||
})
|
||
.catch(err => {
|
||
console.error("反向地理编码失败", err);
|
||
this.address = "地址解析失败";
|
||
});
|
||
},
|
||
|
||
async checkIfNearCampus1() {
|
||
const campuses = [{
|
||
name: "长堽校区",
|
||
latitude: 22.835938,
|
||
longitude: 108.351728
|
||
},
|
||
{
|
||
name: "里建校区",
|
||
latitude: 23.206284,
|
||
longitude: 108.18664
|
||
}
|
||
];
|
||
let isNearby = false;
|
||
let res = false;
|
||
|
||
let campus = campuses[0];
|
||
let p1 = {
|
||
latitude: this.latitude,
|
||
longitude: this.longitude
|
||
}
|
||
let distance = this.getDistance(
|
||
p1.latitude, p1.longitude,
|
||
campus.latitude, campus.longitude
|
||
);
|
||
isNearby = distance < this.distanceThreshold;
|
||
if (isNearby) {
|
||
res = true;
|
||
}
|
||
|
||
campus = campuses[1];
|
||
distance = this.getDistance(
|
||
p1.latitude, p1.longitude,
|
||
campus.latitude, campus.longitude
|
||
);
|
||
isNearby = distance < this.distanceThreshold;
|
||
|
||
if (isNearby) {
|
||
res = true;
|
||
}
|
||
|
||
if (res) {
|
||
return true;
|
||
} else {
|
||
return false;
|
||
}
|
||
},
|
||
toRadians(degree) {
|
||
return degree * (Math.PI / 180);
|
||
},
|
||
|
||
// 计算两个经纬度之间的距离(近似计算,适用于小范围)
|
||
getDistance(lat1, lng1, lat2, lng2) {
|
||
const EARTH_RADIUS = 6378137; // 地球半径,单位:米
|
||
const dLat = this.toRadians(lat2 - lat1);
|
||
const dLng = this.toRadians(lng2 - lng1);
|
||
const a =
|
||
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||
Math.cos(this.toRadians(lat1)) *
|
||
Math.cos(this.toRadians(lat2)) *
|
||
Math.sin(dLng / 2) *
|
||
Math.sin(dLng / 2);
|
||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||
return EARTH_RADIUS * c;
|
||
},
|
||
|
||
// 检查是否在校区范围
|
||
checkIfNearCampus() {
|
||
const campuses = [{
|
||
name: "长堽校区",
|
||
latitude: 22.835938,
|
||
longitude: 108.351728
|
||
},
|
||
{
|
||
name: "里建校区",
|
||
latitude: 23.206284,
|
||
longitude: 108.18664
|
||
}
|
||
];
|
||
|
||
const isNearby = campuses.some(campus => {
|
||
const distance = this.calculateDistance(
|
||
this.latitude,
|
||
this.longitude,
|
||
campus.latitude,
|
||
campus.longitude
|
||
);
|
||
return distance < this.distanceThreshold;
|
||
});
|
||
|
||
if (isNearby) {
|
||
this.$toast("您在校区范围内,可以进行销假");
|
||
this.isLeave = false;
|
||
} else {
|
||
this.$toast("您不在校区范围内,无法销假");
|
||
this.isLeave = true;
|
||
}
|
||
},
|
||
|
||
// 计算两点之间的球面距离
|
||
calculateDistance(lat1, lng1, lat2, lng2) {
|
||
const R = 6371000; // 地球半径(单位:米)
|
||
const toRadians = degrees => (degrees * Math.PI) / 180;
|
||
const dLat = toRadians(lat2 - lat1);
|
||
const dLng = toRadians(lng2 - lng1);
|
||
const a =
|
||
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||
Math.cos(toRadians(lat1)) *
|
||
Math.cos(toRadians(lat2)) *
|
||
Math.sin(dLng / 2) *
|
||
Math.sin(dLng / 2);
|
||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||
return R * c;
|
||
},
|
||
|
||
// 获取销假详情
|
||
getTaskDetail() {
|
||
getLeaveApplicationByProcInsId(this.taskForm.procInsId).then(res => {
|
||
this.leaveApplicationId = res.data.leaveApplicationId;
|
||
this.address = res.data.destinationDetails;
|
||
});
|
||
},
|
||
|
||
// 销假操作
|
||
async confirm() {
|
||
if (await this.checkIfNearCampus1()) {
|
||
uni.showModal({
|
||
title: "提示",
|
||
content: "确定销假吗?",
|
||
confirmText: "确定",
|
||
cancelText: "取消",
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
this.taskForm.comment = '销假'
|
||
complete(this.taskForm).then(res => {
|
||
if (res.code == 200) {
|
||
const data = {
|
||
leaveApplicationId: this.leaveApplicationId,
|
||
};
|
||
editApply(data).then(() => {
|
||
uni.showToast({
|
||
title: "销假成功",
|
||
icon: "success",
|
||
duration: 1500
|
||
});
|
||
|
||
// 延时跳转确保用户看到提示
|
||
setTimeout(() => {
|
||
uni.redirectTo({
|
||
url: "/pages/Approval/index?tab=2"
|
||
});
|
||
}, 1600);
|
||
}).catch(err => {
|
||
uni.showToast({
|
||
title: "销假失败: " + err.message,
|
||
icon: "none"
|
||
});
|
||
});
|
||
}
|
||
})
|
||
|
||
}
|
||
}
|
||
});
|
||
} else {
|
||
uni.showToast({
|
||
title: "您不在学校附近",
|
||
icon: "error"
|
||
});
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.cancel-leave {
|
||
.content {
|
||
.location-info {
|
||
margin: 10px 0;
|
||
text-align: center;
|
||
|
||
.title {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.address {
|
||
font-size: 14px;
|
||
color: #666;
|
||
}
|
||
}
|
||
|
||
.refresh-location {
|
||
margin: 10px auto;
|
||
display: block;
|
||
width: 80%;
|
||
background-color: #007aff;
|
||
color: white;
|
||
text-align: center;
|
||
padding: 10px;
|
||
border-radius: 5px;
|
||
}
|
||
}
|
||
|
||
.confirm-cancel {
|
||
position: fixed;
|
||
bottom: 0;
|
||
width: 100%;
|
||
background-color: #1890ff;
|
||
color: white;
|
||
border-radius: 0;
|
||
padding: 10px;
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
|
||
&[disabled] {
|
||
opacity: 0.5;
|
||
}
|
||
}
|
||
}
|
||
</style> |