2 changed files with 351 additions and 141 deletions
@ -1,200 +1,210 @@ |
|||
<script lang="ts" setup> |
|||
import { onMounted, reactive, ref } from 'vue' |
|||
import type { Dayjs } from 'dayjs' |
|||
import { onMounted, ref } from 'vue' |
|||
import moment from 'moment' |
|||
import { Card, Descriptions, DescriptionsItem, Form, FormItem, RangePicker, Space, Switch, message } from 'ant-design-vue' |
|||
import { mount } from 'sortablejs' |
|||
import { number } from 'vue-types' |
|||
import { useRoute } from 'vue-router' |
|||
import HistoryLine from '../../exa/HistoryLine.vue' |
|||
import { detailColumns, instantForm } from './instant.data' |
|||
import { getExaHistorys } from '@/api/alert/exa' |
|||
import { useModal } from '@/components/Modal' |
|||
import { BasicTable, TableAction, useTable } from '@/components/Table' |
|||
import { getInstant, getInstantChart, getInstantPage, getInstantPoint } from '@/api/alert/run/instant' |
|||
import { Card, Descriptions, DescriptionsItem, message } from 'ant-design-vue' |
|||
import { useRoute, useRouter } from 'vue-router' |
|||
import { useI18n } from '@/hooks/web/useI18n' |
|||
import { router } from '@/router' |
|||
import { BasicForm, useForm } from '@/components/Form' |
|||
import PropsPanel from '@/components/FormDesign/src/components/VFormDesign/modules/PropsPanel.vue' |
|||
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 props = defineProps({ |
|||
// id: { |
|||
// type: Number, |
|||
// default: null, |
|||
// }, |
|||
// }) |
|||
const router = useRouter() |
|||
const { t } = useI18n() |
|||
const loadingBasic = ref<boolean>(false) |
|||
const loadingChart = ref<boolean>(false) |
|||
|
|||
const basicInfo = ref<any>({}) |
|||
const modelInfo = ref<any>({}) |
|||
const pointInfo = ref<any>({}) |
|||
const pointList = ref<any>([]) |
|||
const historyList = ref<any>([]) |
|||
|
|||
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, |
|||
// baseColProps: { span: 24 }, |
|||
schemas: instantForm, |
|||
showResetButton: false, |
|||
layout: 'horizontal', |
|||
// model: { time: [moment().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD HH:mm:ss')] }, |
|||
fieldMapToTime: [ |
|||
// data为时间组件在表单内的字段,startTime,endTime为转化后的开始时间于结束时间 |
|||
['time', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss'], |
|||
], |
|||
actionColOptions: { |
|||
span: 2, |
|||
style:{ |
|||
marginLeft:'5px' |
|||
}}, |
|||
}) |
|||
|
|||
const instantId = ref<any>(route.query.mpId) // 获取URL中的query参数 |
|||
|
|||
onMounted(async () => { |
|||
loadingBasic.value = true |
|||
basicInfo.value = await getInstant(instantId.value) |
|||
loadingBasic.value = false |
|||
|
|||
modelInfo.value = JSON.parse(basicInfo.value.modelInfo) |
|||
pointInfo.value = modelInfo.value.pointInfo |
|||
console.log(modelInfo.value) |
|||
pointList.value = await getInstantPoint(instantId.value) |
|||
getChartsData() |
|||
fieldMapToTime: [['time', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss']], |
|||
}) |
|||
|
|||
function handleSubmitR() { |
|||
getChartsData() |
|||
} |
|||
async function getChartsData() { |
|||
setProps({ |
|||
submitButtonOptions: { |
|||
loading: true, |
|||
}, |
|||
}) |
|||
|
|||
loadingChart.value = true |
|||
console.log(getFieldsValue()) |
|||
const instantForm = getFieldsValue() |
|||
|
|||
historyList.value = await getInstantChart({ ...{ id: instantId.value }, ...instantForm }) |
|||
echarts.connect('async') |
|||
|
|||
loadingChart.value = false |
|||
setProps({ |
|||
submitButtonOptions: { |
|||
loading: false, |
|||
}, |
|||
}) |
|||
} |
|||
|
|||
/* ======================= |
|||
* 表格 |
|||
* ======================= */ |
|||
const [registerTable] = useTable({ |
|||
title: '测点列表', |
|||
size: 'small', |
|||
dataSource: pointList, |
|||
columns: detailColumns, |
|||
useSearchForm: false, |
|||
showTableSetting: true, |
|||
showIndexColumn: false, |
|||
actionColumn: { |
|||
width: 140, |
|||
title: t('common.action'), |
|||
dataIndex: 'action', |
|||
fixed: 'right', |
|||
}, |
|||
}) |
|||
|
|||
function handleDetail(record) { |
|||
console.log(record) |
|||
router.push('/run/instant/detail') |
|||
} |
|||
/* ======================= |
|||
* 生命周期 |
|||
* ======================= */ |
|||
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 |
|||
|
|||
function handleFaultConfig(field) { |
|||
console.log(field) |
|||
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="创建时间"> |
|||
{{ moment(basicInfo.createTime).format("YYYY-MM-DD HH:mm:ss") }} |
|||
</DescriptionsItem> |
|||
<DescriptionsItem label="最近修改人"> |
|||
{{ basicInfo.updateName }} |
|||
</DescriptionsItem> |
|||
<DescriptionsItem label="最近修改时间"> |
|||
{{ 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 |
|||
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> |
|||
<!-- <SlidersOutlined class="click-status" /> --> |
|||
<a class="click-status" @click="handleDetail(record)">{{ record.mpName }}</a> |
|||
</template> |
|||
</BasicTable> |
|||
</Card> |
|||
|
|||
<Card> |
|||
<BasicForm @register="registerForm" @submit="handleSubmitR"> |
|||
<!-- 添加button的插槽 --> |
|||
<template #configButton="{ field }"> |
|||
<a-button @click="handleFaultConfig(field)"> |
|||
故障配置 |
|||
</a-button> |
|||
</template> |
|||
</BasicForm> |
|||
<BasicForm @register="registerForm" @submit="getChartsData" /> |
|||
</Card> |
|||
|
|||
<Card :loading="loadingChart"> |
|||
<div> |
|||
<div v-for="(item, index) in historyList" :key="index"> |
|||
<div style="border:1px solid #ccc"> |
|||
<HistoryLine :is-async="index !== 0" :title="item.title" :data="item.seriesData" :name="item.name" height="250px" /> |
|||
</div> |
|||
<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 |
|||
:deep(.ant-table-body) { |
|||
height: 100% !important; |
|||
max-height: 100% !important; |
|||
} |
|||
</style> |
|||
|
|||
@ -0,0 +1,200 @@ |
|||
<script lang="ts" setup> |
|||
import { onMounted, reactive, ref } from 'vue' |
|||
import type { Dayjs } from 'dayjs' |
|||
import moment from 'moment' |
|||
import { Card, Descriptions, DescriptionsItem, Form, FormItem, RangePicker, Space, Switch, message } from 'ant-design-vue' |
|||
import { mount } from 'sortablejs' |
|||
import { number } from 'vue-types' |
|||
import { useRoute } from 'vue-router' |
|||
import HistoryLine from '../../exa/HistoryLine.vue' |
|||
import { detailColumns, instantForm } from './instant.data' |
|||
import { getExaHistorys } from '@/api/alert/exa' |
|||
import { useModal } from '@/components/Modal' |
|||
import { BasicTable, TableAction, useTable } from '@/components/Table' |
|||
import { getInstant, getInstantChart, getInstantPage, getInstantPoint } from '@/api/alert/run/instant' |
|||
import { useI18n } from '@/hooks/web/useI18n' |
|||
import { router } from '@/router' |
|||
import { BasicForm, useForm } from '@/components/Form' |
|||
import PropsPanel from '@/components/FormDesign/src/components/VFormDesign/modules/PropsPanel.vue' |
|||
import echarts from '@/utils/lib/echarts' |
|||
|
|||
defineOptions({ name: 'InstantDetail' }) |
|||
|
|||
const route = useRoute() |
|||
|
|||
// const props = defineProps({ |
|||
// id: { |
|||
// type: Number, |
|||
// default: null, |
|||
// }, |
|||
// }) |
|||
const { t } = useI18n() |
|||
const loadingBasic = ref<boolean>(false) |
|||
const loadingChart = ref<boolean>(false) |
|||
|
|||
const basicInfo = ref<any>({}) |
|||
const modelInfo = ref<any>({}) |
|||
const pointInfo = ref<any>({}) |
|||
const pointList = ref<any>([]) |
|||
const historyList = ref<any>([]) |
|||
const [registerForm, { getFieldsValue, setProps }] = useForm({ |
|||
labelWidth: 100, |
|||
// baseColProps: { span: 24 }, |
|||
schemas: instantForm, |
|||
showResetButton: false, |
|||
layout: 'horizontal', |
|||
// model: { time: [moment().subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'), moment().format('YYYY-MM-DD HH:mm:ss')] }, |
|||
fieldMapToTime: [ |
|||
// data为时间组件在表单内的字段,startTime,endTime为转化后的开始时间于结束时间 |
|||
['time', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss'], |
|||
], |
|||
actionColOptions: { |
|||
span: 2, |
|||
style:{ |
|||
marginLeft:'5px' |
|||
}}, |
|||
}) |
|||
|
|||
const instantId = ref<any>(route.query.mpId) // 获取URL中的query参数 |
|||
|
|||
onMounted(async () => { |
|||
loadingBasic.value = true |
|||
basicInfo.value = await getInstant(instantId.value) |
|||
loadingBasic.value = false |
|||
|
|||
modelInfo.value = JSON.parse(basicInfo.value.modelInfo) |
|||
pointInfo.value = modelInfo.value.pointInfo |
|||
console.log(modelInfo.value) |
|||
pointList.value = await getInstantPoint(instantId.value) |
|||
getChartsData() |
|||
}) |
|||
|
|||
function handleSubmitR() { |
|||
getChartsData() |
|||
} |
|||
async function getChartsData() { |
|||
setProps({ |
|||
submitButtonOptions: { |
|||
loading: true, |
|||
}, |
|||
}) |
|||
|
|||
loadingChart.value = true |
|||
console.log(getFieldsValue()) |
|||
const instantForm = getFieldsValue() |
|||
|
|||
historyList.value = await getInstantChart({ ...{ id: instantId.value }, ...instantForm }) |
|||
echarts.connect('async') |
|||
|
|||
loadingChart.value = false |
|||
setProps({ |
|||
submitButtonOptions: { |
|||
loading: false, |
|||
}, |
|||
}) |
|||
} |
|||
|
|||
const [registerTable] = useTable({ |
|||
title: '测点列表', |
|||
size: 'small', |
|||
dataSource: pointList, |
|||
columns: detailColumns, |
|||
useSearchForm: false, |
|||
showTableSetting: true, |
|||
showIndexColumn: false, |
|||
actionColumn: { |
|||
width: 140, |
|||
title: t('common.action'), |
|||
dataIndex: 'action', |
|||
fixed: 'right', |
|||
}, |
|||
}) |
|||
|
|||
function handleDetail(record) { |
|||
console.log(record) |
|||
router.push('/run/instant/detail') |
|||
} |
|||
|
|||
|
|||
function handleFaultConfig(field) { |
|||
console.log(field) |
|||
} |
|||
</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="创建时间"> |
|||
{{ moment(basicInfo.createTime).format("YYYY-MM-DD HH:mm:ss") }} |
|||
</DescriptionsItem> |
|||
<DescriptionsItem label="最近修改人"> |
|||
{{ basicInfo.updateName }} |
|||
</DescriptionsItem> |
|||
<DescriptionsItem label="最近修改时间"> |
|||
{{ 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> |
|||
<!-- <SlidersOutlined class="click-status" /> --> |
|||
</template> |
|||
</BasicTable> |
|||
</Card> |
|||
<Card> |
|||
<BasicForm @register="registerForm" @submit="handleSubmitR"> |
|||
<!-- 添加button的插槽 --> |
|||
<template #configButton="{ field }"> |
|||
<a-button @click="handleFaultConfig(field)"> |
|||
故障配置 |
|||
</a-button> |
|||
</template> |
|||
</BasicForm> |
|||
</Card> |
|||
<Card :loading="loadingChart"> |
|||
<div> |
|||
<div v-for="(item, index) in historyList" :key="index"> |
|||
<div style="border:1px solid #ccc"> |
|||
<HistoryLine :is-async="index !== 0" :title="item.title" :data="item.seriesData" :name="item.name" height="250px" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</Card> |
|||
</div> |
|||
</template> |
|||
|
|||
<style lang="less" scoped> |
|||
:deep(.ant-table-body){ |
|||
height:100% !important; |
|||
max-height:100% !important |
|||
} |
|||
</style> |
|||
Loading…
Reference in new issue