Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
junjun 2022-07-11 16:43:06 +08:00
commit b1df267c55
14 changed files with 143 additions and 53 deletions

View File

@ -1,10 +1,14 @@
package io.dataease.commons.utils;
import java.io.File;
import io.dataease.commons.model.excel.ExcelSheetModel;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
@ -14,18 +18,25 @@ import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import cn.hutool.core.util.IdUtil;
public class ExcelUtils {
private static final String suffix = ".xls";
public static File exportExcel(List<ExcelSheetModel> sheets) throws Exception {
String fastUUID = IdUtil.fastUUID();
File result = new File("/opt/dataease/data/" + fastUUID + ".xls");
public static File exportExcel(List<ExcelSheetModel> sheets, String fileName) throws Exception {
AtomicReference<String> realFileName = new AtomicReference<>(fileName);
HSSFWorkbook wb = new HSSFWorkbook();
sheets.forEach(sheet -> {
List<List<String>> details = sheet.getDatas();
details.add(0, sheet.getHeads());
HSSFSheet curSheet = wb.createSheet(sheet.getSheetName());
String sheetName = sheet.getSheetName();
HSSFSheet curSheet = wb.createSheet(sheetName);
if (StringUtils.isBlank(fileName)) {
String cName = sheetName + suffix;
realFileName.set(cName);
}
CellStyle cellStyle = wb.createCellStyle();
Font font = wb.createFont();
font.setFontHeightInPoints((short) 12);
@ -52,6 +63,10 @@ public class ExcelUtils {
}
}
});
if (!StringUtils.endsWith(fileName, suffix)) {
realFileName.set(realFileName.get() + suffix);
}
File result = new File("/opt/dataease/data/" + realFileName.get());
wb.write(result);
return result;
}

View File

@ -8,6 +8,7 @@ import io.dataease.commons.constants.ResourceAuthLevel;
import io.dataease.controller.request.chart.*;
import io.dataease.controller.response.ChartDetail;
import io.dataease.dto.chart.ChartViewDTO;
import io.dataease.dto.chart.ViewOption;
import io.dataease.plugins.common.base.domain.ChartViewWithBLOBs;
import io.dataease.service.chart.ChartViewCacheService;
import io.dataease.service.chart.ChartViewService;
@ -178,4 +179,10 @@ public class ChartViewController {
chartViewService.viewPropsSave(chartViewWithBLOBs);
}
@ApiOperation("查询仪表板下视图选项")
@PostMapping("/viewOptions/{panelId}")
public List<ViewOption> viewOptions(@PathVariable("panelId") String panelId) {
return chartViewService.viewOptions(panelId);
}
}

View File

@ -0,0 +1,13 @@
package io.dataease.dto.chart;
import lombok.Data;
import java.io.Serializable;
@Data
public class ViewOption implements Serializable {
private String id;
private String name;
}

View File

@ -2,6 +2,7 @@ package io.dataease.ext;
import io.dataease.controller.request.chart.ChartViewRequest;
import io.dataease.dto.chart.ChartViewDTO;
import io.dataease.dto.chart.ViewOption;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@ -50,4 +51,6 @@ public interface ExtChartViewMapper {
void deleteNoUseView(@Param("viewIds") List<String> viewIds,@Param("panelId") String panelId );
void initPanelChartViewCache(@Param("panelId") String panelId);
List<ViewOption> chartOptions(@Param("panelId") String panelId);
}

View File

@ -588,4 +588,8 @@
</foreach>
</if>
</delete>
<select id="chartOptions" resultType="io.dataease.dto.chart.ViewOption">
select id, title as name from chart_view where scene_id = #{panelId}
</select>
</mapper>

View File

