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>
|