wuzhen update
This commit is contained in:
1 parent
cbfe6be210
commit
2150f54555
7 files changed
+716
-155
No files matched your search
+18
@@ -99,4 +99,22 @@ public class ZsjyInternshipDailyController extends BaseController {
|
|||||||
return dailyService.getStatistics(queryBo);
|
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
@@ -61,6 +61,18 @@ public interface ZsjyInternshipDailyMapper extends BaseMapper<ZsjyInternshipDail
|
|||||||
boolean existsByStudentAndDate(@Param("studentId") Long studentId,
|
boolean existsByStudentAndDate(@Param("studentId") Long studentId,
|
||||||
@Param("checkDate") Date checkDate);
|
@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
@@ -61,4 +61,14 @@ public interface IZsjyInternshipDailyService {
|
|||||||
*/
|
*/
|
||||||
R<Map<String, Object>> getStatistics(ZsjyInternshipDailyQueryBo queryBo);
|
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
@@ -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
@@ -184,6 +184,44 @@
|
|||||||
) as attendanceRate
|
) as attendanceRate
|
||||||
</select>
|
</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 id="existsByStudentAndDate" resultType="boolean">
|
||||||
SELECT COUNT(*) > 0
|
SELECT COUNT(*) > 0
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export const getCalendarData = (studentId, year, month) => {
|
|||||||
*/
|
*/
|
||||||
export const getStatistics = (params) => {
|
export const getStatistics = (params) => {
|
||||||
return request({
|
return request({
|
||||||
url: '/zsjy/internship/daily/statistics',
|
url: '/zsjy/internship/daily/monthly-statistics',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
params
|
params
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 位置信息卡片 -->
|
<!-- 位置信息卡片 -->
|
||||||
<view class="location-card" v-if="currentLocation">
|
<view class="location-card" v-if="currentLocation" style="display: none;">
|
||||||
<view class="card-header">
|
<view class="card-header">
|
||||||
<view class="header-left">
|
<view class="header-left">
|
||||||
<u-icon name="map-pin" size="18" color="#f56c6c"></u-icon>
|
<u-icon name="map-pin" size="18" color="#f56c6c"></u-icon>
|
||||||
@@ -204,7 +204,7 @@
|
|||||||
<!-- 考勤统计 -->
|
<!-- 考勤统计 -->
|
||||||
<view class="statistics-card">
|
<view class="statistics-card">
|
||||||
<view class="card-header">
|
<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>
|
<text class="card-title">本月考勤</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="stats-grid">
|
<view class="stats-grid">
|
||||||
@@ -228,7 +228,7 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 最近签到记录 -->
|
<!-- 最近签到记录 -->
|
||||||
<view class="records-card">
|
<view class="records-card" style="display: none;">
|
||||||
<view class="card-header">
|
<view class="card-header">
|
||||||
<u-icon name="list" size="18" color="#909399"></u-icon>
|
<u-icon name="list" size="18" color="#909399"></u-icon>
|
||||||
<text class="card-title">最近签到</text>
|
<text class="card-title">最近签到</text>
|
||||||
@@ -264,6 +264,7 @@
|
|||||||
import { getInternshipInfo, getStudentInternshipInfo, checkIn, getDailyList, getStatistics } from '@/api/internship.js';
|
import { getInternshipInfo, getStudentInternshipInfo, checkIn, getDailyList, getStatistics } from '@/api/internship.js';
|
||||||
import { getCurrentLocation, checkLocationPermission, openLocationSettings } from '@/utils/location.js';
|
import { getCurrentLocation, checkLocationPermission, openLocationSettings } from '@/utils/location.js';
|
||||||
import { userManager } from '@/utils/user.js';
|
import { userManager } from '@/utils/user.js';
|
||||||
|
import weChatSDK from '@/utils/wechat.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'InternshipIndex',
|
name: 'InternshipIndex',
|
||||||
@@ -281,11 +282,16 @@ export default {
|
|||||||
checkinTips: '',
|
checkinTips: '',
|
||||||
todayRecord: null,
|
todayRecord: null,
|
||||||
|
|
||||||
// 位置信息
|
// 位置信息(增强版)
|
||||||
currentLocation: null,
|
currentLocation: null,
|
||||||
locationLoading: false,
|
locationLoading: false,
|
||||||
locationError: '',
|
locationError: '',
|
||||||
|
|
||||||
|
// 微信SDK相关(新增)
|
||||||
|
wechatSDK: weChatSDK,
|
||||||
|
isWechatBrowser: false,
|
||||||
|
wechatInitializing: false,
|
||||||
|
|
||||||
// 统计数据
|
// 统计数据
|
||||||
monthStats: {
|
monthStats: {
|
||||||
totalDays: 0,
|
totalDays: 0,
|
||||||
@@ -313,7 +319,10 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
onLoad() {
|
async onLoad() {
|
||||||
|
// 初始化微信环境检查并自动初始化SDK
|
||||||
|
await this.checkWechatEnvironment();
|
||||||
|
|
||||||
this.initPage();
|
this.initPage();
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -324,8 +333,62 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
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() {
|
async initPage() {
|
||||||
try {
|
try {
|
||||||
@@ -343,6 +406,14 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化微信环境检测
|
||||||
|
this.isWechatBrowser = this.wechatSDK.isWeChatBrowser();
|
||||||
|
|
||||||
|
// 如果在微信环境,初始化微信SDK
|
||||||
|
if (this.isWechatBrowser) {
|
||||||
|
await this.initWechatSDK();
|
||||||
|
}
|
||||||
|
|
||||||
// 并行加载数据
|
// 并行加载数据
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.loadInternshipInfo(),
|
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() {
|
async getCurrentLocationInfo() {
|
||||||
this.locationLoading = true;
|
|
||||||
this.locationError = '';
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 方案1: 微信定位(微信浏览器环境)
|
this.locationLoading = true;
|
||||||
if (this.isWechatBrowser()) {
|
this.locationError = '';
|
||||||
try {
|
uni.showLoading({ title: '定位中...', mask: true });
|
||||||
uni.showToast({
|
|
||||||
title: '正在微信定位...',
|
const envInfo = {
|
||||||
icon: 'loading',
|
isWechatBrowser: this.isWechatBrowser,
|
||||||
duration: 2000
|
isWechatSdkReady: this.wechatSDK.isInitialized,
|
||||||
});
|
isH5Web: this.isH5Web(),
|
||||||
const wechatLocation = await this.getWechatLocation();
|
isBrowserGeolocationSupported: this.isBrowserGeolocationSupported(),
|
||||||
if (wechatLocation) {
|
};
|
||||||
this.currentLocation = wechatLocation;
|
|
||||||
this.updateLocationSuccess();
|
|
||||||
uni.showToast({
|
|
||||||
title: '微信定位成功',
|
|
||||||
icon: 'success',
|
|
||||||
duration: 1500
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log('微信定位失败,尝试其他方案:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 方案2: 浏览器HTML5定位(H5环境)
|
console.log('环境检测结果:', envInfo);
|
||||||
if (this.isH5Web() && this.isBrowserGeolocationSupported()) {
|
|
||||||
try {
|
// 优先级1:微信SDK定位(如果在微信环境且SDK已就绪)
|
||||||
uni.showToast({
|
if (this.isWechatBrowser && this.wechatSDK.isInitialized) {
|
||||||
title: '正在浏览器定位...',
|
const wxLocationSuccess = await this.tryWeChatLocationWithSDK();
|
||||||
icon: 'loading',
|
if (wxLocationSuccess) {
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
const browserLocation = await this.getBrowserLocation();
|
|
||||||
if (browserLocation) {
|
|
||||||
this.currentLocation = browserLocation;
|
|
||||||
this.updateLocationSuccess();
|
|
||||||
uni.showToast({
|
|
||||||
title: '浏览器定位成功',
|
|
||||||
icon: 'success',
|
|
||||||
duration: 1500
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log('浏览器定位失败,尝试其他方案:', 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
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.log('uni-app定位失败:', error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 所有定位方案都失败
|
// 优先级2:微信环境但SDK未就绪,尝试初始化后重试
|
||||||
this.updateLocationError('定位失败,请检查网络连接和位置权限');
|
if (this.isWechatBrowser && !this.wechatSDK.isInitialized) {
|
||||||
|
try {
|
||||||
|
await this.initWechatSDK();
|
||||||
|
if (this.wechatSDK.isInitialized) {
|
||||||
|
const wxLocationSuccess = await this.tryWeChatLocationWithSDK();
|
||||||
|
if (wxLocationSuccess) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('微信SDK初始化失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优先级3:H5 web端原生定位
|
||||||
|
if (this.isH5Web() && this.isBrowserGeolocationSupported()) {
|
||||||
|
const h5LocationSuccess = await this.handleH5WebLocation();
|
||||||
|
if (h5LocationSuccess) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优先级4:uni-app通用定位(最后的回退方案)
|
||||||
|
await this.handleFallbackLocation();
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取位置失败:', error);
|
console.error('智能定位流程出错:', error);
|
||||||
this.updateLocationError(error.message || '获取位置失败');
|
this.updateLocationError(error.message || '定位失败');
|
||||||
|
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showModal({
|
||||||
|
title: '定位失败',
|
||||||
|
content: '定位功能暂时不可用,您可以手动输入位置信息或稍后重试。',
|
||||||
|
showCancel: true,
|
||||||
|
cancelText: '取消',
|
||||||
|
confirmText: '重试',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
// 用户选择重试
|
||||||
|
this.getCurrentLocationInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
this.locationLoading = false;
|
this.locationLoading = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信定位
|
* 使用微信SDK进行定位(增强版)
|
||||||
*/
|
*/
|
||||||
async getWechatLocation() {
|
async tryWeChatLocationWithSDK() {
|
||||||
return new Promise((resolve, reject) => {
|
try {
|
||||||
// 检查微信环境
|
console.log('=== 开始微信SDK定位 ===');
|
||||||
if (!this.isWechatBrowser()) {
|
const result = await this.wechatSDK.getLocation({
|
||||||
reject(new Error('不在微信环境中'));
|
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 {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* H5 web端原生定位(增强版)
|
||||||
|
*/
|
||||||
|
async handleH5WebLocation() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (!this.isBrowserGeolocationSupported()) {
|
||||||
|
console.log('浏览器不支持原生定位API');
|
||||||
|
resolve(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 微信JSSDK定位
|
console.log('=== 使用H5原生Geolocation API定位 ===');
|
||||||
if (typeof wx !== 'undefined' && wx.getLocation) {
|
|
||||||
wx.getLocation({
|
const options = {
|
||||||
type: 'gcj02',
|
enableHighAccuracy: true, // 启用高精度定位
|
||||||
success: (res) => {
|
timeout: 15000, // 15秒超时
|
||||||
if (res.latitude && res.longitude) {
|
maximumAge: 300000, // 缓存5分钟
|
||||||
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('微信定位失败'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
reject(new Error('微信JSSDK未初始化'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 浏览器HTML5定位
|
|
||||||
*/
|
|
||||||
async getBrowserLocation() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
navigator.geolocation.getCurrentPosition(
|
navigator.geolocation.getCurrentPosition(
|
||||||
(position) => {
|
(position) => {
|
||||||
|
console.log('H5原生定位成功:', position);
|
||||||
|
|
||||||
const { latitude, longitude, accuracy } = position.coords;
|
const { latitude, longitude, accuracy } = position.coords;
|
||||||
resolve({
|
|
||||||
|
this.currentLocation = {
|
||||||
latitude: latitude,
|
latitude: latitude,
|
||||||
longitude: longitude,
|
longitude: longitude,
|
||||||
accuracy: accuracy || 100,
|
accuracy: accuracy || 100,
|
||||||
address: `${latitude.toFixed(6)}, ${longitude.toFixed(6)}`
|
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) => {
|
(error) => {
|
||||||
let errorMsg = '浏览器定位失败';
|
console.error('H5原生定位失败:', error);
|
||||||
|
|
||||||
|
let errorMessage = '定位失败';
|
||||||
switch (error.code) {
|
switch (error.code) {
|
||||||
case error.PERMISSION_DENIED:
|
case error.PERMISSION_DENIED:
|
||||||
errorMsg = '位置权限被拒绝';
|
errorMessage = '用户拒绝了定位请求';
|
||||||
break;
|
break;
|
||||||
case error.POSITION_UNAVAILABLE:
|
case error.POSITION_UNAVAILABLE:
|
||||||
errorMsg = '位置信息不可用';
|
errorMessage = '位置信息不可用';
|
||||||
break;
|
break;
|
||||||
case error.TIMEOUT:
|
case error.TIMEOUT:
|
||||||
errorMsg = '定位超时';
|
errorMessage = '定位请求超时';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorMessage = '定位出现未知错误';
|
||||||
break;
|
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);
|
||||||
},
|
},
|
||||||
{
|
options,
|
||||||
enableHighAccuracy: true,
|
|
||||||
timeout: 15000,
|
|
||||||
maximumAge: 60000
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* uni-app定位
|
* uni-app通用定位(回退方案)
|
||||||
*/
|
*/
|
||||||
async getUniappLocation() {
|
async handleFallbackLocation() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve) => {
|
||||||
|
console.log('=== 使用uni-app通用定位 ===');
|
||||||
uni.getLocation({
|
uni.getLocation({
|
||||||
type: 'gcj02',
|
type: 'gcj02',
|
||||||
geocode: true,
|
geocode: true,
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
resolve({
|
this.currentLocation = {
|
||||||
latitude: res.latitude,
|
latitude: res.latitude,
|
||||||
longitude: res.longitude,
|
longitude: res.longitude,
|
||||||
accuracy: res.accuracy || 100,
|
accuracy: res.accuracy || 100,
|
||||||
address: res.address || `${res.latitude.toFixed(6)}, ${res.longitude.toFixed(6)}`
|
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) => {
|
fail: (error) => {
|
||||||
|
console.error('uni-app定位失败:', error);
|
||||||
let errorMsg = 'uni-app定位失败';
|
let errorMsg = 'uni-app定位失败';
|
||||||
if (error.errMsg) {
|
if (error.errMsg) {
|
||||||
if (error.errMsg.includes('auth deny')) {
|
if (error.errMsg.includes('auth deny')) {
|
||||||
@@ -730,12 +890,24 @@ export default {
|
|||||||
errorMsg = '定位失败,请检查GPS设置';
|
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();
|
this.getCurrentLocationInfo();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开位置信息在地图中查看
|
* 打开位置信息在地图中查看
|
||||||
*/
|
*/
|
||||||
openLocationInMap() {
|
async openLocationInMap() {
|
||||||
if (!this.currentLocation) {
|
if (!this.currentLocation) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '无法获取位置信息',
|
title: '无法获取位置信息',
|
||||||
@@ -779,23 +953,83 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { latitude, longitude } = this.currentLocation;
|
const { latitude, longitude } = this.currentLocation;
|
||||||
const name = this.currentLocation.address || '当前位置';
|
|
||||||
|
if (!latitude || !longitude || isNaN(latitude) || isNaN(longitude)) {
|
||||||
// 使用uni.openLocation打开系统地图
|
uni.showToast({
|
||||||
uni.openLocation({
|
title: '位置信息无效',
|
||||||
latitude: latitude,
|
icon: 'none',
|
||||||
longitude: longitude,
|
});
|
||||||
name: name,
|
return;
|
||||||
address: this.currentLocation.address || `${latitude.toFixed(6)}, ${longitude.toFixed(6)}`,
|
}
|
||||||
success: () => {
|
|
||||||
console.log('打开地图成功');
|
if (this.isWechatBrowser && this.wechatSDK.isInitialized) {
|
||||||
},
|
try {
|
||||||
fail: (error) => {
|
await this.wechatSDK.openLocation({
|
||||||
console.error('打开地图失败:', error);
|
latitude: latitude,
|
||||||
uni.showToast({
|
longitude: longitude,
|
||||||
title: '打开地图失败',
|
name: '实习签到位置',
|
||||||
icon: 'none'
|
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 {
|
} else {
|
||||||
return { text: '低精度', type: 'warning' };
|
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;
|
margin-bottom: 16px;
|
||||||
padding-bottom: 12px;
|
padding-bottom: 12px;
|
||||||
border-bottom: 1px solid #f0f0f0;
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
min-height: 32px; /* 确保最小高度 */
|
||||||
|
gap: 8px; /* 确保元素之间有间距 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-left {
|
.header-left {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 0; /* 允许flex子项收缩 */
|
||||||
|
margin-right: 12px; /* 与右侧按钮保持距离 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-title {
|
.card-title {
|
||||||
@@ -1060,10 +1418,15 @@ export default {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
|
white-space: nowrap; /* 防止文字换行 */
|
||||||
|
overflow: hidden; /* 隐藏溢出文字 */
|
||||||
|
text-overflow: ellipsis; /* 显示省略号 */
|
||||||
|
flex-shrink: 1; /* 允许收缩 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.refresh-btn {
|
.refresh-btn {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
min-width: 70px; /* 确保按钮最小宽度 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.date-text {
|
.date-text {
|
||||||
@@ -1253,16 +1616,88 @@ export default {
|
|||||||
.location-actions {
|
.location-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
margin-top: 4px; /* 与上方内容保持间距 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.map-btn {
|
.map-btn {
|
||||||
min-width: 140px;
|
min-width: 140px;
|
||||||
|
width: 100%; /* 在小屏幕上占满宽度 */
|
||||||
|
max-width: 200px; /* 最大宽度限制 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-text {
|
.btn-text {
|
||||||
margin-left: 6px;
|
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 {
|
.location-error-card {
|
||||||
background: #fffbe6;
|
background: #fffbe6;
|
||||||
|
|||||||
Reference in new issue
Block a user