diff --git a/src/components/AlarmRecord.vue b/src/components/AlarmRecord.vue
index 6be29b3..6634f19 100644
--- a/src/components/AlarmRecord.vue
+++ b/src/components/AlarmRecord.vue
@@ -15,6 +15,21 @@
-->
+
+
+
+
+ {{ selectedDate || '请选择日期' }}
+ ▼
+
+
+
+
@@ -114,6 +129,11 @@ const isLoadingMore = ref(false);
const scrollTop = ref(0);
const isScrolling = ref(false);
+// 日期选择相关
+const selectedDate = ref('');
+const startTime = ref('');
+const endTime = ref('');
+
// 移除空行占位逻辑,没有数据时只显示"暂无数据"
// MQTT报警服务接口(预留)
@@ -151,10 +171,36 @@ const mqttAlarmService = {
isLoadingMore.value = true;
}
+ // 如果没有选择日期,使用默认日期(当天)
+ let queryStartTime = startTime.value;
+ let queryEndTime = endTime.value;
+
+ if (!queryStartTime || !queryEndTime) {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, '0');
+ const day = String(today.getDate()).padStart(2, '0');
+ const todayStr = `${year}-${month}-${day}`;
+
+ queryStartTime = `${todayStr} 00:00:00`;
+ queryEndTime = `${todayStr} 23:59:59`;
+
+ // 更新选择的日期
+ if (!selectedDate.value) {
+ selectedDate.value = todayStr;
+ startTime.value = queryStartTime;
+ endTime.value = queryEndTime;
+ }
+ }
+
+ console.log('📅 查询时间范围:', queryStartTime, '至', queryEndTime);
+
// 调用分页获取告警接口
- const response = await alertApi.getList({
+ const response = await alertApi.getListByCreateTime({
page: page,
- size: size
+ size: size,
+ startTime: queryStartTime,
+ endTime: queryEndTime
});
// 处理响应数据
@@ -408,6 +454,42 @@ const scrollToTop = () => {
scrollTop.value = scrollTop.value === 0 ? 1 : 0;
};
+// 日期选择处理,选择后直接查询
+const onDateChange = async (e) => {
+ selectedDate.value = e.detail.value;
+ console.log('选择的日期:', selectedDate.value);
+
+ // 自动构建开始和结束时间
+ if (selectedDate.value) {
+ startTime.value = `${selectedDate.value} 00:00:00`;
+ endTime.value = `${selectedDate.value} 23:59:59`;
+ console.log('开始时间:', startTime.value);
+ console.log('结束时间:', endTime.value);
+
+ // 选择日期后直接查询
+ console.log('🔍 开始查询报警记录');
+ console.log('查询时间范围:', startTime.value, '至', endTime.value);
+
+ try {
+ // 重置分页状态
+ currentPage.value = 0;
+ hasMoreData.value = true;
+ alarmList.value = [];
+
+ // 使用选择的日期范围查询
+ await mqttAlarmService.getHistoryAlarms(0, pageSize.value, false);
+
+ uni.showToast({
+ title: '查询成功',
+ icon: 'success',
+ duration: 1500
+ });
+ } catch (error) {
+ console.error('❌ 查询失败:', error);
+ }
+ }
+};
+
// 滚动到底部
const scrollToBottom = () => {
// 使用nextTick确保DOM更新完成
@@ -543,6 +625,49 @@ onUnmounted(() => {
height: 100%;
}
+// 日期选择器容器样式
+.date-picker-container {
+ display: flex;
+ align-items: center;
+ // justify-content: center;
+ padding: 20rpx 30rpx;
+ background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
+ border-bottom: 2rpx solid #e8eaed;
+}
+
+.date-picker {
+ width: 100%;
+ // max-width: 500rpx;
+}
+
+.picker-input {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 16rpx 24rpx;
+ background: #ffffff;
+ border: 2rpx solid #dadce0;
+ border-radius: 8rpx;
+ transition: all 0.3s ease;
+}
+
+.picker-input:active {
+ border-color: #1a73e8;
+ background: #f1f5ff;
+}
+
+.picker-text {
+ font-size: 26rpx;
+ color: #3c4043;
+ flex: 1;
+}
+
+.picker-icon {
+ font-size: 20rpx;
+ color: #5f6368;
+ margin-left: 12rpx;
+}
+
.alarm-content {
// 继承通用内容样式
flex: 1;
@@ -863,6 +988,18 @@ onUnmounted(() => {
.empty-text {
font-size: 28rpx;
}
+
+ .date-picker-container {
+ padding: 24rpx 32rpx;
+ }
+
+ .date-picker {
+ max-width: 600rpx;
+ }
+
+ .picker-text {
+ font-size: 28rpx;
+ }
}
// 响应式设计 - 手机设备适配
@@ -880,6 +1017,18 @@ onUnmounted(() => {
.empty-text {
font-size: 28rpx;
}
+
+ .date-picker-container {
+ padding: 16rpx 20rpx;
+ }
+
+ .date-picker {
+ max-width: 100%;
+ }
+
+ .picker-text {
+ font-size: 24rpx;
+ }
}
// 响应式设计 - 大屏设备适配
diff --git a/src/components/SystemLog.vue b/src/components/SystemLog.vue
index 4b1ee18..5f90e6e 100644
--- a/src/components/SystemLog.vue
+++ b/src/components/SystemLog.vue
@@ -15,6 +15,21 @@
-->
+
+
+
+
+ {{ selectedDate || '请选择日期' }}
+ ▼
+
+
+
+
@@ -91,6 +106,14 @@
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue';
import { eventApi } from '@/utils/api.js';
+// 接收父组件传递的查询日期
+const props = defineProps({
+ queryDate: {
+ type: String,
+ default: ''
+ }
+});
+
// 日志数据
const logList = ref([]);
const isLoading = ref(false);
@@ -107,6 +130,11 @@ const isLoadingMore = ref(false);
const scrollTop = ref(0);
const isScrolling = ref(false);
+// 日期选择相关
+const selectedDate = ref('');
+const startTime = ref('');
+const endTime = ref('');
+
// 移除空行占位逻辑,没有数据时只显示"暂无数据"
// 状态映射函数
@@ -167,8 +195,8 @@ const mqttLogService = {
},
// 获取历史日志(分页)
- getHistoryLogs: async (page = 0, size = 20, isLoadMore = false) => {
- console.log(`📄 加载第${page}页数据,每页${size}条`);
+ getHistoryLogs: async (page = 0, size = 20, isLoadMore = false, queryDate = '') => {
+ console.log(`📄 加载第${page}页数据,每页${size}条,查询日期:${queryDate}`);
try {
if (!isLoadMore) {
isLoading.value = true;
@@ -177,8 +205,40 @@ const mqttLogService = {
}
hasInitialized.value = true;
+ // 如果没有选择日期,使用默认日期(当天)
+ let queryStartTime = startTime.value;
+ let queryEndTime = endTime.value;
+
+ if (!queryStartTime || !queryEndTime) {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, '0');
+ const day = String(today.getDate()).padStart(2, '0');
+ const todayStr = `${year}-${month}-${day}`;
+
+ queryStartTime = `${todayStr} 00:00:00`;
+ queryEndTime = `${todayStr} 23:59:59`;
+
+ // 更新选择的日期
+ if (!selectedDate.value) {
+ selectedDate.value = todayStr;
+ startTime.value = queryStartTime;
+ endTime.value = queryEndTime;
+ }
+ }
+
+ console.log('📅 查询时间范围:', queryStartTime, '至', queryEndTime);
+
+ // 构建查询参数
+ const params = {
+ page: page,
+ size: size,
+ startTime: queryStartTime,
+ endTime: queryEndTime
+ };
+
// 调用事件API获取分页数据
- const response = await eventApi.getList({ page: page, size: size });
+ const response = await eventApi.getListByCreateTime(params);
// 将API数据转换为日志格式
const newLogs = response.data.map(item => ({
@@ -264,7 +324,7 @@ const onScrollToLower = () => {
const nextPage = currentPage.value + 1;
console.log(`📄 开始加载第${nextPage}页数据`);
- mqttLogService.getHistoryLogs(nextPage, pageSize.value, true);
+ mqttLogService.getHistoryLogs(nextPage, pageSize.value, true, props.queryDate);
};
// 滚动到顶部
@@ -272,6 +332,42 @@ const scrollToTop = () => {
scrollTop.value = scrollTop.value === 0 ? 1 : 0;
};
+// 日期选择处理,选择后直接查询
+const onDateChange = async (e) => {
+ selectedDate.value = e.detail.value;
+ console.log('选择的日期:', selectedDate.value);
+
+ // 自动构建开始和结束时间
+ if (selectedDate.value) {
+ startTime.value = `${selectedDate.value} 00:00:00`;
+ endTime.value = `${selectedDate.value} 23:59:59`;
+ console.log('开始时间:', startTime.value);
+ console.log('结束时间:', endTime.value);
+
+ // 选择日期后直接查询
+ console.log('🔍 开始查询系统日志');
+ console.log('查询时间范围:', startTime.value, '至', endTime.value);
+
+ try {
+ // 重置分页状态
+ currentPage.value = 0;
+ hasMoreData.value = true;
+ logList.value = [];
+
+ // 使用选择的日期范围查询
+ await mqttLogService.getHistoryLogs(0, pageSize.value, false, selectedDate.value);
+
+ uni.showToast({
+ title: '查询成功',
+ icon: 'success',
+ duration: 1500
+ });
+ } catch (error) {
+ console.error('❌ 查询失败:', error);
+ }
+ }
+};
+
// 组件生命周期
@@ -280,7 +376,7 @@ onMounted(async () => {
// 连接MQTT并初始化
// await mqttLogService.connect();
// await mqttLogService.subscribeLogData();
- await mqttLogService.getHistoryLogs(0, pageSize.value, false);
+ await mqttLogService.getHistoryLogs(0, pageSize.value, false, props.queryDate);
} catch (error) {
console.error('日志系统初始化失败:', error);
uni.showToast({
@@ -300,15 +396,32 @@ const refreshData = async () => {
logList.value = [];
// 重新获取第一页数据
- await mqttLogService.getHistoryLogs(0, pageSize.value, false);
+ await mqttLogService.getHistoryLogs(0, pageSize.value, false, props.queryDate);
} catch (error) {
console.error('❌ 刷新数据失败:', error);
}
};
+// 按日期查询方法
+const queryByDate = async (queryDate) => {
+ console.log('📅 按日期查询系统日志:', queryDate)
+ try {
+ // 重置分页状态
+ currentPage.value = 0;
+ hasMoreData.value = true;
+ logList.value = [];
+
+ // 按日期获取第一页数据
+ await mqttLogService.getHistoryLogs(0, pageSize.value, false, queryDate);
+ } catch (error) {
+ console.error('❌ 按日期查询失败:', error);
+ }
+};
+
// 暴露方法给父组件
defineExpose({
- refreshData
+ refreshData,
+ queryByDate
});
onUnmounted(() => {
@@ -332,6 +445,49 @@ onUnmounted(() => {
height: 100%;
}
+// 日期选择器容器样式
+.date-picker-container {
+ display: flex;
+ align-items: center;
+ // justify-content: center;
+ padding: 20rpx 30rpx;
+ background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
+ border-bottom: 2rpx solid #e8eaed;
+}
+
+.date-picker {
+ width: 100%;
+ // max-width: 500rpx;
+}
+
+.picker-input {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 16rpx 24rpx;
+ background: #ffffff;
+ border: 2rpx solid #dadce0;
+ border-radius: 8rpx;
+ transition: all 0.3s ease;
+}
+
+.picker-input:active {
+ border-color: #1a73e8;
+ background: #f1f5ff;
+}
+
+.picker-text {
+ font-size: 26rpx;
+ color: #3c4043;
+ flex: 1;
+}
+
+.picker-icon {
+ font-size: 20rpx;
+ color: #5f6368;
+ margin-left: 12rpx;
+}
+
.log-content {
// 继承通用内容样式
flex: 1;
@@ -547,74 +703,6 @@ onUnmounted(() => {
font-weight: 400;
}
-.table-loading-spinner {
- width: 60rpx;
- height: 60rpx;
- border: 4rpx solid #e9ecef;
- border-top: 4rpx solid #6c757d;
- border-radius: 50%;
- animation: spin 1s linear infinite;
-}
-
-.table-loading-text {
- font-size: 28rpx;
- color: #6c757d;
- font-weight: 500;
-}
-
-.table-empty-container {
- display: flex;
- justify-content: center;
- align-items: center;
- padding: 100rpx 20rpx;
- background-color: #ffffff;
-}
-
-.table-empty-text {
- font-size: 32rpx;
- color: #999;
- font-weight: 500;
-}
-
-.loading-container {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- padding: 60rpx;
- gap: 20rpx;
-}
-
-.loading-spinner {
- width: 60rpx;
- height: 60rpx;
- border: 4rpx solid rgba(255, 152, 0, 0.3);
- border-top: 4rpx solid #ff9800;
- border-radius: 50%;
- animation: spin 1s linear infinite;
-}
-
-@keyframes spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
-}
-
-.loading-text {
- font-size: 28rpx;
- color: #666;
-}
-
-.empty-container {
- display: flex;
- justify-content: center;
- align-items: center;
- padding: 100rpx;
-}
-
-.empty-text {
- font-size: 32rpx;
- color: #adb5bd;
-}
// 响应式设计 - 平板设备适配
@media (min-width: 768px) and (max-width: 1024px) {
@@ -631,6 +719,18 @@ onUnmounted(() => {
.empty-text {
font-size: 28rpx;
}
+
+ .date-picker-container {
+ padding: 24rpx 32rpx;
+ }
+
+ .date-picker {
+ max-width: 600rpx;
+ }
+
+ .picker-text {
+ font-size: 28rpx;
+ }
}
// 响应式设计 - 手机设备适配
@@ -648,6 +748,18 @@ onUnmounted(() => {
.empty-text {
font-size: 24rpx;
}
+
+ .date-picker-container {
+ padding: 16rpx 20rpx;
+ }
+
+ .date-picker {
+ max-width: 100%;
+ }
+
+ .picker-text {
+ font-size: 24rpx;
+ }
}
// 响应式设计 - 大屏设备适配
@@ -667,43 +779,43 @@ onUnmounted(() => {
}
}
-/* 加载更多样式 */
+// 加载更多样式
.load-more-container {
display: flex;
+ flex-direction: column;
align-items: center;
justify-content: center;
- padding: 30rpx;
- gap: 20rpx;
+ padding: 30rpx 20rpx;
+ gap: 15rpx;
+ background-color: #ffffff;
}
.load-more-spinner {
width: 40rpx;
height: 40rpx;
- border: 4rpx solid #f3f3f3;
- border-top: 4rpx solid #3f51b5;
+ border: 3rpx solid #e8eaed;
+ border-top: 3rpx solid #5f6368;
border-radius: 50%;
animation: spin 1s linear infinite;
}
-@keyframes spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
-}
-
.load-more-text {
- font-size: 28rpx;
- color: #666;
+ font-size: 24rpx;
+ color: #5f6368;
+ font-weight: 400;
}
.no-more-container {
display: flex;
- align-items: center;
justify-content: center;
- padding: 30rpx;
+ align-items: center;
+ padding: 30rpx 20rpx;
+ background-color: #ffffff;
}
.no-more-text {
- font-size: 28rpx;
- color: #999;
+ font-size: 24rpx;
+ color: #9aa0a6;
+ font-weight: 400;
}
\ No newline at end of file
diff --git a/src/pages/environment/index.vue b/src/pages/environment/index.vue
index 9081772..23b78d6 100644
--- a/src/pages/environment/index.vue
+++ b/src/pages/environment/index.vue
@@ -630,11 +630,8 @@ export default {
const currentStatus = mqttDataManager.getConnectionStatus()
}, 10000) // 每10秒检查一次
},
-
// 更新环境数据(仅处理MQTT的空调数据)
updateEnvironmentData(data) {
- console.log('============MQTT数据', data)
-
// 只处理空调AC数据,温湿度和PM25数据改为从接口获取
if (data.deviceType === 'AC') {
// 处理空调AC数据
diff --git a/src/pages/log/index.vue b/src/pages/log/index.vue
index bf1f290..36cdd2d 100644
--- a/src/pages/log/index.vue
+++ b/src/pages/log/index.vue
@@ -7,16 +7,23 @@
-
-
+
+
+
+
-
-
-
-
-
- {{ selectedDate }}
-
+
+
+
+
+ {{ selectedDate || '请选择日期' }}
+ ▼
-
-
+
@@ -82,10 +79,10 @@ export default {
data() {
return {
selectedDate: this.getTodayDate(), // 默认选择今天
- // 24小时数据 (0-23点)
- temperatureData: [22, 25, 28, 32, 35, 38, 40, 38, 35, 32, 28, 25, 22, 20, 18, 20, 22, 25, 28, 30, 32, 30, 28, 25],
- humidityData: [45, 50, 55, 60, 65, 70, 75, 70, 65, 60, 55, 50, 45, 40, 35, 40, 45, 50, 55, 60, 65, 60, 55, 50],
- pm25Data: [15, 18, 22, 25, 28, 32, 35, 32, 28, 25, 22, 18, 15, 12, 10, 12, 15, 18, 22, 25, 28, 25, 22, 18],
+ // 24小时数据 (0-23点) - 默认显示0
+ temperatureData: new Array(24).fill(0),
+ humidityData: new Array(24).fill(0),
+ pm25Data: new Array(24).fill(0),
connectionStatus: {
isConnected: false,
lastUpdate: null
@@ -143,7 +140,7 @@ export default {
type: 'value',
name: '温度(°C)',
min: 0,
- max: 100,
+ max: 80,
axisLabel: {
formatter: '{value}°C',
fontSize: 10
@@ -211,7 +208,7 @@ export default {
type: 'value',
name: '湿度(%)',
min: 0,
- max: 100,
+ max: 80,
axisLabel: {
formatter: '{value}%',
fontSize: 10
@@ -279,7 +276,7 @@ export default {
type: 'value',
name: 'PM2.5(μg/m³)',
min: 0,
- max: 100,
+ max: 50,
axisLabel: {
formatter: '{value}μg/m³',
fontSize: 10
@@ -323,6 +320,10 @@ export default {
},
onShow() {
console.log('📱 参数记录页面显示,触发页面更新')
+
+ // 重置时间相关状态
+ this.resetTimeState()
+
// 只有在非首次显示时才重新获取历史数据
// 首次显示时已经在onLoad中获取过了
if (this.hasInitialized) {
@@ -331,6 +332,11 @@ export default {
this.hasInitialized = true
}
},
+ onHide() {
+ console.log('📱 参数记录页面隐藏,清除数据缓存')
+ // 页面隐藏时清除数据,防止缓存
+ this.clearPageData()
+ },
onUnload() {
// 页面卸载时移除监听器
if (this.dataUpdateHandler) {
@@ -341,6 +347,57 @@ export default {
}
},
methods: {
+ // 重置时间相关状态
+ resetTimeState() {
+ console.log('🔄 重置时间相关状态')
+
+ // 页面切换后重置为默认查询模式(过去24小时)
+ this.queryMode = 'default'
+ this.selectedDate = this.getTodayDate()
+
+ console.log('📅 重置为默认查询模式,日期:', this.selectedDate)
+
+ // 强制更新X轴标签
+ this.$nextTick(() => {
+ this.updateCharts()
+ })
+ },
+
+ // 清除页面数据缓存
+ clearPageData() {
+ console.log('🧹 清除页面数据缓存')
+
+ // 清除图表数据
+ this.temperatureData = new Array(24).fill(0)
+ this.humidityData = new Array(24).fill(0)
+ this.pm25Data = new Array(24).fill(0)
+
+ // 清除历史数据
+ this.historyData = []
+
+ // 清除处理后的图表数据
+ this.chartData = {
+ temperature: [],
+ humidity: [],
+ pm: []
+ }
+
+ // 重置数据状态
+ this.dataStatus = {
+ isRealData: false,
+ lastUpdateTime: null,
+ dataSource: 'empty'
+ }
+
+ // 重置连接状态
+ this.connectionStatus = {
+ isConnected: false,
+ lastUpdate: null
+ }
+
+ console.log('✅ 页面数据缓存已清除')
+ },
+
// 生成x轴标签
generateXAxisLabels() {
if (this.queryMode === 'date') {
@@ -504,11 +561,10 @@ export default {
this.$refs.pm25ChartRef.init(this.pm25Option)
},
- // 上一天
- goToPreviousDay() {
- const currentDate = new Date(this.selectedDate)
- currentDate.setDate(currentDate.getDate() - 1)
- this.selectedDate = this.formatDate(currentDate)
+ // 日期选择处理,选择后直接查询
+ onDateChange(e) {
+ this.selectedDate = e.detail.value
+ console.log('选择的日期:', this.selectedDate)
this.queryMode = 'date' // 切换到按日期查询模式
// 显示加载状态
@@ -519,36 +575,12 @@ export default {
// 重新获取历史数据
this.getHistoryDataByDate().finally(() => {
uni.hideLoading()
- })
- },
-
- // 下一天
- goToNextDay() {
- const currentDate = new Date(this.selectedDate)
- const today = new Date()
-
- // 检查是否已经是今天,如果是则不允许继续往后
- if (this.selectedDate >= this.formatDate(today)) {
+
uni.showToast({
- title: '不能查看未来日期',
- icon: 'none',
- duration: 2000
+ title: '查询成功',
+ icon: 'success',
+ duration: 1500
})
- return
- }
-
- currentDate.setDate(currentDate.getDate() + 1)
- this.selectedDate = this.formatDate(currentDate)
- this.queryMode = 'date' // 切换到按日期查询模式
-
- // 显示加载状态
- uni.showLoading({
- title: '加载数据中...'
- })
-
- // 重新获取历史数据
- this.getHistoryDataByDate().finally(() => {
- uni.hideLoading()
})
},
@@ -574,7 +606,7 @@ export default {
},
// 根据选择的日期获取历史数据
- async getHistoryDataByDate() {
+ async getHistoryDataByDate(retryCount = 0) {
try {
// 根据选择的日期构建时间范围
const startTime = `${this.selectedDate} 00:00:00`
@@ -585,7 +617,10 @@ export default {
endTime: endTime
}
- const response = await dataHistoryApi.getHistory(params)
+ console.log('📊 请求历史数据(按日期):', params, `第${retryCount + 1}次尝试`)
+
+ // 增加超时时间到20秒
+ const response = await dataHistoryApi.getHistory(params, { timeout: 20000 })
// 处理历史数据
if (response && Array.isArray(response) && response.length > 0) {
@@ -621,6 +656,21 @@ export default {
} catch (error) {
console.error('❌ 历史数据获取失败:', error)
+
+ // 如果是超时错误且重试次数少于2次,则重试
+ if (error.message.includes('timeout') && retryCount < 2) {
+ console.log(`🔄 网络超时,正在重试... (${retryCount + 1}/2)`)
+ uni.showToast({
+ title: `网络超时,重试中...`,
+ icon: 'loading',
+ duration: 1500
+ })
+
+ // 等待1秒后重试
+ await new Promise(resolve => setTimeout(resolve, 1000))
+ return this.getHistoryDataByDate(retryCount + 1)
+ }
+
// 出错时显示空状态
this.showEmptyState()
@@ -635,18 +685,20 @@ export default {
await this.createQueryEvent('error', 0)
// 显示错误提示
+ const errorMessage = error.message.includes('timeout') ? '网络连接超时,请检查网络' : '数据加载失败'
uni.showToast({
- title: '数据加载失败',
+ title: errorMessage,
icon: 'none',
- duration: 2000
+ duration: 3000
})
- throw error
+ // 不再抛出错误,避免未捕获的Promise错误
+ return null
}
},
// 获取历史数据(默认过去24小时)
- async getHistoryData() {
+ async getHistoryData(retryCount = 0) {
try {
// 构建时间范围:从当前时间开始过去24小时
const now = new Date()
@@ -661,11 +713,10 @@ export default {
endTime: endTime
}
- console.log('📊 请求历史数据(过去24小时):', params)
+ console.log('📊 请求历史数据(过去24小时):', params, `第${retryCount + 1}次尝试`)
- const response = await dataHistoryApi.getHistory(params)
-
- console.log('✅ 历史数据获取成功:', response)
+ // 增加超时时间到20秒
+ const response = await dataHistoryApi.getHistory(params, { timeout: 20000 })
// 处理历史数据
if (response && Array.isArray(response) && response.length > 0) {
@@ -701,6 +752,21 @@ export default {
} catch (error) {
console.error('❌ 历史数据获取失败:', error)
+
+ // 如果是超时错误且重试次数少于2次,则重试
+ if (error.message.includes('timeout') && retryCount < 2) {
+ console.log(`🔄 网络超时,正在重试... (${retryCount + 1}/2)`)
+ uni.showToast({
+ title: `网络超时,重试中...`,
+ icon: 'loading',
+ duration: 1500
+ })
+
+ // 等待1秒后重试
+ await new Promise(resolve => setTimeout(resolve, 1000))
+ return this.getHistoryData(retryCount + 1)
+ }
+
// 出错时显示空状态
this.showEmptyState()
@@ -715,13 +781,15 @@ export default {
await this.createQueryEvent('error', 0)
// 显示错误提示
+ const errorMessage = error.message.includes('timeout') ? '网络连接超时,请检查网络' : '数据加载失败'
uni.showToast({
- title: '数据加载失败',
+ title: errorMessage,
icon: 'none',
- duration: 2000
+ duration: 3000
})
- throw error
+ // 不再抛出错误,避免未捕获的Promise错误
+ return null
}
},
@@ -1012,122 +1080,61 @@ export default {
overflow: hidden;
}
-.date-selector {
- background: white;
- border-radius: 12rpx;
- padding: 20rpx;
- margin-bottom: 20rpx;
- box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
+.header-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+ text-align: center;
}
-.time-range-info {
+.tabbar-content {
+ flex: 1;
+ overflow-y: auto;
+}
+
+// 日期选择器容器样式
+.date-picker-container {
+ display: flex;
+ align-items: center;
+ // justify-content: center;
+ padding: 20rpx 30rpx;
+ background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
+ border-bottom: 2rpx solid #e8eaed;
+}
+
+.date-picker {
+ width: 100%;
+ // max-width: 500rpx;
+}
+
+.picker-input {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 16rpx 24rpx;
+ background: #ffffff;
+ border: 2rpx solid #dadce0;
+ border-radius: 8rpx;
+ transition: all 0.3s ease;
+}
+
+.picker-input:active {
+ border-color: #1a73e8;
+ background: #f1f5ff;
+}
+
+.picker-text {
+ font-size: 26rpx;
+ color: #3c4043;
flex: 1;
}
-.time-range-text {
- font-size: 26rpx;
- color: #333;
- font-weight: 500;
+.picker-icon {
+ font-size: 20rpx;
+ color: #5f6368;
+ margin-left: 12rpx;
}
-.connection-status {
- font-size: 24rpx;
- font-weight: bold;
- padding: 8rpx 16rpx;
- border-radius: 20rpx;
-}
-
-.connection-status.connected {
- background-color: #e8f5e8;
- color: #4caf50;
-}
-
-.data-status {
- font-size: 24rpx;
- font-weight: bold;
- padding: 8rpx 16rpx;
- border-radius: 20rpx;
-}
-
-.data-status.api {
- background-color: #e8f5e8;
- color: #4caf50;
-}
-
-.data-status.default {
- background-color: #fff3e0;
- color: #ff9800;
-}
-
-.data-status .status-text {
- font-size: 24rpx;
-}
-
-.date-navigation {
- display: flex;
- align-items: center;
- gap: 15rpx;
- justify-content: space-between;
-}
-
-.nav-button {
- // padding: 12rpx 20rpx;
- // background: #007aff;
- // color: white;
- margin: 0;
- border: none;
- border-radius: 8rpx;
- font-size: 24rpx;
- // min-width: 120rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 6rpx;
- transition: all 0.2s ease;
-}
-
-.nav-button:active {
- // background: #0056b3;
- transform: scale(0.95);
-}
-
-.nav-button::after {
- border: none;
-}
-
-.nav-icon {
- font-size: 24rpx;
- color: white;
-}
-
-.nav-text {
- // color: white;
- font-size: 24rpx;
- font-weight: 500;
-}
-
-.current-date {
- padding: 16rpx 24rpx;
- background: #f8f9fa;
- border-radius: 8rpx;
- min-width: 180rpx;
- text-align: center;
- border: 1rpx solid #e9ecef;
-}
-
-.date-text {
- font-size: 28rpx;
- color: #333;
- font-weight: 600;
- display: block;
- margin-bottom: 4rpx;
-}
-
-.date-weekday {
- font-size: 22rpx;
- color: #666;
- font-weight: 400;
-}
.chart-card {
background: white;
@@ -1190,4 +1197,34 @@ export default {
width: 100%;
// padding: 0 20rpx;
}
+
+// 响应式设计 - 平板设备适配
+@media (min-width: 768px) and (max-width: 1024px) {
+ .date-picker-container {
+ padding: 24rpx 32rpx;
+ }
+
+ .date-picker {
+ max-width: 600rpx;
+ }
+
+ .picker-text {
+ font-size: 28rpx;
+ }
+}
+
+// 响应式设计 - 手机设备适配
+@media (max-width: 750rpx) {
+ .date-picker-container {
+ padding: 16rpx 20rpx;
+ }
+
+ .date-picker {
+ max-width: 100%;
+ }
+
+ .picker-text {
+ font-size: 24rpx;
+ }
+}
\ No newline at end of file
diff --git a/src/utils/api.js b/src/utils/api.js
index f23845d..9333f2b 100644
--- a/src/utils/api.js
+++ b/src/utils/api.js
@@ -36,7 +36,14 @@ export const alertApi = {
// 分页获取告警
getList(params = {}) {
return httpService.get('/api/alerts', params)
- }
+ },
+
+ // 根据创建时间获取告警
+ // http://110.40.171.179:7999/api/alerts/byCreateTime
+ // startTime endTime page size
+ getListByCreateTime(params = {}) {
+ return httpService.get('/api/alerts/byCreateTime', params)
+ },
}
// 事件相关接口
@@ -49,6 +56,11 @@ export const eventApi = {
// 分页获取事件
getList(params = {}) {
return httpService.get('/api/events', params)
+ },
+
+ // 根据创建时间获取事件
+ getListByCreateTime(params = {}) {
+ return httpService.get('/api/events/byCreateTime', params)
}
}
diff --git a/src/utils/sendMqtt.js b/src/utils/sendMqtt.js
index 99d7e7d..982a3cd 100644
--- a/src/utils/sendMqtt.js
+++ b/src/utils/sendMqtt.js
@@ -122,6 +122,9 @@ const initEventHandleMqtt = (topicUrl) => {
duration: 3000
});
} else {
+ sendMqttDataRecall({
+ command: 'Upload immediately',
+ })
// console.log("✅ MQTT订阅主题成功:", topicUrl);
}
});
@@ -299,6 +302,57 @@ const sendMqttData = (data) => {
}
};
+// 发送MQTT数据(单独订阅HDYDCJ_01_RECALL)
+const sendMqttDataRecall = (data) => {
+ try {
+ if (!client || !client.connected) {
+ console.error('❌ MQTT客户端未连接,无法发送数据');
+ uni.showToast({
+ title: 'MQTT未连接',
+ icon: 'error',
+ duration: 2000
+ });
+ return false;
+ }
+
+ const message = JSON.stringify(data);
+ // 先订阅HDYDCJ_01_RECALL主题(如果还没有订阅)
+ client.subscribe("HDYDCJ_01_RECALL", (err) => {
+ if (err) {
+ console.error('❌ 订阅HDYDCJ_01_RECALL失败:', err);
+ } else {
+ console.log('✅ 订阅HDYDCJ_01_RECALL成功');
+ }
+ });
+
+ // 发送数据到HDYDCJ_01_RECALL主题
+ client.publish("HDYDCJ_01_RECALL", message, (err) => {
+ if (err) {
+ uni.showToast({
+ title: '数据发送失败',
+ icon: 'error',
+ duration: 2000
+ });
+ } else {
+ uni.showToast({
+ title: '数据发送成功',
+ icon: 'success',
+ duration: 1500
+ });
+ }
+ });
+
+ return true;
+ } catch (error) {
+ uni.showToast({
+ title: '发送数据异常',
+ icon: 'error',
+ duration: 2000
+ });
+ return false;
+ }
+};
+
export {
createMqtt,
closeMqtt,
@@ -306,5 +360,6 @@ export {
getConnectionStatus,
manualReconnect,
sendMqttData,
+ sendMqttDataRecall,
client,
}
\ No newline at end of file