Compare commits

...

2 Commits

  1. 2
      .vscode/settings.json
  2. 2
      src/api/alert/model/models.ts
  3. 124
      src/views/model/list/step/Step3.vue
  4. 355
      src/views/model/train/index.vue

2
.vscode/settings.json

@ -120,7 +120,7 @@
"source.organizeImports": "never", "source.organizeImports": "never",
"source.fixAll.stylelint": "explicit" "source.fixAll.stylelint": "explicit"
}, },
"editor.defaultFormatter": "stylelint.vscode-stylelint" "editor.defaultFormatter": "octref.vetur"
}, },
"i18n-ally.localesPaths": ["src/locales/lang"], "i18n-ally.localesPaths": ["src/locales/lang"],
"i18n-ally.keystyle": "nested", "i18n-ally.keystyle": "nested",

2
src/api/alert/model/models.ts

@ -9,6 +9,7 @@ enum Api {
CALCULATE_BACK = '/alert/model/data/calculate/', CALCULATE_BACK = '/alert/model/data/calculate/',
OPTIMISTIC = '/alert/optimistic', OPTIMISTIC = '/alert/optimistic',
TRAIN_MODEL = '/alert/model/train', TRAIN_MODEL = '/alert/model/train',
TEST_MODEL = '/alert/model/test',
} }
export function modelCardListApi(params?: ModelQueryParams) { export function modelCardListApi(params?: ModelQueryParams) {
return defHttp.get<ModelCardItem[]>({ url: Api.MODEL_CARD_LIST, params }) return defHttp.get<ModelCardItem[]>({ url: Api.MODEL_CARD_LIST, params })
@ -34,3 +35,4 @@ export function calculateBackApi(id: any, params: any) {
export const getOptimisticApi = (params: any) => defHttp.get<any>({ url: Api.OPTIMISTIC, params }) export const getOptimisticApi = (params: any) => defHttp.get<any>({ url: Api.OPTIMISTIC, params })
export const trainModelApi = (params: any) => defHttp.post<any>({ url: Api.TRAIN_MODEL, data: params }) export const trainModelApi = (params: any) => defHttp.post<any>({ url: Api.TRAIN_MODEL, data: params })
export const testModelApi = (params: any) => defHttp.post<any>({ url: Api.TEST_MODEL, data: params })

124
src/views/model/list/step/Step3.vue

@ -1,14 +1,14 @@
<script lang="ts"> <script lang="ts">
import type { PropType } from 'vue' import type { PropType } from "vue";
import { computed, defineComponent, ref, toRaw, unref } from 'vue' import { computed, defineComponent, ref, toRaw, unref } from "vue";
import { Alert, Descriptions, Divider } from 'ant-design-vue' import { Alert, Descriptions, Divider } from "ant-design-vue";
import type { Recordable } from '@vben/types' import type { Recordable } from "@vben/types";
import { useDebounceFn } from '@vueuse/core' import { useDebounceFn } from "@vueuse/core";
import { step3Schemas } from './data' import { step3Schemas } from "./data";
import { ApiSelect, BasicForm, useForm } from '@/components/Form' import { ApiSelect, BasicForm, useForm } from "@/components/Form";
import { Button } from '@/components/Button' import { Button } from "@/components/Button";
import { pointListApi } from '@/api/alert/model/select' import { pointListApi } from "@/api/alert/model/select";
import { modelSaveApi } from '@/api/alert/model/models' import { modelSaveApi } from "@/api/alert/model/models";
export default defineComponent({ export default defineComponent({
components: { components: {
@ -28,114 +28,118 @@ export default defineComponent({
type: Number, type: Number,
}, },
}, },
emits: ['next', 'prev'], emits: ["next", "prev"],
setup(props, { emit }) { setup(props, { emit }) {
const [register, { appendSchemaByField, removeSchemaByField, validate, setProps }] = useForm({ const [
register,
{ appendSchemaByField, removeSchemaByField, validate, setProps },
] = useForm({
labelWidth: 100, labelWidth: 100,
schemas: step3Schemas, schemas: step3Schemas,
actionColOptions: { actionColOptions: {
span: 14, span: 14,
}, },
resetButtonOptions: { resetButtonOptions: {
text: '上一步', text: "上一步",
}, },
submitButtonOptions: { submitButtonOptions: {
text: '创建模型', text: "创建模型",
}, },
resetFunc: customResetFunc, resetFunc: customResetFunc,
submitFunc: customSubmitFunc, submitFunc: customSubmitFunc,
}) });
const n = ref(4) const n = ref(4);
function add() { function add() {
appendSchemaByField( appendSchemaByField(
[ [
{ {
field: `point${n.value}`, field: `point${n.value}`,
component: 'Input', component: "Input",
label: `参数${n.value}`, label: `参数${n.value}`,
required: true, required: true,
slot: 'remoteSearch', slot: "remoteSearch",
colProps: { colProps: {
span: 23, span: 23,
}, },
}, },
{ {
field: `${n.value}`, field: `${n.value}`,
component: 'Input', component: "Input",
label: ' ', label: " ",
slot: 'add', slot: "add",
colProps: { colProps: {
span: 1, span: 1,
}, },
}, },
], ],
'', ""
) );
n.value++ n.value++;
} }
function del(field) { function del(field) {
removeSchemaByField([`point${field}`, `${field}`]) removeSchemaByField([`point${field}`, `${field}`]);
n.value-- n.value--;
} }
async function customResetFunc() { async function customResetFunc() {
emit('prev') emit("prev");
} }
async function customSubmitFunc() { async function customSubmitFunc() {
try { try {
const values = await validate() const values = await validate();
const pointInfo = [] const pointInfo = [];
for (const key in values) { for (const key in values) {
if (key.startsWith('point')) { if (key.startsWith("point")) {
const point = values[key].split('|') const point = values[key].split("|");
const p = { const p = {
description: point[0], description: point[0],
pointId: point[1], pointId: point[1],
unit: point[2], unit: point[2],
Lower: point[3], Lower: point[3],
Upper: point[4], Upper: point[4],
} dead: true,
pointInfo.push(p) limit: false,
};
pointInfo.push(p);
} }
} }
const modelInfo = toRaw(props.beforeData) const modelInfo = toRaw(props.beforeData);
modelInfo.pointInfo = pointInfo modelInfo.pointInfo = pointInfo;
const modelId = await modelSaveApi(modelInfo) const modelId = await modelSaveApi(modelInfo);
setProps({ setProps({
submitButtonOptions: { submitButtonOptions: {
loading: true, loading: true,
}, },
}) });
setTimeout(() => { setTimeout(() => {
setProps({ setProps({
submitButtonOptions: { submitButtonOptions: {
loading: false, loading: false,
}, },
}) });
emit('next', modelId) emit("next", modelId);
}, 1500) }, 1500);
} } catch (error) {
catch (error) { console.error(error);
console.error(error)
} }
} }
const keyword = ref<string>('') const keyword = ref<string>("");
const searchParams = computed<Recordable>(() => { const searchParams = computed<Recordable>(() => {
return { keyword: unref(keyword) } return { keyword: unref(keyword) };
}) });
function onSearch(value: string) { function onSearch(value: string) {
keyword.value = value keyword.value = value;
} }
async function searchPoint(params) { async function searchPoint(params) {
if (params.keyword) { if (params.keyword) {
const data = await pointListApi(params) const data = await pointListApi(params);
return data return data;
} }
} }
@ -147,11 +151,11 @@ export default defineComponent({
searchParams, searchParams,
searchPoint, searchPoint,
handleReset: () => { handleReset: () => {
keyword.value = '' keyword.value = "";
}, },
} };
}, },
}) });
</script> </script>
<template> <template>
@ -190,20 +194,16 @@ export default defineComponent({
/> />
</template> </template>
<template #add="{ field }"> <template #add="{ field }">
<Button v-if="Number(field) === 0" @click="add"> <Button v-if="Number(field) === 0" @click="add"> + </Button>
+ <Button v-if="field > 0" @click="del(field)"> - </Button>
</Button>
<Button v-if="field > 0" @click="del(field)">
-
</Button>
</template> </template>
</BasicForm> </BasicForm>
</div> </div>
</template> </template>
<style lang="less" scoped> <style lang="less" scoped>
.step3 { .step3 {
width: 450px; width: 450px;
margin: 0 auto; margin: 0 auto;
} }
</style> </style>

355
src/views/model/train/index.vue

@ -3,7 +3,7 @@ import type { ComponentPublicInstance } from 'vue'
import type { Dayjs } from 'dayjs' import type { Dayjs } from 'dayjs'
import { debounce } from 'lodash-es' import { debounce } from 'lodash-es'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { computed, defineComponent, onMounted, ref, watch } from 'vue' import { computed, defineComponent, onMounted, ref, toRaw, watch } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { import {
Button, Button,
@ -17,17 +17,23 @@ import {
InputNumber, InputNumber,
Modal, Modal,
RangePicker, RangePicker,
Spin,
Steps, Steps,
Tabs, Tabs,
} from 'ant-design-vue' } from 'ant-design-vue'
import VueECharts from 'vue-echarts' import VueECharts from 'vue-echarts'
import { func } from 'vue-types'
import { pointTableSchema, sampleInfoTableSchema } from './data' import { pointTableSchema, sampleInfoTableSchema } from './data'
import { BasicTable, useTable } from '@/components/Table' import { BasicTable, useTable } from '@/components/Table'
import { PageWrapper } from '@/components/Page' import { PageWrapper } from '@/components/Page'
import { modelInfoApi, trainModelApi, updateModelInfo } from '@/api/alert/model/models' import {
modelInfoApi,
testModelApi,
trainModelApi,
updateModelInfo,
} from '@/api/alert/model/models'
import { getExaHistorys } from '@/api/alert/exa/index' import { getExaHistorys } from '@/api/alert/exa/index'
import { useECharts } from '@/hooks/web/useECharts' import { useECharts } from '@/hooks/web/useECharts'
import { useMessage } from '@/hooks/web/useMessage'
export default defineComponent({ export default defineComponent({
components: { components: {
@ -50,13 +56,15 @@ export default defineComponent({
ACheckbox: Checkbox, ACheckbox: Checkbox,
AInputNumber: InputNumber, AInputNumber: InputNumber,
AButton: Button, AButton: Button,
ASpin: Spin,
}, },
setup() { setup() {
const { createMessage } = useMessage()
const route = useRoute() const route = useRoute()
const id = route.params.id const id = route.params.id
const model = ref(null) const model = ref(null)
const brushActivated = ref<Set<number>>(new Set()) const brushActivated = ref<Set<number>>(new Set())
const spinning = ref(false)
const fetchModelInfo = async () => { const fetchModelInfo = async () => {
const modelInfo = await modelInfoApi(id) const modelInfo = await modelInfoApi(id)
model.value = modelInfo model.value = modelInfo
@ -83,7 +91,10 @@ export default defineComponent({
type RangeValue = [Dayjs, Dayjs] type RangeValue = [Dayjs, Dayjs]
const currentDate: Dayjs = dayjs() const currentDate: Dayjs = dayjs()
const lastMonthDate: Dayjs = currentDate.subtract(1, 'day') const lastMonthDate: Dayjs = currentDate.subtract(1, 'day')
const rangeValue: RangeValue = [dayjs('2023-10-28 00:00:00'), dayjs('2023-10-28 23:59:59')] const rangeValue: RangeValue = [
dayjs('2025-2-24 00:00:00'),
dayjs('2025-2-24 23:59:59'),
]
const historyTime = ref<RangeValue>(rangeValue) const historyTime = ref<RangeValue>(rangeValue)
const historyList = ref<any[]>([]) const historyList = ref<any[]>([])
const echartsRefs = ref<any[]>([]) const echartsRefs = ref<any[]>([])
@ -91,33 +102,105 @@ export default defineComponent({
async function getHistory() { async function getHistory() {
if (!historyTime.value) if (!historyTime.value)
return return
spinning.value = true
if (model.value.para) {
getTestData()
}
else {
const params = {
startTime: historyTime.value[0].format('YYYY-MM-DD HH:mm:ss'),
endTime: historyTime.value[1].format('YYYY-MM-DD HH:mm:ss'),
itemName: model.value?.pointInfo
.map(item => item.pointId)
.join(','),
interval: model.value.sampling,
}
console.log(params)
const history = await getExaHistorys(params)
historyList.value = history.map((item, index) => {
const point = model.value?.pointInfo[index]
return {
data: [item],
name: `${index + 1}.${point?.description}(${point?.pointId})`,
}
})
echartsRefs.value = Array.from({ length: historyList.value.length })
brushActivated.value = new Set()
}
spinning.value = false
}
async function getTestData() {
const params = { const params = {
startTime: historyTime.value[0].format('YYYY-MM-DD HH:mm:ss'), Model_id: 118,
endTime: historyTime.value[1].format('YYYY-MM-DD HH:mm:ss'), version: model.value?.Cur_Version ? model.value?.Cur_Version : 'v-test',
itemName: model.value?.pointInfo.map(item => item.pointId).join(','), Test_Data: {
time: historyTime.value
.map(t => dayjs(t).format('YYYY-MM-DD HH:mm:ss'))
.join(','),
points: model.value.pointInfo.map(t => t.pointId).join(','),
interval: model.value.sampling * 1000,
},
} }
console.log(params) const result = await testModelApi(params)
const history = await getExaHistorys(params) const sampleData = result.sampleData
historyList.value = history.map((item, index) => { const reconData = result.reconData
const xData = generateTimeList(
historyTime.value,
model.value.sampling * 1000,
)
historyList.value = sampleData.map((item, index) => {
const point = model.value?.pointInfo[index] const point = model.value?.pointInfo[index]
return { return {
data: item, data: [
name: `${index}.${point?.description}(${point?.pointId})`, item.map((t, i) => {
return [xData[i], t]
}),
reconData[index].map((t, i) => {
return [xData[i], t]
}),
],
name: `${index + 1}.${point?.description}(${point?.pointId})`,
} }
}) })
echartsRefs.value = Array.from({ length: historyList.value.length }) console.log(historyList.value)
console.log('echartsRefs', echartsRefs.value) }
brushActivated.value = new Set()
function generateTimeList(time: RangeValue, intervalMs: number) {
const [t1, t2] = time
const count = Math.floor(t2.diff(t1, 'millisecond') / intervalMs) + 1
return Array.from({ length: count }, (_, i) =>
t1.add(i * intervalMs, 'millisecond').valueOf())
} }
function getOption(item: any) { function getOption(item: any) {
console.log('getOption', item) const name = ['测量值', '模型值', '']
return { const color = ['blue', '#ff6f00', 'red']
const yIndex = [0, 0, 1]
const option = {
xAxis: { xAxis: {
type: 'time', type: 'time',
axisLabel: {
formatter(value) {
const date = new Date(value)
return date.toLocaleString()
},
},
}, },
yAxis: { type: 'value' }, yAxis: [{ type: 'value' }, { type: 'value', max: 10, show: false }],
series: [{ data: item.data, type: 'line', smooth: true, symbol: 'none' }], series: item.data.map((item, index) => {
return {
data: item,
type: 'line',
smooth: true,
symbol: 'none',
name: name[index],
color: color[index],
yAxisIndex: yIndex[index],
}
}),
legend: {},
dataZoom: [{}], dataZoom: [{}],
brush: { brush: {
toolbox: ['lineX'], toolbox: ['lineX'],
@ -133,6 +216,8 @@ export default defineComponent({
}, },
], ],
} }
console.log('option', option)
return option
} }
function setChartRef( function setChartRef(
@ -161,7 +246,6 @@ export default defineComponent({
const chart = echartsRefs.value[index] const chart = echartsRefs.value[index]
if (!chart) if (!chart)
return return
console.log('chart', index, chart)
chart.dispatchAction({ chart.dispatchAction({
type: 'takeGlobalCursor', type: 'takeGlobalCursor',
key: 'brush', key: 'brush',
@ -173,7 +257,10 @@ export default defineComponent({
const areas = (model.value?.trainTime || []).map(row => ({ const areas = (model.value?.trainTime || []).map(row => ({
brushType: 'lineX', brushType: 'lineX',
xAxisIndex: 0, xAxisIndex: 0,
coordRange: [dayjs(row.st).valueOf(), dayjs(row.et).valueOf()], coordRange: [
dayjs(row.st).format('YYYY-MM-DD HH:mm:ss'),
dayjs(row.et).format('YYYY-MM-DD HH:mm:ss'),
],
})) }))
chart.dispatchAction({ chart.dispatchAction({
type: 'brush', type: 'brush',
@ -191,7 +278,6 @@ export default defineComponent({
isInitBrush.value = false isInitBrush.value = false
return return
} }
console.log('brush selected:', params.batch)
const selected = params.batch[0].selected const selected = params.batch[0].selected
if (selected.length > 0) { if (selected.length > 0) {
const areas = mergeAreas(params.batch[0].areas).map(area => ({ const areas = mergeAreas(params.batch[0].areas).map(area => ({
@ -201,6 +287,7 @@ export default defineComponent({
})) }))
const trainTime = areas.map((area) => { const trainTime = areas.map((area) => {
const [st, et] = area.coordRange const [st, et] = area.coordRange
console.log('Selected area:', { st, et }, area)
return { return {
st: dayjs(st).format('YYYY-MM-DD HH:mm:ss'), st: dayjs(st).format('YYYY-MM-DD HH:mm:ss'),
et: dayjs(et).format('YYYY-MM-DD HH:mm:ss'), et: dayjs(et).format('YYYY-MM-DD HH:mm:ss'),
@ -220,6 +307,7 @@ export default defineComponent({
isInitBrush.value = true isInitBrush.value = true
} }
}) })
updateModelInfoDebounced()
} }
}, 300) }, 300)
@ -257,23 +345,12 @@ export default defineComponent({
} }
// //
const updateModelInfoDebounced = debounce((val) => { const updateModelInfoDebounced = debounce(() => {
const val = toRaw(model.value)
if (val && val.id) if (val && val.id)
updateModelInfo(val) updateModelInfo(val)
}, 500) }, 500)
// model
watch(
model,
(newVal, oldVal) => {
console.log('model changed:', newVal, oldVal)
if (oldVal === null)
return
updateModelInfoDebounced(newVal)
},
{ deep: true },
)
function handleDeleteTrainTime(index: number) { function handleDeleteTrainTime(index: number) {
if (!model.value?.trainTime) if (!model.value?.trainTime)
return return
@ -297,6 +374,12 @@ export default defineComponent({
isInitBrush.value = true isInitBrush.value = true
} }
}) })
updateModelInfoDebounced()
}
async function clearModel() {
model.value.para = null
updateModelInfoDebounced()
await getHistory()
} }
async function trainModel() { async function trainModel() {
@ -311,24 +394,46 @@ export default defineComponent({
return return
} }
const params = { const params = {
condition: '1==1', conditon: modelInfo.alarmmodelset?.alarmcondition || '1==1',
Hyper_para: { Hyper_para: {
percent: modelInfo.rate, percent: modelInfo.rate,
}, },
Train_Data: { Train_Data: {
points: pointInfo.map(item => item.pointId).join(','), points: pointInfo.map(item => item.pointId).join(','),
dead: pointInfo.map(item => item.dead ? '1' : '0').join(','), dead: pointInfo.map(item => (item.dead ? '1' : '0')).join(','),
limit: pointInfo.map(item => item.limit ? '1' : '0').join(','), limit: pointInfo.map(item => (item.limit ? '1' : '0')).join(','),
uplow: pointInfo.map(item => `${item.Upper},${item.Lower}`).join(';'), uplow: pointInfo
.map(
item =>
`${item.Upper ? item.Upper : null},${
item.Lower ? item.Lower : null
}`,
)
.join(';'),
interval: modelInfo.sampling * 1000, interval: modelInfo.sampling * 1000,
time: modelInfo.trainTime.map(item => `${item.st},${item.et}`).join(';'), time: modelInfo.trainTime
.map(item => `${item.st},${item.et}`)
.join(';'),
}, },
type: 'PCA', type: 'PCA',
smote_config: '[]', smote_config: [],
smote: true, smote: true,
} }
const response = await trainModelApi(params) spinning.value = true
console.log('模型训练结果:', response) try {
const response = await trainModelApi(params)
model.value.para = response
model.value.principal = response.Model_info.K
updateModelInfoDebounced()
getTestData()
createMessage.success('模型训练成功')
}
catch (error) {
console.error('模型训练失败:', error)
createMessage.error('模型训练失败')
}
spinning.value = false
} }
const editForm = ref({ const editForm = ref({
index: -1, index: -1,
@ -336,14 +441,13 @@ export default defineComponent({
Lower: '', Lower: '',
lowerBound: '', lowerBound: '',
upperBound: '', upperBound: '',
dead: false, dead: true,
limit: true, limit: false,
}) })
const openEditPointModal = ref<boolean>(false) const openEditPointModal = ref<boolean>(false)
let pointEditRecord = null let pointEditRecord = null
function editPoint() { function editPoint() {
// //
console.log('编辑点')
model.value.pointInfo[editForm.value.index] = { model.value.pointInfo[editForm.value.index] = {
...model.value.pointInfo[editForm.value.index], ...model.value.pointInfo[editForm.value.index],
Upper: editForm.value.Upper, Upper: editForm.value.Upper,
@ -353,6 +457,7 @@ export default defineComponent({
dead: editForm.value.dead, dead: editForm.value.dead,
limit: editForm.value.limit, limit: editForm.value.limit,
} }
updateModelInfoDebounced()
pointEditRecord.Upper = editForm.value.Upper pointEditRecord.Upper = editForm.value.Upper
pointEditRecord.Lower = editForm.value.Lower pointEditRecord.Lower = editForm.value.Lower
pointEditRecord.lowerBound = editForm.value.lowerBound pointEditRecord.lowerBound = editForm.value.lowerBound
@ -377,7 +482,7 @@ export default defineComponent({
} }
const mode = ref({ const mode = ref({
alarmcondition: '1=1', alarmcondition: '1==1',
alarmname: '全工况运行', alarmname: '全工况运行',
}) })
const openEditModeModal = ref<boolean>(false) const openEditModeModal = ref<boolean>(false)
@ -385,7 +490,7 @@ export default defineComponent({
function openEditMode() { function openEditMode() {
openEditModeModal.value = true openEditModeModal.value = true
mode.value = { mode.value = {
alarmcondition: model.value?.alarmmodelset?.alarmcondition || '1=1', alarmcondition: model.value?.alarmmodelset?.alarmcondition || '1==1',
alarmname: model.value?.alarmmodelset?.alarmname || '全工况运行', alarmname: model.value?.alarmmodelset?.alarmname || '全工况运行',
} }
} }
@ -394,10 +499,11 @@ export default defineComponent({
} }
function handleEditMode() { function handleEditMode() {
// //
console.log('编辑模式')
model.value.alarmmodelset = mode.value model.value.alarmmodelset = mode.value
updateModelInfoDebounced()
closeEditMode() closeEditMode()
} }
return { return {
pointTable, pointTable,
model, model,
@ -423,6 +529,8 @@ export default defineComponent({
closeEditMode, closeEditMode,
handleEditMode, handleEditMode,
mode, mode,
spinning,
clearModel,
} }
}, },
}) })
@ -443,10 +551,10 @@ export default defineComponent({
{{ model?.name }} {{ model?.name }}
</a-descriptions-item> </a-descriptions-item>
<a-descriptions-item label="描述"> <a-descriptions-item label="描述">
{{ model?.description || '暂无描述' }} {{ model?.description || "暂无描述" }}
</a-descriptions-item> </a-descriptions-item>
<a-descriptions-item label="版本"> <a-descriptions-item label="版本">
{{ model?.Cur_Version || 'v-test' }} {{ model?.Cur_Version || "v-test" }}
</a-descriptions-item> </a-descriptions-item>
<a-descriptions-item label="评估报告"> <a-descriptions-item label="评估报告">
暂无 暂无
@ -458,22 +566,22 @@ export default defineComponent({
{{ model?.creatTime }} {{ model?.creatTime }}
</a-descriptions-item> </a-descriptions-item>
<a-descriptions-item label="最近修改人"> <a-descriptions-item label="最近修改人">
{{ model?.Modifier || '暂无' }} {{ model?.Modifier || "暂无" }}
</a-descriptions-item> </a-descriptions-item>
<a-descriptions-item label="最近修改时间"> <a-descriptions-item label="最近修改时间">
{{ model?.modifiedTime || '暂无' }} {{ model?.modifiedTime || "暂无" }}
</a-descriptions-item> </a-descriptions-item>
</a-descriptions> </a-descriptions>
<a-divider /> <a-divider />
<a-descriptions size="small" :column="4" bordered> <a-descriptions size="small" :column="4" bordered>
<a-descriptions-item label="算法"> <a-descriptions-item label="算法">
{{ model?.algorithm || 'PCA' }} {{ model?.algorithm || "PCA" }}
</a-descriptions-item> </a-descriptions-item>
<a-descriptions-item label="训练采样间隔"> <a-descriptions-item label="训练采样间隔">
{{ model?.sampling }} {{ model?.sampling }}
</a-descriptions-item> </a-descriptions-item>
<a-descriptions-item label="参数个数"> <a-descriptions-item label="参数个数">
{{ model?.pointInfo.length || '暂无' }} {{ model?.pointInfo.length || "暂无" }}
</a-descriptions-item> </a-descriptions-item>
<a-descriptions-item label="最小主元贡献率"> <a-descriptions-item label="最小主元贡献率">
{{ model?.rate }} {{ model?.rate }}
@ -485,14 +593,25 @@ export default defineComponent({
{{ model?.precision }} {{ model?.precision }}
</a-descriptions-item> </a-descriptions-item>
<a-descriptions-item label="训练总时长(h)"> <a-descriptions-item label="训练总时长(h)">
{{ (model?.trainTime.reduce((total, item) => total + item.duration, 0) / 3600).toFixed(2) || '暂无' }} {{
(
model?.trainTime.reduce(
(total, item) => total + item.duration,
0,
) / 3600
).toFixed(2) || "暂无"
}}
</a-descriptions-item> </a-descriptions-item>
<a-descriptions-item label="有效样本数"> <a-descriptions-item label="有效样本数">
{{ model?.principal }} {{ model?.principal }}
</a-descriptions-item> </a-descriptions-item>
</a-descriptions> </a-descriptions>
</a-card> </a-card>
<a-card title="模式" :bordered="false" style="margin-top: 16px;margin-bottom: -20px;"> <a-card
title="模式"
:bordered="false"
style="margin-top: 16px; margin-bottom: -20px"
>
<a-button size="large" @click="openEditMode"> <a-button size="large" @click="openEditMode">
{{ model?.alarmmodelset.alarmname }} {{ model?.alarmmodelset.alarmname }}
</a-button> </a-button>
@ -503,7 +622,11 @@ export default defineComponent({
<a-tab-pane key="1" tab="训练采样时间"> <a-tab-pane key="1" tab="训练采样时间">
<BasicTable @register="trainTimeTable"> <BasicTable @register="trainTimeTable">
<template #action="{ record, index }"> <template #action="{ record, index }">
<a-button type="link" danger @click="handleDeleteTrainTime(index)"> <a-button
type="link"
danger
@click="handleDeleteTrainTime(index)"
>
删除 删除
</a-button> </a-button>
</template> </template>
@ -522,46 +645,91 @@ export default defineComponent({
</a-card> </a-card>
<a-card title="智能训练" :bordered="false"> <a-card title="智能训练" :bordered="false">
<div style="display: flex; align-items: center;"> <div style="display: flex; align-items: center">
<a-form layout="inline" style="flex: 1;"> <a-form layout="inline" style="flex: 1">
<a-form-item label="模型预览时间范围"> <a-form-item label="模型预览时间范围">
<a-range-picker v-model:value="historyTime" show-time @change="getHistory" /> <a-range-picker
v-model:value="historyTime"
show-time
@change="getHistory"
/>
</a-form-item> </a-form-item>
</a-form> </a-form>
<a-button type="primary" style="margin-left: auto;" @click="trainModel"> <a-button
type="primary"
style="margin-left: auto"
@click="trainModel"
>
模型训练 模型训练
</a-button> </a-button>
<a-button
type="primary"
style="margin-left: 10px"
@click="clearModel"
>
清除训练结果
</a-button>
</div> </div>
<a-divider /> <a-divider />
<div v-for="(item, index) in historyList" :key="index" class="echart-box"> <a-spin :spinning="spinning" size="large">
<a-card :bordered="false" style="margin-bottom: 16px;"> <div
<template #title> v-for="(item, index) in historyList"
<span style="font-size: 20px;">{{ item.name }}</span> :key="index"
</template> class="echart-box"
<VueECharts style="width: 100%"
:ref="(el) => setEchartsRef(el, index)" :option="getOption(item)" autoresize >
style="width: 100%; height: 300px" @finished="() => onChartFinished(index)" <a-card :bordered="false" style="margin-bottom: 16px">
@brush-selected="onBrushSelected" <template #title>
/> <span style="font-size: 20px">{{ item.name }}</span>
</a-card> </template>
</div> <VueECharts
:ref="(el) => setEchartsRef(el, index)"
:option="getOption(item)"
autoresize
style="width: 100%; height: 200px"
@finished="() => onChartFinished(index)"
@brush-selected="onBrushSelected"
/>
</a-card>
</div>
</a-spin>
</a-card> </a-card>
</div> </div>
<a-modal v-model:open="openEditPointModal" title="更改上下限" @ok="editPoint"> <a-modal
<a-form :model="editForm" :label-col="{ span: 7 }" :wrapper-col="{ span: 15 }"> v-model:open="openEditPointModal"
title="更改上下限"
@ok="editPoint"
>
<a-form
:model="editForm"
:label-col="{ span: 7 }"
:wrapper-col="{ span: 15 }"
>
<a-form-item label="上限"> <a-form-item label="上限">
<a-input-number v-model:value="editForm.Upper" placeholder="请输入上限" /> <a-input-number
v-model:value="editForm.Upper"
placeholder="请输入上限"
/>
</a-form-item> </a-form-item>
<a-form-item label="下限"> <a-form-item label="下限">
<a-input-number v-model:value="editForm.Lower" placeholder="请输入下限" /> <a-input-number
v-model:value="editForm.Lower"
placeholder="请输入下限"
/>
</a-form-item> </a-form-item>
<a-form-item label="残差上限"> <a-form-item label="残差上限">
<a-input-number v-model:value="editForm.upperBound" placeholder="请输入残差上限" /> <a-input-number
v-model:value="editForm.upperBound"
placeholder="请输入残差上限"
/>
</a-form-item> </a-form-item>
<a-form-item label="残差下限"> <a-form-item label="残差下限">
<a-input-number v-model:value="editForm.lowerBound" placeholder="请输入残差下限" /> <a-input-number
v-model:value="editForm.lowerBound"
placeholder="请输入残差下限"
/>
</a-form-item> </a-form-item>
<a-form-item label="清洗方式" style="margin-top: 16px;"> <a-form-item label="清洗方式" style="margin-top: 16px">
<a-checkbox v-model:checked="editForm.dead"> <a-checkbox v-model:checked="editForm.dead">
死区清洗 死区清洗
</a-checkbox> </a-checkbox>
@ -571,13 +739,28 @@ export default defineComponent({
</a-form-item> </a-form-item>
</a-form> </a-form>
</a-modal> </a-modal>
<a-modal v-model:open="openEditModeModal" title="编辑模式" @ok="handleEditMode" @cancel="closeEditMode"> <a-modal
<a-form :model="mode" :label-col="{ span: 7 }" :wrapper-col="{ span: 15 }"> v-model:open="openEditModeModal"
title="编辑模式"
@ok="handleEditMode"
@cancel="closeEditMode"
>
<a-form
:model="mode"
:label-col="{ span: 7 }"
:wrapper-col="{ span: 15 }"
>
<a-form-item label="模式名称"> <a-form-item label="模式名称">
<a-input v-model:value="mode.alarmname" placeholder="请输入模式名称" /> <a-input
v-model:value="mode.alarmname"
placeholder="请输入模式名称"
/>
</a-form-item> </a-form-item>
<a-form-item label="报警条件"> <a-form-item label="报警条件">
<a-input v-model:value="mode.alarmcondition" placeholder="请输入报警条件" /> <a-input
v-model:value="mode.alarmcondition"
placeholder="请输入报警条件"
/>
</a-form-item> </a-form-item>
</a-form> </a-form>
</a-modal> </a-modal>

Loading…
Cancel
Save