|
|
|
@ -1,10 +1,10 @@ |
|
|
|
<script lang="ts"> |
|
|
|
import type { ComponentPublicInstance } from 'vue' |
|
|
|
import type { Dayjs } from 'dayjs' |
|
|
|
import { debounce } from 'lodash-es' |
|
|
|
import dayjs from 'dayjs' |
|
|
|
import { computed, defineComponent, onMounted, ref, toRaw, watch } from 'vue' |
|
|
|
import { useRoute, useRouter } from 'vue-router' |
|
|
|
import type { ComponentPublicInstance } from "vue"; |
|
|
|
import type { Dayjs } from "dayjs"; |
|
|
|
import { debounce } from "lodash-es"; |
|
|
|
import dayjs from "dayjs"; |
|
|
|
import { computed, defineComponent, onMounted, ref, toRaw, watch } from "vue"; |
|
|
|
import { useRoute } from "vue-router"; |
|
|
|
import { |
|
|
|
Button, |
|
|
|
Card, |
|
|
|
@ -25,11 +25,12 @@ import { |
|
|
|
Steps, |
|
|
|
Table, |
|
|
|
Tabs, |
|
|
|
} from 'ant-design-vue' |
|
|
|
import VueECharts from 'vue-echarts' |
|
|
|
import { pointTableSchema, sampleInfoTableSchema } from './data' |
|
|
|
import { BasicTable, useTable } from '@/components/Table' |
|
|
|
import { PageWrapper } from '@/components/Page' |
|
|
|
Transfer, |
|
|
|
} from "ant-design-vue"; |
|
|
|
import VueECharts from "vue-echarts"; |
|
|
|
import { pointTableSchema, sampleInfoTableSchema } from "./data"; |
|
|
|
import { BasicTable, useTable } from "@/components/Table"; |
|
|
|
import { PageWrapper } from "@/components/Page"; |
|
|
|
import { |
|
|
|
bottomModelApi, |
|
|
|
createDraftVersionApi, |
|
|
|
@ -151,14 +152,14 @@ export default defineComponent({ |
|
|
|
pagination: true, |
|
|
|
dataSource: pointData, |
|
|
|
scroll: { y: 300 }, |
|
|
|
}) |
|
|
|
}); |
|
|
|
|
|
|
|
const trainTime = computed(() => model.value?.trainTime || []) |
|
|
|
const trainTime = computed(() => model.value?.trainTime || []); |
|
|
|
const [trainTimeTable] = useTable({ |
|
|
|
columns: sampleInfoTableSchema, |
|
|
|
dataSource: trainTime, |
|
|
|
scroll: { y: 300 }, |
|
|
|
}) |
|
|
|
}); |
|
|
|
|
|
|
|
const updatePrincipalFromTrainTime = (trainTimeList: any[]) => { |
|
|
|
if (!Array.isArray(trainTimeList) || !model.value) |
|
|
|
@ -189,34 +190,33 @@ export default defineComponent({ |
|
|
|
const echartsRefs = ref<any[]>([]) |
|
|
|
|
|
|
|
async function getHistory() { |
|
|
|
if (!historyTime.value) |
|
|
|
return |
|
|
|
spinning.value = true |
|
|
|
if (!historyTime.value) return; |
|
|
|
spinning.value = true; |
|
|
|
if (model.value.para) { |
|
|
|
await 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'), |
|
|
|
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(','), |
|
|
|
.map((item) => item.pointId) |
|
|
|
.join(","), |
|
|
|
interval: model.value.sampling, |
|
|
|
} |
|
|
|
const history = await getExaHistorys(params) |
|
|
|
}; |
|
|
|
const history = await getExaHistorys(params); |
|
|
|
historyList.value = history.map((item, index) => { |
|
|
|
const point = model.value?.pointInfo[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() |
|
|
|
}; |
|
|
|
}); |
|
|
|
echartsRefs.value = Array.from({ length: historyList.value.length }); |
|
|
|
brushActivated.value = new Set(); |
|
|
|
} |
|
|
|
|
|
|
|
spinning.value = false |
|
|
|
spinning.value = false; |
|
|
|
} |
|
|
|
|
|
|
|
async function getTestData(range?: RangeValue) { |
|
|
|
@ -247,7 +247,7 @@ export default defineComponent({ |
|
|
|
model.value.sampling * 1000, |
|
|
|
) |
|
|
|
historyList.value = sampleData.map((item, index) => { |
|
|
|
const point = model.value?.pointInfo[index] |
|
|
|
const point = model.value?.pointInfo[index]; |
|
|
|
return { |
|
|
|
data: [ |
|
|
|
(Array.isArray(item) ? item : []).map((t, i) => { |
|
|
|
@ -258,15 +258,17 @@ export default defineComponent({ |
|
|
|
}), |
|
|
|
], |
|
|
|
name: `${index + 1}.${point?.description}(${point?.pointId})`, |
|
|
|
} |
|
|
|
}) |
|
|
|
brushActivated.value = new Set() |
|
|
|
}; |
|
|
|
}); |
|
|
|
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()) |
|
|
|
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 normalizeTrainTime(modelInfo: any) { |
|
|
|
@ -290,37 +292,37 @@ export default defineComponent({ |
|
|
|
} |
|
|
|
|
|
|
|
function getOption(item: any) { |
|
|
|
const name = ['测量值', '模型值', ''] |
|
|
|
const color = ['blue', '#ff6f00', 'red'] |
|
|
|
const yIndex = [0, 0, 1] |
|
|
|
const name = ["测量值", "模型值", ""]; |
|
|
|
const color = ["blue", "#ff6f00", "red"]; |
|
|
|
const yIndex = [0, 0, 1]; |
|
|
|
const option = { |
|
|
|
xAxis: { |
|
|
|
type: 'time', |
|
|
|
type: "time", |
|
|
|
axisLabel: { |
|
|
|
formatter(value) { |
|
|
|
const date = new Date(value) |
|
|
|
return date.toLocaleString() |
|
|
|
const date = new Date(value); |
|
|
|
return date.toLocaleString(); |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
yAxis: [{ type: 'value' }, { type: 'value', max: 10, show: false }], |
|
|
|
yAxis: [{ type: "value" }, { type: "value", max: 10, show: false }], |
|
|
|
series: item.data.map((item, index) => { |
|
|
|
return { |
|
|
|
data: item, |
|
|
|
type: 'line', |
|
|
|
type: "line", |
|
|
|
smooth: true, |
|
|
|
symbol: 'none', |
|
|
|
symbol: "none", |
|
|
|
name: name[index], |
|
|
|
color: color[index], |
|
|
|
yAxisIndex: yIndex[index], |
|
|
|
} |
|
|
|
}; |
|
|
|
}), |
|
|
|
legend: {}, |
|
|
|
dataZoom: [{}], |
|
|
|
brush: { |
|
|
|
toolbox: ['lineX'], |
|
|
|
toolbox: ["lineX"], |
|
|
|
xAxisIndex: 0, |
|
|
|
brushType: 'lineX', |
|
|
|
brushType: "lineX", |
|
|
|
}, |
|
|
|
grid: [ |
|
|
|
{ |
|
|
|
@ -330,54 +332,49 @@ export default defineComponent({ |
|
|
|
top: 30, |
|
|
|
}, |
|
|
|
], |
|
|
|
} |
|
|
|
return option |
|
|
|
}; |
|
|
|
return option; |
|
|
|
} |
|
|
|
|
|
|
|
function setChartRef( |
|
|
|
el: Element | ComponentPublicInstance | null, |
|
|
|
index: number, |
|
|
|
index: number |
|
|
|
) { |
|
|
|
let dom: HTMLElement | null = null |
|
|
|
let dom: HTMLElement | null = null; |
|
|
|
if (el) { |
|
|
|
if ('$el' in el && (el as any).$el instanceof HTMLElement) |
|
|
|
dom = (el as any).$el |
|
|
|
else if (el instanceof HTMLElement) |
|
|
|
dom = el |
|
|
|
if ("$el" in el && (el as any).$el instanceof HTMLElement) |
|
|
|
dom = (el as any).$el; |
|
|
|
else if (el instanceof HTMLElement) dom = el; |
|
|
|
} |
|
|
|
if (dom) |
|
|
|
useECharts(ref(dom as HTMLDivElement)) |
|
|
|
if (dom) useECharts(ref(dom as HTMLDivElement)); |
|
|
|
} |
|
|
|
|
|
|
|
function setEchartsRef(el: any, index: number) { |
|
|
|
if (el) |
|
|
|
echartsRefs.value[index] = el |
|
|
|
if (el) echartsRefs.value[index] = el; |
|
|
|
} |
|
|
|
const isInitBrush = ref(true) |
|
|
|
const isInitBrush = ref(true); |
|
|
|
function onChartFinished(index: number) { |
|
|
|
if (brushActivated.value.has(index)) |
|
|
|
return |
|
|
|
const chart = echartsRefs.value[index] |
|
|
|
if (!chart) |
|
|
|
return |
|
|
|
if (brushActivated.value.has(index)) return; |
|
|
|
const chart = echartsRefs.value[index]; |
|
|
|
if (!chart) return; |
|
|
|
chart.dispatchAction({ |
|
|
|
type: 'takeGlobalCursor', |
|
|
|
key: 'brush', |
|
|
|
type: "takeGlobalCursor", |
|
|
|
key: "brush", |
|
|
|
brushOption: { |
|
|
|
brushType: 'lineX', |
|
|
|
brushMode: 'multiple', |
|
|
|
brushType: "lineX", |
|
|
|
brushMode: "multiple", |
|
|
|
}, |
|
|
|
}) |
|
|
|
const areas = (model.value?.trainTime || []).map(row => ({ |
|
|
|
brushType: 'lineX', |
|
|
|
}); |
|
|
|
const areas = (model.value?.trainTime || []).map((row) => ({ |
|
|
|
brushType: "lineX", |
|
|
|
xAxisIndex: 0, |
|
|
|
coordRange: [ |
|
|
|
dayjs(row.st).format('YYYY-MM-DD HH:mm:ss'), |
|
|
|
dayjs(row.et).format('YYYY-MM-DD HH:mm:ss'), |
|
|
|
dayjs(row.st).format("YYYY-MM-DD HH:mm:ss"), |
|
|
|
dayjs(row.et).format("YYYY-MM-DD HH:mm:ss"), |
|
|
|
], |
|
|
|
})) |
|
|
|
})); |
|
|
|
chart.dispatchAction({ |
|
|
|
type: 'brush', |
|
|
|
type: "brush", |
|
|
|
areas, |
|
|
|
}) |
|
|
|
isInitBrush.value = true |
|
|
|
@ -385,148 +382,131 @@ export default defineComponent({ |
|
|
|
} |
|
|
|
|
|
|
|
onMounted(async () => { |
|
|
|
await fetchModelInfo() |
|
|
|
}) |
|
|
|
await fetchModelInfo(); |
|
|
|
}); |
|
|
|
const onBrushSelected = debounce((params) => { |
|
|
|
if (isInitBrush.value) { |
|
|
|
isInitBrush.value = false |
|
|
|
return |
|
|
|
isInitBrush.value = false; |
|
|
|
return; |
|
|
|
} |
|
|
|
if (!isInitBrush.value && model.value?.version != 'v-test') |
|
|
|
return |
|
|
|
|
|
|
|
const selected = params.batch[0].selected |
|
|
|
if (!isInitBrush.value && model?.Cur_Version != "v-test") { |
|
|
|
return; |
|
|
|
} |
|
|
|
const selected = params.batch[0].selected; |
|
|
|
if (selected.length > 0) { |
|
|
|
const areas = mergeAreas(params.batch[0].areas).map(area => ({ |
|
|
|
const areas = mergeAreas(params.batch[0].areas).map((area) => ({ |
|
|
|
brushType: area.brushType, |
|
|
|
xAxisIndex: 0, |
|
|
|
coordRange: area.coordRange, |
|
|
|
})) |
|
|
|
})); |
|
|
|
const trainTime = areas.map((area) => { |
|
|
|
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) |
|
|
|
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'), |
|
|
|
st: dayjs(st).format("YYYY-MM-DD HH:mm:ss"), |
|
|
|
et: dayjs(et).format("YYYY-MM-DD HH:mm:ss"), |
|
|
|
duration: Math.round((et - st) / 1000), |
|
|
|
number: '', // 采样数量(如有数据可补充) |
|
|
|
filter: '', // 清洗样本数(如有数据可补充) |
|
|
|
mode: '', // 有效样本数(如有数据可补充) |
|
|
|
} |
|
|
|
}) |
|
|
|
console.log('Selected train time:', trainTime) |
|
|
|
if (trainTimeCopy === JSON.stringify(trainTime)) |
|
|
|
return |
|
|
|
model.value.trainTime = trainTime |
|
|
|
trainTimeCopy = JSON.stringify(trainTime) |
|
|
|
number: "", // 采样数量(如有数据可补充) |
|
|
|
filter: "", // 清洗样本数(如有数据可补充) |
|
|
|
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({ |
|
|
|
type: 'brush', |
|
|
|
type: "brush", |
|
|
|
areas, |
|
|
|
}) |
|
|
|
isInitBrush.value = true |
|
|
|
}); |
|
|
|
isInitBrush.value = true; |
|
|
|
} |
|
|
|
}) |
|
|
|
updateModelInfoDebounced() |
|
|
|
}); |
|
|
|
updateModelInfoDebounced(); |
|
|
|
} |
|
|
|
}, 300) |
|
|
|
}, 300); |
|
|
|
|
|
|
|
function mergeAreas(areas: any[]) { |
|
|
|
if (!areas.length) |
|
|
|
return [] |
|
|
|
if (!areas.length) return []; |
|
|
|
// 只合并 brushType 和 xAxisIndex 相同的区间 |
|
|
|
const sorted = [...areas].sort( |
|
|
|
(a, b) => a.coordRange[0] - b.coordRange[0], |
|
|
|
) |
|
|
|
const merged: any[] = [] |
|
|
|
(a, b) => a.coordRange[0] - b.coordRange[0] |
|
|
|
); |
|
|
|
const merged: any[] = []; |
|
|
|
for (const area of sorted) { |
|
|
|
if ( |
|
|
|
merged.length |
|
|
|
&& merged[merged.length - 1].brushType === area.brushType |
|
|
|
&& merged[merged.length - 1].xAxisIndex === area.xAxisIndex |
|
|
|
&& merged[merged.length - 1].coordRange[1] >= area.coordRange[0] |
|
|
|
merged.length && |
|
|
|
merged[merged.length - 1].brushType === area.brushType && |
|
|
|
merged[merged.length - 1].xAxisIndex === area.xAxisIndex && |
|
|
|
merged[merged.length - 1].coordRange[1] >= area.coordRange[0] |
|
|
|
) { |
|
|
|
// 有交集或相邻,合并 |
|
|
|
merged[merged.length - 1].coordRange[1] = Math.max( |
|
|
|
merged[merged.length - 1].coordRange[1], |
|
|
|
area.coordRange[1], |
|
|
|
) |
|
|
|
} |
|
|
|
else { |
|
|
|
area.coordRange[1] |
|
|
|
); |
|
|
|
} else { |
|
|
|
// 新区间 |
|
|
|
merged.push({ |
|
|
|
brushType: area.brushType, |
|
|
|
xAxisIndex: area.xAxisIndex, |
|
|
|
coordRange: [...area.coordRange], |
|
|
|
}) |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
return merged |
|
|
|
return merged; |
|
|
|
} |
|
|
|
|
|
|
|
// 防抖更新 |
|
|
|
const updateModelInfoDebounced = debounce(() => { |
|
|
|
const val = toRaw(model.value) |
|
|
|
if (val && val.id) |
|
|
|
updateModelInfo(val) |
|
|
|
}, 500) |
|
|
|
const val = toRaw(model.value); |
|
|
|
if (val && val.id) updateModelInfo(val); |
|
|
|
}, 500); |
|
|
|
|
|
|
|
function handleDeleteTrainTime(index: number) { |
|
|
|
if (!canEditModel.value) { |
|
|
|
createMessage.warning('非草稿版本不可修改训练时间') |
|
|
|
return |
|
|
|
} |
|
|
|
if (!model.value?.trainTime) |
|
|
|
return |
|
|
|
if (!model.value?.trainTime) return; |
|
|
|
// 赋值新数组,确保响应式 |
|
|
|
model.value.trainTime = [ |
|
|
|
...model.value.trainTime.slice(0, index), |
|
|
|
...model.value.trainTime.slice(index + 1), |
|
|
|
] |
|
|
|
]; |
|
|
|
// 删除后同步更新所有图表的 brush 区域 |
|
|
|
const areas = (model.value.trainTime || []).map(row => ({ |
|
|
|
brushType: 'lineX', |
|
|
|
const areas = (model.value.trainTime || []).map((row) => ({ |
|
|
|
brushType: "lineX", |
|
|
|
xAxisIndex: 0, |
|
|
|
coordRange: [dayjs(row.st).valueOf(), dayjs(row.et).valueOf()], |
|
|
|
})) |
|
|
|
})); |
|
|
|
echartsRefs.value.forEach((chart) => { |
|
|
|
if (chart) { |
|
|
|
chart.dispatchAction({ |
|
|
|
type: 'brush', |
|
|
|
type: "brush", |
|
|
|
areas, |
|
|
|
}) |
|
|
|
isInitBrush.value = true |
|
|
|
}); |
|
|
|
isInitBrush.value = true; |
|
|
|
} |
|
|
|
}) |
|
|
|
updateModelInfoDebounced() |
|
|
|
}); |
|
|
|
updateModelInfoDebounced(); |
|
|
|
} |
|
|
|
async function clearModel() { |
|
|
|
if (!canEditModel.value) { |
|
|
|
createMessage.warning('非草稿版本不可清除训练结果') |
|
|
|
return |
|
|
|
} |
|
|
|
model.value.para = null |
|
|
|
updateModelInfoDebounced() |
|
|
|
await getHistory() |
|
|
|
model.value.para = null; |
|
|
|
updateModelInfoDebounced(); |
|
|
|
await getHistory(); |
|
|
|
} |
|
|
|
|
|
|
|
async function trainModel() { |
|
|
|
if (!canEditModel.value) { |
|
|
|
createMessage.warning('非草稿版本不可训练模型') |
|
|
|
return |
|
|
|
} |
|
|
|
const modelInfo = model.value |
|
|
|
const modelInfo = model.value; |
|
|
|
if (!modelInfo || !modelInfo.id) { |
|
|
|
console.error('模型信息不完整,无法训练') |
|
|
|
return |
|
|
|
console.error("模型信息不完整,无法训练"); |
|
|
|
return; |
|
|
|
} |
|
|
|
const pointInfo = modelInfo.pointInfo || [] |
|
|
|
const pointInfo = modelInfo.pointInfo || []; |
|
|
|
if (pointInfo.length === 0) { |
|
|
|
console.error('模型参数点信息为空,无法训练') |
|
|
|
return |
|
|
|
console.error("模型参数点信息为空,无法训练"); |
|
|
|
return; |
|
|
|
} |
|
|
|
const params = { |
|
|
|
conditon: modelInfo.alarmmodelset?.alarmcondition || '1=1', |
|
|
|
@ -534,27 +514,27 @@ export default defineComponent({ |
|
|
|
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(','), |
|
|
|
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) => |
|
|
|
`${item.Upper ? item.Upper : null},${ |
|
|
|
item.Lower ? item.Lower : null |
|
|
|
}`, |
|
|
|
}` |
|
|
|
) |
|
|
|
.join(';'), |
|
|
|
.join(";"), |
|
|
|
interval: modelInfo.sampling * 1000, |
|
|
|
time: modelInfo.trainTime |
|
|
|
.map(item => `${item.st},${item.et}`) |
|
|
|
.join(';'), |
|
|
|
.map((item) => `${item.st},${item.et}`) |
|
|
|
.join(";"), |
|
|
|
}, |
|
|
|
type: 'PCA', |
|
|
|
type: "PCA", |
|
|
|
smote_config: [], |
|
|
|
smote: true, |
|
|
|
} |
|
|
|
spinning.value = true |
|
|
|
}; |
|
|
|
spinning.value = true; |
|
|
|
try { |
|
|
|
const response = await trainModelApi(params) |
|
|
|
model.value.para = response |
|
|
|
@ -640,19 +620,19 @@ export default defineComponent({ |
|
|
|
createMessage.error('模型训练失败') |
|
|
|
} |
|
|
|
|
|
|
|
spinning.value = false |
|
|
|
spinning.value = false; |
|
|
|
} |
|
|
|
const editForm = ref({ |
|
|
|
index: -1, |
|
|
|
Upper: '', |
|
|
|
Lower: '', |
|
|
|
lowerBound: '', |
|
|
|
upperBound: '', |
|
|
|
Upper: "", |
|
|
|
Lower: "", |
|
|
|
lowerBound: "", |
|
|
|
upperBound: "", |
|
|
|
dead: true, |
|
|
|
limit: false, |
|
|
|
}) |
|
|
|
const openEditPointModal = ref<boolean>(false) |
|
|
|
let pointEditRecord = null |
|
|
|
}); |
|
|
|
const openEditPointModal = ref<boolean>(false); |
|
|
|
let pointEditRecord = null; |
|
|
|
function editPoint() { |
|
|
|
// 这里可以添加编辑点的逻辑 |
|
|
|
model.value.pointInfo[editForm.value.index] = { |
|
|
|
@ -663,15 +643,15 @@ export default defineComponent({ |
|
|
|
upperBound: editForm.value.upperBound, |
|
|
|
dead: editForm.value.dead, |
|
|
|
limit: editForm.value.limit, |
|
|
|
} |
|
|
|
updateModelInfoDebounced() |
|
|
|
pointEditRecord.Upper = editForm.value.Upper |
|
|
|
pointEditRecord.Lower = editForm.value.Lower |
|
|
|
pointEditRecord.lowerBound = editForm.value.lowerBound |
|
|
|
pointEditRecord.upperBound = editForm.value.upperBound |
|
|
|
pointEditRecord.dead = editForm.value.dead |
|
|
|
pointEditRecord.limit = editForm.value.limit |
|
|
|
openEditPointModal.value = false |
|
|
|
}; |
|
|
|
updateModelInfoDebounced(); |
|
|
|
pointEditRecord.Upper = editForm.value.Upper; |
|
|
|
pointEditRecord.Lower = editForm.value.Lower; |
|
|
|
pointEditRecord.lowerBound = editForm.value.lowerBound; |
|
|
|
pointEditRecord.upperBound = editForm.value.upperBound; |
|
|
|
pointEditRecord.dead = editForm.value.dead; |
|
|
|
pointEditRecord.limit = editForm.value.limit; |
|
|
|
openEditPointModal.value = false; |
|
|
|
} |
|
|
|
|
|
|
|
function openPointModal(index, record) { |
|
|
|
@ -680,29 +660,22 @@ export default defineComponent({ |
|
|
|
return |
|
|
|
} |
|
|
|
// 当前页 index |
|
|
|
const pageIndex = index |
|
|
|
const pageIndex = index; |
|
|
|
// 全局 index |
|
|
|
const globalIndex = model.value.pointInfo.findIndex( |
|
|
|
item => item.pointId === record.pointId, |
|
|
|
) |
|
|
|
openEditPointModal.value = true |
|
|
|
pointEditRecord = record |
|
|
|
const normalizeBool = (val: any) => { |
|
|
|
if (val === true || val === '是' || val === 1 || val === '1') |
|
|
|
return true |
|
|
|
if (val === false || val === '否' || val === 0 || val === '0') |
|
|
|
return false |
|
|
|
return !!val |
|
|
|
} |
|
|
|
(item) => item.pointId === record.pointId |
|
|
|
); |
|
|
|
openEditPointModal.value = true; |
|
|
|
pointEditRecord = record; |
|
|
|
editForm.value = { |
|
|
|
index: globalIndex, |
|
|
|
Upper: record?.Upper ?? '', |
|
|
|
Lower: record?.Lower ?? '', |
|
|
|
lowerBound: record?.lowerBound ?? '', |
|
|
|
upperBound: record?.upperBound ?? '', |
|
|
|
dead: normalizeBool(record?.dead), |
|
|
|
limit: normalizeBool(record?.limit), |
|
|
|
} |
|
|
|
Upper: record?.Upper ?? "", |
|
|
|
Lower: record?.Lower ?? "", |
|
|
|
lowerBound: record?.lowerBound ?? "", |
|
|
|
upperBound: record?.upperBound ?? "", |
|
|
|
dead: !!record?.dead, |
|
|
|
limit: !!record?.limit, |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
const mode = ref({ |
|
|
|
@ -713,58 +686,92 @@ export default defineComponent({ |
|
|
|
const normalizeVersion = (val?: string | null) => (val ? String(val).trim().toLowerCase() : '') |
|
|
|
|
|
|
|
function openEditMode() { |
|
|
|
if (!canEditModel.value) { |
|
|
|
createMessage.warning('非草稿版本不可修改模式') |
|
|
|
return |
|
|
|
} |
|
|
|
openEditModeModal.value = true |
|
|
|
openEditModeModal.value = true; |
|
|
|
mode.value = { |
|
|
|
alarmcondition: model.value?.alarmmodelset?.alarmcondition || '1=1', |
|
|
|
alarmname: model.value?.alarmmodelset?.alarmname || '全工况运行', |
|
|
|
} |
|
|
|
} |
|
|
|
function closeEditMode() { |
|
|
|
openEditModeModal.value = false |
|
|
|
openEditModeModal.value = false; |
|
|
|
} |
|
|
|
function handleEditMode() { |
|
|
|
// 这里可以添加编辑模式的逻辑 |
|
|
|
model.value.alarmmodelset = mode.value |
|
|
|
updateModelInfoDebounced() |
|
|
|
closeEditMode() |
|
|
|
model.value.alarmmodelset = mode.value; |
|
|
|
updateModelInfoDebounced(); |
|
|
|
closeEditMode(); |
|
|
|
} |
|
|
|
|
|
|
|
const openEditModelModal = ref(false) |
|
|
|
const openEditModelModal = ref(false); |
|
|
|
const editModelForm = ref({ |
|
|
|
sampling: 0, |
|
|
|
rate: 0, |
|
|
|
selectedKeys: [], |
|
|
|
}) |
|
|
|
}); |
|
|
|
|
|
|
|
function openEditModel() { |
|
|
|
if (!canEditModel.value) { |
|
|
|
createMessage.warning('非草稿版本不可修改模型') |
|
|
|
return |
|
|
|
} |
|
|
|
editModelForm.value.sampling = model.value?.sampling || 0 |
|
|
|
editModelForm.value.rate = model.value?.rate || 0 |
|
|
|
editModelForm.value.selectedKeys = (model.value?.pointInfo || []).map(item => buildPointKeyFromInfo({ |
|
|
|
description: item.description ?? item.Description, |
|
|
|
pointId: item.pointId ?? item.PointId, |
|
|
|
unit: item.unit ?? item.Unit, |
|
|
|
Lower: item.Lower ?? item.lower, |
|
|
|
Upper: item.Upper ?? item.upper, |
|
|
|
// 穿梭框数据源示例 |
|
|
|
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, |
|
|
|
})) |
|
|
|
openEditModelModal.value = true |
|
|
|
); |
|
|
|
console.log("Transfer data:", transferData.value); |
|
|
|
} |
|
|
|
function handleEditModelOk() { |
|
|
|
if (!canEditModel.value) { |
|
|
|
createMessage.warning('非草稿版本不可修改模型') |
|
|
|
return |
|
|
|
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})`, |
|
|
|
})); |
|
|
|
} |
|
|
|
model.value.sampling = editModelForm.value.sampling |
|
|
|
model.value.rate = editModelForm.value.rate |
|
|
|
} |
|
|
|
|
|
|
|
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 } = parsePointKey(key) |
|
|
|
const [description, pointId, unit, Lower, Upper] = key.split("|"); |
|
|
|
return { |
|
|
|
description, |
|
|
|
pointId, |
|
|
|
@ -773,13 +780,13 @@ export default defineComponent({ |
|
|
|
Upper, |
|
|
|
dead: true, |
|
|
|
limit: false, |
|
|
|
} |
|
|
|
}) |
|
|
|
clearModel() |
|
|
|
openEditModelModal.value = false |
|
|
|
}; |
|
|
|
}); |
|
|
|
clearModel(); |
|
|
|
openEditModelModal.value = false; |
|
|
|
} |
|
|
|
function handleEditModelCancel() { |
|
|
|
openEditModelModal.value = false |
|
|
|
openEditModelModal.value = false; |
|
|
|
} |
|
|
|
|
|
|
|
const reportModalVisible = ref(false) |
|
|
|
@ -1056,7 +1063,7 @@ export default defineComponent({ |
|
|
|
canEditModel, |
|
|
|
} |
|
|
|
}, |
|
|
|
}) |
|
|
|
}); |
|
|
|
</script> |
|
|
|
|
|
|
|
<template> |
|
|
|
@ -1145,7 +1152,7 @@ export default defineComponent({ |
|
|
|
( |
|
|
|
model?.trainTime.reduce( |
|
|
|
(total, item) => total + item.duration, |
|
|
|
0, |
|
|
|
0 |
|
|
|
) / 3600 |
|
|
|
).toFixed(2) || "暂无" |
|
|
|
}} |
|
|
|
@ -1337,12 +1344,8 @@ export default defineComponent({ |
|
|
|
/> |
|
|
|
</a-form-item> |
|
|
|
<a-form-item label="清洗方式" style="margin-top: 16px"> |
|
|
|
<a-checkbox v-model:checked="editForm.dead"> |
|
|
|
死区清洗 |
|
|
|
</a-checkbox> |
|
|
|
<a-checkbox v-model:checked="editForm.limit"> |
|
|
|
限值清洗 |
|
|
|
</a-checkbox> |
|
|
|
<a-checkbox v-model:checked="editForm.dead"> 死区清洗 </a-checkbox> |
|
|
|
<a-checkbox v-model:checked="editForm.limit"> 限值清洗 </a-checkbox> |
|
|
|
</a-form-item> |
|
|
|
</a-form> |
|
|
|
</a-modal> |
|
|
|
@ -1403,10 +1406,24 @@ export default defineComponent({ |
|
|
|
</a-form-item> |
|
|
|
</a-col> |
|
|
|
</a-row> |
|
|
|
<div style="display: flex; justify-content: center; margin-top: 24px;margin-bottom: 10px;"> |
|
|
|
<PointTransfer |
|
|
|
v-model:selected-keys="editModelForm.selectedKeys" |
|
|
|
:prefill-points="model?.pointInfo || []" |
|
|
|
<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', |
|
|
|
|