Merge branch 'dev-v2' of github.com:dataease/dataease into dev-v2

This commit is contained in:
wangjiahao 2024-07-01 17:27:26 +08:00
commit d64db55f50
15 changed files with 213 additions and 72 deletions

View File

@ -71,6 +71,7 @@ public class GroupMixHandler extends MixHandler {
rightFields.addAll(view.getYAxisExt());
var rightOriginData = rightCalcResult.getOriginData();
var rightTable = ChartDataBuild.transTableNormal(rightFields, view, rightOriginData, desensitizationList);
mergeAssistField(rightCalcResult.getDynamicAssistFields(), rightCalcResult.getAssistData());
var rightData = new HashMap<String, Object>(rightTable);
rightData.putAll(rightCalcResult.getData());
rightData.put("dynamicAssistLines", rightCalcResult.getDynamicAssistFields());

View File

@ -157,6 +157,7 @@ public class MixHandler extends YoyChartHandler {
mergeAssistField(rightCalcResult.getDynamicAssistFields(), rightCalcResult.getAssistData());
var rightOriginData = rightCalcResult.getOriginData();
var rightTable = ChartDataBuild.transTableNormal(rightFields, view, rightOriginData, desensitizationList);
mergeAssistField(rightCalcResult.getDynamicAssistFields(), rightCalcResult.getAssistData());
var rightData = new HashMap<String, Object>(rightTable);
rightData.putAll(rightCalcResult.getData());
rightData.put("dynamicAssistLines", rightCalcResult.getDynamicAssistFields());

View File

@ -87,6 +87,7 @@ public class StackMixHandler extends MixHandler {
rightFields.addAll(view.getYAxisExt());
var rightOriginData = rightCalcResult.getOriginData();
var rightTable = ChartDataBuild.transTableNormal(rightFields, view, rightOriginData, desensitizationList);
mergeAssistField(rightCalcResult.getDynamicAssistFields(), rightCalcResult.getAssistData());
var rightData = new HashMap<String, Object>(rightTable);
rightData.putAll(rightCalcResult.getData());
rightData.put("dynamicAssistLines", rightCalcResult.getDynamicAssistFields());

View File

@ -60,7 +60,6 @@ const renameInput = ref([])
const valueSource = ref([])
const conditions = ref([])
const checkAll = ref(false)
const multiple = ref(false)
const activeConditionForRename = reactive({
id: '',
name: '',
@ -209,12 +208,59 @@ const handleCheckAllChange = (val: boolean) => {
curComponent.value.checkedFields = val ? fields.value.map(ele => ele.componentId) : []
isIndeterminate.value = false
}
const setTreeDefault = () => {
if (!!curComponent.value.checkedFields.length) {
let checkId = ''
let tableId = ''
let comId = ''
fields.value.forEach(ele => {
if (
curComponent.value.checkedFields.includes(ele.componentId) &&
curComponent.value.checkedFieldsMap[ele.componentId] &&
!checkId
) {
checkId = curComponent.value.checkedFieldsMap[ele.componentId]
comId = ele.componentId
tableId = datasetFieldList.value.find(itx => itx.id === ele.componentId)?.tableId
}
})
if (checkId && tableId) {
const componentObj = fields.value.find(ele => ele.componentId === comId)
const fieldArr = (
curComponent.value.optionValueSource === 0
? componentObj?.fields?.dimensionList
: curComponent.value.dataset?.fields
).filter(ele => ele.deType === +curComponent.value.field.deType)
fields.value.forEach(ele => {
if (curComponent.value.checkedFields.includes(ele.componentId)) {
if (datasetFieldList.value.find(itx => itx.id === ele.componentId)?.tableId === tableId) {
curComponent.value.checkedFieldsMap[ele.componentId] = checkId
}
}
})
const fieldObj = fieldArr.find(element => element.id === checkId)
if (!!curComponent.value.treeFieldList.length) {
const [fir] = curComponent.value.treeFieldList
if (fir.field !== checkId) {
curComponent.value.treeFieldList = [fieldObj]
}
} else {
curComponent.value.treeFieldList = [fieldObj]
}
}
}
}
const handleCheckedFieldsChange = (value: string[]) => {
if (curComponent.value.displayType === '8') return
handleDialogClick()
const checkedCount = value.length
checkAll.value = checkedCount === fields.value.length
isIndeterminate.value = checkedCount > 0 && checkedCount < fields.value.length
if (curComponent.value.displayType === '8') return
if (curComponent.value.displayType === '9') {
setTreeDefault()
return
}
setType()
}
@ -281,6 +327,10 @@ const setTypeChange = () => {
) {
curComponent.value.timeGranularityMultiple = curComponent.value.timeGranularity
}
if (curComponent.value.displayType === '9') {
setTreeDefault()
}
})
}

View File

@ -1,7 +1,7 @@
<script lang="ts" setup>
import { guid } from '@/views/visualized/data/dataset/form/util.js'
import { ElMessage } from 'element-plus-secondary'
import { ref, shallowRef } from 'vue'
import { ref, shallowRef, computed } from 'vue'
import { cloneDeep } from 'lodash-es'
const dialogVisible = ref(false)
@ -24,6 +24,10 @@ const init = (arr, treeArr) => {
dialogVisible.value = true
}
const disableFieldArr = computed(() => {
return treeList.value.map(ele => ele.field)
})
const cancelClick = () => {
handleBeforeClose()
}
@ -87,8 +91,19 @@ defineExpose({
<div class="cascade-item" v-for="(ele, idx) in treeList" :key="ele.id">
<div class="label">层级{{ indexCascade[idx + 1] }}</div>
<div class="item-name">
<el-select value-key="id" v-model="ele.field" style="width: 300px">
<el-option v-for="item in datasetMap" :key="item.id" :label="item.name" :value="item" />
<el-select
:disabled="idx === 0 && ele.field"
value-key="id"
v-model="ele.field"
style="width: 300px"
>
<el-option
:disabled="disableFieldArr.includes(item.id)"
v-for="item in datasetMap"
:key="item.id"
:label="item.name"
:value="item"
/>
</el-select>
</div>
<el-button v-show="idx !== 0" @click="deleteCascade(idx)" class="cascade-delete" text>

View File

@ -123,9 +123,16 @@ const getValueByDefaultValueCheckOrFirstLoad = (
}
if (firstLoad && !selectValue?.length) {
return defaultValueCheck ? defaultValue : multiple ? [] : ''
return defaultValueCheck
? Array.isArray(defaultValue)
? defaultValue
: [defaultValue]
: multiple
? []
: ''
}
return selectValue || ''
return selectValue ? (Array.isArray(selectValue) ? selectValue : [selectValue]) : ''
}
export const useFilter = (curComponentId: string, firstLoad = false) => {

View File

@ -133,7 +133,6 @@ onMounted(() => {
<el-icon
class="preview-download_icon"
:class="navigateBg === 'light' && 'is-light-setting'"
style="margin: 0 10px"
>
<Icon name="dv-preview-download" @click="downloadClick" />
</el-icon>
@ -160,7 +159,6 @@ onMounted(() => {
<style lang="less" scoped>
.preview-download_icon {
margin: 0 10px;
padding: 5px;
height: 28px;
width: 28px;

View File

@ -375,7 +375,7 @@ em {
}
.color-dataV {
background: rgb(0, 214, 185)!important;
background: rgb(0, 214, 185) !important;
}
.color-dataset {
@ -426,7 +426,11 @@ strong {
color: #1f2329;
display: flex;
align-items: center;
padding-right: 20px;
padding-right: 24px;
}
.m50-export {
max-width: 200px;
}
.btn-text {
@ -498,9 +502,9 @@ strong {
// 解决screenfull全屏时 部分嵌入到body中的组件如 下来框 消息通知框等)被覆盖问题
// 这里使用的方案为直接将body全屏 区间组件覆盖整个body
.de-screen-full{
position:fixed !important;
z-index:200;
.de-screen-full {
position: fixed !important;
z-index: 200;
top: 0;
left: 0;
right: 0;

View File

@ -7,7 +7,7 @@ import cloneDeep from 'lodash-es/cloneDeep'
import defaultsDeep from 'lodash-es/defaultsDeep'
import { formatterType, unitType } from '../../../js/formatter'
import { fieldType } from '@/utils/attr'
import { defaultTo, partition, union } from 'lodash-es'
import { defaultTo, partition, map, includes } from 'lodash-es'
import chartViewManager from '../../../js/panel'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia'
@ -41,13 +41,7 @@ const toolTip = computed(() => {
})
const emit = defineEmits(['onTooltipChange', 'onExtTooltipChange'])
const curSeriesFormatter = ref<DeepPartial<SeriesFormatter>>({})
const realQuota = ref<Axis[]>(inject('quotaData'))
const yAxis = computed(() => {
return union(defaultTo(props.chart.yAxis, []), defaultTo(props.chart.yAxisExt, []))
})
const quotaData = computed<Axis[]>(() => {
return props.chart.type.includes('chart-mix') ? yAxis.value : realQuota.value
})
const quotaData = ref<Axis[]>(inject('quotaData'))
const showSeriesTooltipFormatter = computed(() => {
return showProperty('seriesTooltipFormatter') && !batchOptStatus.value && props.chart.id
})
@ -116,6 +110,18 @@ const quotaAxis = computed(() => {
})
return result
})
const quotaAxisIds = computed(() => {
return map(quotaAxis.value, a => a.id)
})
function showOption(item) {
if (props.chart.type.includes('chart-mix')) {
return includes(quotaAxisIds.value, item.id)
}
return true
}
const extTooltip = computed(() => {
const quotaIds = quotaAxis.value?.map(i => i.id)
return state.tooltipForm.seriesTooltipFormatter.filter(
@ -617,24 +623,25 @@ onMounted(() => {
/>
</el-icon>
</template>
<el-option
class="series-select-option"
:key="item.seriesId"
:value="item"
:label="`${item.name}${
item.summary !== '' ? '(' + t('chart.' + item.summary) + ')' : ''
}`"
v-for="item in state.tooltipForm.seriesTooltipFormatter"
>
<el-icon style="margin-right: 8px">
<Icon
:className="`field-icon-${fieldType[item.deType]}`"
:name="`field_${fieldType[item.deType]}`"
/>
</el-icon>
{{ item.name }}
{{ item.summary !== '' ? '(' + t('chart.' + item.summary) + ')' : '' }}
</el-option>
<template v-for="item in state.tooltipForm.seriesTooltipFormatter" :key="item.seriesId">
<el-option
class="series-select-option"
:value="item"
:label="`${item.name}${
item.summary !== '' ? '(' + t('chart.' + item.summary) + ')' : ''
}`"
v-if="showOption(item)"
>
<el-icon style="margin-right: 8px">
<Icon
:className="`field-icon-${fieldType[item.deType]}`"
:name="`field_${fieldType[item.deType]}`"
/>
</el-icon>
{{ item.name }}
{{ item.summary !== '' ? '(' + t('chart.' + item.summary) + ')' : '' }}
</el-option>
</template>
</el-select>
</el-form-item>
<template v-if="curSeriesFormatter?.seriesId">

View File

@ -7,6 +7,7 @@ import { flow, hexColorToRGBA, parseJson } from '@/views/chart/components/js/uti
import { LINE_EDITOR_PROPERTY_INNER } from '@/views/chart/components/js/panel/charts/line/common'
import { useI18n } from '@/hooks/web/useI18n'
import { valueFormatter } from '@/views/chart/components/js/formatter'
import { Options } from '@antv/g2plot/esm'
const { t } = useI18n()
const DEFAULT_DATA = []
@ -421,23 +422,19 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
const showFiled = chart.data.fields
const customTooltipItems = originalItems => {
const formattedItems = originalItems
.filter(item => item.value !== undefined)
.map(item => {
const fieldObj = showFiled.find(q => q.dataeaseName === item.name)
const displayName = fieldObj?.chartShowName || fieldObj?.name || item.name
const formattedName = displayName.startsWith('ma')
? displayName.toUpperCase()
: displayName
const formattedValue = valueFormatter(item.value, tooltipAttr.tooltipFormatter)
const formattedItems = originalItems.map(item => {
const fieldObj = showFiled.find(q => q.dataeaseName === item.name)
const displayName = fieldObj?.chartShowName || fieldObj?.name || item.name
const formattedName = displayName.startsWith('ma') ? displayName.toUpperCase() : displayName
const formattedValue = valueFormatter(item.value, tooltipAttr.tooltipFormatter)
return {
...item,
name: formattedName,
value: formattedValue,
color: item.color
}
})
return {
...item,
name: formattedName,
value: formattedValue,
color: item.color
}
})
const hasKLine = formattedItems.some(item => !item.name.startsWith('MA'))
const kLines = formattedItems.filter(item => !item.name.startsWith('MA'))
@ -469,7 +466,7 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
</div>
<div style="display: flex; justify-content: space-between; width: 100%;">
<span style="margin-right: 15px;">${item.name}</span>
<span>${item.value || ''}</span>
<span>${item.name.startsWith('MA') && item.value === '0' ? '-' : item.value}</span>
</div>
</li>
`
@ -489,6 +486,7 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
tooltip: {
showMarkers: true,
showCrosshairs: true,
showNil: true,
crosshairs: {
follow: false
},
@ -583,13 +581,45 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
}
}
protected customConfigEmptyDataStrategy(chart: Chart, options: MixOptions): MixOptions {
const { data } = options as unknown as Options
if (!data?.length) {
return options
}
const strategy = parseJson(chart.senior).functionCfg.emptyDataStrategy
if (strategy === 'ignoreData') {
for (let i = data.length - 1; i >= 0; i--) {
const item = data[i]
Object.keys(item).forEach(key => {
if (key.startsWith('f_') && item[key] === null) {
data.splice(i, 1)
}
})
}
}
const updateValues = (strategy: 'breakLine' | 'setZero', data: any[]) => {
data.forEach(obj => {
Object.keys(obj).forEach(key => {
if (obj[key] === null) {
obj[key] = strategy === 'breakLine' ? null : 0
}
})
})
}
if (strategy === 'breakLine' || strategy === 'setZero') {
updateValues(strategy, data)
}
return options
}
protected setupOptions(chart: Chart, options: MixOptions): MixOptions {
return flow(
this.configTheme,
this.configBasicStyle,
this.configXAxis,
this.configYAxis,
this.configTooltip
this.configTooltip,
this.customConfigEmptyDataStrategy
)(chart, options)
}

View File

@ -57,7 +57,7 @@ export class FlowMap extends L7ChartView<Scene, L7Config> {
}
const flowLineStyle = {
type: miscStyle.mapLineType,
size: miscStyle.mapLineWidth,
size: miscStyle.mapLineType === 'line' ? miscStyle.mapLineWidth / 2 : miscStyle.mapLineWidth,
animate: miscStyle.mapLineAnimate,
animateDuration: miscStyle.mapLineAnimateDuration,
gradient: miscStyle.mapLineGradient,

View File

@ -25,9 +25,7 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
'basic-style-selector',
'title-selector',
'label-selector',
'tooltip-selector',
'jump-set',
'linkage'
'tooltip-selector'
]
propertyInner: EditorPropertyInner = {
...MAP_EDITOR_PROPERTY_INNER,

View File

@ -76,7 +76,7 @@ const loadCanvasDataAsync = async (dvId, dvType) => {
const attachParamsEncode = router.currentRoute.value.query.attachParams
if (attachParamsEncode || hasTicketArgs) {
try {
if (!attachParam) {
if (!!attachParamsEncode) {
attachParam = JSON.parse(Base64.decode(decodeURIComponent(attachParamsEncode)))
}
if (hasTicketArgs) {

View File

@ -4,25 +4,39 @@ import { storeToRefs } from 'pinia'
import { useI18n } from '@/hooks/web/useI18n'
import { useAppStoreWithOut } from '@/store/modules/app'
import DvDetailInfo from '@/views/common/DvDetailInfo.vue'
import { useEmbedded } from '@/store/modules/embedded'
import { storeApi, storeStatusApi } from '@/api/visualization/dataVisualization'
import { ref, watch, computed } from 'vue'
import ShareVisualHead from '@/views/share/share/ShareVisualHead.vue'
import { XpackComponent } from '@/components/plugin'
import { useEmitt } from '@/hooks/web/useEmitt'
import DeFullscreen from '@/components/visualization/common/DeFullscreen.vue'
const dvMainStore = dvMainStoreWithOut()
const appStore = useAppStoreWithOut()
const { dvInfo } = storeToRefs(dvMainStore)
const emit = defineEmits(['reload', 'download', 'downloadAsAppTemplate'])
const { t } = useI18n()
const embeddedStore = useEmbedded()
const favorited = ref(false)
const fullScreeRef = ref(null)
const preview = () => {
if (isDataEaseBi.value) {
embeddedStore.clearState()
if (dvInfo.value.type === 'dataV') {
embeddedStore.setDvId(dvInfo.value.id)
} else {
embeddedStore.setResourceId(dvInfo.value.id)
}
useEmitt().emitter.emit('changeCurrentComponent', 'Preview')
return
}
const url = '#/preview?dvId=' + dvInfo.value.id
const newWindow = window.open(url, '_blank')
initOpenHandler(newWindow)
}
const isDataEaseBi = computed(() => appStore.getIsDataEaseBi)
const isIframe = computed(() => appStore.getIsIframe)
const reload = () => {
emit('reload', dvInfo.value.id)
@ -36,6 +50,19 @@ const downloadAsAppTemplate = downloadType => {
}
const dvEdit = () => {
if (isDataEaseBi.value) {
embeddedStore.clearState()
if (dvInfo.value.type === 'dataV') {
embeddedStore.setDvId(dvInfo.value.id)
} else {
embeddedStore.setResourceId(dvInfo.value.id)
}
useEmitt().emitter.emit(
'changeCurrentComponent',
dvInfo.value.type === 'dataV' ? 'VisualizationEditor' : 'DashboardEditor'
)
return
}
const baseUrl = dvInfo.value.type === 'dataV' ? '#/dvCanvas?dvId=' : '#/dashboard?resourceId='
const newWindow = window.open(baseUrl + dvInfo.value.id, '_blank')
initOpenHandler(newWindow)
@ -105,13 +132,13 @@ const initOpenHandler = newWindow => {
</div>
<div class="canvas-opt-button">
<de-fullscreen ref="fullScreeRef"></de-fullscreen>
<el-button v-if="!isDataEaseBi" secondary @click="() => fullScreeRef.toggleFullscreen()">
<el-button v-if="!isIframe" secondary @click="() => fullScreeRef.toggleFullscreen()">
<template #icon>
<icon name="icon_pc_fullscreen"></icon>
</template>
全屏</el-button
>
<el-button secondary v-if="!isDataEaseBi" @click="preview()">
<el-button secondary @click="preview()">
<template #icon>
<icon name="icon_pc_outlined"></icon>
</template>
@ -122,12 +149,7 @@ const initOpenHandler = newWindow => {
:weight="dvInfo.weight"
:resource-type="dvInfo.type"
/>
<el-button
class="custom-button"
v-if="dvInfo.weight > 6 && !isDataEaseBi"
type="primary"
@click="dvEdit()"
>
<el-button class="custom-button" v-if="dvInfo.weight > 6" type="primary" @click="dvEdit()">
<template #icon>
<icon name="icon_edit_outlined"></icon>
</template>

View File

@ -174,7 +174,14 @@ const openMessageLoading = (text, type = 'success', cb) => {
const customClass = `de-message-${type || 'success'} de-message-export`
ElMessage({
message: h('p', null, [
t(text),
h(
'span',
{
title: t(text),
class: 'ellipsis m50-export'
},
t(text)
),
h(
ElButton,
{