refactor: 解决冲突

This commit is contained in:
taojinlong 2022-07-25 17:28:21 +08:00
commit 6245da641a
52 changed files with 2360 additions and 780 deletions

View File

@ -5,6 +5,7 @@ import io.dataease.auth.entity.TokenInfo;
import io.dataease.auth.service.AuthUserService;
import io.dataease.auth.service.impl.AuthUserServiceImpl;
import io.dataease.auth.util.JWTUtils;
import io.dataease.dto.PermissionProxy;
import io.dataease.ext.ExtTaskMapper;
import io.dataease.commons.utils.CommonBeanFactory;
import io.dataease.commons.utils.CronUtils;
@ -19,6 +20,7 @@ import io.dataease.plugins.xpack.email.dto.request.XpackEmailTaskRequest;
import io.dataease.plugins.xpack.email.dto.request.XpackPixelEntity;
import io.dataease.plugins.xpack.email.dto.response.XpackEmailTemplateDTO;
import io.dataease.plugins.xpack.email.service.EmailXpackService;
import io.dataease.service.chart.ViewExportExcel;
import io.dataease.service.system.EmailService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@ -27,7 +29,11 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service("emailTaskHandler")
public class EmailTaskHandler extends TaskHandler implements Job {
@ -39,6 +45,9 @@ public class EmailTaskHandler extends TaskHandler implements Job {
@Resource
private AuthUserServiceImpl authUserServiceImpl;
@Resource
private ViewExportExcel viewExportExcel;
@Override
protected JobDataMap jobDataMap(GlobalTaskEntity taskEntity) {
JobDataMap jobDataMap = new JobDataMap();
@ -132,8 +141,8 @@ public class EmailTaskHandler extends TaskHandler implements Job {
}
@Async("priorityExecutor")
public void sendReport(GlobalTaskInstance taskInstance, XpackEmailTemplateDTO emailTemplateDTO,
SysUserEntity user) {
public void sendReport(GlobalTaskInstance taskInstance, XpackEmailTemplateDTO emailTemplateDTO, SysUserEntity user) {
EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class);
try {
XpackEmailTaskRequest taskForm = emailXpackService.taskForm(taskInstance.getTaskId());
@ -158,8 +167,14 @@ public class EmailTaskHandler extends TaskHandler implements Job {
if (ObjectUtils.isNotEmpty(content)) {
contentStr = new String(content, "UTF-8");
}
emailService.sendWithImage(recipients, emailTemplateDTO.getTitle(),
contentStr, bytes);
String viewIds = emailTemplateDTO.getViewIds();
List<String> viewIdList = Arrays.asList(viewIds.split(",")).stream().map(s -> (s.trim())).collect(Collectors.toList());
PermissionProxy proxy = new PermissionProxy();
proxy.setUserId(user.getUserId());
List<File> files = viewExportExcel.export(panelId, viewIdList, proxy);
emailService.sendWithImageAndFiles(recipients, emailTemplateDTO.getTitle(), contentStr, bytes, files);
success(taskInstance);
} catch (Exception e) {

View File

@ -1,74 +1,24 @@
package io.dataease.job.sechedule.strategy.impl;
import io.dataease.auth.entity.SysUserEntity;
import io.dataease.commons.utils.CronUtils;
import io.dataease.commons.utils.LogUtil;
import io.dataease.dto.PermissionProxy;
import io.dataease.plugins.common.entity.GlobalTaskInstance;
import io.dataease.plugins.config.SpringContextUtil;
import io.dataease.plugins.xpack.email.dto.request.XpackEmailTaskRequest;
import io.dataease.plugins.xpack.email.dto.response.XpackEmailTemplateDTO;
import io.dataease.plugins.xpack.email.service.EmailXpackService;
import io.dataease.service.chart.ViewExportExcel;
import io.dataease.service.system.EmailService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Service("emailTaskViewHandler")
public class EmailTaskViewHandler extends EmailTaskHandler {
@Resource
private ViewExportExcel viewExportExcel;
@Async("priorityExecutor")
public void sendReport(GlobalTaskInstance taskInstance, XpackEmailTemplateDTO emailTemplateDTO,
SysUserEntity user) {
EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class);
List<File> files = null;
try {
XpackEmailTaskRequest taskForm = emailXpackService.taskForm(taskInstance.getTaskId());
if (ObjectUtils.isEmpty(taskForm) || CronUtils.taskExpire(taskForm.getEndTime())) {
removeInstance(taskInstance);
return;
}
String panelId = emailTemplateDTO.getPanelId();
// 下面继续执行发送邮件的
byte[] content = emailTemplateDTO.getContent();
EmailService emailService = SpringContextUtil.getBean(EmailService.class);
String contentStr = "";
if (ObjectUtils.isNotEmpty(content)) {
contentStr = new String(content, "UTF-8");
}
String viewIds = emailTemplateDTO.getPixel();
List<String> viewIdList = Arrays.asList(viewIds.split(",")).stream().map(s -> (s.trim()))
.collect(Collectors.toList());
PermissionProxy proxy = new PermissionProxy();
proxy.setUserId(user.getUserId());
files = viewExportExcel.export(panelId, viewIdList, proxy);
emailService.sendWithFiles(emailTemplateDTO.getRecipients(), emailTemplateDTO.getTitle(), contentStr, files);
success(taskInstance);
} catch (Exception e) {
error(taskInstance, e);
LogUtil.error(e.getMessage(), e);
} finally {
if (CollectionUtils.isNotEmpty(files)) {
for (int i = 0; i < files.size(); i++) {
File file = files.get(i);
if (file.exists()) {
file.delete();
}
}
}
}
public void sendReport(GlobalTaskInstance taskInstance, XpackEmailTemplateDTO emailTemplateDTO, SysUserEntity user) {
super.sendReport(taskInstance, emailTemplateDTO, user);
}
}

View File

@ -136,6 +136,8 @@ public class PanelGroupService {
public String update(PanelGroupRequest request) {
String panelId = request.getId();
request.setUpdateTime(System.currentTimeMillis());
request.setUpdateBy(AuthUtils.getUser().getUsername());
panelViewService.syncPanelViews(request);
if ("toDefaultPanel".equals(request.getOptType())) { // 转存为默认仪表板
panelId = UUID.randomUUID().toString();
@ -148,6 +150,7 @@ public class PanelGroupService {
newDefaultPanel.setLevel(0);
newDefaultPanel.setSource(request.getId());
newDefaultPanel.setCreateBy(AuthUtils.getUser().getUsername());
newDefaultPanel.setCreateTime(System.currentTimeMillis());
checkPanelName(newDefaultPanel.getName(), newDefaultPanel.getPid(), PanelConstants.OPT_TYPE_INSERT, newDefaultPanel.getId(), newDefaultPanel.getNodeType());
panelGroupMapper.insertSelective(newDefaultPanel);
// 清理权限缓存
@ -179,6 +182,8 @@ public class PanelGroupService {
record.setName(request.getName());
record.setId(request.getId());
record.setPid(request.getPid());
record.setUpdateTime(request.getUpdateTime());
record.setUpdateBy(request.getUpdateBy());
panelGroupMapper.updateByPrimaryKeySelective(record);
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.MODIFY, sourceType, request.getId(), panelInfo.getPid(), request.getPid(), sourceType);
@ -338,6 +343,7 @@ public class PanelGroupService {
newPanel.setName(request.getName());
newPanel.setId(newPanelId);
newPanel.setCreateBy(AuthUtils.getUser().getUsername());
newPanel.setCreateTime(System.currentTimeMillis());
//TODO copy panelView
extPanelViewMapper.copyFromPanel(newPanelId, sourcePanelId, copyId);
//TODO 复制视图 chart_view

View File

@ -1,5 +1,6 @@
package io.dataease.service.system;
import cn.hutool.core.util.ArrayUtil;
import io.dataease.commons.constants.ParamConstants;
import io.dataease.commons.exception.DEException;
import io.dataease.commons.utils.CommonBeanFactory;
@ -81,10 +82,15 @@ public class EmailService {
}
}
public void sendWithFiles(String to, String title, String content, List<File> files) {
public void sendWithImageAndFiles(String to, String title, String content, byte[] bytes, List<File> files) {
if (StringUtils.isBlank(to))
return;
if (CollectionUtils.isEmpty(files)) {
if (ArrayUtil.isEmpty(bytes)) {
send(to, title, content);
return;
}
@ -92,19 +98,12 @@ public class EmailService {
checkMailInfo(mailInfo);
JavaMailSenderImpl driver = driver(mailInfo);
MimeMessage mimeMessage = driver.createMimeMessage();
MimeBodyPart text = new MimeBodyPart();
MimeMultipart multipart = new MimeMultipart();
try {
MimeMultipart multipart = new MimeMultipart();
text.setText(content, "gb2312");
multipart.addBodyPart(text);
multipart.setSubType("related");
for (int i = 0; i < files.size(); i++) {
File file = files.get(i);
MimeBodyPart attach = new MimeBodyPart();
FileDataSource fileDataSource = new FileDataSource(file);
attach.setDataHandler(new DataHandler(fileDataSource));
attach.setFileName(MimeUtility.encodeText(file.getName()));
multipart.addBodyPart(attach);
multipart = addImage(multipart, bytes, content);
if (CollectionUtils.isNotEmpty(files)) {
multipart = addFiles(multipart, files);
}
mimeMessage.setFrom(driver.getUsername());
mimeMessage.setSubject(title);
@ -117,38 +116,33 @@ public class EmailService {
}
}
public void sendWithImage(String to, String title, String content, byte[] bytes) {
if (StringUtils.isBlank(to))
return;
MailInfo mailInfo = proxy().mailInfo();
checkMailInfo(mailInfo);
JavaMailSenderImpl driver = driver(mailInfo);
MimeMessage mimeMessage = driver.createMimeMessage();
private MimeMultipart addImage(MimeMultipart multipart, byte[] bytes, String content) throws Exception{
MimeBodyPart image = new MimeBodyPart();
DataHandler png = new DataHandler(new ByteArrayDataSource(bytes, "image/png"));
String uuid = UUID.randomUUID().toString();
MimeBodyPart text = new MimeBodyPart();
try {
text.setContent(content + "<br/><img style='width: 60%;' src='cid:" + uuid + "' />", "text/html; charset=gb2312");
image.setDataHandler(png);
image.setContentID(uuid);
text.setContent(content + "<br/><img style='width: 60%;' src='cid:" + uuid + "' />",
"text/html; charset=gb2312");
image.setDataHandler(png);
image.setContentID(uuid);
MimeMultipart multipart = new MimeMultipart();
multipart.addBodyPart(text);
multipart.addBodyPart(image);
multipart.setSubType("related");
mimeMessage.setFrom(driver.getUsername());
mimeMessage.setSubject(title);
mimeMessage.setRecipients(Message.RecipientType.TO, to);
mimeMessage.setContent(multipart);
driver.send(mimeMessage);
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
throw new RuntimeException(e);
multipart.addBodyPart(text);
multipart.addBodyPart(image);
multipart.setSubType("related");
return multipart;
}
private MimeMultipart addFiles(MimeMultipart multipart, List<File> files) throws Exception{
for (int i = 0; i < files.size(); i++) {
File file = files.get(i);
MimeBodyPart attach = new MimeBodyPart();
FileDataSource fileDataSource = new FileDataSource(file);
attach.setDataHandler(new DataHandler(fileDataSource));
attach.setFileName(MimeUtility.encodeText(file.getName()));
multipart.addBodyPart(attach);
}
System.getProperties().setProperty("mail.mime.splitlongparameters", "false");
multipart.setSubType("related");
return multipart;
}
public JavaMailSenderImpl driver(MailInfo mailInfo) {

View File

@ -72,4 +72,13 @@ INSERT INTO `system_parameter` (`param_key`, `param_value`, `type`, `sort`) VALU
INSERT INTO `system_parameter` (`param_key`, `param_value`, `type`, `sort`) VALUES ('basic.templateMarketUlr', 'https://dataease.io/templates', 'text', 4);
ALTER TABLE `dataset_column_permissions` ADD COLUMN `white_list_user` longtext DEFAULT NULL COMMENT '白名单' AFTER `permissions` ;
ALTER TABLE `dataset_column_permissions` ADD COLUMN `white_list_user` longtext DEFAULT NULL COMMENT '白名单' AFTER `permissions` ;
ALTER TABLE `panel_group`
ADD COLUMN `update_by` varchar(255) NULL COMMENT '更新人' AFTER `status`,
ADD COLUMN `update_time` bigint(13) NULL COMMENT '更新时间' AFTER `update_by`;
ALTER TABLE `sys_task_email`
ADD COLUMN `view_ids` varchar(255) NULL COMMENT '视图ID集合' AFTER `task_id`;

View File

@ -154,7 +154,11 @@ export function initPanelData(panelId, callback) {
name: response.data.name,
privileges: response.data.privileges,
sourcePanelName: response.data.sourcePanelName,
status: response.data.status
status: response.data.status,
createBy: response.data.createBy,
createTime: response.data.createTime,
updateBy: response.data.updateBy,
updateTime: response.data.updateTime
})
// 刷新联动信息
getPanelAllLinkageInfo(panelId).then(rsp => {

View File

@ -13,7 +13,11 @@ export function proxyInitPanelData(panelId, proxy, callback) {
name: response.data.name,
privileges: response.data.privileges,
proxy: proxy.userId,
status: response.data.status
status: response.data.status,
createBy: response.data.createBy,
createTime: response.data.createTime,
updateBy: response.data.updateBy,
updateTime: response.data.updateTime
})
// 刷新联动信息
getPanelAllLinkageInfo(panelId, proxy).then(rsp => {

View File

@ -2,9 +2,7 @@ import request from '@/utils/request'
import { uuid } from 'vue-uuid'
import store from '@/store'
export function uploadFile(fileId, file) {
const param = new FormData()
param.append('file', file.file)
export function uploadFile(fileId, param) {
return request({
url: '/static/resource/upload/' + fileId,
method: 'post',
@ -16,10 +14,12 @@ export function uploadFile(fileId, file) {
export function uploadFileResult(file, callback) {
const fileId = uuid.v1()
const fileName = file.file.name
const fileName = file.name
const newFileName = fileId + fileName.substr(fileName.lastIndexOf('.'), fileName.length)
const fileUrl = store.state.staticResourcePath + newFileName
uploadFile(fileId, file).then(() => {
const param = new FormData()
param.append('file', file)
uploadFile(fileId, param).then(() => {
callback(fileUrl)
})
}

View File

@ -595,14 +595,14 @@ export default {
return (this.canvasStyleData.panel.gap === 'yes' && this.element.auxiliaryMatrix) ? this.componentGap : 0
},
miniWidth() {
return this.element.auxiliaryMatrix ? this.curCanvasScale.matrixStyleWidth * (this.element.miniSizex || 1) : 0
return this.element.auxiliaryMatrix ? this.curCanvasScale.matrixStyleWidth * 4 : 0
},
miniHeight() {
if (this.element.auxiliaryMatrix) {
if (this.element.component === 'de-number-range') {
return this.element.auxiliaryMatrix ? this.curCanvasScale.matrixStyleHeight * (this.element.miniSizey || 2) : 0
return this.element.auxiliaryMatrix ? this.curCanvasScale.matrixStyleHeight * 4 : 0
} else {
return this.element.auxiliaryMatrix ? this.curCanvasScale.matrixStyleHeight * (this.element.miniSizey || 1) : 0
return this.element.auxiliaryMatrix ? this.curCanvasScale.matrixStyleHeight * 4 : 0
}
} else {
return 0

View File

@ -0,0 +1,238 @@
<template>
<div class="el-view-select" :class="selectClass">
<el-select
ref="select"
v-model="innerValues"
v-popover:popover
popper-class="view-select-option"
style="width: 100%;"
multiple
clearable
@remove-tag="_selectRemoveTag"
@clear="_selectClearFun"
@focus="_popoverShowFun"
>
<el-option
v-for="item in selectOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
<el-popover ref="popover" v-model="visible" :placement="placement" :transition="transition" :popper-class="popperClass" :width="width" trigger="click">
<el-scrollbar v-if="viewLoaded" tag="div" wrap-class="el-select-dropdown__wrap" view-class="el-select-dropdown__list" class="is-empty">
<div :style="{'height': panelHeight + 'px'}">
<Preview
:component-data="componentData"
:canvas-style-data="canvasStyleData"
:panel-info="panelInfo"
:show-position="showPosition"
/>
</div>
</el-scrollbar>
<el-empty v-else style="height: 150px;" :image-size="120" description="" />
</el-popover>
</div>
</template>
<script>
import { on, off } from './dom'
import Preview from '@/components/canvas/components/Editor/Preview'
import { findOne } from '@/api/panel/panel'
import { viewOptions } from '@/api/chart/chart'
import { panelDataPrepare } from '@/components/canvas/utils/utils'
export default {
name: 'DeViewSelect',
components: { Preview },
props: {
value: {
type: Array,
default: () => []
},
panelId: {
type: String,
default: null
}
},
data() {
return {
visible: false,
placement: 'bottom',
transition: 'el-zoom-in-top',
width: 500,
selectClass: 'my-top-class',
innerValues: [],
panelHeight: 450,
showPosition: 'email-task',
viewLoaded: false,
selectOptions: []
}
},
computed: {
popperClass() {
const _c = 'el-view-select-popper ' + this.popoverClass
return this.disabled ? _c + ' disabled ' : _c
},
selectedViews() {
return this.$store.getters.panelViews[this.panelId]
}
},
watch: {
value(val, old) {
this.innerValues = val
},
innerValues(val, old) {
if (val !== old) {
this.$emit('input', val)
}
},
panelId(val, old) {
if (val !== old) {
this.innerValues = []
this.loadView()
}
},
selectedViews: {
handler(val) {
if (!val || !JSON.stringify(val)) {
this.innerValues = []
return
}
const viewIds = JSON.parse(JSON.stringify(val))
this.innerValues = JSON.parse(JSON.stringify(viewIds))
},
deep: true
}
},
mounted() {
this._updateH()
this.$nextTick(() => {
on(document, 'mouseup', this._popoverHideFun)
})
},
beforeDestroy() {
this._selectClearFun()
off(document, 'mouseup', this._popoverHideFun)
},
created() {
this.loadView()
},
methods: {
loadView() {
this._selectClearFun()
this.innerValues = this.value
this.viewLoaded = false
this.panelId && findOne(this.panelId).then(response => {
this.panelInfo = {
id: response.data.id,
name: response.data.name,
privileges: response.data.privileges,
sourcePanelName: response.data.sourcePanelName,
status: response.data.status
}
this.$store.dispatch('panel/setPanelInfo', this.panelInfo)
panelDataPrepare(JSON.parse(response.data.panelData), JSON.parse(response.data.panelStyle), rsp => {
this.viewLoaded = true
this.componentData = rsp.componentData
this.canvasStyleData = rsp.componentStyle
this.loadOptions()
})
})
},
loadOptions() {
this.panelId && viewOptions(this.panelId).then(res => {
this.selectOptions = res.data
this.init()
})
},
_updateH() {
this.$nextTick(() => {
this.width = this.$refs.select.$el.getBoundingClientRect().width
this.panelHeight = this.width * 9 / 16
})
},
_popoverShowFun(val) {
this._updateH()
this.$emit('onFoucs')
},
_popoverHideFun(e) {
const path = this._getEventPath(e)
const isInside = path.some(list => {
return list.className && typeof list.className === 'string' && list.className.indexOf('el-view-select') !== -1
})
if (!isInside) {
this.visible = false
}
},
_getEventPath(evt) {
const path = (evt.composedPath && evt.composedPath()) || evt.path
const target = evt.target
if (path != null) {
return path.indexOf(window) < 0 ? path.concat(window) : path
}
if (target === window) {
return [window]
}
function getParents(node, memo) {
memo = memo || []
const parentNode = node.parentNode
if (!parentNode) {
return memo
} else {
return getParents(parentNode, memo.concat(parentNode))
}
}
return [target].concat(getParents(target), window)
},
_selectRemoveTag(viewId) {
this.selectedViews.forEach(item => {
if (item.viewId === viewId) {
this.$store.dispatch('task/delView', { 'panelId': this.panelId, 'viewId': item.viewId })
}
})
},
_selectClearFun() {
this.$store.dispatch('task/delPanelViews', this.panelId)
},
init() {
if (this.value && this.value.length) {
const viewIds = JSON.parse(JSON.stringify(this.value))
this.$store.dispatch('task/initPanelView', { 'panelId': this.panelId, 'viewIds': viewIds })
}
}
}
}
</script>
<style lang="scss" scoped>
.el-view-select .view-select-option {
display: none !important;
}
.el-view-select-popper {
max-height: 800px;
overflow: auto;
}
.el-view-select-popper.disabled {
display: none !important;
}
.el-view-select-popper .el-button--small {
width: 25px !important;
min-width: 25px !important;
}
.el-view-select-popper[x-placement^='bottom'] {
margin-top: 5px;
}
.my-top-class {
width: 100%;
}
</style>

View File

@ -3,7 +3,6 @@
<el-select
ref="select"
v-model="innerValues"
v-popover:popover
popper-class="view-select-option"
style="width: 100%;"
multiple
@ -20,26 +19,38 @@
/>
</el-select>
<el-popover ref="popover" v-model="visible" :placement="placement" :transition="transition" :popper-class="popperClass" :width="width" trigger="click">
<el-scrollbar v-if="viewLoaded" tag="div" wrap-class="el-select-dropdown__wrap" view-class="el-select-dropdown__list" class="is-empty">
<div :style="{'height': panelHeight + 'px'}">
<Preview
:component-data="componentData"
:canvas-style-data="canvasStyleData"
:panel-info="panelInfo"
:show-position="showPosition"
/>
</div>
</el-scrollbar>
<el-empty v-else style="height: 150px;" :image-size="120" description="" />
</el-popover>
<el-dialog
:visible="dialogShow"
:show-close="false"
class="dialog-css"
:fullscreen="true"
>
<div ref="contaninerDiv" :style="{'height': panelHeight + 'px'}" v-if="dialogShow && viewLoaded">
<Preview
:component-data="componentData"
:canvas-style-data="canvasStyleData"
:panel-info="panelInfo"
:show-position="showPosition"
/>
</div>
<div slot="title" class="dialog-footer title-text">
<span style="font-size: 14px;">
选择视图
</span>
<span style="float: right;">
<el-button type="primary" size="mini" @click="closeDialog()">{{ $t('commons.confirm') }}</el-button>
<el-button size="mini" @click="cancelDialog()">{{ $t('commons.cancel') }}</el-button>
</span>
</div>
</el-dialog>
</div>
</template>
<script>
import { on, off } from './dom'
import Preview from '@/components/canvas/components/Editor/Preview'
import { findOne } from '@/api/panel/panel'
import { viewOptions } from '@/api/chart/chart'
@ -69,7 +80,9 @@ export default {
panelHeight: 450,
showPosition: 'email-task',
viewLoaded: false,
selectOptions: []
selectOptions: [],
dialogShow: false,
idsBeforeOpen: []
}
},
computed: {
@ -111,13 +124,11 @@ export default {
},
mounted() {
this._updateH()
this.$nextTick(() => {
on(document, 'mouseup', this._popoverHideFun)
})
},
beforeDestroy() {
this._selectClearFun()
off(document, 'mouseup', this._popoverHideFun)
},
created() {
this.loadView()
@ -133,7 +144,11 @@ export default {
name: response.data.name,
privileges: response.data.privileges,
sourcePanelName: response.data.sourcePanelName,
status: response.data.status
status: response.data.status,
createBy: response.data.createBy,
createTime: response.data.createTime,
updateBy: response.data.updateBy,
updateTime: response.data.updateTime
}
this.$store.dispatch('panel/setPanelInfo', this.panelInfo)
panelDataPrepare(JSON.parse(response.data.panelData), JSON.parse(response.data.panelStyle), rsp => {
@ -153,47 +168,24 @@ export default {
},
_updateH() {
this.$nextTick(() => {
this.width = this.$refs.select.$el.getBoundingClientRect().width
this.panelHeight = this.width * 9 / 16
if(this.$refs.contaninerDiv) {
this.width = this.$refs.contaninerDiv.clientWidth
this.panelHeight = this.width * 9 / 16
}
})
},
_popoverShowFun(val) {
this.openDialog()
this._updateH()
this.$emit('onFoucs')
},
_popoverHideFun(e) {
const path = this._getEventPath(e)
const isInside = path.some(list => {
return list.className && typeof list.className === 'string' && list.className.indexOf('el-view-select') !== -1
})
if (!isInside) {
this.visible = false
}
},
_getEventPath(evt) {
const path = (evt.composedPath && evt.composedPath()) || evt.path
const target = evt.target
if (path != null) {
return path.indexOf(window) < 0 ? path.concat(window) : path
}
if (target === window) {
return [window]
}
function getParents(node, memo) {
memo = memo || []
const parentNode = node.parentNode
if (!parentNode) {
return memo
} else {
return getParents(parentNode, memo.concat(parentNode))
}
}
return [target].concat(getParents(target), window)
},
_selectRemoveTag(viewId) {
this.selectedViews.forEach(item => {
if (item.viewId === viewId) {
this.$store.dispatch('task/delView', { 'panelId': this.panelId, 'viewId': item.viewId })
if (item === viewId) {
this.$store.dispatch('task/delView', { 'panelId': this.panelId, 'viewId': item })
}
})
},
@ -205,6 +197,21 @@ export default {
const viewIds = JSON.parse(JSON.stringify(this.value))
this.$store.dispatch('task/initPanelView', { 'panelId': this.panelId, 'viewIds': viewIds })
}
},
openDialog() {
if (this.value && this.value.length) {
this.idsBeforeOpen = JSON.parse(JSON.stringify(this.value))
}
this.dialogShow = true
},
closeDialog() {
this.dialogShow = false
},
cancelDialog() {
this.innerValues = JSON.parse(JSON.stringify(this.idsBeforeOpen))
const viewIds = JSON.parse(JSON.stringify(this.innerValues))
this.$store.dispatch('task/initPanelView', { 'panelId': this.panelId, 'viewIds': viewIds })
this.closeDialog()
}
}
@ -216,23 +223,18 @@ export default {
display: none !important;
}
.el-view-select-popper {
max-height: 800px;
overflow: auto;
}
.el-view-select-popper.disabled {
display: none !important;
}
.el-view-select-popper .el-button--small {
width: 25px !important;
min-width: 25px !important;
}
.el-view-select-popper[x-placement^='bottom'] {
margin-top: 5px;
}
.my-top-class {
width: 100%;
}
.dialog-css ::v-deep .el-dialog__title {
font-size: 14px;
}
.dialog-css ::v-deep .el-dialog__header {
padding: 20px 20px 0;
}
.dialog-css ::v-deep .el-dialog__body {
padding: 10px 20px 20px;
}
</style>

View File

@ -5,7 +5,7 @@
@click="handleClick"
@mousedown="elementMouseDown"
>
<edit-bar v-if="componentActiveFlag" :element="config" @showViewDetails="showViewDetails" />
<edit-bar v-if="componentActiveFlag" :element="config" :show-position="showPosition" @showViewDetails="showViewDetails" />
<div :id="componentCanvasId" :style="commonStyle" class="main_view">
<close-bar v-if="previewVisible" @closePreview="closePreview" />
<de-out-widget
@ -150,7 +150,7 @@ export default {
return style
},
componentActiveFlag() {
return (this.curComponent && this.config === this.curComponent) && !this.previewVisible && !this.showPosition.includes('multiplexing') && !this.showPosition.includes('email-task')
return (this.curComponent && this.config === this.curComponent && !this.previewVisible && this.showPosition.includes('multiplexing') && !this.showPosition.includes('email-task')) || this.showPosition.includes('multiplexing')
},
curGap() {
return (this.canvasStyleData.panel.gap === 'yes' && this.config.auxiliaryMatrix) ? this.componentGap : 0

View File

@ -30,7 +30,8 @@ export default {
copyData: null,
editFilter: [
'view',
'custom'
'custom',
'custom-button'
]
}
},
@ -56,6 +57,10 @@ export default {
bus.$emit('component-dialog-edit')
}
if (this.curComponent.type === 'custom-button') {
bus.$emit('button-dialog-edit')
}
//
if (this.curComponent.type === 'v-text' || this.curComponent.type === 'de-rich-text' || this.curComponent.type === 'rect-shape') {

View File

@ -1,10 +1,13 @@
<template>
<div class="bar-main">
<div class="bar-main" :class="showEditPosition">
<input id="input" ref="files" type="file" accept="image/*" hidden @click="e => {e.target.value = '';}" @change="handleFileChange">
<div v-if="linkageAreaShow" style="margin-right: -1px;width: 20px">
<el-checkbox v-model="linkageInfo.linkageActive" size="medium" />
<linkage-field v-if="linkageInfo.linkageActive" :element="element" />
</div>
<div v-if="positionCheck('multiplexing')" style="margin-right: 1px;width: 18px;z-index: 5">
<el-checkbox v-model="multiplexingCheckModel" size="medium" @change="multiplexingCheck" />
</div>
<div v-if="batchOptAreaShow" style="margin-right: -1px;width: 20px;z-index: 5">
<el-checkbox size="medium" @change="batchOptChange" />
</div>
@ -73,15 +76,23 @@ export default {
previewVisible: {
type: Boolean,
default: false
},
showPosition: {
type: String,
required: false,
default: 'NotProvided'
}
},
data() {
return {
multiplexingCheckModel: false,
barWidth: 24,
componentType: null,
linkageActiveStatus: false,
editFilter: [
'view',
'custom'
'custom',
'custom-button'
],
timer: null
}
@ -89,6 +100,21 @@ export default {
mounted() {
},
computed: {
showEditPosition() {
if (this.activeModel === 'edit') {
const toRight = (this.canvasStyleData.width - this.element.style.left - this.element.style.width) * this.curCanvasScale.scalePointWidth
const toLeft = this.element.style.left * this.curCanvasScale.scalePointWidth
if (this.barWidth < toRight) {
return 'bar-main-right'
} else if (this.barWidth > toRight && this.barWidth > toLeft) {
return 'bar-main-left-inner'
} else {
return 'bar-main-left-outer'
}
} else {
return 'bar-main-preview'
}
},
showJumpFlag() {
return this.curComponent && this.curComponent.hyperlinks && this.curComponent.hyperlinks.enable
},
@ -102,7 +128,7 @@ export default {
},
//
normalAreaShow() {
return !this.linkageSettingStatus && !this.batchOptStatus
return !this.linkageSettingStatus && !this.batchOptStatus && !this.positionCheck('multiplexing')
},
existLinkage() {
let linkageFiltersCount = 0
@ -121,14 +147,14 @@ export default {
return this.targetLinkageInfo[this.element.propValue.viewId]
},
miniHeight() {
let miniHeight = this.curComponent.miniSizey || 1
let miniHeight = 4
if (this.element.component === 'de-number-range') {
miniHeight = this.curComponent.miniSizey || 2
miniHeight = 4
}
return miniHeight
},
miniWidth() {
return this.curComponent.miniSizex || 1
return 4
},
...mapState([
'menuTop',
@ -148,6 +174,18 @@ export default {
beforeDestroy() {
},
methods: {
positionCheck(position) {
return this.showPosition.includes(position)
},
multiplexingCheck(val) {
if (val) {
// push
this.$store.commit('addCurMultiplexingComponent', { 'component': this.element, 'componentId': this.element.id })
} else {
// remove
this.$store.commit('removeCurMultiplexingComponentWithId', this.element.id )
}
},
closePreview() {
this.$emit('closePreview')
},
@ -199,6 +237,8 @@ export default {
edit() {
if (this.curComponent.type === 'custom') {
bus.$emit('component-dialog-edit', 'update')
} else if (this.curComponent.type === 'custom-button') {
bus.$emit('button-dialog-edit')
} else if (this.curComponent.type === 'v-text' || this.curComponent.type === 'de-rich-text' || this.curComponent.type === 'rect-shape') {
bus.$emit('component-dialog-style')
} else { bus.$emit('change_panel_right_draw', true) }
@ -265,7 +305,6 @@ export default {
<style lang="scss" scoped>
.bar-main{
position: absolute;
right: 0px;
float:right;
z-index: 2;
border-radius:2px;
@ -288,5 +327,22 @@ export default {
.bar-main ::v-deep .el-checkbox__inner::after{
width: 4.5px;
}
.bar-main-right{
width: 22px;
right: -25px;
}
.bar-main-left-inner{
width: 22px;
left: 0px;
}
.bar-main-left-outer{
width: 22px;
left: -25px;
}
.bar-main-preview{
right: 0px;
}
</style>

View File

@ -60,7 +60,8 @@ export default {
hyperlinksSetVisible: false,
editFilter: [
'view',
'custom'
'custom',
'custom-button'
]
}
},
@ -72,6 +73,8 @@ export default {
edit() {
if (this.curComponent.type === 'custom') {
bus.$emit('component-dialog-edit', 'update')
}else if (this.curComponent.type === 'custom-button') {
bus.$emit('button-dialog-edit')
} else if (this.curComponent.type === 'v-text' || this.curComponent.type === 'de-rich-text' || this.curComponent.type === 'rect-shape') {
bus.$emit('component-dialog-style')
} else { bus.$emit('change_panel_right_draw', true) }

View File

@ -236,7 +236,7 @@ export default {
}
},
editBarViewShowFlag() {
return (this.active && this.inTab && !this.mobileLayoutStatus) || this.showPosition.includes('multiplexing') || this.showPosition.includes('email-task')
return (this.active && this.inTab && !this.mobileLayoutStatus) && !this.showPosition.includes('multiplexing') || this.showPosition.includes('email-task')
},
charViewShowFlag() {
return this.httpRequest.status && this.chart.type && !this.chart.type.includes('table') && !this.chart.type.includes('text') && this.chart.type !== 'label' && this.renderComponent() === 'echarts'

View File

@ -35,10 +35,10 @@ export default {
const canvasStyleData = state.canvasStyleData
const curCanvasScale = state.curCanvasScale
const componentGap = state.componentGap
Object.keys(state.curMultiplexingComponents).forEach(function(viewId, index) {
Object.keys(state.curMultiplexingComponents).forEach(function(componentId, index) {
const component =
{
...deepCopy(state.curMultiplexingComponents[viewId]),
...deepCopy(state.curMultiplexingComponents[componentId]),
...deepCopy(deepCopy(state.viewBase)),
'auxiliaryMatrix': canvasStyleData.auxiliaryMatrix
}
@ -105,6 +105,7 @@ export default {
} else if (data.type === 'de-tabs') {
const sourceAndTargetIds = {}
const newCop = deepCopy(data)
newCop.id = uuid.v1()
newCop.options.tabList.forEach((item) => {
if (item.content && item.content.type === 'view') {
const newViewId = uuid.v1()

View File

@ -4,6 +4,7 @@
v-if="options!== null && options.attrs!==null"
:type="options.attrs.type"
:round="options.attrs.round"
:plain="options.attrs.plain"
:size="size"
>
{{ options.value }}

View File

@ -80,6 +80,7 @@
:filters="filterMap[item.content.propValue && item.content.propValue.viewId] || []"
:out-style="outStyle"
:canvas-style-data="canvasStyleData"
:show-position="showPosition"
/>
</div>
@ -193,6 +194,11 @@ export default {
h: {
type: Number,
default: 200
},
showPosition: {
type: String,
required: false,
default: 'NotProvided'
}
},
data() {

View File

@ -0,0 +1,29 @@
<template>
<div>
<el-button type="primary" @click="execute" plain>{{text}}</el-button>
</div>
</template>
<script>
export default {
name: 'SearchButton',
props: {
},
data() {
return {
text: '查询'
}
},
methods: {
execute() {
console.log('开始查询。。。')
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -2,15 +2,15 @@ import { WidgetService } from '../service/WidgetService'
const leftPanel = {
icon: 'iconfont icon-chaxunsousuo',
label: '确定',
label: '查询按钮',
defaultClass: 'time-filter'
}
const drawPanel = {
type: 'custom',
type: 'custom-button',
style: {
width: 300,
height: 47,
width: 150,
height: 60,
fontSize: 14,
fontWeight: 500,
lineHeight: '',
@ -21,9 +21,12 @@ const drawPanel = {
options: {
attrs: {
type: 'primary',
round: true
round: false,
plain: true,
customRange: false,
filterIds: []
},
value: '测试按钮'
value: '查询'
},
component: 'de-button',
miniSizex: 1,
@ -35,6 +38,7 @@ class ButtonSureServiceImpl extends WidgetService {
Object.assign(options, { name: 'buttonSureWidget' })
super(options)
this.filterDialog = false
this.buttonDialog = true
this.showSwitch = false
}

View File

@ -132,7 +132,7 @@ export default {
},
commons: {
manage_member: 'Managing members',
user_confirm_remove_cancel:'Are you sure you want to remove the user from the role?',
user_confirm_remove_cancel: 'Are you sure you want to remove the user from the role?',
confirm_remove_cancel: 'Are you sure to delete the role?',
default_value: 'Default Value',
params_value: 'Param Value',
@ -623,12 +623,11 @@ export default {
can_not_move: `Can't be removed, keep at least one administrator`,
manage_can_not_move: 'Administrator is a preset role of the system. By default, he has all the permissions of system management and cannot be deleted',
manage_can_not_update: 'Administrator is a preset role of the system. By default, he has all the permissions of system management and cannot be edit',
role_name: 'Role name',
role_description: 'Role description',
editer_role: 'Edit role',
add_role: 'Add role',
role_name_exist: 'The role name already exists',
search_by_role: 'Search by role name',
search_by_role: 'Search by role name'
},
menu: {
parent_category: 'Parent Category',
@ -667,7 +666,6 @@ export default {
member: 'member',
organization: 'organization',
add_user: 'Add user',
search_by_name: 'Search by organization name',
sure_move_user: 'Are you sure to remove this user from the organization?',
move_success: 'Removed successfully',
user: 'user',
@ -680,9 +678,8 @@ export default {
canot_delete: 'Cannot delete',
remove_user_first: 'Please remove all users in the organization before deleting the organization',
sure_delete_organization: 'Are you sure to delete this organization?',
delete: 'delete',
add_child_org: 'Add sub organization',
edite_organization: 'Edit organization',
edite_organization: 'Edit organization'
},
system_parameter_setting: {
mailbox_service_settings: 'Mail Settings',
@ -1179,6 +1176,7 @@ export default {
remark_bg_color: 'Background Fill'
},
dataset: {
parse_filed: 'Parse Field',
field_rename: 'Rename Field',
params_work: 'Effective only when editing SQL',
sql_variable_limit_1: '1、SQL variables can only be used in where conditions',
@ -1546,6 +1544,13 @@ export default {
sure_bt: 'Confirm'
},
panel: {
panel_background_item: 'Customize panel background',
panel_background_image_tips: 'Currently.Jpeg,.Jpg,.Png,.Gif files are supported, and the size should not exceed 15m',
reUpload: 'reUpload',
create_by: 'Create By',
create_time: 'Create Time',
update_by: 'Update By',
update_time: 'Update Time',
target_url: 'Target Url',
target_url_tips: 'You can click fields to splice URLs or parameters',
select_world: 'Select World',
@ -1919,8 +1924,6 @@ export default {
column_permission: 'Column permission rule',
enable_column: 'Enable column permissions',
search_by_field: 'Search by field name',
add_condition: 'Add condition',
add_relationship: 'Add relationship',
filter_fields: 'Filter fields',
selct_filter_fields: 'Please select a filter field',
enter_keywords: 'Please enter keywords',
@ -1934,7 +1937,7 @@ export default {
please_fill: 'Please fill in one line and add 500 at most. Duplicate options and added options will be automatically filtered when identifying and entering',
close: 'close',
add: 'add to',
sure: 'determine',
sure: 'determine'
},
about: {
auth_to: 'Authorized to',

View File

@ -624,12 +624,11 @@ export default {
can_not_move: '不可移除,至少保留一位管理員',
manage_can_not_move: '管理員是系統預置角色,默認擁有系統管理全部權限,無法刪除',
manage_can_not_update: '管理員是系統預置角色,默認擁有系統管理全部權限,無法編輯',
role_name: '角色名稱',
role_description: '角色描述',
editer_role: '編輯角色',
add_role: '添加角色',
role_name_exist: '該角色名稱已存在',
search_by_role: '通過角色名稱搜索',
search_by_role: '通過角色名稱搜索'
},
menu: {
parent_category: '上級目錄',
@ -658,7 +657,6 @@ export default {
create_time: '創建日期',
create: '新建組織',
modify: '修改組織',
delete: '刪除組織',
delete_confirm: '確定要刪除該組織嗎?',
input_name: '請輸入組織名稱',
select_organization: '請選擇組織',
@ -668,7 +666,6 @@ export default {
member: '成員',
organization: '組織',
add_user: '添加用戶',
search_by_name: '通過組織名稱搜索',
sure_move_user: '確定將該用戶從組織中移除嗎?',
move_success: '移除成功',
user: '用戶',
@ -683,7 +680,7 @@ export default {
sure_delete_organization: '確定刪除該組織嗎?',
delete: '刪除',
add_child_org: '添加子組織',
edite_organization: '編輯組織',
edite_organization: '編輯組織'
},
system_parameter_setting: {
mailbox_service_settings: '郵件設置',
@ -1178,6 +1175,7 @@ export default {
remark_bg_color: '背景填充'
},
dataset: {
parse_filed: '解析字段',
field_rename: '字段重命名',
params_work: '僅在編輯 sql 時生效',
sql_variable_limit_1: '1、SQL變數只能在WHERE條件中使用',
@ -1546,6 +1544,13 @@ export default {
sure_bt: '確定'
},
panel: {
panel_background_item: '自定义仪表板背景',
panel_background_image_tips: '当前支持.jpeg,.jpg,.png,.gif文件,大小不要超过15M',
reUpload: '重新上传',
create_by: '创建人',
create_time: '创建时间',
update_by: '最近修改人',
update_time: '最近修改时间',
target_url: '目标URL',
target_url_tips: '可以点击字段用来拼接URL或者参数',
select_world: '点击选择字段',
@ -1930,8 +1935,6 @@ export default {
column_permission: '列權限規則',
enable_column: '啟用列權限',
search_by_field: '通過字段名稱搜索',
add_condition: '添加條件',
add_relationship: '添加關系',
filter_fields: '篩選字段',
selct_filter_fields: '請選擇篩選字段',
enter_keywords: '請輸關鍵字',
@ -1945,7 +1948,7 @@ export default {
please_fill: '請一行填一個最多添加500個,識別錄入時會自動過濾重復的選項和已經添加過的選項',
close: '關 閉',
add: '添 加',
sure: '確 定',
sure: '確 定'
},
about: {
auth_to: '授權給',

View File

@ -133,7 +133,7 @@ export default {
commons: {
manage_member: '管理成员',
confirm_remove_cancel: '确定删除该角色吗?',
user_confirm_remove_cancel:'确定将该用户从角色中移除吗?',
user_confirm_remove_cancel: '确定将该用户从角色中移除吗?',
default_value: '默认值',
params_value: '参数值',
input_role_name: '请输入角色名称',
@ -615,7 +615,6 @@ export default {
modify: '修改角色',
tips: '提示',
confirm_delete: '确认删除角色 ',
role_name: '角色名称',
search_by_name: '按名称搜索',
pls_input_name: '请输入名称',
search_by_name_email: '通过姓名或邮箱搜索',
@ -630,7 +629,7 @@ export default {
editer_role: '编辑角色',
add_role: '添加角色',
role_name_exist: '该角色名称已存在',
search_by_role: '通过角色名称搜索',
search_by_role: '通过角色名称搜索'
},
menu: {
parent_category: '上级目录',
@ -659,7 +658,6 @@ export default {
create_time: '创建日期',
create: '新建组织',
modify: '修改组织',
delete: '删除组织',
delete_confirm: '确定要删除该组织吗?',
input_name: '请输入组织名称',
select_organization: '请选择组织',
@ -669,7 +667,6 @@ export default {
member: '成员',
organization: '组织',
add_user: '添加用户',
search_by_name: '通过组织名称搜索',
sure_move_user: '确定将该用户从组织中移除吗?',
move_success: '移除成功',
user: '用户',
@ -684,7 +681,7 @@ export default {
sure_delete_organization: '确定删除该组织吗?',
delete: '删除',
add_child_org: '添加子组织',
edite_organization: '编辑组织',
edite_organization: '编辑组织'
},
system_parameter_setting: {
mailbox_service_settings: '邮件设置',
@ -1180,6 +1177,7 @@ export default {
remark_bg_color: '背景填充'
},
dataset: {
parse_filed: '解析字段',
field_rename: '字段重命名',
params_work: '仅在编辑sql时生效',
select_year: '选择年',
@ -1554,6 +1552,13 @@ export default {
sure_bt: '确定'
},
panel: {
panel_background_item: '自定义仪表板背景',
panel_background_image_tips: '当前支持.jpeg,.jpg,.png,.gif文件,大小不要超过15M',
reUpload: '重新上传',
create_by: '创建人',
create_time: '创建时间',
update_by: '最近修改人',
update_time: '最近修改时间',
target_url: '目标URL',
target_url_tips: '可以点击字段用来拼接URL或者参数',
select_world: '点击选择字段',
@ -1931,8 +1936,6 @@ export default {
row_column: '行列权限设置',
row_permission: '行权限规则',
enable_row: '启用行权限',
add_condition: '添加条件',
add_relationship: '添加关系',
white_list: '白名单',
white_user_not: '以上权限规则对白名单用户不生效',
organization_or_role: '请选择组织或角色',
@ -1954,7 +1957,7 @@ export default {
please_fill: '请一行填一个最多添加500个,识别录入时会自动过滤重复的选项和已经添加过的选项',
close: '关 闭',
add: '添 加',
sure: '确 定',
sure: '确 定'
},
about: {
auth_to: '授权给',

View File

@ -329,7 +329,7 @@ export default {
if (result !== 'success' && result !== 'fail') {
window.location.href = result
} else {
this.$router.push(`/login?redirect=${this.$route.fullPath}`)
this.$router.push('/login')
}
},
loadUiInfo() {

View File

@ -92,7 +92,8 @@ router.beforeEach(async(to, from, next) => {
next()
} else {
// other pages that do not have permission to access are redirected to the login page.
next(`/login?redirect=${to.path}`)
// next(`/login?redirect=${to.path}`)
next('/login')
NProgress.done()
}
}

View File

@ -110,6 +110,23 @@ div:focus {
}
}
.de-button-dialog {
min-width: 250px !important;
width: 30% !important;
.el-dialog__header {
padding: 10px 20px !important;
.el-dialog__headerbtn {
top: 15px !important;
}
}
.el-dialog__body {
padding: 1px 15px !important;
}
}
.de-style-dialog {
width: 600px !important;

View File

@ -213,7 +213,7 @@ export default {
},
upload(file) {
const _this = this
uploadFileResult(file, (fileUrl) => {
uploadFileResult(file.file, (fileUrl) => {
_this.curComponent.commonBackground.outerImage = fileUrl
})
}

View File

@ -31,6 +31,11 @@ export function getCustomTheme(chart) {
fill: DEFAULT_COLOR_CASE.tableFontColor,
fontSize: DEFAULT_SIZE.tableTitleFontSize,
textAlign: headerAlign
},
measureText: {
fill: DEFAULT_COLOR_CASE.tableFontColor,
fontSize: DEFAULT_SIZE.tableTitleFontSize,
textAlign: headerAlign
}
},
rowCell: {
@ -48,6 +53,11 @@ export function getCustomTheme(chart) {
fill: DEFAULT_COLOR_CASE.tableFontColor,
fontSize: DEFAULT_SIZE.tableTitleFontSize,
textAlign: headerAlign
},
measureText: {
fill: DEFAULT_COLOR_CASE.tableFontColor,
fontSize: DEFAULT_SIZE.tableTitleFontSize,
textAlign: headerAlign
}
},
colCell: {
@ -65,6 +75,11 @@ export function getCustomTheme(chart) {
fill: DEFAULT_COLOR_CASE.tableFontColor,
fontSize: DEFAULT_SIZE.tableTitleFontSize,
textAlign: headerAlign
},
measureText: {
fill: DEFAULT_COLOR_CASE.tableFontColor,
fontSize: DEFAULT_SIZE.tableTitleFontSize,
textAlign: headerAlign
}
},
dataCell: {
@ -82,6 +97,11 @@ export function getCustomTheme(chart) {
fill: DEFAULT_COLOR_CASE.tableFontColor,
fontSize: DEFAULT_SIZE.tableItemFontSize,
textAlign: itemAlign
},
measureText: {
fill: DEFAULT_COLOR_CASE.tableFontColor,
fontSize: DEFAULT_SIZE.tableItemFontSize,
textAlign: headerAlign
}
}
}
@ -103,24 +123,28 @@ export function getCustomTheme(chart) {
theme.cornerCell.cell.verticalBorderColor = b_c
theme.cornerCell.bolderText.fill = c.tableFontColor
theme.cornerCell.text.fill = c.tableFontColor
theme.cornerCell.measureText.fill = c.tableFontColor
theme.rowCell.cell.backgroundColor = h_c
theme.rowCell.cell.horizontalBorderColor = b_c
theme.rowCell.cell.verticalBorderColor = b_c
theme.rowCell.bolderText.fill = c.tableFontColor
theme.rowCell.text.fill = c.tableFontColor
theme.rowCell.measureText.fill = c.tableFontColor
theme.colCell.cell.backgroundColor = h_c
theme.colCell.cell.horizontalBorderColor = b_c
theme.colCell.cell.verticalBorderColor = b_c
theme.colCell.bolderText.fill = c.tableFontColor
theme.colCell.text.fill = c.tableFontColor
theme.colCell.measureText.fill = c.tableFontColor
theme.dataCell.cell.backgroundColor = i_c
theme.dataCell.cell.horizontalBorderColor = b_c
theme.dataCell.cell.verticalBorderColor = b_c
theme.dataCell.bolderText.fill = c.tableFontColor
theme.dataCell.text.fill = c.tableFontColor
theme.dataCell.measureText.fill = c.tableFontColor
}
// size
if (customAttr.size) {
@ -132,21 +156,29 @@ export function getCustomTheme(chart) {
theme.cornerCell.bolderText.textAlign = h_a
theme.cornerCell.text.fontSize = parseInt(s.tableTitleFontSize)
theme.cornerCell.text.textAlign = h_a
theme.cornerCell.measureText.fontSize = parseInt(s.tableTitleFontSize)
theme.cornerCell.measureText.textAlign = h_a
theme.rowCell.bolderText.fontSize = parseInt(s.tableTitleFontSize)
theme.rowCell.bolderText.textAlign = h_a
theme.rowCell.text.fontSize = parseInt(s.tableTitleFontSize)
theme.rowCell.text.textAlign = h_a
theme.rowCell.measureText.fontSize = parseInt(s.tableTitleFontSize)
theme.rowCell.measureText.textAlign = h_a
theme.colCell.bolderText.fontSize = parseInt(s.tableTitleFontSize)
theme.colCell.bolderText.textAlign = h_a
theme.colCell.text.fontSize = parseInt(s.tableTitleFontSize)
theme.colCell.text.textAlign = h_a
theme.colCell.measureText.fontSize = parseInt(s.tableTitleFontSize)
theme.colCell.measureText.textAlign = h_a
theme.dataCell.bolderText.fontSize = parseInt(s.tableItemFontSize)
theme.dataCell.bolderText.textAlign = i_a
theme.dataCell.text.fontSize = parseInt(s.tableItemFontSize)
theme.dataCell.text.textAlign = i_a
theme.dataCell.measureText.fontSize = parseInt(s.tableItemFontSize)
theme.dataCell.measureText.textAlign = i_a
}
}

View File

@ -29,6 +29,7 @@ export function baseGaugeOptionAntV(plot, container, chart, action, scale = 1) {
// label
if (customAttr.label) {
const label = JSON.parse(JSON.stringify(customAttr.label))
labelFormatter = label.gaugeLabelFormatter ? label.gaugeLabelFormatter : DEFAULT_LABEL.gaugeLabelFormatter
if (label.show) {
labelContent = {
style: ({ percent }) => ({
@ -48,7 +49,6 @@ export function baseGaugeOptionAntV(plot, container, chart, action, scale = 1) {
} else {
labelContent = false
}
labelFormatter = label.gaugeLabelFormatter ? label.gaugeLabelFormatter : DEFAULT_LABEL.gaugeLabelFormatter
}
const range = [0]

View File

@ -1,6 +1,9 @@
import { Liquid } from '@antv/g2plot'
import { hexColorToRGBA } from '@/views/chart/chart/util'
import { DEFAULT_SIZE } from '@/views/chart/chart/chart'
import { DEFAULT_LABEL, DEFAULT_SIZE } from '@/views/chart/chart/chart'
import { valueFormatter } from '@/views/chart/chart/formatter'
let labelFormatter = null
export function baseLiquid(plot, container, chart) {
let value = 0
@ -31,12 +34,17 @@ export function baseLiquid(plot, container, chart) {
// label
if (customAttr.label) {
const label = JSON.parse(JSON.stringify(customAttr.label))
labelFormatter = label.gaugeLabelFormatter ? label.gaugeLabelFormatter : DEFAULT_LABEL.gaugeLabelFormatter
if (label.show) {
labelContent = {
style: ({ percent }) => ({
fontSize: parseInt(label.fontSize),
color: label.color
})
}),
formatter: function(v) {
const value = v.percent
return valueFormatter(value, labelFormatter)
}
}
} else {
labelContent = false

View File

@ -1,3 +1,5 @@
import { DEFAULT_TITLE_STYLE } from '@/views/chart/chart/chart'
export function hexColorToRGBA(hex, alpha) {
const rgb = [] // 定义rgb数组
if (/^\#[0-9A-F]{3}$/i.test(hex)) { // 判断传入是否为#三位十六进制数
@ -63,7 +65,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
]
}
},
@ -104,7 +107,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
]
}
},
@ -148,7 +152,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
]
}
},
@ -181,7 +186,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
]
}
},
@ -214,7 +220,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
]
}
},
@ -253,7 +260,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
]
}
},
@ -281,9 +289,7 @@ export const TYPE_CONFIGS = [
'liquidSize'
],
'label-selector-ant-v': [
'show',
'fontSize',
'color'
'labelGauge'
],
'title-selector-ant-v': [
'show',
@ -292,7 +298,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
]
}
},
@ -360,7 +367,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
],
'legend-selector-ant-v': [
'show',
@ -436,7 +444,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
],
'legend-selector-ant-v': [
'show',
@ -512,7 +521,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
],
'legend-selector-ant-v': [
'show',
@ -587,7 +597,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
],
'legend-selector-ant-v': [
'show',
@ -655,7 +666,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
]
}
},
@ -722,7 +734,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
],
'legend-selector-ant-v': [
'show',
@ -797,7 +810,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
],
'legend-selector-ant-v': [
'show',
@ -851,7 +865,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
],
'legend-selector-ant-v': [
'show',
@ -905,7 +920,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
],
'legend-selector-ant-v': [
'show',
@ -960,7 +976,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
],
'legend-selector-ant-v': [
'show',
@ -1012,7 +1029,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
],
'legend-selector-ant-v': [
'show',
@ -1051,7 +1069,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
]
}
},
@ -1118,7 +1137,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
],
'legend-selector-ant-v': [
'show',
@ -1167,7 +1187,8 @@ export const TYPE_CONFIGS = [
'color',
'hPosition',
'isItalic',
'isBolder'
'isBolder',
'remarkShow'
],
'legend-selector-ant-v': [
'show',
@ -1351,8 +1372,6 @@ export const TYPE_CONFIGS = [
'show',
'fontSize',
'color',
'position-v',
'formatter',
'gaugeFormatter'
],
'title-selector': [
@ -2496,3 +2515,17 @@ export function antVCustomColor(chart) {
}
return colors
}
export function getRemark(chart) {
const remark = {}
if (chart.customStyle) {
const customStyle = JSON.parse(chart.customStyle)
if (customStyle.text) {
const title = JSON.parse(JSON.stringify(customStyle.text))
remark.show = title.remarkShow ? title.remarkShow : DEFAULT_TITLE_STYLE.remarkShow
remark.content = title.remark ? title.remark : DEFAULT_TITLE_STYLE.remark
remark.bgFill = title.remarkBackgroundColor ? title.remarkBackgroundColor : DEFAULT_TITLE_STYLE.remarkBackgroundColor
}
}
return remark
}

View File

@ -2,7 +2,10 @@
<div ref="chartContainer" style="padding: 0;width: 100%;height: 100%;overflow: hidden;" :style="bg_class">
<view-track-bar ref="viewTrack" :track-menu="trackMenu" class="track-bar" :style="trackBarStyleTime" @trackClick="trackClick" />
<span v-if="chart.type && antVRenderStatus" v-show="title_show" ref="title" :style="title_class" style="cursor: default;display: block;">
<p style="padding:6px 10px 0 10px;margin: 0;overflow: hidden;white-space: pre;text-overflow: ellipsis;">{{ chart.title }}</p>
<div>
<p style="padding:6px 4px 0;margin: 0;overflow: hidden;white-space: pre;text-overflow: ellipsis;display: inline;">{{ chart.title }}</p>
<title-remark v-if="remarkCfg.show" :remark-cfg="remarkCfg" />
</div>
</span>
<div :id="chartId" style="width: 100%;overflow: hidden;" :style="{height:chartHeight}" />
</div>
@ -12,7 +15,7 @@
import { baseLiquid } from '@/views/chart/chart/liquid/liquid'
import { uuid } from 'vue-uuid'
import ViewTrackBar from '@/components/canvas/components/Editor/ViewTrackBar'
import { hexColorToRGBA } from '@/views/chart/chart/util'
import { getRemark, hexColorToRGBA } from '@/views/chart/chart/util'
import { baseBarOptionAntV, hBaseBarOptionAntV } from '@/views/chart/chart/bar/bar_antv'
import { baseAreaOptionAntV, baseLineOptionAntV } from '@/views/chart/chart/line/line_antv'
import { basePieOptionAntV, basePieRoseOptionAntV } from '@/views/chart/chart/pie/pie_antv'
@ -23,10 +26,11 @@ import { baseTreemapOptionAntV } from '@/views/chart/chart/treemap/treemap_antv'
import { baseRadarOptionAntV } from '@/views/chart/chart/radar/radar_antv'
import { baseWaterfallOptionAntV } from '@/views/chart/chart/waterfall/waterfall'
import { baseWordCloudOptionAntV } from '@/views/chart/chart/wordCloud/word_cloud'
import TitleRemark from '@/views/chart/view/TitleRemark'
export default {
name: 'ChartComponentG2',
components: { ViewTrackBar },
components: { TitleRemark, ViewTrackBar },
props: {
chart: {
type: Object,
@ -84,7 +88,11 @@ export default {
title_show: true,
antVRenderStatus: false,
linkageActiveParam: null,
linkageActiveHistory: false
linkageActiveHistory: false,
remarkCfg: {
show: false,
content: ''
}
}
},
@ -320,6 +328,7 @@ export default {
this.borderRadius = (customStyle.background.borderRadius || 0) + 'px'
}
}
this.initRemark()
},
calcHeightRightNow() {
@ -337,6 +346,9 @@ export default {
setTimeout(() => {
this.calcHeightRightNow()
}, 100)
},
initRemark() {
this.remarkCfg = getRemark(this.chart)
}
}
}

View File

@ -2,7 +2,10 @@
<div ref="chartContainer" style="padding: 0;width: 100%;height: 100%;overflow: hidden;" :style="bg_class">
<view-track-bar ref="viewTrack" :track-menu="trackMenu" class="track-bar" :style="trackBarStyleTime" @trackClick="trackClick" />
<span v-if="chart.type" v-show="title_show" ref="title" :style="title_class" style="cursor: default;display: block;">
<p style="padding:6px 10px 0 10px;margin: 0;overflow: hidden;white-space: pre;text-overflow: ellipsis;">{{ chart.title }}</p>
<div>
<p style="padding:6px 4px 0;margin: 0;overflow: hidden;white-space: pre;text-overflow: ellipsis;display: inline;">{{ chart.title }}</p>
<title-remark v-if="remarkCfg.show" :remark-cfg="remarkCfg" />
</div>
</span>
<div ref="tableContainer" style="width: 100%;overflow: hidden;" :style="{background:container_bg_class.background}">
<div v-if="chart.type === 'table-normal'" :id="chartId" style="width: 100%;overflow: hidden;" :class="chart.drill ? 'table-dom-normal-drill' : 'table-dom-normal'" />
@ -34,12 +37,13 @@
<script>
import { uuid } from 'vue-uuid'
import ViewTrackBar from '@/components/canvas/components/Editor/ViewTrackBar'
import { hexColorToRGBA } from '@/views/chart/chart/util'
import { getRemark, hexColorToRGBA } from '@/views/chart/chart/util'
import { baseTableInfo, baseTableNormal, baseTablePivot } from '@/views/chart/chart/table/table-info'
import TitleRemark from '@/views/chart/view/TitleRemark'
export default {
name: 'ChartComponentS2',
components: { ViewTrackBar },
components: { TitleRemark, ViewTrackBar },
props: {
chart: {
type: Object,
@ -102,7 +106,11 @@ export default {
tableData: [],
showPage: false,
scrollTimer: null,
scrollTop: 0
scrollTop: 0,
remarkCfg: {
show: false,
content: ''
}
}
},
@ -322,6 +330,7 @@ export default {
this.container_bg_class.background = hexColorToRGBA(customStyle.background.color, customStyle.background.alpha)
}
}
this.initRemark()
},
calcHeightRightNow() {
@ -389,6 +398,9 @@ export default {
this.myChart.render()
}, senior.scrollCfg.interval)
}
},
initRemark() {
this.remarkCfg = getRemark(this.chart)
}
}
}

View File

@ -36,8 +36,44 @@
<el-checkbox v-model="titleForm.isBolder" @change="changeTitleStyle('isBolder')">{{ $t('chart.bolder') }}</el-checkbox>
</el-form-item>
</div>
<el-form-item v-show="showProperty('remarkShow')" :label="$t('chart.remark')" class="form-item">
<el-checkbox v-model="titleForm.remarkShow" @change="changeTitleStyle('remarkShow')">{{ $t('chart.show') }}</el-checkbox>
</el-form-item>
<span v-show="titleForm.remarkShow">
<el-form-item v-show="showProperty('remarkShow')" :label="$t('chart.remark_edit')" class="form-item">
<el-button
:title="$t('chart.edit')"
icon="el-icon-edit"
type="text"
size="small"
@click="editRemark"
/>
</el-form-item>
<el-form-item v-show="showProperty('remarkShow')" :label="$t('chart.remark_bg_color')" class="form-item">
<el-color-picker v-model="titleForm.remarkBackgroundColor" class="color-picker-style" :predefine="predefineColors" @change="changeTitleStyle('remarkBackgroundColor')" />
</el-form-item>
</span>
</el-form>
</el-col>
<!--富文本编辑框-->
<el-dialog
v-if="showEditRemark"
v-dialogDrag
:title="$t('chart.remark')"
:visible="showEditRemark"
:show-close="false"
width="70%"
class="dialog-css"
append-to-body
>
<remark-editor :remark="titleForm.remark" @onRemarkChange="onRemarkChange" />
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="closeRemark">{{ $t('chart.cancel') }}</el-button>
<el-button type="primary" size="mini" @click="changeRemark">{{ $t('chart.confirm') }}</el-button>
</div>
</el-dialog>
</div>
</template>
@ -45,9 +81,11 @@
import { COLOR_PANEL, DEFAULT_TITLE_STYLE } from '../../chart/chart'
import { checkViewTitle } from '@/components/canvas/utils/utils'
import { mapState } from 'vuex'
import RemarkEditor from '@/views/chart/components/component-style/dialog/RemarkEditor'
export default {
name: 'TitleSelectorAntV',
components: { RemarkEditor },
props: {
param: {
type: Object,
@ -70,7 +108,9 @@ export default {
titleForm: JSON.parse(JSON.stringify(DEFAULT_TITLE_STYLE)),
fontSize: [],
isSetting: false,
predefineColors: COLOR_PANEL
predefineColors: COLOR_PANEL,
showEditRemark: false,
tmpRemark: ''
}
},
computed: {
@ -101,6 +141,9 @@ export default {
}
if (customStyle.text) {
this.titleForm = customStyle.text
this.titleForm.remarkShow = this.titleForm.remarkShow ? this.titleForm.remarkShow : DEFAULT_TITLE_STYLE.remarkShow
this.titleForm.remark = this.titleForm.remark ? this.titleForm.remark : DEFAULT_TITLE_STYLE.remark
this.titleForm.remarkBackgroundColor = this.titleForm.remarkBackgroundColor ? this.titleForm.remarkBackgroundColor : DEFAULT_TITLE_STYLE.remarkBackgroundColor
}
if (!this.batchOptStatus) {
this.titleForm.title = this.chart.title
@ -138,6 +181,21 @@ export default {
},
showProperty(property) {
return this.propertyInner.includes(property)
},
editRemark() {
this.showEditRemark = true
},
closeRemark() {
this.showEditRemark = false
},
changeRemark() {
this.titleForm.remark = this.tmpRemark
this.changeTitleStyle('remark')
this.closeRemark()
},
onRemarkChange(val) {
this.tmpRemark = val
}
}
}
@ -162,12 +220,12 @@ export default {
.el-select-dropdown__item{
padding: 0 20px;
}
span{
font-size: 12px
}
.el-form-item{
margin-bottom: 6px;
}
span{
font-size: 12px
}
.el-form-item{
margin-bottom: 6px;
}
.switch-style{
position: absolute;
@ -178,4 +236,16 @@ export default {
cursor: pointer;
z-index: 1003;
}
.dialog-css >>> .el-dialog__title {
font-size: 14px;
}
.dialog-css >>> .el-dialog__header {
padding: 20px 20px 0;
}
.dialog-css >>> .el-dialog__body {
padding: 10px 20px 20px;
}
</style>

View File

@ -0,0 +1,72 @@
<template>
<div style="max-height: 50vh;overflow-y: auto;">
<Editor
v-model="content"
style="width: 100%;height: 100%"
:init="init"
/>
</div>
</template>
<script>
import tinymce from 'tinymce/tinymce' // tinymcehidden
import Editor from '@tinymce/tinymce-vue'//
export default {
name: 'RemarkEditor',
components: {
Editor
},
props: {
remark: {
type: String,
required: true
}
},
data() {
return {
content: '',
//
init: {
auto_focus: true,
toolbar_items_size: 'small',
language_url: '/tinymce/langs/zh_CN.js', // publicstatic
language: 'zh_CN',
skin_url: '/tinymce/skins/ui/oxide', //
content_css: '/tinymce/skins/content/default/content.css',
plugins: 'advlist autolink link image lists charmap media wordcount table contextmenu directionality pagebreak', //
//
toolbar: 'undo redo |fontselect fontsizeselect |forecolor backcolor bold italic |underline strikethrough link| formatselect |' +
'alignleft aligncenter alignright | bullist numlist |' +
' blockquote subscript superscript removeformat | table image media | fullscreen ' +
'| bdmap indent2em lineheight formatpainter axupimgs',
toolbar_location: '/',
toolbar_mode: 'wrap',
font_formats: '微软雅黑=Microsoft YaHei;宋体=SimSun;黑体=SimHei;仿宋=FangSong;华文黑体=STHeiti;华文楷体=STKaiti;华文宋体=STSong;华文仿宋=STFangsong;Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings',
fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px', //
menubar: false,
branding: false,
height: 300,
min_height: 200,
max_height: 500,
elementpath: false,
statusbar: false
}
}
},
watch: {
content: {
handler(newValue) {
this.$emit('onRemarkChange', newValue)
}
}
},
mounted() {
this.content = this.remark
tinymce.init({})
}
}
</script>
<style scoped>
</style>

View File

@ -100,7 +100,7 @@
<el-dropdown-item icon="el-icon-files" :command="beforeClickItem('filter')">
<span>{{ $t('chart.filter') }}...</span>
</el-dropdown-item>
<el-dropdown-item v-if="chart.render === 'antv'" icon="el-icon-notebook-2" divided :command="beforeClickItem('formatter')">
<el-dropdown-item v-if="chart.render === 'antv' && chart.type !== 'gauge' && chart.type !== 'liquid'" icon="el-icon-notebook-2" divided :command="beforeClickItem('formatter')">
<span>{{ $t('chart.value_formatter') }}...</span>
</el-dropdown-item>
<el-dropdown-item icon="el-icon-edit-outline" divided :command="beforeClickItem('rename')">

View File

@ -100,7 +100,7 @@
<el-dropdown-item icon="el-icon-files" :command="beforeClickItem('filter')">
<span>{{ $t('chart.filter') }}...</span>
</el-dropdown-item>
<el-dropdown-item v-if="chart.render === 'antv'" icon="el-icon-notebook-2" divided :command="beforeClickItem('formatter')">
<el-dropdown-item v-if="chart.render === 'antv' && chart.type !== 'gauge' && chart.type !== 'liquid'" icon="el-icon-notebook-2" divided :command="beforeClickItem('formatter')">
<span>{{ $t('chart.value_formatter') }}...</span>
</el-dropdown-item>
<el-dropdown-item icon="el-icon-edit-outline" divided :command="beforeClickItem('rename')">

View File

@ -1,6 +1,11 @@
<template>
<div ref="tableContainer" :style="bg_class" style="padding: 8px;width: 100%;height: 100%;overflow: hidden;">
<p v-show="title_show" ref="title" :style="title_class">{{ chart.title }}</p>
<div ref="tableContainer" :style="bg_class" style="width: 100%;height: 100%;overflow: hidden;">
<span v-show="title_show" ref="title" :style="title_class" style="cursor: default;display: block;">
<div>
<p style="padding:6px 4px 0;margin: 0;overflow: hidden;white-space: pre;text-overflow: ellipsis;display: inline;">{{ chart.title }}</p>
<title-remark v-if="chart.render && chart.render === 'antv' && remarkCfg.show" :remark-cfg="remarkCfg" />
</div>
</span>
<div
v-if="chart.data && chart.data.x && chart.data.x.length > 0 && chart.data.series && chart.data.series.length > 0 && chart.data.series[0].data && chart.data.series[0].data.length > 0"
id="label-content"
@ -21,12 +26,14 @@
</template>
<script>
import { hexColorToRGBA } from '../../chart/util'
import { getRemark, hexColorToRGBA } from '../../chart/util'
import eventBus from '@/components/canvas/utils/eventBus'
import { formatterItem, valueFormatter } from '@/views/chart/chart/formatter'
import TitleRemark from '@/views/chart/view/TitleRemark'
export default {
name: 'LabelNormal',
components: { TitleRemark },
props: {
chart: {
type: Object,
@ -78,7 +85,11 @@ export default {
},
title_show: true,
borderRadius: '0px',
result: ''
result: '',
remarkCfg: {
show: false,
content: ''
}
}
},
computed: {
@ -113,6 +124,7 @@ export default {
that.calcHeight()
}
this.setBackGroundBorder()
this.initRemark()
},
setBackGroundBorder() {
if (this.chart.customStyle) {
@ -227,6 +239,7 @@ export default {
},
resultFormat() {
if(!this.chart.data)return
const value = this.chart.data.series[0].data[0]
let yAxis = []
try {
@ -242,13 +255,16 @@ export default {
const v = valueFormatter(value, formatterItem)
this.result = v.includes('NaN') ? value : v
}
},
initRemark() {
this.remarkCfg = getRemark(this.chart)
}
}
}
</script>
<style scoped>
.table-class>>>.body--wrapper{
background: rgba(1,1,1,0);
}
.table-class>>>.body--wrapper{
background: rgba(1,1,1,0);
}
</style>

View File

@ -1,7 +1,12 @@
<template>
<div ref="tableContainer" :style="bg_class" style="width: 100%;height: 100%;overflow: hidden;">
<view-track-bar ref="viewTrack" :track-menu="trackMenu" class="track-bar" :style="trackBarStyleTime" @trackClick="trackClick" />
<p v-show="title_show" ref="title" :style="title_class">{{ chart.title }}</p>
<span v-show="title_show" ref="title" :style="title_class" style="cursor: default;display: block;">
<div>
<p style="padding:6px 4px 0;margin: 0;overflow: hidden;white-space: pre;text-overflow: ellipsis;display: inline;">{{ chart.title }}</p>
<title-remark v-if="chart.render && chart.render === 'antv' && remarkCfg.show" :remark-cfg="remarkCfg" />
</div>
</span>
<div
v-if="chart.data && chart.data.series && chart.data.series.length > 0"
id="label-content"
@ -22,13 +27,14 @@
</template>
<script>
import { hexColorToRGBA } from '../../chart/util'
import { getRemark, hexColorToRGBA } from '../../chart/util'
import eventBus from '@/components/canvas/utils/eventBus'
import ViewTrackBar from '@/components/canvas/components/Editor/ViewTrackBar'
import TitleRemark from '@/views/chart/view/TitleRemark'
export default {
name: 'LabelNormalText',
components: { ViewTrackBar },
components: { TitleRemark, ViewTrackBar },
props: {
chart: {
type: Object,
@ -93,7 +99,11 @@ export default {
left: '0px',
top: '0px'
},
pointParam: null
pointParam: null,
remarkCfg: {
show: false,
content: ''
}
}
},
computed: {
@ -130,6 +140,7 @@ export default {
that.calcHeight()
}
this.setBackGroundBorder()
this.initRemark()
},
setBackGroundBorder() {
if (this.chart.customStyle) {
@ -244,13 +255,16 @@ export default {
this.trackBarStyle.top = (this.$refs['textData'].offsetTop + this.$refs['textData'].offsetHeight + 10) + 'px'
this.$refs.viewTrack.trackButtonClick()
}
},
initRemark() {
this.remarkCfg = getRemark(this.chart)
}
}
}
</script>
<style scoped>
.table-class>>>.body--wrapper{
background: rgba(1,1,1,0);
}
.table-class>>>.body--wrapper{
background: rgba(1,1,1,0);
}
</style>

View File

@ -32,7 +32,7 @@
</div>
</el-form>
<el-form v-show="showProperty('labelGauge') && chart.type && chart.type.includes('gauge')" ref="labelForm" :model="labelForm" label-width="80px" size="mini">
<el-form v-show="showProperty('labelGauge') && chart.type && (chart.type.includes('gauge') || chart.type.includes('liquid'))" ref="labelForm" :model="labelForm" label-width="80px" size="mini">
<el-form-item :label="$t('chart.show')" class="form-item">
<el-checkbox v-model="labelForm.show" @change="changeLabelAttr">{{ $t('chart.show') }}</el-checkbox>
</el-form-item>

View File

@ -0,0 +1,44 @@
<template>
<span>
<el-popover
placement="bottom"
trigger="hover"
width="300"
popper-class="remark-pop"
:visible-arrow="false"
>
<div class="remark-style" :style="{backgroundColor:remarkCfg.bgFill}" v-html="remarkCfg.content" />
<i slot="reference" class="el-icon-info" style="cursor: pointer;color: gray;font-size: 12px;" />
</el-popover>
</span>
</template>
<script>
export default {
name: 'TitleRemark',
props: {
remarkCfg: {
type: Object,
required: true
}
}
}
</script>
<style scoped>
.remark-style{
min-height: 100px;
max-height: 200px;
overflow-y: auto;
padding: 10px;
border-radius: 4px;
}
</style>
<style>
.el-popover.remark-pop{
padding: 0;
border: none;
margin-top: 8px!important;
background: transparent;
}
</style>

View File

@ -57,7 +57,11 @@ export default {
id: res.data.id,
name: res.data.name,
privileges: res.data.privileges,
status: res.data.status
status: res.data.status,
createBy: res.data.createBy,
createTime: res.data.createTime,
updateBy: res.data.updateBy,
updateTime: res.data.updateTime
}
this.$store.dispatch('panel/setPanelInfo', this.panelInfo)

View File

@ -1,49 +1,47 @@
<template>
<div style="width: 100%;">
<div style="width: 100%;margin-top: 12px">
<el-form ref="overallSettingForm" :model="overallSettingForm" size="mini">
<el-col style="padding-bottom: 10px;">
<el-row>
<el-col class="custom-item">
<el-radio v-model="panel.backgroundType" label="color" style="float: right" @change="onChangeType">
<span style="font-size: 12px">{{ $t('chart.color') }}</span>
</el-radio>
</el-col>
<el-col :span="10">
<el-color-picker
v-model="panel.color"
:predefine="predefineColors"
size="mini"
class="color-picker-custom"
@change="onChangeType"
/>
</el-col>
</el-row>
<el-row style="height: 60px;margin-top:10px;overflow: hidden">
<el-col class="custom-item">
<el-radio v-model="panel.backgroundType" label="image" style="float: right" @change="onChangeType">
<span style="font-size: 12px">{{ $t('panel.photo') }}</span>
</el-radio>
</el-col>
<el-col :span="15">
<el-upload
action=""
accept=".jpeg,.jpg,.png,.gif"
class="avatar-uploader"
list-type="picture-card"
:http-request="upload"
:class="{disabled:uploadDisabled}"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:file-list="fileList"
>
<i class="el-icon-plus" />
</el-upload>
<el-dialog top="25vh" width="600px" :modal-append-to-body="false" :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</el-col>
</el-row>
<el-col>
<span class="custom-item-text">{{ $t('panel.panel_background_item') }}</span>
</el-col>
<el-col>
<el-radio-group v-model="panel.backgroundType" size="mini" @change="onChangeType()">
<el-radio label="color">{{ $t('chart.color') }}</el-radio>
<el-radio label="image">{{ $t('panel.photo') }}</el-radio>
</el-radio-group>
</el-col>
<el-col v-show="panel.backgroundType==='color'" :span="10">
<el-color-picker
v-model="panel.color"
:predefine="predefineColors"
size="mini"
class="color-picker-custom"
@change="onChangeType"
/>
</el-col>
<el-col v-show="panel.backgroundType==='image'" span="10">
<el-upload
action=""
accept=".jpeg,.jpg,.png,.gif"
class="avatar-uploader"
list-type="picture-card"
:http-request="upload"
:class="{disabled:uploadDisabled}"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:file-list="fileList"
>
<i class="el-icon-plus" />
</el-upload>
<el-dialog top="25vh" width="600px" :modal-append-to-body="false" :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</el-col>
<el-col v-show="panel.backgroundType==='image'">
<span v-show="!this.panel.imageUrl" class="image-hint">{{ $t('panel.panel_background_image_tips') }}</span>
<span v-show="this.panel.imageUrl" class="re-update-span" @click="goFile">{{ $t('panel.reUpload') }}</span>
</el-col>
<input id="input" ref="files" type="file" accept=".jpeg,.jpg,.png,.gif" hidden @click="e => {e.target.value = '';}" @change="reUpload">
</el-form>
</div>
</template>
@ -59,6 +57,7 @@ export default {
name: 'BackgroundSelector',
data() {
return {
maxImageSize: 15000000,
fileList: [],
dialogImageUrl: '',
dialogVisible: false,
@ -82,6 +81,9 @@ export default {
}
},
methods: {
goFile() {
this.$refs.files.click()
},
commitStyle() {
const canvasStyleData = deepCopy(this.canvasStyleData)
canvasStyleData.panel = this.panel
@ -103,11 +105,34 @@ export default {
},
upload(file) {
const _this = this
if (file.size > this.maxImageSize) {
this.sizeMessage()
}
uploadFileResult(file.file, (fileUrl) => {
_this.$store.state.styleChangeTimes++
_this.panel.imageUrl = fileUrl
_this.fileList = [{ url: this.panel.imageUrl }]
_this.commitStyle()
})
},
reUpload(e) {
const file = e.target.files[0]
const _this = this
if (file.size > this.maxImageSize) {
this.sizeMessage()
}
uploadFileResult(file, (fileUrl) => {
_this.$store.state.styleChangeTimes++
_this.panel.imageUrl = fileUrl
_this.fileList = [{ url: this.panel.imageUrl }]
_this.commitStyle()
})
},
sizeMessage() {
this.$notify({
message: '背景图片请不要大于15M',
position: 'top-left'
})
}
}
}
@ -115,18 +140,22 @@ export default {
<style scoped>
.avatar-uploader {
margin-left: 10px;
position: relative;
margin-left: 0px;
margin-top: 8px;
height: 80px;
overflow: hidden;
}
.avatar-uploader ::v-deep .el-upload {
width: 100px;
height: 60px;
line-height: 70px;
width: 80px;
height: 80px;
line-height: 80px;
}
.avatar-uploader ::v-deep .el-upload-list li {
width: 100px !important;
height: 60px !important;
width: 80px !important;
height: 80px !important;
}
.disabled ::v-deep .el-upload--picture-card {
@ -164,12 +193,35 @@ span {
}
.color-picker-custom {
margin-left: 10px;
margin-left: 0px;
cursor: pointer;
margin-top: 8px;
z-index: 1004;
}
.custom-item{
width: 70px;
}
.re-update-span{
cursor: pointer;
color: #3370FF;
size: 14px;
line-height:22px;
font-weight: 400;
}
.image-hint {
color: #8F959E;
size: 14px;
line-height:22px;
font-weight: 400;
}
.custom-item-text {
font-weight: 400 !important;
font-size: 14px !important;
color: var(--TextPrimary, #1F2329) !important;
line-height: 22px;
}
</style>

View File

@ -238,6 +238,25 @@
</div>
</de-container>
<el-dialog
v-if="buttonVisible && panelInfo.id"
:title="(currentWidget && currentWidget.getLeftPanel && currentWidget.getLeftPanel().label ? $t(currentWidget.getLeftPanel().label) : '') + $t('panel.module')"
:visible.sync="buttonVisible"
custom-class="de-button-dialog"
@close="cancelButton"
>
<button-dialog
v-if="buttonVisible && currentWidget"
:ref="'filter-setting-' + currentFilterCom.id"
:widget-info="currentWidget"
:element="currentFilterCom"
@sure-handler="sureHandler"
@cancel-handler="cancelHandler"
/>
</el-dialog>
<el-dialog
v-if="filterVisible && panelInfo.id"
:title="(currentWidget && currentWidget.getLeftPanel && currentWidget.getLeftPanel().label ? $t(currentWidget.getLeftPanel().label) : '') + $t('panel.module')"
@ -357,6 +376,7 @@ import '@/components/canvas/assets/iconfont/iconfont.css'
import '@/components/canvas/styles/animate.css'
import { ApplicationContext } from '@/utils/ApplicationContext'
import FilterDialog from '../filter/filterDialog'
import ButtonDialog from '../filter/ButtonDialog'
import toast from '@/components/canvas/utils/toast'
import { commonAttr } from '@/components/canvas/custom-component/component-list'
import generateID from '@/components/canvas/utils/generateID'
@ -383,6 +403,7 @@ export default {
Editor,
Toolbar,
FilterDialog,
ButtonDialog,
SubjectSetting,
Preview,
AssistComponent,
@ -449,9 +470,11 @@ export default {
],
enableSureButton: false,
filterFromDrag: false,
buttonFromDrag: false,
activeToolsName: 'view',
rightDrawOpen: false,
editType: null
editType: null,
buttonVisible: false
}
},
@ -626,6 +649,7 @@ export default {
beforeDestroy() {
bus.$off('component-on-drag', this.componentOnDrag)
bus.$off('component-dialog-edit', this.editDialog)
bus.$off('button-dialog-edit', this.editButtonDialog)
bus.$off('component-dialog-style', this.componentDialogStyle)
bus.$off('previewFullScreenClose', this.previewFullScreenClose)
bus.$off('change_panel_right_draw', this.changeRightDrawOpen)
@ -645,6 +669,7 @@ export default {
initEvents() {
bus.$on('component-on-drag', this.componentOnDrag)
bus.$on('component-dialog-edit', this.editDialog)
bus.$on('button-dialog-edit', this.editButtonDialog)
bus.$on('component-dialog-style', this.componentDialogStyle)
bus.$on('previewFullScreenClose', this.previewFullScreenClose)
bus.$on('change_panel_right_draw', this.changeRightDrawOpen)
@ -817,6 +842,11 @@ export default {
this.openFilterDialog(true)
return
}
if (this.currentWidget.buttonDialog) {
this.show = false
this.openButtonDialog(true)
return
}
component = deepCopy(this.currentFilterCom)
}
if (this.canvasStyleData.auxiliaryMatrix) {
@ -874,6 +904,24 @@ export default {
if (e.button !== 2) {
this.$store.commit('hideContextMenu')
}
},
openButtonDialog(fromDrag = false) {
this.buttonFromDrag = fromDrag
this.buttonVisible = true
},
closeButton() {
this.buttonVisible = false
this.currentWidget = null
this.clearCurrentInfo()
},
cancelButton() {
this.closeButton()
if (this.buttonFromDrag) {
bus.$emit('onRemoveLastItem')
}
},
sureButton() {
},
openFilterDialog(fromDrag = false) {
this.filterFromDrag = fromDrag
@ -914,6 +962,15 @@ export default {
this.openFilterDialog()
}
},
editButtonDialog(editType) {
this.editType = editType
if (this.curComponent && this.curComponent.serviceName) {
const serviceName = this.curComponent.serviceName
this.currentWidget = ApplicationContext.getService(serviceName)
this.currentFilterCom = this.curComponent
this.openButtonDialog()
}
},
closeLeftPanel() {
this.show = false
},
@ -1093,6 +1150,19 @@ export default {
e.dataTransfer.dropEffect = 'copy'
this.$refs.canvasEditor.handleDragOver(e)
},
sureHandler() {
this.currentFilterCom = this.$refs['filter-setting-' + this.currentFilterCom.id].getElementInfo()
if (this.editType !== 'update') {
adaptCurThemeCommonStyle(this.currentFilterCom)
}
this.$store.commit('setComponentWithId', this.currentFilterCom)
this.$store.commit('recordSnapshot', 'sureFilter')
this.$store.commit('setCurComponent', { component: this.currentFilterCom, index: this.curComponentIndex })
this.closeButton()
},
cancelHandler() {
this.cancelButton()
},
sureStatusChange(status) {
this.enableSureButton = status
},

View File

@ -0,0 +1,100 @@
<template>
<div>
<el-form size="mini" ref="form" :model="form" label-width="100px">
<el-form-item label="名称">
<el-input v-model="currentElement.options.value"></el-input>
</el-form-item>
<el-form-item label="自定义范围">
<el-switch v-model="myAttrs.customRange" @change="customRangeChange"></el-switch>
<el-link style="margin-left: 10px;" type="warning" disabled>默认关联全部过滤组件</el-link>
</el-form-item>
<el-form-item label="关联组件" v-if="myAttrs.customRange">
<el-select style="width: 300px;" multiple clearable v-model="myAttrs.filterIds" placeholder="请选择活动区域">
<el-option v-for="(filter, index) in filters" :key="filter.id" :label="filter.showName" :value="filter.id" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="sure">确定</el-button>
<el-button @click="cancel">取消</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { ApplicationContext } from '@/utils/ApplicationContext'
import { mapState } from 'vuex'
export default {
name: 'ButtonDialog',
props: {
widgetInfo: {
type: Object,
default: null,
},
element: {
type: Object,
default: null
}
},
data() {
return {
form: {
},
currentElement: null,
widget: null,
myAttrs: null
}
},
created() {
this.widget = this.widgetInfo
this.currentElement = JSON.parse(JSON.stringify(this.element))
this.myAttrs = this.currentElement.options.attrs
},
computed: {
...mapState([
'componentData'
]),
filters() {
const datas = this.componentData.filter(item => item.type === 'custom')
datas.forEach(item => {
const serviceName = item.serviceName
const widget = ApplicationContext.getService(serviceName)
const showName = widget.initLeftPanel().label
let result = ''
if(showName) {
result = this.$t(showName)
}
if(item.options.attrs.title) {
result += '【' + item.options.attrs.title + '】'
}
item.showName = result
})
return datas
}
},
methods: {
sure() {
this.$emit('sure-handler')
},
cancel() {
this.$emit('cancel-handler')
},
getElementInfo() {
return this.currentElement
},
customRangeChange(val) {
this.myAttrs.filterIds = []
}
}
}
</script>

View File

@ -59,10 +59,10 @@ export default {
'numberSelectWidget',
'numberSelectGridWidget',
'numberRangeWidget'
],
'按钮': [
'buttonSureWidget'
]
// '': [
// 'buttonSureWidget'
// ]
}
}
},

View File

@ -721,7 +721,11 @@ export default {
name: data.name,
privileges: data.privileges,
sourcePanelName: data.sourcePanelName,
status: data.status
status: data.status,
createBy: data.createBy,
createTime: data.createTime,
updateBy: data.updateBy,
updateTime: data.updateTime
})
bus.$emit('PanelSwitchComponent', { name: 'PanelEdit' })
},

View File

@ -18,9 +18,20 @@
<div style="height: 100%;">
<el-col :span="12" style="text-overflow:ellipsis;overflow: hidden;white-space: nowrap;font-size: 14px">
<span>{{ panelInfo.name || '测试仪表板' }}</span>
&nbsp;
<span v-if="panelInfo.isDefault" style="color: green;font-size: 12px">({{ $t('panel.default_panel_name') }}:{{ panelInfo.defaultPanelName }})</span>
<span v-if="panelInfo.sourcePanelName" style="color: green;font-size: 12px">({{ $t('panel.source_panel_name') }}:{{ panelInfo.sourcePanelName }})</span>
<span v-if="panelInfo.sourcePanelName" style="color: green;font-size: 12px">&nbsp;({{ $t('panel.source_panel_name') }}:{{ panelInfo.sourcePanelName }})</span>
<el-popover
placement="right-start"
width="400"
trigger="click"
>
<panel-detail-info></panel-detail-info>
<i
slot="reference"
class="el-icon-warning icon-class"
style="margin-left: 4px;cursor: pointer;font-size: 14px;"
/>
</el-popover>
</el-col>
<el-col :span="12">
@ -157,10 +168,11 @@ import { initPanelData, updatePanelStatus } from '@/api/panel/panel'
import { proxyInitPanelData } from '@/api/panel/shareProxy'
import { dataURLToBlob } from '@/components/canvas/utils/utils'
import { findResourceAsBase64 } from '@/api/staticResource/staticResource'
import PanelDetailInfo from "@/views/panel/list/common/PanelDetailInfo";
export default {
name: 'PanelViewShow',
components: { Preview, SaveToTemplate, PDFPreExport, ShareHead },
components: {PanelDetailInfo, Preview, SaveToTemplate, PDFPreExport, ShareHead },
props: {
activeTab: {
type: String,

View File

@ -0,0 +1,84 @@
<template>
<el-row>
<el-col class="info-item">
<p class="info-title">{{ $t('panel.create_by') }}</p>
<p class="info-content">{{ panelInfo.createBy }}</p>
</el-col>
<el-col class="info-item">
<p class="info-title">{{ $t('panel.create_time') }}</p>
<p class="info-content">{{ panelInfo.createTime |timestampFormatDate }}</p>
</el-col>
<el-col class="info-item">
<p class="info-title">{{ $t('panel.update_by') }}</p>
<p class="info-content">{{ panelInfo.updateBy || 'N/A' }}</p>
</el-col>
<el-col class="info-item">
<p class="info-title">{{ $t('panel.update_time') }}</p>
<p v-if="panelInfo.updateTime" class="info-content">{{ panelInfo.updateTime | timestampFormatDate }}</p>
<p v-if="!panelInfo.updateTime" class="info-content">N/A</p>
</el-col>
</el-row>
</template>
<script>
export default {
name: 'PanelDetailInfo',
props: {
type: {
type: String,
required: true
},
data: {
type: Object,
required: true
},
tabStatus: {
type: Boolean,
required: true
}
},
data() {
return {
tabActive: 'chart',
detail: {
chart: {},
table: {},
datasource: {}
},
info: {}
}
},
computed: {
panelInfo() {
return this.$store.state.panel.panelInfo
}
},
watch: {
},
mounted() {
},
methods: {
}
}
</script>
<style scoped>
.info-tab>>>.el-tabs__item{
font-weight: 400;
font-size: 12px;
}
.info-item{
margin: 6px 0;
}
.info-title{
margin: 0!important;
font-weight: 600;
font-size: 12px;
}
.info-content{
margin: 0!important;
font-size: 12px;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -502,11 +502,11 @@ export default {
font-weight: 400;
line-height: 22px;
text-align: left;
color: #1f2329;
}
.pwd {
margin: 0 8px;
color: #1f2329;
}
.btn-text {