| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- import { onUnmounted } from 'vue';
- import html2canvas from 'html2canvas'
- import { getUUID, httpErrorHandle, fetchRouteParamsLocation, base64toFile } from '@/utils'
- import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
- import { EditCanvasTypeEnum, ChartEditStoreEnum, ProjectInfoEnum, ChartEditStorage } from '@/store/modules/chartEditStore/chartEditStore.d'
- import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
- import { StylesSetting } from '@/components/Pages/ChartItemSetting'
- import { useSystemStore } from '@/store/modules/systemStore/systemStore'
- import { fetchChartComponent, fetchConfigComponent, createComponent } from '@/packages/index'
- import { saveInterval } from '@/settings/designSetting'
- import throttle from 'lodash/throttle'
- // 接口状态
- import { ResultEnum } from '@/enums/httpEnum'
- // 接口
- import { saveProjectApi, fetchProjectApi, uploadFile, updateProjectApi } from '@/api/path'
- // 画布枚举
- import { SyncEnum } from '@/enums/editPageEnum'
- import { BaseEvent, EventLife, CreateComponentType, CreateComponentGroupType, ConfigType } from '@/packages/index.d'
- import { PublicGroupConfigClass } from '@/packages/public/publicConfig'
- import merge from 'lodash/merge'
- /**
- * * 画布-版本升级对旧数据无法兼容的补丁
- * @param object
- */
- const canvasVersionUpdatePolyfill = (object: any) => {
- return object
- }
- /**
- * * 组件-版本升级对旧数据无法兼容的补丁
- * @param newObject
- * @param sources
- */
- const componentVersionUpdatePolyfill = (newObject: any, sources: any) => {
- try {
- // 判断是否是组件
- if (sources.id) {
- // 处理事件补丁
- const hasVnodeBeforeMount = 'vnodeBeforeMount' in sources.events
- const hasVnodeMounted = 'vnodeMounted' in sources.events
- if (hasVnodeBeforeMount) {
- newObject.events.advancedEvents.vnodeBeforeMount = sources?.events.vnodeBeforeMount
- }
- if (hasVnodeMounted) {
- newObject.events.advancedEvents.vnodeMounted = sources?.events.vnodeMounted
- }
- if (hasVnodeBeforeMount || hasVnodeMounted) {
- sources.events = {
- baseEvent: {
- [BaseEvent.ON_CLICK]: undefined,
- [BaseEvent.ON_DBL_CLICK]: undefined,
- [BaseEvent.ON_MOUSE_ENTER]: undefined,
- [BaseEvent.ON_MOUSE_LEAVE]: undefined
- },
- advancedEvents: {
- [EventLife.VNODE_MOUNTED]: undefined,
- [EventLife.VNODE_BEFORE_MOUNT]: undefined
- }
- }
- }
- return newObject
- }
- } catch (error) {
- return newObject
- }
- }
- /**
- * * 合并处理
- * @param newObject 新的模板数据
- * @param sources 新拿到的数据
- * @returns object
- */
- const componentMerge = (newObject: any, sources: any, notComponent = false) => {
- // 处理组件补丁
- componentVersionUpdatePolyfill(newObject, sources)
- // 非组件不处理
- if (notComponent) return merge(newObject, sources)
- // 组件排除 newObject
- const option = sources.option
- if (!option) return merge(newObject, sources)
- // 为 undefined 的 sources 来源对象属性将被跳过详见 https://www.lodashjs.com/docs/lodash.merge
- sources.option = undefined
- if (option) {
- return {
- ...merge(newObject, sources),
- option: option
- }
- }
- }
- // 请求处理
- export const useSync = () => {
- const chartEditStore = useChartEditStore()
- const chartHistoryStore = useChartHistoryStore()
- const systemStore = useSystemStore()
- /**
- * * 组件动态注册
- * @param projectData 项目数据
- * @param isReplace 是否替换数据
- * @returns
- */
- const updateComponent = async (projectData: ChartEditStorage, isReplace = false, changeId = false) => {
- if (isReplace) {
- // 清除列表
- chartEditStore.componentList = []
- // 清除历史记录
- chartHistoryStore.clearBackStack()
- chartHistoryStore.clearForwardStack()
- }
- // 画布补丁处理
- projectData.editCanvasConfig = canvasVersionUpdatePolyfill(projectData.editCanvasConfig)
- // 列表组件注册
- projectData.componentList.forEach(async (e: CreateComponentType | CreateComponentGroupType) => {
- const intComponent = (target: CreateComponentType) => {
- if (!window['$vue'].component(target.chartConfig.chartKey)) {
- window['$vue'].component(target.chartConfig.chartKey, fetchChartComponent(target.chartConfig))
- window['$vue'].component(target.chartConfig.conKey, fetchConfigComponent(target.chartConfig))
- }
- }
- if (e.isGroup) {
- (e as CreateComponentGroupType).groupList.forEach(groupItem => {
- intComponent(groupItem)
- })
- } else {
- intComponent(e as CreateComponentType)
- }
- })
- // 创建函数-重新创建是为了处理类种方法消失的问题
- const create = async (
- _componentInstance: CreateComponentType,
- callBack?: (componentInstance: CreateComponentType) => void
- ) => {
- // 补充 class 上的方法
- let newComponent: CreateComponentType = await createComponent(_componentInstance.chartConfig)
- if (callBack) {
- if (changeId) {
- callBack(componentMerge(newComponent, { ..._componentInstance, id: getUUID() }))
- } else {
- callBack(componentMerge(newComponent, _componentInstance))
- }
- } else {
- if (changeId) {
- chartEditStore.addComponentList(
- componentMerge(newComponent, { ..._componentInstance, id: getUUID() }),
- false,
- true
- )
- } else {
- chartEditStore.addComponentList(componentMerge(newComponent, _componentInstance), false, true)
- }
- }
- }
- // 数据赋值
- for (const key in projectData) {
- // 组件
- if (key === ChartEditStoreEnum.COMPONENT_LIST) {
- for (const comItem of projectData[key]) {
- if (comItem.isGroup) {
- // 创建分组
- let groupClass = new PublicGroupConfigClass()
- if (changeId) {
- groupClass = componentMerge(groupClass, { ...comItem, id: getUUID() })
- } else {
- groupClass = componentMerge(groupClass, comItem)
- }
- // 异步注册子应用
- const targetList: CreateComponentType[] = []
- for (const groupItem of (comItem as CreateComponentGroupType).groupList) {
- await create(groupItem, e => {
- targetList.push(e)
- })
- }
- groupClass.groupList = targetList
- // 分组插入到列表
- chartEditStore.addComponentList(groupClass, false, true)
- } else {
- await create(comItem as CreateComponentType)
- }
- }
- } else {
- // 非组件(顺便排除脏数据)
- if (key !== 'editCanvasConfig' && key !== 'requestGlobalConfig') return
- componentMerge(chartEditStore[key], projectData[key], true)
- }
- }
- }
- /**
- * * 赋值全局数据
- * @param projectData 项目数据
- * @returns
- */
- const updateStoreInfo = (projectData: {
- id: string,
- projectName: string,
- indexImage: string,
- remarks: string,
- state: number
- }) => {
- const { id, projectName, remarks, indexImage, state } = projectData
- // ID
- chartEditStore.setProjectInfo(ProjectInfoEnum.PROJECT_ID, id)
- // 名称
- chartEditStore.setProjectInfo(ProjectInfoEnum.PROJECT_NAME, projectName)
- // 描述
- chartEditStore.setProjectInfo(ProjectInfoEnum.REMARKS, remarks)
- // 缩略图
- chartEditStore.setProjectInfo(ProjectInfoEnum.THUMBNAIL, indexImage)
- // 发布
- chartEditStore.setProjectInfo(ProjectInfoEnum.RELEASE, state === 1)
- }
- // * 数据获取
- const dataSyncFetch = async () => {
- // FIX:重新执行dataSyncFetch需清空chartEditStore.componentList,否则会导致图层重复
- // 切换语言等操作会导致重新执行 dataSyncFetch,此时pinia中并未清空chartEditStore.componentList,导致图层重复
- chartEditStore.componentList = []
- chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.START)
- try {
- const res = await fetchProjectApi({ projectId: fetchRouteParamsLocation() })
- if (res && res.code === ResultEnum.SUCCESS) {
- if (res.data) {
- updateStoreInfo(res.data)
- // 更新全局数据
- await updateComponent(JSON.parse(res.data.content))
- return
- }else {
- chartEditStore.setProjectInfo(ProjectInfoEnum.PROJECT_ID, fetchRouteParamsLocation())
- }
- setTimeout(() => {
- chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.SUCCESS)
- }, 1000)
- return
- }
- chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.FAILURE)
- } catch (error) {
- chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.FAILURE)
- httpErrorHandle()
- }
- }
- // * 数据保存
- const dataSyncUpdate = throttle(async (updateImg = true) => {
- if(!fetchRouteParamsLocation()) return
- let projectId = chartEditStore.getProjectInfo[ProjectInfoEnum.PROJECT_ID];
- if(projectId === null || projectId === ''){
- window['$message'].error('数据初未始化成功,请刷新页面!')
- return
- }
- chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.START)
- // 异常处理:缩略图上传失败不影响JSON的保存
- try {
- if (updateImg) {
- // 获取缩略图片
- const range = document.querySelector('.go-edit-range') as HTMLElement
- // 生成图片
- const canvasImage: HTMLCanvasElement = await html2canvas(range, {
- backgroundColor: null,
- allowTaint: true,
- useCORS: true
- })
- // 上传预览图
- let uploadParams = new FormData()
- uploadParams.append('object', base64toFile(canvasImage.toDataURL(), `${fetchRouteParamsLocation()}_index_preview.png`))
- const uploadRes = await uploadFile(uploadParams)
- // 保存预览图
- if(uploadRes && uploadRes.code === ResultEnum.SUCCESS) {
- await updateProjectApi({
- id: fetchRouteParamsLocation(),
- indexImage: `${systemStore.getFetchInfo.OSSUrl}${uploadRes.data.fileName}`
- })
- }
- }
- } catch (e) {
- console.log(e)
- }
- // 保存数据
- let params = new FormData()
- params.append('projectId', projectId)
- params.append('content', JSON.stringify(chartEditStore.getStorageInfo || {}))
- const res= await saveProjectApi(params)
- if (res && res.code === ResultEnum.SUCCESS) {
- // 成功状态
- setTimeout(() => {
- chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.SUCCESS)
- }, 1000)
- return
- }
- // 失败状态
- chartEditStore.setEditCanvas(EditCanvasTypeEnum.SAVE_STATUS, SyncEnum.FAILURE)
- }, 3000)
- // * 定时处理
- const intervalDataSyncUpdate = () => {
- // 定时获取数据
- const syncTiming = setInterval(() => {
- dataSyncUpdate()
- }, saveInterval * 1000)
- // 销毁
- onUnmounted(() => {
- clearInterval(syncTiming)
- })
- }
- return {
- updateComponent,
- updateStoreInfo,
- dataSyncFetch,
- dataSyncUpdate,
- intervalDataSyncUpdate
- }
- }
|