diff --git a/frontend/src/data-visualization/store/modules/app.ts b/frontend/src/data-visualization/store/modules/app.ts index 9b15c1f..566a3fd 100644 --- a/frontend/src/data-visualization/store/modules/app.ts +++ b/frontend/src/data-visualization/store/modules/app.ts @@ -2,6 +2,7 @@ import { defineStore } from 'pinia' import { store } from '../index' import { useCache } from '@/data-visualization/hooks/web/useCache' const { wsCache } = useCache() +// import { modelApi } from '@/api/login' interface AppState { size: boolean pageLoading: boolean @@ -54,7 +55,10 @@ export const useAppStore = defineStore('app', { }, actions: { async setAppModel() { - + // const res = await modelApi() + // const data = res.data + // this.desktop = data + // wsCache.set('app.desktop', this.desktop) }, setSize(size: boolean) { this.size = size diff --git a/frontend/src/data-visualization/store/modules/appearance.ts b/frontend/src/data-visualization/store/modules/appearance.ts index 8a2a904..c1c0e9f 100644 --- a/frontend/src/data-visualization/store/modules/appearance.ts +++ b/frontend/src/data-visualization/store/modules/appearance.ts @@ -1,6 +1,15 @@ import { defineStore } from 'pinia' import { store } from '@/data-visualization/store/index' -const basePath = import.meta.env.VITE_API_BASE_URL +// import { defaultFont, list } from '@/api/font' +// import { uiLoadApi } from '@/api/login' +// import { useCache } from '@/hooks/web/useCache' +// import colorFunctions from 'less/lib/less/functions/color.js' +// import colorTree from 'less/lib/less/tree/color.js' +// import { useEmbedded } from '@/store/modules/embedded' +// import { setTitle } from '@/utils/utils' + +// const embeddedStore = useEmbedded() +const basePath = import.meta.env.VITE_API_BASEPATH const baseUrl = basePath + '/appearance/image/' import { isBtnShow } from '@/data-visualization/utils/utils' interface AppearanceState { @@ -28,6 +37,7 @@ interface AppearanceState { community: boolean fontList: Array<{ name: string; id: string; isDefault: boolean }> } +// const { wsCache } = useCache() export const useAppearanceStore = defineStore('appearanceStore', { state: (): AppearanceState => { return { @@ -150,10 +160,29 @@ export const useAppearanceStore = defineStore('appearanceStore', { this.mobileLogin = data }, async setFontList() { - + const res = await list() + this.fontList = res || [] }, setCurrentFont(name) { - + // const currentFont = this.fontList.find(ele => ele.name === name) + // if (currentFont) { + // let fontStyleElement = document.querySelector(`#de-custom_font${name}`) + // if (!fontStyleElement) { + // fontStyleElement = document.createElement('style') + // fontStyleElement.setAttribute('id', `de-custom_font${name}`) + // document.querySelector('head').appendChild(fontStyleElement) + // } + // fontStyleElement.innerHTML = `@font-face { + // font-family: '${name}'; + // src: url(${ + // embeddedStore.baseUrl + // ? (embeddedStore.baseUrl + basePath).replace('/./', '/') + // : basePath + // }/typeface/download/${currentFont.fileTransName}); + // font-weight: normal; + // font-style: normal; + // }` + // } }, setMobileLoginBg(data: string) { this.mobileLoginBg = data @@ -173,6 +202,137 @@ export const useAppearanceStore = defineStore('appearanceStore', { setLoaded(data: boolean) { this.loaded = data }, + // async setAppearance(isDataEaseBi?: boolean) { + // const desktop = wsCache.get('app.desktop') + // if (desktop) { + // this.loaded = true + // this.community = true + // } + // if (this.loaded) { + // return + // } + // defaultFont().then(res => { + // const [font] = res || [] + // setDefaultFont( + // `${ + // embeddedStore.baseUrl + // ? (embeddedStore.baseUrl + basePath).replace('/./', '/') + // : basePath + // }/typeface/download/${font?.fileTransName}`, + // font?.name, + // font?.fileTransName + // ) + // function setDefaultFont(url, name, fileTransName) { + // let fontStyleElement = document.querySelector('#de-custom_font') + // if (!fontStyleElement) { + // fontStyleElement = document.createElement('style') + // fontStyleElement.setAttribute('id', 'de-custom_font') + // document.querySelector('head').appendChild(fontStyleElement) + // } + // fontStyleElement.innerHTML = + // name && fileTransName + // ? `@font-face { + // font-family: '${name}'; + // src: url(${url}); + // font-weight: normal; + // font-style: normal; + // }` + // : '' + // document.documentElement.style.setProperty('--de-custom_font', `${name}`) + // document.documentElement.style.setProperty('--van-base-font', `${name}`) + // } + // }) + // if (!isDataEaseBi) { + // document.title = '' + // } + // const res = await uiLoadApi() + // this.loaded = true + // const resData = res.data + // if (!resData?.length) { + // if (!isDataEaseBi) { + // document.title = 'DataEase' + // setLinkIcon() + // } + // return + // } + // const data: AppearanceState = { loaded: false, community: true } + // let isCommunity = false + // resData.forEach(item => { + // data[item.pkey] = item.pval + // if (item.pkey === 'community') { + // isCommunity = true + // } + // }) + // data.community = isCommunity + // this.community = data.community + // if (this.community) { + // this.showDemoTips = data.showDemoTips + // this.demoTipsContent = data.demoTipsContent + // this.loaded = true + // setLinkIcon() + // return + // } + // this.navigate = data.navigate + // this.mobileLogin = data.mobileLogin + // this.mobileLoginBg = data.mobileLoginBg + // this.help = data.help + // this.showAi = data.showAi + // this.showCopilot = data.showCopilot + // this.showDoc = data.showDoc + // this.showAbout = data.showAbout + // this.navigateBg = data.navigateBg + // this.themeColor = data.themeColor + // this.customColor = data.customColor + // if (this.themeColor === 'custom' && this.customColor) { + // document.documentElement.style.setProperty('--ed-color-primary', this.customColor) + // document.documentElement.style.setProperty('--van-blue', this.customColor) + // document.documentElement.style.setProperty( + // '--ed-color-primary-light-5', + // colorFunctions + // .mix(new colorTree('ffffff'), new colorTree(this.customColor.substr(1)), { value: 40 }) + // .toRGB() + // ) + // document.documentElement.style.setProperty( + // '--ed-color-primary-light-3', + // colorFunctions + // .mix(new colorTree('ffffff'), new colorTree(this.customColor.substr(1)), { value: 15 }) + // .toRGB() + // ) + // document.documentElement.style.setProperty('--ed-color-primary-1a', `${this.customColor}1a`) + // document.documentElement.style.setProperty('--ed-color-primary-33', `${this.customColor}33`) + // document.documentElement.style.setProperty('--ed-color-primary-99', `${this.customColor}99`) + // document.documentElement.style.setProperty( + // '--ed-color-primary-dark-2', + // colorFunctions + // .mix(new colorTree('000000'), new colorTree(this.customColor.substr(1)), { value: 15 }) + // .toRGB() + // ) + // } else if (document.documentElement.style.getPropertyValue('--ed-color-primary')) { + // document.documentElement.style.setProperty('--ed-color-primary', '#3370FF') + // document.documentElement.style.removeProperty('--ed-color-primary-light-3') + // document.documentElement.style.removeProperty('--ed-color-primary-light-5') + // document.documentElement.style.removeProperty('--ed-color-primary-1a') + // document.documentElement.style.removeProperty('--ed-color-primary-33') + // document.documentElement.style.removeProperty('--ed-color-primary-99') + // document.documentElement.style.removeProperty('--ed-color-primary-dark-2') + // } + // this.bg = data.bg + // this.login = data.login + // this.slogan = data.slogan + // this.web = data.web + // this.name = data.name + // this.foot = data.foot + // this.footContent = data.footContent + // if (isDataEaseBi) return + // if (this.name) { + // document.title = this.name + // setTitle(this.name) + // } else { + // document.title = 'DataEase' + // setTitle('DataEase') + // } + // setLinkIcon(this.web) + // } } }) diff --git a/frontend/src/data-visualization/store/modules/data-visualization/compose.ts b/frontend/src/data-visualization/store/modules/data-visualization/compose.ts index c7e9225..f54a4d1 100644 --- a/frontend/src/data-visualization/store/modules/data-visualization/compose.ts +++ b/frontend/src/data-visualization/store/modules/data-visualization/compose.ts @@ -230,6 +230,7 @@ export const composeStore = defineStore('compose', { const editorRect = editor.getBoundingClientRect() const isInTab = isTabCanvas(canvasId) let decomposeComponentData = componentData.value + let parentGroupStyle = null if (isInTab) { const pathMap = {} componentData.value.forEach(componentItem => { @@ -242,10 +243,11 @@ export const composeStore = defineStore('compose', { if (pComponentTarget && pComponentTarget.length > 0) { decomposeComponentData = pComponentTarget[0].componentData } + parentGroupStyle = curComponent.value.groupStyle } dvMainStore.deleteComponentById(curComponent.value.id, decomposeComponentData) components.forEach(component => { - decomposeComponent(component, editorRect, parentStyle, canvasId) + decomposeComponent(component, editorRect, parentStyle, canvasId, parentGroupStyle) dvMainStore.addComponent({ component: component, index: undefined, diff --git a/frontend/src/data-visualization/store/modules/data-visualization/copy.ts b/frontend/src/data-visualization/store/modules/data-visualization/copy.ts index 9a41927..f21cc65 100644 --- a/frontend/src/data-visualization/store/modules/data-visualization/copy.ts +++ b/frontend/src/data-visualization/store/modules/data-visualization/copy.ts @@ -40,11 +40,12 @@ export const copyStore = defineStore('copy', { canvasViewInfoPreview, outerMultiplexingComponents = curMultiplexingComponents.value, keepSize = false, - copyFrom = 'multiplexing' + copyFrom = 'multiplexing', + multiplexingScale = canvasStyleData.value?.scale ) { // eslint-disable-next-line @typescript-eslint/no-this-alias const _this = this - const { width, height, scale } = canvasStyleData.value + const { scale } = canvasStyleData.value Object.keys(outerMultiplexingComponents).forEach(function (componentId, index) { const newComponent = deepCopy(outerMultiplexingComponents[componentId]) newComponent.canvasId = 'canvas-main' @@ -53,13 +54,15 @@ export const copyStore = defineStore('copy', { } else { // dashboard 平铺2个 const xPositionOffset = index % 2 - const yPositionOffset = index % 2 if (!(copyFrom === 'multiplexing' && !multiplexingStyleAdapt.value)) { newComponent.sizeX = pcMatrixCount.value.x / 2 newComponent.sizeY = 14 // dataV 数据大屏 newComponent.style.width = ((canvasStyleData.value.width / 3) * scale) / 100 newComponent.style.height = ((canvasStyleData.value.height / 3) * scale) / 100 + } else { + newComponent.style.width = (newComponent.style.width * scale) / multiplexingScale + newComponent.style.height = (newComponent.style.height * scale) / multiplexingScale } // dataV 数据大屏 newComponent.x = newComponent.sizeX * xPositionOffset + 1 @@ -197,6 +200,9 @@ export function deepCopyTabItemHelper(newCanvasId, tabComponentData, idMap) { function deepCopyHelper(data, idMap) { const result = deepCopy(data) + if (result.freeze) { + result.freeze = false + } const newComponentId = generateID() idMap[data.id] = newComponentId result.id = newComponentId diff --git a/frontend/src/data-visualization/store/modules/data-visualization/dvMain.ts b/frontend/src/data-visualization/store/modules/data-visualization/dvMain.ts index 557cd77..793a3c9 100644 --- a/frontend/src/data-visualization/store/modules/data-visualization/dvMain.ts +++ b/frontend/src/data-visualization/store/modules/data-visualization/dvMain.ts @@ -12,6 +12,7 @@ import { DEFAULT_CANVAS_STYLE_DATA_LIGHT, DEFAULT_CANVAS_STYLE_DATA_SCREEN_DARK } from '@/data-visualization/chart/components/editor/util/dataVisualization' +import { useEmitt } from '@/data-visualization/hooks/web/useEmitt' import chartViewManager from '@/data-visualization/chart/components/js/panel' import { COMMON_COMPONENT_BACKGROUND_DARK, @@ -20,8 +21,13 @@ import { findBaseDeFaultAttr } from '@/data-visualization/custom-component/component-list' import { get, set } from 'lodash-es' +import { viewFieldTimeTrans } from '@/data-visualization/utils/viewUtils' +import { useAppearanceStoreWithOut } from '@/data-visualization/store/modules/appearance' +import { ElMessage } from 'element-plus-secondary' import { useI18n } from '@/data-visualization/hooks/web/useI18n' +import { filterEnumParams } from '@/data-visualization/utils/componentUtils' const { t } = useI18n() + export const dvMainStore = defineStore('dataVisualization', { state: () => { return { @@ -193,7 +199,8 @@ export const dvMainStore = defineStore('dataVisualization', { multiplexingStyleAdapt: true, //复用样式跟随主题 mainScrollTop: 0, //主画布运动量 isIframe: false, // 当前是否在iframe中 - isPopWindow: false // 当前是否在iframe弹框中 + isPopWindow: false, // 当前是否在iframe弹框中 + viewPageInfo: {} //表格分页信息 } }, actions: { @@ -333,6 +340,12 @@ export const dvMainStore = defineStore('dataVisualization', { } } // 移动端通知 + if (this.mobileInPc) { + useEmitt().emitter.emit('curComponentChange', { + type: 'curComponentChange', + value: this.curComponent ? JSON.parse(JSON.stringify(this.curComponent)) : null + }) + } }, setBashMatrixInfo(bashMatrixInfo) { this.bashMatrixInfo = bashMatrixInfo @@ -435,6 +448,91 @@ export const dvMainStore = defineStore('dataVisualization', { }, addComponent({ component, index, isFromGroup = false, componentData = this.componentData }) { + if (isFromGroup) { + componentData.push(component) + return + } + if (index !== undefined) { + componentData.splice(index, 0, component) + this.setCurComponent({ component: component, index: index }) + } else { + componentData.push(component) + this.setCurComponent({ component: component, index: componentData.length - 1 }) + } + const currentFont = useAppearanceStoreWithOut().fontList.find(ele => ele.isDefault) + //如果当前的组件是UserView 图表,则想canvasView中增加一项 UserView ID 和componentID保持一致 + if (component.component === 'UserView') { + const defaultConfig = JSON.parse(JSON.stringify(BASE_VIEW_CONFIG)) + if (component.innerType === 'bar-range') { + defaultConfig.customStyle.xAxis.axisLine.show = false + defaultConfig.customStyle.xAxis.splitLine.show = true + defaultConfig.customStyle.yAxis.axisLine.show = true + defaultConfig.customStyle.yAxis.splitLine.show = false + } + let newView = { + ...defaultConfig, + id: component.id, + type: component.innerType, + render: component.render, + isPlugin: component.isPlugin, + plugin: { + isPlugin: component.isPlugin, + staticMap: component.staticMap + } + } as unknown as ChartObj + // 处理配置项默认值,不同图表的同一配置项默认值不同 + const chartViewInstance = chartViewManager.getChartView(newView.render, newView.type) + if (chartViewInstance) { + newView = chartViewInstance.setupDefaultOptions(newView) + newView['title'] = component.name + } + currentFont && (newView.customStyle.text.fontFamily = currentFont.name) + this.canvasViewInfo[component.id] = newView + } + if (component.component === 'VQuery') { + const { color, titleColor, labelColor, borderColor, bgColor, text, titleLayout, layout } = + this.canvasStyleData.component.filterStyle || {} + const newView = { + ...JSON.parse(JSON.stringify(BASE_VIEW_CONFIG)), + id: component.id, + title: t('visualization.query_component'), + type: component.innerType, + customStyle: { + component: { + show: true, + color, + titleShow: false, + text, + textColorShow: false, + labelColor, + borderColor, + title: '', + borderWidth: 1, + bgColor, + titleColor, + titleLayout, + layout, + btnList: ['sure'], + fontSize: '14', + labelShow: true, + fontWeight: '', + fontStyle: '', + fontSizeBtn: '14', + fontWeightBtn: '', + fontStyleBtn: '', + queryConditionWidth: 227, + nameboxSpacing: 8, + placeholderShow: true, + placeholderSize: 14, + queryConditionSpacing: 16, + queryConditionHeight: 32, + labelColorBtn: '#ffffff', + btnColor: '#3370ff' + } + } + } + this.canvasViewInfo[component.id] = newView + } }, setLinkageTargetInfo(targetLinkageInfo) { this.linkageSettingStatus = true @@ -455,12 +553,18 @@ export const dvMainStore = defineStore('dataVisualization', { }) }, - deleteComponentById(componentId, componentData = this.componentData) { + deleteComponentById(componentId, componentData = this.componentData, deep = false) { if (componentId) { let indexResult componentData.forEach((component, index) => { if (componentId === component.id) { indexResult = index + } else if (deep && component.component === 'Group') { + this.deleteComponentById(componentId, component.propValue || []) + } else if (deep && component.innerType === 'DeTabs') { + component.propValue.forEach(ele => { + this.deleteComponentById(componentId, ele.componentData || []) + }) } }) this.deleteComponent(indexResult, componentData) @@ -501,7 +605,10 @@ export const dvMainStore = defineStore('dataVisualization', { item.linkageFilters.push(newLinkage) }) } - + // 如果linkageFilters内容长度有变化 则需要重新查询 + if (historyLinkageFiltersLength !== newList.length) { + useEmitt().emitter.emit('query-data-' + item.id) + } } }, // 清除相同sourceViewId 的 联动条件 @@ -731,7 +838,13 @@ export const dvMainStore = defineStore('dataVisualization', { } else { viewInfo[propertyInfo.custom][propertyInfo.property] = propertyInfo.value } - + if (['tablePageMode', 'tablePageSize'].includes(propertyInfo.subProp)) { + useEmitt().emitter.emit('calcData-' + viewId, viewInfo) + } else { + setTimeout(() => { + useEmitt().emitter.emit('renderChart-' + viewId, viewInfo) + }, 0) + } }) } else { this.componentData.forEach(component => { @@ -820,7 +933,9 @@ export const dvMainStore = defineStore('dataVisualization', { } else { this.hiddenListStatus = !this.hiddenListStatus } - this.setBatchOptStatus(false) + if (this.dvInfo.type === 'dashboard') { + this.setBatchOptStatus(false) + } }, removeCurBatchComponentWithId(id) { for (let index = 0; index < this.curBatchOptComponents.length; index++) { @@ -887,8 +1002,88 @@ export const dvMainStore = defineStore('dataVisualization', { this.nowPanelOuterParamsInfoV2[dvId] = outerParamsInfo.outerParamsInfoMap this.nowPanelOuterParamsBaseInfoV2[dvId] = outerParamsInfo.outerParamsInfoBaseMap }, - + // 添加联动 下钻 等查询组件 + addViewTrackFilter(data) { + const viewId = data.viewId + let trackInfo + if (data.option === 'linkage') { + // 维度日期类型转换 + viewFieldTimeTrans(this.canvasViewDataInfo[viewId], data) + trackInfo = this.nowPanelTrackInfo + } else { + trackInfo = this.nowPanelJumpInfoTargetPanel + } + const preActiveComponentIds = [] + const checkQDList = [...data.dimensionList, ...data.quotaList] + const customFilterInfo = data.customFilter + for (let indexOuter = 0; indexOuter < this.componentData.length; indexOuter++) { + const element = this.componentData[indexOuter] + if (element.id !== viewId) { + if (['UserView', 'VQuery'].includes(element.component)) { + this.trackFilterCursor( + element, + checkQDList, + trackInfo, + preActiveComponentIds, + viewId, + customFilterInfo + ) + this.componentData[indexOuter] = element + } else if (element.component === 'Group') { + element.propValue?.forEach((groupItem, index) => { + this.trackFilterCursor( + groupItem, + checkQDList, + trackInfo, + preActiveComponentIds, + viewId, + customFilterInfo + ) + element.propValue[index] = groupItem + }) + } else if (element.component === 'DeTabs') { + element.propValue?.forEach(tabItem => { + tabItem.componentData.forEach((tabComponent, index) => { + this.trackFilterCursor( + tabComponent, + checkQDList, + trackInfo, + preActiveComponentIds, + viewId, + customFilterInfo + ) + tabItem.componentData[index] = tabComponent + }) + }) + } + } + } + preActiveComponentIds.forEach(viewId => { + useEmitt().emitter.emit('query-data-' + viewId) + }) + }, addWebParamsFilter(params, curComponentData = this.componentData) { + if (params) { + for (let index = 0; index < curComponentData.length; index++) { + const element = curComponentData[index] + if (['UserView'].includes(element.component)) { + this.trackWebFilterCursor(element, params) + this.componentData[index] = element + } else if (element.component === 'Group') { + element.propValue?.forEach((groupItem, index) => { + this.trackWebFilterCursor(groupItem, params) + element.propValue[index] = groupItem + }) + } else if (element.component === 'DeTabs') { + element.propValue?.forEach(tabItem => { + tabItem.componentData.forEach((tabComponent, index) => { + this.trackWebFilterCursor(tabComponent, params) + tabItem.componentData[index] = tabComponent + }) + }) + } + } + } }, // 添加外部参数的过滤条件 addOuterParamsFilter( @@ -897,9 +1092,90 @@ export const dvMainStore = defineStore('dataVisualization', { source = 'inner', dvId = this.dvInfo.id ) { + // params 结构 {key1:value1,key2:value2} + const params = {} + const paramsVersion = (paramsPre && paramsPre['outerParamsVersion']) || 'v1' + if (this.nowPanelOuterParamsBaseInfoV2[dvId]) { + let errorCount = 0 + let errorMes = '' + Object.keys(this.nowPanelOuterParamsBaseInfoV2[dvId]).forEach(key => { + const targetInfo = this.nowPanelOuterParamsBaseInfoV2[dvId][key] + const userParams = paramsPre ? paramsPre[key] : null + const userParamsIsNull = !userParams || userParams.length === 0 + if (targetInfo.required && userParamsIsNull) { + // 要求用户必填 但是用户没有输入参数 + errorCount++ + errorMes = errorMes + '[' + key + ']' + } else if ( + userParamsIsNull && + targetInfo.enabledDefault && + targetInfo.defaultValue && + targetInfo.defaultValue.length > 0 + ) { + // 非必填时 用户没有填写参数 但是启用默认值且有预设默认值时 + params[key] = JSON.parse(targetInfo.defaultValue) + } else if (!userParamsIsNull) { + params[key] = paramsPre[key] + } + }) + if (errorCount > 0) { + ElMessage.error('参数' + errorMes + '不能为空') + throw new Error('参数' + errorMes + '不能为空') + } + } else { + return + } + + if (params) { + const preActiveComponentIds = [] + const trackInfo = this.nowPanelOuterParamsInfoV2[dvId] + for (let index = 0; index < curComponentData.length; index++) { + const element = curComponentData[index] + if (['UserView', 'VQuery'].includes(element.component)) { + this.trackOuterFilterCursor( + element, + params, + preActiveComponentIds, + trackInfo, + source, + paramsVersion + ) + this.componentData[index] = element + } else if (element.component === 'Group') { + element.propValue?.forEach((groupItem, index) => { + this.trackOuterFilterCursor( + groupItem, + params, + preActiveComponentIds, + trackInfo, + source, + paramsVersion + ) + element.propValue[index] = groupItem + }) + } else if (element.component === 'DeTabs') { + element.propValue?.forEach(tabItem => { + tabItem.componentData.forEach((tabComponent, index) => { + this.trackOuterFilterCursor( + tabComponent, + params, + preActiveComponentIds, + trackInfo, + source, + paramsVersion + ) + tabItem.componentData[index] = tabComponent + }) + }) + } + } + } }, trackWebFilterCursor(element, params) { - + if (params[element.id]) { + element['webParamsFilters'] = params[element.id] + useEmitt().emitter.emit('query-data-' + element.id) + } }, trackOuterFilterCursor( element, @@ -979,7 +1255,7 @@ export const dvMainStore = defineStore('dataVisualization', { } if (element.component === 'VQuery') { const defaultValueMap = {} - element.propValue.forEach(filterItem => { + element.propValue?.forEach(filterItem => { if (filterItem.id === targetViewId) { let queryParams = paramValue if (!['1', '7'].includes(filterItem.displayType)) { @@ -991,6 +1267,12 @@ export const dvMainStore = defineStore('dataVisualization', { filterItem.defaultValueCheck = true filterItem.timeType = 'fixed' if (['0', '2'].includes(filterItem.displayType)) { + const { optionValueSource, field, displayId } = filterItem + const queryMapFlag = optionValueSource === 1 && field.id !== displayId + let queryMapParams = queryParams + if (queryMapFlag) { + queryMapParams = filterEnumParams(queryParams, field.id) + } // 0 文本类型 1 数字类型 if (filterItem.multiple) { // multiple === true 多选 @@ -1001,8 +1283,8 @@ export const dvMainStore = defineStore('dataVisualization', { filterItem['selectValue'] = queryParams[0] filterItem['defaultValue'] = queryParams[0] } - filterItem['defaultMapValue'] = queryParams - filterItem['mapValue'] = queryParams + filterItem['defaultMapValue'] = queryMapParams + filterItem['mapValue'] = queryMapParams } else if (filterItem.displayType === '1') { // 1 时间类型 filterItem['selectValue'] = queryParams[0] @@ -1015,6 +1297,22 @@ export const dvMainStore = defineStore('dataVisualization', { // 8 文本搜索 filterItem['conditionValueF'] = parmaValueSource + '' filterItem['defaultConditionValueF'] = parmaValueSource + '' + } else if (filterItem.displayType === '9') { + // 9 下拉树 + if (filterItem.multiple) { + // multiple === true 多选 + filterItem['selectValue'] = queryParams + filterItem['defaultValue'] = queryParams + } else { + // 单选 + filterItem['selectValue'] = queryParams[0] + filterItem['defaultValue'] = queryParams[0] + } + } else if (filterItem.displayType === '22') { + filterItem['defaultNumValueStart'] = queryParams[0] + filterItem['defaultNumValueEnd'] = queryParams[1] + filterItem['numValueStart'] = queryParams[0] + filterItem['numValueEnd'] = queryParams[1] } if ('DE_EMPTY' === paramValueStr) { filterItem['selectValue'] = null @@ -1038,8 +1336,12 @@ export const dvMainStore = defineStore('dataVisualization', { itemInner['currentSelectValue'] = Array.isArray(curDefaultValue) ? curDefaultValue : [curDefaultValue] + itemInner['selectValue'] = Array.isArray(curDefaultValue) + ? curDefaultValue + : [curDefaultValue] } else { itemInner['currentSelectValue'] = [] + itemInner['selectValue'] = [] } }) } @@ -1052,12 +1354,31 @@ export const dvMainStore = defineStore('dataVisualization', { if (element.component === 'UserView') { element['outerParamsFilters'] = currentFilters } + if (source === 'outer') { + preActiveComponentIds.forEach(viewId => { + useEmitt().emitter.emit('query-data-' + viewId) + }) + } }, - trackFilterCursor(element, checkQDList, trackInfo, preActiveComponentIds, viewId) { + trackFilterCursor( + element, + checkQDList, + trackInfo, + preActiveComponentIds, + viewId, + customFilter? + ) { let currentFilters = element.linkageFilters || [] // 当前联动filter if (['table-info', 'table-normal'].includes(element.innerType)) { currentFilters = [] } + if (currentFilters.length) { + for (let i = currentFilters.length - 1; i >= 0; i--) { + if (currentFilters[i].filterType === 3) { + currentFilters.splice(i, 1) + } + } + } // 联动的图表情况历史条件 // const currentFilters = [] checkQDList.forEach(QDItem => { @@ -1069,42 +1390,50 @@ export const dvMainStore = defineStore('dataVisualization', { const targetInfoArray = targetInfo.split('#') const targetViewId = targetInfoArray[0] // 目标图表 if (element.component === 'UserView' && element.id === targetViewId) { - // 如果目标图表 和 当前循环组件id相等 则进行条件增减 - const targetFieldId = targetInfoArray[1] // 目标图表列ID - let condition - if (QDItem.timeValue && Array.isArray(QDItem.timeValue)) { - // 如果dimension.timeValue存在值且是数组 目前判断为是时间组件 - condition = { - fieldId: targetFieldId, - operator: 'between', - value: QDItem.timeValue, - viewIds: [targetViewId], - sourceViewId: viewId - } + // 如果含有customFilter 仅加入customFilter + if (customFilter) { + currentFilters.push({ + filterType: 3, + customFilter: customFilter + }) } else { - condition = { - fieldId: targetFieldId, - operator: 'eq', - value: [QDItem.value], - viewIds: [targetViewId], - sourceViewId: viewId + // 如果目标图表 和 当前循环组件id相等 则进行条件增减 + const targetFieldId = targetInfoArray[1] // 目标图表列ID + let condition + if (QDItem.timeValue && Array.isArray(QDItem.timeValue)) { + // 如果dimension.timeValue存在值且是数组 目前判断为是时间组件 + condition = { + fieldId: targetFieldId, + operator: 'between', + value: QDItem.timeValue, + viewIds: [targetViewId], + sourceViewId: viewId + } + } else { + condition = { + fieldId: targetFieldId, + operator: 'eq', + value: [QDItem.value], + viewIds: [targetViewId], + sourceViewId: viewId + } } - } - let j = currentFilters.length - while (j--) { - const filter = currentFilters[j] - // 兼容性准备 viewIds 只会存放一个值 - if (targetFieldId === filter.fieldId && filter.viewIds.includes(targetViewId)) { - currentFilters.splice(j, 1) + let j = currentFilters.length + while (j--) { + const filter = currentFilters[j] + // 兼容性准备 viewIds 只会存放一个值 + if (targetFieldId === filter.fieldId && filter.viewIds.includes(targetViewId)) { + currentFilters.splice(j, 1) + } } + // 不存在该条件 且 条件有效 直接保存该条件 + // !filterExist && vValid && currentFilters.push(condition) + currentFilters.push(condition) } - // 不存在该条件 且 条件有效 直接保存该条件 - // !filterExist && vValid && currentFilters.push(condition) - currentFilters.push(condition) preActiveComponentIds.includes(element.id) || preActiveComponentIds.push(element.id) } - if (element.component === 'VQuery') { - element.propValue.forEach(filterItem => { + if (element.component === 'VQuery' && Array.isArray(element.propValue)) { + element.propValue?.forEach(filterItem => { if (filterItem.id === targetViewId) { let queryParams = paramValue if (!['1', '7'].includes(filterItem.displayType)) { @@ -1114,6 +1443,12 @@ export const dvMainStore = defineStore('dataVisualization', { filterItem.defaultValueCheck = true filterItem.timeType = 'fixed' if (['0', '2'].includes(filterItem.displayType)) { + const { optionValueSource, field, displayId } = filterItem + const queryMapFlag = optionValueSource === 1 && field.id !== displayId + let queryMapParams = queryParams + if (queryMapFlag) { + queryMapParams = filterEnumParams(queryParams, field.id) + } // 0 文本类型 1 数字类型 if (filterItem.multiple) { // multiple === true 多选 @@ -1124,8 +1459,8 @@ export const dvMainStore = defineStore('dataVisualization', { filterItem['selectValue'] = queryParams[0] filterItem['defaultValue'] = queryParams[0] } - filterItem['defaultMapValue'] = queryParams - filterItem['mapValue'] = queryParams + filterItem['defaultMapValue'] = queryMapParams + filterItem['mapValue'] = queryMapParams } else if (filterItem.displayType === '1') { // 1 时间类型 filterItem['selectValue'] = queryParams[0] @@ -1156,12 +1491,15 @@ export const dvMainStore = defineStore('dataVisualization', { clearPanelLinkageInfo() { this.componentData.forEach(item => { if (item.component === 'UserView') { - + if (item.linkageFilters && item.linkageFilters.length > 0) { + item.linkageFilters.splice(0, item.linkageFilters.length) + useEmitt().emitter.emit('query-data-' + item.id) + } } else if (item.component === 'Group') { item.propValue.forEach(groupItem => { if (groupItem.linkageFilters && groupItem.linkageFilters.length > 0) { groupItem.linkageFilters.splice(0, groupItem.linkageFilters.length) - + useEmitt().emitter.emit('query-data-' + groupItem.id) } }) } else if (item.component === 'DeTabs') { @@ -1169,7 +1507,7 @@ export const dvMainStore = defineStore('dataVisualization', { tabItem.componentData.forEach(tabComponent => { if (tabComponent.linkageFilters && tabComponent.linkageFilters.length > 0) { tabComponent.linkageFilters.splice(0, tabComponent.linkageFilters.length) - + useEmitt().emitter.emit('query-data-' + tabComponent.id) } }) }) @@ -1251,7 +1589,7 @@ export const dvMainStore = defineStore('dataVisualization', { getViewDetails(viewId) { return this.canvasViewInfo[viewId] }, - updateDvInfoId(newId, contentId?) { + updateDvInfoCall(status = 1, newId?, contentId?) { if (this.dvInfo) { this.dvInfo.dataState = 'ready' this.dvInfo.optType = null @@ -1261,6 +1599,7 @@ export const dvMainStore = defineStore('dataVisualization', { if (contentId) { this.dvInfo.contentId = contentId } + this.dvInfo.status = status } }, popAreaActiveSwitch() { @@ -1287,7 +1626,7 @@ export const dvMainStore = defineStore('dataVisualization', { name: name, pid: pid, type: dvType, - status: 1, + status: 0, selfWatermarkStatus: true, watermarkInfo: watermarkInfo, mobileLayout: false, @@ -1347,6 +1686,14 @@ export const dvMainStore = defineStore('dataVisualization', { this.deleteComponentById(ele.id, curComponentData) }) } + }, + setViewPageInfo(viewId, pageInfo) { + if (this.canvasViewInfo[viewId]) { + this.canvasViewInfo[viewId].pageInfo = pageInfo + } + }, + getViewPageInfo(viewId) { + return this.canvasViewInfo[viewId]?.pageInfo } } }) diff --git a/frontend/src/data-visualization/store/modules/data-visualization/layer.ts b/frontend/src/data-visualization/store/modules/data-visualization/layer.ts index e8b4bfc..b6fbc92 100644 --- a/frontend/src/data-visualization/store/modules/data-visualization/layer.ts +++ b/frontend/src/data-visualization/store/modules/data-visualization/layer.ts @@ -4,6 +4,7 @@ import { dvMainStoreWithOut } from './dvMain' import { swap } from '@/data-visualization/utils/utils' import { useEmitt } from '@/data-visualization/hooks/web/useEmitt' import { getComponentById, getCurInfo } from '@/data-visualization/store/modules/data-visualization/common' +// import ChartCarouselTooltip from '@/data-visualization/chart/components/js/g2plot_tooltip_carousel' const dvMainStore = dvMainStoreWithOut() const { curComponentIndex, curComponent } = storeToRefs(dvMainStore) @@ -93,7 +94,21 @@ export const layerStore = defineStore('layer', { }, 400) } } - } + }, + // pausedTooltipCarousel(componentId?) { + // const targetComponent = getComponentById(componentId) + // // 暂停轮播 + // if (targetComponent) { + // ChartCarouselTooltip.paused(componentId) + // } + // }, + // resumeTooltipCarousel(componentId?) { + // const targetComponent = getComponentById(componentId) + // // 恢复轮播 + // if (targetComponent) { + // ChartCarouselTooltip.resume(componentId) + // } + // } } }) diff --git a/frontend/src/data-visualization/store/modules/data-visualization/snapshot.ts b/frontend/src/data-visualization/store/modules/data-visualization/snapshot.ts index bbadec6..16da774 100644 --- a/frontend/src/data-visualization/store/modules/data-visualization/snapshot.ts +++ b/frontend/src/data-visualization/store/modules/data-visualization/snapshot.ts @@ -4,6 +4,9 @@ import { dvMainStoreWithOut } from './dvMain' import { deepCopy } from '@/data-visualization/utils/utils' import { BASE_THEMES } from '@/data-visualization/chart/components/editor/util/dataVisualization' import eventBus from '@/data-visualization/utils/eventBus' +import { useEmitt } from '@/data-visualization/hooks/web/useEmitt' +import { useCache } from '@/data-visualization/hooks/web/useCache' +const { wsCache } = useCache('localStorage') const dvMainStore = dvMainStoreWithOut() const { @@ -66,7 +69,14 @@ export const snapshotStore = defineStore('snapshot', { recordSnapshotCacheToMobile(type, component = curComponent.value, otherComponent = null) { if (mobileInPc.value && component) { //移动端设计 - + useEmitt().emitter.emit('onMobileStatusChange', { + type: 'componentStyleChange', + value: { + type: type, + component: JSON.parse(JSON.stringify(component)), + otherComponent: otherComponent + } + }) } this.recordSnapshotCache(type) }, @@ -158,7 +168,12 @@ export const snapshotStore = defineStore('snapshot', { canvasViewInfo: snapshotInfo.canvasViewInfo } eventBus.emit('snapshotChange') - + if ( + paramCacheViewInfo.snapshotCacheViewCalc.length > 0 || + paramCacheViewInfo.snapshotCacheViewRender.length > 0 + ) { + useEmitt().emitter.emit('snapshotChangeToView', paramCacheViewInfo) + } }, resetStyleChangeTimes() { @@ -178,7 +193,7 @@ export const snapshotStore = defineStore('snapshot', { this.recordSnapshot() }, - recordSnapshot(type) { + recordSnapshot() { // 移动端设计时暂不保存镜像 if (dataPrepareState.value && !mobileInPc.value && Date.now() > this.snapshotDisableTime) { this.styleChangeTimes = ++this.styleChangeTimes @@ -201,6 +216,9 @@ export const snapshotStore = defineStore('snapshot', { } // 清理缓存计数器 this.snapshotCacheTimes = 0 + if (this.snapshotData.length > 1) { + wsCache.set('DE-DV-CATCH-' + dvInfo.value.id, newSnapshot) + } } } } diff --git a/frontend/src/data-visualization/store/modules/locale.ts b/frontend/src/data-visualization/store/modules/locale.ts index 67df2e6..67d13b8 100644 --- a/frontend/src/data-visualization/store/modules/locale.ts +++ b/frontend/src/data-visualization/store/modules/locale.ts @@ -4,6 +4,8 @@ import type { LocaleDropdownType } from 'types/localeDropdown' import zhCn from 'element-plus-secondary/es/locale/lang/zh-cn' import en from 'element-plus-secondary/es/locale/lang/en' import tw from 'element-plus-secondary/es/locale/lang/zh-tw' +// import { getLocale } from '@/utils/utils' +// import request from '@/config/axios' const elLocaleMap = { 'zh-CN': zhCn, en: en, diff --git a/frontend/src/data-visualization/store/modules/map.ts b/frontend/src/data-visualization/store/modules/map.ts index b3f8230..eadfbe5 100644 --- a/frontend/src/data-visualization/store/modules/map.ts +++ b/frontend/src/data-visualization/store/modules/map.ts @@ -6,6 +6,7 @@ interface MapStore { mapKey: { key: string securityCode: string + mapType: string } } export const useMapStore = defineStore('map', { @@ -13,7 +14,8 @@ export const useMapStore = defineStore('map', { mapCache: {}, mapKey: { key: '', - securityCode: '' + securityCode: '', + mapType: '' } }), actions: { diff --git a/frontend/src/data-visualization/utils/componentUtils.ts b/frontend/src/data-visualization/utils/componentUtils.ts new file mode 100644 index 0000000..9f5160f --- /dev/null +++ b/frontend/src/data-visualization/utils/componentUtils.ts @@ -0,0 +1,44 @@ +import { EnumValue, enumValueObj } from '@/api/data-visualization/dataset' + +let filterEnumMap = {} + +const findFilterEnum = async (val: EnumValue) => { + const queryId = val.queryId + const displayId = val.displayId + const arr = await enumValueObj({ queryId: queryId, displayId: displayId, searchText: '' }) + return arr?.reduce((acc, item) => { + acc[item[displayId]] = item[queryId] + return acc + }, {}) +} + +export const filterEnumParams = (queryParams, fieldId: string) => { + const resultMap = filterEnumMap[fieldId] + if (resultMap) { + const resultParams = [] + queryParams.forEach(param => { + resultParams.push(resultMap[param] || param) + }) + return resultParams + } else { + return queryParams + } +} + +export const filterEnumMapSync = async componentData => { + filterEnumMap = {} + for (const element of componentData) { + if (element.component === 'VQuery') { + for (const filterItem of element.propValue) { + const { optionValueSource, field, displayId } = filterItem + if (optionValueSource === 1 && field.id) { + filterEnumMap[field.id] = await findFilterEnum({ + queryId: field.id, + displayId, + searchText: '' + }) + } + } + } + } +}