|
@@ -1,77 +1,90 @@
|
|
|
-import { defineStore } from "pinia";
|
|
|
-import { DrawData, DrawItem, ShapeType } from '../components'
|
|
|
-import { initData } from "./init";
|
|
|
+import { DrawData } from "../components";
|
|
|
+import { SingleHistory } from "../history";
|
|
|
+import { installGlobalVar } from "../hook/use-global-vars";
|
|
|
+import { useStoreRaw } from "./store";
|
|
|
|
|
|
-const sortFn = (a: Pick<DrawItem, 'zIndex' | 'createTime'>, b: Pick<DrawItem, 'zIndex' | 'createTime'>) =>
|
|
|
- a.zIndex - b.zIndex || a.createTime - b.createTime
|
|
|
+type Store = ReturnType<typeof useStoreRaw>
|
|
|
|
|
|
-export const useStore = defineStore('draw-data', {
|
|
|
- state: (): DrawData => (initData),
|
|
|
- getters: {
|
|
|
- items() {
|
|
|
- return Object.values((this as any).$state).flat() as DrawItem[]
|
|
|
- },
|
|
|
- sortItems() {
|
|
|
- return (this.items as any).sort(sortFn) as DrawItem[]
|
|
|
+class DrawHistory extends SingleHistory<string> {
|
|
|
+ preventFlag = false;
|
|
|
+ onceFlag = false;
|
|
|
+ onceHistory: string | null = null
|
|
|
+ initData: string | null = null
|
|
|
+ renderer: (data: string) => void;
|
|
|
+
|
|
|
+ constructor(renderer: (data: string) => void) {
|
|
|
+ super()
|
|
|
+ this.renderer = renderer
|
|
|
+ }
|
|
|
+
|
|
|
+ init(data: string) {
|
|
|
+ this.initData = data
|
|
|
+ }
|
|
|
+
|
|
|
+ preventTrack(fn: () => void) {
|
|
|
+ this.preventFlag = true;
|
|
|
+ fn();
|
|
|
+ this.preventFlag = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ push(data: string) {
|
|
|
+ if (!this.preventFlag) return;
|
|
|
+ if (this.onceFlag) {
|
|
|
+ this.onceHistory = data
|
|
|
+ } else {
|
|
|
+ super.push(data)
|
|
|
}
|
|
|
- },
|
|
|
- actions: {
|
|
|
- setStore(store: DrawData) {
|
|
|
- this.$patch(store);
|
|
|
- },
|
|
|
- getItemNdx<T extends ShapeType>(type: T, id: string) {
|
|
|
- const items = this.$state[type]
|
|
|
- if (items) {
|
|
|
- return items.findIndex(item => item.id === id)
|
|
|
- }
|
|
|
- return -1
|
|
|
- },
|
|
|
- getItem<T extends ShapeType>(type: T, id: string) {
|
|
|
- const ndx = this.getItemNdx(type, id)
|
|
|
- if (~ndx) return this.$state[type]![ndx]
|
|
|
- },
|
|
|
- addItems<T extends ShapeType>(type: T, items: DrawItem<T>[]) {
|
|
|
- this.$patch((state: DrawData) => {
|
|
|
- if (!(type in state)) {
|
|
|
- state[type] = []
|
|
|
- }
|
|
|
- state[type]!.push(...items);
|
|
|
- })
|
|
|
- },
|
|
|
- addItem<T extends ShapeType>(type: T, item: DrawItem<T>) {
|
|
|
- this.addItems(type, [item])
|
|
|
- },
|
|
|
- delItem<T extends ShapeType>(type: T, id: string) {
|
|
|
- const ndx = this.getItemNdx(type, id)
|
|
|
- if (~ndx) {
|
|
|
- this.$patch(state => {
|
|
|
- state[type]!.splice(ndx, 1)
|
|
|
- })
|
|
|
- }
|
|
|
- },
|
|
|
- setItem<T extends ShapeType>(type: T, playData: { value: DrawItem<T>, id: string }) {
|
|
|
- const ndx = this.getItemNdx(type, playData.id)
|
|
|
- console.log(JSON.stringify(playData.value))
|
|
|
- if (~ndx) {
|
|
|
- this.$patch(state => {
|
|
|
- Object.assign(state[type]![ndx], playData.value)
|
|
|
- })
|
|
|
- }
|
|
|
- },
|
|
|
- getItemsZIndex(items?: DrawItem[]) {
|
|
|
- if (!items) {
|
|
|
- return this.sortItems;
|
|
|
- } else {
|
|
|
- return items.sort(sortFn)
|
|
|
- }
|
|
|
- },
|
|
|
- getType(id: string) {
|
|
|
- const types = Object.keys(this.$state) as ShapeType[]
|
|
|
- for (const type of types) {
|
|
|
- if (this.$state[type]?.some(item=> item.id === id)) {
|
|
|
- return type
|
|
|
- }
|
|
|
- }
|
|
|
+ }
|
|
|
+
|
|
|
+ redo() {
|
|
|
+ const data = super.redo()
|
|
|
+ this.renderer(data)
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+
|
|
|
+ undo() {
|
|
|
+ const data = super.undo()
|
|
|
+ this.renderer(data)
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+
|
|
|
+ onceTrack(fn: () => void) {
|
|
|
+ this.onceFlag = true;
|
|
|
+ fn();
|
|
|
+ if (this.onceHistory) {
|
|
|
+ this.push(this.onceHistory)
|
|
|
+ this.onceHistory = null
|
|
|
}
|
|
|
+ this.onceFlag = false;
|
|
|
}
|
|
|
-})
|
|
|
+
|
|
|
+ clear(): void {
|
|
|
+ super.clear()
|
|
|
+ this.initData && this.push(this.initData)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+export const useStore = installGlobalVar(() => {
|
|
|
+ const store = useStoreRaw() as Store & { history: DrawHistory; };
|
|
|
+ const history = new DrawHistory((data) => {
|
|
|
+ store.data = JSON.parse(data) as DrawData
|
|
|
+ })
|
|
|
+ store.history = history
|
|
|
+
|
|
|
+ const trackActions = ["setStore", "repStore", "addItem", "delItem", "setItem"];
|
|
|
+ store.$onAction(({ args, name, after, store }) => {
|
|
|
+ if (!trackActions.includes(name)) return;
|
|
|
+ const isInit = name === "setStore"
|
|
|
+ const current = isInit ? null : JSON.stringify(store.data)
|
|
|
+ after(() => {
|
|
|
+ if (isInit) {
|
|
|
+ history.init(JSON.stringify(store.data))
|
|
|
+ } else {
|
|
|
+ history.push(current!)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ });
|
|
|
+
|
|
|
+ return store;
|
|
|
+});
|