store-help.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. import { Ref, toRaw } from 'vue'
  2. import { deepIsRevise } from './diff'
  3. export const storeSecurityPush = <T extends any>(items: T[], pushItem: T) => {
  4. const index = items.indexOf(pushItem)
  5. if (!~index) {
  6. items.push(pushItem)
  7. return true
  8. } else {
  9. return false
  10. }
  11. }
  12. export const storeSecurityDelete = <T extends any>(items: T[], pushItem: T) => {
  13. const index = items.indexOf(pushItem)
  14. if (~index) {
  15. items.splice(index, 1)
  16. return true
  17. } else {
  18. return false
  19. }
  20. }
  21. export function addStoreItem <T extends {id: any}>(
  22. items: Ref<T[]>,
  23. addAction: (item: T) => Promise<T>,
  24. ): (item: T) => Promise<T>
  25. export function addStoreItem <T extends {id: any}, K extends {id: any} = T>(
  26. items: Ref<T[]>,
  27. addAction: (item: K) => Promise<K>,
  28. transform: (item: T) => Promise<K> | K
  29. ): (item: T) => Promise<K>
  30. export function addStoreItem <T extends {id: any}, K extends {id: any} = T>(
  31. items: Ref<T[]>,
  32. addAction: (item: K) => Promise<K>,
  33. transform?: (item: T) => Promise<K> | K
  34. ) {
  35. return async (item: T) => {
  36. let actionData: K
  37. if (transform) {
  38. actionData = await transform(item)
  39. } else {
  40. actionData = item as unknown as K
  41. }
  42. const newItem = await addAction(actionData)
  43. const self = items.value.find(findItem => findItem.id === item.id)
  44. if (self) {
  45. Object.assign(self, newItem)
  46. } else {
  47. storeSecurityPush(items.value, item)
  48. }
  49. return newItem
  50. }
  51. }
  52. export function updateStoreItem <T extends {id: any}>(
  53. items: Ref<T[]>,
  54. updateAction: (item: T, oldItem: T) => Promise<any>,
  55. ): (item: T, oldItem: T) => Promise<void>
  56. export function updateStoreItem <T extends {id: any}, K extends {id: any} = T>(
  57. items: Ref<T[]>,
  58. updateAction: (item: K, oldItem: T) => Promise<any>,
  59. transform: (item: T) => Promise<K> | K
  60. ): (item: T, oldItem: T) => Promise<void>
  61. export function updateStoreItem <T extends {id: any}, K extends {id: any} = T>(
  62. items: Ref<T[]>,
  63. updateAction: (item: K, oldItem: T) => Promise<any>,
  64. transform?: (item: T) => Promise<K> | K
  65. ) {
  66. return async (item: T, oldItem: T) => {
  67. let actionData: K
  68. if (transform) {
  69. actionData = await transform(item)
  70. } else {
  71. actionData = item as unknown as K
  72. }
  73. await updateAction(actionData, oldItem)
  74. const storeItem = items.value.find(atom => atom.id === item.id)
  75. if (storeItem) {
  76. Object.assign(storeItem, item)
  77. }
  78. }
  79. }
  80. export function deleteStoreItem <T extends {id: any}>(
  81. items: Ref<T[]>,
  82. deleteAction: (item: T) => Promise<any>,
  83. ): (item: T) => Promise<void>
  84. export function deleteStoreItem <T extends {id: any}, K extends {id: any} = T>(
  85. items: Ref<T[]>,
  86. deleteAction: (item: K) => Promise<any>,
  87. transform: (item: T) => Promise<K> | K
  88. ): (item: T) => Promise<void>
  89. export function deleteStoreItem <T extends {id: any}, K extends {id: any} = T>(
  90. items: Ref<T[]>,
  91. deleteAction: (item: K) => Promise<any>,
  92. transform?: (item: T) => Promise<K> | K
  93. ) {
  94. return async (item: T) => {
  95. let actionData: K
  96. if (transform) {
  97. actionData = await transform(item)
  98. } else {
  99. actionData = item as unknown as K
  100. }
  101. await deleteAction(actionData)
  102. storeSecurityDelete(items.value, item)
  103. }
  104. }
  105. export function fetchStoreItems <T extends {id: any}, K extends {id: any} = T>(
  106. items: Ref<T[]>,
  107. fetchAction: () => Promise<T[]>,
  108. callback: (() => void) | null,
  109. ): () => Promise<void>
  110. export function fetchStoreItems <T extends {id: any}, K extends {id: any} = T>(
  111. items: Ref<T[]>,
  112. fetchAction: () => Promise<K[]>,
  113. callback: (() => void) | null,
  114. transform: (items: K[]) => Promise<T[]> | T[],
  115. ): () => Promise<void>
  116. export function fetchStoreItems <T extends {id: any}, K extends {id: any} = T>(
  117. items: Ref<T[]>,
  118. fetchAction: () => Promise<K[]>,
  119. callback: (() => void) | null,
  120. transform?: (items: K[]) => Promise<T[]> | T[],
  121. ) {
  122. return async () => {
  123. const fetchItems = await fetchAction()
  124. let actionData: T[]
  125. if (transform) {
  126. actionData = await transform(fetchItems)
  127. } else {
  128. actionData = fetchItems as unknown as T[]
  129. }
  130. items.value = actionData
  131. callback && callback()
  132. }
  133. }
  134. export const saveStoreItems = <T extends {id: any}>(
  135. newItems: Ref<T[]>,
  136. getOldItem: () => T[],
  137. actions: {
  138. add?: ReturnType<typeof addStoreItem<T>>,
  139. update?: ReturnType<typeof updateStoreItem<T>>,
  140. delete?: ReturnType<typeof deleteStoreItem<T>>,
  141. }
  142. ) => () => {
  143. const oldItems = getOldItem()
  144. const {
  145. deleted,
  146. updated,
  147. added
  148. } = diffStoreItemsChange(newItems.value, oldItems)
  149. const promiseAll: Promise<any>[] = []
  150. if (actions.delete) {
  151. for (const delItem of deleted) {
  152. promiseAll.push(actions.delete(delItem))
  153. }
  154. }
  155. if (actions.update) {
  156. for (const [newItem, oldItem] of updated) {
  157. promiseAll.push(actions.update(newItem, oldItem))
  158. }
  159. }
  160. if (actions.add) {
  161. for (const addItem of added) {
  162. promiseAll.push(actions.add(addItem))
  163. }
  164. }
  165. return Promise.all(promiseAll)
  166. }
  167. export const diffStoreItemsChange = <T extends Array<{ id: any }>>(newItems: T, oldItems: T) => {
  168. const addedItems = [] as unknown as T
  169. const deletedItems = [] as unknown as T
  170. const updateItems = [] as unknown as [T[number], T[number]][]
  171. newItems = toRaw(newItems)
  172. for (const newItem of newItems) {
  173. const oldItem = oldItems.find(oldItem => newItem.id === oldItem.id)
  174. if (!oldItem) {
  175. storeSecurityPush(addedItems, newItem)
  176. } else if (deepIsRevise(oldItem, newItem)) {
  177. storeSecurityPush(updateItems, [newItem, oldItem] as any)
  178. }
  179. }
  180. for (const oldItem of oldItems) {
  181. const newItem = newItems.find(newItem => newItem.id === oldItem.id)
  182. if (!newItem) {
  183. storeSecurityPush(deletedItems, oldItem)
  184. }
  185. }
  186. return {
  187. added: addedItems,
  188. deleted: deletedItems,
  189. updated: updateItems
  190. }
  191. }
  192. export const recoverStoreItems = <T extends Array<{ id: any }>>(items: Ref<T>, getBackupItems: () => T) => () => {
  193. const backupItems = getBackupItems()
  194. items.value = backupItems.map(oldItem => {
  195. const model = items.value.find(item => item.id === oldItem.id)
  196. console.log("===>", model, oldItem)
  197. return model ? Object.assign(model, oldItem) : oldItem
  198. }) as T
  199. }