Files
movecheck/src/pages/parameter/index.vue

892 lines
25 KiB
Vue
Raw Normal View History

2025-09-29 23:53:09 +08:00
<template>
<view class="parameter-record-page">
<!-- 固定头部 -->
<view class="fixed-header">
<text class="header-title">移动式检修车间</text>
</view>
<!-- 内容区域 -->
<view class="tabbar-content">
<!-- 日期选择器 -->
<view class="date-selector">
<picker mode="date" :value="selectedDate" @change="onDateChange">
<view class="date-picker">
<text class="date-text">{{ selectedDate }}</text>
<text class="picker-arrow"></text>
</view>
</picker>
<!-- <view class="data-status" :class="dataStatus.dataSource">
<text class="status-text">{{ dataStatus.dataSource === 'api' ? '实时数据' : '示例数据' }}</text>
</view> -->
2025-09-29 23:53:09 +08:00
</view>
<!-- 温度趋势图表 -->
<view class="chart-card">
<view class="chart-header">
<text class="chart-title">温度趋势 (WD)</text>
<!-- <view class="status-indicator">
2025-09-29 23:53:09 +08:00
<view class="status-dot temperature-dot"></view>
<text class="status-text">{{ chartData.temperature.length > 0 ? '有数据' : '无数据' }}</text>
</view> -->
2025-09-29 23:53:09 +08:00
</view>
<view class="chart-container">
<e-chart ref="temperatureChartRef" @ready="initTemperatureChart" :height="400" />
2025-09-29 23:53:09 +08:00
</view>
</view>
<!-- 湿度趋势图表 -->
<view class="chart-card">
<view class="chart-header">
<text class="chart-title">湿度趋势 (SD)</text>
<!-- <view class="status-indicator">
2025-09-29 23:53:09 +08:00
<view class="status-dot humidity-dot"></view>
<text class="status-text">{{ chartData.humidity.length > 0 ? '有数据' : '无数据' }}</text>
</view> -->
2025-09-29 23:53:09 +08:00
</view>
<view class="chart-container">
<e-chart ref="humidityChartRef" @ready="initHumidityChart" :height="400" />
2025-09-29 23:53:09 +08:00
</view>
</view>
<!-- PM2.5趋势图表 -->
<view class="chart-card">
<view class="chart-header">
<text class="chart-title">PM趋势 (PM)</text>
<!-- <view class="status-indicator">
2025-09-29 23:53:09 +08:00
<view class="status-dot pm25-dot"></view>
<text class="status-text">{{ chartData.pm.length > 0 ? '有数据' : '无数据' }}</text>
</view> -->
2025-09-29 23:53:09 +08:00
</view>
<view class="chart-container">
<e-chart ref="pm25ChartRef" @ready="initPM25Chart" :height="400" />
2025-09-29 23:53:09 +08:00
</view>
</view>
</view>
</view>
</template>
<script>
import mqttDataManager from '@/utils/mqttDataManager.js'
2025-10-01 04:07:37 +08:00
import { dataHistoryApi, eventApi } from '@/utils/api.js'
import EChart from '@/uni_modules/e-chart/components/e-chart/e-chart.vue'
2025-09-29 23:53:09 +08:00
export default {
components: {
EChart
},
2025-09-29 23:53:09 +08:00
data() {
return {
selectedDate: this.getTodayDate(), // 默认选择今天
2025-09-29 23:53:09 +08:00
// 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],
connectionStatus: {
isConnected: false,
lastUpdate: null
},
// 历史数据
historyData: [],
// 处理后的图表数据
chartData: {
temperature: [],
humidity: [],
pm: []
},
// 数据状态
dataStatus: {
isRealData: false,
lastUpdateTime: null,
dataSource: 'empty' // 'api' | 'empty' | 'error'
},
2025-10-01 04:07:37 +08:00
// 页面初始化状态
hasInitialized: false,
// ECharts配置选项
temperatureOption: {
title: {
text: '温度趋势',
left: 'center',
textStyle: {
fontSize: 16,
color: '#333'
}
},
tooltip: {
trigger: 'axis',
formatter: function(params) {
const data = params[0];
return `时间: ${data.axisValue}<br/>温度: ${data.value}°C`;
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: Array.from({length: 24}, (_, i) => `${i.toString().padStart(2, '0')}:00`),
axisLabel: {
interval: 3, // 每4个小时显示一个标签
fontSize: 10
}
},
yAxis: {
type: 'value',
name: '温度(°C)',
min: 0,
max: 100,
axisLabel: {
formatter: '{value}°C',
fontSize: 10
}
},
series: [{
name: '温度',
type: 'line',
data: [],
smooth: true,
lineStyle: {
color: '#ff6b35',
width: 3
},
itemStyle: {
color: '#ff6b35'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'rgba(255, 107, 53, 0.3)'
}, {
offset: 1, color: 'rgba(255, 107, 53, 0.1)'
}]
}
}
}]
},
humidityOption: {
title: {
text: '湿度趋势',
left: 'center',
textStyle: {
fontSize: 16,
color: '#333'
}
},
tooltip: {
trigger: 'axis',
formatter: function(params) {
const data = params[0];
return `时间: ${data.axisValue}<br/>湿度: ${data.value}%`;
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: Array.from({length: 24}, (_, i) => `${i.toString().padStart(2, '0')}:00`),
axisLabel: {
interval: 3,
fontSize: 10
}
},
yAxis: {
type: 'value',
name: '湿度(%)',
min: 0,
max: 100,
axisLabel: {
formatter: '{value}%',
fontSize: 10
}
},
series: [{
name: '湿度',
type: 'line',
data: [],
smooth: true,
lineStyle: {
color: '#4a90e2',
width: 3
},
itemStyle: {
color: '#4a90e2'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'rgba(74, 144, 226, 0.3)'
}, {
offset: 1, color: 'rgba(74, 144, 226, 0.1)'
}]
}
}
}]
},
pm25Option: {
title: {
text: 'PM2.5趋势',
left: 'center',
textStyle: {
fontSize: 16,
color: '#333'
}
},
tooltip: {
trigger: 'axis',
formatter: function(params) {
const data = params[0];
return `时间: ${data.axisValue}<br/>PM2.5: ${data.value}μg/m³`;
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: Array.from({length: 24}, (_, i) => `${i.toString().padStart(2, '0')}:00`),
axisLabel: {
interval: 3,
fontSize: 10
}
},
yAxis: {
type: 'value',
name: 'PM2.5(μg/m³)',
min: 0,
max: 100,
axisLabel: {
formatter: '{value}μg/m³',
fontSize: 10
}
},
series: [{
name: 'PM2.5',
type: 'line',
data: [],
smooth: true,
lineStyle: {
color: '#7ed321',
width: 3
},
itemStyle: {
color: '#7ed321'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: 'rgba(126, 211, 33, 0.3)'
}, {
offset: 1, color: 'rgba(126, 211, 33, 0.1)'
}]
}
}
}]
2025-09-29 23:53:09 +08:00
}
}
},
onLoad() {
console.log('参数记录页面加载', new Date().toISOString().split('T')[0])
2025-09-29 23:53:09 +08:00
this.initMqttListener()
// 调用历史数据接口
this.getHistoryData()
2025-09-29 23:53:09 +08:00
},
2025-10-01 04:07:37 +08:00
onShow() {
console.log('📱 参数记录页面显示,触发页面更新')
// 只有在非首次显示时才重新获取历史数据
// 首次显示时已经在onLoad中获取过了
if (this.hasInitialized) {
this.getHistoryData()
} else {
this.hasInitialized = true
}
},
2025-09-29 23:53:09 +08:00
onUnload() {
// 页面卸载时移除监听器
if (this.dataUpdateHandler) {
mqttDataManager.removeListener('dataUpdate', this.dataUpdateHandler)
}
if (this.statusUpdateHandler) {
mqttDataManager.removeListener('connectionStatus', this.statusUpdateHandler)
}
},
methods: {
// 获取今天的日期(本地时区)
getTodayDate() {
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')
return `${year}-${month}-${day}`
},
2025-09-29 23:53:09 +08:00
// 初始化MQTT监听
initMqttListener() {
// 监听数据更新
this.dataUpdateHandler = (data) => {
console.log('参数记录页面收到MQTT数据:', data)
// this.updateChartData(data)
2025-09-29 23:53:09 +08:00
}
mqttDataManager.addListener('dataUpdate', this.dataUpdateHandler)
// 监听连接状态
this.statusUpdateHandler = (status) => {
this.connectionStatus = status
console.log('参数记录页面连接状态更新:', status)
}
mqttDataManager.addListener('connectionStatus', this.statusUpdateHandler)
// 获取初始连接状态
this.connectionStatus = mqttDataManager.getConnectionStatus()
},
// 更新图表数据
updateChartData(data) {
console.log('📊 参数记录页面更新数据:', data)
// 只处理WSD设备的数据
if (data.deviceType === 'WSD') {
const now = new Date()
const currentHour = now.getHours()
// 更新对应小时的数据
if (data.temperature !== undefined) {
Math.round(data.temperature) && (this.temperatureData[currentHour] = Math.round(data.temperature))
2025-09-29 23:53:09 +08:00
console.log(`✅ 温度数据已更新 - 小时${currentHour}:`, this.temperatureData[currentHour])
}
if (data.humidity !== undefined) {
Math.round(data.humidity) && (this.humidityData[currentHour] = Math.round(data.humidity))
2025-09-29 23:53:09 +08:00
console.log(`✅ 湿度数据已更新 - 小时${currentHour}:`, this.humidityData[currentHour])
}
if (data.pm !== undefined) {
Math.round(data.pm) && (this.pm25Data[currentHour] = Math.round(data.pm))
console.log(`✅ PM2.5数据已更新 - 小时${currentHour}:`, this.pm25Data[currentHour])
}
2025-09-29 23:53:09 +08:00
// 重新绘制图表
this.$nextTick(() => {
this.updateCharts()
2025-09-29 23:53:09 +08:00
})
console.log('✅ 图表数据更新完成:', {
temperature: this.temperatureData[currentHour],
humidity: this.humidityData[currentHour],
hour: currentHour
})
} else {
console.log('⚠️ 非WSD设备数据跳过图表更新:', data.deviceType)
}
},
// 图表初始化方法
initTemperatureChart() {
console.log('初始化温度图表')
this.temperatureOption.series[0].data = this.temperatureData
this.$refs.temperatureChartRef.init(this.temperatureOption)
},
initHumidityChart() {
console.log('初始化湿度图表')
this.humidityOption.series[0].data = this.humidityData
this.$refs.humidityChartRef.init(this.humidityOption)
},
initPM25Chart() {
console.log('初始化PM2.5图表')
this.pm25Option.series[0].data = this.pm25Data
this.$refs.pm25ChartRef.init(this.pm25Option)
},
2025-09-29 23:53:09 +08:00
onDateChange(e) {
this.selectedDate = e.detail.value
console.log('📅 日期已更改为:', this.selectedDate)
// 显示加载状态
uni.showLoading({
title: '加载数据中...'
})
// 重新获取历史数据
this.getHistoryData().finally(() => {
uni.hideLoading()
2025-09-29 23:53:09 +08:00
})
},
// 更新图表数据
updateCharts() {
if (this.$refs.temperatureChartRef) {
this.temperatureOption.series[0].data = this.temperatureData
this.$refs.temperatureChartRef.setOption(this.temperatureOption)
}
if (this.$refs.humidityChartRef) {
this.humidityOption.series[0].data = this.humidityData
this.$refs.humidityChartRef.setOption(this.humidityOption)
}
if (this.$refs.pm25ChartRef) {
this.pm25Option.series[0].data = this.pm25Data
this.$refs.pm25ChartRef.setOption(this.pm25Option)
}
2025-09-29 23:53:09 +08:00
},
// 获取历史数据
async getHistoryData() {
try {
// 根据选择的日期构建时间范围
const startTime = `${this.selectedDate} 00:00:00`
const endTime = `${this.selectedDate} 23:59:59`
const params = {
startTime: startTime,
endTime: endTime
}
console.log('📊 请求历史数据:', params)
const response = await dataHistoryApi.getHistory(params)
console.log('✅ 历史数据获取成功:', response)
// 处理历史数据
if (response && Array.isArray(response) && response.length > 0) {
this.historyData = response
this.processHistoryData(response)
// 更新数据状态
this.dataStatus = {
isRealData: true,
lastUpdateTime: new Date().toLocaleString(),
dataSource: 'api'
}
2025-10-01 04:07:37 +08:00
// 保存查询事件
await this.createQueryEvent('success', response.length)
} else {
console.log('📊 没有历史数据,显示空状态')
// 没有数据时显示空状态
this.showEmptyState()
// 更新数据状态
this.dataStatus = {
isRealData: false,
lastUpdateTime: new Date().toLocaleString(),
dataSource: 'empty'
}
2025-10-01 04:07:37 +08:00
// 保存查询事件(无数据)
await this.createQueryEvent('empty', 0)
}
return response
} catch (error) {
console.error('❌ 历史数据获取失败:', error)
// 出错时显示空状态
this.showEmptyState()
// 更新数据状态
this.dataStatus = {
isRealData: false,
lastUpdateTime: new Date().toLocaleString(),
dataSource: 'error'
}
2025-10-01 04:07:37 +08:00
// 保存查询事件(错误)
await this.createQueryEvent('error', 0)
// 显示错误提示
uni.showToast({
title: '数据加载失败',
icon: 'none',
duration: 2000
})
throw error
}
2025-09-29 23:53:09 +08:00
},
// 使用默认数据
useDefaultData() {
console.log('🎨 使用默认数据展示图表')
2025-09-29 23:53:09 +08:00
// 使用预设的示例数据
this.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]
this.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]
this.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]
2025-09-29 23:53:09 +08:00
// 更新数据状态
this.dataStatus = {
isRealData: false,
lastUpdateTime: new Date().toLocaleString(),
dataSource: 'default'
2025-09-29 23:53:09 +08:00
}
// 更新图表
this.$nextTick(() => {
this.updateCharts()
})
},
// 显示空状态
showEmptyState() {
console.log('🎨 显示空状态默认值为0')
// 设置默认数据为0
this.temperatureData = new Array(24).fill(0)
this.humidityData = new Array(24).fill(0)
this.pm25Data = new Array(24).fill(0)
// 更新图表
this.$nextTick(() => {
this.updateCharts()
})
},
processHistoryData(data) {
console.log('🔄 开始处理历史数据:', data.length, '条记录')
console.log('📊 原始数据示例:', data[0])
// 初始化图表数据
this.chartData = {
temperature: [],
humidity: [],
pm: []
2025-09-29 23:53:09 +08:00
}
// 按时间排序
const sortedData = data.sort((a, b) => {
const timeA = new Date(a.createTime || a.timestamp || a.time)
const timeB = new Date(b.createTime || b.timestamp || b.time)
return timeA - timeB
})
2025-09-29 23:53:09 +08:00
// 处理每条数据
sortedData.forEach(item => {
const time = new Date(item.createTime || item.timestamp || item.time)
const hour = time.getHours()
const minute = time.getMinutes()
2025-09-29 23:53:09 +08:00
// 处理温度数据 (wd是温度)
const temperature = item.wd || item.temperature || item.temp || item.T
if (temperature !== undefined && temperature !== null && temperature >= 0) {
this.chartData.temperature.push({
time: hour + minute / 60,
value: Number(temperature),
timestamp: item.createTime || item.timestamp || item.time
})
2025-09-29 23:53:09 +08:00
}
// 处理湿度数据 (sd是湿度)
const humidity = item.sd || item.humidity || item.hum || item.H
if (humidity !== undefined && humidity !== null && humidity >= 0) {
this.chartData.humidity.push({
time: hour + minute / 60,
value: Number(humidity),
timestamp: item.createTime || item.timestamp || item.time
})
}
// 处理PM数据 (支持多种字段名)
const pm = item.pm || item.pm25 || item.pm2_5 || item.PM
if (pm !== undefined && pm !== null && pm >= 0) {
this.chartData.pm.push({
time: hour + minute / 60,
value: Number(pm),
timestamp: item.createTime || item.timestamp || item.time
})
}
2025-09-29 23:53:09 +08:00
})
console.log('📈 处理后的图表数据:', {
temperature: this.chartData.temperature.length,
humidity: this.chartData.humidity.length,
pm: this.chartData.pm.length
})
2025-09-29 23:53:09 +08:00
// 重新绘制图表
this.$nextTick(() => {
this.updateChartsWithHistoryData()
2025-09-29 23:53:09 +08:00
})
},
// 使用历史数据更新图表
updateChartsWithHistoryData() {
console.log('🎨 使用历史数据更新图表')
// 处理温度数据
if (this.chartData.temperature.length > 0) {
const temperatureData = new Array(24).fill(0)
this.chartData.temperature.forEach(item => {
const hour = Math.floor(item.time)
if (hour >= 0 && hour < 24) {
temperatureData[hour] = item.value || 0
}
})
this.temperatureData = temperatureData
if (this.$refs.temperatureChartRef) {
this.temperatureOption.series[0].data = temperatureData
this.$refs.temperatureChartRef.setOption(this.temperatureOption)
}
} else {
// 没有温度数据时使用0填充
this.temperatureData = new Array(24).fill(0)
if (this.$refs.temperatureChartRef) {
this.temperatureOption.series[0].data = this.temperatureData
this.$refs.temperatureChartRef.setOption(this.temperatureOption)
}
}
2025-09-29 23:53:09 +08:00
// 处理湿度数据
if (this.chartData.humidity.length > 0) {
const humidityData = new Array(24).fill(0)
this.chartData.humidity.forEach(item => {
const hour = Math.floor(item.time)
if (hour >= 0 && hour < 24) {
humidityData[hour] = item.value || 0
}
})
this.humidityData = humidityData
if (this.$refs.humidityChartRef) {
this.humidityOption.series[0].data = humidityData
this.$refs.humidityChartRef.setOption(this.humidityOption)
}
} else {
// 没有湿度数据时使用0填充
this.humidityData = new Array(24).fill(0)
if (this.$refs.humidityChartRef) {
this.humidityOption.series[0].data = this.humidityData
this.$refs.humidityChartRef.setOption(this.humidityOption)
}
2025-09-29 23:53:09 +08:00
}
// 处理PM数据
if (this.chartData.pm.length > 0) {
const pmData = new Array(24).fill(0)
this.chartData.pm.forEach(item => {
const hour = Math.floor(item.time)
if (hour >= 0 && hour < 24) {
pmData[hour] = item.value || 0
}
})
this.pm25Data = pmData
if (this.$refs.pm25ChartRef) {
this.pm25Option.series[0].data = pmData
this.$refs.pm25ChartRef.setOption(this.pm25Option)
}
} else {
// 没有PM数据时使用0填充
this.pm25Data = new Array(24).fill(0)
if (this.$refs.pm25ChartRef) {
this.pm25Option.series[0].data = this.pm25Data
this.$refs.pm25ChartRef.setOption(this.pm25Option)
}
}
2025-10-01 04:07:37 +08:00
},
// 创建查询事件
async createQueryEvent(status, dataCount) {
try {
const currentTime = this.formatDateTime(new Date())
const queryEvent = {
eventType: "参数记录查询",
eventTime: currentTime,
status: this.getEventStatus(status),
description: this.getEventDescription(status, dataCount),
deviceId: "PARAMETER_QUERY_001"
}
console.log('📤 提交查询事件:', queryEvent)
const response = await eventApi.create(queryEvent)
console.log('✅ 查询事件创建成功:', response)
} catch (error) {
console.error('❌ 查询事件创建失败:', error)
}
},
// 获取事件状态
getEventStatus(status) {
const statusMap = {
'success': '已完成',
'empty': '已完成',
'error': '失败'
};
return statusMap[status] || '未知';
},
// 获取事件描述
getEventDescription(status, dataCount) {
const descriptions = {
'success': `成功查询到${dataCount}条参数记录数据`,
'empty': '查询参数记录,但未找到数据',
'error': '查询参数记录时发生错误'
};
return descriptions[status] || '未知查询状态';
},
// 时间格式化函数
formatDateTime(date) {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
2025-09-29 23:53:09 +08:00
}
}
}
</script>
<style lang="scss" scoped>
.parameter-record-page {
height: 100vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
.date-selector {
background: white;
border-radius: 8rpx;
padding: 15rpx;
margin-bottom: 15rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.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;
2025-09-29 23:53:09 +08:00
}
.date-picker {
display: flex;
align-items: center;
gap: 8rpx;
padding: 15rpx 20rpx;
background-color: #f8f8f8;
border-radius: 6rpx;
}
.date-text {
font-size: 28rpx;
color: #333;
}
.picker-arrow {
color: #999;
font-size: 20rpx;
}
.chart-card {
background: white;
border-radius: 8rpx;
padding: 30rpx;
margin-bottom: 20rpx;
2025-09-29 23:53:09 +08:00
}
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30rpx;
2025-09-29 23:53:09 +08:00
}
.chart-title {
font-size: 28rpx;
font-weight: bold;
color: #333;
}
.chart-subtitle {
font-size: 22rpx;
color: #666;
}
.status-indicator {
display: flex;
align-items: center;
gap: 6rpx;
background-color: #e8f5e8;
padding: 6rpx 12rpx;
border-radius: 15rpx;
}
.status-dot {
width: 8rpx;
height: 8rpx;
border-radius: 50%;
}
.temperature-dot {
background-color: #ff6b35;
}
.humidity-dot {
background-color: #4a90e2;
}
.pm25-dot {
background-color: #7ed321;
}
.status-text {
font-size: 20rpx;
color: #4caf50;
}
.chart-container {
width: 100%;
// padding: 0 20rpx;
2025-09-29 23:53:09 +08:00
}
</style>