useSync.hook.ts 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. import { onUnmounted } from 'vue';
  2. import html2canvas from 'html2canvas'
  3. import { getUUID, httpErrorHandle, fetchRouteParamsLocation, base64toFile } from '@/utils'
  4. import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
  5. import { EditCanvasTypeEnum, ChartEditStoreEnum, ProjectInfoEnum, ChartEditStorage } from '@/store/modules/chartEditStore/chartEditStore.d'
  6. import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
  7. import { useSystemStore } from '@/store/modules/systemStore/systemStore'
  8. import { fetchChartComponent, fetchConfigComponent, createComponent } from '@/packages/index'
  9. import { saveInterval } from '@/settings/designSetting'
  10. import throttle from 'lodash/throttle'
  11. // 接口状态
  12. import { ResultEnum } from '@/enums/httpEnum'
  13. // 接口
  14. import { saveProjectApi, fetchProjectApi, uploadFile, updateProjectApi } from '@/api/path'
  15. // 画布枚举
  16. import { SyncEnum } from '@/enums/editPageEnum'
  17. import { CreateComponentType, CreateComponentGroupType, ConfigType } from '@/packages/index.d'
  18. import { PublicGroupConfigClass } from '@/packages/public/publicConfig'
  19. // 请求处理
  20. export const useSync = () => {
  21. const chartEditStore = useChartEditStore()
  22. const chartHistoryStore = useChartHistoryStore()
  23. const systemStore = useSystemStore()
  24. /**
  25. * * 组件动态注册
  26. * @param projectData 项目数据
  27. * @param isReplace 是否替换数据
  28. * @returns
  29. */
  30. const updateComponent = async (projectData: ChartEditStorage, isReplace = false, changeId = false) => {
  31. if (isReplace) {
  32. // 清除列表
  33. chartEditStore.componentList = []
  34. // 清除历史记录
  35. chartHistoryStore.clearBackStack()
  36. chartHistoryStore.clearForwardStack()
  37. }
  38. // 列表组件注册
  39. projectData.componentList.forEach(async (e: CreateComponentType | CreateComponentGroupType) => {
  40. const intComponent = (target: CreateComponentType) => {
  41. if (!window['$vue'].component(target.chartConfig.chartKey)) {
  42. window['$vue'].component(target.chartConfig.chartKey, fetchChartComponent(target.chartConfig))
  43. window['$vue'].component(target.chartConfig.conKey, fetchConfigComponent(target.chartConfig))
  44. }
  45. }
  46. if (e.isGroup) {
  47. ;(e as CreateComponentGroupType).groupList.forEach(groupItem => {
  48. intComponent(groupItem)
  49. })
  50. } else {
  51. intComponent(e as CreateComponentType)
  52. }
  53. })
  54. // 数据赋值
  55. for (const key in projectData) {
  56. // 组件
  57. if (key === ChartEditStoreEnum.COMPONENT_LIST) {
  58. for (const comItem of projectData[key]) {
  59. // 重新创建是为了处理类种方法消失的问题
  60. const create = async (
  61. _componentInstance: CreateComponentType,
  62. callBack?: (componentInstance: CreateComponentType) => void
  63. ) => {
  64. // 补充 class 上的方法
  65. let newComponent: CreateComponentType = await createComponent(_componentInstance.chartConfig)
  66. if (callBack) {
  67. if (changeId) {
  68. callBack(Object.assign(newComponent, { ..._componentInstance, id: getUUID() }))
  69. } else {
  70. callBack(Object.assign(newComponent, _componentInstance))
  71. }
  72. } else {
  73. if (changeId) {
  74. chartEditStore.addComponentList(
  75. Object.assign(newComponent, { ..._componentInstance, id: getUUID() }),
  76. false,
  77. true
  78. )
  79. } else {
  80. chartEditStore.addComponentList(Object.assign(newComponent, _componentInstance), false, true)
  81. }
  82. }
  83. }
  84. if (comItem.isGroup) {
  85. // 创建分组
  86. let groupClass = new PublicGroupConfigClass()
  87. if (changeId) {
  88. groupClass = Object.assign(groupClass, { ...comItem, id: getUUID() })
  89. } else {
  90. groupClass = Object.assign(groupClass, comItem)
  91. }
  92. // 注册子应用
  93. const targetList: CreateComponentType[] = []
  94. ;(comItem as CreateComponentGroupType).groupList.forEach(groupItem => {
  95. create(groupItem, e => {
  96. targetList.push(e)
  97. })
  98. })
  99. groupClass.groupList = targetList
  100. // 分组插入到列表
  101. chartEditStore.addComponentList(groupClass, false, true)
  102. } else {
  103. create(comItem as CreateComponentType)
  104. }
  105. }
  106. } else {
  107. // 非组件(顺便排除脏数据)
  108. if (key !== 'editCanvasConfig' && key !== 'requestGlobalConfig') return
  109. Object.assign(chartEditStore[key], projectData[key])
  110. }
  111. }
  112. }
  113. /**
  114. * * 赋值全局数据
  115. * @param projectData 项目数据
  116. * @returns
  117. */
  118. const updateStoreInfo = (projectData: {
  119. id: string,
  120. projectName: string,
  121. indexImage: string,
  122. remarks: string,
  123. state: number
  124. }) => {
  125. const { projectName, remarks, indexImage, state } = projectData
  126. // 名称
  127. chartEditStore.setProjectInfo(ProjectInfoEnum.PROJECT_NAME, projectName)
  128. // 描述
  129. chartEditStore.setProjectInfo(ProjectInfoEnum.REMARKS, remarks)
  130. // 缩略图
  131. chartEditStore.setProjectInfo(ProjectInfoEnum.THUMBNAIL, indexImage)
  132. // 发布
  133. chartEditStore.setProjectInfo(ProjectInfoEnum.RELEASE, state === 1)
  134. }
  135. // * 数据获取
  136. const dataSyncFetch = async () => {
  137. chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.START)
  138. try {
  139. const res = await fetchProjectApi({ projectId: fetchRouteParamsLocation() }) as unknown as MyResponseType
  140. if (res.code === ResultEnum.SUCCESS) {
  141. if (res.data) {
  142. updateStoreInfo(res.data)
  143. // 更新全局数据
  144. await updateComponent(JSON.parse(res.data.content))
  145. return
  146. }
  147. setTimeout(() => {
  148. chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.SUCCESS)
  149. }, 1000)
  150. return
  151. }
  152. chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.FAILURE)
  153. } catch (error) {
  154. chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.FAILURE)
  155. httpErrorHandle()
  156. }
  157. }
  158. // * 数据保存
  159. const dataSyncUpdate = throttle(async () => {
  160. if(!fetchRouteParamsLocation()) return
  161. if(!systemStore.getFetchInfo.OSSUrl) {
  162. window['$message'].error('数据保存失败,请刷新页面重试!')
  163. return
  164. }
  165. chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.START)
  166. // 获取缩略图片
  167. const range = document.querySelector('.go-edit-range') as HTMLElement
  168. // 生成图片
  169. const canvasImage: HTMLCanvasElement = await html2canvas(range, {
  170. backgroundColor: null,
  171. allowTaint: true,
  172. useCORS: true
  173. })
  174. // 上传预览图
  175. let uploadParams = new FormData()
  176. uploadParams.append('object', base64toFile(canvasImage.toDataURL(), `${fetchRouteParamsLocation()}_index_preview.png`))
  177. const uploadRes = await uploadFile(systemStore.getFetchInfo.OSSUrl, uploadParams) as unknown as MyResponseType
  178. // 保存预览图
  179. if(uploadRes.code === ResultEnum.SUCCESS) {
  180. await updateProjectApi({
  181. id: fetchRouteParamsLocation(),
  182. indexImage: uploadRes.data.objectContent.httpRequest.uri
  183. })
  184. }
  185. // 保存数据
  186. let params = new FormData()
  187. params.append('projectId', fetchRouteParamsLocation())
  188. params.append('content', JSON.stringify(chartEditStore.getStorageInfo || {}))
  189. const res= await saveProjectApi(params) as unknown as MyResponseType
  190. if (res.code === ResultEnum.SUCCESS) {
  191. // 成功状态
  192. setTimeout(() => {
  193. chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.SUCCESS)
  194. }, 1000)
  195. return
  196. }
  197. // 失败状态
  198. chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.FAILURE)
  199. }, 3000)
  200. // * 定时处理
  201. const intervalDataSyncUpdate = () => {
  202. // 定时获取数据
  203. const syncTiming = setInterval(() => {
  204. dataSyncUpdate()
  205. }, saveInterval * 1000)
  206. // 销毁
  207. onUnmounted(() => {
  208. clearInterval(syncTiming)
  209. })
  210. }
  211. return {
  212. updateComponent,
  213. updateStoreInfo,
  214. dataSyncFetch,
  215. dataSyncUpdate,
  216. intervalDataSyncUpdate
  217. }
  218. }