|
|
|
@ -25,6 +25,7 @@ import { |
|
|
|
Steps, |
|
|
|
Table, |
|
|
|
Tabs, |
|
|
|
Radio, |
|
|
|
} from 'ant-design-vue' |
|
|
|
import VueECharts from 'vue-echarts' |
|
|
|
import PointTransfer from '../components/PointTransfer.vue' |
|
|
|
@ -76,6 +77,8 @@ export default defineComponent({ |
|
|
|
ACol: Col, |
|
|
|
ASelect: Select, |
|
|
|
ASpace: Space, |
|
|
|
ARadio: Radio, |
|
|
|
ARadioGroup: Radio.Group, |
|
|
|
Icon, |
|
|
|
PointTransfer, |
|
|
|
}, |
|
|
|
@ -151,16 +154,17 @@ export default defineComponent({ |
|
|
|
}) |
|
|
|
const [pointTable] = useTable({ |
|
|
|
columns: pointTableSchema, |
|
|
|
pagination: true, |
|
|
|
pagination: false, |
|
|
|
dataSource: pointData, |
|
|
|
scroll: { y: 300 }, |
|
|
|
scroll: { y: 240 }, |
|
|
|
}) |
|
|
|
|
|
|
|
const trainTime = computed(() => model.value?.trainTime || []) |
|
|
|
const [trainTimeTable] = useTable({ |
|
|
|
columns: sampleInfoTableSchema, |
|
|
|
dataSource: trainTime, |
|
|
|
scroll: { y: 300 }, |
|
|
|
pagination: false, |
|
|
|
scroll: { y: 240 }, |
|
|
|
}) |
|
|
|
|
|
|
|
const effectiveSampleCount = computed(() => { |
|
|
|
@ -351,10 +355,11 @@ export default defineComponent({ |
|
|
|
}, |
|
|
|
grid: [ |
|
|
|
{ |
|
|
|
left: 60, |
|
|
|
right: 50, |
|
|
|
bottom: 50, |
|
|
|
top: 30, |
|
|
|
left: 24, |
|
|
|
right: 16, |
|
|
|
bottom: 30, |
|
|
|
top: 18, |
|
|
|
containLabel: true, |
|
|
|
}, |
|
|
|
], |
|
|
|
} |
|
|
|
@ -856,6 +861,51 @@ export default defineComponent({ |
|
|
|
reportNameSelectVisible.value = false |
|
|
|
} |
|
|
|
|
|
|
|
const assessConfigVisible = ref(false) |
|
|
|
const assessSource = ref<'train' | 'time'>('train') |
|
|
|
const assessTimeRange = ref<RangeValue | null>(null) |
|
|
|
const assessSampleCount = ref<number | null>(null) |
|
|
|
|
|
|
|
function openAssessConfig() { |
|
|
|
assessSource.value = 'train' |
|
|
|
assessTimeRange.value = null |
|
|
|
assessSampleCount.value = effectiveSampleCount.value || 0 |
|
|
|
assessConfigVisible.value = true |
|
|
|
} |
|
|
|
|
|
|
|
function handleAssessConfigOk() { |
|
|
|
if (assessSource.value === 'train' && (!model.value?.trainTime || model.value.trainTime.length === 0)) { |
|
|
|
createMessage.warning('暂无训练样本,请选择时间范围') |
|
|
|
return |
|
|
|
} |
|
|
|
if (assessSource.value === 'time') { |
|
|
|
if (!assessTimeRange.value || assessTimeRange.value.length !== 2) { |
|
|
|
createMessage.warning('请选择时间范围') |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
const version = selectedVersion.value || model.value?.Cur_Version || 'v-test' |
|
|
|
const algorithm = model.value?.algorithm || 'PCA' |
|
|
|
const queryParts = [ |
|
|
|
`version=${encodeURIComponent(version)}`, |
|
|
|
`algorithm=${algorithm}`, |
|
|
|
] |
|
|
|
if (assessSource.value === 'time' && assessTimeRange.value) { |
|
|
|
const [start, end] = assessTimeRange.value |
|
|
|
queryParts.push('sampleType=time') |
|
|
|
queryParts.push(`startTime=${encodeURIComponent(dayjs(start).format('YYYY-MM-DD HH:mm:ss'))}`) |
|
|
|
queryParts.push(`endTime=${encodeURIComponent(dayjs(end).format('YYYY-MM-DD HH:mm:ss'))}`) |
|
|
|
} |
|
|
|
else { |
|
|
|
queryParts.push('sampleType=train') |
|
|
|
} |
|
|
|
if (assessSampleCount.value !== null && assessSampleCount.value !== undefined && assessSampleCount.value !== '') { |
|
|
|
queryParts.push(`sampleCount=${assessSampleCount.value}`) |
|
|
|
} |
|
|
|
assessConfigVisible.value = false |
|
|
|
go(`/model/assess-report/${id}?${queryParts.join('&')}`) |
|
|
|
} |
|
|
|
|
|
|
|
async function openBottomModal() { |
|
|
|
if (!model.value?.para) { |
|
|
|
createMessage.error('模型未训练,无法下装') |
|
|
|
@ -1016,9 +1066,13 @@ export default defineComponent({ |
|
|
|
function goAssessReport(reportId?: number | null | Event) { |
|
|
|
// 防止直接作为事件处理时收到 PointerEvent |
|
|
|
const rid = (reportId && typeof reportId === 'object') ? null : reportId |
|
|
|
if (!rid) { |
|
|
|
openAssessConfig() |
|
|
|
return |
|
|
|
} |
|
|
|
const version = selectedVersion.value || model.value?.Cur_Version || 'v-test' |
|
|
|
const algorithm = model.value?.algorithm || 'PCA' |
|
|
|
const extra = rid ? `&reportId=${rid}` : '' |
|
|
|
const extra = `&reportId=${rid}` |
|
|
|
go(`/model/assess-report/${id}?version=${encodeURIComponent(version)}&algorithm=${algorithm}${extra}`) |
|
|
|
} |
|
|
|
|
|
|
|
@ -1083,15 +1137,20 @@ export default defineComponent({ |
|
|
|
showTrainActions, |
|
|
|
canEditModel, |
|
|
|
effectiveSampleCount, |
|
|
|
assessConfigVisible, |
|
|
|
assessSource, |
|
|
|
assessTimeRange, |
|
|
|
assessSampleCount, |
|
|
|
handleAssessConfigOk, |
|
|
|
} |
|
|
|
}, |
|
|
|
}) |
|
|
|
</script> |
|
|
|
|
|
|
|
<template> |
|
|
|
<PageWrapper content-background> |
|
|
|
<PageWrapper class="train-page" content-background> |
|
|
|
<div> |
|
|
|
<a-card title="模型信息" :bordered="false"> |
|
|
|
<a-card title="模型信息" :bordered="false" class="compact-card"> |
|
|
|
<a-descriptions size="small" :column="4" bordered> |
|
|
|
<a-descriptions-item label="模型名称"> |
|
|
|
{{ model?.name }} |
|
|
|
@ -1149,7 +1208,7 @@ export default defineComponent({ |
|
|
|
{{ model?.modifiedTime || "暂无" }} |
|
|
|
</a-descriptions-item> |
|
|
|
</a-descriptions> |
|
|
|
<a-divider /> |
|
|
|
<a-divider class="compact-divider" /> |
|
|
|
<a-descriptions size="small" :column="4" bordered> |
|
|
|
<a-descriptions-item label="算法"> |
|
|
|
{{ model?.algorithm || "PCA" }} |
|
|
|
@ -1187,17 +1246,17 @@ export default defineComponent({ |
|
|
|
<a-card |
|
|
|
title="模式" |
|
|
|
:bordered="false" |
|
|
|
style="margin-top: 16px; margin-bottom: -20px" |
|
|
|
class="compact-card mode-card" |
|
|
|
> |
|
|
|
<a-button size="large" :disabled="!canEditModel" @click="openEditMode"> |
|
|
|
{{ model?.alarmmodelset?.alarmname || '全工况运行' }} |
|
|
|
</a-button> |
|
|
|
</a-card> |
|
|
|
|
|
|
|
<a-card :bordered="false"> |
|
|
|
<a-card :bordered="false" class="compact-card tab-card"> |
|
|
|
<a-tabs v-model:active-key="activeKey"> |
|
|
|
<a-tab-pane key="1" tab="训练采样时间"> |
|
|
|
<BasicTable @register="trainTimeTable"> |
|
|
|
<BasicTable class="compact-table" @register="trainTimeTable"> |
|
|
|
<template #action="{ record, index }"> |
|
|
|
<a-button |
|
|
|
v-if="showTrainActions" |
|
|
|
@ -1212,7 +1271,7 @@ export default defineComponent({ |
|
|
|
</BasicTable> |
|
|
|
</a-tab-pane> |
|
|
|
<a-tab-pane key="2" tab="测点参数"> |
|
|
|
<BasicTable @register="pointTable"> |
|
|
|
<BasicTable class="compact-table" @register="pointTable"> |
|
|
|
<template #action="{ record, index }"> |
|
|
|
<a-button |
|
|
|
v-if="showTrainActions" |
|
|
|
@ -1228,9 +1287,9 @@ export default defineComponent({ |
|
|
|
</a-tabs> |
|
|
|
</a-card> |
|
|
|
|
|
|
|
<a-card title="智能训练" :bordered="false"> |
|
|
|
<div style="display: flex; align-items: center"> |
|
|
|
<a-form layout="inline" style="flex: 1"> |
|
|
|
<a-card title="智能训练" :bordered="false" class="compact-card"> |
|
|
|
<div class="train-toolbar"> |
|
|
|
<a-form layout="inline" class="train-toolbar-form"> |
|
|
|
<a-form-item label="模型预览时间范围"> |
|
|
|
<a-range-picker |
|
|
|
v-model:value="historyTime" |
|
|
|
@ -1242,7 +1301,6 @@ export default defineComponent({ |
|
|
|
<a-button |
|
|
|
v-if="showTrainActions" |
|
|
|
type="primary" |
|
|
|
style="margin-left: auto" |
|
|
|
@click="trainModel" |
|
|
|
> |
|
|
|
模型训练 |
|
|
|
@ -1250,7 +1308,7 @@ export default defineComponent({ |
|
|
|
<a-button |
|
|
|
v-if="showTrainActions" |
|
|
|
type="primary" |
|
|
|
style="margin-left: 10px" |
|
|
|
class="ml-8" |
|
|
|
@click="clearModel" |
|
|
|
> |
|
|
|
清除训练结果 |
|
|
|
@ -1258,7 +1316,7 @@ export default defineComponent({ |
|
|
|
<a-button |
|
|
|
v-if="showTrainActions" |
|
|
|
type="primary" |
|
|
|
style="margin-left: 6px" |
|
|
|
class="ml-8" |
|
|
|
@click="openEditModel" |
|
|
|
> |
|
|
|
修改模型 |
|
|
|
@ -1266,13 +1324,13 @@ export default defineComponent({ |
|
|
|
<a-button |
|
|
|
v-if="showTrainActions" |
|
|
|
danger |
|
|
|
style="margin-left: 10px" |
|
|
|
class="ml-8" |
|
|
|
@click="openBottomModal" |
|
|
|
> |
|
|
|
下装 |
|
|
|
</a-button> |
|
|
|
</div> |
|
|
|
<a-divider /> |
|
|
|
<a-divider class="compact-divider" /> |
|
|
|
<a-spin :spinning="spinning" size="large"> |
|
|
|
<div |
|
|
|
v-for="(item, index) in historyList" |
|
|
|
@ -1280,7 +1338,7 @@ export default defineComponent({ |
|
|
|
class="echart-box" |
|
|
|
style="width: 100%" |
|
|
|
> |
|
|
|
<a-card :bordered="false" style="margin-bottom: 16px"> |
|
|
|
<a-card :bordered="false" class="compact-card inner-card"> |
|
|
|
<template #title> |
|
|
|
<span style="font-size: 20px">{{ item.name }}</span> |
|
|
|
</template> |
|
|
|
@ -1288,7 +1346,7 @@ export default defineComponent({ |
|
|
|
:ref="(el) => setEchartsRef(el, index)" |
|
|
|
:option="getOption(item)" |
|
|
|
autoresize |
|
|
|
style="width: 100%; height: 200px" |
|
|
|
style="width: 100%; height: 180px" |
|
|
|
@finished="() => onChartFinished(index)" |
|
|
|
@brush-selected="onBrushSelected" |
|
|
|
/> |
|
|
|
@ -1297,6 +1355,48 @@ export default defineComponent({ |
|
|
|
</a-spin> |
|
|
|
</a-card> |
|
|
|
</div> |
|
|
|
<a-modal |
|
|
|
v-model:open="assessConfigVisible" |
|
|
|
title="样本选择" |
|
|
|
width="520px" |
|
|
|
@ok="handleAssessConfigOk" |
|
|
|
@cancel="() => { assessConfigVisible = false }" |
|
|
|
> |
|
|
|
<a-space direction="vertical" size="middle" style="width: 100%"> |
|
|
|
<div class="assess-option"> |
|
|
|
<a-radio-group v-model:value="assessSource"> |
|
|
|
<a-radio value="train"> |
|
|
|
训练样本 |
|
|
|
</a-radio> |
|
|
|
<a-radio value="time"> |
|
|
|
时间选择 |
|
|
|
</a-radio> |
|
|
|
</a-radio-group> |
|
|
|
</div> |
|
|
|
<div class="assess-option"> |
|
|
|
<span class="assess-label">时间范围</span> |
|
|
|
<a-range-picker |
|
|
|
v-model:value="assessTimeRange" |
|
|
|
show-time |
|
|
|
format="YYYY-MM-DD HH:mm:ss" |
|
|
|
style="flex: 1" |
|
|
|
:disabled="assessSource !== 'time'" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
<div class="assess-option"> |
|
|
|
<span class="assess-label">样本数量</span> |
|
|
|
<a-input-number |
|
|
|
v-model:value="assessSampleCount" |
|
|
|
:min="0" |
|
|
|
:max="effectiveSampleCount || undefined" |
|
|
|
:controls="false" |
|
|
|
style="flex: 1" |
|
|
|
placeholder="请输入样本数量" |
|
|
|
/> |
|
|
|
<span class="assess-hint">样本选择范围0-{{ effectiveSampleCount }}</span> |
|
|
|
</div> |
|
|
|
</a-space> |
|
|
|
</a-modal> |
|
|
|
<a-modal |
|
|
|
v-model:open="reportModalVisible" |
|
|
|
title="选择评估报告" |
|
|
|
@ -1455,4 +1555,129 @@ export default defineComponent({ |
|
|
|
.el-table .el-table__header th { |
|
|
|
font-weight: bold; |
|
|
|
} |
|
|
|
|
|
|
|
.train-page { |
|
|
|
padding: 8px; |
|
|
|
background: #f6f7fb; |
|
|
|
} |
|
|
|
|
|
|
|
.assess-option { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
gap: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.assess-label { |
|
|
|
width: 72px; |
|
|
|
color: #4b5563; |
|
|
|
} |
|
|
|
|
|
|
|
.assess-hint { |
|
|
|
color: #9098a4; |
|
|
|
font-size: 12px; |
|
|
|
} |
|
|
|
|
|
|
|
.compact-card { |
|
|
|
margin-top: -10px; |
|
|
|
margin-bottom: 8px; |
|
|
|
border-color: #d9dfe7; |
|
|
|
border-radius: 8px; |
|
|
|
box-shadow: 0 2px 6px rgb(0 0 0 / 3%); |
|
|
|
} |
|
|
|
|
|
|
|
.compact-card :deep(.ant-card-head) { |
|
|
|
min-height: 32px; |
|
|
|
padding: 0 8px; |
|
|
|
background: linear-gradient(90deg, #f9fafc 0%, #f6f8fb 100%); |
|
|
|
} |
|
|
|
|
|
|
|
.compact-card :deep(.ant-card-head-title) { |
|
|
|
padding: 6px 0; |
|
|
|
font-weight: 600; |
|
|
|
color: #1d2733; |
|
|
|
} |
|
|
|
|
|
|
|
.compact-card :deep(.ant-card-body) { |
|
|
|
padding: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.compact-card :deep(.ant-descriptions-item-label), |
|
|
|
.compact-card :deep(.ant-descriptions-item-content) { |
|
|
|
padding: 4px 6px; |
|
|
|
font-size: 13px; |
|
|
|
} |
|
|
|
|
|
|
|
.compact-divider { |
|
|
|
margin: 8px 0; |
|
|
|
} |
|
|
|
|
|
|
|
.compact-table :deep(.ant-table-thead > tr > th), |
|
|
|
.compact-table :deep(.ant-table-tbody > tr > td) { |
|
|
|
padding: 4px 6px; |
|
|
|
font-size: 13px; |
|
|
|
} |
|
|
|
|
|
|
|
.compact-table :deep(.ant-table-thead > tr > th) { |
|
|
|
color: #2a2f36; |
|
|
|
background: #f2f4f8; |
|
|
|
} |
|
|
|
|
|
|
|
.mode-card { |
|
|
|
margin-top: 2px; |
|
|
|
margin-bottom: -24px; |
|
|
|
} |
|
|
|
|
|
|
|
.mode-card :deep(.ant-card-body) { |
|
|
|
padding: 2px 8px 4px; |
|
|
|
} |
|
|
|
|
|
|
|
.mode-card :deep(.ant-btn-lg) { |
|
|
|
height: 34px; |
|
|
|
padding: 0 14px; |
|
|
|
font-size: 14px; |
|
|
|
line-height: 34px; |
|
|
|
} |
|
|
|
|
|
|
|
.tab-card :deep(.ant-card-body) { |
|
|
|
padding: 4px 6px 4px; |
|
|
|
} |
|
|
|
|
|
|
|
.train-toolbar { |
|
|
|
display: flex; |
|
|
|
gap: 6px; |
|
|
|
align-items: center; |
|
|
|
} |
|
|
|
|
|
|
|
.train-toolbar-form { |
|
|
|
flex: 1; |
|
|
|
} |
|
|
|
|
|
|
|
.train-toolbar :deep(.ant-form-item) { |
|
|
|
margin-bottom: 6px; |
|
|
|
} |
|
|
|
|
|
|
|
.ml-8 { |
|
|
|
margin-left: 6px; |
|
|
|
} |
|
|
|
|
|
|
|
.echart-box { |
|
|
|
margin-bottom: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.inner-card :deep(.ant-card-body) { |
|
|
|
padding: 8px 8px 6px; |
|
|
|
} |
|
|
|
|
|
|
|
.inner-card :deep(.ant-card-head-title) { |
|
|
|
font-size: 15px; |
|
|
|
} |
|
|
|
|
|
|
|
.train-toolbar :deep(.ant-btn) { |
|
|
|
font-size: 13px; |
|
|
|
} |
|
|
|
|
|
|
|
.train-toolbar :deep(.ant-input), |
|
|
|
.train-toolbar :deep(.ant-picker) { |
|
|
|
font-size: 13px; |
|
|
|
} |
|
|
|
</style> |
|
|
|
|