提交 13efb5af 作者: 吴佳伟

feat: 农场页面天气工具

上级 dfadc655
import { weatherHttp } from '/@/utils/http/axios'
import { otherHttp, weatherHttp } from '/@/utils/http/axios'
const API_KEY = '4fb5c9e814994516b6522419651f2e9e'
......@@ -22,3 +22,25 @@ export function alarm(location: string) {
url: `/weatheralert/v1/current/${location.replace(',', '/')}?key=${API_KEY}`,
})
}
// 格点天气预报-日值(降雨、大风用)
export function gridForecastDaily(location: string, day = 3) {
return weatherHttp.get({
url: `/v7/weather/${day}d?key=${API_KEY}&location=${location}`,
})
}
// 格点天气预报-小时值(温度用)
export function gridForecastHourly(location: string) {
return weatherHttp.get({
url: `/v7/weather/24h?key=${API_KEY}&location=${location}`,
})
}
// 强对流预报(自建接口)
export function severeForecast(lon: string, lat: string) {
return otherHttp.get({
url: '/weather/forecast',
params: { lon, lat },
}, { isTransformResponse: false })
}
......@@ -13,17 +13,17 @@ export default {
},
methods: {
loadLibs: loadEchartsLibs,
init() {
init(notMerge) {
// 如果已经初始化过了,就直接更新配置项
if (this.chart && this.chart.setOption) {
this.chart.setOption(this.option)
this.chart.setOption(this.option, { notMerge: notMerge || false })
return
}
// 初始化组件
const chart = window.echarts.init(document.getElementById(this.option.id))
// 设置图表配置项
chart.setOption(this.option)
chart.setOption(this.option, { notMerge: notMerge || false })
this.chart = chart
},
changeOption(option) {
......@@ -45,12 +45,20 @@ export default {
}
}
this.option = merge(this.option, option)
const notMerge = option.__notMerge
// 清除内部标记
delete option.__notMerge
if (notMerge) {
this.option = option
} else {
this.option = merge(this.option, option)
}
if (typeof window.echarts === 'object' && typeof window.echarts.init === 'function') {
this.init()
this.init(notMerge)
} else {
this.loadLibs().then(() => {
this.init()
this.init(notMerge)
})
}
},
......
......@@ -44,10 +44,10 @@ export function useEcharts<T extends EchartsInstance, P extends EChartsOption>(
return [
register,
{
setOption: (option: Partial<P>): Promise<void> => {
setOption: (option: Partial<P>, opts?: { notMerge?: boolean; lazyUpdate?: boolean }): Promise<void> => {
return new Promise((resolve) => {
tryOnMounted(() => {
getInstance()?.setOption(option)
getInstance()?.setOption(option, opts)
resolve()
})
})
......
......@@ -14,7 +14,7 @@
this.$emit('register', this)
},
methods: {
setOption(option) {
setOption(option, opts) {
// 处理tooltip formatter函数序列化
if (option.tooltip && typeof option.tooltip.formatter === 'function') {
// 将函数转换为字符串,在视图层重新构建
......@@ -25,6 +25,11 @@
id: this.id,
...option,
}
// 保存 opts 供 renderjs 层使用
if (opts?.notMerge !== undefined) {
this.option.__notMerge = opts.notMerge
}
},
},
}
......
......@@ -16,6 +16,7 @@
import { ToolBoxWidget, useToolBoxWidget } from '@/components/Map/Widgets/ToolBox'
import * as NongchangAPI from '@/api/model/nongchang'
import * as farmbaseApi from '@/api/model/farmbase'
import WeatherChartPopup from './components/WeatherChartPopup.vue'
// 页面参数
const page = reactive<Page>({
......@@ -64,7 +65,11 @@
farmbaseInfo: {},
farmbaseInfoList: [],
deviceTypeCount: [],
activeWeatherType: '' as '' | 'rain' | 'temp' | 'wind' | 'severe',
})
// 当前基地中心经纬度(用于天气接口请求)
const baseCenterLonLat = ref<[number, number] | null>(null)
onLoad(() => {
const today = dayjs()
for (let i = 0; i < 5; i++) {
......@@ -113,6 +118,8 @@
if (c[1] > maxLat) maxLat = c[1]
}
const center: [number, number] = [(minLon + maxLon) / 2, (minLat + maxLat) / 2]
// 存储基地中心经纬度,供天气接口使用
baseCenterLonLat.value = center
// 使用 flyTo 而非 fitBounds,避免 maxBounds 约束干扰
map.flyTo({
center,
......@@ -121,8 +128,10 @@
})
}
} else if (res.longitude && res.latitude) {
const center: [number, number] = [Number(res.longitude), Number(res.latitude)]
baseCenterLonLat.value = center
map.flyTo({
center: [Number(res.longitude), Number(res.latitude)],
center,
zoom: 15,
duration: 1000,
})
......@@ -347,15 +356,19 @@
if (c[1] < minLat) minLat = c[1]
if (c[1] > maxLat) maxLat = c[1]
}
const center: [number, number] = [(minLon + maxLon) / 2, (minLat + maxLat) / 2]
baseCenterLonLat.value = center
map.flyTo({
center: [(minLon + maxLon) / 2, (minLat + maxLat) / 2],
center,
zoom: 15,
duration: 0,
})
}
} else if (firstBase.longitude && firstBase.latitude) {
const center: [number, number] = [Number(firstBase.longitude), Number(firstBase.latitude)]
baseCenterLonLat.value = center
map.flyTo({
center: [Number(firstBase.longitude), Number(firstBase.latitude)],
center,
zoom: 15,
duration: 0,
})
......@@ -454,33 +467,33 @@
{
name: '降雨',
icon: '/static/images/codefun/rain.png',
type: 'button',
type: 'toggle' as const,
handle: () => {
Message.toast('暂无降雨数据')
onWeatherClick('rain')
},
},
{
name: '温度',
icon: '/static/images/codefun/temp.png',
type: 'button',
type: 'toggle' as const,
handle: () => {
Message.toast('暂无温度数据')
onWeatherClick('temp')
},
},
{
name: '强对流',
icon: '/static/images/codefun/severe.png',
type: 'button',
type: 'toggle' as const,
handle: () => {
Message.toast('暂无强对流数据')
onWeatherClick('severe')
},
},
{
name: '大风',
icon: '/static/images/codefun/wind.png',
type: 'button',
type: 'toggle' as const,
handle: () => {
Message.toast('暂无大风数据')
onWeatherClick('wind')
},
},
{
......@@ -522,6 +535,14 @@
},
})
}
// 天气按钮点击处理
function onWeatherClick(type: 'rain' | 'temp' | 'wind' | 'severe') {
if (model.activeWeatherType === type) {
model.activeWeatherType = ''
} else {
model.activeWeatherType = type
}
}
// 保留原有的导航栏按钮点击回调(如果有需要的话)
onNavigationBarButtonTap((e) => {
if (e.index === 0) {
......@@ -736,6 +757,13 @@
@submit-success="getDeviceTypeCount"
@close="showDialog = false"
/>
<WeatherChartPopup
:visible="model.activeWeatherType !== ''"
:type="model.activeWeatherType"
:lon="baseCenterLonLat?.[0] ?? ''"
:lat="baseCenterLonLat?.[1] ?? ''"
@close="model.activeWeatherType = ''"
/>
</view>
</template>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论