|
|
|
@ -3,12 +3,13 @@ import type { ComponentPublicInstance } from 'vue' |
|
|
|
import type { Dayjs } from 'dayjs' |
|
|
|
import { debounce } from 'lodash-es' |
|
|
|
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 { |
|
|
|
Button, |
|
|
|
Card, |
|
|
|
Checkbox, |
|
|
|
Col, |
|
|
|
Descriptions, |
|
|
|
Divider, |
|
|
|
Form, |
|
|
|
@ -17,17 +18,27 @@ import { |
|
|
|
InputNumber, |
|
|
|
Modal, |
|
|
|
RangePicker, |
|
|
|
Row, |
|
|
|
Spin, |
|
|
|
Steps, |
|
|
|
Tabs, |
|
|
|
Transfer, |
|
|
|
} from 'ant-design-vue' |
|
|
|
import VueECharts from 'vue-echarts' |
|
|
|
import { func } from 'vue-types' |
|
|
|
import { pointTableSchema, sampleInfoTableSchema } from './data' |
|
|
|
import { BasicTable, useTable } from '@/components/Table' |
|
|
|
import { PageWrapper } from '@/components/Page' |
|
|
|
import { modelInfoApi, trainModelApi, updateModelInfo } from '@/api/alert/model/models' |
|
|
|
import { |
|
|
|
bottomModelApi, |
|
|
|
modelInfoApi, |
|
|
|
testModelApi, |
|
|
|
trainModelApi, |
|
|
|
updateModelInfo, |
|
|
|
} from '@/api/alert/model/models' |
|
|
|
import { getExaHistorys } from '@/api/alert/exa/index' |
|
|
|
import { useECharts } from '@/hooks/web/useECharts' |
|
|
|
import { useMessage } from '@/hooks/web/useMessage' |
|
|
|
import { pointListApi } from '@/api/alert/model/select' |
|
|
|
|
|
|
|
export default defineComponent({ |
|
|
|
components: { |
|
|
|
@ -50,23 +61,30 @@ export default defineComponent({ |
|
|
|
ACheckbox: Checkbox, |
|
|
|
AInputNumber: InputNumber, |
|
|
|
AButton: Button, |
|
|
|
ASpin: Spin, |
|
|
|
ATransfer: Transfer, |
|
|
|
ARow: Row, |
|
|
|
ACol: Col, |
|
|
|
}, |
|
|
|
setup() { |
|
|
|
const { createMessage } = useMessage() |
|
|
|
const route = useRoute() |
|
|
|
const id = route.params.id |
|
|
|
const model = ref(null) |
|
|
|
const brushActivated = ref<Set<number>>(new Set()) |
|
|
|
|
|
|
|
const spinning = ref(false) |
|
|
|
let trainTimeCopy = '' |
|
|
|
const fetchModelInfo = async () => { |
|
|
|
const modelInfo = await modelInfoApi(id) |
|
|
|
model.value = modelInfo |
|
|
|
trainTimeCopy = JSON.stringify(model.value.trainTime) |
|
|
|
getHistory() |
|
|
|
} |
|
|
|
|
|
|
|
const pointData = computed(() => model.value?.pointInfo || []) |
|
|
|
const [pointTable] = useTable({ |
|
|
|
columns: pointTableSchema, |
|
|
|
pagination: false, |
|
|
|
pagination: true, |
|
|
|
dataSource: pointData, |
|
|
|
scroll: { y: 300 }, |
|
|
|
}) |
|
|
|
@ -74,7 +92,6 @@ export default defineComponent({ |
|
|
|
const trainTime = computed(() => model.value?.trainTime || []) |
|
|
|
const [trainTimeTable] = useTable({ |
|
|
|
columns: sampleInfoTableSchema, |
|
|
|
pagination: false, |
|
|
|
dataSource: trainTime, |
|
|
|
scroll: { y: 300 }, |
|
|
|
}) |
|
|
|
@ -83,7 +100,10 @@ export default defineComponent({ |
|
|
|
type RangeValue = [Dayjs, Dayjs] |
|
|
|
const currentDate: Dayjs = dayjs() |
|
|
|
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 = [ |
|
|
|
lastMonthDate, |
|
|
|
currentDate, |
|
|
|
] |
|
|
|
const historyTime = ref<RangeValue>(rangeValue) |
|
|
|
const historyList = ref<any[]>([]) |
|
|
|
const echartsRefs = ref<any[]>([]) |
|
|
|
@ -91,33 +111,103 @@ export default defineComponent({ |
|
|
|
async function getHistory() { |
|
|
|
if (!historyTime.value) |
|
|
|
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, |
|
|
|
} |
|
|
|
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 = { |
|
|
|
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(','), |
|
|
|
Model_id: 530, |
|
|
|
version: model.value?.Cur_Version ? model.value?.Cur_Version : 'v-test', |
|
|
|
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 history = await getExaHistorys(params) |
|
|
|
historyList.value = history.map((item, index) => { |
|
|
|
const result = await testModelApi(params) |
|
|
|
const sampleData = result.sampleData |
|
|
|
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] |
|
|
|
return { |
|
|
|
data: item, |
|
|
|
name: `${index}.${point?.description}(${point?.pointId})`, |
|
|
|
data: [ |
|
|
|
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('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) { |
|
|
|
console.log('getOption', item) |
|
|
|
return { |
|
|
|
const name = ['测量值', '模型值', ''] |
|
|
|
const color = ['blue', '#ff6f00', 'red'] |
|
|
|
const yIndex = [0, 0, 1] |
|
|
|
const option = { |
|
|
|
xAxis: { |
|
|
|
type: 'time', |
|
|
|
axisLabel: { |
|
|
|
formatter(value) { |
|
|
|
const date = new Date(value) |
|
|
|
return date.toLocaleString() |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
yAxis: { type: 'value' }, |
|
|
|
series: [{ data: item.data, type: 'line', smooth: true, symbol: 'none' }], |
|
|
|
yAxis: [{ type: 'value' }, { type: 'value', max: 10, show: false }], |
|
|
|
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: [{}], |
|
|
|
brush: { |
|
|
|
toolbox: ['lineX'], |
|
|
|
@ -133,6 +223,7 @@ export default defineComponent({ |
|
|
|
}, |
|
|
|
], |
|
|
|
} |
|
|
|
return option |
|
|
|
} |
|
|
|
|
|
|
|
function setChartRef( |
|
|
|
@ -161,7 +252,6 @@ export default defineComponent({ |
|
|
|
const chart = echartsRefs.value[index] |
|
|
|
if (!chart) |
|
|
|
return |
|
|
|
console.log('chart', index, chart) |
|
|
|
chart.dispatchAction({ |
|
|
|
type: 'takeGlobalCursor', |
|
|
|
key: 'brush', |
|
|
|
@ -173,7 +263,10 @@ export default defineComponent({ |
|
|
|
const areas = (model.value?.trainTime || []).map(row => ({ |
|
|
|
brushType: 'lineX', |
|
|
|
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({ |
|
|
|
type: 'brush', |
|
|
|
@ -191,7 +284,6 @@ export default defineComponent({ |
|
|
|
isInitBrush.value = false |
|
|
|
return |
|
|
|
} |
|
|
|
console.log('brush selected:', params.batch) |
|
|
|
const selected = params.batch[0].selected |
|
|
|
if (selected.length > 0) { |
|
|
|
const areas = mergeAreas(params.batch[0].areas).map(area => ({ |
|
|
|
@ -200,7 +292,10 @@ export default defineComponent({ |
|
|
|
coordRange: area.coordRange, |
|
|
|
})) |
|
|
|
const trainTime = areas.map((area) => { |
|
|
|
const [st, et] = area.coordRange |
|
|
|
const [stRaw, etRaw] = area.coordRange |
|
|
|
const st = typeof stRaw === 'string' ? dayjs(stRaw).valueOf() : stRaw |
|
|
|
const et = typeof etRaw === 'string' ? dayjs(etRaw).valueOf() : etRaw |
|
|
|
console.log('Selected area:', { st, et }, area) |
|
|
|
return { |
|
|
|
st: dayjs(st).format('YYYY-MM-DD HH:mm:ss'), |
|
|
|
et: dayjs(et).format('YYYY-MM-DD HH:mm:ss'), |
|
|
|
@ -210,7 +305,11 @@ export default defineComponent({ |
|
|
|
mode: '', // 有效样本数(如有数据可补充) |
|
|
|
} |
|
|
|
}) |
|
|
|
console.log('Selected train time:', trainTime) |
|
|
|
if (trainTimeCopy === JSON.stringify(trainTime)) |
|
|
|
return |
|
|
|
model.value.trainTime = trainTime |
|
|
|
trainTimeCopy = JSON.stringify(trainTime) |
|
|
|
echartsRefs.value.forEach((chart, index) => { |
|
|
|
if (chart) { |
|
|
|
chart.dispatchAction({ |
|
|
|
@ -220,6 +319,7 @@ export default defineComponent({ |
|
|
|
isInitBrush.value = true |
|
|
|
} |
|
|
|
}) |
|
|
|
updateModelInfoDebounced() |
|
|
|
} |
|
|
|
}, 300) |
|
|
|
|
|
|
|
@ -257,23 +357,12 @@ export default defineComponent({ |
|
|
|
} |
|
|
|
|
|
|
|
// 防抖更新 |
|
|
|
const updateModelInfoDebounced = debounce((val) => { |
|
|
|
const updateModelInfoDebounced = debounce(() => { |
|
|
|
const val = toRaw(model.value) |
|
|
|
if (val && val.id) |
|
|
|
updateModelInfo(val) |
|
|
|
}, 500) |
|
|
|
|
|
|
|
// 监听 model 变化 |
|
|
|
watch( |
|
|
|
model, |
|
|
|
(newVal, oldVal) => { |
|
|
|
console.log('model changed:', newVal, oldVal) |
|
|
|
if (oldVal === null) |
|
|
|
return |
|
|
|
updateModelInfoDebounced(newVal) |
|
|
|
}, |
|
|
|
{ deep: true }, |
|
|
|
) |
|
|
|
|
|
|
|
function handleDeleteTrainTime(index: number) { |
|
|
|
if (!model.value?.trainTime) |
|
|
|
return |
|
|
|
@ -297,6 +386,12 @@ export default defineComponent({ |
|
|
|
isInitBrush.value = true |
|
|
|
} |
|
|
|
}) |
|
|
|
updateModelInfoDebounced() |
|
|
|
} |
|
|
|
async function clearModel() { |
|
|
|
model.value.para = null |
|
|
|
updateModelInfoDebounced() |
|
|
|
await getHistory() |
|
|
|
} |
|
|
|
|
|
|
|
async function trainModel() { |
|
|
|
@ -311,24 +406,46 @@ export default defineComponent({ |
|
|
|
return |
|
|
|
} |
|
|
|
const params = { |
|
|
|
condition: '1==1', |
|
|
|
conditon: modelInfo.alarmmodelset?.alarmcondition || '1==1', |
|
|
|
Hyper_para: { |
|
|
|
percent: modelInfo.rate, |
|
|
|
}, |
|
|
|
Train_Data: { |
|
|
|
points: pointInfo.map(item => item.pointId).join(','), |
|
|
|
dead: pointInfo.map(item => item.dead ? '1' : '0').join(','), |
|
|
|
limit: pointInfo.map(item => item.limit ? '1' : '0').join(','), |
|
|
|
uplow: pointInfo.map(item => `${item.Upper},${item.Lower}`).join(';'), |
|
|
|
dead: pointInfo.map(item => (item.dead ? '1' : '0')).join(','), |
|
|
|
limit: pointInfo.map(item => (item.limit ? '1' : '0')).join(','), |
|
|
|
uplow: pointInfo |
|
|
|
.map( |
|
|
|
item => |
|
|
|
`${item.Upper ? item.Upper : null},${ |
|
|
|
item.Lower ? item.Lower : null |
|
|
|
}`, |
|
|
|
) |
|
|
|
.join(';'), |
|
|
|
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', |
|
|
|
smote_config: '[]', |
|
|
|
smote_config: [], |
|
|
|
smote: true, |
|
|
|
} |
|
|
|
const response = await trainModelApi(params) |
|
|
|
console.log('模型训练结果:', response) |
|
|
|
spinning.value = true |
|
|
|
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({ |
|
|
|
index: -1, |
|
|
|
@ -336,14 +453,13 @@ export default defineComponent({ |
|
|
|
Lower: '', |
|
|
|
lowerBound: '', |
|
|
|
upperBound: '', |
|
|
|
dead: false, |
|
|
|
limit: true, |
|
|
|
dead: true, |
|
|
|
limit: false, |
|
|
|
}) |
|
|
|
const openEditPointModal = ref<boolean>(false) |
|
|
|
let pointEditRecord = null |
|
|
|
function editPoint() { |
|
|
|
// 这里可以添加编辑点的逻辑 |
|
|
|
console.log('编辑点') |
|
|
|
model.value.pointInfo[editForm.value.index] = { |
|
|
|
...model.value.pointInfo[editForm.value.index], |
|
|
|
Upper: editForm.value.Upper, |
|
|
|
@ -353,6 +469,7 @@ export default defineComponent({ |
|
|
|
dead: editForm.value.dead, |
|
|
|
limit: editForm.value.limit, |
|
|
|
} |
|
|
|
updateModelInfoDebounced() |
|
|
|
pointEditRecord.Upper = editForm.value.Upper |
|
|
|
pointEditRecord.Lower = editForm.value.Lower |
|
|
|
pointEditRecord.lowerBound = editForm.value.lowerBound |
|
|
|
@ -363,21 +480,27 @@ export default defineComponent({ |
|
|
|
} |
|
|
|
|
|
|
|
function openPointModal(index, record) { |
|
|
|
// 当前页 index |
|
|
|
const pageIndex = index |
|
|
|
// 全局 index |
|
|
|
const globalIndex = model.value.pointInfo.findIndex( |
|
|
|
item => item.pointId === record.pointId, |
|
|
|
) |
|
|
|
openEditPointModal.value = true |
|
|
|
pointEditRecord = record |
|
|
|
editForm.value = { |
|
|
|
index, |
|
|
|
index: globalIndex, |
|
|
|
Upper: record?.Upper ?? '', |
|
|
|
Lower: record?.Lower ?? '', |
|
|
|
lowerBound: record?.lowerBound ?? '', |
|
|
|
upperBound: record?.upperBound ?? '', |
|
|
|
dead: record?.dead ?? false, |
|
|
|
limit: record?.limit ?? true, |
|
|
|
dead: !!record?.dead, |
|
|
|
limit: !!record?.limit, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const mode = ref({ |
|
|
|
alarmcondition: '1=1', |
|
|
|
alarmcondition: '1==1', |
|
|
|
alarmname: '全工况运行', |
|
|
|
}) |
|
|
|
const openEditModeModal = ref<boolean>(false) |
|
|
|
@ -385,7 +508,7 @@ export default defineComponent({ |
|
|
|
function openEditMode() { |
|
|
|
openEditModeModal.value = true |
|
|
|
mode.value = { |
|
|
|
alarmcondition: model.value?.alarmmodelset?.alarmcondition || '1=1', |
|
|
|
alarmcondition: model.value?.alarmmodelset?.alarmcondition || '1==1', |
|
|
|
alarmname: model.value?.alarmmodelset?.alarmname || '全工况运行', |
|
|
|
} |
|
|
|
} |
|
|
|
@ -394,10 +517,107 @@ export default defineComponent({ |
|
|
|
} |
|
|
|
function handleEditMode() { |
|
|
|
// 这里可以添加编辑模式的逻辑 |
|
|
|
console.log('编辑模式') |
|
|
|
model.value.alarmmodelset = mode.value |
|
|
|
updateModelInfoDebounced() |
|
|
|
closeEditMode() |
|
|
|
} |
|
|
|
|
|
|
|
const openEditModelModal = ref(false) |
|
|
|
const editModelForm = ref({ |
|
|
|
sampling: 0, |
|
|
|
rate: 0, |
|
|
|
selectedKeys: [], |
|
|
|
}) |
|
|
|
|
|
|
|
// 穿梭框数据源示例 |
|
|
|
const transferData = ref([]) // 穿梭框数据源 |
|
|
|
|
|
|
|
// 初始化时获取全部测点 |
|
|
|
async function fetchAllPoints(keyword = '') { |
|
|
|
// 这里调用你的后端接口,传递 keyword |
|
|
|
// const res = await fetchPointsApi({ keyword }) |
|
|
|
// 示例数据 |
|
|
|
const data = await pointListApi({ keyword }) |
|
|
|
console.log('Fetched points:', data) |
|
|
|
transferData.value = transferData.value.filter(item => editModelForm.value.selectedKeys.includes(item.key)) |
|
|
|
.concat(data.map(item => ({ |
|
|
|
key: item.id, |
|
|
|
title: item.name, |
|
|
|
}))) |
|
|
|
console.log('Transfer data:', transferData.value) |
|
|
|
} |
|
|
|
onMounted(() => { |
|
|
|
fetchAllPoints() |
|
|
|
}) |
|
|
|
|
|
|
|
function handleTransferSearch(dir, value) { |
|
|
|
if (dir === 'left') { |
|
|
|
// 左侧:后端接口查询 |
|
|
|
fetchAllPoints(value) |
|
|
|
} |
|
|
|
else { |
|
|
|
// 右侧:前端过滤 |
|
|
|
transferData.value = (model.value?.pointInfo || []) |
|
|
|
.filter(item => |
|
|
|
editModelForm.value.selectedKeys.includes(`${item.description}|${item.pointId}|${item.unit}|${item.Lower}|${item.Upper}`) |
|
|
|
&& (`${item.description || ''}(${item.pointId})`).includes(value), |
|
|
|
) |
|
|
|
.map(item => ({ |
|
|
|
key: `${item.description}|${item.pointId}|${item.unit}|${item.Lower}|${item.Upper}`, |
|
|
|
title: `${item.description || ''} (${item.pointId})`, |
|
|
|
})) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function openEditModel() { |
|
|
|
editModelForm.value.sampling = model.value?.sampling || 0 |
|
|
|
editModelForm.value.rate = model.value?.rate || 0 |
|
|
|
editModelForm.value.selectedKeys = (model.value?.pointInfo || []).map(item => `${item.description}|${item.pointId}|${item.unit}|${item.Lower}|${item.Upper}`) |
|
|
|
transferData.value = (model.value?.pointInfo || []).map(item => ({ |
|
|
|
key: `${item.description}|${item.pointId}|${item.unit}|${item.Lower}|${item.Upper}`, |
|
|
|
title: `${item.description || ''} (${item.pointId})`, |
|
|
|
})) |
|
|
|
console.log('transferData:', transferData.value) |
|
|
|
openEditModelModal.value = true |
|
|
|
} |
|
|
|
function handleEditModelOk() { |
|
|
|
model.value.sampling = editModelForm.value.sampling |
|
|
|
model.value.rate = editModelForm.value.rate |
|
|
|
model.value.pointInfo = editModelForm.value.selectedKeys.map((key) => { |
|
|
|
const [description, pointId, unit, Lower, Upper] = key.split('|') |
|
|
|
return { |
|
|
|
description, |
|
|
|
pointId, |
|
|
|
unit, |
|
|
|
Lower, |
|
|
|
Upper, |
|
|
|
dead: true, |
|
|
|
limit: false, |
|
|
|
} |
|
|
|
}) |
|
|
|
clearModel() |
|
|
|
openEditModelModal.value = false |
|
|
|
} |
|
|
|
function handleEditModelCancel() { |
|
|
|
openEditModelModal.value = false |
|
|
|
} |
|
|
|
|
|
|
|
async function bottomModel() { |
|
|
|
if (!model.value.para) { |
|
|
|
createMessage.error('模型未训练,无法下装') |
|
|
|
return |
|
|
|
} |
|
|
|
try { |
|
|
|
const response = await bottomModelApi(model.value.id) |
|
|
|
model.value = response |
|
|
|
createMessage.success('模型下装成功') |
|
|
|
} |
|
|
|
catch (error) { |
|
|
|
console.error('底层模型获取失败:', error) |
|
|
|
createMessage.error('底层模型获取失败') |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return { |
|
|
|
pointTable, |
|
|
|
model, |
|
|
|
@ -423,6 +643,16 @@ export default defineComponent({ |
|
|
|
closeEditMode, |
|
|
|
handleEditMode, |
|
|
|
mode, |
|
|
|
spinning, |
|
|
|
clearModel, |
|
|
|
openEditModelModal, |
|
|
|
editModelForm, |
|
|
|
transferData, |
|
|
|
handleTransferSearch, |
|
|
|
openEditModel, |
|
|
|
handleEditModelOk, |
|
|
|
handleEditModelCancel, |
|
|
|
bottomModel, |
|
|
|
} |
|
|
|
}, |
|
|
|
}) |
|
|
|
@ -432,21 +662,15 @@ export default defineComponent({ |
|
|
|
<PageWrapper content-background> |
|
|
|
<div> |
|
|
|
<a-card title="模型信息" :bordered="false"> |
|
|
|
<template #extra> |
|
|
|
<a-button> 下装 </a-button> |
|
|
|
<a-button type="primary" style="margin-left: 6px"> |
|
|
|
修改模型 |
|
|
|
</a-button> |
|
|
|
</template> |
|
|
|
<a-descriptions size="small" :column="4" bordered> |
|
|
|
<a-descriptions-item label="模型名称"> |
|
|
|
{{ model?.name }} |
|
|
|
</a-descriptions-item> |
|
|
|
<a-descriptions-item label="描述"> |
|
|
|
{{ model?.description || '暂无描述' }} |
|
|
|
{{ model?.description || "暂无描述" }} |
|
|
|
</a-descriptions-item> |
|
|
|
<a-descriptions-item label="版本"> |
|
|
|
{{ model?.Cur_Version || 'v-test' }} |
|
|
|
{{ model?.Cur_Version || "v-test" }} |
|
|
|
</a-descriptions-item> |
|
|
|
<a-descriptions-item label="评估报告"> |
|
|
|
暂无 |
|
|
|
@ -458,22 +682,22 @@ export default defineComponent({ |
|
|
|
{{ model?.creatTime }} |
|
|
|
</a-descriptions-item> |
|
|
|
<a-descriptions-item label="最近修改人"> |
|
|
|
{{ model?.Modifier || '暂无' }} |
|
|
|
{{ model?.Modifier || "暂无" }} |
|
|
|
</a-descriptions-item> |
|
|
|
<a-descriptions-item label="最近修改时间"> |
|
|
|
{{ model?.modifiedTime || '暂无' }} |
|
|
|
{{ model?.modifiedTime || "暂无" }} |
|
|
|
</a-descriptions-item> |
|
|
|
</a-descriptions> |
|
|
|
<a-divider /> |
|
|
|
<a-descriptions size="small" :column="4" bordered> |
|
|
|
<a-descriptions-item label="算法"> |
|
|
|
{{ model?.algorithm || 'PCA' }} |
|
|
|
{{ model?.algorithm || "PCA" }} |
|
|
|
</a-descriptions-item> |
|
|
|
<a-descriptions-item label="训练采样间隔"> |
|
|
|
{{ model?.sampling }} |
|
|
|
</a-descriptions-item> |
|
|
|
<a-descriptions-item label="参数个数"> |
|
|
|
{{ model?.pointInfo.length || '暂无' }} |
|
|
|
{{ model?.pointInfo.length || "暂无" }} |
|
|
|
</a-descriptions-item> |
|
|
|
<a-descriptions-item label="最小主元贡献率"> |
|
|
|
{{ model?.rate }} |
|
|
|
@ -485,14 +709,25 @@ export default defineComponent({ |
|
|
|
{{ model?.precision }} |
|
|
|
</a-descriptions-item> |
|
|
|
<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 label="有效样本数"> |
|
|
|
{{ model?.principal }} |
|
|
|
</a-descriptions-item> |
|
|
|
</a-descriptions> |
|
|
|
</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"> |
|
|
|
{{ model?.alarmmodelset.alarmname }} |
|
|
|
</a-button> |
|
|
|
@ -503,7 +738,11 @@ export default defineComponent({ |
|
|
|
<a-tab-pane key="1" tab="训练采样时间"> |
|
|
|
<BasicTable @register="trainTimeTable"> |
|
|
|
<template #action="{ record, index }"> |
|
|
|
<a-button type="link" danger @click="handleDeleteTrainTime(index)"> |
|
|
|
<a-button |
|
|
|
type="link" |
|
|
|
danger |
|
|
|
@click="handleDeleteTrainTime(index)" |
|
|
|
> |
|
|
|
删除 |
|
|
|
</a-button> |
|
|
|
</template> |
|
|
|
@ -522,46 +761,101 @@ export default defineComponent({ |
|
|
|
</a-card> |
|
|
|
|
|
|
|
<a-card title="智能训练" :bordered="false"> |
|
|
|
<div style="display: flex; align-items: center;"> |
|
|
|
<a-form layout="inline" style="flex: 1;"> |
|
|
|
<div style="display: flex; align-items: center"> |
|
|
|
<a-form layout="inline" style="flex: 1"> |
|
|
|
<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> |
|
|
|
<a-button type="primary" style="margin-left: auto;" @click="trainModel"> |
|
|
|
<a-button |
|
|
|
type="primary" |
|
|
|
style="margin-left: auto" |
|
|
|
@click="trainModel" |
|
|
|
> |
|
|
|
模型训练 |
|
|
|
</a-button> |
|
|
|
<a-button |
|
|
|
type="primary" |
|
|
|
style="margin-left: 10px" |
|
|
|
@click="clearModel" |
|
|
|
> |
|
|
|
清除训练结果 |
|
|
|
</a-button> |
|
|
|
<a-button type="primary" style="margin-left: 6px" @click="openEditModel"> |
|
|
|
修改模型 |
|
|
|
</a-button> |
|
|
|
<a-button |
|
|
|
danger |
|
|
|
style="margin-left: 10px" |
|
|
|
@click="bottomModel" |
|
|
|
> |
|
|
|
下装 |
|
|
|
</a-button> |
|
|
|
</div> |
|
|
|
<a-divider /> |
|
|
|
<div v-for="(item, index) in historyList" :key="index" class="echart-box"> |
|
|
|
<a-card :bordered="false" style="margin-bottom: 16px;"> |
|
|
|
<template #title> |
|
|
|
<span style="font-size: 20px;">{{ item.name }}</span> |
|
|
|
</template> |
|
|
|
<VueECharts |
|
|
|
:ref="(el) => setEchartsRef(el, index)" :option="getOption(item)" autoresize |
|
|
|
style="width: 100%; height: 300px" @finished="() => onChartFinished(index)" |
|
|
|
@brush-selected="onBrushSelected" |
|
|
|
/> |
|
|
|
</a-card> |
|
|
|
</div> |
|
|
|
<a-spin :spinning="spinning" size="large"> |
|
|
|
<div |
|
|
|
v-for="(item, index) in historyList" |
|
|
|
:key="index" |
|
|
|
class="echart-box" |
|
|
|
style="width: 100%" |
|
|
|
> |
|
|
|
<a-card :bordered="false" style="margin-bottom: 16px"> |
|
|
|
<template #title> |
|
|
|
<span style="font-size: 20px">{{ item.name }}</span> |
|
|
|
</template> |
|
|
|
<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> |
|
|
|
</div> |
|
|
|
<a-modal v-model:open="openEditPointModal" title="更改上下限" @ok="editPoint"> |
|
|
|
<a-form :model="editForm" :label-col="{ span: 7 }" :wrapper-col="{ span: 15 }"> |
|
|
|
<a-modal |
|
|
|
v-model:open="openEditPointModal" |
|
|
|
title="更改上下限" |
|
|
|
@ok="editPoint" |
|
|
|
> |
|
|
|
<a-form |
|
|
|
:model="editForm" |
|
|
|
:label-col="{ span: 7 }" |
|
|
|
:wrapper-col="{ span: 15 }" |
|
|
|
> |
|
|
|
<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 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 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 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 label="清洗方式" style="margin-top: 16px;"> |
|
|
|
<a-form-item label="清洗方式" style="margin-top: 16px"> |
|
|
|
<a-checkbox v-model:checked="editForm.dead"> |
|
|
|
死区清洗 |
|
|
|
</a-checkbox> |
|
|
|
@ -571,16 +865,83 @@ export default defineComponent({ |
|
|
|
</a-form-item> |
|
|
|
</a-form> |
|
|
|
</a-modal> |
|
|
|
<a-modal v-model:open="openEditModeModal" title="编辑模式" @ok="handleEditMode" @cancel="closeEditMode"> |
|
|
|
<a-form :model="mode" :label-col="{ span: 7 }" :wrapper-col="{ span: 15 }"> |
|
|
|
<a-modal |
|
|
|
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-input v-model:value="mode.alarmname" placeholder="请输入模式名称" /> |
|
|
|
<a-input |
|
|
|
v-model:value="mode.alarmname" |
|
|
|
placeholder="请输入模式名称" |
|
|
|
/> |
|
|
|
</a-form-item> |
|
|
|
<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> |
|
|
|
</a-modal> |
|
|
|
<a-modal |
|
|
|
v-model:open="openEditModelModal" |
|
|
|
title="编辑模型" |
|
|
|
width="1200px" |
|
|
|
@ok="handleEditModelOk" |
|
|
|
@cancel="handleEditModelCancel" |
|
|
|
> |
|
|
|
<a-form |
|
|
|
:model="editModelForm" |
|
|
|
:label-col="{ span: 7 }" |
|
|
|
:wrapper-col="{ span: 15 }" |
|
|
|
> |
|
|
|
<a-row :gutter="16"> |
|
|
|
<a-col :span="12"> |
|
|
|
<a-form-item label="训练采样间隔" required> |
|
|
|
<a-input-number |
|
|
|
v-model:value="editModelForm.sampling" |
|
|
|
placeholder="请输入训练采样间隔" |
|
|
|
style="width: 100%" |
|
|
|
/> |
|
|
|
</a-form-item> |
|
|
|
</a-col> |
|
|
|
<a-col :span="12"> |
|
|
|
<a-form-item label="最小主元贡献率" required> |
|
|
|
<a-input-number |
|
|
|
v-model:value="editModelForm.rate" |
|
|
|
placeholder="请输入最小主元贡献率" |
|
|
|
style="width: 100%" |
|
|
|
/> |
|
|
|
</a-form-item> |
|
|
|
</a-col> |
|
|
|
</a-row> |
|
|
|
<div style="display: flex; justify-content: center; margin-top: 24px;margin-bottom: 10px;"> |
|
|
|
<a-transfer |
|
|
|
v-model:target-keys="editModelForm.selectedKeys" |
|
|
|
:data-source="transferData" |
|
|
|
:render="item => item.title" |
|
|
|
:row-key="(item) => item.key" |
|
|
|
:pagination="false" |
|
|
|
:show-search="true" |
|
|
|
:filter="true" |
|
|
|
search-placeholder="搜索测点" |
|
|
|
:titles="['可选测点', '已选测点']" |
|
|
|
:list-style="{ |
|
|
|
width: '500px', |
|
|
|
height: '450px', |
|
|
|
}" |
|
|
|
@search="handleTransferSearch" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</a-form> |
|
|
|
</a-modal> |
|
|
|
</PageWrapper> |
|
|
|
</template> |
|
|
|
|
|
|
|
|