修改views\chart\components\views
This commit is contained in:
parent
40da16013a
commit
e7904b667e
@ -79,7 +79,8 @@ function createExtremumDiv(id, value, formatterCfg, chart) {
|
|||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: opacity 0.2s ease-in-out;
|
transition: opacity 0.2s ease-in-out;
|
||||||
white-space:nowrap;`
|
white-space:nowrap;
|
||||||
|
overflow:auto;`
|
||||||
)
|
)
|
||||||
div.textContent = valueFormatter(value, formatterCfg)
|
div.textContent = valueFormatter(value, formatterCfg)
|
||||||
const span = document.createElement('span')
|
const span = document.createElement('span')
|
||||||
@ -109,7 +110,7 @@ const noChildrenFieldChart = chart => {
|
|||||||
* 支持最值图表的折线图,面积图,柱状图,分组柱状图
|
* 支持最值图表的折线图,面积图,柱状图,分组柱状图
|
||||||
* @param chart
|
* @param chart
|
||||||
*/
|
*/
|
||||||
const supportExtremumChartType = chart => {
|
export const supportExtremumChartType = chart => {
|
||||||
return ['line', 'area', 'bar', 'bar-group'].includes(chart.type)
|
return ['line', 'area', 'bar', 'bar-group'].includes(chart.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,8 +139,8 @@ function removeDivsWithPrefix(parentDivId, prefix) {
|
|||||||
|
|
||||||
export const extremumEvt = (newChart, chart, _options, container) => {
|
export const extremumEvt = (newChart, chart, _options, container) => {
|
||||||
chart.container = container
|
chart.container = container
|
||||||
|
clearExtremum(chart)
|
||||||
if (!supportExtremumChartType(chart)) {
|
if (!supportExtremumChartType(chart)) {
|
||||||
clearExtremum(chart)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const { label: labelAttr } = parseJson(chart.customAttr)
|
const { label: labelAttr } = parseJson(chart.customAttr)
|
||||||
@ -150,7 +151,9 @@ export const extremumEvt = (newChart, chart, _options, container) => {
|
|||||||
i.forEach(item => {
|
i.forEach(item => {
|
||||||
delete item._origin.EXTREME
|
delete item._origin.EXTREME
|
||||||
})
|
})
|
||||||
const { minItem, maxItem } = findMinMax(i.filter(item => item._origin.value))
|
const { minItem, maxItem } = findMinMax(
|
||||||
|
i.filter(item => item?._origin?.value !== null && item?._origin?.value !== undefined)
|
||||||
|
)
|
||||||
if (!minItem || !maxItem) {
|
if (!minItem || !maxItem) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -223,6 +226,7 @@ export const createExtremumPoint = (chart, ev) => {
|
|||||||
divParent.style.zIndex = '1'
|
divParent.style.zIndex = '1'
|
||||||
divParent.style.opacity = '0'
|
divParent.style.opacity = '0'
|
||||||
divParent.style.transition = 'opacity 0.2s ease-in-out'
|
divParent.style.transition = 'opacity 0.2s ease-in-out'
|
||||||
|
divParent.style.overflow = 'visible'
|
||||||
// 将父标注加入到图表中
|
// 将父标注加入到图表中
|
||||||
const containerElement = document.getElementById(chart.container)
|
const containerElement = document.getElementById(chart.container)
|
||||||
containerElement.insertBefore(divParent, containerElement.firstChild)
|
containerElement.insertBefore(divParent, containerElement.firstChild)
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
import { Datum } from '@antv/g2plot'
|
import { find } from 'lodash-es'
|
||||||
|
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||||
|
import { getLocale } from '@/data-visualization/utils/utils'
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
export const isEnLocal = !['zh', 'zh-cn', 'zh-CN', 'tw'].includes(getLocale())
|
||||||
|
|
||||||
export const formatterItem = {
|
export const formatterItem = {
|
||||||
type: 'auto', // auto,value,percent
|
type: 'auto', // auto,value,percent
|
||||||
|
unitLanguage: isEnLocal ? 'en' : 'ch',
|
||||||
unit: 1, // 换算单位
|
unit: 1, // 换算单位
|
||||||
suffix: '', // 单位后缀
|
suffix: '', // 单位后缀
|
||||||
decimalCount: 2, // 小数位数
|
decimalCount: 2, // 小数位数
|
||||||
@ -10,12 +16,51 @@ export const formatterItem = {
|
|||||||
|
|
||||||
// 单位list
|
// 单位list
|
||||||
export const unitType = [
|
export const unitType = [
|
||||||
{ name: 'unit_none', value: 1 },
|
{ name: t('chart.unit_none'), value: 1 },
|
||||||
{ name: 'unit_thousand', value: 1000 },
|
{ name: t('chart.unit_thousand'), value: 1000 },
|
||||||
{ name: 'unit_ten_thousand', value: 10000 },
|
{ name: t('chart.unit_ten_thousand'), value: 10000 },
|
||||||
{ name: 'unit_million', value: 1000000 },
|
{ name: t('chart.unit_million'), value: 1000000 },
|
||||||
{ name: 'unit_hundred_million', value: 100000000 }
|
{ name: t('chart.unit_hundred_million'), value: 100000000 }
|
||||||
]
|
]
|
||||||
|
export const unitEnType = [
|
||||||
|
{ name: 'None', value: 1 },
|
||||||
|
{ name: 'Thousand (K)', value: 1000 },
|
||||||
|
{ name: 'Million (M)', value: 1000000 },
|
||||||
|
{ name: 'Billion (B)', value: 1000000000 }
|
||||||
|
]
|
||||||
|
|
||||||
|
export function getUnitTypeList(lang) {
|
||||||
|
if (isEnLocal) {
|
||||||
|
return unitEnType
|
||||||
|
}
|
||||||
|
if (lang === 'ch') {
|
||||||
|
return unitType
|
||||||
|
}
|
||||||
|
return unitEnType
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUnitTypeValue(lang, value) {
|
||||||
|
const list = getUnitTypeList(lang)
|
||||||
|
const item = find(list, l => l.value === value)
|
||||||
|
if (item) {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initFormatCfgUnit(cfg) {
|
||||||
|
if (cfg && cfg.unitLanguage === undefined) {
|
||||||
|
cfg.unitLanguage = 'ch'
|
||||||
|
}
|
||||||
|
if (cfg && isEnLocal) {
|
||||||
|
cfg.unitLanguage = 'en'
|
||||||
|
}
|
||||||
|
onChangeFormatCfgUnitLanguage(cfg, cfg.unitLanguage)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onChangeFormatCfgUnitLanguage(cfg, lang) {
|
||||||
|
cfg.unit = getUnitTypeValue(lang, cfg.unit)
|
||||||
|
}
|
||||||
|
|
||||||
// 格式化方式
|
// 格式化方式
|
||||||
export const formatterType = [
|
export const formatterType = [
|
||||||
@ -47,17 +92,32 @@ export function valueFormatter(value, formatter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function transUnit(value, formatter) {
|
function transUnit(value, formatter) {
|
||||||
|
initFormatCfgUnit(formatter)
|
||||||
return value / formatter.unit
|
return value / formatter.unit
|
||||||
}
|
}
|
||||||
|
|
||||||
function transDecimal(value, formatter) {
|
function transDecimal(value, formatter) {
|
||||||
const resultV = value.toFixed(formatter.decimalCount)
|
const resultV = retain(value, formatter.decimalCount) as string
|
||||||
if (Object.is(parseFloat(resultV), -0)) {
|
if (Object.is(parseFloat(resultV), -0)) {
|
||||||
return resultV.slice(1)
|
return resultV.slice(1)
|
||||||
}
|
}
|
||||||
return resultV
|
return resultV
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function retain(value, n) {
|
||||||
|
if (!n) return Math.round(value)
|
||||||
|
const tran = Math.round(value * Math.pow(10, n)) / Math.pow(10, n)
|
||||||
|
let tranV = tran.toString()
|
||||||
|
const newVal = tranV.indexOf('.')
|
||||||
|
if (newVal < 0) {
|
||||||
|
tranV += '.'
|
||||||
|
}
|
||||||
|
for (let i = tranV.length - tranV.indexOf('.'); i <= n; i++) {
|
||||||
|
tranV += '0'
|
||||||
|
}
|
||||||
|
return tranV
|
||||||
|
}
|
||||||
|
|
||||||
function transSeparatorAndSuffix(value, formatter) {
|
function transSeparatorAndSuffix(value, formatter) {
|
||||||
let str = value + ''
|
let str = value + ''
|
||||||
if (str.match(/^(\d)(\.\d)?e-(\d)/)) {
|
if (str.match(/^(\d)(\.\d)?e-(\d)/)) {
|
||||||
@ -74,34 +134,27 @@ function transSeparatorAndSuffix(value, formatter) {
|
|||||||
//百分比没有后缀,直接返回
|
//百分比没有后缀,直接返回
|
||||||
return str
|
return str
|
||||||
} else {
|
} else {
|
||||||
if (formatter.unit === 1000) {
|
const unit = formatter.unit
|
||||||
str += '千'
|
|
||||||
} else if (formatter.unit === 10000) {
|
if (formatter.unitLanguage === 'ch') {
|
||||||
str += '万'
|
if (unit === 1000) {
|
||||||
} else if (formatter.unit === 1000000) {
|
str += t('chart.unit_thousand')
|
||||||
str += '百万'
|
} else if (unit === 10000) {
|
||||||
} else if (formatter.unit === 100000000) {
|
str += t('chart.unit_ten_thousand')
|
||||||
str += '亿'
|
} else if (unit === 1000000) {
|
||||||
|
str += t('chart.unit_million')
|
||||||
|
} else if (unit === 100000000) {
|
||||||
|
str += t('chart.unit_hundred_million')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (unit === 1000) {
|
||||||
|
str += 'K'
|
||||||
|
} else if (unit === 1000000) {
|
||||||
|
str += 'M'
|
||||||
|
} else if (unit === 1000000000) {
|
||||||
|
str += 'B'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return str + formatter.suffix.replace(/(^\s*)|(\s*$)/g, '')
|
return str + formatter.suffix.replace(/(^\s*)|(\s*$)/g, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function singleDimensionTooltipFormatter(param: Datum, chart: Chart, prop = 'category') {
|
|
||||||
let res
|
|
||||||
const yAxis = chart.yAxis
|
|
||||||
const obj = { name: param[prop], value: param.value }
|
|
||||||
for (let i = 0; i < yAxis.length; i++) {
|
|
||||||
const f = yAxis[i]
|
|
||||||
if (f.name === param[prop]) {
|
|
||||||
if (f.formatterCfg) {
|
|
||||||
res = valueFormatter(param.value, f.formatterCfg)
|
|
||||||
} else {
|
|
||||||
res = valueFormatter(param.value, formatterItem)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
obj.value = res ?? ''
|
|
||||||
return obj
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { isEmpty, isNumber } from 'lodash-es'
|
import { isNumber } from 'lodash-es'
|
||||||
import { DEFAULT_TITLE_STYLE } from '../editor/util/chart'
|
import { DEFAULT_TITLE_STYLE } from '../editor/util/chart'
|
||||||
import { equalsAny, includesAny } from '../editor/util/StringUtils'
|
import { equalsAny, includesAny } from '../editor/util/StringUtils'
|
||||||
import { FeatureCollection } from '@antv/l7plot/dist/esm/plots/choropleth/types'
|
import { FeatureCollection } from '@antv/l7plot/dist/esm/plots/choropleth/types'
|
||||||
@ -12,6 +12,8 @@ import { ElMessage } from 'element-plus-secondary'
|
|||||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||||
import { useLinkStoreWithOut } from '@/data-visualization/store/modules/link'
|
import { useLinkStoreWithOut } from '@/data-visualization/store/modules/link'
|
||||||
import { useAppStoreWithOut } from '@/data-visualization/store/modules/app'
|
import { useAppStoreWithOut } from '@/data-visualization/store/modules/app'
|
||||||
|
import { Decimal } from 'decimal.js'
|
||||||
|
|
||||||
const appStore = useAppStoreWithOut()
|
const appStore = useAppStoreWithOut()
|
||||||
const isDataEaseBi = computed(() => appStore.getIsDataEaseBi)
|
const isDataEaseBi = computed(() => appStore.getIsDataEaseBi)
|
||||||
|
|
||||||
@ -283,17 +285,23 @@ export function handleEmptyDataStrategy<O extends PickOptions>(chart: Chart, opt
|
|||||||
}
|
}
|
||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
const { yAxis, xAxisExt, extStack } = chart
|
const { yAxis, xAxisExt, extStack, extBubble } = chart
|
||||||
const multiDimension = yAxis?.length >= 2 || xAxisExt?.length > 0 || extStack?.length > 0
|
const multiDimension = yAxis?.length >= 2 || xAxisExt?.length > 0 || extStack?.length > 0
|
||||||
switch (strategy) {
|
switch (strategy) {
|
||||||
case 'breakLine': {
|
case 'breakLine': {
|
||||||
if (multiDimension) {
|
if (isChartMix) {
|
||||||
// 多维度保持空
|
if (data[0]) {
|
||||||
if (isChartMix) {
|
if (xAxisExt?.length > 0 || extStack?.length > 0) {
|
||||||
for (let i = 0; i < data.length; i++) {
|
handleBreakLineMultiDimension(data[0] as Record<string, any>[])
|
||||||
handleBreakLineMultiDimension(data[i] as Record<string, any>[])
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
if (data[1]) {
|
||||||
|
if (extBubble?.length > 0) {
|
||||||
|
handleBreakLineMultiDimension(data[1] as Record<string, any>[])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (multiDimension) {
|
||||||
handleBreakLineMultiDimension(data)
|
handleBreakLineMultiDimension(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,22 +311,27 @@ export function handleEmptyDataStrategy<O extends PickOptions>(chart: Chart, opt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'setZero': {
|
case 'setZero': {
|
||||||
if (multiDimension) {
|
if (isChartMix) {
|
||||||
// 多维度置0
|
if (data[0]) {
|
||||||
if (isChartMix) {
|
if (xAxisExt?.length > 0 || extStack?.length > 0) {
|
||||||
for (let i = 0; i < data.length; i++) {
|
handleSetZeroMultiDimension(data[0] as Record<string, any>[])
|
||||||
handleSetZeroMultiDimension(data[i] as Record<string, any>[])
|
} else {
|
||||||
|
handleSetZeroSingleDimension(data[0] as Record<string, any>[])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data[1]) {
|
||||||
|
if (extBubble?.length > 0) {
|
||||||
|
handleSetZeroMultiDimension(data[1] as Record<string, any>[], true)
|
||||||
|
} else {
|
||||||
|
handleSetZeroSingleDimension(data[1] as Record<string, any>[], true)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
handleSetZeroMultiDimension(data)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 单维度置0
|
if (multiDimension) {
|
||||||
if (isChartMix) {
|
// 多维度置0
|
||||||
for (let i = 0; i < data.length; i++) {
|
handleSetZeroMultiDimension(data)
|
||||||
handleSetZeroSingleDimension(data[i] as Record<string, any>[])
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
// 单维度置0
|
||||||
handleSetZeroSingleDimension(data)
|
handleSetZeroSingleDimension(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -364,7 +377,7 @@ function handleBreakLineMultiDimension(data) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSetZeroMultiDimension(data: Record<string, any>[]) {
|
function handleSetZeroMultiDimension(data: Record<string, any>[], isExt = false) {
|
||||||
const dimensionInfoMap = new Map()
|
const dimensionInfoMap = new Map()
|
||||||
const subDimensionSet = new Set()
|
const subDimensionSet = new Set()
|
||||||
const quotaMap = new Map<string, { id: string }[]>()
|
const quotaMap = new Map<string, { id: string }[]>()
|
||||||
@ -372,6 +385,9 @@ function handleSetZeroMultiDimension(data: Record<string, any>[]) {
|
|||||||
const item = data[i]
|
const item = data[i]
|
||||||
if (item.value === null) {
|
if (item.value === null) {
|
||||||
item.value = 0
|
item.value = 0
|
||||||
|
if (isExt) {
|
||||||
|
item.valueExt = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const dimensionInfo = dimensionInfoMap.get(item.field)
|
const dimensionInfo = dimensionInfoMap.get(item.field)
|
||||||
if (dimensionInfo) {
|
if (dimensionInfo) {
|
||||||
@ -388,12 +404,17 @@ function handleSetZeroMultiDimension(data: Record<string, any>[]) {
|
|||||||
let subInsertIndex = 0
|
let subInsertIndex = 0
|
||||||
subDimensionSet.forEach(dimension => {
|
subDimensionSet.forEach(dimension => {
|
||||||
if (!dimensionInfo.set.has(dimension)) {
|
if (!dimensionInfo.set.has(dimension)) {
|
||||||
data.splice(dimensionInfo.index + insertCount + subInsertIndex, 0, {
|
const _temp = {
|
||||||
field,
|
field,
|
||||||
value: 0,
|
value: 0,
|
||||||
category: dimension,
|
category: dimension,
|
||||||
quotaList: quotaMap.get(dimension as string)
|
quotaList: quotaMap.get(dimension as string)
|
||||||
})
|
} as any
|
||||||
|
if (isExt) {
|
||||||
|
_temp.valueExt = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
data.splice(dimensionInfo.index + insertCount + subInsertIndex, 0, _temp)
|
||||||
}
|
}
|
||||||
subInsertIndex++
|
subInsertIndex++
|
||||||
})
|
})
|
||||||
@ -402,10 +423,14 @@ function handleSetZeroMultiDimension(data: Record<string, any>[]) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSetZeroSingleDimension(data: Record<string, any>[]) {
|
function handleSetZeroSingleDimension(data: Record<string, any>[], isExt = false) {
|
||||||
data.forEach(item => {
|
data.forEach(item => {
|
||||||
if (item.value === null) {
|
if (item.value === null) {
|
||||||
item.value = 0
|
if (!isExt) {
|
||||||
|
item.value = 0
|
||||||
|
} else {
|
||||||
|
item.valueExt = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -489,7 +514,7 @@ const getExcelDownloadRequest = (data, type?) => {
|
|||||||
const tableRow = JSON.parse(JSON.stringify(data.tableRow))
|
const tableRow = JSON.parse(JSON.stringify(data.tableRow))
|
||||||
const excelHeader = fields.map(item => item.chartShowName ?? item.name)
|
const excelHeader = fields.map(item => item.chartShowName ?? item.name)
|
||||||
const excelTypes = fields.map(item => item.deType)
|
const excelTypes = fields.map(item => item.deType)
|
||||||
const excelHeaderKeys = fields.map(item => item.dataeaseName)
|
const excelHeaderKeys = fields.map(item => item.gisbiName)
|
||||||
let excelData = tableRow.map(item => excelHeaderKeys.map(i => item[i]))
|
let excelData = tableRow.map(item => excelHeaderKeys.map(i => item[i]))
|
||||||
let detailFields = []
|
let detailFields = []
|
||||||
if (data.detailFields?.length) {
|
if (data.detailFields?.length) {
|
||||||
@ -497,7 +522,7 @@ const getExcelDownloadRequest = (data, type?) => {
|
|||||||
return {
|
return {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
deType: item.deType,
|
deType: item.deType,
|
||||||
dataeaseName: item.dataeaseName
|
gisbiName: item.gisbiName
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
excelData = tableRow.map(item => {
|
excelData = tableRow.map(item => {
|
||||||
@ -505,7 +530,7 @@ const getExcelDownloadRequest = (data, type?) => {
|
|||||||
if (i === 'detail' && !item[i] && Array.isArray(item['details'])) {
|
if (i === 'detail' && !item[i] && Array.isArray(item['details'])) {
|
||||||
const arr = item['details']
|
const arr = item['details']
|
||||||
if (arr?.length) {
|
if (arr?.length) {
|
||||||
return arr.map(ele => detailFields.map(field => ele[field.dataeaseName]))
|
return arr.map(ele => detailFields.map(field => ele[field.gisbiName]))
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -522,8 +547,20 @@ const getExcelDownloadRequest = (data, type?) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const exportExcelDownload = (chart, callBack?) => {
|
function getChartExcelTitle(preFix, viewTitle) {
|
||||||
const excelName = chart.title
|
const now = new Date()
|
||||||
|
const pad = n => n.toString().padStart(2, '0')
|
||||||
|
const year = now.getFullYear()
|
||||||
|
const month = pad(now.getMonth() + 1) // 月份从 0 开始
|
||||||
|
const day = pad(now.getDate())
|
||||||
|
const hour = pad(now.getHours())
|
||||||
|
const minute = pad(now.getMinutes())
|
||||||
|
const second = pad(now.getSeconds())
|
||||||
|
return `${preFix}_${viewTitle}_${year}${month}${day}_${hour}${minute}${second}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export const exportExcelDownload = (chart, preFix, callBack?) => {
|
||||||
|
const excelName = getChartExcelTitle(preFix, chart.title)
|
||||||
let request: any = {
|
let request: any = {
|
||||||
proxy: null,
|
proxy: null,
|
||||||
dvId: chart.sceneId,
|
dvId: chart.sceneId,
|
||||||
@ -586,18 +623,21 @@ export const exportExcelDownload = (chart, callBack?) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const copyString = (content: string, notify = false) => {
|
export const copyString = (content: string, notify = false) => {
|
||||||
const clipboard = navigator.clipboard || {
|
let clipboard = navigator.clipboard as Pick<Clipboard, 'writeText'>
|
||||||
writeText: data => {
|
if (!clipboard || window.top !== window.self) {
|
||||||
return new Promise(resolve => {
|
clipboard = {
|
||||||
const textareaDom = document.createElement('textarea')
|
writeText: data => {
|
||||||
textareaDom.setAttribute('style', 'z-index: -1;position: fixed;opacity: 0;')
|
return new Promise<void>(resolve => {
|
||||||
textareaDom.value = data
|
const textareaDom = document.createElement('textarea')
|
||||||
document.body.appendChild(textareaDom)
|
textareaDom.setAttribute('style', 'z-index: -1;position: fixed;opacity: 0;')
|
||||||
textareaDom.select()
|
textareaDom.value = data
|
||||||
document.execCommand('copy')
|
document.body.appendChild(textareaDom)
|
||||||
textareaDom.remove()
|
textareaDom.select()
|
||||||
resolve()
|
document.execCommand('copy')
|
||||||
})
|
textareaDom.remove()
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clipboard.writeText(content).then(() => {
|
clipboard.writeText(content).then(() => {
|
||||||
@ -779,7 +819,7 @@ export function getColor(chart: Chart) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
|
export function setupSeriesColor(chart: ChartObj): ChartBasicStyle['seriesColor'] {
|
||||||
const result: ChartBasicStyle['seriesColor'] = []
|
const result: ChartBasicStyle['seriesColor'] = []
|
||||||
const seriesSet = new Set<string>()
|
const seriesSet = new Set<string>()
|
||||||
const colors = chart.customAttr.basicStyle.colors
|
const colors = chart.customAttr.basicStyle.colors
|
||||||
@ -1152,8 +1192,10 @@ export function getLineLabelColorByCondition(conditions, value, fieldId) {
|
|||||||
if (fieldConditions.length) {
|
if (fieldConditions.length) {
|
||||||
fieldConditions.some(item => {
|
fieldConditions.some(item => {
|
||||||
if (
|
if (
|
||||||
(item.term === 'lt' && value <= item.value) ||
|
(item.term === 'lt' && value < item.value) ||
|
||||||
(item.term === 'gt' && value >= item.value) ||
|
(item.term === 'le' && value <= item.value) ||
|
||||||
|
(item.term === 'gt' && value > item.value) ||
|
||||||
|
(item.term === 'ge' && value >= item.value) ||
|
||||||
(item.term === 'between' && value >= item.min && value <= item.max)
|
(item.term === 'between' && value >= item.min && value <= item.max)
|
||||||
) {
|
) {
|
||||||
color = item.color
|
color = item.color
|
||||||
@ -1207,3 +1249,27 @@ export const hexToRgba = (hex, alpha = 1) => {
|
|||||||
// 返回 RGBA 格式
|
// 返回 RGBA 格式
|
||||||
return `rgba(${r}, ${g}, ${b}, ${a})`
|
return `rgba(${r}, ${g}, ${b}, ${a})`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 安全计算数值字段的总和,使用 Decimal 避免浮点数精度问题
|
||||||
|
export function safeDecimalSum(data, field) {
|
||||||
|
// 使用 reduce 累加所有行的指定字段值
|
||||||
|
return data
|
||||||
|
.reduce((acc, row) => {
|
||||||
|
// 将字段值转换为 Decimal 类型并累加到累加器
|
||||||
|
return acc.plus(new Decimal(row[field] ?? 0))
|
||||||
|
}, new Decimal(0))
|
||||||
|
.toNumber() // 最终结果转换为普通数字返回
|
||||||
|
}
|
||||||
|
|
||||||
|
// 安全计算数值字段的平均值,使用 Decimal 避免浮点数精度问题
|
||||||
|
export function safeDecimalMean(data, field) {
|
||||||
|
// 如果数据为空,直接返回 0
|
||||||
|
if (!data.length) return 0
|
||||||
|
// 计算所有行的指定字段值的总和
|
||||||
|
const sum = data.reduce((acc, row) => {
|
||||||
|
// 将字段值转换为 Decimal 类型并累加到累加器
|
||||||
|
return acc.plus(new Decimal(row[field] ?? 0))
|
||||||
|
}, new Decimal(0))
|
||||||
|
// 将总和除以数据行数,得到平均值,并转换为普通数字返回
|
||||||
|
return sum.dividedBy(data.length).toNumber()
|
||||||
|
}
|
||||||
|
@ -28,7 +28,8 @@ import { isDashboard, trackBarStyleCheck } from '@/data-visualization/utils/canv
|
|||||||
import { useEmitt } from '@/data-visualization/hooks/web/useEmitt'
|
import { useEmitt } from '@/data-visualization/hooks/web/useEmitt'
|
||||||
import { L7ChartView } from '@/data-visualization/chart/components/js/panel/types/impl/l7'
|
import { L7ChartView } from '@/data-visualization/chart/components/js/panel/types/impl/l7'
|
||||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||||
import { ExportImage,Scale } from '@antv/l7'
|
import { ExportImage, Scale, Fullscreen, Control, Scene, TileLayer } from '@antv/l7'
|
||||||
|
import { GaodeMap } from '@antv/l7-maps';
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const dvMainStore = dvMainStoreWithOut()
|
const dvMainStore = dvMainStoreWithOut()
|
||||||
const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc, embeddedCallBack, inMobile } =
|
const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc, embeddedCallBack, inMobile } =
|
||||||
@ -111,7 +112,8 @@ const state = reactive({
|
|||||||
},
|
},
|
||||||
linkageActiveParam: null,
|
linkageActiveParam: null,
|
||||||
pointParam: null,
|
pointParam: null,
|
||||||
data: { fields: [] } // 图表数据
|
data: { fields: [] }, // 图表数据
|
||||||
|
satelliteVisible: false, // 新增卫星图层状态
|
||||||
})
|
})
|
||||||
let chartData = shallowRef<Partial<Chart['data']>>({
|
let chartData = shallowRef<Partial<Chart['data']>>({
|
||||||
fields: []
|
fields: []
|
||||||
@ -333,35 +335,100 @@ const renderL7Plot = async (chart: ChartObj, chartView: L7PlotChartView<any, any
|
|||||||
|
|
||||||
let mapL7Timer: number
|
let mapL7Timer: number
|
||||||
let scaleControl: Scale | null = null // 存储比例尺实例
|
let scaleControl: Scale | null = null // 存储比例尺实例
|
||||||
|
let fullscreenControl
|
||||||
|
let satelliteControlInstance = null; // 用于存储卫星控件实例
|
||||||
const renderL7 = async (chart: ChartObj, chartView: L7ChartView<any, any>, callback) => {
|
const renderL7 = async (chart: ChartObj, chartView: L7ChartView<any, any>, callback) => {
|
||||||
mapL7Timer && clearTimeout(mapL7Timer)
|
mapL7Timer && clearTimeout(mapL7Timer);
|
||||||
mapL7Timer = setTimeout(async () => {
|
mapL7Timer = setTimeout(async () => {
|
||||||
myChart = await chartView.drawChart({
|
myChart = await chartView.drawChart({
|
||||||
chartObj: myChart,
|
chartObj: myChart,
|
||||||
container: containerId,
|
container: containerId,
|
||||||
chart: chart,
|
chart: chart,
|
||||||
action
|
action
|
||||||
})
|
});
|
||||||
|
|
||||||
// 清除已有比例尺
|
// 清除已有比例尺
|
||||||
if (scaleControl) {
|
if (!scaleControl) {
|
||||||
myChart.getScene()?.removeControl(scaleControl)
|
scaleControl = new Scale({
|
||||||
scaleControl = null
|
position: 'bottomleft',
|
||||||
|
imperial: false
|
||||||
|
});
|
||||||
|
myChart.getScene()?.addControl(scaleControl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建并添加新比例尺
|
// 创建并添加新比例尺
|
||||||
scaleControl = new Scale({
|
|
||||||
position: 'bottomleft',
|
|
||||||
imperial: false
|
|
||||||
})
|
|
||||||
myChart.getScene()?.addControl(scaleControl)
|
|
||||||
|
|
||||||
myChart?.render()
|
|
||||||
callback?.()
|
// 添加全屏控件
|
||||||
emit('resetLoading')
|
if (fullscreenControl) {
|
||||||
}, 500)
|
|
||||||
}
|
} else {
|
||||||
|
fullscreenControl = new Fullscreen({
|
||||||
|
position: 'bottomright',
|
||||||
|
});
|
||||||
|
myChart.getScene()?.addControl(fullscreenControl, 'bottomright');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ====== 使用高德地图原生API实现卫星图层切换 ======
|
||||||
|
let satelliteLayer: any = null;
|
||||||
|
let isSatelliteVisible = false;
|
||||||
|
|
||||||
|
class SatelliteControl extends Control {
|
||||||
|
protected onAdd() {
|
||||||
|
const btn = document.createElement('button');
|
||||||
|
btn.className = 'l7-control-button l7-satellite-control';
|
||||||
|
btn.innerHTML = '卫星';
|
||||||
|
// btn.title = '切换到卫星视图';
|
||||||
|
btn.style.backgroundColor = '#000';
|
||||||
|
btn.style.color = '#fff';
|
||||||
|
btn.style.padding = '2px';
|
||||||
|
btn.style.borderRadius = '4px';
|
||||||
|
btn.style.cursor = 'pointer'
|
||||||
|
btn.style.fontSize = '11px';
|
||||||
|
const scene = myChart.getScene()
|
||||||
|
// 确保地图加载完成
|
||||||
|
scene.on('loaded', () => {
|
||||||
|
// 创建高德卫星图层
|
||||||
|
satelliteLayer = new window.AMap.TileLayer.Satellite();
|
||||||
|
btn.onclick = () => {
|
||||||
|
isSatelliteVisible = !isSatelliteVisible;
|
||||||
|
|
||||||
|
if (isSatelliteVisible) {
|
||||||
|
// 使用 scene.addLayer 方法添加卫星图层
|
||||||
|
btn.style.backgroundColor = '#409eff';
|
||||||
|
scene.map.add(satelliteLayer)
|
||||||
|
} else {
|
||||||
|
// 使用 scene.removeLayer 方法移除卫星图层
|
||||||
|
btn.style.backgroundColor = '#000';
|
||||||
|
scene.map.remove(satelliteLayer)
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return btn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加控件到地图
|
||||||
|
// 移除之前的卫星控件(如果存在)
|
||||||
|
if (satelliteControlInstance) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// 添加新的卫星控件到地图
|
||||||
|
satelliteControlInstance = new SatelliteControl({ position: 'bottomright' });
|
||||||
|
myChart.getScene()?.addControl(satelliteControlInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ====== 修复完成 ======
|
||||||
|
|
||||||
|
myChart?.render();
|
||||||
|
callback?.();
|
||||||
|
emit('resetLoading');
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
const pointClickTrans = () => {
|
const pointClickTrans = () => {
|
||||||
if (embeddedCallBack.value === 'yes') {
|
if (embeddedCallBack.value === 'yes') {
|
||||||
trackClick('pointClick')
|
trackClick('pointClick')
|
||||||
@ -706,15 +773,8 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="canvas-area">
|
<div class="canvas-area">
|
||||||
<view-track-bar
|
<view-track-bar ref="viewTrack" :track-menu="trackMenu" :font-family="fontFamily" :is-data-v-mobile="dataVMobile"
|
||||||
ref="viewTrack"
|
class="track-bar" :style="state.trackBarStyle" @trackClick="trackClick" />
|
||||||
:track-menu="trackMenu"
|
|
||||||
:font-family="fontFamily"
|
|
||||||
:is-data-v-mobile="dataVMobile"
|
|
||||||
class="track-bar"
|
|
||||||
:style="state.trackBarStyle"
|
|
||||||
@trackClick="trackClick"
|
|
||||||
/>
|
|
||||||
<div v-if="!isError" ref="chartContainer" class="canvas-content" :id="containerId"></div>
|
<div v-if="!isError" ref="chartContainer" class="canvas-content" :id="containerId"></div>
|
||||||
<chart-error v-else :err-msg="errMsg" />
|
<chart-error v-else :err-msg="errMsg" />
|
||||||
</div>
|
</div>
|
||||||
@ -726,12 +786,32 @@ onBeforeUnmount(() => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
|
||||||
.canvas-content {
|
.canvas-content {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: 100% !important;
|
height: 100% !important;
|
||||||
|
|
||||||
:deep(.g2-tooltip) {
|
:deep(.g2-tooltip) {
|
||||||
position: fixed !important;
|
position: fixed !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
:deep(.l7-button-control) {
|
||||||
|
background-color: #000000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.l7-button-control:not(:disabled):hover) {
|
||||||
|
background-color: #000000d5 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.l7-button-control .l7-iconfont) {
|
||||||
|
fill: #fff !important;
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// :deep(.l7-control-container .l7-top) {
|
||||||
|
// top: auto !important;
|
||||||
|
// bottom: 133px !important;
|
||||||
|
|
||||||
|
// }</style>
|
||||||
|
@ -16,7 +16,6 @@ import {
|
|||||||
} from 'vue'
|
} from 'vue'
|
||||||
import { getData } from '@/api/data-visualization/chart'
|
import { getData } from '@/api/data-visualization/chart'
|
||||||
import chartViewManager from '@/data-visualization/chart/components/js/panel'
|
import chartViewManager from '@/data-visualization/chart/components/js/panel'
|
||||||
import { useAppStoreWithOut } from '@/data-visualization/store/modules/app'
|
|
||||||
import { dvMainStoreWithOut } from '@/data-visualization/store/modules/data-visualization/dvMain'
|
import { dvMainStoreWithOut } from '@/data-visualization/store/modules/data-visualization/dvMain'
|
||||||
import ViewTrackBar from '@/data-visualization/components/visualization/ViewTrackBar.vue'
|
import ViewTrackBar from '@/data-visualization/components/visualization/ViewTrackBar.vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
@ -125,6 +124,7 @@ const state = reactive({
|
|||||||
imgEnlarge: false,
|
imgEnlarge: false,
|
||||||
imgSrc: ''
|
imgSrc: ''
|
||||||
})
|
})
|
||||||
|
const PAGE_CHARTS = ['table-info', 'table-normal']
|
||||||
// 图表数据不用全响应式
|
// 图表数据不用全响应式
|
||||||
let chartData = shallowRef<Partial<Chart['data']>>({
|
let chartData = shallowRef<Partial<Chart['data']>>({
|
||||||
fields: []
|
fields: []
|
||||||
@ -133,19 +133,20 @@ let chartData = shallowRef<Partial<Chart['data']>>({
|
|||||||
const containerId = 'container-' + showPosition.value + '-' + view.value.id + '-' + suffixId.value
|
const containerId = 'container-' + showPosition.value + '-' + view.value.id + '-' + suffixId.value
|
||||||
const viewTrack = ref(null)
|
const viewTrack = ref(null)
|
||||||
|
|
||||||
const calcData = (view: Chart, callback, resetPageInfo = true) => {
|
const calcData = (viewInfo: Chart, callback, resetPageInfo = true) => {
|
||||||
if (view.customAttr.basicStyle.tablePageStyle === 'general') {
|
if (viewInfo.customAttr.basicStyle.tablePageStyle === 'general') {
|
||||||
if (state.currentPageSize !== 0) {
|
if (state.currentPageSize !== 0) {
|
||||||
view.chartExtRequest.pageSize = state.currentPageSize
|
viewInfo.chartExtRequest.pageSize = state.currentPageSize
|
||||||
|
state.pageInfo.pageSize = state.currentPageSize
|
||||||
|
} else {
|
||||||
|
viewInfo.chartExtRequest.pageSize = state.pageInfo.pageSize
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(view.chartExtRequest != undefined){
|
delete viewInfo.chartExtRequest?.pageSize
|
||||||
delete view.chartExtRequest.pageSize
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (view.tableId || view['dataFrom'] === 'template') {
|
if (viewInfo.tableId || viewInfo['dataFrom'] === 'template') {
|
||||||
isError.value = false
|
isError.value = false
|
||||||
const v = JSON.parse(JSON.stringify(view))
|
const v = JSON.parse(JSON.stringify(viewInfo))
|
||||||
getData(v)
|
getData(v)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.code && res.code !== 0) {
|
if (res.code && res.code !== 0) {
|
||||||
@ -154,7 +155,7 @@ const calcData = (view: Chart, callback, resetPageInfo = true) => {
|
|||||||
} else {
|
} else {
|
||||||
chartData.value = res?.data as Partial<Chart['data']>
|
chartData.value = res?.data as Partial<Chart['data']>
|
||||||
state.totalItems = res?.totalItems
|
state.totalItems = res?.totalItems
|
||||||
dvMainStore.setViewDataDetails(view.id, res)
|
dvMainStore.setViewDataDetails(viewInfo.id, res)
|
||||||
emit('onDrillFilters', res?.drillFilters)
|
emit('onDrillFilters', res?.drillFilters)
|
||||||
renderChart(res as unknown as Chart, resetPageInfo)
|
renderChart(res as unknown as Chart, resetPageInfo)
|
||||||
}
|
}
|
||||||
@ -225,7 +226,7 @@ const renderChart = (viewInfo: Chart, resetPageInfo: boolean) => {
|
|||||||
nextTick(() => debounceRender(resetPageInfo))
|
nextTick(() => debounceRender(resetPageInfo))
|
||||||
}
|
}
|
||||||
|
|
||||||
const debounceRender = debounce(resetPageInfo => {
|
const debounceRender = debounce(() => {
|
||||||
myChart?.facet?.timer?.stop()
|
myChart?.facet?.timer?.stop()
|
||||||
myChart?.facet?.cancelScrollFrame()
|
myChart?.facet?.cancelScrollFrame()
|
||||||
myChart?.destroy()
|
myChart?.destroy()
|
||||||
@ -250,19 +251,13 @@ const debounceRender = debounce(resetPageInfo => {
|
|||||||
|
|
||||||
const setupPage = (chart: ChartObj, resetPageInfo?: boolean) => {
|
const setupPage = (chart: ChartObj, resetPageInfo?: boolean) => {
|
||||||
const customAttr = chart.customAttr
|
const customAttr = chart.customAttr
|
||||||
if (chart.type !== 'table-info' || customAttr.basicStyle.tablePageMode !== 'page') {
|
if (!PAGE_CHARTS.includes(chart.type) || customAttr.basicStyle.tablePageMode !== 'page') {
|
||||||
state.showPage = false
|
state.showPage = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const pageInfo = state.pageInfo
|
const pageInfo = state.pageInfo
|
||||||
state.pageStyle = customAttr.basicStyle.tablePageStyle
|
state.pageStyle = customAttr.basicStyle.tablePageStyle
|
||||||
if (state.pageStyle === 'general') {
|
if (state.pageStyle !== 'general') {
|
||||||
if (state.currentPageSize === 0) {
|
|
||||||
state.currentPageSize = pageInfo.pageSize
|
|
||||||
} else {
|
|
||||||
pageInfo.pageSize = state.currentPageSize
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pageInfo.pageSize = customAttr.basicStyle.tablePageSize ?? 20
|
pageInfo.pageSize = customAttr.basicStyle.tablePageSize ?? 20
|
||||||
}
|
}
|
||||||
if (state.totalItems > state.pageInfo.pageSize || state.pageStyle === 'general') {
|
if (state.totalItems > state.pageInfo.pageSize || state.pageStyle === 'general') {
|
||||||
@ -274,6 +269,7 @@ const setupPage = (chart: ChartObj, resetPageInfo?: boolean) => {
|
|||||||
if (resetPageInfo) {
|
if (resetPageInfo) {
|
||||||
state.pageInfo.currentPage = 1
|
state.pageInfo.currentPage = 1
|
||||||
}
|
}
|
||||||
|
dvMainStore.setViewPageInfo(chart.id, state.pageInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
const mouseMove = () => {
|
const mouseMove = () => {
|
||||||
@ -295,7 +291,8 @@ const initScroll = () => {
|
|||||||
myChart &&
|
myChart &&
|
||||||
senior?.scrollCfg?.open &&
|
senior?.scrollCfg?.open &&
|
||||||
chartData.value.tableRow?.length &&
|
chartData.value.tableRow?.length &&
|
||||||
(view.value.type === 'table-normal' || (view.value.type === 'table-info' && !state.showPage))
|
PAGE_CHARTS.includes(props.view.type) &&
|
||||||
|
!state.showPage
|
||||||
) {
|
) {
|
||||||
// 防止多次渲染
|
// 防止多次渲染
|
||||||
myChart.facet.timer?.stop()
|
myChart.facet.timer?.stop()
|
||||||
@ -339,7 +336,7 @@ const initScroll = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const showPage = computed(() => {
|
const showPage = computed(() => {
|
||||||
if (view.value.type !== 'table-info') {
|
if (!PAGE_CHARTS.includes(view.value.type)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return state.showPage
|
return state.showPage
|
||||||
@ -357,6 +354,7 @@ const handleCurrentChange = pageNum => {
|
|||||||
const handlePageSizeChange = pageSize => {
|
const handlePageSizeChange = pageSize => {
|
||||||
if (state.pageStyle === 'general') {
|
if (state.pageStyle === 'general') {
|
||||||
state.currentPageSize = pageSize
|
state.currentPageSize = pageSize
|
||||||
|
emitter.emit('set-page-size', pageSize)
|
||||||
}
|
}
|
||||||
let extReq = { pageSize: pageSize }
|
let extReq = { pageSize: pageSize }
|
||||||
if (chartExtRequest.value) {
|
if (chartExtRequest.value) {
|
||||||
@ -403,10 +401,9 @@ const action = param => {
|
|||||||
state.trackBarStyle.top = barStyleTemp.top + 'px'
|
state.trackBarStyle.top = barStyleTemp.top + 'px'
|
||||||
}
|
}
|
||||||
|
|
||||||
viewTrack.value.trackButtonClick()
|
viewTrack.value.trackButtonClick(view.value.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const appStore = useAppStoreWithOut()
|
|
||||||
|
|
||||||
const trackClick = trackAction => {
|
const trackClick = trackAction => {
|
||||||
const param = state.pointParam
|
const param = state.pointParam
|
||||||
@ -683,12 +680,6 @@ const autoStyle = computed(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const autoHeightStyle = computed(() => {
|
|
||||||
return {
|
|
||||||
height: 20 * scale.value + 8 + 'px'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const tabStyle = computed(() => [
|
const tabStyle = computed(() => [
|
||||||
{ '--de-pager-color': canvasStyleData.value.component.seniorStyleSetting?.pagerColor }
|
{ '--de-pager-color': canvasStyleData.value.component.seniorStyleSetting?.pagerColor }
|
||||||
])
|
])
|
||||||
@ -745,7 +736,7 @@ const tablePageClass = computed(() => {
|
|||||||
v-else
|
v-else
|
||||||
class="table-page-content"
|
class="table-page-content"
|
||||||
layout="prev, pager, next, sizes, jumper"
|
layout="prev, pager, next, sizes, jumper"
|
||||||
v-model:page-size="state.currentPageSize"
|
v-model:page-size="state.pageInfo.pageSize"
|
||||||
v-model:current-page="state.pageInfo.currentPage"
|
v-model:current-page="state.pageInfo.currentPage"
|
||||||
:pager-count="5"
|
:pager-count="5"
|
||||||
:total="state.pageInfo.total"
|
:total="state.pageInfo.total"
|
||||||
|
@ -4,7 +4,7 @@ import { ref } from 'vue'
|
|||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
const props = defineProps({
|
defineProps({
|
||||||
errMsg: {
|
errMsg: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<script lang="tsx" setup>
|
<script lang="tsx" setup>
|
||||||
import { computed, reactive, watch } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
import { useI18n } from '@/data-visualization/hooks/web/useI18n'
|
||||||
import { reverseColor } from '../util/util'
|
|
||||||
import { ArrowRight } from '@element-plus/icons-vue'
|
import { ArrowRight } from '@element-plus/icons-vue'
|
||||||
import { dvMainStoreWithOut } from '@/data-visualization/store/modules/data-visualization/dvMain'
|
import { dvMainStoreWithOut } from '@/data-visualization/store/modules/data-visualization/dvMain'
|
||||||
const dvMainStore = dvMainStoreWithOut()
|
const dvMainStore = dvMainStoreWithOut()
|
||||||
@ -27,51 +26,16 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emit = defineEmits(['onDrillJump'])
|
const emit = defineEmits(['onDrillJump'])
|
||||||
|
|
||||||
const state = reactive({
|
|
||||||
textColor: '#bbbfc4'
|
|
||||||
})
|
|
||||||
|
|
||||||
const textColor = computed(
|
const textColor = computed(
|
||||||
() => dvMainStore.canvasStyleData.component.seniorStyleSetting.drillLayerColor
|
() => dvMainStore.canvasStyleData.component.seniorStyleSetting.drillLayerColor
|
||||||
)
|
)
|
||||||
|
|
||||||
// watch(
|
|
||||||
// [() => props.themeStyle?.backgroundColorSelect, () => props.themeStyle?.color],
|
|
||||||
// () => {
|
|
||||||
// loadThemeStyle()
|
|
||||||
// },
|
|
||||||
// { deep: true }
|
|
||||||
// )
|
|
||||||
|
|
||||||
const drillJump = index => {
|
const drillJump = index => {
|
||||||
if (index < props.drillFilters.length) {
|
if (index < props.drillFilters.length) {
|
||||||
emit('onDrillJump', index)
|
emit('onDrillJump', index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const loadThemeStyle = () => {
|
|
||||||
let themeStyle = null
|
|
||||||
if (props.themeStyle) {
|
|
||||||
themeStyle = JSON.parse(JSON.stringify(props.themeStyle))
|
|
||||||
if (themeStyle && themeStyle.commonBackground) {
|
|
||||||
const viewBGColor = themeStyle.commonBackground.color
|
|
||||||
if (viewBGColor !== '#FFFFFF') {
|
|
||||||
const reverseValue = reverseColor(viewBGColor)
|
|
||||||
state.textColor = reverseValue
|
|
||||||
} else {
|
|
||||||
state.textColor = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (themeStyle && themeStyle.backgroundColorSelect) {
|
|
||||||
const panelColor = themeStyle.color
|
|
||||||
if (panelColor !== '#FFFFFF') {
|
|
||||||
const reverseValue = reverseColor(panelColor)
|
|
||||||
state.textColor = reverseValue
|
|
||||||
} else {
|
|
||||||
state.textColor = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const drillPathVar = computed(() => [{ '--drill-color': textColor.value }])
|
const drillPathVar = computed(() => [{ '--drill-color': textColor.value }])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
<script lang="tsx" setup></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="scroll-shadow-content">tet</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.scroll-shadow-content {
|
||||||
|
z-index: 1;
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #ece7e7;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
</style>
|
@ -61,12 +61,13 @@ const dvMainStore = dvMainStoreWithOut()
|
|||||||
const { emitter } = useEmitt()
|
const { emitter } = useEmitt()
|
||||||
const dePreviewPopDialogRef = ref(null)
|
const dePreviewPopDialogRef = ref(null)
|
||||||
let innerRefreshTimer = null
|
let innerRefreshTimer = null
|
||||||
|
let innerSearchCount = 0
|
||||||
const appStore = useAppStoreWithOut()
|
const appStore = useAppStoreWithOut()
|
||||||
const appearanceStore = useAppearanceStoreWithOut()
|
const appearanceStore = useAppearanceStoreWithOut()
|
||||||
const isDataEaseBi = computed(() => appStore.getIsDataEaseBi)
|
const isDataEaseBi = computed(() => appStore.getIsDataEaseBi)
|
||||||
const isIframe = computed(() => appStore.getIsIframe)
|
const isIframe = computed(() => appStore.getIsIframe)
|
||||||
|
|
||||||
const emit = defineEmits(['onPointClick'])
|
const emit = defineEmits(['onPointClick', 'onComponentEvent'])
|
||||||
|
|
||||||
const {
|
const {
|
||||||
nowPanelJumpInfo,
|
nowPanelJumpInfo,
|
||||||
@ -76,11 +77,15 @@ const {
|
|||||||
canvasStyleData,
|
canvasStyleData,
|
||||||
mobileInPc,
|
mobileInPc,
|
||||||
inMobile,
|
inMobile,
|
||||||
editMode,
|
editMode
|
||||||
hiddenListStatus
|
|
||||||
} = storeToRefs(dvMainStore)
|
} = storeToRefs(dvMainStore)
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
// 公共参数集
|
||||||
|
commonParams: {
|
||||||
|
type: Object,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
active: {
|
active: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
@ -234,6 +239,7 @@ const buildInnerRefreshTimer = (
|
|||||||
innerRefreshTimer = setInterval(() => {
|
innerRefreshTimer = setInterval(() => {
|
||||||
clearViewLinkage()
|
clearViewLinkage()
|
||||||
queryData()
|
queryData()
|
||||||
|
innerSearchCount++
|
||||||
}, timerRefreshTime)
|
}, timerRefreshTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,14 +250,6 @@ const clearViewLinkage = () => {
|
|||||||
useEmitt().emitter.emit('clearPanelLinkage', { viewId: element.value.id })
|
useEmitt().emitter.emit('clearPanelLinkage', { viewId: element.value.id })
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
|
||||||
[() => view.value],
|
|
||||||
() => {
|
|
||||||
initTitle()
|
|
||||||
},
|
|
||||||
{ deep: true }
|
|
||||||
)
|
|
||||||
|
|
||||||
watch([() => scale.value], () => {
|
watch([() => scale.value], () => {
|
||||||
initTitle()
|
initTitle()
|
||||||
})
|
})
|
||||||
@ -374,17 +372,29 @@ const chartClick = param => {
|
|||||||
|
|
||||||
// 仪表板和大屏所有额外过滤参数都在此处
|
// 仪表板和大屏所有额外过滤参数都在此处
|
||||||
const filter = (firstLoad?: boolean) => {
|
const filter = (firstLoad?: boolean) => {
|
||||||
// const { filter } = useFilter(view.value.id, firstLoad)
|
const { filter } = useFilter(view.value.id, firstLoad)
|
||||||
// return {
|
const result = {
|
||||||
// user: wsCache.get('user.uid'),
|
user: wsCache.get('user.uid'),
|
||||||
// filter,
|
filter,
|
||||||
// linkageFilters: element.value.linkageFilters,
|
linkageFilters: element.value.linkageFilters,
|
||||||
// outerParamsFilters: element.value.outerParamsFilters,
|
outerParamsFilters: element.value.outerParamsFilters,
|
||||||
// webParamsFilters: element.value.webParamsFilters,
|
webParamsFilters: element.value.webParamsFilters,
|
||||||
// drill: state.drillClickDimensionList,
|
drill: state.drillClickDimensionList,
|
||||||
// resultCount: resultCount.value,
|
resultCount: resultCount.value,
|
||||||
// resultMode: resultMode.value
|
resultMode: resultMode.value
|
||||||
// }
|
}
|
||||||
|
// 定时报告相关勿动
|
||||||
|
if (route.path === '/preview' && route.query.taskId) {
|
||||||
|
const sceneId = view.value['sceneId']
|
||||||
|
const filterJson = window[`de-report-filter-${sceneId}`]
|
||||||
|
let filterObj = {}
|
||||||
|
if (filterJson) {
|
||||||
|
filterObj = JSON.parse(filterJson)
|
||||||
|
}
|
||||||
|
filterObj[view.value.id] = result
|
||||||
|
window[`de-report-filter-${sceneId}`] = JSON.stringify(filterObj)
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDrillFilters = param => {
|
const onDrillFilters = param => {
|
||||||
@ -457,9 +467,16 @@ const jumpClick = param => {
|
|||||||
if (isDataEaseBi.value) {
|
if (isDataEaseBi.value) {
|
||||||
embeddedBaseUrl = embeddedStore.baseUrl
|
embeddedBaseUrl = embeddedStore.baseUrl
|
||||||
}
|
}
|
||||||
|
const jumpInfoParam = `&jumpInfoParam=${encodeURIComponent(
|
||||||
|
Base64.encode(JSON.stringify(param))
|
||||||
|
)}`
|
||||||
|
|
||||||
// 内部仪表板跳转
|
// 内部仪表板跳转
|
||||||
if (jumpInfo.linkType === 'inner') {
|
if (jumpInfo.linkType === 'inner') {
|
||||||
if (jumpInfo.targetDvId) {
|
if (jumpInfo.targetDvId) {
|
||||||
|
const editPreviewParams = ['canvas', 'edit-preview'].includes(showPosition.value)
|
||||||
|
? '&editPreview=true'
|
||||||
|
: ''
|
||||||
const filterOuterParams = {}
|
const filterOuterParams = {}
|
||||||
const curFilter = dvMainStore.getLastViewRequestInfo(param.viewId)
|
const curFilter = dvMainStore.getLastViewRequestInfo(param.viewId)
|
||||||
const targetViewInfoList = jumpInfo.targetViewInfoList
|
const targetViewInfoList = jumpInfo.targetViewInfoList
|
||||||
@ -492,13 +509,11 @@ const jumpClick = param => {
|
|||||||
if (publicLinkStatus.value) {
|
if (publicLinkStatus.value) {
|
||||||
// 判断是否有公共链接ID
|
// 判断是否有公共链接ID
|
||||||
if (jumpInfo.publicJumpId) {
|
if (jumpInfo.publicJumpId) {
|
||||||
let url = `${embeddedBaseUrl}#/de-link/${
|
let url = `${embeddedBaseUrl}#/de-link/${jumpInfo.publicJumpId}?fromLink=true&dvType=${jumpInfo.targetDvType}`
|
||||||
jumpInfo.publicJumpId
|
|
||||||
}?fromLink=true&jumpInfoParam=${encodeURIComponent(
|
|
||||||
Base64.encode(JSON.stringify(param))
|
|
||||||
)}`
|
|
||||||
if (attachParamsInfo) {
|
if (attachParamsInfo) {
|
||||||
url = url + attachParamsInfo
|
url = url + attachParamsInfo + jumpInfoParam + editPreviewParams
|
||||||
|
} else {
|
||||||
|
url = url + '&ignoreParams=true' + jumpInfoParam + editPreviewParams
|
||||||
}
|
}
|
||||||
const currentUrl = window.location.href
|
const currentUrl = window.location.href
|
||||||
localStorage.setItem('beforeJumpUrl', currentUrl)
|
localStorage.setItem('beforeJumpUrl', currentUrl)
|
||||||
@ -507,11 +522,11 @@ const jumpClick = param => {
|
|||||||
ElMessage.warning(t('visualization.public_link_tips'))
|
ElMessage.warning(t('visualization.public_link_tips'))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let url = `${embeddedBaseUrl}#/preview?dvId=${
|
let url = `${embeddedBaseUrl}#/preview?dvId=${jumpInfo.targetDvId}&fromLink=true&dvType=${jumpInfo.targetDvType}`
|
||||||
jumpInfo.targetDvId
|
|
||||||
}&fromLink=true&jumpInfoParam=${encodeURIComponent(Base64.encode(JSON.stringify(param)))}`
|
|
||||||
if (attachParamsInfo) {
|
if (attachParamsInfo) {
|
||||||
url = url + attachParamsInfo
|
url = url + attachParamsInfo + jumpInfoParam + editPreviewParams
|
||||||
|
} else {
|
||||||
|
url = url + '&ignoreParams=true' + jumpInfoParam + editPreviewParams
|
||||||
}
|
}
|
||||||
const currentUrl = window.location.href
|
const currentUrl = window.location.href
|
||||||
localStorage.setItem('beforeJumpUrl', currentUrl)
|
localStorage.setItem('beforeJumpUrl', currentUrl)
|
||||||
@ -567,13 +582,13 @@ const calcData = params => {
|
|||||||
methodName: 'calcData',
|
methodName: 'calcData',
|
||||||
args: [
|
args: [
|
||||||
params,
|
params,
|
||||||
res => {
|
() => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
chartComponent?.value?.calcData?.(params, res => {
|
chartComponent?.value?.calcData?.(params, () => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -691,10 +706,19 @@ const changeChartType = () => {
|
|||||||
const changeDataset = () => {
|
const changeDataset = () => {
|
||||||
checkFieldIsAllowEmpty()
|
checkFieldIsAllowEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loadPlugin = ref(false)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (!view.value.isPlugin) {
|
if (!view.value.isPlugin) {
|
||||||
state.drillClickDimensionList = view.value?.chartExtRequest?.drill ?? []
|
state.drillClickDimensionList = view.value?.chartExtRequest?.drill ?? []
|
||||||
queryData(!showPosition.value.includes('viewDialog'))
|
queryData(!showPosition.value.includes('viewDialog'))
|
||||||
|
} else {
|
||||||
|
const searched = dvMainStore.firstLoadMap.includes(element.value.id)
|
||||||
|
const queryFilter = filter(!searched)
|
||||||
|
view.value['chartExtRequest'] = queryFilter
|
||||||
|
chartExtRequest.value = queryFilter
|
||||||
|
loadPlugin.value = true
|
||||||
}
|
}
|
||||||
if (!listenerEnable.value) {
|
if (!listenerEnable.value) {
|
||||||
return
|
return
|
||||||
@ -829,7 +853,11 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 1.开启仪表板刷新 2.首次加载(searchCount =0 )3.正在请求数据 则显示加载状态
|
// 1.开启仪表板刷新 2.首次加载(searchCount =0 )3.正在请求数据 则显示加载状态
|
||||||
const loadingFlag = computed(() => {
|
const loadingFlag = computed(() => {
|
||||||
return (canvasStyleData.value.refreshViewLoading || searchCount.value === 0) && loading.value
|
return (
|
||||||
|
(canvasStyleData.value.refreshViewLoading ||
|
||||||
|
(searchCount.value === 0 && innerSearchCount === 0)) &&
|
||||||
|
loading.value
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const chartAreaShow = computed(() => {
|
const chartAreaShow = computed(() => {
|
||||||
@ -903,7 +931,7 @@ function onTitleChange() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const toolTip = computed(() => {
|
const toolTip = computed(() => {
|
||||||
return props.themes === 'dark' ? 'ndark' : 'dark'
|
return props.themes === 'dark' ? 'light' : 'dark'
|
||||||
})
|
})
|
||||||
|
|
||||||
const marginBottom = computed<string | 0>(() => {
|
const marginBottom = computed<string | 0>(() => {
|
||||||
@ -1033,6 +1061,14 @@ const titleTooltipWidth = computed(() => {
|
|||||||
}
|
}
|
||||||
return '500px'
|
return '500px'
|
||||||
})
|
})
|
||||||
|
const clearG2Tooltip = () => {
|
||||||
|
const g2TooltipWrapper = document.getElementById('g2-tooltip-wrapper')
|
||||||
|
if (g2TooltipWrapper) {
|
||||||
|
for (const ele of g2TooltipWrapper.children) {
|
||||||
|
ele.style.display = 'none'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -1123,7 +1159,7 @@ const titleTooltipWidth = computed(() => {
|
|||||||
<!--这里去渲染不同图库的图表-->
|
<!--这里去渲染不同图库的图表-->
|
||||||
<div v-if="allEmptyCheck || (chartAreaShow && !showEmpty)" style="flex: 1; overflow: hidden">
|
<div v-if="allEmptyCheck || (chartAreaShow && !showEmpty)" style="flex: 1; overflow: hidden">
|
||||||
<plugin-component
|
<plugin-component
|
||||||
v-if="view.plugin?.isPlugin"
|
v-if="view.plugin?.isPlugin && loadPlugin"
|
||||||
:jsname="view.plugin.staticMap['index']"
|
:jsname="view.plugin.staticMap['index']"
|
||||||
:scale="scale"
|
:scale="scale"
|
||||||
:dynamic-area-id="dynamicAreaId"
|
:dynamic-area-id="dynamicAreaId"
|
||||||
@ -1170,9 +1206,17 @@ const titleTooltipWidth = computed(() => {
|
|||||||
:themes="canvasStyleData.dashboard.themeColor"
|
:themes="canvasStyleData.dashboard.themeColor"
|
||||||
ref="chartComponent"
|
ref="chartComponent"
|
||||||
:view="view"
|
:view="view"
|
||||||
|
:element="element"
|
||||||
:show-position="showPosition"
|
:show-position="showPosition"
|
||||||
:suffixId="suffixId"
|
:suffixId="suffixId"
|
||||||
:font-family="fontFamily"
|
:font-family="fontFamily"
|
||||||
|
:common-params="commonParams"
|
||||||
|
@touchstart="clearG2Tooltip"
|
||||||
|
@onChartClick="chartClick"
|
||||||
|
@onPointClick="onPointClick"
|
||||||
|
@onDrillFilters="onDrillFilters"
|
||||||
|
@onJumpClick="jumpClick"
|
||||||
|
@onComponentEvent="() => emit('onComponentEvent')"
|
||||||
/>
|
/>
|
||||||
<chart-component-g2-plot
|
<chart-component-g2-plot
|
||||||
:scale="scale"
|
:scale="scale"
|
||||||
@ -1182,6 +1226,7 @@ const titleTooltipWidth = computed(() => {
|
|||||||
:element="element"
|
:element="element"
|
||||||
:suffixId="suffixId"
|
:suffixId="suffixId"
|
||||||
:font-family="fontFamily"
|
:font-family="fontFamily"
|
||||||
|
:active="active"
|
||||||
v-else-if="
|
v-else-if="
|
||||||
showChartView(ChartLibraryType.G2_PLOT, ChartLibraryType.L7_PLOT, ChartLibraryType.L7)
|
showChartView(ChartLibraryType.G2_PLOT, ChartLibraryType.L7_PLOT, ChartLibraryType.L7)
|
||||||
"
|
"
|
||||||
@ -1212,6 +1257,7 @@ const titleTooltipWidth = computed(() => {
|
|||||||
v-if="(!chartAreaShow || showEmpty) && !allEmptyCheck"
|
v-if="(!chartAreaShow || showEmpty) && !allEmptyCheck"
|
||||||
:themes="canvasStyleData.dashboard.themeColor"
|
:themes="canvasStyleData.dashboard.themeColor"
|
||||||
:view-icon="view.type"
|
:view-icon="view.type"
|
||||||
|
@touchstart="clearG2Tooltip"
|
||||||
></chart-empty-info>
|
></chart-empty-info>
|
||||||
<drill-path
|
<drill-path
|
||||||
:disabled="optType === 'enlarge'"
|
:disabled="optType === 'enlarge'"
|
||||||
@ -1240,6 +1286,7 @@ const titleTooltipWidth = computed(() => {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.title-container {
|
.title-container {
|
||||||
|
position: relative;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user