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