Explorar o código

wuzhen update

wuzhen hai 1 ano
pai
achega
2150f54555

+ 18 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/controller/ZsjyInternshipDailyController.java

@@ -99,4 +99,22 @@ public class ZsjyInternshipDailyController extends BaseController {
         return dailyService.getStatistics(queryBo);
     }
 
+    /**
+     * 获取学生个人月度考勤统计(移动端专用)
+     */
+    @Operation(summary = "获取学生月度统计", description = "获取指定学生的月度考勤统计数据")
+    @SaCheckPermission("zsjy:internshipdaily:statistics")
+    @GetMapping("/monthly-statistics")
+    public R<Map<String, Object>> getStudentMonthlyStatistics(
+            @Parameter(description = "学生ID", required = true) @RequestParam Long studentId,
+            @Parameter(description = "年份", required = true) @RequestParam Integer year,
+            @Parameter(description = "月份", required = true) @RequestParam Integer month) {
+
+        log.info("=== Controller层调试 ===");
+        log.info("接口被调用: /zsjy/internship/daily/monthly-statistics");
+        log.info("学生ID: {}, 年月: {}-{}", studentId, year, month);
+
+        return dailyService.getStudentMonthlyStatistics(studentId, year, month);
+    }
+
 }

+ 12 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/mapper/ZsjyInternshipDailyMapper.java

@@ -61,6 +61,18 @@ public interface ZsjyInternshipDailyMapper extends BaseMapper<ZsjyInternshipDail
     boolean existsByStudentAndDate(@Param("studentId") Long studentId,
                                   @Param("checkDate") Date checkDate);
 
+    /**
+     * 获取学生个人月度考勤统计
+     *
+     * @param studentId 学生ID
+     * @param year 年份
+     * @param month 月份
+     * @return 学生月度统计数据
+     */
+    Map<String, Object> selectStudentMonthlyStatistics(@Param("studentId") Long studentId,
+                                                      @Param("year") Integer year,
+                                                      @Param("month") Integer month);
+
     /**
      * 统计班主任管理的班级数量
      *

+ 10 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/IZsjyInternshipDailyService.java

@@ -61,4 +61,14 @@ public interface IZsjyInternshipDailyService {
      */
     R<Map<String, Object>> getStatistics(ZsjyInternshipDailyQueryBo queryBo);
 
+    /**
+     * 获取学生个人月度考勤统计
+     *
+     * @param studentId 学生ID
+     * @param year 年份
+     * @param month 月份
+     * @return 学生月度统计数据
+     */
+    R<Map<String, Object>> getStudentMonthlyStatistics(Long studentId, Integer year, Integer month);
+
 }

+ 48 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/java/org/dromara/zsjy/service/impl/ZsjyInternshipDailyServiceImpl.java

@@ -216,6 +216,54 @@ public class ZsjyInternshipDailyServiceImpl implements IZsjyInternshipDailyServi
         }
     }
 
+    /**
+     * 获取学生个人月度考勤统计
+     */
+    @Override
+    public R<Map<String, Object>> getStudentMonthlyStatistics(Long studentId, Integer year, Integer month) {
+        try {
+            // 1. 参数校验
+            if (ObjectUtil.isNull(studentId)) {
+                return R.fail("学生ID不能为空");
+            }
+            if (ObjectUtil.isNull(year) || ObjectUtil.isNull(month)) {
+                return R.fail("年月参数不能为空");
+            }
+            if (year < 2020 || year > 2030) {
+                return R.fail("年份参数不合法");
+            }
+            if (month < 1 || month > 12) {
+                return R.fail("月份参数不合法");
+            }
+
+            // 2. 查询学生月度统计数据
+            Map<String, Object> statistics = baseMapper.selectStudentMonthlyStatistics(studentId, year, month);
+
+            // 3. 补充默认值
+            if (ObjectUtil.isNull(statistics)) {
+                statistics = new HashMap<>();
+                statistics.put("totalDays", 0);
+                statistics.put("checkedDays", 0);
+                statistics.put("missedDays", 0);
+                statistics.put("exceptionDays", 0);
+            }
+
+            // 4. 确保数据类型正确
+            statistics.put("totalDays", ObjectUtil.defaultIfNull(statistics.get("totalDays"), 0));
+            statistics.put("checkedDays", ObjectUtil.defaultIfNull(statistics.get("checkedDays"), 0));
+            statistics.put("missedDays", ObjectUtil.defaultIfNull(statistics.get("missedDays"), 0));
+            statistics.put("exceptionDays", ObjectUtil.defaultIfNull(statistics.get("exceptionDays"), 0));
+
+            log.info("学生{}的{}-{}月度统计: {}", studentId, year, month, statistics);
+            return R.ok(statistics);
+
+        } catch (Exception e) {
+            log.error("获取学生月度统计数据失败: studentId={}, year={}, month={}, error={}",
+                     studentId, year, month, e.getMessage(), e);
+            return R.fail("获取学生月度统计数据失败: " + e.getMessage());
+        }
+    }
+
         /**
      * 设置数据权限(班主任只能查看自己班级的学生数据)
      */

+ 38 - 0
backend/ruoyi-modules/ruoyi-zsjy/src/main/resources/mapper/ZsjyInternshipDailyMapper.xml

@@ -184,6 +184,44 @@
             ) as attendanceRate
     </select>
 
+        <!-- 获取学生个人月度考勤统计 -->
+    <select id="selectStudentMonthlyStatistics" resultType="java.util.Map">
+        <![CDATA[
+        SELECT
+            -- 本月工作日总天数(简化计算,按22天计算)
+            22 as totalDays,
+
+            -- 已签到天数
+            (SELECT COUNT(*)
+             FROM zsjy_internship_daily
+             WHERE student_id = #{studentId}
+               AND deleted = 0
+               AND YEAR(check_date) = #{year}
+               AND MONTH(check_date) = #{month}
+               AND check_in_time IS NOT NULL) as checkedDays,
+
+            -- 异常天数
+            (SELECT COUNT(*)
+             FROM zsjy_internship_daily
+             WHERE student_id = #{studentId}
+               AND deleted = 0
+               AND YEAR(check_date) = #{year}
+               AND MONTH(check_date) = #{month}
+               AND is_exception = '1') as exceptionDays,
+
+            -- 未签到天数(22 - 已签到 - 异常)
+            (22 - 
+             (SELECT COUNT(*)
+              FROM zsjy_internship_daily
+              WHERE student_id = #{studentId}
+                AND deleted = 0
+                AND YEAR(check_date) = #{year}
+                AND MONTH(check_date) = #{month}
+                AND (check_in_time IS NOT NULL OR is_exception = '1'))
+            ) as missedDays
+        ]]>
+    </select>
+
     <!-- 检查学生当日是否已签到 -->
     <select id="existsByStudentAndDate" resultType="boolean">
         SELECT COUNT(*) > 0

+ 1 - 1
mobile/src/api/internship.js

@@ -63,7 +63,7 @@ export const getCalendarData = (studentId, year, month) => {
  */
 export const getStatistics = (params) => {
     return request({
-        url: '/zsjy/internship/daily/statistics',
+        url: '/zsjy/internship/daily/monthly-statistics',
         method: 'GET',
         params
     });

+ 579 - 144
mobile/src/pages/internship/index.vue

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