This commit is contained in:
Dustella 2025-01-16 16:03:21 +08:00
parent 148d73b945
commit f80f93a9b3
6 changed files with 209 additions and 28 deletions

2
auto-imports.d.ts vendored
View File

@ -38,6 +38,7 @@ declare global {
const getCurrentInstance: typeof import('vue')['getCurrentInstance'] const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope'] const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h'] const h: typeof import('vue')['h']
const hasConnection: typeof import('./src/composables/online')['hasConnection']
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch'] const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject'] const inject: typeof import('vue')['inject']
const injectLocal: typeof import('@vueuse/core')['injectLocal'] const injectLocal: typeof import('@vueuse/core')['injectLocal']
@ -335,6 +336,7 @@ declare module 'vue' {
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']> readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']> readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
readonly h: UnwrapRef<typeof import('vue')['h']> readonly h: UnwrapRef<typeof import('vue')['h']>
readonly hasConnection: UnwrapRef<typeof import('./src/composables/online')['hasConnection']>
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']> readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']>
readonly inject: UnwrapRef<typeof import('vue')['inject']> readonly inject: UnwrapRef<typeof import('vue')['inject']>
readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']> readonly injectLocal: UnwrapRef<typeof import('@vueuse/core')['injectLocal']>

View File

@ -100,7 +100,20 @@ const data = {
}, },
], ],
}, },
{
title: 'TIDI',
url: '#',
icon: 'mdi:telescope',
isActive: true,
items: [
{
title: '波动',
url: '/tidi/waves',
},
],
},
], ],
关于: [ 关于: [
{ {
name: 'Design Engineering', name: 'Design Engineering',

View File

@ -19,7 +19,7 @@ const selectedDateType = ref('day')
const selectedStation = ref('武汉左岭镇站') const selectedStation = ref('武汉左岭镇站')
const selectedYear = ref('2017') const selectedYear = ref('2017')
const selectedWindType = ref('uwind') const selectedWindType = ref('uwind')
const selectedH = ref(90000) const selectedH = ref(94000)
const selectedDate = ref('20170316') const selectedDate = ref('20170316')
const selectedMonth = ref('1') const selectedMonth = ref('1')
@ -55,6 +55,7 @@ const queryUrl = computed(() => {
query.set('model_name', mode) query.set('model_name', mode)
query.set('wind_type', windType) query.set('wind_type', windType)
query.set('H', selectedH.value.toString()) query.set('H', selectedH.value.toString())
query.set('mode', selectedDateType.value)
if (selectedDateType.value === 'day') { if (selectedDateType.value === 'day') {
const queryDay = `${selectedDate.value.slice(0, 4)}-${selectedDate.value.slice(4, 6)}-${selectedDate.value.slice(6, 8)}` const queryDay = `${selectedDate.value.slice(0, 4)}-${selectedDate.value.slice(4, 6)}-${selectedDate.value.slice(6, 8)}`
query.set('day', queryDay) query.set('day', queryDay)
@ -87,8 +88,8 @@ onMounted(async () => {
const data = await resp.json() const data = await resp.json()
// use regex to extract the year from the path, // use regex to extract the year from the path,
// ./radar/data\\\\2017\\ZLT_MET01_DLL_L21_01D_20170316.txt // ./radar/data\\\\2017\\ZLT_MET01_DLL_L21_01D_20170316.txt
const station_pattern = /data\\(.*?)\\/ const station_pattern = /data\/(.*?)\//
const year_pattern = /(\d{4})\\ZLT_/ const year_pattern = /(\d{4})\/ZLT_/
const date_pattern = /01D_(\d{8})\.txt/ const date_pattern = /01D_(\d{8})\.txt/
const pairs = data.map((source_text: string) => { const pairs = data.map((source_text: string) => {
const station = source_text.match(station_pattern)?.[1] const station = source_text.match(station_pattern)?.[1]
@ -179,7 +180,7 @@ onMounted(async () => {
id="start" id="start"
v-model:model-value="selectedH" :format-options="{ v-model:model-value="selectedH" :format-options="{
useGrouping: false, useGrouping: false,
}" :default-value="90000" }" :default-value="94000"
> >
<NumberFieldContent> <NumberFieldContent>
<NumberFieldDecrement /> <NumberFieldDecrement />

View File

@ -13,9 +13,11 @@
import type { ImageResult } from '~/components/ImageContainer.vue' import type { ImageResult } from '~/components/ImageContainer.vue'
import { API_BASE_URL } from '~/CONSTANT' import { API_BASE_URL } from '~/CONSTANT'
const selectedMode = ref('潮汐波') const selectedMode = ref('2日行星波')
const selectedWave = ref('潮汐波')
const selectedStation = ref('武汉左岭镇站') const selectedStation = ref('武汉左岭镇站')
const selectedYear = ref('2017') const selectedYear = ref('2017')
const selectedMonthRange = reactive({ start: '1', end: '12' })
const imageResult = reactive<ImageResult>({ const imageResult = reactive<ImageResult>({
result: 'idle', result: 'idle',
imageUrl: '', imageUrl: '',
@ -23,7 +25,6 @@ const imageResult = reactive<ImageResult>({
}) })
const modes = [ const modes = [
'潮汐波',
'2日行星波', '2日行星波',
'5日行星波', '5日行星波',
'10日行星波', '10日行星波',
@ -35,15 +36,18 @@ const stations = ref<Set<string>>(new Set())
const years = ref<Set<string>>(new Set()) const years = ref<Set<string>>(new Set())
const queryUrl = computed(() => { const queryUrl = computed(() => {
const station = encodeURIComponent(selectedStation.value) // const query = `?station=${station}&year=${year}&model_name=${mode}`
const year = encodeURIComponent(selectedYear.value) const query = new URLSearchParams()
const mode = encodeURIComponent(selectedMode.value) query.set('station', selectedStation.value)
const query = `?station=${station}&year=${year}&model_name=${mode}` query.set('year', selectedYear.value)
const path = `${API_BASE_URL}/radar/render/v2${query}` query.set('model_name', selectedWave.value === '潮汐波' ? '潮汐波' : selectedMode.value)
query.set('start_month', selectedMonthRange.start)
query.set('end_month', selectedMonthRange.end)
const path = `${API_BASE_URL}/radar/render/changes?${query}`
return path return path
}) })
const { onFetchResponse, isFetching, execute } = useFetch(queryUrl, { refetch: true }) const { onFetchResponse, isFetching, execute } = useFetch(queryUrl, { immediate: false })
onFetchResponse(async (resp) => { onFetchResponse(async (resp) => {
const blob = await resp.blob() const blob = await resp.blob()
@ -63,8 +67,8 @@ onMounted(async () => {
const data = await resp.json() const data = await resp.json()
// use regex to extract the year from the path, // use regex to extract the year from the path,
// ./radar/data\\\\2017\\ZLT_MET01_DLL_L21_01D_20170316.txt // ./radar/data\\\\2017\\ZLT_MET01_DLL_L21_01D_20170316.txt
const station_pattern = /data\\(.*?)\\/ const station_pattern = /data\/(.*?)\//
const year_pattern = /(\d{4})\\ZLT_/ const year_pattern = /(\d{4})\/ZLT_/
const pairs = data.map((source_text: string) => { const pairs = data.map((source_text: string) => {
const station = source_text.match(station_pattern)?.[1] const station = source_text.match(station_pattern)?.[1]
const year = source_text.match(year_pattern)?.[1] const year = source_text.match(year_pattern)?.[1]
@ -86,19 +90,28 @@ onMounted(async () => {
<DenseFramework :image-result="imageResult" @submit="execute"> <DenseFramework :image-result="imageResult" @submit="execute">
<div> <div>
<div flex="~ col items-stretch gap-3" py-3> <div flex="~ col items-stretch gap-3" py-3>
<Select v-model="selectedMode"> <Label>计算模式</Label>
<SelectTrigger> <Tabs id="waves" v-model="selectedWave" default-value="潮汐波">
<SelectValue placeholder="Select a fruit" /> <TabsList class="grid grid-cols-2 w-full">
</SelectTrigger> <TabsTrigger value="潮汐波">
<SelectContent> 潮汐波
<SelectGroup> </TabsTrigger>
<SelectLabel>计算模式</SelectLabel> <TabsTrigger value="行星波">
<SelectItem v-for="mode in modes" :key="mode" :value="mode"> 行星波
{{ mode }} </TabsTrigger>
</SelectItem> </TabsList>
</SelectGroup> </Tabs>
</SelectContent> <div v-if="selectedWave === '行星波'">
</Select> <Label>行星波类型</Label>
<Tabs v-model="selectedMode" default-value="uwind">
<TabsList class="grid grid-cols-4 w-full">
<TabsTrigger v-for="m in modes" :key="m" :value="m">
{{ m.replace("行星波", "") }}
</TabsTrigger>
</TabsList>
</Tabs>
</div>
<Label>观测站</Label>
<Select v-model="selectedStation"> <Select v-model="selectedStation">
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder="Select a fruit" /> <SelectValue placeholder="Select a fruit" />
@ -112,19 +125,56 @@ onMounted(async () => {
</SelectGroup> </SelectGroup>
</SelectContent> </SelectContent>
</Select> </Select>
<Label>年份</Label>
<Select v-model="selectedYear"> <Select v-model="selectedYear">
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder="Select a fruit" /> <SelectValue placeholder="Select a fruit" />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectGroup> <SelectGroup>
<SelectLabel></SelectLabel> <SelectLabel></SelectLabel>
<SelectItem v-for="year in years" :key="year" :value="year"> <SelectItem v-for="year in years" :key="year" :value="year">
{{ year }} {{ year }}
</SelectItem> </SelectItem>
</SelectGroup> </SelectGroup>
</SelectContent> </SelectContent>
</Select> </Select>
<Label>起始月份</Label>
<Select v-model="selectedMonthRange.start">
<SelectTrigger>
<SelectValue placeholder="选择起始月" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel></SelectLabel>
<SelectItem
v-for="month in [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
]" :key="month" :value="month.toString()"
>
{{ month }}
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
<Label>终止月份</Label>
<Select v-model="selectedMonthRange.end">
<SelectTrigger>
<SelectValue placeholder="选择终止月" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel></SelectLabel>
<SelectItem
v-for="month in [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
]" :key="month" :value="month.toString()"
>
{{ month }}
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div> </div>
</div> </div>
</DenseFramework> </DenseFramework>

114
src/pages/tidi/waves.vue Normal file
View File

@ -0,0 +1,114 @@
<script setup lang="ts">
import type { ImageResult } from '~/components/ImageContainer.vue'
import { API_BASE_URL } from '~/CONSTANT'
const imageResult = reactive<ImageResult>({
result: 'idle',
imageUrl: '',
message: '请你选择一个模式和日期',
})
const selectedMode = ref('V_Meridional')
const years = ref([] as string[])
const selectedYear = ref('2017')
// const k = [ -4,-3,-2,-1,0,1,2,3,4]
const selectedK = ref(0)
const selectedT = ref(15)
const queryUrl = computed(() => {
const query = new URLSearchParams()
query.set('mode', selectedMode.value)
query.set('year', selectedYear.value)
query.set('k', selectedK.value.toString())
query.set('T', selectedT.value.toString())
return `${API_BASE_URL}/tidi/render/wave?${query}`
})
const { execute, onFetchResponse, isFetching } = useFetch(queryUrl, { immediate: false })
watch(isFetching, (fetching) => {
if (fetching) {
imageResult.result = 'pending'
}
})
onFetchResponse(async (resp) => {
const blob = await resp.blob()
const url = URL.createObjectURL(blob)
imageResult.result = 'success'
imageResult.imageUrl = url
})
onMounted(async () => {
const metas = await fetch(`${API_BASE_URL}/tidi/metadata`).then(resp => resp.json())
const _years = metas.path.map((a: string) => {
const year_pattern = /data\/(\d{4})\//
return a.match(year_pattern)?.[1]
})
_years.sort()
years.value = Array.from(new Set(_years))
})
</script>
<template>
<DenseFramework :image-result="imageResult" @submit="execute">
<div flex="col gap-3 ~ justify-stretch">
<Label>计算模式</Label>
<Tabs id="modes" v-model="selectedMode" default-value="V_Meridional">
<TabsList class="grid grid-cols-2 w-full">
<TabsTrigger value="V_Meridional">
纬向风
</TabsTrigger>
<TabsTrigger value="V_Zonal">
经向风
</TabsTrigger>
</TabsList>
</Tabs>
<Label>年份</Label>
<Select v-model="selectedYear">
<SelectTrigger>
<SelectValue placeholder="选择年份" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>年份</SelectLabel>
<SelectItem v-for="year in years" :key="year" :value="year">
{{ year }}
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
<Label>波数 k</Label>
<NumberField
v-model="selectedK"
:max="4" :min="-4" :step="1"
>
<NumberFieldContent>
<NumberFieldIncrement />
<NumberFieldInput />
<NumberFieldDecrement />
</NumberFieldContent>
</NumberField>
<Label>滑动窗口 T</Label>
<Tabs v-model:model-value="selectedT" default-value="15">
<TabsList class="grid grid-cols-3 w-full">
<TabsTrigger value="5">
5
</TabsTrigger>
<TabsTrigger value="10">
10
</TabsTrigger>
<TabsTrigger value="15">
15
</TabsTrigger>
</TabsList>
</Tabs>
</div>
</DenseFramework>
</template>
<style scoped>
</style>

1
typed-router.d.ts vendored
View File

@ -28,5 +28,6 @@ declare module 'vue-router/auto-routes' {
'/saber/day_fft_ifft_plot': RouteRecordInfo<'/saber/day_fft_ifft_plot', '/saber/day_fft_ifft_plot', Record<never, never>, Record<never, never>>, '/saber/day_fft_ifft_plot': RouteRecordInfo<'/saber/day_fft_ifft_plot', '/saber/day_fft_ifft_plot', Record<never, never>, Record<never, never>>,
'/saber/month_power_wave_plot': RouteRecordInfo<'/saber/month_power_wave_plot', '/saber/month_power_wave_plot', Record<never, never>, Record<never, never>>, '/saber/month_power_wave_plot': RouteRecordInfo<'/saber/month_power_wave_plot', '/saber/month_power_wave_plot', Record<never, never>, Record<never, never>>,
'/saber/plot_wave_fitting': RouteRecordInfo<'/saber/plot_wave_fitting', '/saber/plot_wave_fitting', Record<never, never>, Record<never, never>>, '/saber/plot_wave_fitting': RouteRecordInfo<'/saber/plot_wave_fitting', '/saber/plot_wave_fitting', Record<never, never>, Record<never, never>>,
'/tidi/waves': RouteRecordInfo<'/tidi/waves', '/tidi/waves', Record<never, never>, Record<never, never>>,
} }
} }