Merge branch 'dev' into pr@dev@fixconn

This commit is contained in:
taojinlong 2024-03-26 18:55:34 +08:00 committed by GitHub
commit 7b5f246c6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
159 changed files with 15533 additions and 284 deletions

View File

@ -37,6 +37,9 @@ public class DeCleanerAnnotationHandler {
switch (type.name()) {
case "DATA_FILL":
catchProcess().cleanDataFiling(paramValue);
break;
case "DATASOURCE":
catchProcess().cleanDataSource(paramValue);
break;

View File

@ -92,8 +92,7 @@ public class JWTFilter extends BasicHttpAuthenticationFilter {
if (isLoginAttempt(request, response) || ApiKeyHandler.isApiKeyCall(hRequest)) {
try {
boolean loginSuccess = executeLogin(request, response);
return loginSuccess;
return executeLogin(request, response);
} catch (Exception e) {
LogUtil.error(e);
if (e instanceof AuthenticationException && StringUtils.equals(e.getMessage(), expireMessage)) {

View File

@ -26,7 +26,6 @@ import io.dataease.plugins.xpack.ldap.dto.response.ValidateResult;
import io.dataease.plugins.xpack.ldap.service.LdapXpackService;
import io.dataease.plugins.xpack.oidc.service.OidcXpackService;
import io.dataease.service.sys.SysUserService;
import io.dataease.service.system.SystemParameterService;
import io.dataease.websocket.entity.WsMessage;
import io.dataease.websocket.service.WsService;
@ -38,15 +37,14 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@RestController
public class AuthServer implements AuthApi {
@ -203,11 +201,12 @@ public class AuthServer implements AuthApi {
result.put("defaultPwd", DEFAULT_PWD);
}
}
Long expireTime = System.currentTimeMillis() + JWTUtils.getExpireTime();
TokenInfo tokenInfo = TokenInfo.builder().userId(user.getUserId()).username(username).build();
String token = JWTUtils.sign(tokenInfo, realPwd);
// 记录token操作时间
result.put("token", token);
result.put("expireTime", expireTime);
ServletUtils.setToken(token);
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.LOGIN, SysLogConstants.SOURCE_TYPE.USER, user.getUserId(), null, null, null);
authUserService.unlockAccount(username, ObjectUtils.isEmpty(loginType) ? 0 : loginType);

View File

@ -15,19 +15,33 @@ public interface ExtAuthService {
AuthURD resourceTarget(String resourceId);
List<AuthItem> dataSourceIdByUser(Long userId);
List<AuthItem> dataSetIdByUser(Long userId);
List<AuthItem> panelIdByUser(Long userId);
List<AuthItem> dataFillingIdByUser(Long userId);
List<AuthItem> dataSourceIdByRole(Long roleId);
List<AuthItem> dataSetIdByRole(Long roleId);
List<AuthItem> panelIdByRole(Long roleId);
List<AuthItem> dataFillingIdByRole(Long roleId);
List<AuthItem> dataSourceIdByDept(Long deptId);
List<AuthItem> dataSetIdByDept(Long deptId);
List<AuthItem> panelIdByDept(Long deptId);
List<AuthItem> dataFillingIdByDept(Long deptId);
void clearUserResource(Long userId);
void clearDeptResource(Long deptId);
void clearRoleResource(Long roleId);
List<String> parentResource(String resourceId, String type);

View File

@ -90,7 +90,7 @@ public class DynamicMenuServiceImpl implements DynamicMenuService {
dynamicMenuDto.setPermission(sysMenu.getPermission());
dynamicMenuDto.setMenuSort(sysMenu.getMenuSort());
dynamicMenuDto.setHidden(sysMenu.getHidden());
dynamicMenuDto.setIsPlugin(true);
dynamicMenuDto.setIsPlugin(!sysMenu.isUseBasicResource());
dynamicMenuDto.setNoLayout(!!sysMenu.isNoLayout());
return dynamicMenuDto;
}

View File

@ -2,12 +2,12 @@ package io.dataease.auth.service.impl;
import io.dataease.auth.entity.AuthItem;
import io.dataease.auth.service.ExtAuthService;
import io.dataease.commons.constants.SysAuthConstants;
import io.dataease.plugins.common.base.domain.SysAuth;
import io.dataease.ext.ExtAuthMapper;
import io.dataease.commons.constants.AuthConstants;
import io.dataease.commons.constants.SysAuthConstants;
import io.dataease.commons.model.AuthURD;
import io.dataease.commons.utils.LogUtil;
import io.dataease.ext.ExtAuthMapper;
import io.dataease.plugins.common.base.domain.SysAuth;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
@ -109,6 +109,16 @@ public class ExtAuthServiceImpl implements ExtAuthService {
);
}
@Cacheable(value = AuthConstants.USER_DATA_FILL_NAME, key = "'user' + #userId")
@Override
public List<AuthItem> dataFillingIdByUser(Long userId) {
return extAuthMapper.queryAuthItems(
SysAuthConstants.AUTH_TARGET_TYPE_USER,
userId.toString(),
SysAuthConstants.AUTH_SOURCE_TYPE_DATA_FILLING
);
}
@Cacheable(value = AuthConstants.ROLE_LINK_NAME, key = "'role' + #roleId")
@Override
@ -140,6 +150,16 @@ public class ExtAuthServiceImpl implements ExtAuthService {
);
}
@Cacheable(value = AuthConstants.ROLE_DATA_FILL_NAME, key = "'role' + #roleId")
@Override
public List<AuthItem> dataFillingIdByRole(Long roleId) {
return extAuthMapper.queryAuthItems(
SysAuthConstants.AUTH_TARGET_TYPE_ROLE,
roleId.toString(),
SysAuthConstants.AUTH_SOURCE_TYPE_DATA_FILLING
);
}
@Cacheable(value = AuthConstants.DEPT_LINK_NAME, key = "'dept' + #deptId")
@Override
public List<AuthItem> dataSourceIdByDept(Long deptId) {
@ -173,10 +193,22 @@ public class ExtAuthServiceImpl implements ExtAuthService {
);
}
@Cacheable(value = AuthConstants.DEPT_DATA_FILL_NAME, key = "'dept' + #deptId")
@Override
public List<AuthItem> dataFillingIdByDept(Long deptId) {
if (ObjectUtils.isEmpty(deptId)) return emptyResult;
return extAuthMapper.queryAuthItems(
SysAuthConstants.AUTH_TARGET_TYPE_DEPT,
deptId.toString(),
SysAuthConstants.AUTH_SOURCE_TYPE_DATA_FILLING
);
}
@Caching(evict = {
@CacheEvict(value = AuthConstants.USER_LINK_NAME, key = "'user' + #userId"),
@CacheEvict(value = AuthConstants.USER_DATASET_NAME, key = "'user' + #userId"),
@CacheEvict(value = AuthConstants.USER_PANEL_NAME, key = "'user' + #userId")
@CacheEvict(value = AuthConstants.USER_PANEL_NAME, key = "'user' + #userId"),
@CacheEvict(value = AuthConstants.USER_DATA_FILL_NAME, key = "'user' + #userId")
})
public void clearUserResource(Long userId) {
LogUtil.info("all permission resource of user {} is cleaning...", userId);
@ -185,7 +217,8 @@ public class ExtAuthServiceImpl implements ExtAuthService {
@Caching(evict = {
@CacheEvict(value = AuthConstants.DEPT_LINK_NAME, key = "'dept' + #deptId"),
@CacheEvict(value = AuthConstants.DEPT_DATASET_NAME, key = "'dept' + #deptId"),
@CacheEvict(value = AuthConstants.DEPT_PANEL_NAME, key = "'dept' + #deptId")
@CacheEvict(value = AuthConstants.DEPT_PANEL_NAME, key = "'dept' + #deptId"),
@CacheEvict(value = AuthConstants.DEPT_DATA_FILL_NAME, key = "'dept' + #deptId")
})
public void clearDeptResource(Long deptId) {
LogUtil.info("all permission resource of dept {} is cleaning...", deptId);
@ -194,7 +227,8 @@ public class ExtAuthServiceImpl implements ExtAuthService {
@Caching(evict = {
@CacheEvict(value = AuthConstants.ROLE_LINK_NAME, key = "'role' + #roleId"),
@CacheEvict(value = AuthConstants.ROLE_DATASET_NAME, key = "'role' + #roleId"),
@CacheEvict(value = AuthConstants.ROLE_PANEL_NAME, key = "'role' + #roleId")
@CacheEvict(value = AuthConstants.ROLE_PANEL_NAME, key = "'role' + #roleId"),
@CacheEvict(value = AuthConstants.ROLE_DATA_FILL_NAME, key = "'role' + #roleId")
})
public void clearRoleResource(Long roleId) {
LogUtil.info("all permission resource of role {} is cleaning...", roleId);

View File

@ -1,8 +1,8 @@
package io.dataease.auth.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.JWTCreator.Builder;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.Verification;
@ -10,7 +10,10 @@ import com.google.gson.Gson;
import io.dataease.auth.entity.TokenInfo;
import io.dataease.auth.entity.TokenInfo.TokenInfoBuilder;
import io.dataease.commons.model.OnlineUserModel;
import io.dataease.commons.utils.*;
import io.dataease.commons.utils.CommonBeanFactory;
import io.dataease.commons.utils.IPUtils;
import io.dataease.commons.utils.ServletUtils;
import io.dataease.commons.utils.TokenCacheUtils;
import io.dataease.plugins.common.exception.DataEaseException;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@ -77,6 +80,13 @@ public class JWTUtils {
return sign(tokenInfo, secret, true);
}
public static Long getExpireTime() {
if (ObjectUtils.isEmpty(expireTime)) {
expireTime = Objects.requireNonNull(CommonBeanFactory.getBean(Environment.class)).getProperty("dataease.login_timeout", Long.class, 480L);
}
return expireTime * 60000L;
}
private static boolean tokenValid(OnlineUserModel model) {
String token = model.getToken();
// 如果已经加入黑名单 则直接返回无效
@ -84,10 +94,7 @@ public class JWTUtils {
if (invalid) return false;
Long loginTime = model.getLoginTime();
if (ObjectUtils.isEmpty(expireTime)) {
expireTime = CommonBeanFactory.getBean(Environment.class).getProperty("dataease.login_timeout", Long.class, 480L);
}
long expireTimeMillis = expireTime * 60000L;
long expireTimeMillis = getExpireTime();
// 如果当前时间减去登录时间小于超时时间则说明token未过期 返回有效状态
return System.currentTimeMillis() - loginTime < expireTimeMillis;
@ -133,10 +140,7 @@ public class JWTUtils {
DataEaseException.throwException("MultiLoginError1");
}
}
if (ObjectUtils.isEmpty(expireTime)) {
expireTime = CommonBeanFactory.getBean(Environment.class).getProperty("dataease.login_timeout", Long.class, 480L);
}
long expireTimeMillis = expireTime * 60000L;
long expireTimeMillis = getExpireTime();
Date date = new Date(System.currentTimeMillis() + expireTimeMillis);
Algorithm algorithm = Algorithm.HMAC256(secret);
Builder builder = JWT.create()

View File

@ -12,14 +12,17 @@ public class AuthConstants {
public final static String USER_LINK_NAME = "user_link";
public final static String USER_DATASET_NAME = "user_dataset";
public final static String USER_PANEL_NAME = "user_panel";
public final static String USER_DATA_FILL_NAME = "user_data_fill";
public final static String ROLE_LINK_NAME = "role_link";
public final static String ROLE_DATASET_NAME = "role_dataset";
public final static String ROLE_PANEL_NAME = "role_panel";
public final static String ROLE_DATA_FILL_NAME = "role_data_fill";
public final static String DEPT_LINK_NAME = "dept_link";
public final static String DEPT_DATASET_NAME = "dept_dataset";
public final static String DEPT_PANEL_NAME = "dept_panel";
public final static String DEPT_DATA_FILL_NAME = "dept_data_fill";

View File

@ -0,0 +1,19 @@
package io.dataease.commons.constants;
public class DataFillConstants {
public final static String DATA_FILL_NODE_TYPE_FOlDER = "folder";
public final static String DATA_FILL_NODE_TYPE_DATA_FILL = "data_fill";
public final static String OPT_TYPE_INSERT = "insert";
public final static String OPT_TYPE_UPDATE = "update";
public final static String DATA_FILL_GATHER_DATA_FILL_LIST = "data_fill_list";
}

View File

@ -1,5 +1,5 @@
package io.dataease.commons.constants;
public enum DePermissionType {
DATASOURCE, DATASET, PANEL
DATASOURCE, DATASET, PANEL, DATA_FILL
}

View File

@ -19,7 +19,12 @@ public enum ResourceAuthLevel {
DATASOURCE_LEVEL_USE(1),
DATASOURCE_LEVEL_MANAGE(3),
DATASOURCE_LEVEL_GRANT(15);
DATASOURCE_LEVEL_GRANT(15),
DATA_FILLING_LEVEL_USE(1),
DATA_FILLING_LEVEL_MANAGE(3),
DATA_FILLING_LEVEL_GRANT(15);
private Integer level;

View File

@ -19,4 +19,6 @@ public class SysAuthConstants {
public final static String AUTH_SOURCE_TYPE_DATASOURCE = "link";
public final static String AUTH_SOURCE_TYPE_DATA_FILLING = "data_fill";
}

View File

@ -70,7 +70,10 @@ public class SysLogConstants {
DRIVER(9, "SOURCE_TYPE_DRIVER"),
DRIVER_FILE(10, "SOURCE_TYPE_DRIVER_FILE"),
MENU(11, "SOURCE_TYPE_MENU"),
APIKEY(12, "SOURCE_TYPE_APIKEY");
APIKEY(12, "SOURCE_TYPE_APIKEY"),
DATA_FILL_FORM(13,"SOURCE_TYPE_DATA_FILL_FORM"),
DATA_FILL_DATA(14,"SOURCE_TYPE_DATA_FILL_DATA");
private Integer value;
private String name;

View File

@ -29,6 +29,7 @@ public class AuthUtils {
private static final String[] defaultPanelPermissions = { "panel_list" };
private static final String[] defaultDataSetPermissions = { "0" };
private static final String[] defaultLinkPermissions = { "0" };
private static final String[] defaultDataFillingPermissions = { "0" };
private static final ThreadLocal<CurrentUserDto> USER_INFO = new ThreadLocal<CurrentUserDto>();
@ -138,6 +139,18 @@ public class AuthUtils {
result.add(new AuthItem(item, ResourceAuthLevel.PANEL_LEVEL_MANAGE.getLevel()));
});
return result;
} else if (StringUtils.equals(DePermissionType.DATA_FILL.name().toLowerCase(), type)) {
Set<AuthItem> userSet = extAuthService.dataFillingIdByUser(userId).stream().collect(Collectors.toSet());
Set<AuthItem> roleSet = roles.stream().map(role -> extAuthService.dataFillingIdByRole(role.getId()))
.flatMap(Collection::stream).collect(Collectors.toSet());
Set<AuthItem> deptSet = extAuthService.dataFillingIdByDept(deptId).stream().collect(Collectors.toSet());
result.addAll(userSet);
result.addAll(roleSet);
result.addAll(deptSet);
Arrays.stream(defaultDataFillingPermissions).forEach(item -> {
result.add(new AuthItem(item, ResourceAuthLevel.DATA_FILLING_LEVEL_MANAGE.getLevel()));
});
return result;
}
return result;

View File

@ -71,6 +71,10 @@ public class IndexController {
if (StringUtils.isNotEmpty(fromLink)) {
url = url + "&fromLink=" + fromLink;
}
String ticket = request.getParameter("ticket");
if (StringUtils.isNotEmpty(ticket)) {
url = url + "&ticket=" + ticket;
}
response.sendRedirect(url);
} catch (IOException e) {
LogUtil.error(e.getMessage());

View File

@ -0,0 +1,177 @@
package io.dataease.controller.datafill;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.dataease.commons.utils.AuthUtils;
import io.dataease.commons.utils.PageUtils;
import io.dataease.commons.utils.Pager;
import io.dataease.controller.ResultHolder;
import io.dataease.controller.request.datafill.*;
import io.dataease.controller.response.datafill.DataFillFormTableDataResponse;
import io.dataease.dto.datafill.DataFillCommitLogDTO;
import io.dataease.dto.datafill.DataFillFormDTO;
import io.dataease.dto.datafill.DataFillTaskDTO;
import io.dataease.dto.datafill.DataFillUserTaskDTO;
import io.dataease.plugins.common.base.domain.DataFillFormWithBLOBs;
import io.dataease.plugins.common.dto.datafill.ExtTableField;
import io.dataease.service.datafill.DataFillDataService;
import io.dataease.service.datafill.DataFillLogService;
import io.dataease.service.datafill.DataFillService;
import io.dataease.service.datafill.DataFillTaskService;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@ApiIgnore
@RequestMapping("dataFilling")
@RestController
public class DataFillController {
@Resource
private DataFillService dataFillService;
@Resource
private DataFillLogService dataFillLogService;
@Resource
private DataFillTaskService dataFillTaskService;
@Resource
private DataFillDataService dataFillDataService;
@ApiIgnore
@PostMapping("/form/save")
public ResultHolder saveForm(@RequestBody DataFillFormWithBLOBs dataFillForm) throws Exception {
return dataFillService.saveForm(dataFillForm);
}
@ApiIgnore
@PostMapping("/form/update")
public ResultHolder updateForm(@RequestBody DataFillFormWithBLOBs dataFillForm) throws Exception {
return dataFillService.updateForm(dataFillForm);
}
@PostMapping("/manage/form/{id}")
public DataFillFormDTO getWithPrivileges(@PathVariable String id) throws Exception {
return dataFillService.getWithPrivileges(id);
}
@PostMapping("/form/get/{id}")
public DataFillFormWithBLOBs get(@PathVariable String id) throws Exception {
return dataFillService.get(id);
}
@ApiIgnore
@PostMapping("/form/delete/{id}")
public void saveForm(@PathVariable String id) throws Exception {
dataFillService.deleteForm(id);
}
@ApiOperation("查询树")
@PostMapping("/form/tree")
public List<DataFillFormDTO> tree(@RequestBody DataFillFormRequest request) {
return dataFillService.tree(request);
}
@ApiIgnore
@PostMapping("/form/{id}/tableData")
public DataFillFormTableDataResponse tableData(@PathVariable String id, @RequestBody DataFillFormTableDataRequest request) throws Exception {
request.setId(id);
return dataFillDataService.listData(request);
}
@ApiIgnore
@PostMapping("/form/fields/{id}")
public List<ExtTableField> listFields(@PathVariable String id) throws Exception {
return dataFillService.listFields(id);
}
@ApiIgnore
@PostMapping("/form/{formId}/delete/{id}")
public void deleteRowData(@PathVariable String formId, @PathVariable String id) throws Exception {
dataFillDataService.deleteRowData(formId, id);
}
@ApiIgnore
@PostMapping("/form/{formId}/rowData/save")
public String newRowData(@PathVariable String formId, @RequestBody Map<String, Object> data) throws Exception {
return dataFillDataService.updateRowData(formId, null, data, true);
}
@ApiIgnore
@PostMapping("/form/{formId}/rowData/save/{id}")
public String updateRowData(@PathVariable String formId, @PathVariable String id, @RequestBody Map<String, Object> data) throws Exception {
return dataFillDataService.updateRowData(formId, id, data, false);
}
@ApiIgnore
@PostMapping("/form/{formId}/commitLog/{goPage}/{pageSize}")
public Pager<List<DataFillCommitLogDTO>> commitLogs(@PathVariable String formId, @PathVariable int goPage, @PathVariable int pageSize, @RequestBody DataFillCommitLogSearchRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
List<DataFillCommitLogDTO> logs = dataFillLogService.commitLogs(formId, request);
return PageUtils.setPageInfo(page, logs);
}
@ApiIgnore
@PostMapping("/form/{formId}/task/{goPage}/{pageSize}")
public Pager<List<DataFillTaskDTO>> tasks(@PathVariable String formId, @PathVariable int goPage, @PathVariable int pageSize, @RequestBody DataFillTaskSearchRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
List<DataFillTaskDTO> tasks = dataFillTaskService.tasks(formId, request);
return PageUtils.setPageInfo(page, tasks);
}
@ApiIgnore
@PostMapping("/form/{formId}/task/save")
public void saveTask(@PathVariable String formId, @RequestBody DataFillTaskSearchRequest request) throws Exception {
dataFillTaskService.saveTask(formId, request);
}
@ApiIgnore
@PostMapping("/form/task/{taskId}/delete")
public void deleteTask(@PathVariable Long taskId) {
dataFillTaskService.deleteTask(taskId);
}
@ApiIgnore
@PostMapping("/form/task/{taskId}/enable")
public void enableTask(@PathVariable Long taskId) throws Exception {
dataFillTaskService.enableTask(taskId);
}
@ApiIgnore
@PostMapping("/form/task/{taskId}/disable")
public void disableTask(@PathVariable Long taskId) throws Exception {
dataFillTaskService.disableTask(taskId);
}
@ApiIgnore
@PostMapping("/myTask/{type}/{goPage}/{pageSize}")
public Pager<List<DataFillUserTaskDTO>> userTasks(@PathVariable String type, @PathVariable int goPage, @PathVariable int pageSize, @RequestBody DataFillUserTaskSearchRequest request) {
Long userId = AuthUtils.getUser().getUserId();
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
List<DataFillUserTaskDTO> tasks = dataFillTaskService.userTasks(userId, type, request);
return PageUtils.setPageInfo(page, tasks);
}
@ApiIgnore
@PostMapping("/myTask/fill/{taskId}")
public void userFillData(@PathVariable String taskId, @RequestBody Map<String, Object> data) throws Exception {
dataFillService.fillFormData(taskId, data);
}
}

View File

@ -2,7 +2,9 @@ package io.dataease.controller.handler;
import io.dataease.controller.ResultHolder;
import io.dataease.i18n.Translator;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
@ -49,7 +51,7 @@ public class GlobalExceptionHandler implements ErrorController {
response.setStatus(code);
String errorMessage = StringUtils.EMPTY;
if (t != null) {
if (Logger.isDebugEnabled()) {
if (Logger.isDebugEnabled() && (ObjectUtils.isEmpty(t.getCause()) || !(t.getCause() instanceof AuthenticationException))) {
Logger.error("Fail to proceed " + errorAttributeMap.get("path"), t);
}
errorMessage = t.getMessage();

View File

@ -84,4 +84,8 @@ public interface LinkApi {
@ApiOperation("删除ticket")
@PostMapping("/delTicket")
void deleteTicket(@RequestBody TicketDelRequest request);
@ApiOperation("切换是否必填ticket")
@PostMapping("/enableTicket")
void switchRequire(@RequestBody TicketSwitchRequest request);
}

View File

@ -9,9 +9,11 @@ import io.dataease.controller.panel.api.LinkApi;
import io.dataease.controller.request.chart.ChartExtRequest;
import io.dataease.controller.request.panel.link.*;
import io.dataease.dto.panel.link.GenerateDto;
import io.dataease.dto.panel.link.TicketDto;
import io.dataease.dto.panel.link.ValidateDto;
import io.dataease.plugins.common.base.domain.PanelGroupWithBLOBs;
import io.dataease.plugins.common.base.domain.PanelLink;
import io.dataease.plugins.common.base.domain.PanelLinkMapping;
import io.dataease.plugins.common.base.domain.PanelLinkTicket;
import io.dataease.service.chart.ChartViewService;
import io.dataease.service.panel.PanelLinkService;
@ -95,7 +97,8 @@ public class LinkServer implements LinkApi {
dto.setValid(false);
return dto;
}
String mappingUuid = panelLinkService.getMappingUuid(one);
PanelLinkMapping mapping = panelLinkService.getMapping(one);
String mappingUuid = mapping.getUuid();
if (!StringUtils.equals(uuid, mappingUuid)) {
dto.setValid(false);
return dto;
@ -104,6 +107,10 @@ public class LinkServer implements LinkApi {
dto.setEnablePwd(one.getEnablePwd());
dto.setPassPwd(panelLinkService.validateHeads(one));
dto.setExpire(panelLinkService.isExpire(one));
String ticketText = request.getTicket();
TicketDto ticketDto = panelLinkService.validateTicket(ticketText, mapping);
dto.setTicket(ticketDto);
return dto;
}
@ -158,4 +165,9 @@ public class LinkServer implements LinkApi {
public void deleteTicket(TicketDelRequest request) {
panelLinkService.deleteTicket(request);
}
@Override
public void switchRequire(TicketSwitchRequest request) {
panelLinkService.switchRequire(request);
}
}

View File

@ -0,0 +1,18 @@
package io.dataease.controller.request.datafill;
import io.dataease.dto.datafill.DataFillCommitLogDTO;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
public class DataFillCommitLogSearchRequest extends DataFillCommitLogDTO {
private static final long serialVersionUID = -1067572649791328116L;
private List<String> formIds;
}

View File

@ -0,0 +1,25 @@
package io.dataease.controller.request.datafill;
import io.dataease.plugins.common.base.domain.DataFillForm;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Set;
@Data
@Accessors(chain=true)
public class DataFillFormRequest extends DataFillForm {
private static final long serialVersionUID = -6752223673862214909L;
@ApiModelProperty("排序")
private String sort;
@ApiModelProperty("用户ID")
private String userId;
@ApiModelProperty("ID集合")
private Set<String> ids;
@ApiModelProperty("排除的ID")
private String excludedId;
}

View File

@ -0,0 +1,19 @@
package io.dataease.controller.request.datafill;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain=true)
public class DataFillFormTableDataRequest extends DataFillFormRequest {
private static final long serialVersionUID = -314618516232771747L;
private long currentPage;
private long pageSize;
private String primaryKeyValue;
}

View File

@ -0,0 +1,14 @@
package io.dataease.controller.request.datafill;
import io.dataease.dto.datafill.DataFillTaskDTO;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class DataFillTaskSearchRequest extends DataFillTaskDTO {
private static final long serialVersionUID = 5881604308639714955L;
}

View File

@ -0,0 +1,14 @@
package io.dataease.controller.request.datafill;
import io.dataease.dto.datafill.DataFillUserTaskDTO;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class DataFillUserTaskSearchRequest extends DataFillUserTaskDTO {
private static final long serialVersionUID = 5881604308639714955L;
}

View File

@ -9,4 +9,5 @@ public class LinkValidateRequest implements Serializable {
private String link;
private String user;
private String ticket;
}

View File

@ -0,0 +1,13 @@
package io.dataease.controller.request.panel.link;
import lombok.Data;
import java.io.Serializable;
@Data
public class TicketSwitchRequest implements Serializable {
private String resourceId;
private Boolean require = false;
}

View File

@ -0,0 +1,28 @@
package io.dataease.controller.response.datafill;
import io.dataease.plugins.common.dto.datafill.ExtTableField;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
@Data
@Accessors(chain = true)
public class DataFillFormTableDataResponse implements Serializable {
private static final long serialVersionUID = -6463885075511811532L;
private Object data;
private List<ExtTableField> fields;
private long total;
private long currentPage;
private long pageSize;
private String key;
}

View File

@ -0,0 +1,18 @@
package io.dataease.dto.datafill;
import io.dataease.plugins.common.base.domain.DataFillCommitLog;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DataFillCommitLogDTO extends DataFillCommitLog {
private static final long serialVersionUID = 5324275156717345584L;
private String commitByName;
}

View File

@ -0,0 +1,26 @@
package io.dataease.dto.datafill;
import io.dataease.plugins.common.base.domain.DataFillFormWithBLOBs;
import io.dataease.plugins.common.model.ITreeBase;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class DataFillFormDTO extends DataFillFormWithBLOBs implements ITreeBase<DataFillFormDTO> {
private static final long serialVersionUID = 1428065978308162738L;
@ApiModelProperty("标签")
private String label;
@ApiModelProperty("子节点")
private List<DataFillFormDTO> children;
@ApiModelProperty("权限")
private String privileges;
private String creatorName;
private String datasourceName;
}

View File

@ -0,0 +1,20 @@
package io.dataease.dto.datafill;
import io.dataease.plugins.common.base.domain.DataFillTaskWithBLOBs;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DataFillTaskDTO extends DataFillTaskWithBLOBs {
private static final long serialVersionUID = 3610753131867651856L;
private String formName;
private String creatorName;
}

View File

@ -0,0 +1,20 @@
package io.dataease.dto.datafill;
import io.dataease.plugins.common.base.domain.DataFillUserTask;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DataFillUserTaskDTO extends DataFillUserTask {
private static final long serialVersionUID = 3610753131867651856L;
private String taskName;
private String formName;
private Long creator;
private String creatorName;
}

View File

@ -0,0 +1,15 @@
package io.dataease.dto.panel.link;
import lombok.Data;
import java.io.Serializable;
@Data
public class TicketDto implements Serializable {
private boolean ticketValid;
private boolean ticketExp;
private String args;
}

View File

@ -19,4 +19,6 @@ public class ValidateDto {
private String resourceId;
@ApiModelProperty("用户ID")
private String userId;
private TicketDto ticket;
}

View File

@ -0,0 +1,30 @@
package io.dataease.ext;
import io.dataease.controller.request.datafill.DataFillFormRequest;
import io.dataease.controller.request.datafill.DataFillTaskSearchRequest;
import io.dataease.dto.datafill.DataFillCommitLogDTO;
import io.dataease.dto.datafill.DataFillFormDTO;
import io.dataease.dto.datafill.DataFillTaskDTO;
import io.dataease.dto.datafill.DataFillUserTaskDTO;
import io.dataease.plugins.common.base.domain.DataFillTask;
import java.util.Date;
import java.util.List;
import java.util.Map;
public interface ExtDataFillFormMapper {
List<DataFillFormDTO> search(DataFillFormRequest request);
Map<String, String> searchChildrenIds(String id, String type);
List<DataFillCommitLogDTO> selectLatestLogByFormDataIds(String formId, List<String> dataIds);
List<DataFillCommitLogDTO> selectDataFillLogs(String formId, String commitByName);
List<DataFillTaskDTO> selectDataFillTasks(DataFillTaskSearchRequest request);
List<DataFillTask> selectActiveDataFillTasks();
List<DataFillUserTaskDTO> listTodoUserTask(long userId, Date current, String taskName);
List<DataFillUserTaskDTO> listFinishedUserTask(long userId, String taskName);
List<DataFillUserTaskDTO> listExpiredUserTask(long userId, Date current, String taskName);
}

View File

@ -0,0 +1,267 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.dataease.ext.ExtDataFillFormMapper">
<resultMap id="BaseResultMapDTO" type="io.dataease.dto.datafill.DataFillFormDTO"
extends="io.dataease.plugins.common.base.mapper.DataFillFormMapper.BaseResultMap">
<result column="label" property="label"/>
<result column="privileges" property="privileges"/>
</resultMap>
<select id="search" resultMap="BaseResultMapDTO">
select
id, `name`, ifnull(pid, 0) as pid, `level`, node_type, `table_name`, datasource, create_index, create_by,
create_time, update_by, update_time,
`name` as label,
authInfo.privileges as `privileges`
from (select GET_V_AUTH_MODEL_ID_P_USE (#{userId}, 'data_fill') cids) t, data_fill_form
left join (
SELECT
auth_source,
group_concat( DISTINCT sys_auth_detail.privilege_extend ) as `privileges`
FROM
(
`sys_auth`
LEFT JOIN `sys_auth_detail` ON ((
`sys_auth`.`id` = `sys_auth_detail`.`auth_id`
)))
WHERE
sys_auth_detail.privilege_value = 1
AND sys_auth.auth_source_type = 'data_fill'
AND (
(
sys_auth.auth_target_type = 'dept'
AND sys_auth.auth_target IN ( SELECT dept_id FROM sys_user WHERE user_id = #{userId} )
)
OR (
sys_auth.auth_target_type = 'user'
AND sys_auth.auth_target = #{userId}
)
OR (
sys_auth.auth_target_type = 'role'
AND sys_auth.auth_target IN ( SELECT role_id FROM sys_users_roles WHERE user_id = #{userId} )
)
)
GROUP BY
`sys_auth`.`auth_source`
) authInfo
on data_fill_form.id = authInfo.auth_source
<where>
FIND_IN_SET(data_fill_form.id, cids)
<if test="id != null">
and data_fill_form.id = #{id,jdbcType=VARCHAR}
</if>
<if test="name != null and name != ''">
and data_fill_form.`name` like CONCAT('%', #{name},'%')
</if>
<if test="pid != null">
and data_fill_form.pid = #{pid,jdbcType=VARCHAR}
</if>
<if test="nodeType != null">
and data_fill_form.node_type = #{nodeType,jdbcType=VARCHAR}
</if>
<if test="level != null">
and data_fill_form.`level` = #{level,jdbcType=INTEGER}
</if>
<if test="createBy != null">
and data_fill_form.create_by = #{createBy,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
and data_fill_form.create_time = #{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateBy != null">
and data_fill_form.update_by = #{updateBy,jdbcType=VARCHAR},
</if>
<if test="updateTime != null">
and data_fill_form.update_time = #{updateTime,jdbcType=TIMESTAMP},
</if>
<if test="excludedId != null">
and data_fill_form.id != #{excludedId,jdbcType=VARCHAR}
</if>
<if test="ids != null and ids.size() > 0">
and id in
<foreach collection="ids" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</if>
</where>
ORDER BY CONVERT(`name` using gbk)
</select>
<select id="searchChildrenIds" resultType="java.util.Map">
select GET_V_AUTH_MODEL_WITH_CHILDREN(#{id}, #{type}) ids
</select>
<resultMap id="BaseResultMapLogDTO" type="io.dataease.dto.datafill.DataFillCommitLogDTO"
extends="io.dataease.plugins.common.base.mapper.DataFillCommitLogMapper.BaseResultMap">
<result column="nick_name" property="commitByName"/>
</resultMap>
<select id="selectDataFillLogs" resultMap="BaseResultMapLogDTO">
SELECT t1.id,
t1.form_id,
t1.data_id,
t1.operate,
t1.commit_by,
t1.commit_time,
t2.nick_name
FROM (SELECT * FROM data_fill_commit_log
WHERE form_id = #{formId} ) t1
LEFT JOIN (SELECT username, nick_name FROM sys_user) t2 ON t1.commit_by = t2.username
<where>
<if test="commitByName != null" >
AND t2.nick_name LIKE CONCAT('%',#{commitByName},'%')
</if>
</where>
ORDER BY t1.commit_time DESC
</select>
<select id="selectLatestLogByFormDataIds" resultMap="BaseResultMapLogDTO">
SELECT t3.id,
t3.form_id,
t3.data_id,
t3.operate,
t3.commit_by,
t3.commit_time,
t4.nick_name
FROM (SELECT t1.id,
t1.form_id,
t1.data_id,
t1.operate,
t1.commit_by,
t1.commit_time
FROM (SELECT * FROM data_fill_commit_log
WHERE form_id = #{formId}
<if test="dataIds != null and dataIds.size() > 0">
AND data_id in
<foreach collection="dataIds" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</if>
) t1
INNER JOIN (SELECT MAX(commit_time) AS commit_time, form_id, data_id
FROM data_fill_commit_log
GROUP BY form_id, data_id) t2
ON t1.form_id = t2.form_id AND t1.commit_time = t2.commit_time AND t1.data_id = t2.data_id) t3
LEFT JOIN (SELECT username, nick_name FROM sys_user) t4 ON t3.commit_by = t4.username
</select>
<resultMap id="BaseResultMapTaskDTO" type="io.dataease.dto.datafill.DataFillTaskDTO"
extends="io.dataease.plugins.common.base.mapper.DataFillTaskMapper.ResultMapWithBLOBs">
<result column="formName" property="formName"/>
<result column="nick_name" property="creatorName"/>
</resultMap>
<select id="selectDataFillTasks" resultMap="BaseResultMapTaskDTO">
SELECT t1.id, t1.`name`, t1.form_id, t1.start_time, t1.end_time, t1.rate_type, t1.rate_val, t1.publish_start_time,
t1.publish_end_time, t1.publish_range_time_type, t1.publish_range_time, t1.creator, t1.create_time,
t1.`status`,
t1.reci_users, t1.role_list, t1.org_list,
t2.nick_name, t3.`name` AS formName
FROM (SELECT * FROM data_fill_task
WHERE form_id = #{formId}
<if test="id != null">
and `id` = #{id,jdbcType=VARCHAR}
</if>
<if test="name != null" >
AND `name` LIKE CONCAT('%',#{name},'%')
</if>
) t1
LEFT JOIN (SELECT user_id, nick_name FROM sys_user) t2 ON t1.creator = t2.user_id
LEFT JOIN (SELECT name, id FROM data_fill_form) t3 ON t1.form_id = t3.id
WHERE 1 = 1
ORDER BY t1.create_time DESC
</select>
<select id="selectActiveDataFillTasks" resultMap="io.dataease.plugins.common.base.mapper.DataFillTaskMapper.BaseResultMap">
SELECT
<include refid="io.dataease.plugins.common.base.mapper.DataFillTaskMapper.Base_Column_List" />
FROM data_fill_task
WHERE status = 1
AND ((rate_type = -1 AND publish_start_time &lt;= current_timestamp AND (publish_end_time is null OR
publish_end_time &gt;= current_timestamp))
OR
(rate_type != -1 AND start_time &lt;= current_timestamp AND (end_time is null OR end_time &gt;=
current_timestamp))
)
</select>
<resultMap id="BaseResultMapUserTaskDTO" type="io.dataease.dto.datafill.DataFillUserTaskDTO"
extends="io.dataease.plugins.common.base.mapper.DataFillUserTaskMapper.BaseResultMap">
<result column="taskName" property="taskName"/>
<result column="formName" property="formName"/>
<result column="creator" property="creator"/>
<result column="creatorName" property="creatorName"/>
</resultMap>
<select id="listTodoUserTask" resultMap="BaseResultMapUserTaskDTO">
SELECT
t1.id, t1.task_id, t1.form_id, t1.value_id, t1.`user`, t1.start_time, t1.end_time, t1.finish_time,
t2.`name` AS formName, t3.`name` AS taskName, t3.`creator`, t4.`nick_name` AS creatorName
FROM
(SELECT
<include refid="io.dataease.plugins.common.base.mapper.DataFillUserTaskMapper.Base_Column_List" />
FROM data_fill_user_task
WHERE user = #{userId}
AND finish_time IS NULL
AND start_time &lt;= #{current} AND (end_time IS NULL OR end_time &gt;= #{current})) t1
LEFT JOIN (SELECT id, `name` FROM data_fill_form) t2 ON t1.form_id = t2.id
LEFT JOIN (SELECT id, `name`, `creator` FROM data_fill_task) t3 ON t1.task_id = t3.id
LEFT JOIN (SELECT user_id, nick_name FROM sys_user) t4 ON t3.creator = t4.user_id
<where>
<if test="taskName != null" >
AND t3.`name` LIKE CONCAT('%',#{taskName},'%')
</if>
</where>
ORDER BY t1.end_time DESC, t1.start_time
</select>
<select id="listFinishedUserTask" resultMap="BaseResultMapUserTaskDTO">
SELECT
t1.id, t1.task_id, t1.form_id, t1.value_id, t1.`user`, t1.start_time, t1.end_time, t1.finish_time,
t2.`name` AS formName, t3.`name` AS taskName, t3.`creator`, t4.`nick_name` AS creatorName
FROM
(SELECT
<include refid="io.dataease.plugins.common.base.mapper.DataFillUserTaskMapper.Base_Column_List" />
FROM data_fill_user_task
WHERE user = #{userId}
AND finish_time IS NOT NULL) t1
LEFT JOIN (SELECT id, `name` FROM data_fill_form) t2 ON t1.form_id = t2.id
LEFT JOIN (SELECT id, `name`, `creator` FROM data_fill_task) t3 ON t1.task_id = t3.id
LEFT JOIN (SELECT user_id, nick_name FROM sys_user) t4 ON t3.creator = t4.user_id
<where>
<if test="taskName != null" >
AND t3.`name` LIKE CONCAT('%',#{taskName},'%')
</if>
</where>
ORDER BY t1.finish_time DESC, t1.end_time DESC, t1.start_time
</select>
<select id="listExpiredUserTask" resultMap="BaseResultMapUserTaskDTO">
SELECT
t1.id, t1.task_id, t1.form_id, t1.value_id, t1.`user`, t1.start_time, t1.end_time, t1.finish_time,
t2.`name` AS formName, t3.`name` AS taskName, t3.`creator`, t4.`nick_name` AS creatorName
FROM
(SELECT
<include refid="io.dataease.plugins.common.base.mapper.DataFillUserTaskMapper.Base_Column_List" />
FROM data_fill_user_task
WHERE user = #{userId}
AND end_time &lt;= #{current}) t1
LEFT JOIN (SELECT id, `name` FROM data_fill_form) t2 ON t1.form_id = t2.id
LEFT JOIN (SELECT id, `name`, `creator` FROM data_fill_task) t3 ON t1.task_id = t3.id
LEFT JOIN (SELECT user_id, nick_name FROM sys_user) t4 ON t3.creator = t4.user_id
<where>
<if test="taskName != null" >
AND t3.`name` LIKE CONCAT('%',#{taskName},'%')
</if>
</where>
ORDER BY t1.end_time DESC, t1.start_time
</select>
</mapper>

View File

@ -206,6 +206,21 @@
</where>
</if>
<if test="type == 13">
id, name
from data_fill_form
<where>
id in
<foreach collection="ids" item="id" index="index" open="(" separator="," close=")">
#{id}
</foreach>
ORDER BY FIELD(id,
<foreach collection="ids" item="id" index="index" open="" separator="," close=")">
#{id}
</foreach>
</where>
</if>
</select>

View File

@ -4,10 +4,11 @@ import io.dataease.commons.utils.CronUtils;
import io.dataease.job.sechedule.ScheduleManager;
import io.dataease.plugins.common.entity.GlobalTaskEntity;
import org.apache.commons.lang3.ObjectUtils;
import org.quartz.*;
import org.quartz.JobDataMap;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.InitializingBean;
import java.util.Date;
public abstract class TaskHandler implements InitializingBean {

View File

@ -0,0 +1,184 @@
package io.dataease.job.sechedule.strategy.impl;
import io.dataease.auth.service.AuthUserService;
import io.dataease.commons.utils.CommonBeanFactory;
import io.dataease.commons.utils.CronUtils;
import io.dataease.service.datafill.DataFillTaskService;
import io.dataease.job.sechedule.ScheduleManager;
import io.dataease.job.sechedule.strategy.TaskHandler;
import io.dataease.plugins.common.base.domain.DataFillTaskWithBLOBs;
import io.dataease.plugins.common.entity.GlobalTaskEntity;
import io.dataease.plugins.common.util.SpringContextUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.quartz.*;
import org.springframework.stereotype.Service;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
@Service("dataFillTaskHandler")
public class DataFillTaskHandler extends TaskHandler implements Job {
@Override
protected JobDataMap jobDataMap(GlobalTaskEntity taskEntity) {
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("taskEntity", taskEntity);
return jobDataMap;
}
@Override
public void resetRunningInstance(Long taskId) {
}
@Override
protected Boolean taskIsRunning(Long taskId) {
return null;
}
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
// 插件没有加载 空转
if (!CommonBeanFactory.getBean(AuthUserService.class).pluginLoaded())
return;
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
GlobalTaskEntity taskEntity = (GlobalTaskEntity) jobDataMap.get("taskEntity");
ScheduleManager scheduleManager = SpringContextUtil.getBean(ScheduleManager.class);
DataFillTaskService dataFillTaskService = SpringContextUtil.getBean(DataFillTaskService.class);
DataFillTaskWithBLOBs task = dataFillTaskService.getTaskById(taskEntity.getTaskId());
try {
dataFillTaskService.createUserTasks(task, null);
if (task.getRateType() == -1) {
//一次性任务执行完之后需要修改为停止
dataFillTaskService.finishTask(task.getId());
removeTask(scheduleManager, taskEntity);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void addTask(ScheduleManager scheduleManager, GlobalTaskEntity taskEntity) throws Exception {
DataFillTaskService dataFillTaskService = SpringContextUtil.getBean(DataFillTaskService.class);
// 1首先看看是否过期
Long endTime = taskEntity.getEndTime();
removeTask(scheduleManager, taskEntity);
if (CronUtils.taskExpire(endTime)) { // 过期了就删除任务
dataFillTaskService.finishTask(taskEntity.getTaskId()); //状态置为已停止
return;
}
if (!taskEntity.getStatus()) return;
JobKey jobKey = new JobKey("DATA_FILL_TASK_" + taskEntity.getTaskId().toString());
TriggerKey triggerKey = new TriggerKey("DATA_FILL_TASK_" + taskEntity.getTaskId());
Date start = new Date(taskEntity.getStartTime());
Date end = null;
if (ObjectUtils.isNotEmpty(taskEntity.getEndTime())) {
end = new Date(taskEntity.getEndTime());
}
Class<? extends TaskHandler> executor = this.getClass();
String cron = cron(taskEntity);
if (taskEntity.getRateType() == -1) {
long currentTriggerTime = System.currentTimeMillis() + 30 * 1000; //一次性的任务确保下发成功增加一点延时
if (taskEntity.getStartTime() >= currentTriggerTime) {
currentTriggerTime = taskEntity.getStartTime();
start = new Date(taskEntity.getStartTime() - 30 * 1000);
}
cron = cron(new Date(currentTriggerTime));
}
scheduleManager.addOrUpdateCronJob(jobKey, triggerKey, executor, cron, start, end, jobDataMap(taskEntity));
}
private static String cron(Date date) {
Calendar instance = Calendar.getInstance();
instance.setTime(date);
return instance.get(Calendar.SECOND) + " " +
instance.get(Calendar.MINUTE) + " " +
instance.get(Calendar.HOUR_OF_DAY) + " " +
instance.get(Calendar.DAY_OF_MONTH) + " " +
(instance.get(Calendar.MONTH) + 1) + " ? " +
instance.get(Calendar.YEAR);
}
private static String cron(GlobalTaskEntity taskEntity) {
if (taskEntity.getRateType() == -1) {
return taskEntity.getRateVal();
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;
try {
date = sdf.parse(taskEntity.getRateVal());
} catch (ParseException e) {
e.printStackTrace();
}
java.util.Calendar instance = java.util.Calendar.getInstance();
instance.setTime(date);
if (taskEntity.getRateType() == 0) {
return instance.get(java.util.Calendar.SECOND) + " " +
instance.get(java.util.Calendar.MINUTE) + " " +
instance.get(java.util.Calendar.HOUR_OF_DAY) + " * * ?";
}
if (taskEntity.getRateType() == 1) {
return instance.get(java.util.Calendar.SECOND) + " " +
instance.get(java.util.Calendar.MINUTE) + " " +
instance.get(java.util.Calendar.HOUR_OF_DAY) + " ? * " +
getWeekDayStr(instance.get(Calendar.DATE)); //这里是拿日当作周来保存的
}
if (taskEntity.getRateType() == 2) {
return instance.get(java.util.Calendar.SECOND) + " " +
instance.get(java.util.Calendar.MINUTE) + " " +
instance.get(java.util.Calendar.HOUR_OF_DAY) + " " +
instance.get(Calendar.DATE) + " * ?";
}
return null;
}
private static String getWeekDayStr(int day) {
switch (day) {
case 1:
return "MON";
case 2:
return "TUE";
case 3:
return "WED";
case 4:
return "THU";
case 5:
return "FRI";
case 6:
return "SAT";
case 7:
return "SUN";
}
return "*";
}
@Override
public void removeTask(ScheduleManager scheduleManager, GlobalTaskEntity taskEntity) {
JobKey jobKey = new JobKey("DATA_FILL_TASK_" + taskEntity.getTaskId().toString());
TriggerKey triggerKey = new TriggerKey("DATA_FILL_TASK_" + taskEntity.getTaskId());
scheduleManager.removeJob(jobKey, triggerKey);
}
@Override
public void executeTask(ScheduleManager scheduleManager, GlobalTaskEntity taskEntity) throws Exception {
JobKey jobKey = new JobKey("DATA_FILL_TASK_" + taskEntity.getTaskId().toString());
scheduleManager.fireNow(jobKey);
}
}

View File

@ -0,0 +1,43 @@
package io.dataease.listener;
import io.dataease.auth.service.AuthUserService;
import io.dataease.service.datafill.DataFillTaskService;
import io.dataease.job.sechedule.ScheduleManager;
import io.dataease.job.sechedule.strategy.TaskHandler;
import io.dataease.job.sechedule.strategy.TaskStrategyFactory;
import io.dataease.plugins.common.entity.GlobalTaskEntity;
import io.dataease.plugins.common.util.SpringContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class DataFillTaskStartListener implements ApplicationListener<ApplicationReadyEvent> {
@Autowired
private AuthUserService authUserService;
@Autowired
private ScheduleManager scheduleManager;
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
if (authUserService.pluginLoaded()) {
DataFillTaskService service = SpringContextUtil.getBean(DataFillTaskService.class);
List<GlobalTaskEntity> tasks = service.listActiveTasksGlobalTaskEntity();
tasks.stream().forEach(task -> {
TaskHandler taskHandler = TaskStrategyFactory.getInvokeStrategy(task.getTaskType());
try {
taskHandler.resetRunningInstance(task.getTaskId());
taskHandler.addTask(scheduleManager, task);
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
}

View File

@ -1,17 +1,27 @@
package io.dataease.plugins.server;
import io.dataease.commons.utils.LogUtil;
import io.dataease.plugins.common.exception.DataEaseException;
import io.dataease.plugins.common.util.SpringContextUtil;
import io.dataease.plugins.xpack.display.dto.response.SysSettingDto;
import io.dataease.plugins.xpack.oidc.service.OidcXpackService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ApiIgnore
@RequestMapping("/plugin/oidc")
@RestController
@ -31,19 +41,19 @@ public class XOidcServer {
oidcXpackService.save(settings);
}
@PostMapping(value="/authInfo")
@PostMapping(value = "/authInfo")
public Map<String, Object> authInfo() {
OidcXpackService oidcXpackService = SpringContextUtil.getBean(OidcXpackService.class);
Map<String, Object> result = new HashMap<String, Object>();
List<SysSettingDto> oidcSettings = oidcXpackService.oidcSettings();
Map<String, String> authParam = new HashMap<>();
authParam.put("response_type", "code");
authParam.put("state", "state");
oidcSettings.forEach(param -> {
if(StringUtils.isNotBlank(param.getParamKey())) {
if (StringUtils.isNotBlank(param.getParamKey())) {
if (StringUtils.equals(param.getParamKey(), "oidc.authEndpoint")) {
result.put("authEndpoint", param.getParamValue());
}
@ -53,10 +63,46 @@ public class XOidcServer {
if (StringUtils.equals(param.getParamKey(), "oidc.clientId")) {
authParam.put("client_id", param.getParamValue());
}
if (StringUtils.equals(param.getParamKey(), "oidc.pkce") && StringUtils.isNotBlank(param.getParamValue())) {
String pkceMethod = param.getParamValue();
authParam.put("code_challenge_method", pkceMethod);
if (StringUtils.equalsIgnoreCase("S256", pkceMethod)) {
String verifier = generateVerifier();
authParam.put("code_challenge", s256Challenge(verifier));
authParam.put("state", verifier);
} else if (StringUtils.equalsIgnoreCase("plain", pkceMethod)) {
String verifier = generateVerifier();
authParam.put("code_challenge", verifier);
authParam.put("state", verifier);
} else {
authParam.remove("code_challenge_method");
}
}
}
});
result.put("authParam", authParam);
return result;
}
private String generateVerifier() {
SecureRandom sr = new SecureRandom();
byte[] code = new byte[32];
sr.nextBytes(code);
return Base64.getUrlEncoder().withoutPadding().encodeToString(code);
}
private String s256Challenge(String verifier) {
try {
byte[] bytes = verifier.getBytes(StandardCharsets.US_ASCII);
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(bytes, 0, bytes.length);
byte[] digest = md.digest();
return org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString(digest);
} catch (Exception e) {
LogUtil.error(e.getMessage());
DataEaseException.throwException(e.getMessage());
}
return null;
}
}

View File

@ -22,6 +22,7 @@ import io.dataease.plugins.datasource.provider.DefaultJdbcProvider;
import io.dataease.plugins.datasource.provider.ExtendedJdbcClassLoader;
import io.dataease.plugins.datasource.provider.ProviderFactory;
import io.dataease.plugins.datasource.query.QueryProvider;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
@ -76,6 +77,27 @@ public class JdbcProvider extends DefaultJdbcProvider {
}
}
public int execWithPreparedStatement(DatasourceRequest datasourceRequest) throws Exception {
JdbcConfiguration jdbcConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), JdbcConfiguration.class);
int queryTimeout = jdbcConfiguration.getQueryTimeout() > 0 ? jdbcConfiguration.getQueryTimeout() : 0;
try (Connection connection = getConnectionFromPool(datasourceRequest); PreparedStatement stat = getPreparedStatement(connection, queryTimeout, datasourceRequest.getQuery())) {
if (CollectionUtils.isNotEmpty(datasourceRequest.getTableFieldWithValues())) {
for (int i = 0; i < datasourceRequest.getTableFieldWithValues().size(); i++) {
stat.setObject(i + 1, datasourceRequest.getTableFieldWithValues().get(i).getValue(), datasourceRequest.getTableFieldWithValues().get(i).getType());
}
}
return stat.executeUpdate();
} catch (SQLException e) {
DataEaseException.throwException(e);
} catch (Exception e) {
DataEaseException.throwException(e);
}
return 0;
}
@Override
public List<TableField> getTableFields(DatasourceRequest datasourceRequest) throws Exception {
@ -110,6 +132,10 @@ public class JdbcProvider extends DefaultJdbcProvider {
Set<String> primaryKeySet = new HashSet<>();
while (primaryKeys.next()) {
String tableName = primaryKeys.getString("TABLE_NAME");
if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.mysql.name()) || datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.mariadb.name())) {
//这里因为旧版mysql驱动问题需要特殊处理
tableName = tableName.replaceAll("`", "");
}
String database;
String schema = primaryKeys.getString("TABLE_SCHEM");
if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.pg.name()) || datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.ck.name())
@ -201,6 +227,7 @@ public class JdbcProvider extends DefaultJdbcProvider {
}
tableField.setRemarks(remarks);
String dbType = resultSet.getString("TYPE_NAME").toUpperCase();
tableField.setType(resultSet.getInt("DATA_TYPE"));
tableField.setFieldType(dbType);
if (dbType.equalsIgnoreCase("LONG")) {
tableField.setFieldSize(65533);
@ -398,7 +425,16 @@ public class JdbcProvider extends DefaultJdbcProvider {
List<String[]> list = new LinkedList<>();
JdbcConfiguration jdbcConfiguration = new Gson().fromJson(dsr.getDatasource().getConfiguration(), JdbcConfiguration.class);
int queryTimeout = jdbcConfiguration.getQueryTimeout() > 0 ? jdbcConfiguration.getQueryTimeout() : 0;
try (Connection connection = getConnectionFromPool(dsr); Statement stat = getStatement(connection, queryTimeout); ResultSet rs = stat.executeQuery(dsr.getQuery())) {
try (Connection connection = getConnectionFromPool(dsr); PreparedStatement stat = getPreparedStatement(connection, queryTimeout, dsr.getQuery())) {
if (CollectionUtils.isNotEmpty(dsr.getTableFieldWithValues())) {
for (int i = 0; i < dsr.getTableFieldWithValues().size(); i++) {
stat.setObject(i + 1, dsr.getTableFieldWithValues().get(i).getValue(), dsr.getTableFieldWithValues().get(i).getType());
}
}
ResultSet rs = stat.executeQuery();
list = getDataResult(rs, dsr);
if (dsr.isPageable() && (dsr.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.sqlServer.name()) || dsr.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.db2.name()))) {
Integer realSize = dsr.getPage() * dsr.getPageSize() < list.size() ? dsr.getPage() * dsr.getPageSize() : list.size();
@ -584,13 +620,13 @@ public class JdbcProvider extends DefaultJdbcProvider {
jdbcClassLoader = extendedJdbcClassLoader;
DeDriver driver = deDriverMapper.selectByPrimaryKey("default-" + datasourceRequest.getDatasource().getType());
if(driver == null){
if (driver == null) {
for (DataSourceType value : SpringContextUtil.getApplicationContext().getBeansOfType(DataSourceType.class).values()) {
if (value.getType().equalsIgnoreCase(datasourceRequest.getDatasource().getType())) {
surpportVersions = value.getSurpportVersions();
}
}
}else {
} else {
surpportVersions = driver.getSurpportVersions();
}
} else {

View File

@ -1437,7 +1437,7 @@ public class DorisQueryProvider extends QueryProvider {
}
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
String keyword = value.get(0).toUpperCase();
whereValue = "'%" + keyword + "%'";
whereValue = formatLikeValue(keyword);
whereName = "upper(" + whereName + ")";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == 1) {

View File

@ -1379,7 +1379,7 @@ public class MysqlQueryProvider extends QueryProvider {
}
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
String keyword = value.get(0).toUpperCase();
whereValue = "'%" + keyword + "%'";
whereValue = formatLikeValue(keyword);
whereName = "upper(" + whereName + ")";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == 1) {

View File

@ -0,0 +1,344 @@
package io.dataease.provider.ext;
import io.dataease.commons.utils.BeanUtils;
import io.dataease.plugins.common.dto.datafill.ExtIndexField;
import io.dataease.plugins.common.dto.datafill.ExtTableField;
import io.dataease.plugins.common.dto.datasource.TableField;
import io.dataease.plugins.common.request.datasource.DatasourceRequest;
import io.dataease.plugins.datasource.provider.DefaultExtDDLProvider;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service("extMysqlDDLProvider")
public class MysqlExtDDLProvider extends DefaultExtDDLProvider {
private static final String creatTableSql =
"CREATE TABLE `TABLE_NAME`" +
"Column_Fields" + " ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;";
private static final String creatTableIndexSql =
"create index `INDEX_NAME` on `TABLE_NAME` (Column_Fields);";
private static final String dropTableSql = "DROP TABLE IF EXISTS `TABLE_NAME`";
@Override
public String dropTableSql(String table) {
return dropTableSql.replace("TABLE_NAME", table);
}
@Override
public String createTableSql(String table, List<ExtTableField> formFields) {
//check inject
if (checkSqlInjection(table)) {
throw new RuntimeException("包含SQL注入的参数请检查参数");
}
List<ExtTableField.TableField> fields = convertTableFields(true, formFields);
String fieldSql = convertTableFieldsString(table, fields);
return creatTableSql.replace("TABLE_NAME", table).replace("Column_Fields", fieldSql);
}
@Override
public String searchSql(String table, List<TableField> formFields, String whereSql, long limit, long offset) {
String baseSql = "SELECT $Column_Fields$ FROM `$TABLE_NAME$` $WHERE_SQL$ LIMIT $OFFSET_COUNT$, $LIMIT_COUNT$ ;";
baseSql = baseSql.replace("$TABLE_NAME$", table)
.replace("$OFFSET_COUNT$", Long.toString(offset))
.replace("$LIMIT_COUNT$", Long.toString(limit));
if (StringUtils.isBlank(whereSql)) {
baseSql = baseSql.replace("$WHERE_SQL$", "");
} else {
baseSql = baseSql.replace("$WHERE_SQL$", whereSql);
}
baseSql = baseSql.replace("$Column_Fields$", convertSearchFields(formFields));
return baseSql;
}
@Override
public String whereSql(String tableName, List<TableField> searchFields) {
StringBuilder builder = new StringBuilder("WHERE 1 = 1 ");
for (TableField searchField : searchFields) {
//目前只考虑等于
builder.append("AND $Column_Field$ = ? ".replace("$Column_Field$", searchField.getFieldName()));
}
return builder.toString();
}
@Override
public String countSql(String table, List<TableField> formFields, String whereSql) {
String baseSql = "SELECT COUNT(1) FROM `$TABLE_NAME$` $WHERE_SQL$ ;";
baseSql = baseSql.replace("$TABLE_NAME$", table);
if (StringUtils.isBlank(whereSql)) {
baseSql = baseSql.replace("$WHERE_SQL$", "");
} else {
baseSql = baseSql.replace("$WHERE_SQL$", whereSql);
}
return baseSql;
}
private String convertSearchFields(List<TableField> formFields) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < formFields.size(); i++) {
TableField f = formFields.get(i);
if (StringUtils.equalsAnyIgnoreCase(f.getFieldType(), "datetime")) {
//特殊处理全部使用统一格式输出
builder.append("DATE_FORMAT(`").append(f.getFieldName()).append("`,'%Y-%m-%d %H:%i:%S')");
} else {
builder.append("`").append(f.getFieldName()).append("`");
}
if (i < formFields.size() - 1) {
builder.append(", ");
}
}
return builder.toString();
}
private List<ExtTableField.TableField> convertTableFields(boolean create, List<ExtTableField> formFields) {
List<ExtTableField.TableField> list = new ArrayList<>();
if (create) {
list.add(
ExtTableField.TableField.builder()
.columnName("id")
.comment("ID")
.primaryKey(true)
.type(ExtTableField.BaseType.nvarchar)
.size(128)
.build()
);
}
for (ExtTableField formField : formFields) {
ExtTableField.TableField.TableFieldBuilder fieldBuilder = ExtTableField.TableField.builder()
.columnName(formField.getSettings().getMapping().getColumnName())
.type(formField.getSettings().getMapping().getType())
.comment(formField.getSettings().getName())
.required(formField.getSettings().isRequired());
if (StringUtils.equalsIgnoreCase(formField.getType(), "dateRange")) {
ExtTableField.TableField f1 = fieldBuilder
.columnName(formField.getSettings().getMapping().getColumnName1())
.comment(formField.getSettings().getName() + " start")
.build();
list.add(f1);
ExtTableField.TableField f2 = BeanUtils.copyBean(new ExtTableField.TableField(), f1);
f2.setColumnName(formField.getSettings().getMapping().getColumnName2());
f2.setComment(formField.getSettings().getName() + " end");
list.add(f2);
} else {
list.add(fieldBuilder.build());
}
}
return list;
}
@Override
public String deleteDataByIdSql(String table, DatasourceRequest.TableFieldWithValue pk) {
String deleteSql = "DELETE FROM `$TABLE_NAME$` WHERE `$PRIMARY_KEY$` = ?;";
return deleteSql.replace("$TABLE_NAME$", table)
.replace("$PRIMARY_KEY$", pk.getFiledName());
}
private String convertFields(List<DatasourceRequest.TableFieldWithValue> fields) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < fields.size(); i++) {
DatasourceRequest.TableFieldWithValue f = fields.get(i);
builder.append("`").append(f.getFiledName()).append("`");
if (i < fields.size() - 1) {
builder.append(", ");
}
}
return builder.toString();
}
private String convertValueFields(List<DatasourceRequest.TableFieldWithValue> fields) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < fields.size(); i++) {
DatasourceRequest.TableFieldWithValue f = fields.get(i);
builder.append("?");
if (i < fields.size() - 1) {
builder.append(", ");
}
}
return builder.toString();
}
@Override
public String insertDataSql(String tableName, List<DatasourceRequest.TableFieldWithValue> fields) {
String sql = "INSERT INTO `$TABLE_NAME$`($Column_Fields$) VALUES ($Value_Fields$);";
return sql.replace("$TABLE_NAME$", tableName)
.replace("$Column_Fields$", convertFields(fields))
.replace("$Value_Fields$", convertValueFields(fields));
}
private String convertUpdateFields(List<DatasourceRequest.TableFieldWithValue> fields) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < fields.size(); i++) {
DatasourceRequest.TableFieldWithValue f = fields.get(i);
builder.append("`").append(f.getFiledName()).append("` = ?");
if (i < fields.size() - 1) {
builder.append(", ");
}
}
return builder.toString();
}
@Override
public String updateDataByIdSql(String tableName, List<DatasourceRequest.TableFieldWithValue> fields, DatasourceRequest.TableFieldWithValue pk) {
String sql = "UPDATE `$TABLE_NAME$` SET $Column_Fields$ WHERE `$PRIMARY_KEY$` = ?;";
return sql.replace("$TABLE_NAME$", tableName)
.replace("$Column_Fields$", convertUpdateFields(fields))
.replace("$PRIMARY_KEY$", pk.getFiledName());
}
@Override
public String checkUniqueValueSql(String tableName, DatasourceRequest.TableFieldWithValue field, DatasourceRequest.TableFieldWithValue pk) {
String sql = "SELECT COUNT(1) FROM `$TABLE_NAME$` WHERE `$Column_Field$` = ? $PRIMARY_KEY_CONDITION$;";
StringBuilder pkCondition = new StringBuilder();
if (pk != null) {
pkCondition.append("AND `").append(pk.getFiledName()).append("` != ?");
}
return sql.replace("$TABLE_NAME$", tableName)
.replace("$Column_Field$", field.getFiledName())
.replace("$PRIMARY_KEY_CONDITION$", pkCondition.toString());
}
private String convertTableFieldsString(String table, List<ExtTableField.TableField> fields) {
StringBuilder str = new StringBuilder();
str.append("(\n");
ExtTableField.TableField primaryKeyField = null;
for (ExtTableField.TableField field : fields) {
if (field.isPrimaryKey()) {
primaryKeyField = field;
}
//check inject
if (checkSqlInjection(field.getColumnName())) {
throw new RuntimeException("包含SQL注入的参数请检查参数");
}
//column name
str.append("`").append(field.getColumnName()).append("` ");
//type
switch (field.getType()) {
case nvarchar:
str.append("NVARCHAR(");
if (field.getSize() != null && field.getSize() > 0) {
str.append(field.getSize());
} else {
str.append(256);
}
str.append(") ");
break;
case number:
str.append("BIGINT(");
if (field.getSize() != null && field.getSize() > 0) {
str.append(field.getSize());
} else {
str.append(20);
}
str.append(") ");
break;
case decimal:
str.append("DECIMAL(");
if (field.getSize() != null && field.getSize() > 0) {
str.append(field.getSize());
} else {
str.append(20);
}
str.append(",");
if (field.getAccuracy() != null && field.getAccuracy() >= 0) {
str.append(field.getAccuracy());
} else {
str.append(4);
}
str.append(") ");
break;
case datetime:
str.append("DATETIME ");
break;
default:
str.append("LONGTEXT ");
break;
}
//必填
if (field.isRequired()) {
str.append("NOT NULL ");
}
//comment
str.append("COMMENT '").append(field.getComment()).append("' ");
//换行
str.append(",\n");
}
if (primaryKeyField != null) {
str.append("constraint ")
.append(table)
.append("_pk ")
.append("PRIMARY KEY (")
.append("`")
.append(primaryKeyField.getColumnName())
.append("`)");
}
str.append("\n)\n");
return str.toString();
}
@Override
public List<String> createTableIndexSql(String table, List<ExtIndexField> indexFields) {
List<String> list = new ArrayList<>();
for (ExtIndexField indexField : indexFields) {
String c = convertTableIndexSql(table, indexField);
if (StringUtils.isNotEmpty(c)) {
list.add(c);
}
}
return list;
}
private String convertTableIndexSql(String table, ExtIndexField indexField) {
StringBuilder column = new StringBuilder();
if (CollectionUtils.isEmpty(indexField.getColumns())) {
return null;
}
//check inject
if (checkSqlInjection(table) || checkSqlInjection(indexField.getName())) {
throw new RuntimeException("包含SQL注入的参数请检查参数");
}
int count = 0;
for (ExtIndexField.ColumnSetting indexFieldColumn : indexField.getColumns()) {
count++;
column.append("`").append(indexFieldColumn.getColumn()).append("` ");
if (StringUtils.equalsIgnoreCase(indexFieldColumn.getOrder(), "asc")) {
column.append("asc");
} else if (StringUtils.equalsIgnoreCase(indexFieldColumn.getOrder(), "desc")) {
column.append("desc");
}
if (count < indexField.getColumns().size()) {
column.append(", ");
}
}
return creatTableIndexSql.replace("TABLE_NAME", table).replace("INDEX_NAME", indexField.getName()).replace("Column_Fields", column.toString());
}
}

View File

@ -1480,7 +1480,7 @@ public class CKQueryProvider extends QueryProvider {
}
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
String keyword = value.get(0).toUpperCase();
whereValue = "'%" + keyword + "%'";
whereValue = formatLikeValue(keyword);
whereName = "upper(" + whereName + ")";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == DeTypeConstants.DE_TIME) {

View File

@ -1476,7 +1476,7 @@ public class Db2QueryProvider extends QueryProvider {
}
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
String keyword = value.get(0).toUpperCase();
whereValue = "'%" + keyword + "%'";
whereValue = formatLikeValue(keyword);
whereName = "upper(" + whereName + ")";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == DeTypeConstants.DE_TIME) {

View File

@ -1403,7 +1403,7 @@ public class EsQueryProvider extends QueryProvider {
}
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
String keyword = value.get(0).toUpperCase();
whereValue = "'%" + keyword + "%'";
whereValue = formatLikeValue(keyword);
whereName = "UCASE(" + whereName + ")";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == 1) {

View File

@ -1360,7 +1360,7 @@ public class HiveQueryProvider extends QueryProvider {
}
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
String keyword = value.get(0).toUpperCase();
whereValue = "'%" + keyword + "%'";
whereValue = formatLikeValue(keyword);
whereName = "upper(" + whereName + ")";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == DeTypeConstants.DE_TIME) {

View File

@ -1380,7 +1380,7 @@ public class ImpalaQueryProvider extends QueryProvider {
}
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
String keyword = value.get(0).toUpperCase();
whereValue = "'%" + keyword + "%'";
whereValue = formatLikeValue(keyword);
whereName = "upper(" + whereName + ")";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == DeTypeConstants.DE_TIME) {

View File

@ -1235,7 +1235,7 @@ public class MongoQueryProvider extends QueryProvider {
}
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
String keyword = value.get(0).toUpperCase();
whereValue = "'%" + keyword + "%'";
whereValue = formatLikeValue(keyword);
whereName = "upper(" + whereName + ")";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == DeTypeConstants.DE_TIME) {

View File

@ -1444,7 +1444,7 @@ public class MysqlQueryProvider extends QueryProvider {
}
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
String keyword = value.get(0).toUpperCase();
whereValue = "'%" + keyword + "%'";
whereValue = formatLikeValue(keyword);
whereName = "upper(" + whereName + ")";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == 1) {

View File

@ -1549,7 +1549,7 @@ public class OracleQueryProvider extends QueryProvider {
}
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
String keyword = value.get(0).toUpperCase();
whereValue = "'%" + keyword + "%'";
whereValue = formatLikeValue(keyword);
whereName = "upper(" + whereName + ")";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == 1) {

View File

@ -1400,7 +1400,7 @@ public class PgQueryProvider extends QueryProvider {
}
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
String keyword = value.get(0).toUpperCase();
whereValue = "'%" + keyword + "%'";
whereValue = formatLikeValue(keyword);
whereName = "upper(" + whereName + ")";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == 1) {

View File

@ -1386,7 +1386,7 @@ public class RedshiftQueryProvider extends QueryProvider {
}
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
String keyword = value.get(0).toUpperCase();
whereValue = "'%" + keyword + "%'";
whereValue = formatLikeValue(keyword);
whereName = "upper(" + whereName + ")";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == 1) {

View File

@ -1532,7 +1532,7 @@ public class SqlserverQueryProvider extends QueryProvider {
}
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) {
String keyword = value.get(0).toUpperCase();
whereValue = "'%" + keyword + "%'";
whereValue = formatLikeValue(keyword);
whereName = "upper(" + whereName + ")";
} else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) {
if (request.getDatasetTableField().getDeType() == DeTypeConstants.DE_TIME) {

View File

@ -731,7 +731,11 @@ public class ChartViewService {
}
if (chartExtRequest.getPageSize() == null) {
String pageSize = (String) mapSize.get("tablePageSize");
chartExtRequest.setPageSize(Math.min(Long.parseLong(pageSize), view.getResultCount().longValue()));
if (StringUtils.equalsIgnoreCase(view.getResultMode(), "custom")) {
chartExtRequest.setPageSize(Math.min(Long.parseLong(pageSize), view.getResultCount().longValue()));
} else {
chartExtRequest.setPageSize(Long.parseLong(pageSize));
}
}
} else {
if (StringUtils.equalsIgnoreCase(view.getResultMode(), "custom")) {
@ -1856,7 +1860,7 @@ public class ChartViewService {
}
Date date = simpleDateFormat.parse(cTime);
calendar.setTime(date);
calendar.add(Calendar.DAY_OF_YEAR,6);// 加6天用一周最后一天计算周可避免跨年的问题
calendar.add(Calendar.DAY_OF_YEAR, 6);// 加6天用一周最后一天计算周可避免跨年的问题
calendar.add(Calendar.WEEK_OF_YEAR, -1);
lastTime = simpleDateFormat.format(calendar.getTime());
}

View File

@ -0,0 +1,406 @@
package io.dataease.service.datafill;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import io.dataease.auth.service.AuthUserService;
import io.dataease.commons.utils.CommonBeanFactory;
import io.dataease.controller.request.datafill.DataFillFormTableDataRequest;
import io.dataease.controller.response.datafill.DataFillFormTableDataResponse;
import io.dataease.dto.datafill.DataFillCommitLogDTO;
import io.dataease.ext.ExtDataFillFormMapper;
import io.dataease.plugins.common.base.domain.DataFillFormWithBLOBs;
import io.dataease.plugins.common.base.domain.Datasource;
import io.dataease.plugins.common.base.mapper.DataFillFormMapper;
import io.dataease.plugins.common.dto.datafill.ExtTableField;
import io.dataease.plugins.common.dto.datasource.TableField;
import io.dataease.plugins.common.exception.DataEaseException;
import io.dataease.plugins.common.request.datasource.DatasourceRequest;
import io.dataease.plugins.datasource.provider.ExtDDLProvider;
import io.dataease.plugins.datasource.provider.Provider;
import io.dataease.plugins.datasource.provider.ProviderFactory;
import io.dataease.provider.datasource.JdbcProvider;
import io.dataease.service.datasource.DatasourceService;
import io.dataease.service.sys.SysAuthService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.pentaho.di.core.util.UUIDUtil;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class DataFillDataService {
@Resource
private Environment env;
@Resource
private DataFillFormMapper dataFillFormMapper;
@Resource
private ExtDataFillFormMapper extDataFillFormMapper;
@Resource
private DatasourceService datasource;
@Resource
private SysAuthService sysAuthService;
@Resource
private DataFillLogService dataFillLogService;
private final static Gson gson = new Gson();
public DataFillFormTableDataResponse listData(DataFillFormTableDataRequest searchRequest) throws Exception {
DataFillFormWithBLOBs dataFillForm = dataFillFormMapper.selectByPrimaryKey(searchRequest.getId());
if (StringUtils.equals(dataFillForm.getNodeType(), "folder")) {
return null;
}
List<ExtTableField> fields = gson.fromJson(dataFillForm.getForms(), new TypeToken<List<ExtTableField>>() {
}.getType());
Datasource ds = datasource.get(dataFillForm.getDatasource());
Provider datasourceProvider = ProviderFactory.getProvider(ds.getType());
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setDatasource(ds);
datasourceRequest.setTable(dataFillForm.getTableName());
List<TableField> tableFields = datasourceProvider.getTableFields(datasourceRequest);
Map<String, ExtTableField.BaseType> extTableFieldTypeMap = new HashMap<>();
Map<String, TableField> tableFieldMap = new HashMap<>();
List<TableField> searchFields = new ArrayList<>();
String key = "";
TableField pk = null;
for (TableField tableField : tableFields) {
if (tableField.isPrimaryKey()) {
//先把ID放进来
searchFields.add(tableField);
key = tableField.getFieldName();
pk = tableField;
}
tableFieldMap.put(tableField.getFieldName(), tableField);
}
//核对一下字段
for (ExtTableField field : fields) {
if (StringUtils.equalsIgnoreCase(field.getType(), "dateRange")) {
String name1 = field.getSettings().getMapping().getColumnName1();
extTableFieldTypeMap.put(name1, field.getSettings().getMapping().getType());
TableField f1 = tableFieldMap.get(name1);
if (f1 != null) {
//调整类型给后面解析字段用
f1.setFieldType(field.getSettings().getMapping().getType().name());
searchFields.add(f1);
}
String name2 = field.getSettings().getMapping().getColumnName2();
extTableFieldTypeMap.put(name2, field.getSettings().getMapping().getType());
TableField f2 = tableFieldMap.get(name2);
if (f2 != null) {
//调整类型给后面解析字段用
f2.setFieldType(field.getSettings().getMapping().getType().name());
searchFields.add(f2);
}
} else {
String name = field.getSettings().getMapping().getColumnName();
extTableFieldTypeMap.put(name, field.getSettings().getMapping().getType());
TableField f = tableFieldMap.get(field.getSettings().getMapping().getColumnName());
if (f != null) {
//调整类型给后面解析字段用
f.setFieldType(field.getSettings().getMapping().getType().name());
searchFields.add(f);
}
}
}
ExtDDLProvider extDDLProvider = ProviderFactory.gerExtDDLProvider(ds.getType());
String whereSql = "";
if (StringUtils.isNoneBlank(searchRequest.getPrimaryKeyValue())) {
whereSql = extDDLProvider.whereSql(dataFillForm.getTableName(), List.of(pk));
}
String countSql = extDDLProvider.countSql(dataFillForm.getTableName(), searchFields, whereSql);
if (StringUtils.isNoneBlank(searchRequest.getPrimaryKeyValue())) {
datasourceRequest.setTableFieldWithValues(List.of(new DatasourceRequest.TableFieldWithValue()
.setValue(searchRequest.getPrimaryKeyValue())
.setFiledName(pk.getFieldName())
.setTypeName(pk.getFieldType())
.setType(pk.getType())));
}
datasourceRequest.setQuery(countSql);
List<String[]> countData = datasourceProvider.getData(datasourceRequest);
long count = NumberUtils.toLong(countData.get(0)[0]);
String searchSql = extDDLProvider.searchSql(dataFillForm.getTableName(), searchFields, whereSql, searchRequest.getPageSize(), (searchRequest.getCurrentPage() - 1) * searchRequest.getPageSize());
datasourceRequest.setQuery(searchSql);
List<String[]> data2 = datasourceProvider.getData(datasourceRequest);
List<Map<String, Object>> result = new ArrayList<>();
List<Map<String, Object>> resultList = new ArrayList<>();
List<String> ids = new ArrayList<>();
for (String[] strings : data2) {
Map<String, Object> object = new HashMap<>();
for (int i = 0; i < searchFields.size(); i++) {
TableField f = searchFields.get(i);
String name = f.getFieldName();
String data = strings[i];
if (data == null) {
object.put(name, null);
continue;
}
if (StringUtils.equals(key, name)) {
ids.add(strings[i]);
}
ExtTableField.BaseType extFieldType = extTableFieldTypeMap.get(name);
if (extFieldType != null) {
switch (extFieldType) {
case number:
object.put(name, NumberUtils.toLong(strings[i]));
break;
case decimal:
object.put(name, new BigDecimal(strings[i]));
break;
case datetime:
SimpleDateFormat sdf = new SimpleDateFormat(extDDLProvider.DEFAULT_DATE_FORMAT_STR);
object.put(name, sdf.parse(strings[i]));
break;
default:
object.put(name, strings[i]);
break;
}
} else {
object.put(name, strings[i]);
}
}
result.add(object);
}
List<DataFillCommitLogDTO> list = new ArrayList<>();
if (CollectionUtils.isNotEmpty(ids)) {
list = extDataFillFormMapper.selectLatestLogByFormDataIds(dataFillForm.getId(), ids);
}
Map<String, DataFillCommitLogDTO> logMap = list.stream().collect(Collectors.toMap(log -> log.getFormId() + "__" + log.getDataId(), log -> log));
for (Map<String, Object> object : result) {
Map<String, Object> temp = new HashMap<>();
temp.put("data", object);
temp.put("logInfo", logMap.get(dataFillForm.getId() + "__" + object.get(key)));
resultList.add(temp);
}
return new DataFillFormTableDataResponse()
.setKey(key)
.setData(resultList)
.setFields(fields)
.setTotal(count)
.setPageSize(searchRequest.getPageSize())
.setCurrentPage(searchRequest.getCurrentPage());
}
public void deleteRowData(String formId, String id) throws Exception {
DataFillFormWithBLOBs dataFillForm = dataFillFormMapper.selectByPrimaryKey(formId);
if (StringUtils.equals(dataFillForm.getNodeType(), "folder")) {
return;
}
Datasource ds = datasource.get(dataFillForm.getDatasource());
ExtDDLProvider extDDLProvider = ProviderFactory.gerExtDDLProvider(ds.getType());
Provider datasourceProvider = ProviderFactory.getProvider(ds.getType());
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setDatasource(ds);
datasourceRequest.setTable(dataFillForm.getTableName());
List<TableField> tableFields = datasourceProvider.getTableFields(datasourceRequest).stream().filter(TableField::isPrimaryKey).collect(Collectors.toList());
if (CollectionUtils.isEmpty(tableFields)) {
throw new RuntimeException("没有主键");
}
TableField key = tableFields.get(0);
DatasourceRequest.TableFieldWithValue pk = new DatasourceRequest.TableFieldWithValue()
.setValue(id) //todo 有可能是数字
.setFiledName(key.getFieldName())
.setTypeName(key.getFieldType())
.setType(key.getType());
String deleteSql = extDDLProvider.deleteDataByIdSql(dataFillForm.getTableName(), pk);
datasourceRequest.setQuery(deleteSql);
datasourceRequest.setTableFieldWithValues(List.of(pk));
JdbcProvider jdbcProvider = CommonBeanFactory.getBean(JdbcProvider.class);
jdbcProvider.execWithPreparedStatement(datasourceRequest);
dataFillLogService.saveCommitOperation(DataFillLogService.COMMIT_OPERATE_DELETE, dataFillForm.getId(), id);
}
public String updateRowData(String formId, String rowId, Map<String, Object> data, boolean insert) throws Exception {
if (!CommonBeanFactory.getBean(AuthUserService.class).pluginLoaded()) {
DataEaseException.throwException("invalid");
}
if (rowId == null) {
insert = true;
//先默认主键是uuid
rowId = UUIDUtil.getUUIDAsString();
}
DataFillFormWithBLOBs dataFillForm = dataFillFormMapper.selectByPrimaryKey(formId);
List<ExtTableField> fields = gson.fromJson(dataFillForm.getForms(), new TypeToken<List<ExtTableField>>() {
}.getType());
Datasource ds = datasource.get(dataFillForm.getDatasource());
Provider datasourceProvider = ProviderFactory.getProvider(ds.getType());
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setDatasource(ds);
datasourceRequest.setTable(dataFillForm.getTableName());
List<TableField> tableFields = datasourceProvider.getTableFields(datasourceRequest);
Map<String, TableField> tableFieldMap = new HashMap<>();
List<DatasourceRequest.TableFieldWithValue> searchFields = new ArrayList<>();
List<DatasourceRequest.TableFieldWithValue> uniqueFields = new ArrayList<>();
Map<String, ExtTableField> extTableFields = new HashMap<>();
DatasourceRequest.TableFieldWithValue pk = null;
for (TableField tableField : tableFields) {
if (tableField.isPrimaryKey()) {
pk = new DatasourceRequest.TableFieldWithValue()
.setValue(rowId)
.setFiledName(tableField.getFieldName())
.setTypeName(tableField.getFieldType())
.setType(tableField.getType());
if (insert) {
searchFields.add(pk);
}
continue;
}
tableFieldMap.put(tableField.getFieldName(), tableField);
}
for (ExtTableField field : fields) {
if (StringUtils.equalsIgnoreCase(field.getType(), "dateRange")) {
String name1 = field.getSettings().getMapping().getColumnName1();
String name2 = field.getSettings().getMapping().getColumnName2();
if (tableFieldMap.containsKey(name1) && data.containsKey(name1) && data.get(name1) != null) {
DatasourceRequest.TableFieldWithValue value1 = new DatasourceRequest.TableFieldWithValue()
.setValue(new java.sql.Date((long) data.get(name1)))
.setFiledName(name1)
.setTypeName(tableFieldMap.get(name1).getFieldType())
.setType(tableFieldMap.get(name1).getType());
searchFields.add(value1);
extTableFields.put(name1, field);
}
if (tableFieldMap.containsKey(name2) && data.containsKey(name2) && data.get(name2) != null) {
DatasourceRequest.TableFieldWithValue value2 = new DatasourceRequest.TableFieldWithValue()
.setValue(new java.sql.Date((long) data.get(name2)))
.setFiledName(name2)
.setTypeName(tableFieldMap.get(name2).getFieldType())
.setType(tableFieldMap.get(name2).getType());
searchFields.add(value2);
extTableFields.put(name2, field);
}
} else {
String name = field.getSettings().getMapping().getColumnName();
if (tableFieldMap.containsKey(name) && data.containsKey(name) && data.get(name) != null) {
DatasourceRequest.TableFieldWithValue value = new DatasourceRequest.TableFieldWithValue()
.setValue(data.get(name))
.setFiledName(name)
.setTypeName(tableFieldMap.get(name).getFieldType())
.setType(tableFieldMap.get(name).getType());
if (StringUtils.equalsIgnoreCase(field.getType(), "date")) {
value.setValue(new java.sql.Date((long) data.get(name)));
}
searchFields.add(value);
extTableFields.put(name, field);
// 关于unique的字段判断
if (field.getSettings().isUnique()) {
uniqueFields.add(value);
}
}
}
}
ExtDDLProvider extDDLProvider = ProviderFactory.gerExtDDLProvider(ds.getType());
if (CollectionUtils.isNotEmpty(uniqueFields)) {
for (DatasourceRequest.TableFieldWithValue uniqueField : uniqueFields) {
String sql = extDDLProvider.checkUniqueValueSql(dataFillForm.getTableName(), uniqueField, insert ? null : pk);
datasourceRequest.setQuery(sql);
List<DatasourceRequest.TableFieldWithValue> fs = new ArrayList<>();
fs.add(uniqueField);
if (!insert) {
fs.add(pk);
}
datasourceRequest.setTableFieldWithValues(fs);
List<String[]> countData = datasourceProvider.getData(datasourceRequest);
long count = NumberUtils.toLong(countData.get(0)[0]);
if (count > 0) {
DataEaseException.throwException(extTableFields.get(uniqueField.getFiledName()).getSettings().getName() + " 值不能重复");
}
}
}
String sql = insert ?
extDDLProvider.insertDataSql(dataFillForm.getTableName(), searchFields) :
extDDLProvider.updateDataByIdSql(dataFillForm.getTableName(), searchFields, pk);
datasourceRequest.setQuery(sql);
boolean skip = false;
if (!insert && CollectionUtils.isEmpty(searchFields)) {
//DataEaseException.throwException("没有修改");
skip = true;
}
JdbcProvider jdbcProvider = CommonBeanFactory.getBean(JdbcProvider.class);
// 主键在最后传进去
if (!insert) {
searchFields.add(pk);
}
datasourceRequest.setTableFieldWithValues(searchFields);
if (!skip) {
int result = jdbcProvider.execWithPreparedStatement(datasourceRequest);
}
if (insert) {
dataFillLogService.saveCommitOperation(DataFillLogService.COMMIT_OPERATE_INSERT, dataFillForm.getId(), rowId);
} else {
dataFillLogService.saveCommitOperation(DataFillLogService.COMMIT_OPERATE_UPDATE, dataFillForm.getId(), rowId);
}
return rowId;
}
}

View File

@ -0,0 +1,51 @@
package io.dataease.service.datafill;
import io.dataease.commons.utils.AuthUtils;
import io.dataease.controller.request.datafill.DataFillCommitLogSearchRequest;
import io.dataease.dto.datafill.DataFillCommitLogDTO;
import io.dataease.ext.ExtDataFillFormMapper;
import io.dataease.plugins.common.base.domain.DataFillCommitLog;
import io.dataease.plugins.common.base.mapper.DataFillCommitLogMapper;
import org.pentaho.di.core.util.UUIDUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
@Service
@Transactional(rollbackFor = Exception.class)
public class DataFillLogService {
@Resource
private ExtDataFillFormMapper extDataFillFormMapper;
@Resource
private DataFillCommitLogMapper dataFillCommitLogMapper;
public static final String COMMIT_OPERATE_INSERT = "INSERT";
public static final String COMMIT_OPERATE_UPDATE = "UPDATE";
public static final String COMMIT_OPERATE_DELETE = "DELETE";
public List<DataFillCommitLogDTO> commitLogs(String formId, DataFillCommitLogSearchRequest request) {
return extDataFillFormMapper.selectDataFillLogs(formId, request.getCommitByName());
}
public void saveCommitOperation(String operate, String formId, String dataId) {
DataFillCommitLog log = new DataFillCommitLog();
log.setId(UUIDUtil.getUUIDAsString());
log.setFormId(formId);
log.setDataId(dataId);
log.setCommitBy(AuthUtils.getUser().getUsername());
log.setOperate(operate);
log.setCommitTime(new Date());
dataFillCommitLogMapper.insertSelective(log);
}
}

View File

@ -0,0 +1,334 @@
package io.dataease.service.datafill;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import io.dataease.auth.annotation.DeCleaner;
import io.dataease.auth.service.AuthUserService;
import io.dataease.commons.constants.*;
import io.dataease.commons.utils.*;
import io.dataease.controller.ResultHolder;
import io.dataease.controller.request.datafill.DataFillFormRequest;
import io.dataease.dto.DatasourceDTO;
import io.dataease.dto.datafill.DataFillFormDTO;
import io.dataease.ext.ExtDataFillFormMapper;
import io.dataease.i18n.Translator;
import io.dataease.listener.util.CacheUtils;
import io.dataease.plugins.common.base.domain.*;
import io.dataease.plugins.common.base.mapper.DataFillFormMapper;
import io.dataease.plugins.common.base.mapper.DataFillUserTaskMapper;
import io.dataease.plugins.common.base.mapper.SysUserMapper;
import io.dataease.plugins.common.dto.datafill.ExtIndexField;
import io.dataease.plugins.common.dto.datafill.ExtTableField;
import io.dataease.plugins.common.dto.datasource.TableField;
import io.dataease.plugins.common.exception.DataEaseException;
import io.dataease.plugins.common.request.datasource.DatasourceRequest;
import io.dataease.plugins.datasource.provider.ExtDDLProvider;
import io.dataease.plugins.datasource.provider.Provider;
import io.dataease.plugins.datasource.provider.ProviderFactory;
import io.dataease.provider.datasource.JdbcProvider;
import io.dataease.service.datasource.DatasourceService;
import io.dataease.service.sys.SysAuthService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.pentaho.di.core.util.UUIDUtil;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class DataFillService {
@Resource
private Environment env;
@Resource
private DataFillFormMapper dataFillFormMapper;
@Resource
private ExtDataFillFormMapper extDataFillFormMapper;
@Resource
private DatasourceService datasource;
@Resource
private SysAuthService sysAuthService;
@Resource
private SysUserMapper sysUserMapper;
@Resource
private DataFillTaskService dataFillTaskService;
@Resource
private DataFillDataService dataFillDataService;
@Resource
private DataFillUserTaskMapper dataFillUserTaskMapper;
private final static Gson gson = new Gson();
@DeCleaner(value = DePermissionType.DATA_FILL, key = "pid")
public ResultHolder saveForm(DataFillFormWithBLOBs dataFillForm) throws Exception {
if (!CommonBeanFactory.getBean(AuthUserService.class).pluginLoaded()) {
DataEaseException.throwException("invalid");
}
String uuid = UUIDUtil.getUUID().toString();
dataFillForm.setId(uuid);
checkName(uuid, dataFillForm.getName(), dataFillForm.getPid(), dataFillForm.getLevel(), dataFillForm.getNodeType(), DataFillConstants.OPT_TYPE_INSERT);
if (!StringUtils.equals(dataFillForm.getNodeType(), "folder")) {
List<ExtTableField> fields = gson.fromJson(dataFillForm.getForms(), new TypeToken<List<ExtTableField>>() {
}.getType());
List<ExtIndexField> indexes = new ArrayList<>();
if (dataFillForm.getCreateIndex()) {
indexes = gson.fromJson(dataFillForm.getTableIndexes(), new TypeToken<List<ExtIndexField>>() {
}.getType());
}
DatasourceDTO datasourceDTO = datasource.getDataSourceDetails(dataFillForm.getDatasource());
datasourceDTO.setConfiguration(new String(java.util.Base64.getDecoder().decode(datasourceDTO.getConfiguration())));
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setDatasource(datasourceDTO);
datasourceRequest.setQuery("SELECT VERSION()");
JdbcProvider jdbcProvider = CommonBeanFactory.getBean(JdbcProvider.class);
String version = jdbcProvider.getData(datasourceRequest).get(0)[0];
//拼sql
ExtDDLProvider extDDLProvider = ProviderFactory.gerExtDDLProvider(datasourceDTO.getType());
String sql = extDDLProvider.createTableSql(dataFillForm.getTableName(), fields);
//创建表
datasourceRequest.setQuery(sql);
jdbcProvider.exec(datasourceRequest);
if (dataFillForm.getCreateIndex()) {
try {
List<String> sqls = extDDLProvider.createTableIndexSql(dataFillForm.getTableName(), indexes);
for (String indexSql : sqls) {
datasourceRequest.setQuery(indexSql);
jdbcProvider.exec(datasourceRequest);
}
} catch (Exception e) {
// 执行到这里说明表已经建成功了创建index出错那就需要回滚删除创建的表
datasourceRequest.setQuery(extDDLProvider.dropTableSql(dataFillForm.getTableName()));
jdbcProvider.exec(datasourceRequest);
throw e;
}
}
}
dataFillForm.setCreateBy(AuthUtils.getUser().getUsername());
dataFillForm.setUpdateBy(AuthUtils.getUser().getUsername());
Date current = new Date();
dataFillForm.setCreateTime(current);
dataFillForm.setUpdateTime(current);
dataFillFormMapper.insertSelective(dataFillForm);
// 清理权限缓存应该不需要
//clearPermissionCache();
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.CREATE, SysLogConstants.SOURCE_TYPE.DATA_FILL_FORM, dataFillForm.getId(), dataFillForm.getPid(), null, null);
sysAuthService.copyAuth(uuid, SysAuthConstants.AUTH_SOURCE_TYPE_DATA_FILLING);
return ResultHolder.success(uuid);
}
@DeCleaner(value = DePermissionType.DATA_FILL, key = "pid")
public ResultHolder updateForm(DataFillFormWithBLOBs dataFillForm) {
if (!CommonBeanFactory.getBean(AuthUserService.class).pluginLoaded()) {
DataEaseException.throwException("invalid");
}
Assert.notNull(dataFillForm.getId(), "id cannot be null");
dataFillForm.setUpdateTime(new Date());
dataFillFormMapper.updateByPrimaryKeySelective(dataFillForm);
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.MODIFY, SysLogConstants.SOURCE_TYPE.DATA_FILL_FORM, dataFillForm.getId(), dataFillForm.getPid(), null, null);
return ResultHolder.success(dataFillForm.getId());
}
private void checkName(String id, String name, String pid, int level, String nodeType, String optType) {
DataFillFormExample example = new DataFillFormExample();
if (DataFillConstants.OPT_TYPE_INSERT.equalsIgnoreCase(optType)) {
example.createCriteria().andPidEqualTo(pid).andNameEqualTo(name).andNodeTypeEqualTo(nodeType);
} else if (DataFillConstants.OPT_TYPE_UPDATE.equalsIgnoreCase(optType)) {
example.createCriteria().andPidEqualTo(pid).andNameEqualTo(name).andIdNotEqualTo(id).andNodeTypeEqualTo(nodeType);
}
List<DataFillForm> checkResult = dataFillFormMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(checkResult)) {
DataEaseException.throwException(DataFillConstants.DATA_FILL_NODE_TYPE_DATA_FILL.equals(nodeType) ? Translator.get("I18N_DATA_FILL_FORM_EXIST") : Translator.get("I18N_FOlDER_EXIST"));
}
}
public List<DataFillFormDTO> tree(DataFillFormRequest request) {
if (!CommonBeanFactory.getBean(AuthUserService.class).pluginLoaded()) {
DataEaseException.throwException("invalid");
}
String userId = String.valueOf(AuthUtils.getUser().getUserId());
request.setUserId(userId);
List<DataFillFormDTO> list = extDataFillFormMapper.search(request);
return TreeUtils.mergeTree(list);
}
public DataFillFormWithBLOBs get(String id) {
if (!CommonBeanFactory.getBean(AuthUserService.class).pluginLoaded()) {
DataEaseException.throwException("invalid");
}
Assert.notNull(id, "id cannot be null");
return dataFillFormMapper.selectByPrimaryKey(id);
}
public DataFillFormDTO getWithPrivileges(String id) {
if (!CommonBeanFactory.getBean(AuthUserService.class).pluginLoaded()) {
DataEaseException.throwException("invalid");
}
Assert.notNull(id, "id cannot be null");
String userId = String.valueOf(AuthUtils.getUser().getUserId());
DataFillFormRequest request = new DataFillFormRequest();
request.setUserId(userId);
request.setId(id);
List<DataFillFormDTO> list = extDataFillFormMapper.search(request);
if (CollectionUtils.isEmpty(list)) {
return null;
}
DataFillFormDTO base = list.stream().filter(dto -> StringUtils.equals(dto.getId(), id)).collect(Collectors.toList()).get(0);
DataFillFormDTO result = new DataFillFormDTO();
BeanUtils.copyBean(result, get(id));
result.setPrivileges(base.getPrivileges());
SysUserExample userExample = new SysUserExample();
userExample.createCriteria().andUsernameEqualTo(result.getCreateBy());
List<SysUser> sysUsers = sysUserMapper.selectByExample(userExample);
if (CollectionUtils.isNotEmpty(sysUsers)) {
result.setCreatorName(sysUsers.get(0).getNickName());
}
Datasource d = datasource.get(result.getDatasource());
if (d != null) {
result.setDatasourceName(d.getName());
}
return result;
}
public void deleteForm(String id) throws Exception {
if (!CommonBeanFactory.getBean(AuthUserService.class).pluginLoaded()) {
DataEaseException.throwException("invalid");
}
Assert.notNull(id, "id cannot be null");
sysAuthService.checkTreeNoManageCount(SysAuthConstants.AUTH_SOURCE_TYPE_DATA_FILLING, id);
Map<String, String> stringStringMap = extDataFillFormMapper.searchChildrenIds(id, SysAuthConstants.AUTH_SOURCE_TYPE_DATA_FILLING);
String[] split = stringStringMap.get("ids").split(",");
DataFillFormWithBLOBs dataFillForm = dataFillFormMapper.selectByPrimaryKey(id);
List<String> ids = new ArrayList<>();
for (String dsId : split) {
if (StringUtils.isNotEmpty(dsId)) {
ids.add(dsId);
}
}
if (CollectionUtils.isNotEmpty(ids)) {
DataFillFormExample example = new DataFillFormExample();
example.createCriteria().andIdIn(ids);
dataFillFormMapper.deleteByExample(example);
}
DeLogUtils.save(SysLogConstants.OPERATE_TYPE.DELETE, SysLogConstants.SOURCE_TYPE.DATA_FILL_FORM, dataFillForm.getId(), dataFillForm.getPid(), null, null);
dataFillTaskService.deleteTaskByFormId(id);
}
public List<ExtTableField> listFields(String id) throws Exception {
DataFillFormWithBLOBs dataFillForm = dataFillFormMapper.selectByPrimaryKey(id);
if (StringUtils.equals(dataFillForm.getNodeType(), "folder")) {
return null;
}
return gson.fromJson(dataFillForm.getForms(), new TypeToken<List<ExtTableField>>() {
}.getType());
}
public void fillFormData(String userTaskId, Map<String, Object> data) throws Exception {
if (!CommonBeanFactory.getBean(AuthUserService.class).pluginLoaded()) {
DataEaseException.throwException("invalid");
}
DataFillUserTask task = dataFillUserTaskMapper.selectByPrimaryKey(userTaskId);
if (task == null) {
DataEaseException.throwException("任务不存在");
}
if (!AuthUtils.getUser().getUserId().equals(task.getUser())) {
DataEaseException.throwException("当前用户非任务用户");
}
if (task.getEndTime() != null) {
if (task.getEndTime().getTime() < System.currentTimeMillis()) {
DataEaseException.throwException("已经超过了任务截止时间");
}
}
String formId = task.getFormId();
String rowId = null;
if (StringUtils.isNotBlank(task.getValueId())) {
rowId = task.getValueId();
} else {
DataFillFormWithBLOBs dataFillForm = dataFillFormMapper.selectByPrimaryKey(formId);
Datasource ds = datasource.get(dataFillForm.getDatasource());
Provider datasourceProvider = ProviderFactory.getProvider(ds.getType());
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setDatasource(ds);
datasourceRequest.setTable(dataFillForm.getTableName());
List<TableField> tableFields = datasourceProvider.getTableFields(datasourceRequest);
for (TableField tableField : tableFields) {
if (tableField.isPrimaryKey()) {
rowId = (String) data.get(tableField.getFieldName());
break;
}
}
}
rowId = dataFillDataService.updateRowData(formId, rowId, data, rowId == null);
task.setValueId(rowId);
task.setFinishTime(new Date());
dataFillUserTaskMapper.updateByPrimaryKeySelective(task);
}
}

View File

@ -0,0 +1,259 @@
package io.dataease.service.datafill;
import io.dataease.auth.service.AuthUserService;
import io.dataease.commons.model.AuthURD;
import io.dataease.commons.utils.AuthUtils;
import io.dataease.commons.utils.CommonBeanFactory;
import io.dataease.controller.request.datafill.DataFillTaskSearchRequest;
import io.dataease.controller.request.datafill.DataFillUserTaskSearchRequest;
import io.dataease.dto.datafill.DataFillTaskDTO;
import io.dataease.dto.datafill.DataFillUserTaskDTO;
import io.dataease.ext.ExtDataFillFormMapper;
import io.dataease.job.sechedule.ScheduleManager;
import io.dataease.job.sechedule.strategy.TaskHandler;
import io.dataease.job.sechedule.strategy.TaskStrategyFactory;
import io.dataease.plugins.common.base.domain.*;
import io.dataease.plugins.common.base.mapper.DataFillTaskMapper;
import io.dataease.plugins.common.base.mapper.DataFillUserTaskMapper;
import io.dataease.plugins.common.base.mapper.SysUserMapper;
import io.dataease.plugins.common.entity.GlobalTaskEntity;
import io.dataease.plugins.common.exception.DataEaseException;
import org.apache.commons.lang3.StringUtils;
import org.pentaho.di.core.util.UUIDUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class DataFillTaskService {
@Resource
private ExtDataFillFormMapper extDataFillFormMapper;
@Resource
private DataFillTaskMapper dataFillTaskMapper;
@Resource
private DataFillUserTaskMapper dataFillUserTaskMapper;
@Resource
private SysUserMapper sysUserMapper;
@Resource
private ScheduleManager scheduleManager;
public List<DataFillTaskDTO> tasks(String formId, DataFillTaskSearchRequest request) {
request.setFormId(formId);
return extDataFillFormMapper.selectDataFillTasks(request);
}
private List<DataFillTask> listActiveTasks() {
return extDataFillFormMapper.selectActiveDataFillTasks();
}
public List<GlobalTaskEntity> listActiveTasksGlobalTaskEntity() {
List<GlobalTaskEntity> list = new ArrayList<>();
List<DataFillTask> tasks = dataFillTaskMapper.selectByExample(null);
for (DataFillTask task : tasks) {
list.add(getGlobalTaskEntity(task));
}
return list;
}
private GlobalTaskEntity getGlobalTaskEntity(DataFillTask task) {
GlobalTaskEntity entity = new GlobalTaskEntity()
.setTaskId(task.getId())
.setTaskName(task.getName())
.setRateType(task.getRateType())
.setRateVal(task.getRateVal())
.setStatus(task.getStatus())
.setTaskType("dataFillTaskHandler")
.setCreator(task.getCreator());
if (task.getRateType() == -1) {
entity.setStartTime(task.getPublishStartTime() == null ? null : task.getPublishStartTime().getTime());
entity.setEndTime(task.getPublishEndTime() == null ? null : task.getPublishEndTime().getTime());
} else {
entity.setStartTime(task.getStartTime() == null ? null : task.getStartTime().getTime());
entity.setEndTime(task.getEndTime() == null ? null : task.getEndTime().getTime());
}
return entity;
}
public void saveTask(String formId, DataFillTaskSearchRequest request) throws Exception {
if (!CommonBeanFactory.getBean(AuthUserService.class).pluginLoaded()) {
DataEaseException.throwException("invalid");
}
request.setCreator(AuthUtils.getUser().getUserId());
boolean insert = false;
if (request.getId() == null) {
insert = true;
request.setFormId(formId);
}
if (insert) {
dataFillTaskMapper.insertSelective(request);
} else {
dataFillTaskMapper.updateByPrimaryKeySelective(request);
}
DataFillTaskWithBLOBs task = dataFillTaskMapper.selectByPrimaryKey(request.getId());
GlobalTaskEntity entity = getGlobalTaskEntity(task);
TaskHandler taskHandler = TaskStrategyFactory.getInvokeStrategy(entity.getTaskType());
taskHandler.addTask(scheduleManager, entity);
}
public DataFillTaskWithBLOBs getTaskById(Long id) {
return dataFillTaskMapper.selectByPrimaryKey(id);
}
public void finishTask(Long id) {
DataFillTaskWithBLOBs task = new DataFillTaskWithBLOBs();
task.setId(id);
task.setStatus(false);
dataFillTaskMapper.updateByPrimaryKeySelective(task);
}
public void deleteTaskByFormId(String formId) {
DataFillTaskExample example = new DataFillTaskExample();
example.createCriteria().andFormIdEqualTo(formId);
for (DataFillTask dataFillTask : dataFillTaskMapper.selectByExample(example)) {
deleteTask(dataFillTask.getId());
}
}
public void deleteTask(Long id) {
try {
GlobalTaskEntity entity = getGlobalTaskEntity(dataFillTaskMapper.selectByPrimaryKey(id));
TaskHandler taskHandler = TaskStrategyFactory.getInvokeStrategy(entity.getTaskType());
taskHandler.removeTask(scheduleManager, entity);
} catch (Exception e) {
e.printStackTrace();
}
dataFillTaskMapper.deleteByPrimaryKey(id);
DataFillUserTaskExample example = new DataFillUserTaskExample();
example.createCriteria().andTaskIdEqualTo(id);
dataFillUserTaskMapper.deleteByExample(example);
}
public void enableTask(Long taskId) throws Exception {
DataFillTask task = dataFillTaskMapper.selectByPrimaryKey(taskId);
DataFillTaskSearchRequest request = new DataFillTaskSearchRequest();
request.setId(taskId);
request.setStatus(true);
saveTask(task.getFormId(), request);
}
public void disableTask(Long taskId) throws Exception {
DataFillTask task = dataFillTaskMapper.selectByPrimaryKey(taskId);
DataFillTaskSearchRequest request = new DataFillTaskSearchRequest();
request.setId(taskId);
request.setStatus(false);
saveTask(task.getFormId(), request);
}
public void createUserTasks(DataFillTaskWithBLOBs dataFillTask, String valueId) throws Exception {
String reciUsers = dataFillTask.getReciUsers();
List<String> accountSet = new ArrayList<>();
if (StringUtils.isNotBlank(reciUsers)) {
accountSet.addAll(Arrays.stream(reciUsers.split(",")).collect(Collectors.toSet()));
}
List<SysUser> sysUsers = new ArrayList<>();
if (!accountSet.isEmpty()) {
SysUserExample example = new SysUserExample();
example.createCriteria().andUsernameIn(accountSet);
sysUsers = sysUserMapper.selectByExample(example);
}
String roleList = dataFillTask.getRoleList();
String orgList = dataFillTask.getOrgList();
AuthURD authURD = new AuthURD();
if (StringUtils.isNotBlank(roleList)) {
authURD.setRoleIds(Arrays.stream(roleList.split(",")).map(Long::parseLong).collect(Collectors.toList()));
}
if (StringUtils.isNotBlank(orgList)) {
authURD.setDeptIds(Arrays.stream(orgList.split(",")).map(Long::parseLong).collect(Collectors.toList()));
}
Set<Long> ids = AuthUtils.userIdsByURD(authURD);
for (SysUser sysUser : sysUsers) {
ids.add(sysUser.getUserId());
}
Date startTime = null;
Date endTime = null;
if (dataFillTask.getRateType() == -1) {
startTime = dataFillTask.getPublishStartTime();
endTime = dataFillTask.getPublishEndTime();
} else {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date val = sdf.parse(dataFillTask.getRateVal());
Calendar calendar = Calendar.getInstance();
calendar.setTime(val);
Calendar current = Calendar.getInstance();
calendar.set(Calendar.YEAR, current.get(Calendar.YEAR));
calendar.set(Calendar.MONTH, current.get(Calendar.MONTH));
calendar.set(Calendar.DAY_OF_MONTH, current.get(Calendar.DAY_OF_MONTH));
startTime = calendar.getTime();
if (dataFillTask.getPublishRangeTimeType() == -1) {
calendar.add(Calendar.HOUR_OF_DAY, dataFillTask.getPublishRangeTime());
} else if (dataFillTask.getPublishRangeTimeType() == 0) {
calendar.add(Calendar.DAY_OF_MONTH, dataFillTask.getPublishRangeTime());
} else if (dataFillTask.getPublishRangeTimeType() == 1) {
calendar.add(Calendar.WEEK_OF_YEAR, dataFillTask.getPublishRangeTime());
} else if (dataFillTask.getPublishRangeTimeType() == 2) {
calendar.add(Calendar.MONTH, dataFillTask.getPublishRangeTime());
}
endTime = calendar.getTime();
}
for (Long id : ids) {
DataFillUserTask task = new DataFillUserTask();
task.setId(UUIDUtil.getUUIDAsString());
task.setTaskId(dataFillTask.getId());
task.setFormId(dataFillTask.getFormId());
task.setUser(id);
task.setStartTime(startTime);
task.setEndTime(endTime);
task.setValueId(valueId);
dataFillUserTaskMapper.insertSelective(task);
}
}
public List<DataFillUserTaskDTO> userTasks(Long userId, String type, DataFillUserTaskSearchRequest request) {
List<DataFillUserTaskDTO> list = new ArrayList<>();
String taskName = StringUtils.isNotBlank(request.getTaskName()) ? request.getTaskName() : null;
if (StringUtils.equalsIgnoreCase(type, "finished")) {
list = extDataFillFormMapper.listFinishedUserTask(userId, taskName);
} else if (StringUtils.equalsIgnoreCase(type, "expired")) {
list = extDataFillFormMapper.listExpiredUserTask(userId, new Date(), taskName);
} else {
list = extDataFillFormMapper.listTodoUserTask(userId, new Date(), taskName);
}
return list;
}
}

View File

@ -62,6 +62,18 @@ public class DeCatchProcess {
cleanCacheParent(resourceId.toString(), "link");
});
}
public void cleanDataFiling(Object pid) {
CurrentUserDto user = AuthUtils.getUser();
CacheUtils.remove(AuthConstants.USER_DATA_FILL_NAME, "user" + user.getUserId());
CacheUtils.remove(AuthConstants.DEPT_DATA_FILL_NAME, "dept" + user.getDeptId());
user.getRoles().forEach(role -> {
CacheUtils.remove(AuthConstants.ROLE_DATA_FILL_NAME, "role" + role.getId());
});
Optional.ofNullable(pid).ifPresent(resourceId -> {
cleanCacheParent(resourceId.toString(), "data_fill");
});
}
private void cleanCacheParent(String pid, String type) {
if (StringUtils.isBlank(pid) || StringUtils.isBlank(type)) {

View File

@ -11,6 +11,7 @@ import io.dataease.commons.utils.ServletUtils;
import io.dataease.controller.request.panel.link.*;
import io.dataease.dto.panel.PanelGroupDTO;
import io.dataease.dto.panel.link.GenerateDto;
import io.dataease.dto.panel.link.TicketDto;
import io.dataease.ext.ExtPanelGroupMapper;
import io.dataease.ext.ExtPanelLinkMapper;
import io.dataease.plugins.common.base.domain.*;
@ -128,13 +129,13 @@ public class PanelLinkService {
}
}
public String getMappingUuid(PanelLink link) {
public PanelLinkMapping getMapping(PanelLink link) {
String resourceId = link.getResourceId();
Long userId = link.getUserId();
PanelLinkMappingExample example = new PanelLinkMappingExample();
example.createCriteria().andResourceIdEqualTo(resourceId).andUserIdEqualTo(userId);
List<PanelLinkMapping> mappings = panelLinkMappingMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(mappings)) return mappings.get(0).getUuid();
if (CollectionUtils.isNotEmpty(mappings)) return mappings.get(0);
return null;
}
@ -291,8 +292,12 @@ public class PanelLinkService {
PanelLinkTicketExample example = new PanelLinkTicketExample();
example.createCriteria().andTicketEqualTo(ticket);
if (creator.isGenerateNew()) {
ticketEntity.setAccessTime(null);
ticketEntity.setTicket(CodingUtil.shortUuid());
}
ticketEntity.setArgs(creator.getArgs());
ticketEntity.setExp(creator.getExp());
ticketEntity.setUuid(creator.getUuid());
panelLinkTicketMapper.updateByExample(ticketEntity, example);
return ticketEntity.getTicket();
}
@ -317,7 +322,15 @@ public class PanelLinkService {
panelLinkTicketMapper.deleteByExample(example);
}
public void switchRequire(TicketSwitchRequest request) {
String resourceId = request.getResourceId();
Boolean require = request.getRequire();
PanelLinkMappingExample example = new PanelLinkMappingExample();
example.createCriteria().andResourceIdEqualTo(resourceId).andUserIdEqualTo(AuthUtils.getUser().getUserId());
PanelLinkMapping mapping = new PanelLinkMapping();
mapping.setRequireTicket(require);
panelLinkMappingMapper.updateByExampleSelective(mapping, example);
}
public PanelLinkTicket getByTicket(String ticket) {
PanelLinkTicketExample example = new PanelLinkTicketExample();
@ -354,4 +367,37 @@ public class PanelLinkService {
PanelLink one = findOne(resourceId, userId);
return convertDto(one, uuid, mapping.getRequireTicket()).getUri();
}
public TicketDto validateTicket(String ticket, PanelLinkMapping mapping) {
String uuid = mapping.getUuid();
TicketDto ticketDto = new TicketDto();
if (StringUtils.isBlank(ticket)) {
ticketDto.setTicketValid(!mapping.getRequireTicket());
return ticketDto;
}
PanelLinkTicketExample example = new PanelLinkTicketExample();
example.createCriteria().andTicketEqualTo(ticket).andUuidEqualTo(uuid);
List<PanelLinkTicket> tickets = panelLinkTicketMapper.selectByExample(example);
if (CollectionUtils.isEmpty(tickets)) {
ticketDto.setTicketValid(false);
return ticketDto;
}
PanelLinkTicket linkTicket = tickets.get(0);
ticketDto.setTicketValid(true);
ticketDto.setArgs(linkTicket.getArgs());
Long accessTime = linkTicket.getAccessTime();
long now = System.currentTimeMillis();
if (ObjectUtils.isEmpty(accessTime)) {
accessTime = now;
ticketDto.setTicketExp(false);
linkTicket.setAccessTime(accessTime);
panelLinkTicketMapper.updateByPrimaryKey(linkTicket);
return ticketDto;
}
Long exp = linkTicket.getExp();
long expTime = exp * 60L * 1000L;
long time = now - accessTime;
ticketDto.setTicketExp(time > expTime);
return ticketDto;
}
}

View File

@ -81,6 +81,7 @@ server.servlet.context-parameters.configurationStrategy=SYSTEM_PROPERTIES
server.servlet.session.cookie.http-only=true
server.servlet.session.tracking-modes=cookie
spring.jackson.parser.allow-numeric-leading-zeros=true
logging.level.org.apache.shiro=OFF

View File

@ -4,11 +4,12 @@
DROP TABLE IF EXISTS `panel_link_ticket`;
CREATE TABLE `panel_link_ticket`
(
`id` bigint NOT NULL AUTO_INCREMENT,
`uuid` varchar(255) NOT NULL,
`ticket` varchar(255) NOT NULL,
`exp` bigint DEFAULT NULL,
`args` varchar(255) DEFAULT NULL,
`id` bigint NOT NULL AUTO_INCREMENT,
`uuid` varchar(255) NOT NULL,
`ticket` varchar(255) NOT NULL,
`exp` bigint DEFAULT NULL,
`args` varchar(255) DEFAULT NULL,
`access_time` bigint DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1;

View File

@ -0,0 +1,310 @@
DROP TABLE IF EXISTS `data_fill_form`;
create table data_fill_form
(
id varchar(50) not null comment '主键ID'
primary key,
name varchar(255) null comment '名称',
pid varchar(255) null comment '父级ID',
level int(10) null comment '层级',
node_type varchar(255) null comment 'folder/panel 目录或文件夹',
table_name varchar(255) null comment '表名',
datasource varchar(255) null comment '数据源',
forms longtext null comment '表单内容',
create_index tinyint(1) default 0 null comment '是否创建索引',
table_indexes longtext null comment '索引',
create_by varchar(255) null comment '创建人',
create_time datetime default current_timestamp() null comment '创建时间',
update_by varchar(255) null comment '更新人',
update_time datetime default current_timestamp() null comment '更新时间'
)
comment '数据填报表单';
CREATE TRIGGER `delete_auth_data_fill_form`
AFTER DELETE
ON `data_fill_form`
FOR EACH ROW select delete_auth_source(OLD.id, 'data_fill')
into @ee;
DROP VIEW IF EXISTS `v_auth_model`;
CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW `v_auth_model` AS
SELECT `sys_user`.`user_id` AS `id`,
concat(`sys_user`.`nick_name`, '', `sys_user`.`username`, '') AS `name`,
`sys_user`.`username` AS `label`,
'0' AS `pid`,
'leaf' AS `node_type`,
'user' AS `model_type`,
'user' AS `model_inner_type`,
'target' AS `auth_type`,
`sys_user`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM `sys_user`
WHERE (`sys_user`.`is_admin` <> 1)
UNION ALL
SELECT `sys_role`.`role_id` AS `id`,
`sys_role`.`name` AS `name`,
`sys_role`.`name` AS `label`,
'0' AS `pid`,
'leaf' AS `node_type`,
'role' AS `model_type`,
'role' AS `model_inner_type`,
'target' AS `auth_type`,
`sys_role`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM `sys_role`
UNION ALL
SELECT `sys_dept`.`dept_id` AS `id`,
`sys_dept`.`name` AS `name`,
`sys_dept`.`name` AS `label`,
(
cast(`sys_dept`.`pid` AS CHAR charset utf8mb4) COLLATE utf8mb4_general_ci
) AS `pid`,
IF
((`sys_dept`.`sub_count` = 0), 'leaf', 'spine') AS `node_type`,
'dept' AS `model_type`,
'dept' AS `model_inner_type`,
'target' AS `auth_type`,
`sys_dept`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM `sys_dept`
UNION ALL
SELECT `datasource`.`id` AS `id`,
`datasource`.`name` AS `NAME`,
`datasource`.`name` AS `label`,
'0' AS `pid`,
'leaf' AS `node_type`,
'link' AS `model_type`,
`datasource`.`type` AS `model_inner_type`,
'source' AS `auth_type`,
`datasource`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM `datasource`
UNION ALL
SELECT `dataset_group`.`id` AS `id`,
`dataset_group`.`name` AS `NAME`,
`dataset_group`.`name` AS `label`,
IF
(isnull(`dataset_group`.`pid`), '0', `dataset_group`.`pid`) AS `pid`,
'spine' AS `node_type`,
'dataset' AS `model_type`,
`dataset_group`.`type` AS `model_inner_type`,
'source' AS `auth_type`,
`dataset_group`.`create_by` AS `create_by`,
`dataset_group`.`level` AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM `dataset_group`
UNION ALL
SELECT `data_fill_form`.`id` AS `id`,
`data_fill_form`.`name` AS `NAME`,
`data_fill_form`.`name` AS `label`,
(
CASE
`data_fill_form`.`id`
WHEN 'data_fill_list' THEN
'0'
WHEN 'default_data_fill' THEN
'0'
ELSE `data_fill_form`.`pid`
END
) AS `pid`,
IF
((`data_fill_form`.`node_type` = 'folder'), 'spine', 'leaf') AS `node_type`,
'data_fill' AS `model_type`,
'form' AS `model_inner_type`,
'source' AS `auth_type`,
`data_fill_form`.`create_by` AS `create_by`,
`data_fill_form`.`level` AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM `data_fill_form`
UNION ALL
SELECT `dataset_table`.`id` AS `id`,
`dataset_table`.`name` AS `NAME`,
`dataset_table`.`name` AS `label`,
`dataset_table`.`scene_id` AS `pid`,
'leaf' AS `node_type`,
'dataset' AS `model_type`,
`dataset_table`.`type` AS `model_inner_type`,
'source' AS `auth_type`,
`dataset_table`.`create_by` AS `create_by`,
0 AS `level`,
`dataset_table`.`mode` AS `mode`,
`dataset_table`.`data_source_id` AS `data_source_id`
FROM `dataset_table`
UNION ALL
SELECT `panel_group`.`id` AS `id`,
`panel_group`.`name` AS `NAME`,
`panel_group`.`name` AS `label`,
(
CASE
`panel_group`.`id`
WHEN 'panel_list' THEN
'0'
WHEN 'default_panel' THEN
'0'
ELSE `panel_group`.`pid`
END
) AS `pid`,
IF
((`panel_group`.`node_type` = 'folder'), 'spine', 'leaf') AS `node_type`,
'panel' AS `model_type`,
`panel_group`.`panel_type` AS `model_inner_type`,
'source' AS `auth_type`,
`panel_group`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM `panel_group`
UNION ALL
SELECT `sys_menu`.`menu_id` AS `menu_id`,
`sys_menu`.`title` AS `name`,
`sys_menu`.`title` AS `label`,
`sys_menu`.`pid` AS `pid`,
IF
((`sys_menu`.`sub_count` > 0), 'spine', 'leaf') AS `node_type`,
'menu' AS `model_type`,
(
CASE
`sys_menu`.`type`
WHEN 0 THEN
'folder'
WHEN 1 THEN
'menu'
WHEN 2 THEN
'button'
END
) AS `model_inner_type`,
'source' AS `auth_type`,
`sys_menu`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM `sys_menu`
WHERE ((
`sys_menu`.`i_frame` <> 1
)
OR isnull(`sys_menu`.`i_frame`))
UNION ALL
SELECT `plugin_sys_menu`.`menu_id` AS `menu_id`,
`plugin_sys_menu`.`title` AS `name`,
`plugin_sys_menu`.`title` AS `label`,
`plugin_sys_menu`.`pid` AS `pid`,
IF
((`plugin_sys_menu`.`sub_count` > 0), 'spine', 'leaf') AS `node_type`,
'menu' AS `model_type`,
(
CASE
`plugin_sys_menu`.`type`
WHEN 0 THEN
'folder'
WHEN 1 THEN
'menu'
WHEN 2 THEN
'button'
END
) AS `model_inner_type`,
'source' AS `auth_type`,
`plugin_sys_menu`.`create_by` AS `create_by`,
0 AS `level`,
0 AS `mode`,
'0' AS `data_source_id`
FROM `plugin_sys_menu`
WHERE ((
`plugin_sys_menu`.`i_frame` <> 1
)
OR isnull(`plugin_sys_menu`.`i_frame`));
INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`,
`privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`,
`copy_id`)
VALUES ('data_fill_grant', 'data_fill', 'i18n_auth_grant', 15, 0, 'grant', '基础权限-授权', 'system', NULL, NULL, NULL,
NULL);
INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`,
`privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`,
`copy_id`)
VALUES ('data_fill_manage', 'data_fill', 'i18n_auth_manage', 3, 0, 'manage', '基础权限-管理', 'system', NULL, NULL,
NULL, NULL);
INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`,
`privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`,
`copy_id`)
VALUES ('data_fill_use', 'data_fill', 'i18n_auth_use', 1, 0, 'use', '基础权限-使用', 'system', NULL, NULL, NULL, NULL);
DROP TABLE IF EXISTS `data_fill_commit_log`;
create table data_fill_commit_log
(
id varchar(50) not null
primary key,
form_id varchar(50) not null,
data_id varchar(255) null,
operate varchar(50) not null,
commit_by varchar(255) not null,
commit_time datetime default current_timestamp() null
);
create index data_fill_commit_log_form_id_index
on data_fill_commit_log (form_id);
DROP TABLE IF EXISTS `data_fill_task`;
create table data_fill_task
(
id bigint auto_increment comment '任务ID'
primary key,
name varchar(255) not null comment '任务名称',
form_id varchar(100) not null comment '任务ID',
start_time datetime null comment '开始时间',
end_time datetime null comment '结束时间',
rate_type int(10) not null comment '频率方式',
rate_val varchar(255) null comment '频率值',
publish_start_time datetime null,
publish_end_time datetime null,
publish_range_time_type int null,
publish_range_time int null,
creator bigint not null comment '创建者ID',
create_time datetime default current_timestamp() null comment '创建时间',
status tinyint(1) default 1 null comment '运行状态',
reci_users longtext null comment '接收人账号',
role_list longtext null comment '收件角色',
org_list longtext null comment '收件组织'
)
comment '数据填报任务';
create index data_fill_task_form_id_index
on data_fill_task (form_id);
DROP TABLE IF EXISTS `data_fill_user_task`;
create table data_fill_user_task
(
id varchar(50) not null comment 'ID'
primary key,
task_id bigint not null comment '任务ID',
form_id varchar(100) not null comment '表单ID',
value_id varchar(100) null comment '表内值ID',
user bigint not null comment '用户ID',
start_time datetime null comment '开始时间',
end_time datetime null comment '结束时间',
finish_time datetime null comment '完成时间'
)
comment '数据填报用户任务';
create index data_fill_user_task_form_id_index
on data_fill_user_task (form_id);
create index data_fill_user_task_task_id_index
on data_fill_user_task (task_id);

View File

@ -173,6 +173,7 @@ SOURCE_TYPE_DRIVER_FILE=DRIVER FILE
SOURCE_TYPE_MENU=MENU
SOURCE_TYPE_LINK=PUBLIC LINK
SOURCE_TYPE_APIKEY=APIKEY
SOURCE_TYPE_DATA_FILL_FORM=DATA FILL FORM
I18N_OPERATE_TYPE=Operation type
I18N_DETAIL=Operation details
I18N_USER=Operator
@ -237,6 +238,7 @@ I18N_DS_INVALID=Datasource is invalid
I18N_DS_INVALID_TABLE=Datasource has invalid tables
I18N_ACCOUNT_LOCKED=Account\u3010%s\u3011is locked(Please contact the administrator to unlock or try again in %s minutes)
I18N_PANEL_EXIST=The current panel name already exists under this directory
I18N_DATA_FILL_FORM_EXIST=The current data filling form name already exists under this directory
I18N_FOlDER_EXIST=The name already exists under this directory
I18N_DATASET_GROUP_EXIST=The current dataset grouping name already exists under this directory
I18N_NOT_JAR=File is not jar!

View File

@ -94,7 +94,7 @@ i18n_sql_delete_not_matching=\u589E\u91CF\u5220\u9664 SQL \u7684\u6570\u636E\u52
i18n_cst_ds_tb_or_field_deleted=\u81EA\u5B9A\u4E49\u6570\u636E\u96C6\u6240\u5173\u8054\u6570\u636E\u88AB\u5220\u9664\u6216\u5B57\u6BB5\u53D1\u751F\u53D8\u5316\uFF0C\u65E0\u6CD5\u6B63\u5E38\u663E\u793A
i18n_no_all_delete_privilege_folder=\u8BE5\u76EE\u5F55\u4E0B\u5B58\u5728\u6CA1\u6709\u7BA1\u7406\u6743\u9650\u6216\u67E5\u770B\u6743\u9650\u7684\u8D44\u6E90\uFF0C\u65E0\u6CD5\u5220\u9664
i18n_excel_field_repeat=\u5B58\u5728\u91CD\u590D\u5B57\u6BB5\uFF1A
i18n_dont_contain_key=\u5f53\u524d\u7684sql\u4e0d\u5305\u542b\u8fd9\u4e2a\u952e\uff1a
i18n_dont_contain_key=\u5F53\u524D\u7684sql\u4E0D\u5305\u542B\u8FD9\u4E2A\u952E\uFF1A
i18n_schema_is_empty=\u6570\u636E\u5E93 Schema \u4E3A\u7A7A
\u7AD9\u5185\u6D88\u606F=\u6D88\u606F\u4E2D\u5FC3
\u6240\u6709\u6D88\u606F=\u6240\u6709\u6D88\u606F
@ -173,6 +173,7 @@ SOURCE_TYPE_DRIVER_FILE=\u9A71\u52A8\u6587\u4EF6
SOURCE_TYPE_MENU=\u83DC\u5355
SOURCE_TYPE_LINK=\u516C\u5171\u94FE\u63A5
SOURCE_TYPE_APIKEY=APIKEY
SOURCE_TYPE_DATA_FILL_FORM=\u6570\u636E\u586B\u62A5\u8868\u5355
I18N_OPERATE_TYPE=\u64CD\u4F5C\u7C7B\u578B
I18N_DETAIL=\u64CD\u4F5C\u8BE6\u60C5
I18N_USER=\u64CD\u4F5C\u4EBA
@ -237,6 +238,7 @@ I18N_DS_INVALID=\u6570\u636E\u6E90\u65E0\u6548
I18N_DS_INVALID_TABLE=\u6570\u636E\u6E90\u4E2D\u6709\u65E0\u6548\u7684\u8868
I18N_ACCOUNT_LOCKED=\u8D26\u53F7\u3010%s\u3011\u5DF2\u9501\u5B9A(\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u89E3\u9501\u6216%s\u5206\u949F\u540E\u91CD\u8BD5)
I18N_PANEL_EXIST=\u5F53\u524D\u4EEA\u8868\u677F\u540D\u79F0\u5728\u8BE5\u76EE\u5F55\u4E0B\u9762\u5DF2\u7ECF\u5B58\u5728
I18N_DATA_FILL_FORM_EXIST=\u5F53\u524D\u6570\u636E\u586B\u62A5\u8868\u5355\u540D\u79F0\u5728\u8BE5\u76EE\u5F55\u4E0B\u9762\u5DF2\u7ECF\u5B58\u5728
I18N_FOlDER_EXIST=\u5F53\u524D\u540D\u79F0\u5728\u8BE5\u76EE\u5F55\u4E0B\u9762\u5DF2\u7ECF\u5B58\u5728
I18N_DATASET_GROUP_EXIST=\u5F53\u524D\u6570\u636E\u96C6\u5206\u7EC4\u540D\u79F0\u5728\u8BE5\u76EE\u5F55\u4E0B\u9762\u5DF2\u7ECF\u5B58\u5728
I18N_NOT_JAR=\u6587\u4EF6\u4E0D\u662F jar \u5305!
@ -268,6 +270,6 @@ I18N_PANEL_PDF_TEMPLATE_WITH_PARAMS=\u9ED8\u8BA4\u6A21\u677F(\u52A0\u4EEA\u8868\
I18N_PANEL_PDF_TEMPLATE_ONLY_PIC=\u9ED8\u8BA4\u6A21\u677F(\u53EA\u622A\u56FE)
I18n_name_cant_empty=\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A\uFF01
I18n_del_admin_tips=\u7981\u6B62\u5220\u9664admin\u8D26\u53F7
I18N_NO_DRIVER_PERMISSION=\u6ca1\u6709\u6743\u9650\uff01
I18N_NO_DRIVER_PERMISSION=\u6CA1\u6709\u6743\u9650\uFF01
i18n_field_circular_error=\u5B57\u6BB5\u89E3\u6790\u9519\u8BEF\uFF0C\u53EF\u80FD\u539F\u56E0\uFF1A\u5B57\u6BB5\u5DF2\u5220\u9664\u3001\u8BA1\u7B97\u5B57\u6BB5\u5F15\u7528\u5C42\u7EA7\u8FC7\u6DF1\u3001\u5B58\u5728\u5FAA\u73AF\u5F15\u7528\u7B49\uFF0C\u8BF7\u68C0\u67E5\u8868\u8282\u70B9\u548C\u5B57\u6BB5\u5E76\u91CD\u65B0\u7F16\u8F91\u3002
i18n_field_circular_ref=\u5B57\u6BB5\u5B58\u5728\u5FAA\u73AF\u5F15\u7528

View File

@ -94,7 +94,7 @@ i18n_sql_delete_not_matching=\u589E\u91CF\u522A\u9664 sql \u7684\u6578\u64DA\u52
i18n_cst_ds_tb_or_field_deleted=\u81EA\u5B9A\u7FA9\u6578\u64DA\u96C6\u6240\u95DC\u806F\u6578\u64DA\u88AB\u522A\u9664\u6216\u5B57\u6BB5\u767C\u751F\u8B8A\u5316\uFF0C\u7121\u6CD5\u6B63\u5E38\u986F\u793A
i18n_no_all_delete_privilege_folder=\u8A72\u76EE\u9304\u4E0B\u5B58\u5728\u6C92\u6709\u7BA1\u7406\u6B0A\u9650\u6216\u67E5\u770B\u6B0A\u9650\u7684\u8CC7\u6E90\uFF0C\u7121\u6CD5\u522A\u9664
i18n_excel_field_repeat=\u5B58\u5728\u91CD\u5FA9\u5B57\u6BB5\uFF1A
i18n_dont_contain_key=\u7576\u524d\u7684sql\u4e0d\u5305\u542b\u9019\u500b\u9375\uff1a
i18n_dont_contain_key=\u7576\u524D\u7684sql\u4E0D\u5305\u542B\u9019\u500B\u9375\uFF1A
i18n_schema_is_empty=\u6578\u64DA\u5EAB Schema \u70BA\u7A7A
\u7AD9\u5185\u6D88\u606F=\u6D88\u606F\u4E2D\u5FC3
\u6240\u6709\u6D88\u606F=\u6240\u6709\u6D88\u606F
@ -173,6 +173,7 @@ SOURCE_TYPE_DRIVER_FILE=\u9A45\u52D5\u6587\u4EF6
SOURCE_TYPE_MENU=\u83DC\u55AE
SOURCE_TYPE_LINK=\u516C\u5171\u93C8\u63A5
SOURCE_TYPE_APIKEY=APIKEY
SOURCE_TYPE_DATA_FILL_FORM=\u6578\u64DA\u586B\u5831\u8868\u55AE
I18N_DRIVER_NOT_DELETE=\u4F7F\u7528\u4E2D\u7684\u9A45\u52D5\u4E0D\u5141\u8A31\u5220\u9664
I18N_DRIVER_REPEAT_NAME=\u540D\u7A31\u91CD\u8907
I18N_DRIVER_NOT_FOUND=\u672A\u627E\u5230\u9A45\u52D5
@ -233,6 +234,7 @@ I18N_DS_INVALID=\u6578\u64DA\u6E90\u7121\u6548
I18N_DS_INVALID_TABLE=\u6578\u64DA\u6E90\u4E2D\u6709\u7121\u6548\u7684\u8868
I18N_ACCOUNT_LOCKED=\u8CEC\u865F\u3010%s\u3011\u5DF2\u9396\u5B9A(\u8ACB\u806F\u7CFB\u7BA1\u7406\u54E1\u89E3\u9396\u6216%s\u5206\u9418\u5F8C\u91CD\u8A66)
I18N_PANEL_EXIST=\u7576\u524D\u5100\u9336\u95C6\u540D\u7A31\u5728\u8A72\u76EE\u9304\u4E0B\u9762\u5DF2\u7D93\u5B58\u5728
I18N_DATA_FILL_FORM_EXIST=\u7576\u524D\u6578\u64DA\u586B\u5831\u8868\u55AE\u540D\u7A31\u5728\u8A72\u76EE\u9304\u4E0B\u9762\u5DF2\u7D93\u5B58\u5728
I18N_FOlDER_EXIST=\u540D\u7A31\u5728\u8A72\u76EE\u9304\u4E0B\u9762\u5DF2\u7D93\u5B58\u5728
I18N_DATASET_GROUP_EXIST=\u7576\u524D\u6578\u64DA\u96C6\u5206\u7D44\u540D\u7A31\u5728\u8A72\u76EE\u9304\u4E0B\u9762\u5DF2\u7D93\u5B58\u5728
I18N_NOT_JAR=\u6587\u4EF6\u4E0D\u662F jar \u5305!
@ -274,6 +276,6 @@ I18N_PANEL_PDF_TEMPLATE_ONLY_PIC=\u9ED8\u8A8D\u6A21\u677F(\u53EA\u622A\u5716)
\u8FB9\u684610=\u908A\u6846 10
I18n_name_cant_empty=\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A\uFF01
I18n_del_admin_tips=\u7981\u6B62\u522A\u9664admin\u8CEC\u865F
I18N_NO_DRIVER_PERMISSION=\u6c92\u6709\u8a31\u53ef\u6b0a\uff01
I18N_NO_DRIVER_PERMISSION=\u6C92\u6709\u8A31\u53EF\u6B0A\uFF01
i18n_field_circular_error=\u5B57\u6BB5\u89E3\u6790\u932F\u8AA4\uFF0C\u53EF\u80FD\u539F\u56E0\uFF1A\u5B57\u6BB5\u5DF2\u522A\u9664\u3001\u8A08\u7B97\u5B57\u6BB5\u5F15\u7528\u5C64\u7D1A\u904E\u6DF1\u3001\u5B58\u5728\u5FAA\u74B0\u5F15\u7528\u7B49\uFF0C\u8ACB\u6AA2\u67E5\u8868\u7BC0\u9EDE\u548C\u5B57\u6BB5\u4E26\u91CD\u65B0\u7DE8\u8F2F\u3002
i18n_field_circular_ref=\u5B57\u6BB5\u5B58\u5728\u5FAA\u74B0\u5F15\u7528

View File

@ -74,6 +74,7 @@
"svgo": "1.2.2",
"tinymce": "^5.8.2",
"umy-ui": "^1.1.6",
"uuid": "^9.0.1",
"vant": "^2.13.2",
"vue": "2.6.10",
"vue-clipboard2": "0.3.1",

View File

@ -34,6 +34,7 @@
const terminal = getQueryVariable('terminal')
const attachParams = getQueryVariable('attachParams')
const fromLink = getQueryVariable('fromLink')
const ticket = getQueryVariable('ticket')
const baseUrl = window.location.pathname.replace('link.html', '')
let url = baseUrl + "#/delink?link=" + encodeURIComponent(link)
if (terminal) {
@ -48,6 +49,9 @@
if (fromLink) {
url += '&fromLink=' + fromLink
}
if (ticket) {
url += '&ticket=' + ticket
}
window.location.href = url
</script>

View File

@ -50,6 +50,14 @@ export function switchEnablePwd(data) {
})
}
export function switchEnableTicket(data) {
return request({
url: 'api/link/enableTicket',
method: 'post',
data
})
}
export function viewLinkLog(data) {
return request({
url: 'api/link/viewLog',

View File

@ -313,7 +313,7 @@ export default {
scaleWidth: '100',
scaleHeight: '100',
timer: null,
componentDataShow: null,
componentDataShow: [],
mainWidth: '100%',
mainHeight: '100%',
searchCount: 0,

View File

@ -946,6 +946,7 @@ export default {
}
if (this.isFirstLoad) {
this.element.filters = this.filter.filter?.length ? JSON.parse(JSON.stringify(this.filter.filter)) : []
this.$store.commit('setViewInitFilter', this.element)
}
method(id, this.panelInfo.id, requestInfo).then(response => {
try {

View File

@ -0,0 +1,3 @@
<svg width="12" height="14" viewBox="0 0 12 14" fill="" xmlns="http://www.w3.org/2000/svg">
<path d="M1.33333 4.33334V12.3333H8V4.33334H1.33333ZM9.33333 3.66668V13.0741C9.33333 13.4014 9.05476 13.6667 8.71111 13.6667H0.622222C0.278578 13.6667 0 13.4014 0 13.0741V3.5926C0 3.26532 0.278578 3.00001 0.622222 3.00001H8.66667C9.03486 3.00001 9.33333 3.29849 9.33333 3.66668ZM11.8047 0.528606C11.9254 0.649249 12 0.815915 12 1.00001V9.33334C12 9.51744 11.8508 9.66668 11.6667 9.66668H11C10.8159 9.66668 10.6667 9.51744 10.6667 9.33334V1.66668H4.33333C4.14924 1.66668 4 1.51744 4 1.33334V0.666677C4 0.482582 4.14924 0.333344 4.33333 0.333344H11.3333C11.5174 0.333344 11.6841 0.407963 11.8047 0.528606Z" fill=""/>
</svg>

After

Width:  |  Height:  |  Size: 714 B

View File

@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="" xmlns="http://www.w3.org/2000/svg">
<path d="M8.00008 3.66667C8.46031 3.66667 8.83341 4.03977 8.83341 4.5C8.83341 4.96023 8.46031 5.33333 8.00008 5.33333C7.53985 5.33333 7.16675 4.96023 7.16675 4.5C7.16675 4.03977 7.53985 3.66667 8.00008 3.66667Z" fill=""/>
<path d="M8.16675 6H7.33341C7.05727 6 6.83341 6.22386 6.83341 6.5V6.83333C6.83341 7.10948 7.05727 7.33333 7.33341 7.33333H7.50008V10.6667H6.83341C6.55727 10.6667 6.33341 10.8905 6.33341 11.1667V11.5C6.33341 11.7761 6.55727 12 6.83341 12H9.50008C9.77622 12 10.0001 11.7761 10.0001 11.5V11.1667C10.0001 10.8905 9.77622 10.6667 9.50008 10.6667H8.83341V6.66667C8.83341 6.29848 8.53494 6 8.16675 6Z" fill=""/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.00008 15.3332C3.95008 15.3332 0.666748 12.0498 0.666748 7.99984C0.666748 3.94984 3.95008 0.666504 8.00008 0.666504C12.0501 0.666504 15.3334 3.94984 15.3334 7.99984C15.3334 12.0498 12.0501 15.3332 8.00008 15.3332ZM8.00008 13.9998C11.3138 13.9998 14.0001 11.3135 14.0001 7.99984C14.0001 4.68617 11.3138 1.99984 8.00008 1.99984C4.68642 1.99984 2.00008 4.68617 2.00008 7.99984C2.00008 11.3135 4.68642 13.9998 8.00008 13.9998Z" fill=""/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,4 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.83301 1.33398C5.10915 1.33398 5.33301 1.55784 5.33301 1.83398V2.00065H10.6663V1.83398C10.6663 1.55784 10.8902 1.33398 11.1663 1.33398H11.4997C11.7758 1.33398 11.9997 1.55784 11.9997 1.83398V2.00065H13.9997C14.3679 2.00065 14.6663 2.29913 14.6663 2.66732V14.0007C14.6663 14.3688 14.3679 14.6673 13.9997 14.6673H1.99967C1.63148 14.6673 1.33301 14.3688 1.33301 14.0007L1.33301 2.66732C1.33301 2.29913 1.63148 2.00065 1.99967 2.00065H3.99967V1.83398C3.99967 1.55784 4.22353 1.33398 4.49967 1.33398H4.83301ZM10.6663 3.33398H5.33301V3.50065C5.33301 3.77679 5.10915 4.00065 4.83301 4.00065H4.49967C4.22353 4.00065 3.99967 3.77679 3.99967 3.50065V3.33398H2.66634V13.334H13.333V3.33398H11.9997V3.50065C11.9997 3.77679 11.7758 4.00065 11.4997 4.00065H11.1663C10.8902 4.00065 10.6663 3.77679 10.6663 3.50065V3.33398ZM5.99967 6.83398C5.99967 6.55784 5.77582 6.33398 5.49967 6.33398H4.49967C4.22353 6.33398 3.99967 6.55784 3.99967 6.83398V7.83398C3.99967 8.11013 4.22353 8.33398 4.49967 8.33398H5.49967C5.77582 8.33398 5.99967 8.11013 5.99967 7.83398V6.83398ZM6.99967 6.83398C6.99967 6.55784 7.22353 6.33398 7.49967 6.33398H8.49967C8.77582 6.33398 8.99967 6.55784 8.99967 6.83398V7.83398C8.99967 8.11013 8.77582 8.33398 8.49967 8.33398H7.49967C7.22353 8.33398 6.99967 8.11013 6.99967 7.83398V6.83398ZM5.99967 9.83398C5.99967 9.55784 5.77582 9.33398 5.49967 9.33398H4.49967C4.22353 9.33398 3.99967 9.55784 3.99967 9.83398V10.834C3.99967 11.1101 4.22353 11.334 4.49967 11.334H5.49967C5.77582 11.334 5.99967 11.1101 5.99967 10.834V9.83398ZM6.99967 9.83398C6.99967 9.55784 7.22353 9.33398 7.49967 9.33398H8.49967C8.77582 9.33398 8.99967 9.55784 8.99967 9.83398V10.834C8.99967 11.1101 8.77582 11.334 8.49967 11.334H7.49967C7.22353 11.334 6.99967 11.1101 6.99967 10.834V9.83398ZM11.9997 6.83398C11.9997 6.55784 11.7758 6.33398 11.4997 6.33398H10.4997C10.2235 6.33398 9.99967 6.55784 9.99967 6.83398V7.83398C9.99967 8.11013 10.2235 8.33398 10.4997 8.33398H11.4997C11.7758 8.33398 11.9997 8.11013 11.9997 7.83398V6.83398Z" fill="#646A73"/>
<path d="M11.9997 9.83398C11.9997 9.55784 11.7758 9.33398 11.4997 9.33398H10.4997C10.2235 9.33398 9.99967 9.55784 9.99967 9.83398V10.834C9.99967 11.1101 10.2235 11.334 10.4997 11.334H11.4997C11.7758 11.334 11.9997 11.1101 11.9997 10.834V9.83398Z" fill="#646A73"/>
<path d="M4.83334 1.33301C5.10949 1.33301 5.33334 1.55687 5.33334 1.83301V1.99967H10.6667V1.83301C10.6667 1.55687 10.8905 1.33301 11.1667 1.33301H11.5C11.7762 1.33301 12 1.55687 12 1.83301V1.99967H14C14.3682 1.99967 14.6667 2.29815 14.6667 2.66634V13.9997C14.6667 14.3679 14.3682 14.6663 14 14.6663H2.00001C1.63182 14.6663 1.33334 14.3679 1.33334 13.9997L1.33334 2.66634C1.33334 2.29815 1.63182 1.99967 2.00001 1.99967H4.00001V1.83301C4.00001 1.55687 4.22387 1.33301 4.50001 1.33301H4.83334ZM10.6667 3.33301H5.33334V3.49967C5.33334 3.77582 5.10949 3.99967 4.83334 3.99967H4.50001C4.22387 3.99967 4.00001 3.77582 4.00001 3.49967V3.33301H2.66668V13.333H13.3333V3.33301H12V3.49967C12 3.77582 11.7762 3.99967 11.5 3.99967H11.1667C10.8905 3.99967 10.6667 3.77582 10.6667 3.49967V3.33301ZM6.00001 6.83301C6.00001 6.55687 5.77615 6.33301 5.50001 6.33301H4.50001C4.22387 6.33301 4.00001 6.55687 4.00001 6.83301V7.83301C4.00001 8.10915 4.22387 8.33301 4.50001 8.33301H5.50001C5.77615 8.33301 6.00001 8.10915 6.00001 7.83301V6.83301ZM7.00001 6.83301C7.00001 6.55687 7.22387 6.33301 7.50001 6.33301H8.50001C8.77615 6.33301 9.00001 6.55687 9.00001 6.83301V7.83301C9.00001 8.10915 8.77615 8.33301 8.50001 8.33301H7.50001C7.22387 8.33301 7.00001 8.10915 7.00001 7.83301V6.83301ZM6.00001 9.83301C6.00001 9.55687 5.77615 9.33301 5.50001 9.33301H4.50001C4.22387 9.33301 4.00001 9.55687 4.00001 9.83301V10.833C4.00001 11.1092 4.22387 11.333 4.50001 11.333H5.50001C5.77615 11.333 6.00001 11.1092 6.00001 10.833V9.83301ZM7.00001 9.83301C7.00001 9.55687 7.22387 9.33301 7.50001 9.33301H8.50001C8.77615 9.33301 9.00001 9.55687 9.00001 9.83301V10.833C9.00001 11.1092 8.77615 11.333 8.50001 11.333H7.50001C7.22387 11.333 7.00001 11.1092 7.00001 10.833V9.83301ZM12 6.83301C12 6.55687 11.7762 6.33301 11.5 6.33301H10.5C10.2239 6.33301 10 6.55687 10 6.83301V7.83301C10 8.10915 10.2239 8.33301 10.5 8.33301H11.5C11.7762 8.33301 12 8.10915 12 7.83301V6.83301Z" fill="#646A73"/>
<path d="M12 9.83301C12 9.55687 11.7762 9.33301 11.5 9.33301H10.5C10.2239 9.33301 10 9.55687 10 9.83301V10.833C10 11.1092 10.2239 11.333 10.5 11.333H11.5C11.7762 11.333 12 11.1092 12 10.833V9.83301Z" fill="#646A73"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.33333 5.33301V13.333H10V5.33301H3.33333ZM11.3333 4.66634V14.0737C11.3333 14.401 11.0548 14.6663 10.7111 14.6663H2.62222C2.27858 14.6663 2 14.401 2 14.0737V4.59227C2 4.26499 2.27858 3.99967 2.62222 3.99967H10.6667C11.0349 3.99967 11.3333 4.29815 11.3333 4.66634ZM13.8047 1.52827C13.9254 1.64891 14 1.81558 14 1.99967V10.333C14 10.5171 13.8508 10.6663 13.6667 10.6663H13C12.8159 10.6663 12.6667 10.5171 12.6667 10.333V2.66634H6.33333C6.14924 2.66634 6 2.5171 6 2.33301V1.66634C6 1.48225 6.14924 1.33301 6.33333 1.33301H13.3333C13.5174 1.33301 13.6841 1.40763 13.8047 1.52827Z" fill="#646A73"/>
</svg>

After

Width:  |  Height:  |  Size: 707 B

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.3335 2.66634V1.99967C5.3335 1.63148 5.63197 1.33301 6.00016 1.33301H10.0002C10.3684 1.33301 10.6668 1.63148 10.6668 1.99967V2.66634H14.2395C14.3881 2.66634 14.442 2.68181 14.4963 2.71086C14.5506 2.73991 14.5933 2.78255 14.6223 2.83687C14.6514 2.89119 14.6668 2.94507 14.6668 3.09366V3.57236C14.6668 3.72095 14.6514 3.77483 14.6223 3.82915C14.5933 3.88347 14.5506 3.9261 14.4963 3.95515C14.442 3.9842 14.3881 3.99967 14.2395 3.99967H13.3335V13.9997C13.3335 14.3679 13.035 14.6663 12.6668 14.6663H3.3335C2.96531 14.6663 2.66683 14.3679 2.66683 13.9997V3.99967H1.76081C1.61222 3.99967 1.55834 3.9842 1.50402 3.95515C1.4497 3.9261 1.40707 3.88347 1.37802 3.82915C1.34897 3.77483 1.3335 3.72095 1.3335 3.57236V3.09366C1.3335 2.94507 1.34897 2.89119 1.37802 2.83687C1.40707 2.78255 1.4497 2.73991 1.50402 2.71086C1.55834 2.68181 1.61222 2.66634 1.76081 2.66634H5.3335ZM4.00016 3.99967V13.333H12.0002V3.99967H4.00016ZM6.3335 5.33301H7.00016C7.18426 5.33301 7.3335 5.48225 7.3335 5.66634V11.6663C7.3335 11.8504 7.18426 11.9997 7.00016 11.9997H6.3335C6.1494 11.9997 6.00016 11.8504 6.00016 11.6663V5.66634C6.00016 5.48225 6.1494 5.33301 6.3335 5.33301ZM9.00016 5.33301H9.66683C9.85092 5.33301 10.0002 5.48225 10.0002 5.66634V11.6663C10.0002 11.8504 9.85092 11.9997 9.66683 11.9997H9.00016C8.81607 11.9997 8.66683 11.8504 8.66683 11.6663V5.66634C8.66683 5.48225 8.81607 5.33301 9.00016 5.33301Z" fill="#646A73"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.99998 10.5764L13.4211 5.15525C13.5513 5.02507 13.7624 5.02507 13.8925 5.15525L14.3639 5.62665C14.4941 5.75683 14.4941 5.96788 14.3639 6.09806L8.47139 11.9906C8.21104 12.251 7.78893 12.251 7.52858 11.9906L1.63602 6.09806C1.50585 5.96788 1.50585 5.75683 1.63602 5.62665L2.10743 5.15525C2.2376 5.02507 2.44866 5.02507 2.57883 5.15525L7.99998 10.5764Z" fill="#646A73"/>
</svg>

After

Width:  |  Height:  |  Size: 481 B

View File

@ -0,0 +1,11 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_8693_7580)">
<path d="M1.33332 2H14.6667C15.0348 2 15.3333 2.29848 15.3333 2.66667V13.3333C15.3333 13.7015 15.0348 14 14.6667 14H1.33332C0.965133 14 0.666656 13.7015 0.666656 13.3333V2.66667C0.666656 2.29848 0.965133 2 1.33332 2ZM1.99999 3.33333V12.6667H14V3.33333H1.99999Z" fill="#646A73"/>
<path d="M4.66667 5.02255C4.66667 4.82618 4.50748 4.66699 4.31112 4.66699H3.68889C3.49253 4.66699 3.33334 4.82618 3.33334 5.02255L3.33325 7.00033C3.33325 7.19669 3.49244 7.35588 3.68881 7.35588H4.31103C4.5074 7.35588 4.66659 7.19669 4.66659 7.00033L4.66667 5.02255Z" fill="#646A73"/>
</g>
<defs>
<clipPath id="clip0_8693_7580">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 812 B

View File

@ -0,0 +1,11 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_8693_4607)">
<path d="M7.99999 15.3337C12.0501 15.3337 15.3333 12.0504 15.3333 8.00033C15.3333 3.95024 12.0501 0.666992 7.99999 0.666992C3.9499 0.666992 0.666656 3.95024 0.666656 8.00033C0.666656 12.0504 3.9499 15.3337 7.99999 15.3337ZM7.99999 14.0003C4.68628 14.0003 1.99999 11.314 1.99999 8.00033C1.99999 4.68662 4.68628 2.00033 7.99999 2.00033C11.3137 2.00033 14 4.68662 14 8.00033C14 11.314 11.3137 14.0003 7.99999 14.0003Z" fill="#646A73"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.00001 10.6663C9.47277 10.6663 10.6667 9.47243 10.6667 7.99967C10.6667 6.52692 9.47277 5.33301 8.00001 5.33301C6.52725 5.33301 5.33334 6.52692 5.33334 7.99967C5.33334 9.47243 6.52725 10.6663 8.00001 10.6663Z" fill="#646A73"/>
</g>
<defs>
<clipPath id="clip0_8693_4607">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 959 B

View File

@ -0,0 +1,11 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_8096_189573)">
<path d="M1.33335 4H14.6667C15.0349 4 15.3334 4.29848 15.3334 4.66667V11.3333C15.3334 11.7015 15.0349 12 14.6667 12H1.33335C0.965164 12 0.666687 11.7015 0.666687 11.3333V4.66667C0.666687 4.29848 0.965164 4 1.33335 4ZM2.00002 5.33333V10.6667H14V5.33333H2.00002Z" fill="#646A73"/>
<path d="M4.66665 7.02255C4.66665 6.82618 4.50746 6.66699 4.31109 6.66699H3.68887C3.4925 6.66699 3.33331 6.82618 3.33331 7.02255V8.9781C3.33331 9.17447 3.4925 9.33366 3.68887 9.33366H4.31109C4.50746 9.33366 4.66665 9.17447 4.66665 8.9781V7.02255Z" fill="#646A73"/>
</g>
<defs>
<clipPath id="clip0_8096_189573">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 797 B

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.66666 1.77734H13.3333C13.8242 1.77734 14.2222 2.17531 14.2222 2.66623V13.3329C14.2222 13.8238 13.8242 14.2218 13.3333 14.2218H2.66666C2.17574 14.2218 1.77777 13.8238 1.77777 13.3329V2.66623C1.77777 2.17531 2.17574 1.77734 2.66666 1.77734ZM3.1111 3.11068V12.8885H12.8889V3.11068H3.1111ZM10.5524 5.52146C10.6566 5.41732 10.8254 5.41732 10.9296 5.52146L11.4952 6.08715C11.5994 6.19129 11.5994 6.36013 11.4952 6.46427L7.47259 10.4869C7.463 10.4965 7.45285 10.5052 7.44226 10.5131L7.35921 10.5961C7.25571 10.6996 7.08815 10.7003 6.98375 10.5978L4.63634 8.29133C4.53063 8.18747 4.52988 8.01734 4.63467 7.91255L5.20034 7.34688C5.30383 7.24339 5.47139 7.24265 5.57579 7.34523L7.16611 8.90778L10.5524 5.52146Z" fill="#646A73"/>
</svg>

After

Width:  |  Height:  |  Size: 834 B

View File

@ -169,6 +169,16 @@ export default {
default_login: 'Normal'
},
commons: {
component: {
input: 'Input',
textarea: 'Textarea',
select: 'Select',
radio: 'Radio',
checkbox: 'Checkbox',
date: 'Date Picker',
dateRange: 'Date Range Picker',
add_component_hint: 'Click or drag the component on the left to add a field'
},
consanguinity: 'Consanguinity',
collapse_navigation: 'Collapse navigation',
operate_cancelled: 'Operation cancelled',
@ -579,6 +589,27 @@ export default {
logic_filter: 'Condition Filter',
enum_filter: 'Enum Filter'
},
data_fill: {
form: {
confirm_delete: 'Confirm delete? (The tables created in database will not be deleted)',
list: 'Form List',
record: 'Fill Record',
task_manage: 'Task Manage',
form_name: 'Form Name',
datasource: 'Datasource',
table: 'Table',
creator: 'Creator',
createTime: 'Create Time'
},
data: {
confirm_delete: 'Confirm delete?'
},
task: {
confirm_enable: 'Confirm enable task?',
confirm_disable: 'Confirm disable task?'
},
on_the_left: 'Please select a form on the left'
},
detabs: {
custom_sort: 'Custom Sort',
eidttitle: 'Edit Title',
@ -1470,7 +1501,7 @@ export default {
line_type_dotted: 'Dotted',
value_can_not_empty: 'Value can not be empty',
value_error: 'Value illegal',
threshold: 'Threshold',
threshold: 'Conditional styles',
threshold_range: 'Range',
gauge_threshold_format_error: 'Format Error',
total_cfg: 'Total Config',
@ -1660,7 +1691,8 @@ export default {
regression_pow: 'Power law',
regression_loess: 'LOESS',
regression_algo: 'Algorithm',
trend_line: 'Trend Line'
trend_line: 'Trend Line',
field_enum: 'Enumeration values'
},
dataset: {
scope_edit: 'Effective only when editing',
@ -2848,9 +2880,14 @@ export default {
chart_data_range: 'View data range',
panel_format: 'Panel format',
simple_repeat: 'Simple repeat',
single_task: 'Single task',
once_a_day: 'Once a day',
once_a_week: 'Once a week',
once_a_month: 'Once a month',
hour: 'Hour',
day: 'Day',
week: 'Week',
month: 'Month',
complex_repeat: 'Complex repeat',
pixel_tip: 'Please code custom pixel(such as 2560 * 1600) or select',
task_type: 'Task type',

View File

@ -169,6 +169,16 @@ export default {
default_login: '普通登錄'
},
commons: {
component: {
input: '單行輸入',
textarea: '多行輸入',
select: '下拉框',
radio: '單選',
checkbox: '多選框',
date: '日期',
dateRange: '時間范圍',
add_component_hint: '點擊或拖拽左側組件添加字段'
},
consanguinity: '血緣關係',
collapse_navigation: '收起導航',
operate_cancelled: '已取消操作',
@ -579,6 +589,27 @@ export default {
logic_filter: '條件篩選',
enum_filter: '枚舉篩選'
},
data_fill: {
form: {
confirm_delete: '確認刪除?(不會刪除已創建的數據庫表)',
list: '表單數據',
record: '提交記錄',
task_manage: '任務管理',
form_name: '表單名稱',
datasource: '數據源',
table: '數據庫表',
creator: '創建人',
createTime: '創建時間'
},
data: {
confirm_delete: '確認刪除?'
},
task: {
confirm_enable: '確認啟動任務?(單次任務會新建下發任務)',
confirm_disable: '確認停止任務?'
},
on_the_left: '請在左側選擇表單'
},
detabs: {
custom_sort: '自定義排序',
eidttitle: '編輯標題',
@ -1468,7 +1499,7 @@ export default {
line_type_dotted: '點',
value_can_not_empty: '值不能為空',
value_error: '值必須為數值',
threshold: '閾值',
threshold: '條件樣式',
threshold_range: '閾值區間',
gauge_threshold_format_error: '格式錯誤',
total_cfg: '總計配置',
@ -1652,7 +1683,8 @@ export default {
regression_pow: '冪函數',
regression_loess: '局部加權',
regression_algo: '算法',
trend_line: '趨勢線'
trend_line: '趨勢線',
field_enum: '枚舉值'
},
dataset: {
scope_edit: '僅編輯時生效',
@ -2840,9 +2872,14 @@ export default {
chart_data_range: '視圖數據範圍',
panel_format: '儀表板格式',
simple_repeat: '簡單重複',
single_task: '單次任務',
once_a_day: '每天',
once_a_week: '每周',
once_a_month: '每月',
hour: '小時',
day: '天',
week: '周',
month: '月',
complex_repeat: '複雜重複',
pixel_tip: '可直接輸入分辨率(例如:2560 * 1600)或者選擇',
task_type: '任務類型',

View File

@ -169,6 +169,16 @@ export default {
default_login: '普通登录'
},
commons: {
component: {
input: '单行输入',
textarea: '多行输入',
select: '下拉框',
radio: '单选',
checkbox: '多选框',
date: '日期',
dateRange: '时间范围',
add_component_hint: '点击或拖拽左侧组件添加字段'
},
consanguinity: '血缘关系',
collapse_navigation: '收起导航',
operate_cancelled: '已取消操作',
@ -578,6 +588,27 @@ export default {
logic_filter: '条件筛选',
enum_filter: '枚举筛选'
},
data_fill: {
form: {
confirm_delete: '确认删除?(不会删除已创建的数据库表)',
list: '表单数据',
record: '提交记录',
task_manage: '任务管理',
form_name: '表单名称',
datasource: '数据源',
table: '数据库表',
creator: '创建人',
createTime: '创建时间'
},
data: {
confirm_delete: '确认删除?'
},
task: {
confirm_enable: '确认启动任务?(单次任务会新建下发任务)',
confirm_disable: '确认停止任务?'
},
on_the_left: '请在左侧选择表单'
},
detabs: {
custom_sort: '自定义排序',
eidttitle: '编辑标题',
@ -1468,7 +1499,7 @@ export default {
line_type_dotted: '点',
value_can_not_empty: '值不能为空',
value_error: '值必须为数值',
threshold: '阈值',
threshold: '条件样式',
threshold_range: '阈值区间',
gauge_threshold_format_error: '格式错误',
total_cfg: '总计配置',
@ -1652,7 +1683,8 @@ export default {
regression_pow: '幂函数',
regression_loess: '局部加权',
regression_algo: '算法',
trend_line: '趋势线'
trend_line: '趋势线',
field_enum: '枚举值'
},
dataset: {
scope_edit: '仅编辑时生效',
@ -2843,9 +2875,14 @@ export default {
chart_data_range: '视图数据范围',
panel_format: '仪表板格式',
simple_repeat: '简单重复',
single_task: '单次任务',
once_a_day: '每天',
once_a_week: '每周',
once_a_month: '每月',
hour: '小时',
day: '天',
week: '周',
month: '月',
complex_repeat: '复杂重复',
pixel_tip: '可直接输入自定义分辨率(例如:2560 * 1600)或选择',
task_type: '任务类型',

View File

@ -13,7 +13,7 @@
<de-container :style="mainStyle">
<de-aside-container
v-if="!sidebar.hide"
v-if="showSideBar"
:is-collapse-width="sideWidth"
type="system"
class="le-aside-container"
@ -65,8 +65,6 @@ import DeAsideContainer from '@/components/dataease/DeAsideContainer'
import bus from '@/utils/bus'
import { showMultiLoginMsg } from '@/utils/index'
import { needModifyPwd, removePwdTips } from '@/api/user'
export default {
name: 'Layout',
components: {
@ -101,7 +99,11 @@ export default {
return this.$store.state.settings.showSettings
},
fullHeightFlag() {
return this.$route.path.indexOf('panel') > -1 && (this.componentName === 'PanelEdit' || this.componentName === 'ChartEdit')
const path = this.$route.path
return (path.indexOf('panel') > -1 && (this.componentName === 'PanelEdit' || this.componentName === 'ChartEdit')) || (path.indexOf('/data-filling/create') > -1)
},
showSideBar() {
return !this.sidebar.hide && this.$route.path.indexOf('data-filling') === -1
},
mainStyle() {
if (this.fullHeightFlag) {
@ -154,20 +156,13 @@ export default {
bus.$emit('sys-logout')
},
panelSwitchComponent(c) {
console.log(c)
this.componentName = c.name
},
handleClickOutside() {
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
},
doNotNoti() {
this.buttonDisable = true
removePwdTips().then(res => {
this.showTips = false
this.buttonDisable = false
}).catch(e => {
this.buttonDisable = false
})
}
}
}
</script>

View File

@ -1,5 +1,6 @@
module.exports = {
TokenKey: 'Authorization',
TokenExpKey: 'de-login-login-exp',
RefreshTokenKey: 'refreshauthorization',
LinkTokenKey: 'LINK-PWD-TOKEN',
title: 'DataEase',

View File

@ -938,6 +938,15 @@ const data = {
if (state.lastValidFilters[id]) {
delete state.lastValidFilters[id]
}
},
setViewInitFilter(state, viewInfo) {
if (viewInfo) {
state.componentData.forEach(component => {
if (viewInfo.id === component.id) {
component.filters = viewInfo.filters
}
})
}
}
},
modules: {

View File

@ -1,5 +1,5 @@
import { login, logout, deLogout, getInfo, getUIinfo, languageApi } from '@/api/user'
import { getToken, setToken, removeToken, setSysUI } from '@/utils/auth'
import { getToken, setToken, removeToken, setSysUI, setTokenExp } from '@/utils/auth'
import { resetRouter } from '@/router'
import { format } from '@/utils/formatUi'
import { getLanguage } from '@/lang/index'
@ -82,6 +82,7 @@ const actions = {
commit('SET_TOKEN', data.token)
commit('SET_LOGIN_MSG', null)
setToken(data.token)
setTokenExp(data.expireTime)
let passwordModified = true
if (Object.prototype.hasOwnProperty.call(data, 'passwordModified')) {
passwordModified = data.passwordModified

View File

@ -861,7 +861,6 @@ div:focus {
height: 24px !important;
line-height: 24px !important;
margin-bottom: 9px !important;
font-size: 16px !important;
}
}

View File

@ -2,6 +2,7 @@ import Cookies from 'js-cookie'
import Config from '@/settings'
import store from '@/store'
const TokenKey = Config.TokenKey
const TokenExpKey = Config.TokenExpKey
const IdTokenKey = Config.IdTokenKey
@ -22,11 +23,26 @@ export function getToken() {
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
export function setTokenExp(exp) {
if (exp) {
return Cookies.set(TokenExpKey, exp)
}
return null
}
export function tokenExp() {
const exp = Cookies.get(TokenExpKey)
if (exp && exp > 3000) {
return new Date().getTime() > (exp - 3000)
}
return false
}
export function removeToken() {
Cookies.remove(casSessionKey)
Cookies.remove(IdTokenKey)
Cookies.remove(AccessTokenKey)
Cookies.remove(TokenExpKey)
return Cookies.remove(TokenKey)
}

View File

@ -1,7 +1,7 @@
import axios from 'axios'
import store from '@/store'
import { $alert, $error } from './message'
import { getToken, getIdToken, setToken } from '@/utils/auth'
import { getToken, getIdToken, setToken, tokenExp } from '@/utils/auth'
import Config from '@/settings'
import i18n from '@/lang'
import { tryShowLoading, tryHideLoading } from './loading'
@ -56,7 +56,6 @@ service.interceptors.request.use(
if (idToken) {
config.headers[Config.IdTokenKey] = idToken
}
if (store.getters.token) {
config.headers[TokenKey] = getToken()
}
@ -74,7 +73,26 @@ service.interceptors.request.use(
config.headers['Accept-Language'] = lang
}
config.loading && tryShowLoading(store.getters.currentPath)
if (config.headers[TokenKey]) {
const logoutApiList = ['/api/auth/deLogout', '/api/auth/logout']
if (tokenExp() && !logoutApiList.includes(config.url)) {
config['expCancel'] = null
config.cancelToken = new CancelToken(function executor(c) {
config['expCancel'] = c
})
const message = i18n.t('login.expires')
$alert(message, () => {
store.dispatch('user/logout').then(() => {
location.reload()
})
}, {
confirmButtonText: i18n.t('login.re_login'),
showClose: false
})
config.expCancel('login.expires')
return config
}
}
config.cancelToken = new CancelToken(function executor(c) {
Vue.prototype.$currentHttpRequestList.set(config.url, c)
})
@ -104,10 +122,12 @@ service.interceptors.response.use(response => {
}
return response.data
}, error => {
const config = error.response && error.response.config || error.config
let config = error.response && error.response.config || error.config
const headers = error.response && error.response.headers || error.response || config && config.headers
config.loading && tryHideLoading(store.getters.currentPath)
config?.loading && tryHideLoading(store.getters.currentPath)
if (!config && !headers && error.code === 'ERR_CANCELED' && error.message === 'login.expires') {
config = { hideMsg: true }
}
let msg = ''
if (error.response) {
@ -119,7 +139,7 @@ service.interceptors.response.use(response => {
if (msg.length > 600) {
msg = msg.slice(0, 600)
}
!config.hideMsg && (!headers['authentication-status']) && !msg?.startsWith('MultiLoginError') && $error(msg)
!config?.hideMsg && (!headers['authentication-status']) && !msg?.startsWith('MultiLoginError') && $error(msg)
return Promise.reject(config.url === '/dataset/table/sqlPreview' ? msg : error)
})
const checkDownError = response => {

View File

@ -20,3 +20,4 @@ export function validUsername(str) {
}
export const PHONE_REGEX = '^1[3|4|5|7|8][0-9]{9}$'
export const EMAIL_REGEX = '^[a-zA-Z0-9_._-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$'

View File

@ -236,7 +236,7 @@
</el-col>
</el-row>
<template v-if="this.curComponent.component === 'de-select'">
<template v-if="this.curComponent.component === 'de-select' && !this.curComponent.options.attrs.multiple">
<el-row
style="height: 40px;overflow: hidden;"
>

View File

@ -766,12 +766,16 @@ function getConditions(chart) {
// table item color
let valueColor = DEFAULT_COLOR_CASE.tableFontColor
let valueBgColor = DEFAULT_COLOR_CASE.tableItemBgColor
let headerColor = DEFAULT_COLOR_CASE.tableHeaderFontColor
let headerBgColor = DEFAULT_COLOR_CASE.tableHeaderBgColor
if (chart.customAttr) {
const customAttr = JSON.parse(chart.customAttr)
// color
if (customAttr.color) {
const c = JSON.parse(JSON.stringify(customAttr.color))
valueColor = c.tableFontColor
headerColor = c.tableHeaderFontColor
headerBgColor = c.tableHeaderBgColor
const enableTableCrossBG = c.enableTableCrossBG
if (!enableTableCrossBG) {
valueBgColor = hexColorToRGBA(c.tableItemBgColor, c.alpha)
@ -781,21 +785,35 @@ function getConditions(chart) {
}
}
const dimensionAxis = [...JSON.parse(chart.xaxis), ...JSON.parse(chart.xaxisExt)]
const filedValueMap = getFieldValueMap(chart)
for (let i = 0; i < conditions.length; i++) {
const field = conditions[i]
let defaultTextColor = valueColor
let defaultBgColor = valueBgColor
if (chart.type === 'table-pivot') {
const index = dimensionAxis.findIndex(i => i.dataeaseName === field.field.dataeaseName)
defaultTextColor = index === -1 ? valueColor : headerColor
defaultBgColor = index === -1 ? valueBgColor : headerBgColor
}
res.text.push({
field: field.field.dataeaseName,
mapping(value, rowData) {
if (rowData?.isTotals) {
return null
}
return {
fill: mappingColor(value, valueColor, field, 'color', filedValueMap, rowData)
fill: mappingColor(value, defaultTextColor, field, 'color', filedValueMap, rowData)
}
}
})
res.background.push({
field: field.field.dataeaseName,
mapping(value, rowData) {
const fill = mappingColor(value, valueBgColor, field, 'backgroundColor', filedValueMap, rowData)
if (rowData?.isTotals) {
return null
}
const fill = mappingColor(value, defaultBgColor, field, 'backgroundColor', filedValueMap, rowData)
if (fill) {
return { fill }
}
@ -884,28 +902,62 @@ function mappingColor(value, defaultColor, field, type, filedValueMap, rowData)
let tv
if (t.field === '1') {
tv = getValue(t.targetField, filedValueMap, rowData)
} else if (t.field === '2') {
tv = t.enumValues
} else {
tv = t.value
}
if (t.term === 'eq') {
if (value === tv) {
color = t[type]
flag = true
if (t.field === '2') {
const index = tv?.findIndex(v => v === value)
if (index !== -1) {
color = t[type]
flag = true
}
} else {
if (value === tv) {
color = t[type]
flag = true
}
}
} else if (t.term === 'not_eq') {
if (value !== tv) {
color = t[type]
flag = true
if (t.field === '2') {
const index = tv?.findIndex(v => v === value)
if (index === -1) {
color = t[type]
flag = true
}
} else {
if (value !== tv) {
color = t[type]
flag = true
}
}
} else if (t.term === 'like') {
if (value.includes(tv)) {
color = t[type]
flag = true
if (t.field === '2') {
const index = tv?.findIndex(v => value.includes(v))
if (index !== -1) {
color = t[type]
flag = true
}
} else {
if (value.includes(tv)) {
color = t[type]
flag = true
}
}
} else if (t.term === 'not like') {
if (!value.includes(tv)) {
color = t[type]
flag = true
if (t.field === '2') {
const index = tv?.findIndex(v => value.includes(v))
if (index === -1) {
color = t[type]
flag = true
}
} else {
if (!value.includes(tv)) {
color = t[type]
flag = true
}
}
} else if (t.term === 'null') {
if (value === null || value === undefined || value === '') {
@ -931,20 +983,41 @@ function mappingColor(value, defaultColor, field, type, filedValueMap, rowData)
if (fieldValue) {
tv = new Date(fieldValue.replace(/-/g, '/') + ' GMT+8').getTime()
}
} else if (t.field === '2') {
tv = []
t.enumValues?.forEach(v => {
tv.push(new Date(v.replace(/-/g, '/') + ' GMT+8').getTime())
})
} else {
tv = new Date(t.value.replace(/-/g, '/') + ' GMT+8').getTime()
}
const v = new Date(value.replace(/-/g, '/') + ' GMT+8').getTime()
if (t.term === 'eq') {
if (v === tv) {
color = t[type]
flag = true
if (t.field === '2') {
const index = tv.findIndex(val => v === val)
if (index !== -1) {
color = t[type]
flag = true
}
} else {
if (v === tv) {
color = t[type]
flag = true
}
}
} else if (t.term === 'not_eq') {
if (v !== tv) {
color = t[type]
flag = true
if (t.field === '2') {
const index = tv.findIndex(val => v === val)
if (index === -1) {
color = t[type]
flag = true
}
} else {
if (v !== tv) {
color = t[type]
flag = true
}
}
} else if (t.term === 'lt') {
if (v < tv) {

View File

@ -3923,3 +3923,10 @@ export function handleTableEmptyStrategy(tableData, chart) {
}
return newData
}
export function parseJson(target) {
if (Object.prototype.toString.call(target) === '[object String]') {
return JSON.parse(target)
}
return JSON.parse(JSON.stringify(target))
}

View File

@ -329,6 +329,10 @@
v-if="item.field === '1'"
:title="$t('chart.field_dynamic')"
>{{ $t('chart.field_dynamic') }}</span>
<span
v-if="item.field === '2'"
:title="$t('chart.field_enum')"
>{{ $t('chart.field_enum') }}</span>
</el-col>
<el-col
v-if="item.term.includes('null') || item.term.includes('empty')"
@ -369,6 +373,23 @@
<span v-else>&nbsp;</span>
</el-col>
<el-col
v-if="item.field === '2'"
:span="10"
>
<div
v-if="item.enumValues && item.enumValues.length"
style="display: flex; box-sizing: border-box; justify-content: start; align-items: center; overflow: hidden"
>
<span style="display: inline"> {{ item.enumValues.join(',') }}</span>
<el-tooltip
v-if="item.enumValues && item.enumValues.length"
:content="item.enumValues.join(',')"
>
<i class="el-icon-info"></i>
</el-tooltip>
</div>
</el-col>
<el-col :span="2">
<span

View File

@ -76,7 +76,7 @@
<el-select
v-model="item.term"
size="mini"
@change="changeThresholdField(item)"
@change="changeThresholdField(item, fieldItem)"
>
<el-option-group
v-for="(group,idx) in fieldItem.options"
@ -99,10 +99,10 @@
v-model="item.field"
size="mini"
style="margin-left: 10px;"
@change="changeThresholdField(item)"
@change="changeThresholdField(item, fieldItem)"
>
<el-option
v-for="opt in fieldTypeOptions"
v-for="opt in getFieldTypeOptions(fieldItem.field, item)"
:key="opt.value"
:label="opt.label"
:value="opt.value"
@ -328,7 +328,26 @@
</span>
</el-col>
<el-col
v-if="item.field === '2'"
:span="12"
>
<el-select
v-if="!item.term.includes('null') && !item.term.includes('empty') && item.term !== 'between'"
v-model="item.enumValues"
size="mini"
style="margin-left: 10px; width: 100%"
multiple
clearable
>
<el-option
v-for="value in fieldEnumValues[fieldItem.fieldId]"
:key="value"
:value="value"
:label="value"
/>
</el-select>
</el-col>
<el-col
:span="3"
style="display: flex;align-items: center;justify-content: center;"
@ -373,6 +392,8 @@
<script>
import { COLOR_PANEL } from '@/views/chart/chart/chart'
import { post } from '@/api/dataset/dataset'
import { parseJson } from '@/views/chart/chart/util'
export default {
name: 'TableThresholdEdit',
@ -410,7 +431,8 @@ export default {
max: '1',
targetField: {},
minField: {},
maxField: {}
maxField: {},
enumValues: []
},
summaryOptions: [{
id: 'value',
@ -530,9 +552,16 @@ export default {
],
fieldTypeOptions: [
{ label: this.$t('chart.field_fixed'), value: '0' },
{ label: this.$t('chart.field_dynamic'), value: '1' }
{ label: this.$t('chart.field_dynamic'), value: '1' },
{ label: this.$t('chart.field_enum'), value: '2' }
],
predefineColors: COLOR_PANEL
predefineColors: COLOR_PANEL,
fieldEnumValues: {}
}
},
computed: {
panelInfo() {
return this.$store.state.panel.panelInfo
}
},
mounted() {
@ -542,14 +571,21 @@ export default {
init() {
this.thresholdArr = JSON.parse(JSON.stringify(this.threshold))
this.initFields()
this.thresholdArr && this.thresholdArr.forEach(ele => {
const enumFields = new Set([])
this.thresholdArr?.forEach(ele => {
this.initOptions(ele)
if (ele.conditions) {
for (const item of ele.conditions) {
this.initConditionField(item)
if (item.field === '2') {
enumFields.add(ele.fieldId)
}
}
}
})
enumFields.forEach(fieldId => {
this.getFieldEnumValues(fieldId)
})
},
initConditionField(item) {
//
@ -587,30 +623,17 @@ export default {
}
},
initFields() {
//
if (this.chart.type === 'table-info') {
if (Object.prototype.toString.call(this.chart.xaxis) === '[object Array]') {
this.fields = JSON.parse(JSON.stringify(this.chart.xaxis))
} else {
this.fields = JSON.parse(this.chart.xaxis)
}
this.fields.splice(0, this.fields.length, ...parseJson(this.chart.xaxis))
} else if (this.chart.type === 'table-pivot') {
if (Object.prototype.toString.call(this.chart.yaxis) === '[object Array]') {
this.fields = JSON.parse(JSON.stringify(this.chart.yaxis))
} else {
this.fields = JSON.parse(this.chart.yaxis)
}
const yAxis = parseJson(this.chart.yaxis)
const xAxis = parseJson(this.chart.xaxis)
const xAxisExt = parseJson(this.chart.xaxisExt)
this.fields.splice(0, this.fields.length, ...yAxis, ...xAxis, ...xAxisExt)
} else {
if (Object.prototype.toString.call(this.chart.xaxis) === '[object Array]') {
this.fields = this.fields.concat(JSON.parse(JSON.stringify(this.chart.xaxis)))
} else {
this.fields = this.fields.concat(JSON.parse(this.chart.xaxis))
}
if (Object.prototype.toString.call(this.chart.yaxis) === '[object Array]') {
this.fields = this.fields.concat(JSON.parse(JSON.stringify(this.chart.yaxis)))
} else {
this.fields = this.fields.concat(JSON.parse(this.chart.yaxis))
}
const yAxis = parseJson(this.chart.yaxis)
const xAxis = parseJson(this.chart.xaxis)
this.fields.splice(0, this.fields.length, ...yAxis, ...xAxis)
}
//
@ -654,24 +677,50 @@ export default {
changeThreshold() {
this.$emit('onTableThresholdChange', this.thresholdArr)
},
changeThresholdField(item) {
if (item.field === '1') {
if (item.term === 'between') {
item.minField.curField = this.getQuotaField(item.minField.fieldId)
item.maxField.curField = this.getQuotaField(item.maxField.fieldId)
changeThresholdField(item, curField) {
switch (item.field) {
case '0':
item.targetField = {}
} else {
item.targetField.curField = this.getQuotaField(item.targetField.fieldId)
item.minField = {}
item.maxField = {}
}
} else {
item.targetField = {}
item.minField = {}
item.maxField = {}
break
case '1':
if (item.term === 'between') {
item.minField.curField = this.getQuotaField(item.minField.fieldId)
item.maxField.curField = this.getQuotaField(item.maxField.fieldId)
item.targetField = {}
} else {
item.targetField.curField = this.getQuotaField(item.targetField.fieldId)
item.minField = {}
item.maxField = {}
}
break
case '2':
if (!curField?.fieldId) {
break
}
//
if (curField.field.deType === 1 && !['eq', 'not_eq'].includes(item.term)) {
item.field = '0'
}
this.getFieldEnumValues(curField.fieldId)
break
default:
break
}
this.changeThreshold()
},
getFieldEnumValues(fieldId) {
if (this.fieldEnumValues[fieldId]) {
return
}
const fieldType = this.getFieldType(fieldId)
if (fieldType) {
post('/chart/view/getFieldData/' + this.chart.id + '/' + this.panelInfo.id + '/' + fieldId + '/' + fieldType, {}).then(response => {
this.$set(this.fieldEnumValues, fieldId, response.data)
})
}
},
getQuotaField(id) {
if (!id) {
return {}
@ -703,11 +752,60 @@ export default {
}
})
}
// term
item.conditions && item.conditions.forEach(ele => {
// term field
item.conditions?.forEach(ele => {
ele.term = ''
if (item.field.groupType === 'q' && ele.field === '2') {
ele.field = '0'
}
if (item.field.groupType === 'd') {
if (this.chart.type === 'table-pivot' && ele.field === '1') {
ele.field = '0'
}
if (ele.field === '2') {
ele.enumValues?.splice(0)
this.getFieldEnumValues(item.fieldId)
}
}
})
this.changeThreshold()
},
getFieldType(fieldId) {
let index = -1
index = JSON.parse(this.chart.xaxis).findIndex(i => i.id === fieldId)
if (index !== -1) {
return 'xaxis'
}
index = JSON.parse(this.chart.xaxisExt).findIndex(i => i.id === fieldId)
if (index !== -1) {
return 'xaxisExt'
}
},
getFieldTypeOptions(field, condition) {
if (field.groupType === 'q') {
return [
{ label: this.$t('chart.field_fixed'), value: '0' },
{ label: this.$t('chart.field_dynamic'), value: '1' }
]
}
if (field.deType === 1 && !['eq', 'not_eq'].includes(condition.term)) {
if (this.chart.type === 'table-pivot') {
return [
{ label: this.$t('chart.field_fixed'), value: '0' }
]
}
return [
{ label: this.$t('chart.field_fixed'), value: '0' },
{ label: this.$t('chart.field_dynamic'), value: '1' }
]
}
if (this.chart.type === 'table-pivot') {
return [
{ label: this.$t('chart.field_fixed'), value: '0' },
{ label: this.$t('chart.field_enum'), value: '2' }
]
}
return this.fieldTypeOptions
}
}
}

View File

@ -0,0 +1,968 @@
<template>
<el-container class="DataFillingSave">
<el-header class="de-header">
<div class="panel-info-area">
<span class="text16 margin-left12">
{{ id? '编辑任务': '新建任务' }}
</span>
</div>
<div style="padding-right: 20px">
<i
class="el-icon-close"
style="cursor: pointer"
@click="reset"
/>
</div>
</el-header>
<el-main class="de-main">
<div
v-if="userLoadFinish && showDrawer"
class="new-task-form"
>
<el-form
ref="taskForm"
class="de-form-item"
:model="form"
:rules="rule"
size="small"
label-width="100px"
>
<div class="row-rules marTop0">
<span>{{ $t("datasource.base_info") }}</span>
</div>
<el-form-item
:label="$t('xpacktask.name')"
prop="name"
>
<el-input
v-model="form.name"
@input="setTitle"
/>
</el-form-item>
<el-form-item
:label="$t('commons.user')"
prop="userValues"
>
<el-select
ref="userSelect"
v-model="form.userValues"
style="width: 100%"
filterable
multiple
:popper-append-to-body="false"
:placeholder="
$t('commons.please_select') + $t('emailtask.recipients')
"
>
<el-option
v-for="item in users"
:key="item.nickName"
:label="item.nickName"
:value="item.username"
/>
</el-select>
</el-form-item>
<el-form-item
:label="$t('commons.role')"
prop="roleList"
>
<el-select
ref="roleSelect"
v-model="form.roleList"
style="width: 100%"
filterable
multiple
:popper-append-to-body="false"
:placeholder="
$t('commons.please_select') + $t('commons.role')
"
>
<el-option
v-for="item in roleOptions"
:key="item.name"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item
:label="$t('commons.organization')"
prop="orgList"
>
<treeselect
ref="orgTreeSelect"
v-model="form.orgList"
class="email-task-tree"
size="mini"
:multiple="true"
:flat="true"
:sort-value-by="sortValueBy"
:options="orgTreeData"
:placeholder="$t('commons.please_select') + $t('commons.organization')"
/>
</el-form-item>
<div class="row-rules marTop0">
<span>{{ $t("emailtask.send_config") }}</span>
</div>
<el-form-item
:label="$t('emailtask.rate_type')"
prop="rateType"
>
<el-radio-group v-model="rateType">
<el-radio
v-for="rate in rateTypeList"
:key="rate.label"
:label="rate.value"
>{{ $t(rate.label) }}</el-radio>
</el-radio-group>
<template v-if="rateType === 'single_task'">
<div
class="rate-type-time"
style="padding-top: 28px; padding-bottom: 0"
>
<span
class="perfix"
style="margin-bottom: 28px; "
>任务下发时间</span>
<el-form-item
prop="publishStartTime"
style="flex:1"
>
<el-date-picker
v-model="form.publishStartTime"
:clearable="false"
style="width: 100%"
type="datetime"
:picker-options="startPickerOptions"
class="de-time-range"
:placeholder="$t('commons.please_select')"
/>
</el-form-item>
</div>
<div
class="rate-type-time"
style="padding-top: 0; padding-bottom: 0"
>
<span
class="perfix"
style="margin-bottom: 28px"
>填报截止时间</span>
<el-form-item
prop="publishEndTime"
style="flex:1"
>
<el-date-picker
v-model="form.publishEndTime"
:clearable="false"
style="width: 100%"
type="datetime"
:picker-options="startPickerOptions"
:placeholder="$t('commons.please_select')"
class="de-time-range"
default-time="23:59:59"
/>
</el-form-item>
</div>
</template>
<template v-else-if="rateType === 'simple_repeat'">
<div class="rate-type-time">
<el-select
v-model="timeTypeValue"
class="w140"
>
<el-option
v-for="item in timeType"
:key="item.value"
:label="$t(item.label)"
:value="item.value"
/>
</el-select>
<el-select
v-if="timeTypeValue === 1"
v-model="weekTypeValue"
class="w140"
>
<el-option
v-for="item in weekType"
:key="item.value"
:label="$t(item.label)"
:value="item.value"
/>
</el-select>
<el-select
v-if="timeTypeValue === 2"
v-model="monthTypeValue"
class="w140"
>
<el-option
v-for="item in monthType"
:key="item.value"
:label="(item.label + $t('dynamic_time.date'))"
:value="item.value"
/>
</el-select>
<el-time-picker
v-model="timePicker"
:clearable="false"
class="w140"
:picker-options="{
selectableRange: '00:00:00 - 23:59:59',
}"
/>
<span class="tail">{{ $t('cron.every_exec') }}</span>
</div>
<div class="rate-type-time second-row">
<span class="perfix">在任务下发</span>
<el-input-number
v-model.number="form.publishRangeTime"
class="w140"
min="1"
step="1"
/>
<el-select
v-model="form.publishRangeTimeType"
class="w140"
>
<el-option
v-for="item in simpleTimeType"
:key="item.value"
:label="$t(item.label)"
:value="item.value"
/>
</el-select>
<span class="tail">内完成填报</span>
</div>
</template>
</el-form-item>
<template v-if="rateType === 'simple_repeat'">
<el-form-item
:label="$t('emailtask.start_time')"
prop="startTime"
>
<el-date-picker
v-model="form.startTime"
:clearable="false"
class="de-time-range"
type="datetime"
:picker-options="startPickerOptions"
:placeholder="
$t('commons.please_select') + $t('emailtask.start_time')
"
/>
</el-form-item>
<el-form-item
:label="$t('emailtask.end_time')"
prop="endTime"
>
<el-date-picker
v-model="form.endTime"
class="de-time-range"
type="datetime"
:clearable="false"
:picker-options="startPickerOptions"
popper-class="link-date-picker-class"
:placeholder="$t('commons.please_select') + $t('emailtask.end_time')"
default-time="23:59:59"
/>
</el-form-item>
</template>
</el-form>
</div>
</el-main>
<el-footer
class="de-footer"
>
<el-button @click="reset">{{ $t("commons.cancel") }}</el-button>
<el-button
type="primary"
@click="save"
>{{ $t("commons.confirm") }}
</el-button>
</el-footer>
</el-container>
</template>
<script>
import { timeType, weekType, monthType, simpleTimeType } from './options'
import { roleGrid, userListsWithOutPage } from '@/api/system/user'
import { loadTable } from '@/api/system/dept'
import { saveFormTasks, searchFormTasks } from '@/views/dataFilling/form/dataFilling'
import { cloneDeep } from 'lodash-es'
export default {
name: 'TaskEmailForm',
props: {
id: {
type: String,
required: false
},
formId: {
type: String,
required: true
},
showDrawer: {
type: Boolean,
required: true
}
},
data() {
return {
showTable: false,
showMedia: false,
formType: 'add',
rateType: 'single_task',
timeType,
weekType,
monthType,
simpleTimeType,
timeTypeValue: 1,
weekTypeValue: 1,
monthTypeValue: 1,
timePicker: new Date(),
roleOptions: [],
orgTreeData: [],
sortValueBy: 'ORDER_SELECTED',
form: {
name: '',
rateType: -1,
rateVal: undefined,
publishStartTime: undefined,
publishEndTime: undefined,
publishRangeTimeType: 0,
publishRangeTime: 1,
userValues: [],
roleList: [],
orgList: []
},
rule: {
name: [
{
required: true,
trigger: 'blur',
message: this.$t('commons.cannot_be_null')
},
{
min: 1,
max: 50,
message: this.$t('commons.input_limit', [1, 50]),
trigger: 'blur'
}
],
userValues: [
{
required: false,
trigger: ['blur', 'change'],
validator: this.validateReci
}
],
rateType: [
{
required: true,
trigger: 'blur',
message: this.$t('commons.cannot_be_null')
}
],
rateVal: [
{
required: true,
trigger: 'blur',
message: this.$t('commons.cannot_be_null')
}
],
startTime: [
{
required: true,
trigger: 'blur',
message: this.$t('commons.cannot_be_null')
},
{
required: true,
validator: this.validateMin,
trigger: 'blur'
}
],
endTime: [
{
required: true,
trigger: 'blur',
message: this.$t('commons.cannot_be_null')
},
{
required: true,
validator: this.validateMax,
trigger: 'blur'
}
],
publishStartTime: [
{
required: true,
trigger: 'blur',
message: this.$t('commons.cannot_be_null')
},
{
required: true,
validator: this.validatePublishMin,
trigger: 'blur'
}
],
publishEndTime: [
{
required: true,
trigger: 'blur',
message: this.$t('commons.cannot_be_null')
},
{
required: true,
validator: this.validatePublishMax,
trigger: 'blur'
}
],
roleList: [
{
required: false,
trigger: ['blur', 'change'],
validator: this.validateReci
}
],
orgList: [
{
required: false,
trigger: ['blur', 'change'],
validator: this.validateReci
}
]
},
roles: [],
originName: null,
panelData: [],
users: [],
radio: 'default',
rateTypeList: [
{
label: 'emailtask.single_task',
value: 'single_task'
},
{
label: 'emailtask.simple_repeat',
value: 'simple_repeat'
}
],
format: '',
htmlContent: '',
previewHtml: '',
previewDialog: false,
startPickerOptions: {
disabledDate: (time) => {
return time.getTime() < Date.now() - 8.64e7
}
},
sourceForm: {},
panelLoadFinish: false,
userLoadFinish: false,
viewLoaded: false,
showEditor: false
}
},
computed: {},
watch: {
},
created() {
this.loadRoles()
this.loadOrgs()
this.loadUsers()
},
mounted() {
if (this.id) {
searchFormTasks(this.formId, { id: this.id }, 1, 10).then(res => {
if (res.data) {
const _data = res.data.listObject[0]
this.form = {
name: _data.name,
rateType: _data.rateType,
rateVal: _data.rateVal,
publishStartTime: _data.publishStartTime ? new Date(_data.publishStartTime) : undefined,
publishEndTime: _data.publishEndTime ? new Date(_data.publishEndTime) : undefined,
startTime: _data.startTime ? new Date(_data.startTime) : undefined,
endTime: _data.endTime ? new Date(_data.endTime) : undefined,
publishRangeTimeType: _data.publishRangeTimeType ? _data.publishRangeTimeType : 0,
publishRangeTime: _data.publishRangeTime ? _data.publishRangeTime : 1,
userValues: _data.reciUsers ? _data.reciUsers.split(',') : [],
roleList: _data.roleList ? _data.roleList.split(',') : [],
orgList: _data.orgList ? _data.orgList.split(',') : []
}
this.sourceForm = cloneDeep(this.form)
if (_data.rateType === -1) {
this.rateType = 'single_task'
} else {
this.rateType = 'simple_repeat'
this.timePicker = new Date(_data.rateVal)
this.timeTypeValue = _data.rateType
if (this.timeTypeValue === 1) {
this.weekTypeValue = this.timePicker.getDate()
}
if (this.timeTypeValue === 2) {
this.monthTypeValue = this.timePicker.getDate()
}
}
}
})
}
},
destroyed() {
},
methods: {
beforeClearAll(val) {
this.beforeClearAll()
return true
},
onRemarkChange(value) {
this.htmlContent = value
},
reset() {
this.$emit('update:showDrawer', false)
},
save() {
const request = this.form
request.rateType = -1
if (this.rateType !== 'single_task') {
request.rateType = this.timeTypeValue
let dayTime = '01'
if (this.timeTypeValue === 1) {
dayTime = `0${this.weekTypeValue}`
}
if (this.timeTypeValue === 2) {
dayTime =
this.monthTypeValue < 10
? `0${this.monthTypeValue}`
: this.monthTypeValue
}
const hms = this.timePicker
? new Date(this.timePicker).format('hh:mm:ss')
: '00:00:01'
request.rateVal = `2024-03-${dayTime} ${hms}`
delete request.publishStartTime
delete request.publishEndTime
} else {
delete request.publishRangeTimeType
delete request.publishRangeTime
}
const param = {
request: JSON.parse(JSON.stringify(request))
}
this.$refs.taskForm.validate((valid) => {
if (valid) {
param.request.reciUsers = null
if (param.request.userValues) {
const valueResult = this.resolveUserValue(param.request.userValues)
if (valueResult && valueResult.reciUsers) {
param.request.reciUsers = Array.isArray(valueResult.reciUsers) ? valueResult.reciUsers.join() : valueResult.reciUsers
}
}
if (param.request.roleList) {
param.request.roleList = Array.isArray(param.request.roleList) ? param.request.roleList.join() : param.request.roleList
}
if (param.request.orgList) {
param.request.orgList = Array.isArray(param.request.orgList) ? param.request.orgList.join() : param.request.orgList
}
delete param.request.userValues
if (this.id) {
param.request.id = this.id
}
saveFormTasks(this.formId, param.request).then(res => {
this.$emit('save-success')
})
} else {
return false
}
})
},
buildUserValue(recipients, reciUsers) {
const userValues = []
reciUsers.forEach(user => {
!userValues.includes(user) && userValues.push(user)
})
recipients.forEach(recipient => {
const tempUser = this.userWithEmail(recipient)
if (tempUser && tempUser.username) {
!userValues.includes(tempUser.username) && userValues.push(tempUser.username)
} else {
!userValues.includes(recipient) && userValues.push(recipient)
}
})
return userValues
},
userWithRecipient(recipient) {
for (let index = 0; index < this.users.length; index++) {
const element = this.users[index]
if (recipient === element.username) {
return element
}
}
return null
},
userWithEmail(email) {
for (let index = 0; index < this.users.length; index++) {
const element = this.users[index]
if (email === element.email) {
return element
}
}
return null
},
resolveUserValue(userValues) {
const result = {}
userValues.forEach(value => {
const user = this.userWithRecipient(value)
if (user) {
if (!result.reciUsers) {
result.reciUsers = []
}
result.reciUsers.push(value)
} else {
if (!result.recipients) {
result.recipients = []
}
result.recipients.push(value)
}
})
return result
},
loadUsers(callBack) {
userListsWithOutPage({}).then((res) => {
this.userLoadFinish = true
this.users = res.data
callBack && callBack()
})
},
loadRoles() {
roleGrid(1, 0, {}).then((res) => {
this.roleOptions = res.data.listObject.map(item => {
return {
id: item.roleId.toString(),
name: item.name
}
})
})
},
convertOrgNode(data) {
return data.map(item => {
const tempItem = {
id: item.deptId,
label: item.name,
pid: item.pid
}
if (item.hasChildren) {
tempItem.children = null
}
return tempItem
})
},
loadOrgs() {
loadTable({ pid: null }).then((res) => {
const data = this.convertOrgNode(res.data)
this.orgTreeData = this.buildTree(data)
})
},
buildTree(arrs) {
const idMapping = arrs.reduce((acc, el, i) => {
acc[el.id] = i
return acc
}, {})
const roots = []
arrs.forEach(el => {
//
if (el.pid === null || el.pid === 0) {
roots.push(el)
return
}
//
const parentEl = arrs[idMapping[el.pid]]
// `children`
parentEl.children = [...(parentEl.children || []), el]
})
return roots
},
setTitle(val) {
this.form.title = val
},
validateMin(rule, value, callback) {
if (this.id && value?.getTime() === this.sourceForm.startTime?.getTime()) { return callback() }
if (!value) return callback()
const val = new Date(value)
if (val.getTime() < Date.now() - 60 * 1000) {
return callback(new Error('不能小于当前时间'))
}
if (this.form.endTime) {
if (val.getTime() >= new Date(this.form.endTime).getTime()) {
return callback(new Error('不能大于结束时间'))
}
}
return callback()
},
validateMax(rule, value, callback) {
if (this.id && value?.getTime() === this.sourceForm.endTime?.getTime()) { return callback() }
if (!value) return callback()
const val = new Date(value)
if (val.getTime() < Date.now()) {
return callback(new Error('不能小于当前时间'))
}
if (this.form.startTime) {
if (val.getTime() <= new Date(this.form.startTime).getTime()) {
return callback(new Error('不能小于开始时间'))
}
}
return callback()
},
validatePublishMin(rule, value, callback) {
if (this.id && value?.getTime() === this.sourceForm?.publishStartTime?.getTime()) { return callback() }
if (!value) return callback()
const val = new Date(value)
if (val.getTime() < Date.now() - 60 * 1000) {
return callback(new Error('不能小于当前时间'))
}
if (this.form.publishEndTime) {
if (val.getTime() >= new Date(this.form.publishEndTime).getTime()) {
return callback(new Error('不能大于结束时间'))
}
}
return callback()
},
validatePublishMax(rule, value, callback) {
if (this.id && value?.getTime() === this.sourceForm.publishEndTime?.getTime()) { return callback() }
if (!value) return callback()
const val = new Date(value)
if (val.getTime() < Date.now()) {
return callback(new Error('不能小于当前时间'))
}
if (this.form.publishStartTime) {
if (val.getTime() <= new Date(this.form.publishStartTime).getTime()) {
return callback(new Error('不能小于开始时间'))
}
}
return callback()
},
validateWaitTime(rule, value, callback) {
if (value === null || typeof value === 'undefined') {
return callback(new Error(this.$t('commons.cannot_be_null')))
}
const reg = /^([0-9]{1,2}|30)$/
if (!reg.test(value)) {
return callback(new Error(this.$t('emailtask.wat_time_limit')))
}
callback()
},
validateReci(rule, value, callback) {
if ((!this.form.userValues || this.form.userValues.length === 0) &&
(!this.form.roleList || this.form.roleList.length === 0) &&
(!this.form.orgList || this.form.orgList.length === 0)) {
return callback(new Error('收件人、角色、组织至少选择一项'))
}
return callback()
}
}
}
</script>
<style lang="scss" scoped>
.inline {
display: flex;
.el-form-item {
margin-right: 30px !important;
}
}
.email-task-tree >>> .vue-treeselect__control {
height: 28px !important;
}
.email-task-tree >>> .vue-treeselect__menu-container {
z-index: 2000 !important;
}
.row-rules {
display: flex;
align-items: center;
position: relative;
font-family: PingFang SC;
font-size: 14px;
font-weight: 500;
line-height: 22px;
padding-left: 10px;
margin: 16px 0;
&::before {
content: "";
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
height: 14px;
width: 2px;
background: #3370ff;
}
}
.marTop0 {
margin-top: 0;
}
</style>
<style lang="scss">
.DataFillingSave {
height: 100%;
.de-header {
height: 56px !important;
padding: 0px !important;
border-bottom: 1px solid #E6E6E6;
background-color: var(--SiderBG, white);
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between
}
.de-footer {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end
}
.panel-info-area {
padding-left: 20px;
}
}
.new-task-form {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
padding-bottom: 24px;
& > :nth-child(1) {
width: 600px;
}
textarea {
height: 92px;
width: 100%;
}
.el-textarea .el-input__count {
font-family: PingFang SC;
font-size: 12px;
font-weight: 400;
color: #8f959e;
line-height: 20px;
padding: 0 12px 6px 0;
right: 1px;
bottom: 1px;
border-bottom-right-radius: 4px;
}
}
.de-time-range {
width: 100% !important;
}
.rate-type-time {
width: 100%;
border-radius: 4px;
padding: 20px;
background-color: var(--MainBG, #f5f6f7);
display: flex;
align-items: center;
.w140 {
width: 140px !important;
margin-right: 8px;
}
.el-input__inner {
background: var(--ContentBG, #ffffff) !important;
}
.w160 {
width: 160px !important;
}
.perfix {
font-family: PingFang SC;
font-size: 14px;
font-weight: 400;
color: var(--deTextPrimary, #1f2329);
margin-right: 8px;
}
.tail {
font-family: PingFang SC;
font-size: 14px;
font-weight: 400;
color: var(--deTextPrimary, #1f2329);
}
}
.second-row {
padding-top: 0;
}
.de-foot-layout {
position: absolute;
width: calc(100% - 48px);
height: 80px;
bottom: 0;
right: 24px;
background-color: var(--MainBG, #fff);
box-shadow: 0px -2px 4px rgba(0, 0, 0, 0.08);
display: flex;
align-items: center;
justify-content: center;
.cont {
width: 600px;
text-align: right;
}
}
</style>

Some files were not shown because too many files have changed in this diff Show More