feat: 增加Undo撤销功能

This commit is contained in:
Xu Zhimeng 2023-09-11 18:59:08 +08:00
parent dcc75bd800
commit 6f9a4cbaed

View File

@ -84,10 +84,10 @@
<a-button type="primary" @click="handleModifyCP">(M)odify CP</a-button> <a-button type="primary" @click="handleModifyCP">(M)odify CP</a-button>
</div> </div>
<div class="peak-box-item"> <div class="peak-box-item">
<a-button type="primary">Edit (S)lope</a-button> <a-button type="primary" @click="handleEditSlope">Edit (S)lope</a-button>
</div> </div>
<div class="peak-box-item"> <div class="peak-box-item">
<a-button type="primary">Undo</a-button> <a-button type="primary" :disabled="isOperationStackEmpty" @click="popOperationStack">Undo</a-button>
</div> </div>
<div class="peak-box-item"> <div class="peak-box-item">
<a-button type="primary">Replot</a-button> <a-button type="primary">Replot</a-button>
@ -383,6 +383,14 @@ const thumbnailOption = {
}, },
series: null series: null
} }
//
export const Operators = {
ADD: 1, //
REMOVE: 2, //
MODIFY: 3 //
}
export default { export default {
mixins: [ModalMixin, SampleDataMixin], mixins: [ModalMixin, SampleDataMixin],
components: { components: {
@ -429,7 +437,9 @@ export default {
currChannel: undefined, // currChannelchannel currChannel: undefined, // currChannelchannel
selectedTableItem: undefined, // selectedTableItem: undefined, //
isModifying: false // isModifying: false, //
operationStack: [] //
} }
}, },
created() { created() {
@ -1141,8 +1151,8 @@ export default {
if (this.btnGroupType == 2) { if (this.btnGroupType == 2) {
this.$nextTick(() => { this.$nextTick(() => {
this.option.graphic = this._channelBaseCPChart.map(({ point: { x, y } }, dataIndex) => { this.option.graphic = this._channelBaseCPChart.map(({ point: { x, y } }) => {
return this.buildGraphicPoint(chart, x, y, dataIndex) return this.buildGraphicPoint(chart, x, y)
}) })
}) })
} }
@ -1164,8 +1174,8 @@ export default {
if (this.btnGroupType == 2) { if (this.btnGroupType == 2) {
const chart = this.$refs.chartRef.getChartInstance() const chart = this.$refs.chartRef.getChartInstance()
this.$nextTick(() => { this.$nextTick(() => {
this.option.graphic = this._channelBaseCPChart.map(({ point: { x, y } }, dataIndex) => { this.option.graphic = this._channelBaseCPChart.map(({ point: { x, y } }) => {
return this.buildGraphicPoint(chart, x, y, dataIndex) return this.buildGraphicPoint(chart, x, y)
}) })
}) })
} }
@ -1176,6 +1186,7 @@ export default {
// Base Line Control Point // Base Line Control Point
if (this.btnGroupType == 1) { if (this.btnGroupType == 1) {
this.btnGroupType = 2 this.btnGroupType = 2
this.clearOperationStack()
const originalCPSeries = findSeriesByName(this.option.series, 'BaseLine') const originalCPSeries = findSeriesByName(this.option.series, 'BaseLine')
@ -1187,8 +1198,8 @@ export default {
const chart = this.$refs.chartRef.getChartInstance() const chart = this.$refs.chartRef.getChartInstance()
this.option.graphic = this.channelBaseCPChart.map(({ point: { x, y } }, dataIndex) => { this.option.graphic = this.channelBaseCPChart.map(({ point: { x, y } }) => {
return this.buildGraphicPoint(chart, x, y, dataIndex) return this.buildGraphicPoint(chart, x, y)
}) })
this._channelBaseCPChart = cloneDeep(this.channelBaseCPChart) this._channelBaseCPChart = cloneDeep(this.channelBaseCPChart)
@ -1205,7 +1216,7 @@ export default {
} }
}, },
buildGraphicPoint(chart, x, y, dataIndex) { buildGraphicPoint(chart, x, y) {
const [xPix, yPix] = chart.convertToPixel('grid', [x, y]) const [xPix, yPix] = chart.convertToPixel('grid', [x, y])
return { return {
type: 'rect', type: 'rect',
@ -1227,6 +1238,10 @@ export default {
this.position[0] = xPixel this.position[0] = xPixel
}, },
ondragend: ({ offsetY }) => { ondragend: ({ offsetY }) => {
const graphic = this.option.graphic
const dataIndex = graphic.findIndex(item => item.position[0] == xPix)
this.option.graphic[dataIndex].position = [xPix, offsetY] this.option.graphic[dataIndex].position = [xPix, offsetY]
this.setGraphicDraggable(false) this.setGraphicDraggable(false)
@ -1237,6 +1252,11 @@ export default {
baseLineEditSeries.data[parseInt(xAxis) - 1] = [x, yAxis] baseLineEditSeries.data[parseInt(xAxis) - 1] = [x, yAxis]
this._channelBaseCPChart[dataIndex].point.y = yAxis this._channelBaseCPChart[dataIndex].point.y = yAxis
this.pushOperationStack(Operators.MODIFY, {
index: dataIndex,
position: [xPix, yPix]
})
}, },
zlevel: 100 zlevel: 100
} }
@ -1288,13 +1308,11 @@ export default {
const baseLineEditSeries = findSeriesByName(this.option.series, 'BaseLine_Edit') const baseLineEditSeries = findSeriesByName(this.option.series, 'BaseLine_Edit')
const yAxis = baseLineEditSeries.data[this.currChannel - 1][1] const yAxis = baseLineEditSeries.data[this.currChannel - 1][1]
this.option.graphic.splice( this.option.graphic.splice(i, 0, this.buildGraphicPoint(chart, this.currChannel, yAxis))
i,
0,
this.buildGraphicPoint(chart, this.currChannel, yAxis, this.option.graphic.length)
)
this._channelBaseCPChart.splice(i, 0, { point: { x: this.currChannel, y: yAxis } }) this._channelBaseCPChart.splice(i, 0, { point: { x: this.currChannel, y: yAxis } })
this.pushOperationStack(Operators.ADD, { index: i })
}, },
// //
@ -1319,7 +1337,12 @@ export default {
return return
} }
controlPointList.splice(i, 1) const [point] = controlPointList.splice(i, 1)
this.pushOperationStack(Operators.REMOVE, {
index: i,
point
})
}, },
// //
@ -1327,6 +1350,24 @@ export default {
this.setGraphicDraggable(true) this.setGraphicDraggable(true)
}, },
//
handleEditSlope() {
// if (m_baseCtrl.XCtrl.empty()) {
// this.$message.warn('No control points to be edited')
// return
// }
// // find nearest control-point
// let i = 1,
// n = m_baseCtrl.XCtrl.size()
// for (; i < n; ++i) {
// if (m_baseCtrl.XCtrl[i] >= m_curChan) {
// if (m_baseCtrl.XCtrl[i] - m_curChan > m_curChan - m_baseCtrl.XCtrl[i - 1]) --i
// break
// }
// }
// if (i == n) i = n - 1
},
// Control Point // Control Point
handleAccept() {}, handleAccept() {},
@ -1390,6 +1431,47 @@ export default {
this.selectedTableItem._deleting = false this.selectedTableItem._deleting = false
} }
} }
},
/**
* 推入操作
* @param {*} operator 操作符
* @param {*} operand 操作数
*/
pushOperationStack(operator, operand) {
this.operationStack.push({
operator,
operand
})
},
/**
* 弹出操作
*/
popOperationStack() {
const { operator, operand } = this.operationStack.pop()
const { index } = operand
switch (operator) {
case Operators.ADD:
this.option.graphic.splice(index, 1)
this._channelBaseCPChart.splice(index, 1)
break
case Operators.MODIFY:
const { position } = operand
this.option.graphic[index].position = position
break
case Operators.REMOVE:
const { point } = operand
this.option.graphic.splice(index, 0, point)
break
}
},
/**
* 清理操作栈
*/
clearOperationStack() {
this.operationStack = []
} }
}, },
computed: { computed: {
@ -1397,6 +1479,10 @@ export default {
const [selectedKey] = this.selectedKeys const [selectedKey] = this.selectedKeys
const findIndex = this.list.findIndex(item => item.index == selectedKey) const findIndex = this.list.findIndex(item => item.index == selectedKey)
return findIndex return findIndex
},
isOperationStackEmpty() {
return this.operationStack.length == 0
} }
} }
} }
@ -1405,6 +1491,7 @@ export default {
<style lang="less" scoped> <style lang="less" scoped>
.interactive-analysis-tools { .interactive-analysis-tools {
display: flex; display: flex;
margin-top: 5px;
&-left { &-left {
width: 75%; width: 75%;