|
@@ -0,0 +1,121 @@
|
|
|
+import { Ref, toRaw } from 'vue'
|
|
|
+import { deepIsRevise } from './diff'
|
|
|
+
|
|
|
+export const storeSecurityPush = <T extends any>(items: T[], pushItem: T) => {
|
|
|
+ const index = items.indexOf(pushItem)
|
|
|
+ if (!~index) {
|
|
|
+ items.push(pushItem)
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+}
|
|
|
+export const storeSecurityDelete = <T extends any>(items: T[], pushItem: T) => {
|
|
|
+ const index = items.indexOf(pushItem)
|
|
|
+ if (~index) {
|
|
|
+ items.splice(index, 1)
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export const addStoreItem = <T extends {id: any}>(items: Ref<T[]>, addAction: (item: T) => Promise<T>) => {
|
|
|
+ return async (item: T) => {
|
|
|
+ const newItem = await addAction(item)
|
|
|
+ item.id = newItem.id
|
|
|
+ storeSecurityPush(items.value, item)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export const updateStoreItem = <T extends {id: any}>(items: Ref<T[]>, updateAction: (item: T, oldItem: T) => Promise<any>) => {
|
|
|
+ return async (item: T, oldItem: T) => {
|
|
|
+ await updateAction(item, oldItem)
|
|
|
+ const storeItem = items.value.find(atom => atom.id === item.id)
|
|
|
+ if (storeItem) {
|
|
|
+ Object.assign(storeItem, item)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+export const deleteStoreItem = <T extends {id: any}>(items: Ref<T[]>, deleteAction: (item: T) => Promise<any>) => {
|
|
|
+ return async (item: T) => {
|
|
|
+ await deleteAction(item)
|
|
|
+ storeSecurityDelete(items.value, item)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export const fetchStoreItems = <T extends {id: any}>(items: Ref<T[]>, fetchAction: () => Promise<T[]>, callback?: () => void) => {
|
|
|
+ return async () => {
|
|
|
+ const fetchItems = await fetchAction()
|
|
|
+ items.value = fetchItems
|
|
|
+ callback && callback()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export const saveStoreItems = <T extends {id: any}>(
|
|
|
+ newItems: Ref<T[]>,
|
|
|
+ getOldItem: () => T[],
|
|
|
+ actions: {
|
|
|
+ add: ReturnType<typeof addStoreItem<T>>,
|
|
|
+ update: ReturnType<typeof updateStoreItem<T>>,
|
|
|
+ delete: ReturnType<typeof deleteStoreItem<T>>,
|
|
|
+ }
|
|
|
+) => () => {
|
|
|
+ const oldItems = getOldItem()
|
|
|
+ const {
|
|
|
+ deleted,
|
|
|
+ updated,
|
|
|
+ added
|
|
|
+ } = diffStoreItemsChange(newItems.value, oldItems)
|
|
|
+
|
|
|
+ const promiseAll: Promise<any>[] = []
|
|
|
+
|
|
|
+ for (const delItem of deleted) {
|
|
|
+ promiseAll.push(actions.delete(delItem))
|
|
|
+ }
|
|
|
+ for (const [newItem, oldItem] of updated) {
|
|
|
+ promiseAll.push(actions.update(newItem, oldItem))
|
|
|
+ }
|
|
|
+ for (const addItem of added) {
|
|
|
+ promiseAll.push(actions.add(addItem))
|
|
|
+ }
|
|
|
+ return Promise.all(promiseAll)
|
|
|
+}
|
|
|
+
|
|
|
+export const diffStoreItemsChange = <T extends Array<{ id: any }>>(newItems: T, oldItems: T) => {
|
|
|
+ const addedItems = [] as unknown as T
|
|
|
+ const deletedItems = [] as unknown as T
|
|
|
+ const updateItems = [] as unknown as [T[number], T[number]][]
|
|
|
+ newItems = toRaw(newItems)
|
|
|
+ for (const newItem of newItems) {
|
|
|
+ const oldItem = oldItems.find(oldItem => newItem.id === oldItem.id)
|
|
|
+ if (!oldItem) {
|
|
|
+ storeSecurityPush(addedItems, newItem)
|
|
|
+ } else if (deepIsRevise(oldItem, newItem)) {
|
|
|
+ storeSecurityPush(updateItems, [newItem, oldItem] as any)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (const oldItem of oldItems) {
|
|
|
+ const newItem = newItems.find(newItem => newItem.id === oldItem.id)
|
|
|
+ if (!newItem) {
|
|
|
+ storeSecurityPush(deletedItems, oldItem)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ added: addedItems,
|
|
|
+ deleted: deletedItems,
|
|
|
+ updated: updateItems
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export const recoverStoreItems = <T extends Array<{ id: any }>>(items: Ref<T>, getBackupItems: () => T) => () => {
|
|
|
+ const backupItems = getBackupItems()
|
|
|
+ items.value = backupItems.map(oldItem => {
|
|
|
+ const model = items.value.find(item => item.id === oldItem.id)
|
|
|
+ return model ? Object.assign(model, oldItem) : oldItem
|
|
|
+ }) as T
|
|
|
+}
|