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

This commit is contained in:
dataeaseShu 2024-11-22 17:47:58 +08:00
commit 690d294a28
42 changed files with 316 additions and 99 deletions

View File

@ -394,7 +394,11 @@ public class ChartDataServer implements ChartDataApi {
detailsSheet.setColumnWidth(j, 255 * 20);
} else if (cellValObj != null) {
try {
cell.setCellValue(cellValObj.toString());
if ((excelTypes[j].equals(DeTypeConstants.DE_INT) || excelTypes[j].equals(DeTypeConstants.DE_FLOAT)) && StringUtils.isNotEmpty(cellValObj.toString())) {
cell.setCellValue(Double.valueOf(cellValObj.toString()));
} else if (cellValObj != null) {
cell.setCellValue(cellValObj.toString());
}
} catch (Exception e) {
LogUtil.warn("export excel data transform error");
}

View File

@ -70,7 +70,7 @@ public class DatasourceSyncManage {
if (updateType.equals(DatasourceServer.UpdateType.all_scope)) {
createEngineTable(TableUtils.tmpName(datasourceRequest.getTable()), tableFields);
}
extractExcelData(datasourceRequest, updateType);
extractExcelData(datasourceRequest, updateType, tableFields);
if (updateType.equals(DatasourceServer.UpdateType.all_scope)) {
replaceTable(datasourceRequest.getTable());
}
@ -145,7 +145,7 @@ public class DatasourceSyncManage {
if (updateType.equals(DatasourceServer.UpdateType.all_scope)) {
createEngineTable(TableUtils.tmpName(datasourceRequest.getTable()), tableFields);
}
extractApiData(datasourceRequest, updateType);
extractApiData(datasourceRequest, updateType, tableFields);
if (updateType.equals(DatasourceServer.UpdateType.all_scope)) {
replaceTable(datasourceRequest.getTable());
}
@ -198,7 +198,7 @@ public class DatasourceSyncManage {
if (updateType.equals(DatasourceServer.UpdateType.all_scope)) {
createEngineTable(TableUtils.tmpName(datasourceRequest.getTable()), tableFields);
}
extractApiData(datasourceRequest, updateType);
extractApiData(datasourceRequest, updateType, tableFields);
if (updateType.equals(DatasourceServer.UpdateType.all_scope)) {
replaceTable(datasourceRequest.getTable());
}
@ -222,20 +222,10 @@ public class DatasourceSyncManage {
}
}
private void extractApiData(DatasourceRequest datasourceRequest, DatasourceServer.UpdateType extractType) throws Exception {
private void extractApiData(DatasourceRequest datasourceRequest, DatasourceServer.UpdateType extractType, List<TableField> tableFields) throws Exception {
Map<String, Object> result = ApiUtils.fetchResultField(datasourceRequest);
List<String[]> dataList = (List<String[]>) result.get("dataList");
String engineTableName;
switch (extractType) {
case all_scope:
engineTableName = TableUtils.tmpName(TableUtils.tableName(datasourceRequest.getTable()));
break;
default:
engineTableName = TableUtils.tableName(datasourceRequest.getTable());
break;
}
CoreDeEngine engine = engineManage.info();
EngineRequest engineRequest = new EngineRequest();
engineRequest.setEngine(engine);
EngineProvider engineProvider = ProviderUtil.getEngineProvider(engine.getType());
@ -246,14 +236,13 @@ public class DatasourceSyncManage {
} else {
totalPage = dataList.size() / pageNumber;
}
for (int page = 1; page <= totalPage; page++) {
engineRequest.setQuery(engineProvider.insertSql(engineTableName, dataList, page, pageNumber));
engineRequest.setQuery(engineProvider.insertSql(datasourceRequest.getTable(), extractType, dataList, page, pageNumber, tableFields));
calciteProvider.exec(engineRequest);
}
}
private void extractExcelData(DatasourceRequest datasourceRequest, DatasourceServer.UpdateType extractType) throws Exception {
private void extractExcelData(DatasourceRequest datasourceRequest, DatasourceServer.UpdateType extractType, List<TableField> tableFields) throws Exception {
ExcelUtils excelUtils = new ExcelUtils();
List<String[]> dataList = excelUtils.fetchDataList(datasourceRequest);
String engineTableName;
@ -278,7 +267,7 @@ public class DatasourceSyncManage {
totalPage = dataList.size() / pageNumber;
}
for (int page = 1; page <= totalPage; page++) {
engineRequest.setQuery(engineProvider.insertSql(engineTableName, dataList, page, pageNumber));
engineRequest.setQuery(engineProvider.insertSql(engineTableName, extractType, dataList, page, pageNumber, tableFields));
calciteProvider.exec(engineRequest);
}
}

View File

@ -580,6 +580,7 @@ public class ApiUtils {
o.put("checked", true);
o.put("name", field.getName());
o.put("primaryKey", field.isPrimaryKey());
o.put("length", field.getLength());
o.put("deExtractType", field.getDeExtractType());
}
}

View File

@ -2,6 +2,7 @@ package io.dataease.datasource.provider;
import io.dataease.datasource.dao.auto.entity.CoreDeEngine;
import io.dataease.datasource.request.EngineRequest;
import io.dataease.datasource.server.DatasourceServer;
import io.dataease.extensions.datasource.dto.TableField;
import java.util.List;
@ -21,7 +22,7 @@ public abstract class EngineProvider {
public abstract String createTableSql(String name, List<TableField> tableFields, CoreDeEngine engine);
public abstract String insertSql(String name, List<String[]> dataList, int page, int pageNumber);
public abstract String insertSql(String tableName, DatasourceServer.UpdateType extractType, List<String[]> dataList, int page, int pageNumber, List<TableField> tableFields);
}

View File

@ -3,20 +3,11 @@ package io.dataease.datasource.provider;
import io.dataease.dataset.utils.TableUtils;
import io.dataease.datasource.dao.auto.entity.CoreDeEngine;
import io.dataease.datasource.request.EngineRequest;
import io.dataease.datasource.type.H2;
import io.dataease.datasource.type.Mysql;
import io.dataease.extensions.datasource.dto.ConnectionObj;
import io.dataease.extensions.datasource.dto.DatasourceDTO;
import io.dataease.datasource.server.DatasourceServer;
import io.dataease.extensions.datasource.dto.TableField;
import io.dataease.extensions.datasource.vo.DatasourceConfiguration;
import io.dataease.utils.BeanUtils;
import io.dataease.utils.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.Arrays;
import java.util.List;
@ -34,8 +25,17 @@ public class H2EngineProvider extends EngineProvider {
}
@Override
public String insertSql(String name, List<String[]> dataList, int page, int pageNumber) {
String insertSql = "INSERT INTO `TABLE_NAME` VALUES ".replace("TABLE_NAME", name);
public String insertSql(String tableName, DatasourceServer.UpdateType extractType, List<String[]> dataList, int page, int pageNumber,List<TableField> tableFields) {
String engineTableName;
switch (extractType) {
case all_scope:
engineTableName = TableUtils.tmpName(TableUtils.tableName(tableName));
break;
default:
engineTableName = TableUtils.tableName(tableName);
break;
}
String insertSql = "INSERT INTO `TABLE_NAME` VALUES ".replace("TABLE_NAME", engineTableName);
StringBuffer values = new StringBuffer();
Integer realSize = page * pageNumber < dataList.size() ? page * pageNumber : dataList.size();
@ -88,7 +88,11 @@ public class H2EngineProvider extends EngineProvider {
int size = tableField.getPrecision() * 4;
switch (tableField.getDeType()) {
case 0:
columnFields.append("varchar(2048)").append(",`");
if (StringUtils.isNotEmpty(tableField.getLength())) {
columnFields.append("varchar(length)".replace("length", tableField.getLength())).append(",`");
} else {
columnFields.append("longtext").append(",`");
}
break;
case 1:
columnFields.append("varchar(2048)").append(",`");
@ -103,7 +107,7 @@ public class H2EngineProvider extends EngineProvider {
columnFields.append("TINYINT(length)".replace("length", String.valueOf(tableField.getPrecision()))).append(",`");
break;
default:
columnFields.append("varchar(2048)").append(",`");
columnFields.append("longtext").append(",`");
break;
}
}

View File

@ -3,21 +3,15 @@ package io.dataease.datasource.provider;
import io.dataease.dataset.utils.TableUtils;
import io.dataease.datasource.dao.auto.entity.CoreDeEngine;
import io.dataease.datasource.request.EngineRequest;
import io.dataease.datasource.type.Mysql;
import io.dataease.extensions.datasource.dto.ConnectionObj;
import io.dataease.extensions.datasource.dto.DatasourceDTO;
import io.dataease.datasource.server.DatasourceServer;
import io.dataease.extensions.datasource.dto.TableField;
import io.dataease.extensions.datasource.vo.DatasourceConfiguration;
import io.dataease.utils.BeanUtils;
import io.dataease.utils.JsonUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Author gin
@ -37,8 +31,18 @@ public class MysqlEngineProvider extends EngineProvider {
}
@Override
public String insertSql(String name, List<String[]> dataList, int page, int pageNumber) {
String insertSql = "INSERT INTO `TABLE_NAME` VALUES ".replace("TABLE_NAME", name);
public String insertSql(String tableName, DatasourceServer.UpdateType extractType, List<String[]> dataList, int page, int pageNumber, List<TableField> tableFields) {
String engineTableName;
switch (extractType) {
case all_scope:
engineTableName = TableUtils.tmpName(TableUtils.tableName(tableName));
break;
default:
engineTableName = TableUtils.tableName(tableName);
break;
}
String insertSql = "INSERT INTO `TABLE_NAME` VALUES ".replace("TABLE_NAME", engineTableName);
StringBuffer values = new StringBuffer();
Integer realSize = page * pageNumber < dataList.size() ? page * pageNumber : dataList.size();
@ -54,7 +58,18 @@ public class MysqlEngineProvider extends EngineProvider {
values.append("('").append(String.join("','", Arrays.asList(strings1)))
.append("'),");
}
return (insertSql + values.substring(0, values.length() - 1)).replaceAll("'null'", "null");
List<TableField> keys = tableFields.stream().filter(TableField::isPrimaryKey).toList();
List<TableField> notKeys = tableFields.stream().filter(tableField -> !tableField.isPrimaryKey()).toList();
String insetSql = (insertSql + values.substring(0, values.length() - 1)).replaceAll("'null'", "null");
if (CollectionUtils.isNotEmpty(keys) && extractType.equals(DatasourceServer.UpdateType.add_scope)) {
insetSql = insetSql + " ON DUPLICATE KEY UPDATE ";
List<String> updateColumes = new ArrayList<>();
for (TableField notKey : notKeys) {
updateColumes.add("column = VALUES(column)".replace("column", notKey.getName()));
}
insetSql = insetSql + updateColumes.stream().collect(Collectors.joining(","));
}
return insetSql;
}
@ -93,7 +108,11 @@ public class MysqlEngineProvider extends EngineProvider {
int size = tableField.getPrecision() * 4;
switch (tableField.getDeExtractType()) {
case 0:
columnFields.append("varchar(1024)").append(",`");
if (StringUtils.isNotEmpty(tableField.getLength())) {
columnFields.append("varchar(length)".replace("length", tableField.getLength())).append(",`");
} else {
columnFields.append("longtext").append(",`");
}
break;
case 1:
columnFields.append("datetime").append(",`");
@ -108,7 +127,7 @@ public class MysqlEngineProvider extends EngineProvider {
columnFields.append("TINYINT(length)".replace("length", String.valueOf(tableField.getPrecision()))).append(",`");
break;
default:
columnFields.append("varchar(1024)").append(",`");
columnFields.append("longtext").append(",`");
break;
}
}

View File

@ -21,6 +21,7 @@ import io.dataease.dataset.dao.auto.entity.CoreDatasetGroup;
import io.dataease.dataset.dao.auto.mapper.CoreDatasetGroupMapper;
import io.dataease.dataset.manage.*;
import io.dataease.datasource.utils.DatasourceUtils;
import io.dataease.engine.constant.DeTypeConstants;
import io.dataease.engine.sql.SQLProvider;
import io.dataease.engine.trans.Field2SQLObj;
import io.dataease.engine.trans.Order2SQLObj;
@ -349,7 +350,7 @@ public class ExportCenterManage implements BaseExportApi {
startViewTask(exportTask, request);
}
public void addTask(Long exportFrom, String exportFromType, DataSetExportRequest request)throws Exception{
public void addTask(Long exportFrom, String exportFromType, DataSetExportRequest request) throws Exception {
datasetGroupManage.getDatasetGroupInfoDTO(exportFrom, null);
CoreExportTask exportTask = new CoreExportTask();
exportTask.setId(UUID.randomUUID().toString());
@ -571,7 +572,15 @@ public class ExportCenterManage implements BaseExportApi {
cell.setCellStyle(cellStyle);
detailsSheet.setColumnWidth(j, 255 * 20);
} else {
cell.setCellValue(rowData.get(j));
if ((allFields.get(j).getDeType().equals(DeTypeConstants.DE_INT) || allFields.get(j).getDeType() == DeTypeConstants.DE_FLOAT) && StringUtils.isNotEmpty(rowData.get(j))) {
try {
cell.setCellValue(Double.valueOf(rowData.get(j)));
} catch (Exception e) {
cell.setCellValue(rowData.get(j));
}
} else {
cell.setCellValue(rowData.get(j));
}
}
}
}
@ -668,7 +677,6 @@ public class ExportCenterManage implements BaseExportApi {
Sheet detailsSheet = wb.createSheet("数据");
ChartDataServer.setExcelData(detailsSheet, cellStyle, header, details, detailFields, excelTypes);
}
} else {
//多个sheet
for (int i = 0; i < request.getMultiInfo().size(); i++) {

View File

@ -298,7 +298,11 @@ const onRefreshChange = val => {
themeChange()
}
const fontFamilyChange = () => {
appearanceStore.setCurrentFont(canvasStyleData.fontFamily)
appearanceStore.setCurrentFont(canvasStyleData.value.fontFamily)
document.documentElement.style.setProperty(
'--de-canvas_custom_font',
`${canvasStyleData.value.fontFamily}`
)
}
const themeChange = (modifyName?) => {

View File

@ -24,7 +24,8 @@ const canvasAttrActiveNames = ref(['size', 'baseSetting', 'background', 'color']
const screenAdaptorList = [
{ label: '宽度优先', value: 'widthFirst' },
{ label: '高度优先', value: 'heightFirst' },
{ label: '铺满全屏', value: 'full' }
{ label: '铺满全屏', value: 'full' },
{ label: '不缩放', value: 'keep' }
]
const init = () => {
nextTick(() => {

View File

@ -172,6 +172,11 @@ const props = defineProps({
type: Boolean,
required: false,
default: true
},
fontFamily: {
type: String,
required: false,
default: 'inherit'
}
})
@ -1628,6 +1633,7 @@ defineExpose({
:dv-info="dvInfo"
:canvas-active="canvasActive"
:show-position="'canvas'"
:font-family="fontFamily"
/>
<component
v-else-if="item.component.includes('Svg')"
@ -1646,6 +1652,7 @@ defineExpose({
:active="item.id === curComponentId"
:canvas-active="canvasActive"
:show-position="'edit'"
:font-family="fontFamily"
/>
<component
v-else
@ -1664,6 +1671,7 @@ defineExpose({
:active="item.id === curComponentId"
:canvas-active="canvasActive"
:show-position="'edit'"
:font-family="fontFamily"
/>
</Shape>
<!-- 右击菜单 -->

View File

@ -107,6 +107,12 @@ const props = defineProps({
type: String,
required: false,
default: 'common'
},
//
fontFamily: {
type: String,
required: false,
default: 'inherit'
}
})
const {
@ -424,6 +430,7 @@ const showActive = computed(() => props.popActive || (dvMainStore.mobileInPc &&
:disabled="true"
:is-edit="false"
:suffix-id="suffixId"
:font-family="fontFamily"
@onPointClick="onPointClick"
/>
</div>

View File

@ -141,9 +141,12 @@ const canvasStyle = computed(() => {
style['overflowY'] = 'hidden !important'
}
if (canvasStyleData.value && canvasStyleData.value.width && isMainCanvas(canvasId.value)) {
style = {
...getCanvasStyle(canvasStyleData.value),
height: dashboardActive.value
style = getCanvasStyle(canvasStyleData.value)
if (canvasStyleData.value?.screenAdaptor === 'keep') {
style['height'] = canvasStyleData.value?.height + 'px'
style['width'] = canvasStyleData.value?.width + 'px'
} else {
style['height'] = dashboardActive.value
? downloadStatus.value
? getDownloadStatusMainHeight()
: '100%'
@ -151,11 +154,11 @@ const canvasStyle = computed(() => {
canvasStyleData.value?.screenAdaptor === 'widthFirst'
? changeStyleWithScale(canvasStyleData.value?.height, scaleMin.value) + 'px'
: '100%'
style['width'] =
!dashboardActive.value && canvasStyleData.value?.screenAdaptor === 'heightFirst'
? changeStyleWithScale(canvasStyleData.value?.width, scaleHeightPoint.value) + 'px'
: '100%'
}
style['width'] =
!dashboardActive.value && canvasStyleData.value?.screenAdaptor === 'heightFirst'
? changeStyleWithScale(canvasStyleData.value?.width, scaleHeightPoint.value) + 'px'
: '100%'
}
return style
})

View File

@ -96,7 +96,11 @@ const fontFamily = CHART_FONT_FAMILY.concat(
}))
)
const onFontFamilyChange = () => {
appearanceStore.setCurrentFont(canvasStyleData.fontFamily)
appearanceStore.setCurrentFont(canvasStyleData.value.fontFamily)
document.documentElement.style.setProperty(
'--de-canvas_custom_font',
`${canvasStyleData.value.fontFamily}`
)
}
const onThemeChange = () => {
snapshotStore.recordSnapshotCache()

View File

@ -3,7 +3,11 @@
<el-dropdown :teleported="false" trigger="click">
<input id="input" ref="trackButton" type="button" hidden />
<template #dropdown>
<el-dropdown-menu class="track-menu" :append-to-body="false">
<el-dropdown-menu
class="track-menu"
:style="{ 'font-family': fontFamily }"
:append-to-body="false"
>
<el-dropdown-item
v-for="(item, key) in trackMenu"
:key="key"
@ -27,6 +31,11 @@ const props = defineProps({
trackMenu: {
type: Array,
required: true
},
fontFamily: {
type: String,
required: false,
default: 'inherit'
}
})
const { trackMenu } = toRefs(props)

View File

@ -42,7 +42,7 @@
<el-icon v-if="isEdit"><ArrowDown /></el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-menu :style="{ 'font-family': fontFamily }">
<el-dropdown-item :command="beforeHandleCommand('editTitle', tabItem)">
编辑标题
</el-dropdown-item>
@ -77,6 +77,7 @@
:canvas-id="element.id + '--' + tabItem.name"
:class="moveActive ? 'canvas-move-in' : ''"
:canvas-active="editableTabsValue === tabItem.name"
:font-family="fontFamily"
></de-canvas>
<de-preview
v-else
@ -90,6 +91,7 @@
:preview-active="editableTabsValue === tabItem.name"
:show-position="showPosition"
:outer-scale="scale"
:font-family="fontFamily"
:outer-search-count="searchCount"
></de-preview>
</div>
@ -190,6 +192,12 @@ const props = defineProps({
type: Number,
required: false,
default: 0
},
//
fontFamily: {
type: String,
required: false,
default: 'inherit'
}
})
const {
@ -566,6 +574,9 @@ onBeforeMount(() => {
:deep(.ed-tabs__content) {
height: calc(100% - 46px) !important;
}
:deep(.ed-tabs__item) {
font-family: inherit;
}
}
.ed-tabs-dark {

View File

@ -8,7 +8,7 @@
/>
<div v-else class="pic-upload">
<span
><el-button @click="uploadImg" text style="color: #646a73" icon="Plus"
><el-button @click="uploadImg" text style="font-family: inherit; color: #646a73" icon="Plus"
>请上传图片...</el-button
></span
>

View File

@ -58,6 +58,11 @@ const props = defineProps({
type: String,
required: false,
default: 'common'
},
fontFamily: {
type: String,
required: false,
default: 'inherit'
}
})
@ -87,6 +92,7 @@ const onPointClick = param => {
:search-count="searchCount"
:disabled="disabled"
:suffixId="suffixId"
:font-family="fontFamily"
@onPointClick="onPointClick"
></chart>
</div>

View File

@ -698,6 +698,7 @@ const autoStyle = computed(() => {
<el-button
:disabled="showPosition === 'preview' || mobileInPc"
@click="addCriteriaConfigOut"
style="font-family: inherit"
text
>
{{ t('v_query.add_query_condition') }}
@ -825,7 +826,6 @@ const autoStyle = computed(() => {
justify-content: center;
color: #646a73;
text-align: center;
font-family: var(--de-custom_font, 'PingFang');
font-size: 16px;
font-style: normal;
font-weight: 400;
@ -841,7 +841,6 @@ const autoStyle = computed(() => {
.title {
color: #1f2329;
font-feature-settings: 'clig' off, 'liga' off;
font-family: var(--de-custom_font, 'PingFang');
font-size: 14px;
font-style: normal;
font-weight: 500;
@ -900,7 +899,6 @@ const autoStyle = computed(() => {
text-overflow: ellipsis;
white-space: nowrap;
color: #1f2329;
font-family: var(--de-custom_font, 'PingFang');
font-size: 14px;
font-style: normal;
font-weight: 400;

View File

@ -167,6 +167,13 @@ onBeforeMount(() => {
v-model="selectValue"
:type="config.timeGranularity"
:prefix-icon="Calendar"
:popper-class="'custom-dynamic-time-popper_class'"
:placeholder="$t('commons.date.select_date_time')"
/>
</template>
<style lang="less">
.custom-dynamic-time-popper_class {
font-family: var(--de-canvas_custom_font);
}
</style>

View File

@ -170,8 +170,14 @@ const formatDate = computed(() => {
:type="config.timeGranularityMultiple"
:prefix-icon="Calendar"
:format="formatDate"
:popper-class="'custom-dynamic-time-range-popper_class'"
:range-separator="$t('cron.to')"
:start-placeholder="$t('datasource.start_time')"
:end-placeholder="$t('datasource.end_time')"
/>
</template>
<style lang="less">
.custom-dynamic-time-range-popper_class {
font-family: var(--de-canvas_custom_font);
}
</style>

View File

@ -147,8 +147,15 @@ const formatDate = computed(() => {
:type="timeInterval"
:prefix-icon="Calendar"
:format="formatDate"
:popper-class="'custom-dynamic-time-range-filter-popper_class'"
:range-separator="$t('cron.to')"
:start-placeholder="$t('datasource.start_time')"
:end-placeholder="$t('datasource.end_time')"
/>
</template>
<style lang="less">
.custom-dynamic-time-range-filter-popper_class {
font-family: var(--de-canvas_custom_font);
}
</style>

View File

@ -648,6 +648,7 @@ defineExpose({
<style lang="less">
.filter-select-popper_class {
--ed-fill-color-light: #f5f7fa47;
font-family: var(--de-canvas_custom_font);
.ed-vl__window.ed-select-dropdown__list {
min-width: 200px;
}

View File

@ -1416,8 +1416,8 @@ export default {
table_header_show_vertical_border: 'Header vertical border',
table_cell_show_horizon_border: 'horizontal cell border',
table_cell_show_vertical_border: 'vertical cell border',
table_col_freeze_tip: 'first column to',
tbale_row_freeze_tip: 'first row to',
table_col_freeze_tip: 'First n col',
table_row_freeze_tip: 'First n row',
table_freeze: 'freeze',
stripe: 'zebra stripe',
start_angle: 'starting angle',

View File

@ -1086,6 +1086,7 @@ export default {
primary_key_change: '主鍵不能改變:',
api_field_not_empty: '欄位不能為空',
success_copy: '複製成功',
primary_key_length: '主键必须设置长度: ',
valid: '有效',
invalid: '無效',
api_step_1: '連結API',
@ -1137,6 +1138,7 @@ export default {
set_key: '設為主鍵',
field_rename: '重命名',
select_type: '選擇資料來源類型',
length: '字段长度',
sync_table: '同步指定表',
req_completed: '請求成功',
sync_rate: '更新頻率',

View File

@ -1086,6 +1086,7 @@ export default {
has_repeat_name: 'API 数据表名称重复',
has_repeat_field_name: '字段名重复请修改后再选择',
primary_key_change: '主键不能改变:',
primary_key_length: '主键必须设置长度: ',
api_field_not_empty: '字段不能为空',
success_copy: '复制成功',
valid: '有效',
@ -1137,6 +1138,7 @@ export default {
end_time: '结束时间',
parse_filed: '解析字段',
set_key: '设为主键',
length: '字段长度',
field_rename: '重命名',
select_type: '选择数据源类型',
sync_table: '同步指定表',
@ -1379,8 +1381,8 @@ export default {
table_header_show_vertical_border: '表头纵边框线',
table_cell_show_horizon_border: '单元格横边框线',
table_cell_show_vertical_border: '单元格纵边框线',
table_col_freeze_tip: '第一列到',
tbale_row_freeze_tip: '第一行到',
table_col_freeze_tip: '冻结前 n ',
table_row_freeze_tip: '冻结前 n ',
table_freeze: '冻结',
stripe: '斑马纹',
start_angle: '起始角度',

View File

@ -590,6 +590,13 @@ strong {
overflow-y: auto;
}
.preview-content-inner-size-keep {
width: 100%;
height: auto;
overflow-x: auto;
overflow-y: auto;
}
.preview-content-inner-height-first {
width: auto;
height: 100%;
@ -607,3 +614,7 @@ strong {
.ed-message .ed-message__closeBtn:hover {
background: #ebebebe6 !important;
}
.canvas_keep-size {
overflow-x: auto!important;
}

View File

@ -348,7 +348,11 @@ export function initCanvasDataPrepare(dvId, busiFlag, callBack) {
dvInfo.type === 'dashboard' && canvasStyleResult['dashboard'].gap === 'yes'
? canvasStyleResult['dashboard'].gapSize
: 0
appearanceStore.setCurrentFont(canvasStyleData.fontFamily)
appearanceStore.setCurrentFont(canvasStyleResult.fontFamily)
document.documentElement.style.setProperty(
'--de-canvas_custom_font',
`${canvasStyleResult.fontFamily}`
)
callBack({ canvasDataResult, canvasStyleResult, dvInfo, canvasViewInfoPreview, curPreviewGap })
})
}

View File

@ -39,6 +39,12 @@ const props = defineProps({
type: Number,
required: false,
default: 1
},
//
fontFamily: {
type: String,
required: false,
default: 'inherit'
}
})
const { canvasStyleData, componentData, canvasViewInfo, canvasId, canvasActive, outerScale } =
@ -321,6 +327,7 @@ defineExpose({
:base-margin-top="baseMarginTop"
:base-width="baseWidth"
:base-height="baseHeight"
:font-family="fontFamily"
@scrollCanvasToTop="scrollTo(1)"
></canvas-core>
</div>

View File

@ -531,6 +531,7 @@ initParams()
<el-select
v-model="currentPlaceholder"
@change="handleCurrentPlaceholder"
:effect="themes"
style="width: 100%"
>
<el-option

View File

@ -353,7 +353,7 @@ onMounted(() => {
</el-col>
<el-col :span="12">
<el-form-item
:label="t('chart.tbale_row_freeze_tip')"
:label="t('chart.table_row_freeze_tip')"
class="form-item"
:class="'form-item-' + themes"
v-if="showProperty('tableRowFreezeHead')"
@ -388,7 +388,7 @@ onMounted(() => {
<span style="margin-right: 4px">{{ t('chart.merge_cells') }}</span>
<el-tooltip class="item" effect="dark" placement="bottom">
<template #content>
<div>合并单元格后行列冻结会失效</div>
<div>合并单元格后行列冻结自动换行会失效</div>
</template>
<el-icon class="hint-icon" :class="{ 'hint-icon--dark': themes === 'dark' }">
<Icon name="icon_info_outlined"><icon_info_outlined class="svg-icon" /></Icon>

View File

@ -172,6 +172,7 @@ export function getLabel(chart: Chart) {
'bar'
].includes(chart.type)
) {
layout.push({ type: 'limit-in-canvas' })
layout.push({ type: 'hide-overlap' })
} else {
layout.push({ type: 'limit-in-plot' })

View File

@ -1615,7 +1615,7 @@ const drawTextShape = (cell, isHeader) => {
// 不是表头处理文本高度和换行
if (!isHeader) {
const textHeight = cell.spreadsheet.measureTextHeight(wrapText.replaceAll(lineBreak, ''), textStyle)
const textHeight = getWrapTextHeight(wrapText.replaceAll(lineBreak, ''), textStyle, cell.spreadsheet, maxLines)
const lineCountInCell = Math.floor(cell.meta.height / textHeight)
const wrapTextArr = lines.slice(0, lineCountInCell)
@ -1623,17 +1623,28 @@ const drawTextShape = (cell, isHeader) => {
wrapText = lineCountInCell === 1
? lines[0].slice(0, -1) + ellipsis
: wrapTextArr.join(lineBreak) || ellipsis
}
const resultWrapArr = wrapText.split(lineBreak)
// 控制最大行数
if (lines.length > maxLines) {
const temp = resultWrapArr.slice(0, maxLines)
if (!temp[temp.length - 1].endsWith(ellipsis)) {
temp[temp.length - 1] = temp[temp.length - 1][0] + ellipsis
const resultWrapArr = wrapText.split(lineBreak)
// 控制最大行数
if ( !wrapText.endsWith(ellipsis) && (lines.length > maxLines || lines.length > lineCountInCell)) {
// 第一行的字符个数
const firstLineStrNumber = resultWrapArr[0].length
const temp = resultWrapArr.slice(0, Math.min(maxLines, lineCountInCell))
// 修改最后一行的字符,按照第一行字符个数-1修改最后一行的字符为...
temp[temp.length - 1] = temp[temp.length-1].slice(0,firstLineStrNumber - 1) + ellipsis
wrapText = temp.join(lineBreak)
}
} else {
const resultWrapArr = wrapText.split(lineBreak)
// 控制最大行数
if (lines.length > maxLines) {
const temp = resultWrapArr.slice(0, maxLines)
// 第一行的字符个数
const firstLineStrNumber = resultWrapArr[0].length
// 修改最后一行的字符
temp[temp.length - 1] = temp[temp.length-1].slice(0,firstLineStrNumber - 1) + ellipsis
wrapText = temp.join(lineBreak)
}
wrapText = temp.join(lineBreak)
}
// 设置最终文本和其宽度
cell.actualText = wrapText
cell.actualTextWidth = cell.spreadsheet.measureTextWidth(wrapText, textStyle)
@ -1691,27 +1702,27 @@ export const calculateHeaderHeight = (info, newChart, tableHeader, basicStyle, l
* @param cellWidth
* @param spreadsheet
*/
const getWrapText = (sourceText, textStyle, cellWidth, spreadsheet) => {
const getWrapText = (sourceText, textStyle, cellWidth, spreadsheet) => {
if (!sourceText && sourceText !== 0) return ''
sourceText = sourceText.toString().trim()
const getTextWidth = text => spreadsheet.measureTextWidthRoughly(text, textStyle)
let resultWrapText = ''
let restText = ''
let restTextWidth = 0
let restTextWidth = 10
for (let i = 0; i < sourceText.length; i++) {
const char = sourceText[i]
const charWidth = getTextWidth(char)
restTextWidth += charWidth
restText += char
// 中文时需要单元格宽度减去16个文字宽度否则会超出单元格宽度
const cWidth = char.charCodeAt(0) >= 128 ? 16 : 0
const cWidth = char.charCodeAt(0) >= 128 ? 16 : 10
// 添加换行
if (restTextWidth >= cellWidth - textStyle.fontSize - cWidth) {
// 最后一个字符不添加换行符
resultWrapText += restText + (i !== sourceText.length - 1 ? '\n' : '')
restText = ''
restTextWidth = 0
restTextWidth = 10
}
}
@ -1730,7 +1741,8 @@ const getWrapTextHeight = (wrapText, textStyle, spreadsheet, maxLines) => {
let maxHeight = 0
// 获取最高字符的高度
for (const char of wrapText) {
maxHeight = Math.max(maxHeight, spreadsheet.measureTextHeight(char, textStyle))
const h = textStyle.fontSize / (char.charCodeAt(0) >= 128 ? 5 : 2.5)
maxHeight = Math.max(maxHeight, spreadsheet.measureTextHeight(char, textStyle) + h)
}
// 行数
const lines = wrapText.split('\n').length

View File

@ -68,6 +68,11 @@ const props = defineProps({
type: String,
required: false,
default: 'common'
},
fontFamily: {
type: String,
required: false,
default: 'inherit'
}
})
@ -568,6 +573,7 @@ onBeforeUnmount(() => {
<view-track-bar
ref="viewTrack"
:track-menu="trackMenu"
:font-family="fontFamily"
class="track-bar"
:style="state.trackBarStyle"
@trackClick="trackClick"

View File

@ -83,6 +83,11 @@ const props = defineProps({
type: String,
required: false,
default: 'common'
},
fontFamily: {
type: String,
required: false,
default: 'inherit'
}
})
@ -659,6 +664,7 @@ const tablePageClass = computed(() => {
<view-track-bar
ref="viewTrack"
:track-menu="trackMenu"
:font-family="fontFamily"
class="track-bar"
:style="state.trackBarStyle"
@trackClick="trackClick"

View File

@ -130,6 +130,11 @@ const props = defineProps({
type: String,
required: false,
default: 'common'
},
fontFamily: {
type: String,
required: false,
default: 'inherit'
}
})
const dynamicAreaId = ref('')

View File

@ -273,6 +273,7 @@ onUnmounted(() => {
:component-data="componentData"
:canvas-style-data="canvasStyleData"
:canvas-view-info="canvasViewInfo"
:font-family="canvasStyleData.fontFamily"
></de-canvas>
</main>
<!-- 右侧侧组件列表 -->

View File

@ -52,6 +52,8 @@ const contentInnerClass = computed(() => {
return 'preview-content-inner-height-first'
} else if (props.canvasStylePreview.screenAdaptor === 'full') {
return 'preview-content-inner-full'
} else if (props.canvasStylePreview.screenAdaptor === 'keep') {
return 'preview-content-inner-size-keep'
} else {
return 'preview-content-inner-width-first'
}

View File

@ -1,6 +1,6 @@
<script setup lang="ts">
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { nextTick, onMounted, reactive, ref, watch } from 'vue'
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'
import DePreview from '@/components/data-visualization/canvas/DePreview.vue'
import router from '@/router'
import { useEmitt } from '@/hooks/web/useEmitt'
@ -188,13 +188,17 @@ onMounted(async () => {
dvMainStore.setPublicLinkStatus(props.publicLinkStatus)
})
const dataVKeepSize = computed(() => {
return state.canvasStylePreview?.screenAdaptor === 'keep'
})
defineExpose({
loadCanvasDataAsync
})
</script>
<template>
<div class="content" ref="previewCanvasContainer">
<div class="content" :class="{ 'canvas_keep-size': dataVKeepSize }" ref="previewCanvasContainer">
<de-preview
ref="dvPreview"
v-if="state.canvasStylePreview && state.initState"

View File

@ -170,6 +170,10 @@ const resourceNodeClick = data => {
loadCanvasData(data.id, data.weight, data.ext)
}
const dataVKeepSize = computed(() => {
return state.canvasStylePreview?.screenAdaptor === 'keep'
})
const state = reactive({
canvasDataPreview: null,
canvasStylePreview: null,
@ -276,7 +280,12 @@ onBeforeMount(() => {
:dv-info="state.dvInfo"
></multiplex-preview-show>
</div>
<div v-if="showPosition === 'preview'" ref="previewCanvasContainer" class="content">
<div
v-if="showPosition === 'preview'"
:class="{ 'canvas_keep-size': dataVKeepSize }"
ref="previewCanvasContainer"
class="content"
>
<dv-preview
ref="dvPreviewRef"
v-if="state.canvasStylePreview && dataInitState"

View File

@ -20,6 +20,7 @@ const state = reactive({
:component-data="componentData"
:canvas-style-data="canvasStyleData"
:canvas-view-info="canvasViewInfo"
:font-family="canvasStyleData.fontFamily"
></de-canvas>
</div>
</template>

View File

@ -18,6 +18,7 @@ import { iconFieldMap } from '@/components/icon-group/field-list'
export interface Field {
name: string
length: number
value: Array<{}>
checked: boolean
primaryKey: boolean
@ -48,6 +49,7 @@ export interface JsonField {
name: string
checked: false
primaryKey: false
length: string
extField: number
jsonPath: string
type: string
@ -258,7 +260,7 @@ const saveItem = () => {
for (let i = 0; i < apiItem.fields.length; i++) {
if (apiItem.fields[i].primaryKey) {
let find = false
for (let j = 0; j < fields.length - 1; j++) {
for (let j = 0; j < fields.length; j++) {
if (fields[j].name === apiItem.fields[i].name && fields[j].primaryKey) {
find = true
}
@ -268,10 +270,10 @@ const saveItem = () => {
}
}
}
for (let i = 0; i < fields.length - 1; i++) {
for (let i = 0; i < fields.length; i++) {
if (fields[i].primaryKey) {
let find = false
for (let j = i + 1; j < apiItem.fields.length; j++) {
for (let j = 0; j < apiItem.fields.length; j++) {
if (fields[i].name === apiItem.fields[j].name && apiItem.fields[j].primaryKey) {
find = true
}
@ -285,6 +287,12 @@ const saveItem = () => {
ElMessage.error(t('datasource.primary_key_change') + msg)
return
}
} else {
for (let i = 0; i < apiItem.fields.length; i++) {
if (apiItem.fields[i].primaryKey && !apiItem.fields[i].length) {
ElMessage.error(t('datasource.primary_key_length') + apiItem.fields[i].name)
}
}
}
returnAPIItem('returnItem', cloneDeep(apiItem))
edit_api_item.value = false
@ -381,6 +389,14 @@ const disabledByChildren = item => {
}
}
const disabledFieldLength = item => {
if (item.hasOwnProperty('children') && item.children.length > 0) {
return true
} else {
return item.deExtractType !== 0
}
}
const disabledChangeFieldByChildren = item => {
if (apiItem.type == 'params') {
return true
@ -391,6 +407,12 @@ const disabledChangeFieldByChildren = item => {
return false
}
}
const deExtractTypeChange = item => {
if (item.deExtractType !== 0) {
item.length = ''
}
}
const previewData = () => {
showEmpty.value = false
const data = []
@ -491,7 +513,7 @@ defineExpose({
"
v-model="edit_api_item"
custom-class="api-datasource-drawer"
size="840px"
size="1000px"
:before-close="closeEditItem"
direction="rtl"
>
@ -661,7 +683,7 @@ defineExpose({
prop="originName"
:label="t('datasource.parse_filed')"
:show-overflow-tooltip="true"
width="255"
width="200"
>
<template #default="scope">
<el-checkbox
@ -696,6 +718,7 @@ defineExpose({
:disabled="disabledChangeFieldByChildren(scope.row)"
class="select-type"
style="display: inline-block; width: 120px"
@change="deExtractTypeChange(scope.row)"
>
<template #prefix>
<el-icon>
@ -733,12 +756,33 @@ defineExpose({
</template>
</el-table-column>
<el-table-column
prop="length"
:label="t('datasource.length')"
v-if="apiItem.type !== 'params'"
>
<template #default="scope">
<el-input-number
:disabled="disabledFieldLength(scope.row)"
v-model="scope.row.length"
autocomplete="off"
step-strictly
class="text-left edit-all-line"
:min="1"
:max="4096"
:placeholder="t('common.inputText')"
controls-position="right"
type="number"
/>
</template>
</el-table-column>
<el-table-column
prop="primaryKey"
class-name="checkbox-table"
:label="t('datasource.set_key')"
v-if="apiItem.type !== 'params'"
width="155"
width="100"
>
<template #default="scope">
<el-checkbox

View File

@ -14,6 +14,7 @@ public class TableField implements Serializable {
private int precision;
private long size;
private int scale;
private String length;
private boolean checked = false;
private boolean primaryKey = false;
private String fieldType;