feat: 修复一些错误
This commit is contained in:
parent
f5174fe156
commit
a5d382493a
@ -111,11 +111,15 @@ func main() {
|
||||
if *bfFrom == "" || *bfTo == "" {
|
||||
log.Fatalln("backfill 需要提供 --from 与 --to 时间")
|
||||
}
|
||||
fromT, err := time.Parse("2006-01-02 15:04:05", *bfFrom)
|
||||
loc, _ := time.LoadLocation("Asia/Shanghai")
|
||||
if loc == nil {
|
||||
loc = time.FixedZone("CST", 8*3600)
|
||||
}
|
||||
fromT, err := time.ParseInLocation("2006-01-02 15:04:05", *bfFrom, loc)
|
||||
if err != nil {
|
||||
log.Fatalf("解析from失败: %v", err)
|
||||
}
|
||||
toT, err := time.Parse("2006-01-02 15:04:05", *bfTo)
|
||||
toT, err := time.ParseInLocation("2006-01-02 15:04:05", *bfTo, loc)
|
||||
if err != nil {
|
||||
log.Fatalf("解析to失败: %v", err)
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"math"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@ -137,7 +138,17 @@ func RunCaiyunFetch(ctx context.Context, token string) error {
|
||||
if ft, err := time.ParseInLocation("2006-01-02T15:04-07:00", p.Datetime, loc); err == nil {
|
||||
v := table[ft]
|
||||
v.rain = p.Value
|
||||
v.prob = p.Probability * 100.0
|
||||
// 直接使用API返回的概率值,只进行范围限制
|
||||
prob := p.Probability
|
||||
// 四舍五入并确保在0-100范围内
|
||||
prob = math.Round(prob)
|
||||
if prob < 0 {
|
||||
prob = 0
|
||||
}
|
||||
if prob > 100 {
|
||||
prob = 100
|
||||
}
|
||||
v.prob = prob
|
||||
table[ft] = v
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,6 +138,23 @@ func RunBackfill10Min(ctx context.Context, opts BackfillOptions) error {
|
||||
// 雨量增量:按时间比例切分到跨越的各个桶,避免边界全部被计入后一桶
|
||||
if rf.Valid {
|
||||
curr := rf.Float64
|
||||
|
||||
// 若该站点的上一条样本未知(窗口首条),尝试读取窗口前一条样本作为种子,避免首桶丢雨
|
||||
if math.IsNaN(prevTotal) || prevTS.IsZero() {
|
||||
var seedTS time.Time
|
||||
var seedTotal sql.NullFloat64
|
||||
if err := db.QueryRowContext(ctx, `
|
||||
SELECT timestamp, rainfall
|
||||
FROM rs485_weather_data
|
||||
WHERE station_id = $1 AND timestamp < $2
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT 1
|
||||
`, stationID, ts).Scan(&seedTS, &seedTotal); err == nil && seedTotal.Valid {
|
||||
prevTotal = seedTotal.Float64
|
||||
prevTS = seedTS
|
||||
}
|
||||
}
|
||||
|
||||
if !math.IsNaN(prevTotal) && !prevTS.IsZero() {
|
||||
// 计算增量(带回绕)
|
||||
inc := 0.0
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<!-- OpenLayers CSS and JS -->
|
||||
<link rel="stylesheet" href="/static/css/ol.css">
|
||||
<script src="/static/js/ol.js"></script>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link rel="stylesheet" href="/static/css/tailwind.min.css">
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
@ -16,6 +16,26 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 自定义:百分比左右内边距(避免 JIT 依赖)*/
|
||||
.px-7p {
|
||||
padding-left: 7%;
|
||||
padding-right: 7%;
|
||||
}
|
||||
|
||||
/* 自定义:内容区宽度控制(避免 JIT 任意值类)*/
|
||||
.content-narrow {
|
||||
width: 86%;
|
||||
max-width: 1200px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.content-narrow {
|
||||
width: 92%;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
@ -231,7 +251,6 @@
|
||||
|
||||
/* 设备列表样式 */
|
||||
.device-modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@ -239,19 +258,20 @@
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
z-index: 2000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.device-modal-content {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
height: 40vh;
|
||||
width: 100%;
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
|
||||
height: auto;
|
||||
max-height: 70vh;
|
||||
width: 90%;
|
||||
max-width: 720px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 10px 25px rgba(0,0,0,0.15);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@ -411,36 +431,36 @@
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body x-data="{ showPastForecast: false }" class="text-[14px] md:text-[15px]">
|
||||
<body x-data="{ showPastForecast: false, deviceModalOpen: false }" class="text-[14px] md:text-[15px]" x-init="window.addEventListener('close-device-modal', () => { deviceModalOpen = false })">
|
||||
<div class="header p-2 text-center border-b border-gray-200">
|
||||
<h1 class="text-2xl md:text-3xl font-semibold p-7">{{.Title}}</h1>
|
||||
</div>
|
||||
|
||||
<!-- 设备列表 -->
|
||||
<div id="deviceModal" class="device-modal">
|
||||
<div class="device-modal-content">
|
||||
<div class="device-list-header">
|
||||
设备列表
|
||||
<span class="close-modal">×</span>
|
||||
<div id="deviceModal" class="device-modal" x-show="deviceModalOpen" x-transition.opacity @click.self="deviceModalOpen=false">
|
||||
<div class="device-modal-content bg-white shadow-xl" x-transition.scale.duration.150ms>
|
||||
<div class="device-list-header flex items-center justify-between border-b">
|
||||
<div class="text-sm">设备列表</div>
|
||||
<span class="close-modal" @click="deviceModalOpen=false">×</span>
|
||||
</div>
|
||||
<div id="deviceList" class="device-list">
|
||||
<!-- 设备列表将通过JavaScript动态填充 -->
|
||||
</div>
|
||||
<div class="device-list-footer">
|
||||
<div class="pagination">
|
||||
<button class="pagination-btn" id="prevPage" disabled>< 上一页</button>
|
||||
<button class="pagination-btn" id="prevPage" :disabled="window.WeatherApp.currentPage <= 1" @click="window.WeatherApp.updateDeviceList(window.WeatherApp.currentPage - 1)">< 上一页</button>
|
||||
<span>第 <span id="currentPage">1</span> 页,共 <span id="totalPages">1</span> 页</span>
|
||||
<button class="pagination-btn" id="nextPage" disabled>下一页 ></button>
|
||||
<button class="pagination-btn" id="nextPage" :disabled="window.WeatherApp.currentPage >= Math.ceil(window.WeatherApp.filteredDevices.length / window.WeatherApp.itemsPerPage)" @click="window.WeatherApp.updateDeviceList(window.WeatherApp.currentPage + 1)">下一页 ></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container max-w-screen-xl mx-auto px-[7%] py-5">
|
||||
<div class="container content-narrow py-5">
|
||||
<!-- 系统信息 -->
|
||||
<div class="system-info bg-gray-100 p-3 mb-5 rounded text-sm">
|
||||
<strong>在线设备: </strong> <span id="onlineDevices">{{.OnlineDevices}}</span> 个 |
|
||||
<strong>总设备: </strong> <a href="#" id="showDeviceList" class="text-blue-600 hover:text-blue-700 underline-offset-2"><span id="wh65lpCount">0</span> 个</a>
|
||||
<strong>总设备: </strong> <a href="#" id="showDeviceList" class="text-blue-600 hover:text-blue-700 underline-offset-2" @click.prevent="deviceModalOpen = true; window.WeatherApp.updateDeviceList(1)"><span id="wh65lpCount">0</span> 个</a>
|
||||
</div>
|
||||
|
||||
<!-- 控制面板 -->
|
||||
@ -543,7 +563,7 @@
|
||||
<script>
|
||||
window.TIANDITU_KEY = '{{.TiandituKey}}';
|
||||
</script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
<script defer src="/static/js/alpinejs.min.js"></script>
|
||||
<script src="/static/js/utils.js"></script>
|
||||
<script src="/static/js/weather-app.js"></script>
|
||||
<script src="/static/js/weather-chart.js"></script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user