123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- import { set } from "lodash";
- import { StateRoot } from "queenjs";
- type RecordOptions = { combine?: boolean };
- class State extends StateRoot {
- currLen = 0; //操作栈的长度
- maxLen = 100; //操作栈总长度
- opIndex = -1; //操作栈的指针
- canUndo = this.computed((state) => {
- return state.opIndex >= 0;
- });
- canRedo = this.computed((state) => {
- return state.opIndex < state.currLen - 1;
- });
- }
- export class HistoryController {
- state = new State().reactive();
- queue: GroupAction[] = [];
- cacheGroupAction = new GroupAction();
- // 添加缓存记录
- record(action: Action, options?: RecordOptions) {
- this.cacheGroupAction.record(action, options);
- }
- // 保存缓存记录到历史栈中
- submit(action?: Action) {
- const { state, queue, cacheGroupAction } = this;
- if (action) this.record(action);
- if (!cacheGroupAction.actions.length) return;
- // 将缓存操作记录保存到当前指针的下一栈中
- queue[++state.opIndex] = cacheGroupAction;
- // 设置栈的长度为指针的长度,舍弃后面的记录
- queue.length = state.opIndex + 1;
- // 若栈长度超过上限, 舍弃之前的记录
- if (queue.length > state.maxLen) {
- queue.splice(0, queue.length - state.maxLen);
- state.opIndex = state.maxLen - 1;
- }
- // 更新当前长度状态
- state.currLen = queue.length;
- // 更新当前缓存GroupAction
- this.cacheGroupAction = new GroupAction();
- console.log(this);
- }
- undo() {
- if (!this.state.canUndo) return;
- this.queue[this.state.opIndex--].undo();
- console.log(this)
- }
- redo() {
- if (!this.state.canRedo) return;
- this.queue[++this.state.opIndex].redo();
- console.log(this)
- }
- //清除操作
- clear() {
- this.queue = [];
- this.state.currLen = 0;
- this.state.opIndex = -1;
- this.cacheGroupAction = new GroupAction();
- }
- }
- export class Action {
- constructor(
- public type: "set" | "delete",
- public root: any,
- public path: string,
- public value?: any,
- public oldValue?: any
- ) {}
- undo() {
- set(this.root, this.path, this.oldValue);
- }
- redo() {
- set(this.root, this.path, this.value);
- }
- }
- export class GroupAction {
- actions: Action[] = [];
- record(action: Action, options?: RecordOptions) {
- const lastAction = this.actions.at(-1);
- if (
- options?.combine &&
- lastAction?.root === action.root &&
- lastAction?.path === action.path
- ) {
- this.actions[this.actions.length - 1] = action;
- } else {
- this.actions.push(action);
- }
- }
- undo() {
- [...this.actions].reverse().forEach((act) => act.undo());
- }
- redo() {
- this.actions.forEach((d) => d.redo());
- }
- }
|