@ -27,6 +27,7 @@ import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Optional;
@Service("emailTaskHandler")
public class EmailTaskHandler extends TaskHandler implements Job {
@ -116,6 +117,13 @@ public class EmailTaskHandler extends TaskHandler implements Job {
emailXpackService.saveInstance(taskInstance);
}
protected void removeInstance(GlobalTaskInstance taskInstance) {
EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class);
Optional.ofNullable(taskInstance).ifPresent(instance ->
Optional.ofNullable(taskInstance.getInstanceId()).ifPresent(instanceId ->
emailXpackService.delInstance(instanceId)));
}
protected void error(GlobalTaskInstance taskInstance, Throwable t) {
taskInstance.setStatus(ERROR);
taskInstance.setInfo(t.getMessage());
@ -125,11 +133,12 @@ public class EmailTaskHandler extends TaskHandler implements Job {
@Async("priorityExecutor")
public void sendReport(GlobalTaskInstance taskInstance, XpackEmailTemplateDTO emailTemplateDTO,
SysUserEntity user) {
SysUserEntity user) {
EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class);
try {
XpackEmailTaskRequest taskForm = emailXpackService.taskForm(taskInstance.getTaskId());
if (ObjectUtils.isEmpty(taskForm) || CronUtils.taskExpire(taskForm.getEndTime())) {
removeInstance(taskInstance);
return;
}
String panelId = emailTemplateDTO.getPanelId();

View File

@ -11,6 +11,7 @@ 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;
@ -31,9 +32,11 @@ public class EmailTaskViewHandler extends EmailTaskHandler {
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();
@ -51,13 +54,21 @@ public class EmailTaskViewHandler extends EmailTaskHandler {
.collect(Collectors.toList());
PermissionProxy proxy = new PermissionProxy();
proxy.setUserId(user.getUserId());
List<File> files = viewExportExcel.export(panelId, viewIdList, proxy);
emailService.sendWithFiles(emailTemplateDTO.getRecipients(), emailTemplateDTO.getTitle(), contentStr,
files);
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();
}
}
}
}
}
}

View File

@ -1548,4 +1548,8 @@ public class ChartViewService {
}
return res;
}
public List<ViewOption> viewOptions(String panelId) {
return extChartViewMapper.chartOptions(panelId);
}
}

View File

