|
|
|
|
<script lang="ts" setup>
|
|
|
|
|
import { onMounted, ref } from 'vue'
|
|
|
|
|
import moment from 'moment'
|
|
|
|
|
import { Card, Descriptions, DescriptionsItem, message } from 'ant-design-vue'
|
|
|
|
|
import { useRoute, useRouter } from 'vue-router'
|
|
|
|
|
import { useI18n } from '@/hooks/web/useI18n'
|
|
|
|
|
import { BasicForm, useForm } from '@/components/Form'
|
|
|
|
|
import { BasicTable, useTable } from '@/components/Table'
|
|
|
|
|
import HistoryLine from '../../exa/HistoryLine.vue'
|
|
|
|
|
import { detailColumns, instantForm } from './instant.data'
|
|
|
|
|
import { getInstant, getInstantChart, getInstantPoint } from '@/api/alert/run/instant'
|
|
|
|
|
import echarts from '@/utils/lib/echarts'
|
|
|
|
|
|
|
|
|
|
/* =======================
|
|
|
|
|
* 类型定义(严格 TS 核心)
|
|
|
|
|
* ======================= */
|
|
|
|
|
interface BasicInfo {
|
|
|
|
|
mpName?: string
|
|
|
|
|
createName?: string
|
|
|
|
|
createTime?: string
|
|
|
|
|
updateName?: string
|
|
|
|
|
updateTime?: string
|
|
|
|
|
algorithmShortname?: string
|
|
|
|
|
modelInfo?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface ModelInfo {
|
|
|
|
|
sampling?: string | number
|
|
|
|
|
rate?: number
|
|
|
|
|
principal?: number
|
|
|
|
|
precision?: number
|
|
|
|
|
pointInfo?: any[]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface HistoryItem {
|
|
|
|
|
title: string
|
|
|
|
|
name: string
|
|
|
|
|
seriesData: any[]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ======================= */
|
|
|
|
|
|
|
|
|
|
defineOptions({ name: 'InstantDetail' })
|
|
|
|
|
|
|
|
|
|
const route = useRoute()
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
const { t } = useI18n()
|
|
|
|
|
|
|
|
|
|
const instantId = ref<number | null>(Number(route.query.mpId) || null)
|
|
|
|
|
|
|
|
|
|
const loadingBasic = ref(false)
|
|
|
|
|
const loadingChart = ref(false)
|
|
|
|
|
|
|
|
|
|
const basicInfo = ref<BasicInfo>({})
|
|
|
|
|
const modelInfo = ref<ModelInfo>({})
|
|
|
|
|
const pointInfo = ref<any[]>([])
|
|
|
|
|
const pointList = ref<any[]>([])
|
|
|
|
|
const historyList = ref<HistoryItem[]>([])
|
|
|
|
|
|
|
|
|
|
/* =======================
|
|
|
|
|
* 表单
|
|
|
|
|
* ======================= */
|
|
|
|
|
const [registerForm, { getFieldsValue, setProps }] = useForm({
|
|
|
|
|
labelWidth: 100,
|
|
|
|
|
schemas: instantForm,
|
|
|
|
|
showResetButton: false,
|
|
|
|
|
layout: 'horizontal',
|
|
|
|
|
fieldMapToTime: [['time', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss']],
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
/* =======================
|
|
|
|
|
* 表格
|
|
|
|
|
* ======================= */
|
|
|
|
|
const [registerTable] = useTable({
|
|
|
|
|
title: '测点列表',
|
|
|
|
|
size: 'small',
|
|
|
|
|
dataSource: pointList,
|
|
|
|
|
columns: detailColumns,
|
|
|
|
|
useSearchForm: false,
|
|
|
|
|
showIndexColumn: false,
|
|
|
|
|
actionColumn: {
|
|
|
|
|
width: 140,
|
|
|
|
|
title: t('common.action'),
|
|
|
|
|
dataIndex: 'action',
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
/* =======================
|
|
|
|
|
* 生命周期
|
|
|
|
|
* ======================= */
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
if (!instantId.value) return
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
loadingBasic.value = true
|
|
|
|
|
|
|
|
|
|
const res = await getInstant(instantId.value)
|
|
|
|
|
if (!res) return
|
|
|
|
|
|
|
|
|
|
basicInfo.value = res
|
|
|
|
|
|
|
|
|
|
if (res.modelInfo) {
|
|
|
|
|
try {
|
|
|
|
|
const parsed: ModelInfo = JSON.parse(res.modelInfo)
|
|
|
|
|
modelInfo.value = parsed
|
|
|
|
|
pointInfo.value = Array.isArray(parsed.pointInfo) ? parsed.pointInfo : []
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('modelInfo JSON 解析失败', e)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pointList.value = (await getInstantPoint(instantId.value)) || []
|
|
|
|
|
await getChartsData()
|
|
|
|
|
} catch (e) {
|
|
|
|
|
message.error('加载实例详情失败')
|
|
|
|
|
} finally {
|
|
|
|
|
loadingBasic.value = false
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
/* =======================
|
|
|
|
|
* 事件
|
|
|
|
|
* ======================= */
|
|
|
|
|
async function getChartsData() {
|
|
|
|
|
if (!instantId.value) return
|
|
|
|
|
|
|
|
|
|
loadingChart.value = true
|
|
|
|
|
setProps({ submitButtonOptions: { loading: true } })
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const formValue = getFieldsValue() || {}
|
|
|
|
|
const res = await getInstantChart({ id: instantId.value, ...formValue })
|
|
|
|
|
|
|
|
|
|
historyList.value = Array.isArray(res) ? res : []
|
|
|
|
|
|
|
|
|
|
if (historyList.value.length) {
|
|
|
|
|
echarts.connect('async')
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
historyList.value = []
|
|
|
|
|
message.error('获取图表数据失败')
|
|
|
|
|
} finally {
|
|
|
|
|
loadingChart.value = false
|
|
|
|
|
setProps({ submitButtonOptions: { loading: false } })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleDetail(record: any) {
|
|
|
|
|
router.push('/run/instant/detail')
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div>
|
|
|
|
|
<Card :loading="loadingBasic">
|
|
|
|
|
<Descriptions
|
|
|
|
|
size="small"
|
|
|
|
|
title="模型基本信息"
|
|
|
|
|
bordered
|
|
|
|
|
:column="{ xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }"
|
|
|
|
|
>
|
|
|
|
|
<DescriptionsItem label="实例名称" :span="4">{{ basicInfo.mpName || '-' }}</DescriptionsItem>
|
|
|
|
|
<DescriptionsItem label="创建人">{{ basicInfo.createName || '-' }}</DescriptionsItem>
|
|
|
|
|
<DescriptionsItem label="创建时间">{{ basicInfo.createTime ? moment(basicInfo.createTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</DescriptionsItem>
|
|
|
|
|
<DescriptionsItem label="最近修改人">{{ basicInfo.updateName || '-' }}</DescriptionsItem>
|
|
|
|
|
<DescriptionsItem label="最近修改时间">{{ basicInfo.updateTime ? moment(basicInfo.updateTime).format('YYYY-MM-DD HH:mm:ss') : '-' }}</DescriptionsItem>
|
|
|
|
|
<DescriptionsItem label="算法">{{ basicInfo.algorithmShortname || '-' }}</DescriptionsItem>
|
|
|
|
|
<DescriptionsItem label="训练采样间隔">{{ modelInfo.sampling ?? '-' }}</DescriptionsItem>
|
|
|
|
|
<DescriptionsItem label="参数个数">{{ pointInfo.length }}</DescriptionsItem>
|
|
|
|
|
<DescriptionsItem label="最小主元贡献率">{{ modelInfo.rate ?? '-' }}</DescriptionsItem>
|
|
|
|
|
<DescriptionsItem label="主元个数">{{ modelInfo.principal ?? '-' }}</DescriptionsItem>
|
|
|
|
|
<DescriptionsItem label="模型精度">{{ modelInfo.precision ?? '-' }}</DescriptionsItem>
|
|
|
|
|
</Descriptions>
|
|
|
|
|
</Card>
|
|
|
|
|
|
|
|
|
|
<Card>
|
|
|
|
|
<BasicTable @register="registerTable">
|
|
|
|
|
<template #detail="{ record }">
|
|
|
|
|
<a class="click-status" @click="handleDetail(record)">{{ record.mpName }}</a>
|
|
|
|
|
</template>
|
|
|
|
|
</BasicTable>
|
|
|
|
|
</Card>
|
|
|
|
|
|
|
|
|
|
<Card>
|
|
|
|
|
<BasicForm @register="registerForm" @submit="getChartsData" />
|
|
|
|
|
</Card>
|
|
|
|
|
|
|
|
|
|
<Card :loading="loadingChart">
|
|
|
|
|
<div v-if="historyList.length">
|
|
|
|
|
<div v-for="(item, index) in historyList" :key="index" style="border:1px solid #ccc">
|
|
|
|
|
<HistoryLine
|
|
|
|
|
:is-async="index !== 0"
|
|
|
|
|
:title="item.title"
|
|
|
|
|
:data="item.seriesData"
|
|
|
|
|
:name="item.name"
|
|
|
|
|
height="250px"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-else class="empty">暂无数据</div>
|
|
|
|
|
</Card>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style lang="less" scoped>
|
|
|
|
|
:deep(.ant-table-body) {
|
|
|
|
|
height: 100% !important;
|
|
|
|
|
max-height: 100% !important;
|
|
|
|
|
}
|
|
|
|
|
</style>
|