Merge branch 'dev-v2' into pr@dev-v2_dzz

This commit is contained in:
dataeaseShu 2024-09-14 16:42:12 +08:00
commit 0bdd56ca6a
16 changed files with 608 additions and 81 deletions

View File

@ -1,11 +1,32 @@
package io.dataease.chart.charts.impl.mix;
import io.dataease.chart.utils.ChartDataBuild;
import io.dataease.extensions.view.dto.AxisFormatResult;
import io.dataease.extensions.view.dto.ChartAxis;
import io.dataease.extensions.view.dto.ChartViewDTO;
import io.dataease.extensions.view.dto.CustomFilterResult;
import lombok.Getter;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Component
public class DualLineMixHandler extends GroupMixHandler {
@Getter
private final String type = "chart-mix-dual-line";
@Override
public Map<String, Object> buildNormalResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, List<String[]> data) {
boolean isDrill = filterResult
.getFilterList()
.stream()
.anyMatch(ele -> ele.getFilterType() == 1);
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var xAxisBase = xAxis.subList(0, xAxis.size() - xAxisExt.size());
return ChartDataBuild.transMixChartDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill, true);
}
}

View File

@ -55,11 +55,19 @@ public class MixHandler extends YoyChartHandler {
.getFilterList()
.stream()
.anyMatch(ele -> ele.getFilterType() == 1);
if (StringUtils.equals((String) formatResult.getContext().get("isRight"), "isRight")) {
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt);
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var xAxisBase = xAxis.subList(0, xAxis.size() - xAxisExt.size());
return ChartDataBuild.transMixChartDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill, true);
}
var xAxisBase = (List<ChartViewFieldDTO>) formatResult.getContext().get("xAxisBase");
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
var xAxis = formatResult.getAxisMap().get(ChartAxis.xAxis);
var xAxisExt = formatResult.getAxisMap().get(ChartAxis.xAxisExt);
var result = ChartDataBuild.transMixChartDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill);
var result = ChartDataBuild.transMixChartDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill, false);
return result;
}
@ -97,11 +105,6 @@ public class MixHandler extends YoyChartHandler {
AxisFormatResult formatResult2 = new AxisFormatResult();
var axisMap = new HashMap<ChartAxis, List<ChartViewFieldDTO>>();
axisMap.put(ChartAxis.xAxis, new ArrayList<>(formatResult.getAxisMap().get(ChartAxis.xAxis)));
axisMap.put(ChartAxis.extStack, new ArrayList<>());
axisMap.put(ChartAxis.xAxisExt, new ArrayList<>());
axisMap.put(ChartAxis.extBubble, new ArrayList<>(formatResult.getAxisMap().get(ChartAxis.extBubble)));
axisMap.put(ChartAxis.yAxisExt, new ArrayList<>(formatResult.getAxisMap().get(ChartAxis.yAxisExt)));
axisMap.put(ChartAxis.extLabel, new ArrayList<>(formatResult.getAxisMap().get(ChartAxis.extLabel)));
axisMap.put(ChartAxis.extTooltip, new ArrayList<>(formatResult.getAxisMap().get(ChartAxis.extTooltip)));
axisMap.put(ChartAxis.drill, new ArrayList<>(formatResult.getAxisMap().get(ChartAxis.drill)));
@ -110,18 +113,16 @@ public class MixHandler extends YoyChartHandler {
// 计算右轴包含 xAxis,xAxisExt,yAxisExt,需要去掉 group stack
var xAxis = new ArrayList<>(view.getXAxis());
var extStack = formatResult2.getAxisMap().get(ChartAxis.extStack);
var xAxisExt = formatResult2.getAxisMap().get(ChartAxis.xAxisExt);
//xAxis = xAxis.subList(0, xAxis.size() - extStack.size() - xAxisExt.size());
var extBubble = formatResult2.getAxisMap().get(ChartAxis.extBubble);
var extBubble = new ArrayList<>(formatResult.getAxisMap().get(ChartAxis.extBubble));
xAxis.addAll(extBubble);
var dillAxis = (ArrayList<ChartViewFieldDTO>) formatResult.getContext().get("dillAxis");
xAxis.addAll(dillAxis);
formatResult2.getAxisMap().put(ChartAxis.xAxis, xAxis);
formatResult2.getAxisMap().put(ChartAxis.xAxisExt, extBubble);
var yAxisExt = formatResult2.getAxisMap().get(ChartAxis.yAxisExt);
var yAxisExt = new ArrayList<>(formatResult.getAxisMap().get(ChartAxis.yAxisExt));
formatResult2.getAxisMap().put(ChartAxis.yAxis, yAxisExt);
formatResult2.getContext().remove("yoyFiltered");
formatResult2.getContext().put("isRight", "isRight");
formatResult.getContext().put("subAxisMap", axisMap);

View File

@ -1,6 +1,7 @@
package io.dataease.chart.utils;
import io.dataease.api.chart.dto.*;
import io.dataease.api.chart.dto.ScatterChartDataDTO;
import io.dataease.api.chart.dto.Series;
import io.dataease.extensions.view.dto.*;
import io.dataease.i18n.Lang;
import io.dataease.i18n.Translator;
@ -423,7 +424,7 @@ public class ChartDataBuild {
axisChartDataDTO.setValue(new BigDecimal(0));
}
axisChartDataDTO.setCategory(StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName()));
buildDynamicValue(view, axisChartDataDTO, row, size, ObjectUtils.isNotEmpty(extBubble)?extSize-1:extSize);
buildDynamicValue(view, axisChartDataDTO, row, size, ObjectUtils.isNotEmpty(extBubble) ? extSize - 1 : extSize);
// pop
if (ObjectUtils.isNotEmpty(extBubble)) {
try {
@ -504,6 +505,11 @@ public class ChartDataBuild {
// antV组合图形
public static Map<String, Object> transMixChartDataAntV(List<ChartViewFieldDTO> xAxisBase, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> xAxisExt, List<ChartViewFieldDTO> yAxis, ChartViewDTO view, List<String[]> data, boolean isDrill) {
return transMixChartDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill, false);
}
public static Map<String, Object> transMixChartDataAntV(List<ChartViewFieldDTO> xAxisBase, List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> xAxisExt, List<ChartViewFieldDTO> yAxis, ChartViewDTO view, List<String[]> data, boolean isDrill, boolean isLine) {
Map<String, Object> map = new HashMap<>();
List<Series> series = new ArrayList<>();
@ -571,8 +577,16 @@ public class ChartDataBuild {
} catch (Exception e) {
axisChartDataDTO.setValue(new BigDecimal(0));
}
String category = StringUtils.defaultIfBlank(b.toString(),
StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName()));
if (isLine) {
if (ObjectUtils.isEmpty(xAxisExt)) {
category = StringUtils.defaultIfBlank(yAxis.get(j).getChartShowName(), yAxis.get(j).getName());
}
}
axisChartDataDTO.setCategory(category);
categories.add(category);
@ -1764,7 +1778,7 @@ public class ChartDataBuild {
List<Map<String, Object>> tableRow = (List<Map<String, Object>>) map.get("tableRow");
final int xEndIndex = detailIndex;
Map<String, List<String[]>> groupDataList = detailData.stream().collect(Collectors.groupingBy(item -> "(" + StringUtils.join(ArrayUtils.subarray(item, 0, xEndIndex), ")-de-(") + ")"));
String extBubbleDataeaseName = ObjectUtils.isNotEmpty(extBubble)?extBubble.get(0).getDataeaseName():"";
String extBubbleDataeaseName = ObjectUtils.isNotEmpty(extBubble) ? extBubble.get(0).getDataeaseName() : "";
tableRow.forEach(row -> {
BigDecimal rowValue = row.get(extBubbleDataeaseName) == null ? BigDecimal.ZERO : new BigDecimal(row.get(extBubbleDataeaseName).toString());
String key = xAxis.stream().map(x -> String.format(format, row.get(x.getDataeaseName()).toString())).collect(Collectors.joining("-de-"));
@ -1773,16 +1787,16 @@ public class ChartDataBuild {
Map<String, Object> temp = new HashMap<>();
for (int i = 0; i < realDetailFields.size(); i++) {
ChartViewFieldDTO realDetailField = realDetailFields.get(i);
if(StringUtils.equalsIgnoreCase(extBubbleDataeaseName,realDetailField.getDataeaseName())){
if (StringUtils.equalsIgnoreCase(extBubbleDataeaseName, realDetailField.getDataeaseName())) {
temp.put(realDetailField.getDataeaseName(), rowValue);
}else{
} else {
temp.put(realDetailField.getDataeaseName(), detailArr[detailIndex + i]);
}
}
return temp;
})).collect(Collectors.toList());
//详情只要一个
row.put("details", !detailValueMapList.isEmpty() ?Collections.singletonList(detailValueMapList.getFirst()):detailValueMapList);
row.put("details", !detailValueMapList.isEmpty() ? Collections.singletonList(detailValueMapList.getFirst()) : detailValueMapList);
});
// 先过滤掉所有记录数字段
List<ChartViewFieldDTO> filterCountAxis = fields.stream()

View File

@ -8,7 +8,6 @@ import io.dataease.constant.CommonConstants;
import io.dataease.dataset.server.DatasetFieldServer;
import io.dataease.engine.constant.DeTypeConstants;
import io.dataease.exception.DEException;
import io.dataease.extensions.datasource.dto.DatasetTableFieldDTO;
import io.dataease.extensions.view.dto.ChartExtFilterDTO;
import io.dataease.extensions.view.dto.ChartExtRequest;
import io.dataease.extensions.view.dto.ChartViewDTO;
@ -50,6 +49,12 @@ public class CoreVisualizationExportManage {
@Resource
private DatasetFieldServer datasetFieldServer;
public String getResourceName(Long dvId, String busiFlag) {
DataVisualizationVO visualization = extDataVisualizationMapper.findDvInfo(dvId, busiFlag);
if (ObjectUtils.isEmpty(visualization)) DEException.throwException("资源不存在或已经被删除...");
return visualization.getName();
}
public File exportExcel(Long dvId, String busiFlag, List<Long> viewIdList, boolean onlyDisplay) throws Exception {
DataVisualizationVO visualization = extDataVisualizationMapper.findDvInfo(dvId, busiFlag);
if (ObjectUtils.isEmpty(visualization)) DEException.throwException("资源不存在或已经被删除...");
@ -73,27 +78,14 @@ public class CoreVisualizationExportManage {
}
view.getChartExtRequest().setUser(AuthUtils.getUser().getUserId());
view.setTitle((i + 1) + "-" + view.getTitle());
sheets.add(exportViewData(view));
sheets.addAll(exportViewData(view));
}
return VisualizationExcelUtils.exportExcel(sheets, visualization.getName(), visualization.getId().toString());
}
private ExcelSheetModel exportViewData(ChartViewDTO request) {
private ExcelSheetModel exportSingleData(Map<String, Object> chart, String title) {
ExcelSheetModel result = new ExcelSheetModel();
ChartViewDTO chartViewDTO = null;
if (CommonConstants.VIEW_DATA_FROM.TEMPLATE.equalsIgnoreCase(request.getDataFrom())) {
chartViewDTO = extendDataManage.getChartDataInfo(request.getId(), request);
} else {
try {
chartViewDTO = chartDataManage.calcData(request);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
String title = chartViewDTO.getTitle();
Map<String, Object> chart = chartViewDTO.getData();
Object objectFields = chart.get("fields");
List<ChartViewFieldDTO> fields = (List<ChartViewFieldDTO>) objectFields;
List<String> heads = new ArrayList<>();
@ -116,6 +108,9 @@ public class CoreVisualizationExportManage {
});
}
Object objectTableRow = chart.get("tableRow");
if (objectTableRow == null) {
objectTableRow = chart.get("sourceData");
}
List<Map<String, Object>> tableRow = (List<Map<String, Object>>) objectTableRow;
List<List<String>> details = tableRow.stream().map(row -> {
@ -140,6 +135,40 @@ public class CoreVisualizationExportManage {
return result;
}
private List<ExcelSheetModel> exportViewData(ChartViewDTO request) {
ChartViewDTO chartViewDTO = null;
request.setIsExcelExport(true);
if (CommonConstants.VIEW_DATA_FROM.TEMPLATE.equalsIgnoreCase(request.getDataFrom())) {
chartViewDTO = extendDataManage.getChartDataInfo(request.getId(), request);
} else {
try {
chartViewDTO = chartDataManage.calcData(request);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
String title = chartViewDTO.getTitle();
Map<String, Object> chart = chartViewDTO.getData();
List<ExcelSheetModel> resultList = new ArrayList<>();
boolean leftExist = ObjectUtils.isNotEmpty(chart.get("left"));
boolean rightExist = ObjectUtils.isNotEmpty(chart.get("right"));
if (!leftExist && !rightExist) {
ExcelSheetModel sheetModel = exportSingleData(chart, title);
resultList.add(sheetModel);
return resultList;
}
if (leftExist) {
ExcelSheetModel sheetModel = exportSingleData((Map<String, Object>) chart.get("left"), title + "_left");
resultList.add(sheetModel);
}
if (rightExist) {
ExcelSheetModel sheetModel = exportSingleData((Map<String, Object>) chart.get("right"), title + "_right");
resultList.add(sheetModel);
}
return resultList;
}
private String filterInvalidDecimal(String sourceNumberStr) {
if (StringUtils.isNotBlank(sourceNumberStr) && StringUtils.contains(sourceNumberStr, ".")) {
sourceNumberStr = sourceNumberStr.replaceAll("0+?$", "");

View File

@ -0,0 +1,357 @@
<script setup lang="ts">
import CommonAttr from '@/custom-component/common/CommonAttr.vue'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
import { storeToRefs } from 'pinia'
import { ElIcon, ElMessage } from 'element-plus-secondary'
import { ref, onMounted, onBeforeUnmount, watch, PropType, reactive, toRefs, computed } from 'vue'
import { beforeUploadCheck, uploadFileResult } from '@/api/staticResource'
import { imgUrlTrans } from '@/utils/imgUtils'
import eventBus from '@/utils/eventBus'
import ImgViewDialog from '@/custom-component/ImgViewDialog.vue'
import DatasetSelect from '@/views/chart/components/editor/dataset-select/DatasetSelect.vue'
import Icon from '../../components/icon-custom/src/Icon.vue'
import { useI18n } from '@/hooks/web/useI18n'
import { cloneDeep } from 'lodash-es'
import FilterTree from '@/views/chart/components/editor/filter/FilterTree.vue'
const { t } = useI18n()
const props = defineProps({
themes: {
type: String as PropType<EditorTheme>,
default: 'dark'
}
})
const dvMainStore = dvMainStoreWithOut()
const snapshotStore = snapshotStoreWithOut()
const { curComponent } = storeToRefs(dvMainStore)
const fileList = ref([])
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const uploadDisabled = ref(false)
const files = ref(null)
const maxImageSize = 15000000
const handlePictureCardPreview = file => {
dialogImageUrl.value = file.url
dialogVisible.value = true
}
const handleRemove = (_, fileList) => {
uploadDisabled.value = false
curComponent.value.propValue.url = null
fileList.value = []
snapshotStore.recordSnapshotCache()
}
async function upload(file) {
uploadFileResult(file.file, fileUrl => {
snapshotStore.recordSnapshotCache()
curComponent.value.propValue.url = fileUrl
})
}
const onStyleChange = () => {
snapshotStore.recordSnapshotCache()
}
const goFile = () => {
files.value.click()
}
const reUpload = e => {
const file = e.target.files[0]
if (file.size > maxImageSize) {
sizeMessage()
return
}
uploadFileResult(file, fileUrl => {
snapshotStore.recordSnapshotCache()
curComponent.value.propValue.url = fileUrl
fileList.value = [{ url: imgUrlTrans(curComponent.value.propValue.url) }]
})
}
const sizeMessage = () => {
ElMessage.success('图片大小不符合')
}
const init = () => {
if (curComponent.value.propValue.url) {
fileList.value = [{ url: imgUrlTrans(curComponent.value.propValue.url) }]
} else {
fileList.value = []
}
}
const toolTip = computed(() => {
return props.themes === 'dark' ? 'ndark' : 'dark'
})
watch(
() => curComponent.value.propValue.url,
() => {
init()
}
)
onMounted(() => {
init()
eventBus.on('uploadImg', goFile)
})
onBeforeUnmount(() => {
eventBus.off('uploadImg', goFile)
})
</script>
<template>
<div class="attr-list de-collapse-style">
<input
id="input"
ref="files"
type="file"
accept=".jpeg,.jpg,.png,.gif,.svg"
hidden
@click="
e => {
e.target.value = ''
}
"
@change="reUpload"
/>
<CommonAttr
:themes="themes"
:element="curComponent"
:background-color-picker-width="197"
:background-border-select-width="197"
>
<el-collapse-item :effect="themes" title="图片组" name="picture">
<el-row class="img-area" :class="`img-area_${themes}`">
<el-col style="width: 130px !important">
<el-upload
:themes="themes"
action=""
accept=".jpeg,.jpg,.png,.gif,.svg"
class="avatar-uploader"
list-type="picture-card"
:class="{ disabled: uploadDisabled }"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:before-upload="beforeUploadCheck"
:http-request="upload"
:file-list="fileList"
>
<el-icon><Plus /></el-icon>
</el-upload>
<img-view-dialog v-model="dialogVisible" :image-url="dialogImageUrl"></img-view-dialog>
</el-col>
</el-row>
<el-row>
<span
style="margin-top: 2px"
v-if="!curComponent.propValue.url"
class="image-hint"
:class="`image-hint_${themes}`"
>
支持JPGPNGGIFSVG
</span>
<el-button
size="small"
style="margin: 8px 0 0 -4px"
v-if="curComponent.propValue.url"
text
@click="goFile"
>
重新上传
</el-button>
</el-row>
<el-row class="pic-adaptor">
<el-form-item
v-if="curComponent.style.adaptation"
class="form-item"
label="图片适应方式"
size="small"
:effect="themes"
:class="'form-item-' + themes"
>
<el-radio-group
size="small"
v-model="curComponent.style.adaptation"
@change="onStyleChange"
:effect="themes"
>
<el-radio label="adaptation" :effect="themes">适应组件</el-radio>
<el-radio label="original" :effect="themes">原始尺寸</el-radio>
<el-radio label="equiratio" :effect="themes">等比适应</el-radio>
</el-radio-group>
</el-form-item>
</el-row>
</el-collapse-item>
</CommonAttr>
</div>
</template>
<style lang="less" scoped>
.de-collapse-style {
:deep(.ed-collapse-item__header) {
height: 36px !important;
line-height: 36px !important;
font-size: 12px !important;
padding: 0 !important;
font-weight: 500 !important;
.ed-collapse-item__arrow {
margin: 0 6px 0 8px;
}
}
:deep(.ed-collapse-item__content) {
padding: 16px 8px 0;
}
:deep(.ed-form-item) {
display: block;
margin-bottom: 8px;
}
:deep(.ed-form-item__label) {
justify-content: flex-start;
}
}
.disabled :deep(.el-upload--picture-card) {
display: none;
}
.avatar-uploader :deep(.ed-upload) {
width: 80px;
height: 80px;
line-height: 90px;
}
.avatar-uploader :deep(.ed-upload-list li) {
width: 80px !important;
height: 80px !important;
}
:deep(.ed-upload--picture-card) {
background: #eff0f1;
border: 1px dashed #dee0e3;
border-radius: 4px;
.ed-icon {
color: #1f2329;
}
&:hover {
.ed-icon {
color: var(--ed-color-primary);
}
}
}
.img-area {
height: 80px;
width: 80px;
margin-top: 10px;
overflow: hidden;
&.img-area_dark {
:deep(.ed-upload-list__item).is-success {
border-color: #434343;
}
:deep(.ed-upload--picture-card) {
background: #373737;
border-color: #434343;
.ed-icon {
color: #ebebeb;
}
&:hover {
.ed-icon {
color: var(--ed-color-primary);
}
}
}
}
&.img-area_light {
:deep(.ed-upload-list__item).is-success {
border-color: #dee0e3;
}
}
}
.image-hint {
color: #8f959e;
size: 14px;
line-height: 22px;
font-weight: 400;
margin-top: 2px;
&.image-hint_dark {
color: #757575;
}
}
.re-update-span {
cursor: pointer;
color: var(--ed-color-primary);
size: 14px;
line-height: 22px;
font-weight: 400;
}
.pic-adaptor {
margin: 8px 0 16px 0;
:deep(.ed-form-item__content) {
margin-top: 8px !important;
}
}
.form-item-dark {
.ed-radio {
margin-right: 4px !important;
}
}
.drag-data {
padding-top: 8px;
padding-bottom: 16px;
.tree-btn {
width: 100%;
margin-top: 8px;
background: #fff;
height: 32px;
border-radius: 4px;
border: 1px solid #dcdfe6;
display: flex;
color: #cccccc;
align-items: center;
cursor: pointer;
justify-content: center;
font-size: 12px;
&.tree-btn--dark {
background: rgba(235, 235, 235, 0.05);
border-color: #5f5f5f;
}
&.active {
color: #3370ff;
border-color: #3370ff;
}
}
&.no-top-border {
border-top: none !important;
}
&.no-top-padding {
padding-top: 0 !important;
}
&:nth-child(n + 2) {
border-top: 1px solid @side-outline-border-color;
}
&:first-child {
border-top: none !important;
}
}
</style>

View File

@ -0,0 +1,90 @@
<template>
<div class="pic-main" @click="onPictureClick">
<img
draggable="false"
v-if="propValue['url']"
:style="imageAdapter"
:src="imgUrlTrans(propValue['url'])"
/>
<div v-else class="pic-upload">
<span
><el-button @click="uploadImg" text style="color: #646a73" icon="Plus"
>请上传图片...</el-button
></span
>
</div>
</div>
</template>
<script setup lang="ts">
import { CSSProperties, computed, nextTick, toRefs } from 'vue'
import { imgUrlTrans } from '@/utils/imgUtils'
import eventBus from '@/utils/eventBus'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
const dvMainStore = dvMainStoreWithOut()
const props = defineProps({
propValue: {
type: String,
required: true,
default: ''
},
element: {
type: Object,
default() {
return {
propValue: null
}
}
}
})
const { propValue, element } = toRefs(props)
const imageAdapter = computed(() => {
const style = {
position: 'relative',
width: '100%',
height: '100%'
}
if (element.value.style.adaptation === 'original') {
style.width = 'auto'
style.height = 'auto'
} else if (element.value.style.adaptation === 'equiratio') {
style.height = 'auto'
}
return style as CSSProperties
})
const onPictureClick = e => {
if (element.value.events && element.value.events.checked) {
if (element.value.events.type === 'displayChange') {
//
nextTick(() => {
dvMainStore.popAreaActiveSwitch()
})
}
}
}
const uploadImg = () => {
nextTick(() => {
eventBus.emit('uploadImg')
})
}
</script>
<style lang="less" scoped>
.pic-main {
overflow: hidden;
width: 100%;
height: 100%;
cursor: pointer;
}
.pic-upload {
display: flex;
width: 100%;
height: 100%;
color: #5370af;
align-items: center;
justify-content: center;
}
</style>

View File

@ -35,6 +35,8 @@ import ScrollText from '@/custom-component/scroll-text/Component.vue'
import ScrollTextAttr from '@/custom-component/scroll-text/Attr.vue'
import PopArea from '@/custom-component/pop-area/Component.vue'
import PopAreaAttr from '@/custom-component/pop-area/Attr.vue'
import PictureGroup from '@/custom-component/picture-group/Component.vue'
import PictureGroupAttr from '@/custom-component/picture-group/Attr.vue'
export const componentsMap = {
VText: VText,
VQuery,
@ -72,7 +74,9 @@ export const componentsMap = {
ScrollText: ScrollText,
ScrollTextAttr: ScrollTextAttr,
PopArea: PopArea,
PopAreaAttr: PopAreaAttr
PopAreaAttr: PopAreaAttr,
PictureGroup: PictureGroup,
PictureGroupAttr: PictureGroupAttr
}
export default function findComponent(key) {

View File

@ -3,7 +3,6 @@ import router from '@/router'
import { usePermissionStoreWithOut } from '@/store/modules/permission'
import { interactiveStoreWithOut } from '@/store/modules/interactive'
import { useCache } from '@/hooks/web/useCache'
import request from '@/config/axios'
const { wsCache } = useCache()
const permissionStore = usePermissionStoreWithOut()
@ -11,12 +10,6 @@ const userStore = useUserStoreWithOut()
const interactiveStore = interactiveStoreWithOut()
export const logoutHandler = (justClean?: boolean) => {
const idToken = wsCache.get('oauth2-id-token')
if (idToken) {
request.get({ url: `/oauth2/logout/${idToken}` }).finally(() => {
wsCache.delete('oauth2-id-token')
})
}
userStore.clear()
userStore.$reset()
permissionStore.clear()

View File

@ -1508,14 +1508,14 @@ export const CHART_TYPE_CONFIGS = [
},
{
category: 'other',
title: '图片',
title: '图片',
display: 'hidden',
details: [
{
render: 'custom',
category: 'quota',
value: 'Picture',
title: '图片',
value: 'picture-group',
title: '图片',
icon: 'picture'
}
]

View File

@ -1,19 +0,0 @@
import { AbstractChartView, ChartLibraryType, ChartRenderType } from '../../types'
import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
/**
* 富文本图表
*/
export class PictureChartView extends AbstractChartView {
properties: EditorProperty[] = ['background-overall-component', 'border-style']
propertyInner: EditorPropertyInner = {
'background-overall-component': ['all'],
'border-style': ['all']
}
axis: AxisType[] = ['filter']
axisConfig: AxisConfig = {}
constructor() {
super(ChartRenderType.CUSTOM, ChartLibraryType.PICTURE, 'Picture')
}
}

View File

@ -870,9 +870,9 @@ export class DualLineMix extends ColumnLineMix {
p[n.id] = n
return p
}, {})
const { yAxis, extStack } = chart
const { yAxis, xAxisExt } = chart
const { data } = options as unknown as Options
if (extStack?.length) {
if (xAxisExt?.length) {
const seriesSet = new Set()
data[0]?.forEach(d => d.category !== null && seriesSet.add(d.category))
const tmp = [...seriesSet]
@ -917,8 +917,8 @@ export class DualLineMix extends ColumnLineMix {
const result: ChartBasicStyle['seriesColor'] = []
const seriesSet = new Set<string>()
const colors = chart.customAttr.basicStyle.colors
const { yAxis, extStack } = chart
if (extStack?.length) {
const { yAxis, xAxisExt } = chart
if (xAxisExt?.length) {
data?.forEach(d => {
if (d.value === null || d.category === null || seriesSet.has(d.category)) {
return

View File

@ -0,0 +1,35 @@
import { AbstractChartView, ChartLibraryType, ChartRenderType } from '../../types'
import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
/**
* 图片组图表
*/
export class PictureGroupView extends AbstractChartView {
properties: EditorProperty[] = [
'background-overall-component',
'border-style',
'threshold',
'function-cfg'
]
propertyInner: EditorPropertyInner = {
'background-overall-component': ['all'],
'border-style': ['all'],
threshold: ['tableThreshold'],
'function-cfg': ['emptyDataStrategy']
}
axis: AxisType[] = ['xAxis', 'yAxis', 'filter']
axisConfig: AxisConfig = {
xAxis: {
name: `${t('chart.dimension')}`,
type: 'd'
},
yAxis: {
name: `${t('chart.quota')}`,
type: 'q'
}
}
constructor() {
super(ChartRenderType.CUSTOM, ChartLibraryType.PICTURE_GROUP, 'picture-group')
}
}

View File

@ -15,7 +15,7 @@ export enum ChartLibraryType {
ECHARTS = 'echarts',
S2 = 's2',
RICH_TEXT = 'rich-text',
PICTURE = 'Picture',
PICTURE_GROUP = 'picture_group',
INDICATOR = 'indicator'
}
export abstract class ChartWrapper<O> {

View File

@ -47,7 +47,7 @@ import { storeToRefs } from 'pinia'
import { checkAddHttp, setIdValueTrans } from '@/utils/canvasUtils'
import { Base64 } from 'js-base64'
import DeRichTextView from '@/custom-component/rich-text/DeRichTextView.vue'
import DePictureV2 from '@/custom-component/picture/Component.vue'
import DePictureGroup from '@/custom-component/picture-group/component.vue'
import ChartEmptyInfo from '@/views/chart/components/views/components/ChartEmptyInfo.vue'
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
import { viewFieldTimeTrans } from '@/utils/viewUtils'
@ -123,12 +123,13 @@ const props = defineProps({
const dynamicAreaId = ref('')
const { view, showPosition, element, active, searchCount, scale } = toRefs(props)
const titleShow = computed(
() =>
!['rich-text', 'Picture'].includes('rich-text') &&
const titleShow = computed(() => {
return (
!['rich-text', 'Picture'].includes(element.value.innerType) &&
state.title_show &&
showPosition.value !== 'viewDialog'
)
)
})
const snapshotStore = snapshotStoreWithOut()
const state = reactive({
@ -904,11 +905,15 @@ const loadPluginCategory = data => {
@onJumpClick="jumpClick"
@resetLoading="() => (loading = false)"
/>
<de-picture-v2
<de-picture-group
v-else-if="showChartView(ChartLibraryType.PICTURE_GROUP)"
:themes="canvasStyleData.dashboard.themeColor"
ref="chartComponent"
:element="element"
:prop-value="element.propValue"
v-else-if="showChartView(ChartLibraryType.PICTURE)"
></de-picture-v2>
:active="active"
:show-position="showPosition"
>
</de-picture-group>
<de-rich-text-view
v-else-if="showChartView(ChartLibraryType.RICH_TEXT)"
:themes="canvasStyleData.dashboard.themeColor"

@ -1 +1 @@
Subproject commit d883d74073867950a4347dc50b417c3093298e60
Subproject commit bf9cd45f206458e3bfa385e451f56e74dea334ee

View File

@ -6,7 +6,6 @@ import io.dataease.api.xpack.settings.vo.XpackOauthAuthVO;
import io.dataease.api.xpack.settings.vo.XpackOauthTokenVO;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -20,6 +19,4 @@ public interface XpackOauth2Api {
@PostMapping("/token")
XpackOauthTokenVO oauth2Token(@RequestBody XpackOauth2TokenRequest request);
@GetMapping("/logout/{idToken}")
void logout(@PathVariable("idToken") String idToken);
}