|
|
@@ -90,7 +90,7 @@
|
|
|
</view>
|
|
|
|
|
|
<!-- 位置信息卡片 -->
|
|
|
- <view class="location-card" v-if="currentLocation">
|
|
|
+ <view class="location-card" v-if="currentLocation" style="display: none;">
|
|
|
<view class="card-header">
|
|
|
<view class="header-left">
|
|
|
<u-icon name="map-pin" size="18" color="#f56c6c"></u-icon>
|
|
|
@@ -204,7 +204,7 @@
|
|
|
<!-- 考勤统计 -->
|
|
|
<view class="statistics-card">
|
|
|
<view class="card-header">
|
|
|
- <u-icon name="bar-chart" size="18" color="#e6a23c"></u-icon>
|
|
|
+ <u-icon size="18" color="#e6a23c"></u-icon>
|
|
|
<text class="card-title">本月考勤</text>
|
|
|
</view>
|
|
|
<view class="stats-grid">
|
|
|
@@ -228,7 +228,7 @@
|
|
|
</view>
|
|
|
|
|
|
<!-- 最近签到记录 -->
|
|
|
- <view class="records-card">
|
|
|
+ <view class="records-card" style="display: none;">
|
|
|
<view class="card-header">
|
|
|
<u-icon name="list" size="18" color="#909399"></u-icon>
|
|
|
<text class="card-title">最近签到</text>
|
|
|
@@ -264,6 +264,7 @@
|
|
|
import { getInternshipInfo, getStudentInternshipInfo, checkIn, getDailyList, getStatistics } from '@/api/internship.js';
|
|
|
import { getCurrentLocation, checkLocationPermission, openLocationSettings } from '@/utils/location.js';
|
|
|
import { userManager } from '@/utils/user.js';
|
|
|
+import weChatSDK from '@/utils/wechat.js';
|
|
|
|
|
|
export default {
|
|
|
name: 'InternshipIndex',
|
|
|
@@ -281,11 +282,16 @@ export default {
|
|
|
checkinTips: '',
|
|
|
todayRecord: null,
|
|
|
|
|
|
- // 位置信息
|
|
|
+ // 位置信息(增强版)
|
|
|
currentLocation: null,
|
|
|
locationLoading: false,
|
|
|
locationError: '',
|
|
|
|
|
|
+ // 微信SDK相关(新增)
|
|
|
+ wechatSDK: weChatSDK,
|
|
|
+ isWechatBrowser: false,
|
|
|
+ wechatInitializing: false,
|
|
|
+
|
|
|
// 统计数据
|
|
|
monthStats: {
|
|
|
totalDays: 0,
|
|
|
@@ -313,7 +319,10 @@ export default {
|
|
|
};
|
|
|
},
|
|
|
|
|
|
- onLoad() {
|
|
|
+ async onLoad() {
|
|
|
+ // 初始化微信环境检查并自动初始化SDK
|
|
|
+ await this.checkWechatEnvironment();
|
|
|
+
|
|
|
this.initPage();
|
|
|
},
|
|
|
|
|
|
@@ -324,8 +333,62 @@ export default {
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
+ // === 微信SDK相关方法 ===
|
|
|
+
|
|
|
+ // 检查微信环境并自动初始化SDK
|
|
|
+ async checkWechatEnvironment() {
|
|
|
+ try {
|
|
|
+ // 检查是否在微信浏览器中
|
|
|
+ this.isWechatBrowser = this.wechatSDK.isWeChatBrowser();
|
|
|
+
|
|
|
+ if (this.isWechatBrowser) {
|
|
|
+ // 在微信环境中,自动初始化SDK
|
|
|
+ await this.initWechatSDK();
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('微信环境检查失败:', error);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 初始化微信SDK
|
|
|
+ async initWechatSDK() {
|
|
|
+ if (this.wechatInitializing) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.wechatInitializing = true;
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 使用微信SDK工具类进行初始化
|
|
|
+ await this.wechatSDK.init({
|
|
|
+ debug: process.env.NODE_ENV === 'development',
|
|
|
+ jsApiList: ['chooseImage', 'previewImage', 'getLocation', 'openLocation'],
|
|
|
+ });
|
|
|
+
|
|
|
+ // 检查关键API支持情况
|
|
|
+ try {
|
|
|
+ const apiCheckResult = await this.wechatSDK.checkJsApi([
|
|
|
+ 'chooseImage',
|
|
|
+ 'getLocation',
|
|
|
+ ]);
|
|
|
+ } catch (apiError) {
|
|
|
+ console.warn('API支持检查失败:', apiError.message);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('微信SDK初始化失败:', error);
|
|
|
+ } finally {
|
|
|
+ this.wechatInitializing = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 重新初始化微信SDK
|
|
|
+ async reinitWechatSDK() {
|
|
|
+ this.wechatSDK.isInitialized = false;
|
|
|
+ await this.initWechatSDK();
|
|
|
+ },
|
|
|
+
|
|
|
/**
|
|
|
- * 初始化页面
|
|
|
+ * 初始化页面(增强版)
|
|
|
*/
|
|
|
async initPage() {
|
|
|
try {
|
|
|
@@ -343,6 +406,14 @@ export default {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ // 初始化微信环境检测
|
|
|
+ this.isWechatBrowser = this.wechatSDK.isWeChatBrowser();
|
|
|
+
|
|
|
+ // 如果在微信环境,初始化微信SDK
|
|
|
+ if (this.isWechatBrowser) {
|
|
|
+ await this.initWechatSDK();
|
|
|
+ }
|
|
|
+
|
|
|
// 并行加载数据
|
|
|
await Promise.all([
|
|
|
this.loadInternshipInfo(),
|
|
|
@@ -360,6 +431,40 @@ export default {
|
|
|
});
|
|
|
}
|
|
|
},
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化微信SDK(新增)
|
|
|
+ */
|
|
|
+ async initWechatSDK() {
|
|
|
+ if (this.wechatInitializing) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.wechatInitializing = true;
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 使用微信SDK工具类进行初始化
|
|
|
+ await this.wechatSDK.init({
|
|
|
+ debug: process.env.NODE_ENV === 'development',
|
|
|
+ jsApiList: ['getLocation', 'openLocation'],
|
|
|
+ });
|
|
|
+
|
|
|
+ console.log('微信SDK初始化成功,支持定位和地图功能');
|
|
|
+ } catch (error) {
|
|
|
+ console.error('微信SDK初始化失败:', error);
|
|
|
+ // 不影响正常功能,继续使用其他定位方案
|
|
|
+ } finally {
|
|
|
+ this.wechatInitializing = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重新初始化微信SDK(新增)
|
|
|
+ */
|
|
|
+ async reinitWechatSDK() {
|
|
|
+ this.wechatSDK.isInitialized = false;
|
|
|
+ await this.initWechatSDK();
|
|
|
+ },
|
|
|
|
|
|
/**
|
|
|
* 加载实习信息
|
|
|
@@ -540,188 +645,243 @@ export default {
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
- * 获取当前位置信息 - 增强版多重定位方案
|
|
|
+ * 智能定位:根据环境自动选择最适合的定位方式(增强版)
|
|
|
*/
|
|
|
async getCurrentLocationInfo() {
|
|
|
- this.locationLoading = true;
|
|
|
- this.locationError = '';
|
|
|
-
|
|
|
try {
|
|
|
- // 方案1: 微信定位(微信浏览器环境)
|
|
|
- if (this.isWechatBrowser()) {
|
|
|
- try {
|
|
|
- uni.showToast({
|
|
|
- title: '正在微信定位...',
|
|
|
- icon: 'loading',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- const wechatLocation = await this.getWechatLocation();
|
|
|
- if (wechatLocation) {
|
|
|
- this.currentLocation = wechatLocation;
|
|
|
- this.updateLocationSuccess();
|
|
|
- uni.showToast({
|
|
|
- title: '微信定位成功',
|
|
|
- icon: 'success',
|
|
|
- duration: 1500
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- console.log('微信定位失败,尝试其他方案:', error);
|
|
|
+ this.locationLoading = true;
|
|
|
+ this.locationError = '';
|
|
|
+ uni.showLoading({ title: '定位中...', mask: true });
|
|
|
+
|
|
|
+ const envInfo = {
|
|
|
+ isWechatBrowser: this.isWechatBrowser,
|
|
|
+ isWechatSdkReady: this.wechatSDK.isInitialized,
|
|
|
+ isH5Web: this.isH5Web(),
|
|
|
+ isBrowserGeolocationSupported: this.isBrowserGeolocationSupported(),
|
|
|
+ };
|
|
|
+
|
|
|
+ console.log('环境检测结果:', envInfo);
|
|
|
+
|
|
|
+ // 优先级1:微信SDK定位(如果在微信环境且SDK已就绪)
|
|
|
+ if (this.isWechatBrowser && this.wechatSDK.isInitialized) {
|
|
|
+ const wxLocationSuccess = await this.tryWeChatLocationWithSDK();
|
|
|
+ if (wxLocationSuccess) {
|
|
|
+ return;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- // 方案2: 浏览器HTML5定位(H5环境)
|
|
|
- if (this.isH5Web() && this.isBrowserGeolocationSupported()) {
|
|
|
+
|
|
|
+ // 优先级2:微信环境但SDK未就绪,尝试初始化后重试
|
|
|
+ if (this.isWechatBrowser && !this.wechatSDK.isInitialized) {
|
|
|
try {
|
|
|
- uni.showToast({
|
|
|
- title: '正在浏览器定位...',
|
|
|
- icon: 'loading',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- const browserLocation = await this.getBrowserLocation();
|
|
|
- if (browserLocation) {
|
|
|
- this.currentLocation = browserLocation;
|
|
|
- this.updateLocationSuccess();
|
|
|
- uni.showToast({
|
|
|
- title: '浏览器定位成功',
|
|
|
- icon: 'success',
|
|
|
- duration: 1500
|
|
|
- });
|
|
|
- return;
|
|
|
+ await this.initWechatSDK();
|
|
|
+ if (this.wechatSDK.isInitialized) {
|
|
|
+ const wxLocationSuccess = await this.tryWeChatLocationWithSDK();
|
|
|
+ if (wxLocationSuccess) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- console.log('浏览器定位失败,尝试其他方案:', error);
|
|
|
+ console.error('微信SDK初始化失败:', error);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- // 方案3: uni-app定位(通用回退方案)
|
|
|
- try {
|
|
|
- uni.showToast({
|
|
|
- title: '正在系统定位...',
|
|
|
- icon: 'loading',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- const uniLocation = await this.getUniappLocation();
|
|
|
- if (uniLocation) {
|
|
|
- this.currentLocation = uniLocation;
|
|
|
- this.updateLocationSuccess();
|
|
|
- uni.showToast({
|
|
|
- title: '定位成功',
|
|
|
- icon: 'success',
|
|
|
- duration: 1500
|
|
|
- });
|
|
|
+
|
|
|
+ // 优先级3:H5 web端原生定位
|
|
|
+ if (this.isH5Web() && this.isBrowserGeolocationSupported()) {
|
|
|
+ const h5LocationSuccess = await this.handleH5WebLocation();
|
|
|
+ if (h5LocationSuccess) {
|
|
|
return;
|
|
|
}
|
|
|
- } catch (error) {
|
|
|
- console.log('uni-app定位失败:', error);
|
|
|
}
|
|
|
-
|
|
|
- // 所有定位方案都失败
|
|
|
- this.updateLocationError('定位失败,请检查网络连接和位置权限');
|
|
|
+
|
|
|
+ // 优先级4:uni-app通用定位(最后的回退方案)
|
|
|
+ await this.handleFallbackLocation();
|
|
|
|
|
|
} catch (error) {
|
|
|
- console.error('获取位置失败:', error);
|
|
|
- this.updateLocationError(error.message || '获取位置失败');
|
|
|
+ console.error('智能定位流程出错:', error);
|
|
|
+ this.updateLocationError(error.message || '定位失败');
|
|
|
+
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showModal({
|
|
|
+ title: '定位失败',
|
|
|
+ content: '定位功能暂时不可用,您可以手动输入位置信息或稍后重试。',
|
|
|
+ showCancel: true,
|
|
|
+ cancelText: '取消',
|
|
|
+ confirmText: '重试',
|
|
|
+ success: (res) => {
|
|
|
+ if (res.confirm) {
|
|
|
+ // 用户选择重试
|
|
|
+ this.getCurrentLocationInfo();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
} finally {
|
|
|
this.locationLoading = false;
|
|
|
}
|
|
|
},
|
|
|
|
|
|
/**
|
|
|
- * 微信定位
|
|
|
+ * 使用微信SDK进行定位(增强版)
|
|
|
*/
|
|
|
- async getWechatLocation() {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- // 检查微信环境
|
|
|
- if (!this.isWechatBrowser()) {
|
|
|
- reject(new Error('不在微信环境中'));
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 微信JSSDK定位
|
|
|
- if (typeof wx !== 'undefined' && wx.getLocation) {
|
|
|
- wx.getLocation({
|
|
|
- type: 'gcj02',
|
|
|
- success: (res) => {
|
|
|
- if (res.latitude && res.longitude) {
|
|
|
- resolve({
|
|
|
- latitude: res.latitude,
|
|
|
- longitude: res.longitude,
|
|
|
- accuracy: res.accuracy || 50,
|
|
|
- address: `${res.latitude.toFixed(6)}, ${res.longitude.toFixed(6)}`
|
|
|
- });
|
|
|
- } else {
|
|
|
- reject(new Error('微信定位返回数据无效'));
|
|
|
- }
|
|
|
- },
|
|
|
- fail: (error) => {
|
|
|
- console.error('微信定位失败:', error);
|
|
|
- reject(new Error('微信定位失败'));
|
|
|
- }
|
|
|
+ async tryWeChatLocationWithSDK() {
|
|
|
+ try {
|
|
|
+ console.log('=== 开始微信SDK定位 ===');
|
|
|
+ const result = await this.wechatSDK.getLocation({
|
|
|
+ type: 'gcj02', // 火星坐标系,适合国内地图
|
|
|
+ });
|
|
|
+
|
|
|
+ if (result.latitude && result.longitude) {
|
|
|
+ this.currentLocation = {
|
|
|
+ latitude: parseFloat(result.latitude),
|
|
|
+ longitude: parseFloat(result.longitude),
|
|
|
+ accuracy: result.accuracy || 50,
|
|
|
+ address: `${parseFloat(result.latitude).toFixed(6)}, ${parseFloat(result.longitude).toFixed(6)}`
|
|
|
+ };
|
|
|
+
|
|
|
+ this.updateLocationSuccess();
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showToast({
|
|
|
+ title: '微信定位成功',
|
|
|
+ icon: 'success',
|
|
|
+ duration: 2000,
|
|
|
});
|
|
|
+
|
|
|
+ return true;
|
|
|
} else {
|
|
|
- reject(new Error('微信JSSDK未初始化'));
|
|
|
+ console.warn('微信定位返回数据无效:', result);
|
|
|
+ return false;
|
|
|
}
|
|
|
- });
|
|
|
+ } catch (error) {
|
|
|
+ console.error('微信SDK定位失败:', error);
|
|
|
+
|
|
|
+ // 根据错误类型提供更友好的提示
|
|
|
+ if (error.message && error.message.includes('denied')) {
|
|
|
+ uni.showModal({
|
|
|
+ title: '定位权限',
|
|
|
+ content: '需要获取位置信息来记录打卡地点,请在微信中允许位置权限。',
|
|
|
+ showCancel: false,
|
|
|
+ confirmText: '知道了',
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
},
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
- * 浏览器HTML5定位
|
|
|
+ * H5 web端原生定位(增强版)
|
|
|
*/
|
|
|
- async getBrowserLocation() {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
+ async handleH5WebLocation() {
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ if (!this.isBrowserGeolocationSupported()) {
|
|
|
+ console.log('浏览器不支持原生定位API');
|
|
|
+ resolve(false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('=== 使用H5原生Geolocation API定位 ===');
|
|
|
+
|
|
|
+ const options = {
|
|
|
+ enableHighAccuracy: true, // 启用高精度定位
|
|
|
+ timeout: 15000, // 15秒超时
|
|
|
+ maximumAge: 300000, // 缓存5分钟
|
|
|
+ };
|
|
|
+
|
|
|
navigator.geolocation.getCurrentPosition(
|
|
|
(position) => {
|
|
|
+ console.log('H5原生定位成功:', position);
|
|
|
+
|
|
|
const { latitude, longitude, accuracy } = position.coords;
|
|
|
- resolve({
|
|
|
+
|
|
|
+ this.currentLocation = {
|
|
|
latitude: latitude,
|
|
|
longitude: longitude,
|
|
|
accuracy: accuracy || 100,
|
|
|
address: `${latitude.toFixed(6)}, ${longitude.toFixed(6)}`
|
|
|
+ };
|
|
|
+
|
|
|
+ this.updateLocationSuccess();
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showToast({
|
|
|
+ title: `定位成功 (精度: ${Math.round(accuracy)}m)`,
|
|
|
+ icon: 'success',
|
|
|
+ duration: 2000,
|
|
|
});
|
|
|
+
|
|
|
+ resolve(true);
|
|
|
},
|
|
|
(error) => {
|
|
|
- let errorMsg = '浏览器定位失败';
|
|
|
+ console.error('H5原生定位失败:', error);
|
|
|
+
|
|
|
+ let errorMessage = '定位失败';
|
|
|
switch (error.code) {
|
|
|
case error.PERMISSION_DENIED:
|
|
|
- errorMsg = '位置权限被拒绝';
|
|
|
+ errorMessage = '用户拒绝了定位请求';
|
|
|
break;
|
|
|
case error.POSITION_UNAVAILABLE:
|
|
|
- errorMsg = '位置信息不可用';
|
|
|
+ errorMessage = '位置信息不可用';
|
|
|
break;
|
|
|
case error.TIMEOUT:
|
|
|
- errorMsg = '定位超时';
|
|
|
+ errorMessage = '定位请求超时';
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ errorMessage = '定位出现未知错误';
|
|
|
break;
|
|
|
}
|
|
|
- reject(new Error(errorMsg));
|
|
|
+
|
|
|
+ // 显示友好的错误提示
|
|
|
+ uni.showModal({
|
|
|
+ title: '定位失败',
|
|
|
+ content: `${errorMessage}。是否手动输入位置信息?`,
|
|
|
+ showCancel: true,
|
|
|
+ cancelText: '取消',
|
|
|
+ confirmText: '稍后重试',
|
|
|
+ success: (res) => {
|
|
|
+ if (res.confirm) {
|
|
|
+ // 用户选择重试
|
|
|
+ uni.showToast({
|
|
|
+ title: '请稍后重试定位',
|
|
|
+ icon: 'none',
|
|
|
+ duration: 2000,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ resolve(false);
|
|
|
},
|
|
|
- {
|
|
|
- enableHighAccuracy: true,
|
|
|
- timeout: 15000,
|
|
|
- maximumAge: 60000
|
|
|
- }
|
|
|
+ options,
|
|
|
);
|
|
|
});
|
|
|
},
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
- * uni-app定位
|
|
|
+ * uni-app通用定位(回退方案)
|
|
|
*/
|
|
|
- async getUniappLocation() {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
+ async handleFallbackLocation() {
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ console.log('=== 使用uni-app通用定位 ===');
|
|
|
uni.getLocation({
|
|
|
type: 'gcj02',
|
|
|
geocode: true,
|
|
|
success: (res) => {
|
|
|
- resolve({
|
|
|
+ this.currentLocation = {
|
|
|
latitude: res.latitude,
|
|
|
longitude: res.longitude,
|
|
|
accuracy: res.accuracy || 100,
|
|
|
address: res.address || `${res.latitude.toFixed(6)}, ${res.longitude.toFixed(6)}`
|
|
|
+ };
|
|
|
+
|
|
|
+ this.updateLocationSuccess();
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showToast({
|
|
|
+ title: '定位成功',
|
|
|
+ icon: 'success',
|
|
|
+ duration: 2000
|
|
|
});
|
|
|
+ resolve(true);
|
|
|
},
|
|
|
fail: (error) => {
|
|
|
+ console.error('uni-app定位失败:', error);
|
|
|
let errorMsg = 'uni-app定位失败';
|
|
|
if (error.errMsg) {
|
|
|
if (error.errMsg.includes('auth deny')) {
|
|
|
@@ -730,12 +890,24 @@ export default {
|
|
|
errorMsg = '定位失败,请检查GPS设置';
|
|
|
}
|
|
|
}
|
|
|
- reject(new Error(errorMsg));
|
|
|
- }
|
|
|
+
|
|
|
+ this.updateLocationError(errorMsg);
|
|
|
+ uni.hideLoading();
|
|
|
+ uni.showToast({
|
|
|
+ title: errorMsg,
|
|
|
+ icon: 'none',
|
|
|
+ duration: 3000
|
|
|
+ });
|
|
|
+ resolve(false);
|
|
|
+ },
|
|
|
});
|
|
|
});
|
|
|
},
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 更新定位成功状态
|
|
|
*/
|
|
|
@@ -766,10 +938,12 @@ export default {
|
|
|
this.getCurrentLocationInfo();
|
|
|
},
|
|
|
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 打开位置信息在地图中查看
|
|
|
*/
|
|
|
- openLocationInMap() {
|
|
|
+ async openLocationInMap() {
|
|
|
if (!this.currentLocation) {
|
|
|
uni.showToast({
|
|
|
title: '无法获取位置信息',
|
|
|
@@ -779,23 +953,83 @@ export default {
|
|
|
}
|
|
|
|
|
|
const { latitude, longitude } = this.currentLocation;
|
|
|
- const name = this.currentLocation.address || '当前位置';
|
|
|
-
|
|
|
- // 使用uni.openLocation打开系统地图
|
|
|
- uni.openLocation({
|
|
|
- latitude: latitude,
|
|
|
- longitude: longitude,
|
|
|
- name: name,
|
|
|
- address: this.currentLocation.address || `${latitude.toFixed(6)}, ${longitude.toFixed(6)}`,
|
|
|
- success: () => {
|
|
|
- console.log('打开地图成功');
|
|
|
- },
|
|
|
- fail: (error) => {
|
|
|
- console.error('打开地图失败:', error);
|
|
|
- uni.showToast({
|
|
|
- title: '打开地图失败',
|
|
|
- icon: 'none'
|
|
|
+
|
|
|
+ if (!latitude || !longitude || isNaN(latitude) || isNaN(longitude)) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '位置信息无效',
|
|
|
+ icon: 'none',
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.isWechatBrowser && this.wechatSDK.isInitialized) {
|
|
|
+ try {
|
|
|
+ await this.wechatSDK.openLocation({
|
|
|
+ latitude: latitude,
|
|
|
+ longitude: longitude,
|
|
|
+ name: '实习签到位置',
|
|
|
+ address: this.currentLocation.address || '当前位置',
|
|
|
+ scale: 16,
|
|
|
});
|
|
|
+ } catch (error) {
|
|
|
+ console.error('微信地图打开失败:', error);
|
|
|
+ this.fallbackOpenMap(latitude, longitude);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.fallbackOpenMap(latitude, longitude);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 备用地图打开方式
|
|
|
+ fallbackOpenMap(latitude, longitude) {
|
|
|
+ // 首先尝试使用uni.openLocation(原生地图)
|
|
|
+ if (typeof uni.openLocation === 'function') {
|
|
|
+ uni.showLoading({
|
|
|
+ title: '打开地图中...'
|
|
|
+ });
|
|
|
+
|
|
|
+ uni.openLocation({
|
|
|
+ latitude: Number(latitude),
|
|
|
+ longitude: Number(longitude),
|
|
|
+ name: '实习签到位置',
|
|
|
+ address: this.currentLocation.address || '当前位置',
|
|
|
+ scale: 16,
|
|
|
+ success: () => {
|
|
|
+ console.log('使用uni.openLocation打开地图成功');
|
|
|
+ uni.hideLoading();
|
|
|
+ },
|
|
|
+ fail: (error) => {
|
|
|
+ console.error('uni.openLocation打开地图失败:', error);
|
|
|
+ uni.hideLoading();
|
|
|
+ this.showCopyCoordinatesOption(latitude, longitude);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 如果uni.openLocation不可用,显示复制坐标选项
|
|
|
+ this.showCopyCoordinatesOption(latitude, longitude);
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 显示复制坐标选项
|
|
|
+ showCopyCoordinatesOption(latitude, longitude) {
|
|
|
+ uni.showModal({
|
|
|
+ title: '无法打开地图',
|
|
|
+ content: '当前环境不支持地图功能,是否复制坐标到剪贴板?\n您可以在其他地图应用中粘贴坐标查看位置。',
|
|
|
+ showCancel: true,
|
|
|
+ cancelText: '取消',
|
|
|
+ confirmText: '复制坐标',
|
|
|
+ success: (res) => {
|
|
|
+ if (res.confirm) {
|
|
|
+ uni.setClipboardData({
|
|
|
+ data: `${latitude.toFixed(6)},${longitude.toFixed(6)}`,
|
|
|
+ success: () => {
|
|
|
+ uni.showToast({
|
|
|
+ title: '坐标已复制',
|
|
|
+ icon: 'success'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
});
|
|
|
},
|
|
|
@@ -980,6 +1214,126 @@ export default {
|
|
|
} else {
|
|
|
return { text: '低精度', type: 'warning' };
|
|
|
}
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 加载用户信息
|
|
|
+ */
|
|
|
+ async loadUserInfo() {
|
|
|
+ try {
|
|
|
+ const userInfo = userManager.getUserInfo();
|
|
|
+ if (userInfo) {
|
|
|
+ this.userInfo = userInfo;
|
|
|
+ console.log('用户信息加载成功:', userInfo);
|
|
|
+ } else {
|
|
|
+ console.warn('未获取到用户信息');
|
|
|
+ // 尝试重新获取
|
|
|
+ await userManager.refreshUserInfo();
|
|
|
+ this.userInfo = userManager.getUserInfo() || {};
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载用户信息失败:', error);
|
|
|
+ this.userInfo = {};
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查今日签到状态
|
|
|
+ */
|
|
|
+ async checkTodayCheckInStatus() {
|
|
|
+ try {
|
|
|
+ if (!this.internshipInfo?.internshipId) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const today = this.formatDate(new Date());
|
|
|
+ // 这里可以调用API检查今日签到状态
|
|
|
+ // const result = await checkTodayStatus(this.internshipInfo.internshipId, today);
|
|
|
+ // this.todayRecord = result.data;
|
|
|
+
|
|
|
+ // 暂时设置为未签到状态
|
|
|
+ this.todayRecord = null;
|
|
|
+ this.canCheckin = true;
|
|
|
+
|
|
|
+ console.log('今日签到状态检查完成');
|
|
|
+ } catch (error) {
|
|
|
+ console.error('检查今日签到状态失败:', error);
|
|
|
+ this.todayRecord = null;
|
|
|
+ this.canCheckin = true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查是否在微信浏览器环境
|
|
|
+ */
|
|
|
+ checkIsWechatBrowser() {
|
|
|
+ const ua = navigator.userAgent.toLowerCase();
|
|
|
+ return ua.includes('micromessenger');
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 页面加载时
|
|
|
+ */
|
|
|
+ onLoad() {
|
|
|
+ console.log('实习页面加载');
|
|
|
+ this.initPage();
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 页面显示时
|
|
|
+ */
|
|
|
+ onShow() {
|
|
|
+ console.log('实习页面显示');
|
|
|
+ this.refreshData();
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化页面
|
|
|
+ */
|
|
|
+ async initPage() {
|
|
|
+ // 设置当前日期
|
|
|
+ this.currentDate = this.formatDate(new Date());
|
|
|
+
|
|
|
+ // 检测微信环境
|
|
|
+ this.isWechatBrowser = this.checkIsWechatBrowser();
|
|
|
+
|
|
|
+ // 获取用户信息(不阻塞)
|
|
|
+ this.loadUserInfo().catch(error => {
|
|
|
+ console.error('用户信息加载失败:', error);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 获取实习信息(不阻塞)
|
|
|
+ this.loadInternshipInfo().catch(error => {
|
|
|
+ console.error('实习信息加载失败:', error);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 获取位置信息(核心功能,但不阻塞页面显示)
|
|
|
+ this.getCurrentLocationInfo().catch(error => {
|
|
|
+ console.error('位置信息获取失败:', error);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 检查今日签到状态(不阻塞)
|
|
|
+ this.checkTodayCheckInStatus().catch(error => {
|
|
|
+ console.error('签到状态检查失败:', error);
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 刷新数据
|
|
|
+ */
|
|
|
+ async refreshData() {
|
|
|
+ try {
|
|
|
+ // 刷新位置信息
|
|
|
+ if (!this.currentLocation) {
|
|
|
+ await this.getCurrentLocationInfo();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查今日签到状态
|
|
|
+ await this.checkTodayCheckInStatus();
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('数据刷新失败:', error);
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
@@ -1047,12 +1401,16 @@ export default {
|
|
|
margin-bottom: 16px;
|
|
|
padding-bottom: 12px;
|
|
|
border-bottom: 1px solid #f0f0f0;
|
|
|
+ min-height: 32px; /* 确保最小高度 */
|
|
|
+ gap: 8px; /* 确保元素之间有间距 */
|
|
|
}
|
|
|
|
|
|
.header-left {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
flex: 1;
|
|
|
+ min-width: 0; /* 允许flex子项收缩 */
|
|
|
+ margin-right: 12px; /* 与右侧按钮保持距离 */
|
|
|
}
|
|
|
|
|
|
.card-title {
|
|
|
@@ -1060,10 +1418,15 @@ export default {
|
|
|
font-weight: bold;
|
|
|
margin-left: 8px;
|
|
|
color: #303133;
|
|
|
+ white-space: nowrap; /* 防止文字换行 */
|
|
|
+ overflow: hidden; /* 隐藏溢出文字 */
|
|
|
+ text-overflow: ellipsis; /* 显示省略号 */
|
|
|
+ flex-shrink: 1; /* 允许收缩 */
|
|
|
}
|
|
|
|
|
|
.refresh-btn {
|
|
|
flex-shrink: 0;
|
|
|
+ min-width: 70px; /* 确保按钮最小宽度 */
|
|
|
}
|
|
|
|
|
|
.date-text {
|
|
|
@@ -1253,16 +1616,88 @@ export default {
|
|
|
.location-actions {
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
+ margin-top: 4px; /* 与上方内容保持间距 */
|
|
|
}
|
|
|
|
|
|
.map-btn {
|
|
|
min-width: 140px;
|
|
|
+ width: 100%; /* 在小屏幕上占满宽度 */
|
|
|
+ max-width: 200px; /* 最大宽度限制 */
|
|
|
}
|
|
|
|
|
|
.btn-text {
|
|
|
margin-left: 6px;
|
|
|
}
|
|
|
|
|
|
+/* 小屏幕适配 */
|
|
|
+@media screen and (max-width: 375px) {
|
|
|
+ .card-header {
|
|
|
+ flex-wrap: nowrap; /* 保持单行,避免换行 */
|
|
|
+ gap: 4px;
|
|
|
+ min-height: 36px; /* 稍微增加高度 */
|
|
|
+ }
|
|
|
+
|
|
|
+ .header-left {
|
|
|
+ min-width: 0; /* 允许完全收缩 */
|
|
|
+ flex: 1;
|
|
|
+ margin-right: 6px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .card-title {
|
|
|
+ font-size: 15px; /* 稍微减小字体 */
|
|
|
+ max-width: 100px; /* 限制最大宽度 */
|
|
|
+ }
|
|
|
+
|
|
|
+ .refresh-btn {
|
|
|
+ min-width: 58px; /* 小屏幕下减小按钮宽度 */
|
|
|
+ font-size: 12px; /* 减小按钮字体 */
|
|
|
+ }
|
|
|
+
|
|
|
+ .map-btn {
|
|
|
+ min-width: 120px;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 极小屏幕适配(iPhone SE等) */
|
|
|
+@media screen and (max-width: 320px) {
|
|
|
+ .card-header {
|
|
|
+ gap: 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .header-left {
|
|
|
+ margin-right: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .card-title {
|
|
|
+ font-size: 14px;
|
|
|
+ max-width: 80px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .refresh-btn {
|
|
|
+ min-width: 50px;
|
|
|
+ font-size: 11px;
|
|
|
+ padding: 4px 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .location-address {
|
|
|
+ padding: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .address-text {
|
|
|
+ font-size: 13px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .coord-row {
|
|
|
+ padding: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .map-btn {
|
|
|
+ min-width: 100px;
|
|
|
+ font-size: 13px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/* 位置获取失败提示 */
|
|
|
.location-error-card {
|
|
|
background: #fffbe6;
|