@ -46,10 +46,8 @@ public class ViewExportExcel {
List<Map<String, Object>> components = gson.fromJson(componentsJson, tokenType);
ChartExtRequest chartExtRequest = buildViewRequest(componentsFilter(components, "custom", null, null));
List<File> results = new ArrayList<>();
List<ExcelSheetModel> sheets = viewIds.stream().map(viewId -> viewFiles(viewId, chartExtRequest))
.collect(Collectors.toList());
File excelFile = ExcelUtils.exportExcel(sheets);
List<ExcelSheetModel> sheets = viewIds.stream().map(viewId -> viewFiles(viewId, chartExtRequest)).collect(Collectors.toList());
File excelFile = ExcelUtils.exportExcel(sheets, panelDto.getName());
results.add(excelFile);
return results;
}
@ -57,8 +55,8 @@ public class ViewExportExcel {
private List<Map<String, Object>> componentsFilter(List<Map<String, Object>> components, String type,
String componentType, String serviceName) {
return components.stream().filter(component -> {
String ctype = component.get("type").toString();
String cComponentType = component.get("component").toString();
String ctype = Optional.ofNullable(component.get("type")).orElse("").toString();
String cComponentType = Optional.ofNullable(component.get("component")).orElse("").toString();
String cServiceName = Optional.ofNullable(component.get("serviceName")).orElse("").toString();
boolean typeMatch = true;

View File

@ -84,16 +84,18 @@ public class EmailService {
public void sendWithFiles(String to, String title, String content, List<File> files) {
if (StringUtils.isBlank(to))
return;
if (CollectionUtils.isEmpty(files)) {
send(to, title, content);
return;
}
MailInfo mailInfo = proxy().mailInfo();
checkMailInfo(mailInfo);
JavaMailSenderImpl driver = driver(mailInfo);
MimeMessage mimeMessage = driver.createMimeMessage();
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");
MimeMultipart multipart = new MimeMultipart();
text.setText(content, "gb2312");
multipart.addBodyPart(text);
multipart.setSubType("related");
for (int i = 0; i < files.size(); i++) {

View File

@ -1,6 +1,4 @@
import request from '@/utils/request'
import store from '@/store'
import { queryPanelComponents } from '@/api/panel/panel'
export function post(url, data, loading = false) {
return request({
@ -134,3 +132,10 @@ export function viewPropsSave(panelId, data) {
data
})
}
export const viewOptions = panelId => {
return request({
url: '/chart/view/viewOptions/' + panelId,
method: 'post'
})
}

View File

@ -4,7 +4,6 @@
ref="select"
v-model="innerValues"
v-popover:popover
:title="labels"
popper-class="view-select-option"
style="width: 100%;"
multiple
@ -14,10 +13,10 @@
@focus="_popoverShowFun"
>
<el-option
v-for="item in selectedViews"
:key="item.viewId"
:label="item.title"
:value="item.viewId"
v-for="item in selectOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
@ -43,6 +42,7 @@
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',
@ -60,7 +60,6 @@ export default {
},
data() {
return {
labels: [],
visible: false,
placement: 'bottom',
transition: 'el-zoom-in-top',
@ -69,7 +68,8 @@ export default {
innerValues: [],
panelHeight: 450,
showPosition: 'email-task',
viewLoaded: false
viewLoaded: false,
selectOptions: []
}
},
computed: {
@ -92,25 +92,19 @@ export default {
},
panelId(val, old) {
if (val !== old) {
this.innerValues = []
this.loadView()
}
},
selectedViews: {
handler(val) {
if (!val || !JSON.stringify(val)) {
this.labels = []
this.innerValues = []
return
}
const views = JSON.parse(JSON.stringify(val))
const viewIds = []
const names = []
views.forEach(item => {
viewIds.push(item.viewId)
names.push(item.title)
})
const viewIds = JSON.parse(JSON.stringify(val))
this.innerValues = JSON.parse(JSON.stringify(viewIds))
this.labels = JSON.parse(JSON.stringify(names))
},
deep: true
}
@ -122,6 +116,7 @@ export default {
})
},
beforeDestroy() {
this._selectClearFun()
off(document, 'mouseup', this._popoverHideFun)
},
created() {
@ -129,6 +124,8 @@ export default {
},
methods: {
loadView() {
this._selectClearFun()
this.innerValues = this.value
this.viewLoaded = false
this.panelId && findOne(this.panelId).then(response => {
this.panelInfo = {
@ -143,9 +140,17 @@ export default {
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
@ -193,10 +198,13 @@ export default {
})
},
_selectClearFun() {
const views = JSON.parse(JSON.stringify(this.selectedViews))
views.forEach(item => {
this.$store.dispatch('task/delView', { 'panelId': this.panelId, 'viewId': item.viewId })
})
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 })
}
}
}

View File

@ -47,10 +47,6 @@ export default {
panelId: {
type: String,
default: null
},
chartTitle: {
type: String,
default: null
}
},
data() {
@ -85,7 +81,7 @@ export default {
taskChecked() {
const panelId = this.panelId
return !!this.panelViews && !!this.panelViews[panelId] && !!this.panelViews[panelId].some(view => view.viewId === this.viewId)
return !!this.panelViews && !!this.panelViews[panelId] && !!this.panelViews[panelId].some(viewId => viewId === this.viewId)
}
},
watch: {
@ -100,7 +96,6 @@ export default {
}
if (this.showPosition === 'email-task') {
this.isTaskChecked = !!this.taskChecked
// this.emailTaskCheck(this.isTaskChecked)
}
},
beforeDestroy() {
@ -134,7 +129,7 @@ export default {
},
emailTaskCheck(val) {
if (val) {
this.$store.dispatch('task/addView', { 'panelId': this.panelId, 'viewId': this.viewId, 'title': this.chartTitle })
this.$store.dispatch('task/addView', { 'panelId': this.panelId, 'viewId': this.viewId })
} else {
this.$store.dispatch('task/delView', { 'panelId': this.panelId, 'viewId': this.viewId })
}

View File

@ -5,16 +5,16 @@ const state = {
const mutations = {
ADD_VIEW: (state, { panelId, viewId, title }) => {
ADD_VIEW: (state, { panelId, viewId }) => {
if (!state.panelViews[panelId]) {
Vue.set(state.panelViews, panelId, [])
}
const views = state.panelViews[panelId]
if (views.some(item => item.viewId === viewId)) {
const viewIds = state.panelViews[panelId]
if (viewIds.some(item => item === viewId)) {
return
}
views.push({ viewId, title })
state.panelViews[panelId] = views
viewIds.push(viewId)
state.panelViews[panelId] = viewIds
},
DEL_VIEW: (state, { panelId, viewId }) => {
@ -23,20 +23,36 @@ const mutations = {
let len = views.length
while (len--) {
const item = views[len]
if (viewId === item.viewId) {
if (viewId === item) {
views.splice(len, 1)
}
}
state.panelViews[panelId] = views
},
DEL_PANEL_VIEW: (state, panelId) => {
const views = state.panelViews[panelId]
if (!views || !views.length) return
Vue.set(state.panelViews, panelId, [])
},
INIT_PANEL_VIEWS: (state, { panelId, viewIds }) => {
state.panelViews[panelId] = viewIds || []
}
}
const actions = {
initPanelView({ commit }, data) {
commit('INIT_PANEL_VIEWS', data)
},
addView({ commit }, data) {
commit('ADD_VIEW', data)
},
delView({ commit }, data) {
commit('DEL_VIEW', data)
},
delPanelViews({ commit }, data) {
commit('DEL_PANEL_VIEW', data)
}
}