refactor: new imageFetch
Some checks are pending
Test / build (lts/*, ubuntu-latest) (push) Waiting to run
Test / build (lts/*, windows-latest) (push) Waiting to run

This commit is contained in:
Dustella 2025-01-23 22:06:53 +08:00
parent 089874885e
commit d700b28fb6
Signed by: Dustella
GPG Key ID: 35AA0AA3DC402D5C
12 changed files with 97 additions and 249 deletions

View File

@ -6,11 +6,55 @@ import {
ResizablePanelGroup,
} from '~/components/ui/resizable'
defineProps<{
imageResult: ImageResult
const props = defineProps<{
imageQuery: string
extraErrorHandle?: (resp: Response) => {
type: string
message: string
}
extraResponseHandle?: (resp: Response) => Promise<ImageResult>
}>()
defineEmits(['submit'])
const imageResult = reactive<ImageResult>({
result: 'idle',
resourceId: '',
message: '请你选择一个模式和日期',
})
const urlRef = computed(() => {
return props.imageQuery
})
const { onFetchResponse, onFetchError, isFetching, execute } = baseFetch(
urlRef,
{ immediate: false },
)
watch(isFetching, (fetching) => {
if (fetching) {
imageResult.result = 'pending'
}
})
onFetchResponse(async (resp) => {
if (props.extraResponseHandle) {
const newResult = await props.extraResponseHandle(resp)
imageResult.result = newResult.result
imageResult.resourceId = newResult.resourceId
imageResult.message = newResult.message
}
else {
const blob = await resp.blob()
const url = URL.createObjectURL(blob)
imageResult.result = 'success'
imageResult.resourceId = url
}
})
onFetchError(async (error) => {
imageResult.result = 'error'
imageResult.message = error
})
</script>
<template>
@ -22,7 +66,10 @@ defineEmits(['submit'])
>
<ResizablePanel id="demo-panel-1" :default-size="200" py-5>
<ParamsCard
@submit="$emit('submit')"
@submit="() => {
$emit('submit')
execute()
}"
>
<slot />
</ParamsCard>

View File

@ -3,7 +3,7 @@ import { Icon } from '@iconify/vue/dist/iconify.js'
export interface ImageResult {
result: 'success' | 'error' | 'pending' | 'idle'
imageUrl: string
resourceId: string
message?: string
}
@ -14,7 +14,7 @@ const props = defineProps<{
function download() {
if (props.imageResult.result === 'success') {
const a = document.createElement('a')
a.href = props.imageResult.imageUrl
a.href = props.imageResult.resourceId
a.download = 'image.png'
a.click()
}
@ -30,7 +30,7 @@ function download() {
<Icon icon="akar-icons:loading" class="mr-2 animate-spin" />
<span>正在加载图片</span>
</div>
<Image v-else-if="imageResult.result === 'success'" class="flex flex-1 items-center justify-center text-xl" :image-url="imageResult.imageUrl" />
<Image v-else-if="imageResult.result === 'success'" class="flex flex-1 items-center justify-center text-xl" :image-url="imageResult.resourceId" />
<div v-else class="flex flex-1 items-center justify-center text-xl">
{{ imageResult.message }}
</div>

View File

@ -12,12 +12,6 @@ import { useForm } from 'vee-validate'
import { z } from 'zod'
import { API_BASE_URL } from '~/CONSTANT'
const imageResult = reactive<ImageResult>({
result: 'idle',
imageUrl: '',
message: '请你选择一个模式和日期',
})
const modes = [
'观测的二阶多项式拟合',
'扰动分量的正弦波拟合',
@ -57,35 +51,42 @@ onMounted(async () => {
})
})
async function get_image(
selectedMode: string,
selectedDate: string,
) {
const { response } = await baseFetch(`${API_BASE_URL}/balloon/render/single?mode=${encodeURIComponent(selectedMode)}&path=${encodeURIComponent(selectedDate)}`)
// check for MIME Type, check if is png
const resp = response.value!
const isPng = resp.headers.get('Content-Type') === 'image/png'
if (!isPng) {
imageResult.result = 'error' as const
imageResult.message = '这一天没有数据'
return
}
imageResult.result = 'success' as const
const blob = await resp.blob()
const url = URL.createObjectURL(blob)
imageResult.imageUrl = url
}
const queryUrl = computed(() => {
const selectedMode = form.values.selectedMode
const selectedDate = stagedDates.value.find(d => d.includes(form.values.selectedDate))!
return `${API_BASE_URL}/balloon/render/single?mode=${encodeURIComponent(selectedMode)}&path=${encodeURIComponent(selectedDate)}`
})
function submit() {
const value = form.values
const selectedMode = value.selectedMode
const selectedDate = stagedDates.value.find(d => d.includes(value.selectedDate))
get_image(selectedMode, selectedDate!)
async function customHandle(resp: Response) {
if (resp.status === 204) {
const res: ImageResult = {
message: '这一天没有数据',
result: 'error',
resourceId: '',
}
return res
}
if (resp.status === 200) {
const blob = await resp.blob()
const url = URL.createObjectURL(blob)
const res: ImageResult = {
message: '成功',
result: 'success',
resourceId: url,
}
return res
}
return {
message: '未知错误',
result: 'error',
resourceId: '',
} as ImageResult
}
</script>
<template>
<DenseFramework :image-result="imageResult" @submit="submit">
<DenseFramework :image-query="queryUrl" :extra-response-handle="customHandle">
<AutoForm
:form="form"
:field-config="{

View File

@ -7,17 +7,10 @@ meta:
</route>
<script setup lang="ts">
import type { ImageResult } from '~/components/ImageContainer.vue'
import { API_BASE_URL } from '~/CONSTANT'
const selectedMode = ref('w/f值统计结果')
const imageResult = reactive<ImageResult>({
result: 'idle',
imageUrl: '',
message: '请你选择一个模式和日期',
})
const isIllegal = ref(false)
const startYear = ref(2017)
@ -60,14 +53,9 @@ const mode_display_mapping = {
'动能和势能分布情况': '动能和势能分布情况',
}
async function refreshImage() {
const url = `${API_BASE_URL}/balloon/render/year?mode=${encodeURIComponent(selectedMode.value)}&start_year=${startYear.value}&end_year=${endYear.value}`
const { data } = await baseFetch(url).arrayBuffer()
const blob = new Blob([data.value!])
const u = URL.createObjectURL(blob)
imageResult.result = 'success'
imageResult.imageUrl = u
}
const queryUrl = computed(() => {
return `${API_BASE_URL}/balloon/render/year?mode=${encodeURIComponent(selectedMode.value)}&start_year=${startYear.value}&end_year=${endYear.value}`
})
watch([selectedMode, startYear, endYear], () => {
if (startYear.value > endYear.value) {
@ -79,7 +67,7 @@ watch([selectedMode, startYear, endYear], () => {
</script>
<template>
<DenseFramework :image-result="imageResult" @submit="refreshImage">
<DenseFramework :image-query="queryUrl">
<div flex="col gap-5 ~ justify-center">
<div>
<Label>统计参数</Label>

View File

@ -8,16 +8,9 @@
</route>
<script setup lang="ts">
import type { ImageResult } from '~/components/ImageContainer.vue'
import DenseFramework from '~/components/DenseFramework.vue'
import { API_BASE_URL } from '~/CONSTANT'
const imageResult = reactive<ImageResult>({
result: 'idle',
imageUrl: '',
message: '',
})
const selectedT = ref<'5' | '10' | '16'>('5')
const fetchUrl = computed(() => {
@ -25,27 +18,10 @@ const fetchUrl = computed(() => {
query.set('T_', selectedT.value)
return `${API_BASE_URL}/cosmic/temp_render?${query}`
})
const { onFetchResponse, isFetching, execute } = baseFetch(fetchUrl, {
immediate: false,
})
watch(isFetching, (isFetching) => {
if (isFetching) {
imageResult.result = 'pending'
}
})
onFetchResponse(async (resp) => {
const blob = await resp.blob()
const url = URL.createObjectURL(blob)
imageResult.result = 'success'
imageResult.imageUrl = url
})
</script>
<template>
<DenseFramework :image-result="imageResult" @submit="execute">
<DenseFramework :image-query="fetchUrl">
<Label for="T_range">行星波周期</Label>
<Tabs id="T_range" v-model="selectedT" default-value="5">
<TabsList class="grid grid-cols-3 w-full">

View File

@ -10,7 +10,6 @@
</route>
<script setup lang="ts">
import type { ImageResult } from '~/components/ImageContainer.vue'
import { API_BASE_URL } from '~/CONSTANT'
const selectedMode = ref('2日行星波')
@ -23,12 +22,6 @@ const selectedH = ref(94000)
const selectedDate = ref('20170316')
const selectedMonth = ref('1')
const imageResult = reactive<ImageResult>({
result: 'idle',
imageUrl: '',
message: '请你选择一个模式和日期',
})
const modes = [
'2日行星波',
'5日行星波',
@ -68,21 +61,6 @@ const queryUrl = computed(() => {
return path
})
const { onFetchResponse, isFetching, execute } = baseFetch(queryUrl, { immediate: false })
onFetchResponse(async (resp) => {
const blob = await resp.blob()
const url = URL.createObjectURL(blob)
imageResult.result = 'success'
imageResult.imageUrl = url
})
watch(isFetching, (fetching) => {
if (fetching) {
imageResult.result = 'pending'
}
})
onMounted(async () => {
const resp = await baseFetch(`${API_BASE_URL}/radar/metadata`).json()
const data = await resp.data.value
@ -118,7 +96,7 @@ watch(selectedYear, (newV) => {
</script>
<template>
<DenseFramework :image-result="imageResult" @submit="execute">
<DenseFramework :image-query="queryUrl">
<div>
<div flex="~ col gap-3" py-3>
<Label for="waves">波类型</Label>

View File

@ -10,7 +10,6 @@
</route>
<script setup lang="ts">
import type { ImageResult } from '~/components/ImageContainer.vue'
import { API_BASE_URL } from '~/CONSTANT'
const selectedMode = ref('2日行星波')
@ -18,11 +17,6 @@ const selectedWave = ref('潮汐波')
const selectedStation = ref('武汉左岭镇站')
const selectedYear = ref('2017')
const selectedMonthRange = reactive({ start: '1', end: '12' })
const imageResult = reactive<ImageResult>({
result: 'idle',
imageUrl: '',
message: '请你选择一个模式和日期',
})
const modes = [
'2日行星波',
@ -47,21 +41,6 @@ const queryUrl = computed(() => {
return path
})
const { onFetchResponse, isFetching, execute } = baseFetch(queryUrl, { immediate: false })
onFetchResponse(async (resp) => {
const blob = await resp.blob()
const url = URL.createObjectURL(blob)
imageResult.result = 'success'
imageResult.imageUrl = url
})
watch(isFetching, (fetching) => {
if (fetching) {
imageResult.result = 'pending'
}
})
onMounted(async () => {
const resp = await baseFetch(`${API_BASE_URL}/radar/metadata`).json()
const data = await resp.data.value!
@ -87,7 +66,7 @@ onMounted(async () => {
</script>
<template>
<DenseFramework :image-result="imageResult" @submit="execute">
<DenseFramework :image-query="queryUrl">
<div>
<div flex="~ col items-stretch gap-3" py-3>
<Label>计算模式</Label>

View File

@ -10,7 +10,6 @@
</route>
<script setup lang="ts">
import type { ImageResult } from '~/components/ImageContainer.vue'
import { API_BASE_URL } from '~/CONSTANT'
import { currentSaberDays, refreshCurrentSaberDays, refreshPath, saberPaths } from './utils'
@ -20,35 +19,12 @@ const selected = reactive({
cycle_no: 1,
})
const imageResult = reactive<ImageResult>({
result: 'idle',
imageUrl: '',
message: '请你选择一个模式和日期',
})
const urll = computed(() => {
const path = encodeURIComponent(selected.path)
const day = encodeURIComponent(selected.day)
const query = `path=${path}&day=${day}&cycle_no=${selected.cycle_no}`
return `${API_BASE_URL}/saber/render/day_cycle_power_wave_plot?${query}`
})
const { onFetchResponse, isFetching, execute } = baseFetch(
urll,
{ 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 () => {
await refreshPath()
@ -75,7 +51,7 @@ function renderPath(path: string) {
</script>
<template>
<DenseFramework :image-result="imageResult" @submit="execute">
<DenseFramework :image-query="urll">
<div>
<div flex="~ col items-stretch gap-3" py-3>
<Label for="day">年月</Label>

View File

@ -10,45 +10,21 @@
</route>
<script setup lang="ts">
import type { ImageResult } from '~/components/ImageContainer.vue'
import { API_BASE_URL } from '~/CONSTANT'
import { currentSaberDays, refreshCurrentSaberDays, refreshPath, saberPaths } from './utils'
const selected = reactive({
path: './saber/data\\2012\\SABER_Temp_O3_April2012_v2.0.nc',
path: './saber/data/2012/SABER_Temp_O3_April2012_v2.0.nc',
day: '',
cycle_no: 1,
})
const imageResult = reactive<ImageResult>({
result: 'idle',
imageUrl: '',
message: '请你选择一个模式和日期',
})
const urll = computed(() => {
const path = encodeURIComponent(selected.path)
const day = encodeURIComponent(selected.day)
const query = `path=${path}&day=${day}&cycle_no=${selected.cycle_no}`
return `${API_BASE_URL}/saber/render/day_fft_ifft_plot?${query}`
})
const { onFetchResponse, isFetching, execute } = baseFetch(
urll,
{ 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 () => {
await refreshPath()
@ -57,9 +33,6 @@ onMounted(async () => {
watch(() => selected.path, async () => {
await refreshCurrentSaberDays(selected.path)
if (selected.day === '') {
selected.day = currentSaberDays.value[0]
}
})
function renderPath(path: string) {
@ -72,7 +45,7 @@ function renderPath(path: string) {
</script>
<template>
<DenseFramework :image-result="imageResult" @submit="execute">
<DenseFramework :image-query="urll">
<div>
<div flex="~ col items-stretch gap-3" py-3>
<Label for="day">年月</Label>

View File

@ -10,7 +10,6 @@
</route>
<script setup lang="ts">
import type { ImageResult } from '~/components/ImageContainer.vue'
import { API_BASE_URL } from '~/CONSTANT'
import { refreshPath, saberPaths } from './utils'
@ -18,34 +17,11 @@ const selected = reactive({
path: '',
})
const imageResult = reactive<ImageResult>({
result: 'idle',
imageUrl: '',
message: '请你选择一个模式和日期',
})
const urll = computed(() => {
const path = encodeURIComponent(selected.path)
const query = `path=${path}`
return `${API_BASE_URL}/saber/render/month_power_wave_plot?${query}`
})
const { onFetchResponse, execute, isFetching } = baseFetch(
urll,
{ 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 () => {
await refreshPath()
@ -62,7 +38,7 @@ function renderPath(path: string) {
</script>
<template>
<DenseFramework :image-result="imageResult" @submit="execute">
<DenseFramework :image-query="urll">
<div>
<div flex="~ row items-center gap-3" py-3>
<Label for="day">年月</Label>

View File

@ -10,7 +10,6 @@
</route>
<script setup lang="ts">
import type { ImageResult } from '~/components/ImageContainer.vue'
import { API_BASE_URL } from '~/CONSTANT'
import { currentSaberDays, refreshCurrentSaberDays, refreshPath, saberPaths } from './utils'
@ -20,35 +19,12 @@ const selected = reactive({
height_no: 1,
})
const imageResult = reactive<ImageResult>({
result: 'idle',
imageUrl: '',
message: '请你选择一个模式和日期',
})
const urll = computed(() => {
const path = encodeURIComponent(selected.path)
const day = encodeURIComponent(selected.day)
const query = `path=${path}&day=${day}&height=${selected.height_no}`
return `${API_BASE_URL}/saber/render/plot_wave_fitting?${query}`
})
const { onFetchResponse, execute, isFetching } = baseFetch(
urll,
{ 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 () => {
await refreshPath()
@ -72,7 +48,7 @@ function renderPath(path: string) {
</script>
<template>
<DenseFramework :image-result="imageResult" @submit="execute">
<DenseFramework :image-query="urll">
<div>
<div flex="~ col justify-stretch gap-3" py-3>
<Label for="day">年月</Label>

View File

@ -11,15 +11,8 @@
</route>
<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[])
@ -38,21 +31,6 @@ const queryUrl = computed(() => {
return `${API_BASE_URL}/tidi/render/wave?${query}`
})
const { execute, onFetchResponse, isFetching } = baseFetch(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 baseFetch<{ path: string [] }>(`${API_BASE_URL}/tidi/metadata`).json()
const _years = metas.data.value.path.map((a: string) => {
@ -66,7 +44,7 @@ onMounted(async () => {
</script>
<template>
<DenseFramework :image-result="imageResult" @submit="execute">
<DenseFramework :image-query="queryUrl">
<div flex="col gap-3 ~ justify-stretch">
<Label>计算模式</Label>
<Tabs id="modes" v-model="selectedMode" default-value="V_Meridional">