refactor: 修复冲突
@ -256,6 +256,11 @@
|
||||
<artifactId>selenium-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>1.14.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@ -415,10 +420,10 @@
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
|
||||
|
||||
<copy file="../mobile/dist/build/h5/index.html" tofile="src/main/resources/templates/app.html" />
|
||||
|
||||
|
||||
|
||||
|
||||
</target>
|
||||
</configuration>
|
||||
<goals>
|
||||
|
@ -13,31 +13,27 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Api(tags = "权限:权限管理")
|
||||
@ApiSupport(order = 10)
|
||||
@RequestMapping("/api/auth")
|
||||
public interface AuthApi {
|
||||
|
||||
|
||||
@ApiOperation("登录")
|
||||
@PostMapping("/login")
|
||||
Object login(LoginDto loginDto) throws Exception;
|
||||
|
||||
|
||||
@ApiOperation("获取用户信息")
|
||||
@PostMapping("/userInfo")
|
||||
CurrentUserDto userInfo();
|
||||
|
||||
|
||||
|
||||
|
||||
@ApiOperation("是否使用初始密码")
|
||||
@PostMapping("/useInitPwd")
|
||||
Boolean useInitPwd();
|
||||
|
||||
@ApiOperation("登出")
|
||||
@PostMapping("/logout")
|
||||
String logout();
|
||||
|
||||
|
||||
@ApiOperation("验证账号")
|
||||
@PostMapping("/validateName")
|
||||
Boolean validateName(Map<String, String> nameDto);
|
||||
@ -46,7 +42,6 @@ public interface AuthApi {
|
||||
@PostMapping("/isOpenLdap")
|
||||
boolean isOpenLdap();
|
||||
|
||||
|
||||
@ApiOperation("是否开启oidc")
|
||||
@PostMapping("/isOpenOidc")
|
||||
boolean isOpenOidc();
|
||||
|
@ -27,6 +27,7 @@ import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@ -40,6 +41,9 @@ import javax.servlet.http.HttpServletRequest;
|
||||
@RestController
|
||||
public class AuthServer implements AuthApi {
|
||||
|
||||
@Value("${dataease.init_password:DataEase123..}")
|
||||
private String DEFAULT_PWD;
|
||||
|
||||
@Autowired
|
||||
private AuthUserService authUserService;
|
||||
|
||||
@ -65,14 +69,19 @@ public class AuthServer implements AuthApi {
|
||||
SysUserEntity user = authUserService.getLdapUserByName(username);
|
||||
if (ObjectUtils.isEmpty(user) || ObjectUtils.isEmpty(user.getUserId())) {
|
||||
LdapAddRequest ldapAddRequest = new LdapAddRequest();
|
||||
ldapAddRequest.setUsers(new ArrayList<XpackLdapUserEntity>() {{
|
||||
add(ldapUserEntity);
|
||||
}});
|
||||
ldapAddRequest.setUsers(new ArrayList<XpackLdapUserEntity>() {
|
||||
{
|
||||
add(ldapUserEntity);
|
||||
}
|
||||
});
|
||||
ldapAddRequest.setEnabled(1L);
|
||||
ldapAddRequest.setRoleIds(new ArrayList<Long>() {{
|
||||
add(2L);
|
||||
}});
|
||||
sysUserService.validateExistUser(ldapUserEntity.getUsername(), ldapUserEntity.getNickname(), ldapUserEntity.getEmail());
|
||||
ldapAddRequest.setRoleIds(new ArrayList<Long>() {
|
||||
{
|
||||
add(2L);
|
||||
}
|
||||
});
|
||||
sysUserService.validateExistUser(ldapUserEntity.getUsername(), ldapUserEntity.getNickname(),
|
||||
ldapUserEntity.getEmail());
|
||||
sysUserService.saveLdapUsers(ldapAddRequest);
|
||||
}
|
||||
|
||||
@ -92,9 +101,9 @@ public class AuthServer implements AuthApi {
|
||||
|
||||
// 普通登录需要验证密码
|
||||
if (loginType == 0 || !isSupportLdap) {
|
||||
//私钥解密
|
||||
// 私钥解密
|
||||
|
||||
//md5加密
|
||||
// md5加密
|
||||
pwd = CodingUtil.md5(pwd);
|
||||
|
||||
if (!StringUtils.equals(pwd, realPwd)) {
|
||||
@ -128,6 +137,16 @@ public class AuthServer implements AuthApi {
|
||||
return userDto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean useInitPwd() {
|
||||
CurrentUserDto user = AuthUtils.getUser();
|
||||
if (null == user) {
|
||||
return false;
|
||||
}
|
||||
String md5 = CodingUtil.md5(DEFAULT_PWD);
|
||||
return StringUtils.equals(AuthUtils.getUser().getPassword(), md5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String logout() {
|
||||
String token = ServletUtils.getToken();
|
||||
@ -158,7 +177,8 @@ public class AuthServer implements AuthApi {
|
||||
@Override
|
||||
public Boolean validateName(@RequestBody Map<String, String> nameDto) {
|
||||
String userName = nameDto.get("userName");
|
||||
if (StringUtils.isEmpty(userName)) return false;
|
||||
if (StringUtils.isEmpty(userName))
|
||||
return false;
|
||||
SysUserEntity userEntity = authUserService.getUserByName(userName);
|
||||
return !ObjectUtils.isEmpty(userEntity);
|
||||
}
|
||||
@ -166,29 +186,30 @@ public class AuthServer implements AuthApi {
|
||||
@Override
|
||||
public boolean isOpenLdap() {
|
||||
Boolean licValid = PluginUtils.licValid();
|
||||
if (!licValid) return false;
|
||||
if (!licValid)
|
||||
return false;
|
||||
return authUserService.supportLdap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpenOidc() {
|
||||
Boolean licValid = PluginUtils.licValid();
|
||||
if (!licValid) return false;
|
||||
if (!licValid)
|
||||
return false;
|
||||
return authUserService.supportOidc();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPluginLoaded() {
|
||||
Boolean licValid = PluginUtils.licValid();
|
||||
if (!licValid) return false;
|
||||
if (!licValid)
|
||||
return false;
|
||||
return authUserService.pluginLoaded();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getPublicKey() {
|
||||
return RsaProperties.publicKey;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import io.dataease.base.domain.SysMenu;
|
||||
import io.dataease.base.domain.SysMenuExample;
|
||||
import io.dataease.base.mapper.SysMenuMapper;
|
||||
import io.dataease.base.mapper.ext.ExtPluginSysMenuMapper;
|
||||
import io.dataease.base.mapper.ext.ExtSysMenuMapper;
|
||||
import io.dataease.plugins.common.dto.PluginSysMenu;
|
||||
import io.dataease.plugins.util.PluginUtils;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
@ -30,12 +31,16 @@ public class DynamicMenuServiceImpl implements DynamicMenuService {
|
||||
@Resource
|
||||
private ExtPluginSysMenuMapper extPluginSysMenuMapper;
|
||||
|
||||
@Resource
|
||||
private ExtSysMenuMapper extSysMenuMapper;
|
||||
|
||||
@Override
|
||||
public List<DynamicMenuDto> load(String userId) {
|
||||
SysMenuExample sysMenuExample = new SysMenuExample();
|
||||
sysMenuExample.createCriteria().andTypeLessThanOrEqualTo(1);
|
||||
sysMenuExample.setOrderByClause(" menu_sort ");
|
||||
List<SysMenu> sysMenus = sysMenuMapper.selectByExample(sysMenuExample);
|
||||
// SysMenuExample sysMenuExample = new SysMenuExample();
|
||||
// sysMenuExample.createCriteria().andTypeLessThanOrEqualTo(1);
|
||||
// sysMenuExample.setOrderByClause(" menu_sort ");
|
||||
// List<SysMenu> sysMenus = sysMenuMapper.selectByExample(sysMenuExample);
|
||||
List<SysMenu> sysMenus = extSysMenuMapper.querySysMenu();
|
||||
List<DynamicMenuDto> dynamicMenuDtos = sysMenus.stream().map(this::convert).collect(Collectors.toList());
|
||||
//增加插件中的菜单
|
||||
List<PluginSysMenu> pluginSysMenus = PluginUtils.pluginMenus();
|
||||
|
@ -17,16 +17,13 @@ import org.springframework.core.env.Environment;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
public class JWTUtils {
|
||||
|
||||
|
||||
// token过期时间1min (过期会自动刷新续命 目的是避免一直都是同一个token )
|
||||
private static final long EXPIRE_TIME = 1 * 60 * 1000;
|
||||
// 登录间隔时间10min 超过这个时间强制重新登录
|
||||
private static long Login_Interval;
|
||||
|
||||
|
||||
/**
|
||||
* 校验token是否正确
|
||||
*
|
||||
@ -82,7 +79,8 @@ public class JWTUtils {
|
||||
public static boolean loginExpire(String token) {
|
||||
if (Login_Interval == 0) {
|
||||
// 默认超时时间是8h
|
||||
int minute = CommonBeanFactory.getBean(Environment.class).getProperty("dataease.login_timeout", Integer.class, 8 * 60);
|
||||
Long minute = CommonBeanFactory.getBean(Environment.class).getProperty("dataease.login_timeout", Long.class,
|
||||
8 * 60L);
|
||||
// 分钟换算成毫秒
|
||||
Login_Interval = minute * 1000 * 60;
|
||||
}
|
||||
@ -128,19 +126,19 @@ public class JWTUtils {
|
||||
|
||||
public static String signLink(String resourceId, Long userId, String secret) {
|
||||
Algorithm algorithm = Algorithm.HMAC256(secret);
|
||||
if(userId == null){
|
||||
if (userId == null) {
|
||||
return JWT.create().withClaim("resourceId", resourceId).sign(algorithm);
|
||||
}else {
|
||||
} else {
|
||||
return JWT.create().withClaim("resourceId", resourceId).withClaim("userId", userId).sign(algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean verifyLink(String token, String resourceId, Long userId, String secret) {
|
||||
public static boolean verifyLink(String token, String resourceId, Long userId, String secret) {
|
||||
Algorithm algorithm = Algorithm.HMAC256(secret);
|
||||
JWTVerifier verifier;
|
||||
if(userId == null){
|
||||
if (userId == null) {
|
||||
verifier = JWT.require(algorithm).withClaim("resourceId", resourceId).build();
|
||||
}else {
|
||||
} else {
|
||||
verifier = JWT.require(algorithm).withClaim("resourceId", resourceId).withClaim("userId", userId).build();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.dataease.base.mapper.ext;
|
||||
|
||||
import io.dataease.base.domain.SysMenu;
|
||||
import io.dataease.base.mapper.ext.query.GridExample;
|
||||
import io.dataease.controller.sys.request.SimpleTreeNode;
|
||||
|
||||
@ -10,4 +11,6 @@ public interface ExtSysMenuMapper {
|
||||
List<SimpleTreeNode> allNodes();
|
||||
|
||||
List<SimpleTreeNode> nodesByExample(GridExample example);
|
||||
|
||||
List<SysMenu> querySysMenu();
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
<result property="pid" column="pid" javaType="java.lang.Long"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap id="ExtBaseResultMap" type="io.dataease.base.domain.SysMenu" extends="io.dataease.base.mapper.SysMenuMapper.BaseResultMap"></resultMap>
|
||||
|
||||
<select id="allNodes" resultMap="simpleNode">
|
||||
select menu_id as id, pid from sys_menu where hidden != 1
|
||||
</select>
|
||||
@ -19,4 +21,27 @@
|
||||
</select>
|
||||
|
||||
|
||||
<select id="querySysMenu" resultMap="ExtBaseResultMap">
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
sys_menu
|
||||
WHERE
|
||||
type <= 1
|
||||
AND (
|
||||
sys_menu.menu_id != 61
|
||||
OR EXISTS (
|
||||
SELECT
|
||||
1
|
||||
FROM
|
||||
system_parameter
|
||||
WHERE
|
||||
param_key = 'ui.openHomePage'
|
||||
AND param_value = 'true'
|
||||
)
|
||||
)
|
||||
ORDER BY
|
||||
menu_sort
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
@ -0,0 +1,9 @@
|
||||
package io.dataease.base.mapper.ext;
|
||||
|
||||
public interface ExtTaskMapper {
|
||||
|
||||
int runningCount(Long taskId);
|
||||
|
||||
void resetRunnings(Long taskId);
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<?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.base.mapper.ext.ExtTaskMapper">
|
||||
|
||||
<select id="runningCount" resultType="java.lang.Integer">
|
||||
select count(*) as count from sys_task_instance where task_id = #{taskId} and status = 0
|
||||
</select>
|
||||
|
||||
<update id="resetRunnings">
|
||||
update sys_task_instance set status = -1, info = 'System Interrupt Error' where task_id = #{taskId} and status = 0
|
||||
</update>
|
||||
|
||||
</mapper>
|
@ -0,0 +1,113 @@
|
||||
package io.dataease.commons.pool;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import io.dataease.commons.utils.LogUtil;
|
||||
|
||||
public class PriorityThreadPoolExecutor extends ThreadPoolExecutor {
|
||||
|
||||
public static AtomicInteger globaInteger = new AtomicInteger(1);
|
||||
|
||||
private ThreadLocal<Integer> local = new ThreadLocal<Integer>() {
|
||||
@Override
|
||||
protected Integer initialValue() {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit) {
|
||||
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, getWorkQueue());
|
||||
}
|
||||
|
||||
public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
|
||||
ThreadFactory threadFactory) {
|
||||
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, getWorkQueue(), threadFactory);
|
||||
}
|
||||
|
||||
public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
|
||||
RejectedExecutionHandler handler) {
|
||||
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, getWorkQueue(), handler);
|
||||
}
|
||||
|
||||
public PriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
|
||||
ThreadFactory threadFactory, RejectedExecutionHandler handler) {
|
||||
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, getWorkQueue(), threadFactory, handler);
|
||||
}
|
||||
|
||||
protected static PriorityBlockingQueue getWorkQueue() {
|
||||
return new PriorityBlockingQueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
int andIncrement = globaInteger.getAndIncrement();
|
||||
Integer theadInteger = local.get();
|
||||
try {
|
||||
if (theadInteger == 0) {
|
||||
this.execute(command, 0);
|
||||
} else {
|
||||
this.execute(command, andIncrement);
|
||||
}
|
||||
|
||||
} finally {
|
||||
local.set(1);
|
||||
}
|
||||
}
|
||||
|
||||
public void execute(Runnable command, int priority) {
|
||||
super.execute(new PriorityRunnable(command, priority));
|
||||
}
|
||||
|
||||
public <T> Future<T> submit(Callable<T> task, int priority) {
|
||||
local.set(priority);
|
||||
return super.submit(task);
|
||||
}
|
||||
|
||||
protected static class PriorityRunnable<E extends Comparable<? super E>>
|
||||
implements Runnable, Comparable<PriorityRunnable<E>> {
|
||||
private final static AtomicLong seq = new AtomicLong();
|
||||
private final long seqNum;
|
||||
Runnable run;
|
||||
private int priority;
|
||||
|
||||
public PriorityRunnable(Runnable run, int priority) {
|
||||
seqNum = seq.getAndIncrement();
|
||||
this.run = run;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setPriority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public Runnable getRun() {
|
||||
return run;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
LogUtil.info("number " + priority + " is starting...");
|
||||
this.run.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(PriorityRunnable<E> other) {
|
||||
int res = 0;
|
||||
if (this.priority == other.priority) {
|
||||
if (other.run != this.run) {// ASC
|
||||
res = (seqNum < other.seqNum ? -1 : 1);
|
||||
}
|
||||
} else {// DESC
|
||||
res = this.priority > other.priority ? 1 : -1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package io.dataease.commons.pool;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@ConfigurationProperties(prefix = "detask", ignoreInvalidFields = true)
|
||||
@Data
|
||||
@Component
|
||||
public class PriorityThreadPoolProperties {
|
||||
|
||||
private int corePoolSize = 2;
|
||||
private int maximumPoolSize = 100;
|
||||
private int keepAliveTime = 60;
|
||||
|
||||
}
|
@ -1,15 +1,25 @@
|
||||
package io.dataease.config;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import io.dataease.commons.pool.PriorityThreadPoolExecutor;
|
||||
import io.dataease.commons.pool.PriorityThreadPoolProperties;
|
||||
|
||||
@EnableAsync(proxyTargetClass = true)
|
||||
@Configuration
|
||||
public class AsyncConfig {
|
||||
|
||||
@Resource
|
||||
private PriorityThreadPoolProperties priorityThreadPoolProperties;
|
||||
|
||||
@Bean
|
||||
public AsyncTaskExecutor taskExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
@ -18,4 +28,18 @@ public class AsyncConfig {
|
||||
executor.setMaxPoolSize(10);
|
||||
return executor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PriorityThreadPoolExecutor priorityExecutor() {
|
||||
int corePoolSize = priorityThreadPoolProperties.getCorePoolSize();
|
||||
|
||||
int maximumPoolSize = priorityThreadPoolProperties.getMaximumPoolSize();
|
||||
|
||||
int keepAliveTime = priorityThreadPoolProperties.getKeepAliveTime();
|
||||
|
||||
PriorityThreadPoolExecutor executor = new PriorityThreadPoolExecutor(corePoolSize, maximumPoolSize,
|
||||
keepAliveTime, TimeUnit.SECONDS);
|
||||
return executor;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
package io.dataease.controller.wizard;
|
||||
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
|
||||
import io.dataease.service.wizard.ReptileService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Map;
|
||||
|
||||
@Api(tags = "首页")
|
||||
@ApiSupport(order = 80)
|
||||
@RestController
|
||||
@RequestMapping("Reptile")
|
||||
public class ReptileController {
|
||||
|
||||
@Resource
|
||||
private ReptileService reptileService;
|
||||
|
||||
@GetMapping("lastActive")
|
||||
@ApiOperation("获取官方Blog最新动态")
|
||||
public Map<String, String> lastActive() {
|
||||
return reptileService.lastActive();
|
||||
}
|
||||
}
|
@ -28,7 +28,7 @@ public class ScheduleManager {
|
||||
* @throws SchedulerException
|
||||
*/
|
||||
public void addSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class<? extends Job> cls, int repeatIntervalTime,
|
||||
JobDataMap jobDataMap) throws SchedulerException {
|
||||
JobDataMap jobDataMap) throws SchedulerException {
|
||||
|
||||
JobBuilder jobBuilder = JobBuilder.newJob(cls).withIdentity(jobKey);
|
||||
|
||||
@ -46,7 +46,8 @@ public class ScheduleManager {
|
||||
scheduler.scheduleJob(jd, trigger);
|
||||
}
|
||||
|
||||
public void addSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class<? extends Job> cls, int repeatIntervalTime) throws SchedulerException {
|
||||
public void addSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class<? extends Job> cls, int repeatIntervalTime)
|
||||
throws SchedulerException {
|
||||
addSimpleJob(jobKey, triggerKey, cls, repeatIntervalTime);
|
||||
}
|
||||
|
||||
@ -59,7 +60,8 @@ public class ScheduleManager {
|
||||
* @param cron
|
||||
* @param jobDataMap
|
||||
*/
|
||||
public void addCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, Date startTime, Date endTime, JobDataMap jobDataMap) {
|
||||
public void addCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, Date startTime,
|
||||
Date endTime, JobDataMap jobDataMap) {
|
||||
try {
|
||||
|
||||
LogUtil.info("addCronJob: " + triggerKey.getName() + "," + triggerKey.getGroup());
|
||||
@ -99,7 +101,8 @@ public class ScheduleManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void addCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, Date startTime, Date endTime) {
|
||||
public void addCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, Date startTime,
|
||||
Date endTime) {
|
||||
addCronJob(jobKey, triggerKey, jobClass, cron, startTime, endTime, null);
|
||||
}
|
||||
|
||||
@ -140,7 +143,8 @@ public class ScheduleManager {
|
||||
* @param cron
|
||||
* @throws SchedulerException
|
||||
*/
|
||||
public void modifyCronJobTime(TriggerKey triggerKey, String cron, Date startTime, Date endTime) throws SchedulerException {
|
||||
public void modifyCronJobTime(TriggerKey triggerKey, String cron, Date startTime, Date endTime)
|
||||
throws SchedulerException {
|
||||
|
||||
LogUtil.info("modifyCronJobTime: " + triggerKey.getName() + "," + triggerKey.getGroup());
|
||||
|
||||
@ -151,7 +155,6 @@ public class ScheduleManager {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/** 方式一 :调用 rescheduleJob 开始 */
|
||||
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();// 触发器
|
||||
|
||||
@ -279,7 +282,6 @@ public class ScheduleManager {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void startJobs(Scheduler sched) {
|
||||
try {
|
||||
sched.start();
|
||||
@ -289,7 +291,6 @@ public class ScheduleManager {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void shutdownJobs(Scheduler sched) {
|
||||
try {
|
||||
if (!sched.isShutdown()) {
|
||||
@ -312,7 +313,7 @@ public class ScheduleManager {
|
||||
* @throws SchedulerException
|
||||
*/
|
||||
public void addOrUpdateSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class clz,
|
||||
int intervalTime, JobDataMap jobDataMap) throws SchedulerException {
|
||||
int intervalTime, JobDataMap jobDataMap) throws SchedulerException {
|
||||
|
||||
if (scheduler.checkExists(triggerKey)) {
|
||||
modifySimpleJobTime(triggerKey, intervalTime);
|
||||
@ -323,7 +324,7 @@ public class ScheduleManager {
|
||||
}
|
||||
|
||||
public void addOrUpdateSingleJob(JobKey jobKey, TriggerKey triggerKey, Class clz,
|
||||
Date date, JobDataMap jobDataMap) throws SchedulerException {
|
||||
Date date, JobDataMap jobDataMap) throws SchedulerException {
|
||||
if (scheduler.checkExists(triggerKey)) {
|
||||
modifySingleJobTime(triggerKey, date);
|
||||
} else {
|
||||
@ -333,15 +334,15 @@ public class ScheduleManager {
|
||||
}
|
||||
|
||||
public void addOrUpdateSingleJob(JobKey jobKey, TriggerKey triggerKey, Class clz,
|
||||
Date date) throws SchedulerException {
|
||||
Date date) throws SchedulerException {
|
||||
addOrUpdateSingleJob(jobKey, triggerKey, clz, date, null);
|
||||
}
|
||||
|
||||
public void addOrUpdateSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class clz, int intervalTime) throws SchedulerException {
|
||||
public void addOrUpdateSimpleJob(JobKey jobKey, TriggerKey triggerKey, Class clz, int intervalTime)
|
||||
throws SchedulerException {
|
||||
addOrUpdateSimpleJob(jobKey, triggerKey, clz, intervalTime, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加或修改 cronJob
|
||||
*
|
||||
@ -352,7 +353,8 @@ public class ScheduleManager {
|
||||
* @param jobDataMap
|
||||
* @throws SchedulerException
|
||||
*/
|
||||
public void addOrUpdateCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, Date startTime, Date endTime, JobDataMap jobDataMap) throws SchedulerException {
|
||||
public void addOrUpdateCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, Date startTime,
|
||||
Date endTime, JobDataMap jobDataMap) throws SchedulerException {
|
||||
|
||||
LogUtil.info("AddOrUpdateCronJob: " + jobKey.getName() + "," + triggerKey.getGroup());
|
||||
|
||||
@ -363,7 +365,8 @@ public class ScheduleManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void addOrUpdateCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, Date startTime, Date endTime) throws SchedulerException {
|
||||
public void addOrUpdateCronJob(JobKey jobKey, TriggerKey triggerKey, Class jobClass, String cron, Date startTime,
|
||||
Date endTime) throws SchedulerException {
|
||||
addOrUpdateCronJob(jobKey, triggerKey, jobClass, cron, startTime, endTime, null);
|
||||
}
|
||||
|
||||
@ -398,7 +401,8 @@ public class ScheduleManager {
|
||||
if (!CronExpression.isValidExpression(cron)) {
|
||||
DataEaseException.throwException("cron :" + cron + " error");
|
||||
}
|
||||
return TriggerBuilder.newTrigger().withIdentity("Calculate Date").withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
|
||||
return TriggerBuilder.newTrigger().withIdentity("Calculate Date")
|
||||
.withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
|
||||
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,6 @@ import java.util.Date;
|
||||
|
||||
public abstract class TaskHandler implements InitializingBean {
|
||||
|
||||
private static final String[] week = {"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY"};
|
||||
|
||||
|
||||
public void addTask(ScheduleManager scheduleManager, GlobalTaskEntity taskEntity) throws Exception {
|
||||
// 1。首先看看是否过期
|
||||
Long endTime = taskEntity.getEndTime();
|
||||
@ -30,12 +27,11 @@ public abstract class TaskHandler implements InitializingBean {
|
||||
if (ObjectUtils.isNotEmpty(taskEntity.getEndTime())) {
|
||||
new Date(taskEntity.getEndTime());
|
||||
}
|
||||
Class executor = this.getClass();
|
||||
Class<? extends TaskHandler> executor = this.getClass();
|
||||
String cron = cron(taskEntity);
|
||||
scheduleManager.addOrUpdateCronJob(jobKey, triggerKey, executor, cron, start, end, jobDataMap(taskEntity));
|
||||
}
|
||||
|
||||
|
||||
protected abstract JobDataMap jobDataMap(GlobalTaskEntity taskEntity);
|
||||
|
||||
private String cron(GlobalTaskEntity taskEntity) {
|
||||
@ -54,36 +50,34 @@ public abstract class TaskHandler implements InitializingBean {
|
||||
instance.setTime(date);
|
||||
|
||||
if (taskEntity.getRateType() == 0) {
|
||||
return
|
||||
instance.get(Calendar.SECOND) + " " +
|
||||
instance.get(Calendar.MINUTE) + " " +
|
||||
instance.get(Calendar.HOUR_OF_DAY) + " * * ?";
|
||||
return instance.get(Calendar.SECOND) + " " +
|
||||
instance.get(Calendar.MINUTE) + " " +
|
||||
instance.get(Calendar.HOUR_OF_DAY) + " * * ?";
|
||||
}
|
||||
if (taskEntity.getRateType() == 1) {
|
||||
return
|
||||
instance.get(Calendar.SECOND) + " " +
|
||||
instance.get(Calendar.MINUTE) + " " +
|
||||
instance.get(Calendar.HOUR_OF_DAY) + " ? * " +
|
||||
getDayOfWeek(instance);
|
||||
return instance.get(Calendar.SECOND) + " " +
|
||||
instance.get(Calendar.MINUTE) + " " +
|
||||
instance.get(Calendar.HOUR_OF_DAY) + " ? * " +
|
||||
getDayOfWeek(instance);
|
||||
}
|
||||
if (taskEntity.getRateType() == 2) {
|
||||
return
|
||||
instance.get(Calendar.SECOND) + " " +
|
||||
instance.get(Calendar.MINUTE) + " " +
|
||||
instance.get(Calendar.HOUR_OF_DAY) + " " +
|
||||
instance.get(Calendar.DATE) + " * ?";
|
||||
return instance.get(Calendar.SECOND) + " " +
|
||||
instance.get(Calendar.MINUTE) + " " +
|
||||
instance.get(Calendar.HOUR_OF_DAY) + " " +
|
||||
instance.get(Calendar.DATE) + " * ?";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract void resetRunningInstance(Long taskId);
|
||||
|
||||
private String getDayOfWeek(Calendar instance) {
|
||||
int index = instance.get(Calendar.DAY_OF_WEEK);
|
||||
index = (index + 1) % 7;
|
||||
index = (index + 1) % 7;
|
||||
return String.valueOf(index);
|
||||
}
|
||||
|
||||
|
||||
public void removeTask(ScheduleManager scheduleManager, GlobalTaskEntity taskEntity) {
|
||||
JobKey jobKey = new JobKey(taskEntity.getTaskId().toString());
|
||||
TriggerKey triggerKey = new TriggerKey(taskEntity.getTaskId().toString());
|
||||
@ -95,14 +89,16 @@ public abstract class TaskHandler implements InitializingBean {
|
||||
scheduleManager.fireNow(jobKey);
|
||||
}
|
||||
|
||||
|
||||
//判断任务是否过期
|
||||
// 判断任务是否过期
|
||||
public Boolean taskExpire(Long endTime) {
|
||||
if (ObjectUtils.isEmpty(endTime)) return false;
|
||||
if (ObjectUtils.isEmpty(endTime))
|
||||
return false;
|
||||
Long now = System.currentTimeMillis();
|
||||
return now > endTime;
|
||||
}
|
||||
|
||||
protected abstract Boolean taskIsRunning(Long taskId);
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
String beanName = null;
|
||||
|
@ -5,6 +5,7 @@ import io.dataease.auth.entity.TokenInfo;
|
||||
import io.dataease.auth.service.AuthUserService;
|
||||
import io.dataease.auth.service.impl.AuthUserServiceImpl;
|
||||
import io.dataease.auth.util.JWTUtils;
|
||||
import io.dataease.base.mapper.ext.ExtTaskMapper;
|
||||
import io.dataease.commons.utils.CommonBeanFactory;
|
||||
import io.dataease.commons.utils.LogUtil;
|
||||
import io.dataease.commons.utils.ServletUtils;
|
||||
@ -20,6 +21,7 @@ import io.dataease.service.system.EmailService;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.quartz.*;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@ -46,6 +48,16 @@ public class EmailTaskHandler extends TaskHandler implements Job {
|
||||
return jobDataMap;
|
||||
}
|
||||
|
||||
public EmailTaskHandler proxy() {
|
||||
return CommonBeanFactory.getBean(EmailTaskHandler.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean taskIsRunning(Long taskId) {
|
||||
ExtTaskMapper extTaskMapper = CommonBeanFactory.getBean(ExtTaskMapper.class);
|
||||
return extTaskMapper.runningCount(taskId) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(JobExecutionContext context) throws JobExecutionException {
|
||||
// 插件没有加载 空转
|
||||
@ -54,11 +66,16 @@ public class EmailTaskHandler extends TaskHandler implements Job {
|
||||
|
||||
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
|
||||
GlobalTaskEntity taskEntity = (GlobalTaskEntity) jobDataMap.get("taskEntity");
|
||||
ScheduleManager scheduleManager = SpringContextUtil.getBean(ScheduleManager.class);
|
||||
if (taskExpire(taskEntity.getEndTime())) {
|
||||
ScheduleManager scheduleManager = SpringContextUtil.getBean(ScheduleManager.class);
|
||||
removeTask(scheduleManager, taskEntity);
|
||||
return;
|
||||
}
|
||||
if (taskIsRunning(taskEntity.getTaskId())) {
|
||||
LogUtil.info("Skip synchronization task: {} ,due to task status is {}",
|
||||
taskEntity.getTaskId(), "running");
|
||||
return;
|
||||
}
|
||||
|
||||
GlobalTaskInstance taskInstance = buildInstance(taskEntity);
|
||||
Long instanceId = saveInstance(taskInstance);
|
||||
@ -67,10 +84,15 @@ public class EmailTaskHandler extends TaskHandler implements Job {
|
||||
XpackEmailTemplateDTO emailTemplate = (XpackEmailTemplateDTO) jobDataMap.get("emailTemplate");
|
||||
SysUserEntity creator = (SysUserEntity) jobDataMap.get("creator");
|
||||
LogUtil.info("start execute send panel report task...");
|
||||
sendReport(taskInstance, emailTemplate, creator);
|
||||
proxy().sendReport(taskInstance, emailTemplate, creator);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetRunningInstance(Long taskId) {
|
||||
ExtTaskMapper extTaskMapper = CommonBeanFactory.getBean(ExtTaskMapper.class);
|
||||
extTaskMapper.resetRunnings(taskId);
|
||||
}
|
||||
|
||||
public Long saveInstance(GlobalTaskInstance taskInstance) {
|
||||
EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class);
|
||||
@ -99,11 +121,12 @@ public class EmailTaskHandler extends TaskHandler implements Job {
|
||||
emailXpackService.saveInstance(taskInstance);
|
||||
}
|
||||
|
||||
|
||||
@Async("priorityExecutor")
|
||||
public void sendReport(GlobalTaskInstance taskInstance, XpackEmailTemplateDTO emailTemplateDTO,
|
||||
SysUserEntity user) {
|
||||
SysUserEntity user) {
|
||||
EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class);
|
||||
try {
|
||||
|
||||
String panelId = emailTemplateDTO.getPanelId();
|
||||
String url = panelUrl(panelId);
|
||||
String token = tokenByUser(user);
|
||||
@ -116,11 +139,15 @@ public class EmailTaskHandler extends TaskHandler implements Job {
|
||||
String recipients = emailTemplateDTO.getRecipients();
|
||||
byte[] content = emailTemplateDTO.getContent();
|
||||
EmailService emailService = SpringContextUtil.getBean(EmailService.class);
|
||||
|
||||
String contentStr = "";
|
||||
if (ObjectUtils.isNotEmpty(content)) {
|
||||
contentStr = new String(content, "UTF-8");
|
||||
}
|
||||
emailService.sendWithImage(recipients, emailTemplateDTO.getTitle(), contentStr, bytes);
|
||||
emailService.sendWithImage(recipients, emailTemplateDTO.getTitle(),
|
||||
contentStr, bytes);
|
||||
|
||||
Thread.sleep(10000);
|
||||
success(taskInstance);
|
||||
} catch (Exception e) {
|
||||
error(taskInstance, e);
|
||||
|
@ -32,6 +32,7 @@ public class GlobalTaskStartListener implements ApplicationListener<ApplicationR
|
||||
tasks.stream().forEach(task -> {
|
||||
TaskHandler taskHandler = TaskStrategyFactory.getInvokeStrategy(task.getTaskType());
|
||||
try {
|
||||
taskHandler.resetRunningInstance(task.getTaskId());
|
||||
taskHandler.addTask(scheduleManager, task);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
@ -4,12 +4,13 @@ import java.util.List;
|
||||
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
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.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.dataease.commons.exception.DEException;
|
||||
import io.dataease.commons.utils.LogUtil;
|
||||
import io.dataease.plugins.config.SpringContextUtil;
|
||||
import io.dataease.plugins.xpack.theme.dto.ThemeDto;
|
||||
import io.dataease.plugins.xpack.theme.dto.ThemeItem;
|
||||
@ -20,10 +21,8 @@ import io.dataease.plugins.xpack.theme.service.ThemeXpackService;
|
||||
@RestController
|
||||
public class ThemeServer {
|
||||
|
||||
|
||||
|
||||
@PostMapping("/themes")
|
||||
public List<ThemeDto> themes(){
|
||||
public List<ThemeDto> themes() {
|
||||
|
||||
ThemeXpackService themeXpackService = SpringContextUtil.getBean(ThemeXpackService.class);
|
||||
return themeXpackService.themes();
|
||||
@ -36,15 +35,22 @@ public class ThemeServer {
|
||||
}
|
||||
|
||||
@PostMapping("/save")
|
||||
public void save(@RequestPart("request") ThemeRequest request, @RequestPart(value = "file", required = false) MultipartFile bodyFile) {
|
||||
public void save(@RequestPart("request") ThemeRequest request,
|
||||
@RequestPart(value = "file", required = false) MultipartFile bodyFile) {
|
||||
ThemeXpackService themeXpackService = SpringContextUtil.getBean(ThemeXpackService.class);
|
||||
themeXpackService.save(request, bodyFile);
|
||||
try {
|
||||
themeXpackService.save(request, bodyFile);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
DEException.throwException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@PostMapping("/delete/{themeId}")
|
||||
public void save(@PathVariable("themeId") int themeId) {
|
||||
public void delete(@PathVariable("themeId") int themeId) {
|
||||
ThemeXpackService themeXpackService = SpringContextUtil.getBean(ThemeXpackService.class);
|
||||
themeXpackService.deleteTheme(themeId);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package io.dataease.plugins.server;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.dataease.commons.exception.DEException;
|
||||
import io.dataease.commons.pool.PriorityThreadPoolExecutor;
|
||||
import io.dataease.commons.utils.*;
|
||||
import io.dataease.plugins.common.entity.GlobalTaskEntity;
|
||||
import io.dataease.plugins.common.entity.GlobalTaskInstance;
|
||||
@ -23,6 +24,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Api(tags = "xpack:定时报告")
|
||||
@RequestMapping("/plugin/task")
|
||||
@ -32,6 +36,9 @@ public class XEmailTaskServer {
|
||||
@Autowired
|
||||
private ScheduleService scheduleService;
|
||||
|
||||
@Resource
|
||||
private PriorityThreadPoolExecutor priorityExecutor;
|
||||
|
||||
@PostMapping("/queryTasks/{goPage}/{pageSize}")
|
||||
public Pager<List<XpackTaskGridDTO>> queryTask(@PathVariable int goPage, @PathVariable int pageSize,
|
||||
@RequestBody XpackGridRequest request) {
|
||||
@ -85,7 +92,19 @@ public class XEmailTaskServer {
|
||||
String token = ServletUtils.getToken();
|
||||
String fileId = null;
|
||||
try {
|
||||
fileId = emailXpackService.print(url, token, buildPixel(request.getPixel()));
|
||||
Future<?> future = priorityExecutor.submit(() -> {
|
||||
try {
|
||||
return emailXpackService.print(url, token, buildPixel(request.getPixel()));
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
DEException.throwException("预览失败,请联系管理员");
|
||||
}
|
||||
return null;
|
||||
}, 0);
|
||||
Object object = future.get();
|
||||
if (ObjectUtils.isNotEmpty(object)) {
|
||||
fileId = object.toString();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
DEException.throwException("预览失败,请联系管理员");
|
||||
|
@ -0,0 +1,45 @@
|
||||
package io.dataease.service.wizard;
|
||||
|
||||
import io.dataease.commons.utils.HttpClientUtil;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Author: wangjiahao
|
||||
* Date: 2022/1/11
|
||||
* Description:
|
||||
*/
|
||||
@Service
|
||||
public class ReptileService {
|
||||
String blogUrl = "https://blog.fit2cloud.com/?cat=321";
|
||||
|
||||
public Map<String, String> lastActive() {
|
||||
Map<String, String> result = new HashMap();
|
||||
try {
|
||||
//爬取最新数据
|
||||
Document doc = Jsoup.parse(HttpClientUtil.get(blogUrl, null));
|
||||
Elements elementsContent = doc.getElementsByAttributeValue("rel", "bookmark");
|
||||
Elements elementsTime = doc.getElementsByTag("time");
|
||||
Element lastInfo = elementsContent.get(0);
|
||||
result.put("title",lastInfo.attr("title"));
|
||||
result.put("href",lastInfo.attr("href"));
|
||||
result.put("time",elementsTime.get(0).childNode(0).outerHtml());
|
||||
} catch (Exception e) {
|
||||
//ignore
|
||||
result.put("title","支持移动端展示,数据源新增对DB2的支持,DataEase开源数据可视化分析平台v1.6.0发布");
|
||||
result.put("href","https://blog.fit2cloud.com/?p=3200");
|
||||
result.put("time","2022年1月10日");
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -6,4 +6,8 @@ CREATE TABLE `dataset_column_permissions` (
|
||||
`permissions` longtext DEFAULT NULL COMMENT '权限',
|
||||
`update_time` bigint(13) NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
|
||||
|
||||
INSERT INTO `sys_menu` (`menu_id`, `pid`, `sub_count`, `type`, `title`, `name`, `component`, `menu_sort`, `icon`, `path`, `i_frame`, `cache`, `hidden`, `permission`, `create_by`, `update_by`, `create_time`, `update_time`) VALUES (61, 0, 0, 1, '首页', 'wizard', 'wizard/index', 0, '', '/wizard', b'1', b'0', b'0', NULL, NULL, NULL, NULL, 1614915491036);
|
||||
INSERT INTO `system_parameter` (`param_key`, `param_value`, `type`, `sort`) VALUES ('ui.openHomePage', 'true', 'boolean', 13);
|
||||
|
||||
|
@ -223,6 +223,7 @@ authsource_configuration_is_null=Authentication source configuration cannot be e
|
||||
角色表单=Role Form
|
||||
重置密码=Reset Password
|
||||
关于=About Us
|
||||
首页=Home Page
|
||||
i18n_auth_view=View
|
||||
i18n_auth_use=Use
|
||||
i18n_auth_export=Export
|
||||
|
@ -222,6 +222,7 @@ authsource_configuration_is_null=认证源配置不能为空
|
||||
角色表单=角色表单
|
||||
重置密码=重置密码
|
||||
关于=关于
|
||||
首页=首页
|
||||
i18n_auth_view=查看
|
||||
i18n_auth_use=使用
|
||||
i18n_auth_export=导出
|
||||
|
@ -225,6 +225,7 @@ authsource_configuration_is_null=認證源配置不能為空
|
||||
角色表单=角色表單
|
||||
重置密码=重置密碼
|
||||
关于=關於
|
||||
首页=首頁
|
||||
i18n_auth_view=查看
|
||||
i18n_auth_use=使用
|
||||
i18n_auth_export=導出
|
||||
|
@ -22,6 +22,13 @@ export function logout() {
|
||||
})
|
||||
}
|
||||
|
||||
export function needModifyPwd() {
|
||||
return request({
|
||||
url: '/api/auth/useInitPwd',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function validateUserName(data) {
|
||||
return request({
|
||||
url: '/api/auth/validateName',
|
||||
|
8
frontend/src/api/wizard/wizard.js
Normal file
@ -0,0 +1,8 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function blogLastActive() {
|
||||
return request({
|
||||
url: 'Reptile/lastActive',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
BIN
frontend/src/assets/deV.png
Normal file
After Width: | Height: | Size: 250 KiB |
@ -535,7 +535,7 @@ export default {
|
||||
return this.$store.state.curComponent
|
||||
},
|
||||
curGap() {
|
||||
return (this.canvasStyleData.panel.gap === 'yes' && this.element.auxiliaryMatrix && this.element.type !== 'custom') ? this.componentGap : 0
|
||||
return (this.canvasStyleData.panel.gap === 'yes' && this.element.auxiliaryMatrix) ? this.componentGap : 0
|
||||
},
|
||||
...mapState([
|
||||
'editor',
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="bar-main">
|
||||
<input id="input" ref="files" type="file" accept="image/*" hidden @click="e => {e.target.value = '';}" @change="handleFileChange">
|
||||
<div v-if="linkageAreaShow" style="margin-right: -1px;width: 18px">
|
||||
<el-checkbox v-model="linkageInfo.linkageActive" />
|
||||
<linkage-field v-if="linkageInfo.linkageActive" :element="element" />
|
||||
@ -25,6 +26,9 @@
|
||||
<span :title="$t('panel.cancel_linkage')">
|
||||
<i v-if="curComponent.type==='view'&&existLinkage" class="icon iconfont icon-quxiaoliandong" @click.stop="clearLinkage" />
|
||||
</span>
|
||||
<span :title="$t('panel.switch_picture')">
|
||||
<i v-if="activeModel==='edit'&&curComponent&&curComponent.type==='picture-add'" class="icon iconfont icon-genghuan" @click.stop="goFile" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -34,6 +38,7 @@ import { mapState } from 'vuex'
|
||||
import bus from '@/utils/bus'
|
||||
import SettingMenu from '@/components/canvas/components/Editor/SettingMenu'
|
||||
import LinkageField from '@/components/canvas/components/Editor/LinkageField'
|
||||
import toast from '@/components/canvas/utils/toast'
|
||||
|
||||
export default {
|
||||
components: { SettingMenu, LinkageField },
|
||||
@ -207,6 +212,24 @@ export default {
|
||||
},
|
||||
linkJumpSet() {
|
||||
this.$emit('linkJumpSet')
|
||||
},
|
||||
goFile() {
|
||||
this.$refs.files.click()
|
||||
},
|
||||
handleFileChange(e) {
|
||||
const file = e.target.files[0]
|
||||
if (!file.type.includes('image')) {
|
||||
toast('只能插入图片')
|
||||
return
|
||||
}
|
||||
const reader = new FileReader()
|
||||
reader.onload = (res) => {
|
||||
const fileResult = res.target.result
|
||||
this.curComponent.propValue = fileResult
|
||||
this.$store.commit('recordSnapshot', 'handleFileChange')
|
||||
}
|
||||
|
||||
reader.readAsDataURL(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,10 @@ import {
|
||||
HYPERLINKS
|
||||
} from '@/components/canvas/custom-component/component-list'
|
||||
|
||||
import {
|
||||
ApplicationContext
|
||||
} from '@/utils/ApplicationContext'
|
||||
|
||||
export function deepCopy(target) {
|
||||
if (typeof target === 'object') {
|
||||
const result = Array.isArray(target) ? [] : {}
|
||||
@ -62,28 +66,17 @@ export function mobile2MainCanvas(mainSource, mobileSource) {
|
||||
export function panelInit(componentDatas) {
|
||||
componentDatas.forEach(item => {
|
||||
if (item.component && item.component === 'de-date') {
|
||||
if (item.serviceName === 'timeDateWidget' && item.options.attrs && !item.options.attrs.default) {
|
||||
item.options.attrs.default = {
|
||||
isDynamic: false,
|
||||
dkey: 0,
|
||||
dynamicPrefix: 1,
|
||||
dynamicInfill: 'day',
|
||||
dynamicSuffix: 'before'
|
||||
}
|
||||
}
|
||||
if (item.serviceName === 'timeDateRangeWidget' && item.options.attrs && !item.options.attrs.default) {
|
||||
item.options.attrs.default = {
|
||||
isDynamic: false,
|
||||
dkey: 0,
|
||||
sDynamicPrefix: 1,
|
||||
sDynamicInfill: 'day',
|
||||
sDynamicSuffix: 'before',
|
||||
eDynamicPrefix: 1,
|
||||
eDynamicInfill: 'day',
|
||||
eDynamicSuffix: 'after'
|
||||
if (item.options.attrs &&
|
||||
(!item.options.attrs.default || (item.serviceName === 'timeYearWidget' && item.options.attrs.default.dynamicInfill !== 'year') || (item.serviceName === 'timeMonthWidget' && item.options.attrs.default.dynamicInfill !== 'month'))) {
|
||||
const widget = ApplicationContext.getService(item.serviceName)
|
||||
if (widget && widget.defaultSetting) {
|
||||
item.options.attrs.default = widget.defaultSetting()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (item.type === 'custom') {
|
||||
item.options.manualModify = false
|
||||
}
|
||||
if (item.filters && item.filters.length > 0) {
|
||||
item.filters = []
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ export default {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.my-container {
|
||||
position: absolute;
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
|
@ -64,6 +64,9 @@ export default {
|
||||
viewIds() {
|
||||
if (!this.element || !this.element.options || !this.element.options.attrs.viewIds) return ''
|
||||
return this.element.options.attrs.viewIds.toString()
|
||||
},
|
||||
manualModify() {
|
||||
return !!this.element.options.manualModify
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -72,9 +75,7 @@ export default {
|
||||
this.setCondition()
|
||||
},
|
||||
'defaultValueStr': function(value, old) {
|
||||
if ((this.element.serviceName === 'timeDateWidget' || this.element.serviceName === 'timeDateRangeWidget') &&
|
||||
this.element.options.attrs.default.isDynamic) {
|
||||
// 如果设置了动态时间 不做任何操作
|
||||
if (this.element.options.attrs.default.isDynamic) {
|
||||
return
|
||||
}
|
||||
if (value === old) return
|
||||
@ -82,13 +83,10 @@ export default {
|
||||
this.dateChange(value)
|
||||
},
|
||||
'defaultoptions': function(val, old) {
|
||||
// console.log('default chaneg')
|
||||
if (this.element.serviceName !== 'timeDateWidget' || this.element.serviceName === 'timeDateRangeWidget') {
|
||||
if (!this.element.options.attrs.default.isDynamic) {
|
||||
this.values = this.fillValueDerfault()
|
||||
this.dateChange(this.values)
|
||||
return
|
||||
}
|
||||
if (!this.element.options.attrs.default.isDynamic) {
|
||||
this.values = this.fillValueDerfault()
|
||||
this.dateChange(this.values)
|
||||
return
|
||||
}
|
||||
if (val === old) return
|
||||
const widget = ApplicationContext.getService(this.element.serviceName)
|
||||
@ -97,9 +95,7 @@ export default {
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if ((this.element.serviceName === 'timeDateWidget' || this.element.serviceName === 'timeDateRangeWidget') && this
|
||||
.element.options.attrs.default && this.element.options
|
||||
.attrs.default.isDynamic) {
|
||||
if (this.element.options.attrs.default && this.element.options.attrs.default.isDynamic) {
|
||||
if (this.element.options.attrs.default) {
|
||||
const widget = ApplicationContext.getService(this.element.serviceName)
|
||||
this.values = widget.dynamicDateFormNow(this.element)
|
||||
@ -118,6 +114,18 @@ export default {
|
||||
this.$refs.dateRef.hidePicker()
|
||||
}
|
||||
})
|
||||
bus.$on('reset-default-value', id => {
|
||||
if (this.inDraw && this.manualModify && this.element.id === id) {
|
||||
if (!this.element.options.attrs.default.isDynamic) {
|
||||
this.values = this.fillValueDerfault()
|
||||
this.dateChange(this.values)
|
||||
return
|
||||
}
|
||||
const widget = ApplicationContext.getService(this.element.serviceName)
|
||||
this.values = widget.dynamicDateFormNow(this.element)
|
||||
this.dateChange(this.values)
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
onBlur() {
|
||||
@ -145,6 +153,9 @@ export default {
|
||||
} else {
|
||||
this.element.options.value = Array.isArray(value) ? value.join() : value.toString()
|
||||
}
|
||||
this.element.options.manualModify = false
|
||||
} else {
|
||||
this.element.options.manualModify = true
|
||||
}
|
||||
this.setCondition()
|
||||
this.styleChange()
|
||||
|
@ -17,6 +17,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import bus from '@/utils/bus'
|
||||
export default {
|
||||
|
||||
props: {
|
||||
@ -45,6 +46,9 @@ export default {
|
||||
viewIds() {
|
||||
if (!this.element || !this.element.options || !this.element.options.attrs.viewIds) return ''
|
||||
return this.element.options.attrs.viewIds.toString()
|
||||
},
|
||||
manualModify() {
|
||||
return !!this.element.options.manualModify
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -64,6 +68,14 @@ export default {
|
||||
this.search()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
bus.$on('reset-default-value', id => {
|
||||
if (this.inDraw && this.manualModify && this.element.id === id) {
|
||||
this.value = this.fillValueDerfault()
|
||||
this.search()
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
search() {
|
||||
if (!this.inDraw) {
|
||||
@ -85,6 +97,9 @@ export default {
|
||||
valueChange(val) {
|
||||
if (!this.inDraw) {
|
||||
this.element.options.value = val
|
||||
this.element.options.manualModify = false
|
||||
} else {
|
||||
this.element.options.manualModify = true
|
||||
}
|
||||
},
|
||||
fillValueDerfault() {
|
||||
|
@ -17,6 +17,7 @@
|
||||
<script>
|
||||
const MIN_NUMBER = -2147483648
|
||||
const MAX_NUMBER = 2147483647
|
||||
import bus from '@/utils/bus'
|
||||
export default {
|
||||
|
||||
props: {
|
||||
@ -64,6 +65,9 @@ export default {
|
||||
viewIds() {
|
||||
if (!this.element || !this.element.options || !this.element.options.attrs.viewIds) return ''
|
||||
return this.element.options.attrs.viewIds.toString()
|
||||
},
|
||||
manualModify() {
|
||||
return !!this.element.options.manualModify
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -99,6 +103,18 @@ export default {
|
||||
this.search()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
bus.$on('reset-default-value', id => {
|
||||
if (this.inDraw && this.manualModify && this.element.id === id) {
|
||||
const values = this.element.options.value
|
||||
this.form.min = values[0]
|
||||
if (values.length > 1) {
|
||||
this.form.max = values[1]
|
||||
}
|
||||
this.search()
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
searchWithKey(index) {
|
||||
this.timeMachine = setTimeout(() => {
|
||||
@ -211,6 +227,9 @@ export default {
|
||||
if (!this.inDraw) {
|
||||
const values = [this.form.min, this.form.max]
|
||||
this.element.options.value = values
|
||||
this.element.options.manualModify = false
|
||||
} else {
|
||||
this.element.options.manualModify = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,9 +28,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { multFieldValues, linkMultFieldValues} from '@/api/dataset/dataset'
|
||||
import { multFieldValues, linkMultFieldValues } from '@/api/dataset/dataset'
|
||||
import bus from '@/utils/bus'
|
||||
import {getLinkToken, getToken} from "@/utils/auth";
|
||||
import { getLinkToken, getToken } from '@/utils/auth'
|
||||
export default {
|
||||
|
||||
props: {
|
||||
@ -70,6 +70,9 @@ export default {
|
||||
viewIds() {
|
||||
if (!this.element || !this.element.options || !this.element.options.attrs.viewIds) return ''
|
||||
return this.element.options.attrs.viewIds.toString()
|
||||
},
|
||||
manualModify() {
|
||||
return !!this.element.options.manualModify
|
||||
}
|
||||
},
|
||||
|
||||
@ -87,7 +90,7 @@ export default {
|
||||
if (typeof value === 'undefined' || value === old) return
|
||||
this.datas = []
|
||||
|
||||
let method = multFieldValues
|
||||
let method = multFieldValues
|
||||
const token = this.$store.getters.token || getToken()
|
||||
const linkToken = this.$store.getters.linkToken || getLinkToken()
|
||||
if (!token && linkToken) {
|
||||
@ -95,7 +98,7 @@ export default {
|
||||
}
|
||||
this.element.options.attrs.fieldId &&
|
||||
this.element.options.attrs.fieldId.length > 0 &&
|
||||
method({fieldIds: this.element.options.attrs.fieldId.split(',')}).then(res => {
|
||||
method({ fieldIds: this.element.options.attrs.fieldId.split(',') }).then(res => {
|
||||
this.datas = this.optionDatas(res.data)
|
||||
}) || (this.element.options.value = '')
|
||||
},
|
||||
@ -122,6 +125,12 @@ export default {
|
||||
this.$refs.deSelect.blur()
|
||||
}
|
||||
})
|
||||
bus.$on('reset-default-value', id => {
|
||||
if (this.inDraw && this.manualModify && this.element.id === id) {
|
||||
this.value = this.fillValueDerfault()
|
||||
this.changeValue(this.value)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
@ -132,13 +141,13 @@ export default {
|
||||
this.value = this.fillValueDerfault()
|
||||
this.datas = []
|
||||
if (this.element.options.attrs.fieldId) {
|
||||
let method = multFieldValues
|
||||
let method = multFieldValues
|
||||
const token = this.$store.getters.token || getToken()
|
||||
const linkToken = this.$store.getters.linkToken || getLinkToken()
|
||||
if (!token && linkToken) {
|
||||
method = linkMultFieldValues
|
||||
}
|
||||
method({fieldIds: this.element.options.attrs.fieldId.split(',')}).then(res => {
|
||||
method({ fieldIds: this.element.options.attrs.fieldId.split(',') }).then(res => {
|
||||
this.datas = this.optionDatas(res.data)
|
||||
})
|
||||
}
|
||||
@ -154,6 +163,9 @@ export default {
|
||||
} else {
|
||||
this.element.options.value = Array.isArray(value) ? value.join() : value
|
||||
}
|
||||
this.element.options.manualModify = false
|
||||
} else {
|
||||
this.element.options.manualModify = true
|
||||
}
|
||||
this.setCondition()
|
||||
this.styleChange()
|
||||
|
@ -38,6 +38,7 @@
|
||||
<script>
|
||||
import { multFieldValues, linkMultFieldValues } from '@/api/dataset/dataset'
|
||||
import { getLinkToken, getToken } from '@/utils/auth'
|
||||
import bus from '@/utils/bus'
|
||||
export default {
|
||||
|
||||
props: {
|
||||
@ -89,6 +90,9 @@ export default {
|
||||
viewIds() {
|
||||
if (!this.element || !this.element.options || !this.element.options.attrs.viewIds) return ''
|
||||
return this.element.options.attrs.viewIds.toString()
|
||||
},
|
||||
manualModify() {
|
||||
return !!this.element.options.manualModify
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -137,6 +141,19 @@ export default {
|
||||
created() {
|
||||
this.initLoad()
|
||||
},
|
||||
mounted() {
|
||||
bus.$on('reset-default-value', id => {
|
||||
if (this.inDraw && this.manualModify && this.element.id === id) {
|
||||
this.value = this.fillValueDerfault()
|
||||
this.changeValue(this.value)
|
||||
|
||||
if (this.element.options.attrs.multiple) {
|
||||
this.checkAll = this.value.length === this.datas.length
|
||||
this.isIndeterminate = this.value.length > 0 && this.value.length < this.datas.length
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
initLoad() {
|
||||
@ -168,6 +185,9 @@ export default {
|
||||
} else {
|
||||
this.element.options.value = Array.isArray(value) ? value.join() : value
|
||||
}
|
||||
this.element.options.manualModify = false
|
||||
} else {
|
||||
this.element.options.manualModify = true
|
||||
}
|
||||
this.setCondition()
|
||||
this.styleChange()
|
||||
|
@ -15,7 +15,8 @@ const dialogPanel = {
|
||||
fieldId: '',
|
||||
dragItems: []
|
||||
},
|
||||
value: ''
|
||||
value: '',
|
||||
manualModify: false
|
||||
},
|
||||
defaultClass: 'tree-filter',
|
||||
component: 'de-number-range'
|
||||
|
@ -20,7 +20,8 @@ const dialogPanel = {
|
||||
fieldId: '',
|
||||
dragItems: []
|
||||
},
|
||||
value: ''
|
||||
value: '',
|
||||
manualModify: false
|
||||
},
|
||||
defaultClass: 'tree-filter',
|
||||
component: 'de-select-grid'
|
||||
|
@ -20,7 +20,8 @@ const dialogPanel = {
|
||||
fieldId: '',
|
||||
dragItems: []
|
||||
},
|
||||
value: ''
|
||||
value: '',
|
||||
manualModify: false
|
||||
},
|
||||
defaultClass: 'tree-filter',
|
||||
component: 'de-select'
|
||||
|
@ -15,7 +15,8 @@ const dialogPanel = {
|
||||
dragItems: []
|
||||
|
||||
},
|
||||
value: ''
|
||||
value: '',
|
||||
manualModify: false
|
||||
},
|
||||
defaultClass: 'text-filter',
|
||||
component: 'de-input-search'
|
||||
|
@ -20,7 +20,8 @@ const dialogPanel = {
|
||||
fieldId: '',
|
||||
dragItems: []
|
||||
},
|
||||
value: ''
|
||||
value: '',
|
||||
manualModify: false
|
||||
},
|
||||
defaultClass: 'text-filter',
|
||||
component: 'de-select-grid'
|
||||
|
@ -20,7 +20,8 @@ const dialogPanel = {
|
||||
fieldId: '',
|
||||
dragItems: []
|
||||
},
|
||||
value: ''
|
||||
value: '',
|
||||
manualModify: false
|
||||
},
|
||||
defaultClass: 'text-filter',
|
||||
component: 'de-select'
|
||||
|
@ -29,7 +29,8 @@ const dialogPanel = {
|
||||
eDynamicSuffix: 'after'
|
||||
}
|
||||
},
|
||||
value: ''
|
||||
value: '',
|
||||
manualModify: false
|
||||
},
|
||||
defaultClass: 'time-filter',
|
||||
component: 'de-date'
|
||||
@ -80,6 +81,9 @@ class TimeDateRangeServiceImpl extends WidgetService {
|
||||
return field['deType'] === 1
|
||||
})
|
||||
}
|
||||
defaultSetting() {
|
||||
return dialogPanel.options.attrs.default
|
||||
}
|
||||
getStartDayOfWeek() {
|
||||
var now = new Date() // 当前日期
|
||||
var nowDayOfWeek = now.getDay()
|
||||
|
@ -21,10 +21,27 @@ const dialogPanel = {
|
||||
dkey: 0,
|
||||
dynamicPrefix: 1,
|
||||
dynamicInfill: 'day',
|
||||
dynamicSuffix: 'before'
|
||||
dynamicSuffix: 'before',
|
||||
radioOptions: [{ value: false, text: 'dynamic_time.fix' }, { value: true, text: 'dynamic_time.dynamic' }],
|
||||
relativeOptions: [
|
||||
{ value: 0, text: 'dynamic_time.today' },
|
||||
{ value: 1, text: 'dynamic_time.yesterday' },
|
||||
{ value: 2, text: 'dynamic_time.firstOfMonth' },
|
||||
{ value: 3, text: 'dynamic_time.custom' }
|
||||
],
|
||||
custom: {
|
||||
unitsOptions: [
|
||||
{ value: 'day', text: 'dynamic_time.date' },
|
||||
{ value: 'week', text: 'dynamic_time.week' },
|
||||
{ value: 'month', text: 'dynamic_time.month' },
|
||||
{ value: 'year', text: 'dynamic_time.year' }
|
||||
],
|
||||
limits: [1, 12]
|
||||
}
|
||||
}
|
||||
},
|
||||
value: ''
|
||||
value: '',
|
||||
manualModify: false
|
||||
},
|
||||
defaultClass: 'time-filter',
|
||||
component: 'de-date'
|
||||
@ -75,6 +92,9 @@ class TimeDateServiceImpl extends WidgetService {
|
||||
return field['deType'] === 1
|
||||
})
|
||||
}
|
||||
defaultSetting() {
|
||||
return dialogPanel.options.attrs.default
|
||||
}
|
||||
dynamicDateFormNow(element) {
|
||||
if (element.options.attrs.default === null || typeof element.options.attrs.default === 'undefined' || !element.options.attrs.default.isDynamic) return null
|
||||
|
||||
|
@ -13,9 +13,30 @@ const dialogPanel = {
|
||||
placeholder: 'deyearmonth.placeholder',
|
||||
viewIds: [],
|
||||
fieldId: '',
|
||||
dragItems: []
|
||||
dragItems: [],
|
||||
default: {
|
||||
isDynamic: false,
|
||||
dkey: 0,
|
||||
dynamicPrefix: 1,
|
||||
dynamicInfill: 'month',
|
||||
dynamicSuffix: 'before',
|
||||
radioOptions: [{ value: false, text: 'dynamic_month.fix' }, { value: true, text: 'dynamic_month.dynamic' }],
|
||||
relativeOptions: [
|
||||
{ value: 0, text: 'dynamic_month.current' },
|
||||
{ value: 1, text: 'dynamic_month.last' },
|
||||
{ value: 2, text: 'dynamic_month.firstOfYear' },
|
||||
{ value: 3, text: 'dynamic_time.custom' }
|
||||
],
|
||||
custom: {
|
||||
unitsOptions: [
|
||||
{ value: 'month', text: 'dynamic_time.month' }
|
||||
],
|
||||
limits: [0, 10]
|
||||
}
|
||||
}
|
||||
},
|
||||
value: ''
|
||||
value: '',
|
||||
manualModify: false
|
||||
},
|
||||
defaultClass: 'time-filter',
|
||||
component: 'de-date'
|
||||
@ -64,6 +85,38 @@ class TimeMonthServiceImpl extends WidgetService {
|
||||
return field['deType'] === 1
|
||||
})
|
||||
}
|
||||
defaultSetting() {
|
||||
return dialogPanel.options.attrs.default
|
||||
}
|
||||
dynamicDateFormNow(element) {
|
||||
const now = new Date()
|
||||
const nowMonth = now.getMonth()
|
||||
const nowYear = now.getFullYear()
|
||||
if (element.options.attrs.default === null || typeof element.options.attrs.default === 'undefined' || !element.options.attrs.default.isDynamic) return null
|
||||
|
||||
if (element.options.attrs.default.dkey === 0) {
|
||||
return new Date(nowYear, nowMonth, 1).getTime()
|
||||
}
|
||||
|
||||
if (element.options.attrs.default.dkey === 1) {
|
||||
return new Date(nowYear, nowMonth - 1, 1).getTime()
|
||||
}
|
||||
|
||||
if (element.options.attrs.default.dkey === 2) {
|
||||
return new Date(nowYear, 0, 1).getTime()
|
||||
}
|
||||
|
||||
if (element.options.attrs.default.dkey === 3) {
|
||||
const dynamicPrefix = parseInt(element.options.attrs.default.dynamicPrefix)
|
||||
const dynamicSuffix = element.options.attrs.default.dynamicSuffix
|
||||
|
||||
if (dynamicSuffix === 'before') {
|
||||
return new Date(nowYear, nowMonth - dynamicPrefix, 1).getTime()
|
||||
} else {
|
||||
return new Date(nowYear, nowMonth + dynamicPrefix, 1).getTime()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const timeMonthServiceImpl = new TimeMonthServiceImpl()
|
||||
export default timeMonthServiceImpl
|
||||
|
@ -13,9 +13,29 @@ const dialogPanel = {
|
||||
placeholder: 'deyear.placeholder',
|
||||
viewIds: [],
|
||||
fieldId: '',
|
||||
dragItems: []
|
||||
dragItems: [],
|
||||
default: {
|
||||
isDynamic: false,
|
||||
dkey: 0,
|
||||
dynamicPrefix: 1,
|
||||
dynamicInfill: 'year',
|
||||
dynamicSuffix: 'before',
|
||||
radioOptions: [{ value: false, text: 'dynamic_year.fix' }, { value: true, text: 'dynamic_year.dynamic' }],
|
||||
relativeOptions: [
|
||||
{ value: 0, text: 'dynamic_year.current' },
|
||||
{ value: 1, text: 'dynamic_year.last' },
|
||||
{ value: 2, text: 'dynamic_time.custom' }
|
||||
],
|
||||
custom: {
|
||||
unitsOptions: [
|
||||
{ value: 'year', text: 'dynamic_time.year' }
|
||||
],
|
||||
limits: [0, 10]
|
||||
}
|
||||
}
|
||||
},
|
||||
value: ''
|
||||
value: '',
|
||||
manualModify: false
|
||||
},
|
||||
defaultClass: 'time-filter',
|
||||
component: 'de-date'
|
||||
@ -65,6 +85,29 @@ class TimeYearServiceImpl extends WidgetService {
|
||||
return field['deType'] === 1
|
||||
})
|
||||
}
|
||||
defaultSetting() {
|
||||
return dialogPanel.options.attrs.default
|
||||
}
|
||||
dynamicDateFormNow(element) {
|
||||
if (element.options.attrs.default === null || typeof element.options.attrs.default === 'undefined' || !element.options.attrs.default.isDynamic) return null
|
||||
|
||||
const now = new Date()
|
||||
const nowYear = now.getFullYear()
|
||||
if (element.options.attrs.default.dkey === 0) {
|
||||
return new Date(nowYear, 0, 1).getTime()
|
||||
}
|
||||
|
||||
if (element.options.attrs.default.dkey === 1) {
|
||||
return new Date(nowYear - 1, 0, 1).getTime()
|
||||
}
|
||||
|
||||
if (element.options.attrs.default.dkey === 2) {
|
||||
const dynamicPrefix = parseInt(element.options.attrs.default.dynamicPrefix)
|
||||
const dynamicSuffix = element.options.attrs.default.dynamicSuffix
|
||||
|
||||
return new Date(dynamicSuffix === 'before' ? (nowYear - dynamicPrefix) : (nowYear + dynamicPrefix), 0, 1).getTime()
|
||||
}
|
||||
}
|
||||
}
|
||||
const timeYearServiceImpl = new TimeYearServiceImpl()
|
||||
export default timeYearServiceImpl
|
||||
|
@ -131,6 +131,9 @@ export default {
|
||||
default_login: 'Normal'
|
||||
},
|
||||
commons: {
|
||||
first_login_tips: 'Please change the initial password',
|
||||
roger_that: 'Roger That',
|
||||
apply: 'Apply',
|
||||
search: 'Search',
|
||||
folder: 'Folder',
|
||||
no_target_permission: 'No permission',
|
||||
@ -437,7 +440,10 @@ export default {
|
||||
background: 'Background color',
|
||||
custom: 'Custom color',
|
||||
otherSave: 'Theme Save as',
|
||||
info: 'Theme info'
|
||||
info: 'Theme info',
|
||||
add: 'Add Theme',
|
||||
please_input_name: 'Please enter a name',
|
||||
name_repeat: 'Name already exists'
|
||||
},
|
||||
tagsView: {
|
||||
refresh: 'Refresh',
|
||||
@ -455,7 +461,8 @@ export default {
|
||||
sysParams: {
|
||||
display: 'Display Setting',
|
||||
ldap: 'LDAP Setting',
|
||||
oidc: 'OIDC Setting'
|
||||
oidc: 'OIDC Setting',
|
||||
theme: 'Theme Setting'
|
||||
},
|
||||
license: {
|
||||
i18n_no_license_record: 'No License Record',
|
||||
@ -1443,6 +1450,7 @@ export default {
|
||||
linkage: 'linkage',
|
||||
jump: 'Jump',
|
||||
cancel_linkage: 'Cancel Linkage',
|
||||
switch_picture: 'Switch Picture',
|
||||
remove_all_linkage: 'Remove All Linkage',
|
||||
exit_un_march_linkage_field: 'Exit Un March Linkage Field',
|
||||
details: 'Details',
|
||||
@ -1519,7 +1527,9 @@ export default {
|
||||
|
||||
themeLight: 'Light',
|
||||
themeDark: 'Dark',
|
||||
themeCustom: 'Custom'
|
||||
themeCustom: 'Custom',
|
||||
openHomePage: 'Show Home Page'
|
||||
|
||||
},
|
||||
auth: {
|
||||
authConfig: 'Auth Config',
|
||||
@ -1771,6 +1781,40 @@ export default {
|
||||
cweek: 'This Week',
|
||||
cmonth: 'This Month',
|
||||
cquarter: 'This Quarter',
|
||||
cyear: 'This Year'
|
||||
cyear: 'This Year',
|
||||
openHomePage: 'Show Home Page'
|
||||
},
|
||||
dynamic_year: {
|
||||
fix: 'Fixed Year',
|
||||
dynamic: 'Dynamic Year',
|
||||
current: 'This Year',
|
||||
last: 'Last Year'
|
||||
},
|
||||
dynamic_month: {
|
||||
fix: 'Fixed Month',
|
||||
dynamic: 'Dynamic Month',
|
||||
current: 'This Month',
|
||||
last: 'Last Month',
|
||||
firstOfYear: 'First month of this year'
|
||||
},
|
||||
wizard: {
|
||||
welcome_title: 'Welcome To Use DataEase',
|
||||
welcome_hint: 'Open source data visual analysis tool available to everyone',
|
||||
demo_video: 'Demo',
|
||||
online_document: 'Online',
|
||||
latest_developments: 'Latest',
|
||||
teaching_video: 'Teaching',
|
||||
enterprise_edition: 'Enterprise',
|
||||
contact_us: 'Contact Us',
|
||||
demo_video_hint: 'How to make a DataEase dashboard in 3 minutes and share it with others',
|
||||
online_document_hint: 'It covers the installation steps, user manuals, tutorials, solutions to common problems, and secondary development of DataEase',
|
||||
teaching_video_bottom_hint: 'More videos',
|
||||
enterprise_edition_hint1: 'Provide enterprise application scenario x-pack enhancement package',
|
||||
enterprise_edition_hint2: 'Provide high-level original factory service support',
|
||||
enterprise_edition_hint3: 'Provide dataease O & M security best practices',
|
||||
open_source_community: 'Open source community',
|
||||
click_show: 'Click To View',
|
||||
show_more: 'Show More',
|
||||
click_inner: 'Click To Enter'
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +131,9 @@ export default {
|
||||
default_login: '普通登錄'
|
||||
},
|
||||
commons: {
|
||||
first_login_tips: '您使用的是初始密碼,記得修改密碼哦',
|
||||
roger_that: '知道了',
|
||||
apply: '應用',
|
||||
search: '搜索',
|
||||
folder: '目錄',
|
||||
no_target_permission: '沒有權限',
|
||||
@ -437,7 +440,10 @@ export default {
|
||||
background: '背景顏色',
|
||||
custom: '自定義顏色',
|
||||
otherSave: '主題另存為',
|
||||
info: '主題信息'
|
||||
info: '主題信息',
|
||||
add: '新增主題',
|
||||
please_input_name: '請輸入名稱',
|
||||
name_repeat: '名稱已存在'
|
||||
},
|
||||
tagsView: {
|
||||
refresh: '刷新',
|
||||
@ -455,7 +461,8 @@ export default {
|
||||
sysParams: {
|
||||
display: '顯示設置',
|
||||
ldap: 'LDAP設置',
|
||||
oidc: 'OIDC設置'
|
||||
oidc: 'OIDC設置',
|
||||
theme: '主题设置'
|
||||
},
|
||||
license: {
|
||||
i18n_no_license_record: '沒有 License 記錄',
|
||||
@ -1445,6 +1452,7 @@ export default {
|
||||
linkage: '聯動',
|
||||
jump: '跳轉',
|
||||
cancel_linkage: '取消聯動',
|
||||
switch_picture: '更换图片',
|
||||
remove_all_linkage: '清除所有聯動',
|
||||
exit_un_march_linkage_field: '存在未匹配聯動關繫的字段',
|
||||
details: '詳情',
|
||||
@ -1529,7 +1537,8 @@ export default {
|
||||
|
||||
themeLight: '淺色',
|
||||
themeDark: '深色',
|
||||
themeCustom: '自定義'
|
||||
themeCustom: '自定義',
|
||||
openHomePage: '显示首页'
|
||||
|
||||
},
|
||||
auth: {
|
||||
@ -1784,5 +1793,38 @@ export default {
|
||||
cmonth: '本月',
|
||||
cquarter: '本季',
|
||||
cyear: '本年'
|
||||
},
|
||||
dynamic_year: {
|
||||
fix: '固定年份',
|
||||
dynamic: '動態年份',
|
||||
current: '當年',
|
||||
last: '去年'
|
||||
},
|
||||
dynamic_month: {
|
||||
fix: '固定年月',
|
||||
dynamic: '動態年月',
|
||||
current: '本月',
|
||||
last: '上月',
|
||||
firstOfYear: '當年首月'
|
||||
},
|
||||
wizard: {
|
||||
welcome_title: '歡迎使用DataEase',
|
||||
welcome_hint: '人人可用的開源數據可視化分析工具',
|
||||
demo_video: '演示視頻',
|
||||
online_document: '在線文檔',
|
||||
latest_developments: '最新動態',
|
||||
teaching_video: '教學視頻',
|
||||
enterprise_edition: '企業版',
|
||||
contact_us: '聯系我們',
|
||||
demo_video_hint: '如何3分鐘製作一個DataEase 數據看板、並分享給他人',
|
||||
online_document_hint: '涵蓋DataEase的安裝步驟、用戶手冊、使用教程、常見問題的解決方案、以及二次開發等',
|
||||
teaching_video_bottom_hint: '更多視頻資料',
|
||||
enterprise_edition_hint1: '提供企業級應用場景X-Pack增強包',
|
||||
enterprise_edition_hint2: '提供高等級原廠服務支持',
|
||||
enterprise_edition_hint3: '提供DataEase 運維安全最佳實踐',
|
||||
open_source_community: '開源社區',
|
||||
click_show: '點擊查看',
|
||||
show_more: '查看更多',
|
||||
click_inner: '點擊進入'
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +131,9 @@ export default {
|
||||
default_login: '普通登录'
|
||||
},
|
||||
commons: {
|
||||
first_login_tips: '您使用的是初始密码,记得修改密码哦',
|
||||
roger_that: '知道了',
|
||||
apply: '应用',
|
||||
search: '搜索',
|
||||
folder: '目录',
|
||||
no_target_permission: '没有权限',
|
||||
@ -438,7 +441,10 @@ export default {
|
||||
background: '背景颜色',
|
||||
custom: '自定义颜色',
|
||||
otherSave: '主题另存为',
|
||||
info: '主题信息'
|
||||
info: '主题信息',
|
||||
add: '新增主题',
|
||||
please_input_name: '请输入名称',
|
||||
name_repeat: '名称已存在'
|
||||
},
|
||||
tagsView: {
|
||||
refresh: '刷新',
|
||||
@ -1456,6 +1462,7 @@ export default {
|
||||
linkage: '联动',
|
||||
jump: '跳转',
|
||||
cancel_linkage: '取消联动',
|
||||
switch_picture: '更换图片',
|
||||
remove_all_linkage: '清除所有联动',
|
||||
exit_un_march_linkage_field: '存在未匹配联动关系的字段',
|
||||
details: '详情',
|
||||
@ -1539,7 +1546,8 @@ export default {
|
||||
|
||||
themeLight: '浅色',
|
||||
themeDark: '深色',
|
||||
themeCustom: '自定义'
|
||||
themeCustom: '自定义',
|
||||
openHomePage: '显示首页'
|
||||
|
||||
},
|
||||
auth: {
|
||||
@ -1795,5 +1803,38 @@ export default {
|
||||
cmonth: '本月',
|
||||
cquarter: '本季',
|
||||
cyear: '本年'
|
||||
},
|
||||
dynamic_year: {
|
||||
fix: '固定年份',
|
||||
dynamic: '动态年份',
|
||||
current: '当年',
|
||||
last: '去年'
|
||||
},
|
||||
dynamic_month: {
|
||||
fix: '固定年月',
|
||||
dynamic: '动态年月',
|
||||
current: '当月',
|
||||
last: '上月',
|
||||
firstOfYear: '当年首月'
|
||||
},
|
||||
wizard: {
|
||||
welcome_title: '欢迎使用DataEase',
|
||||
welcome_hint: '人人可用的开源数据可视化分析工具',
|
||||
demo_video: '演示视频',
|
||||
online_document: '在线文档',
|
||||
latest_developments: '最新动态',
|
||||
teaching_video: '教学视频',
|
||||
enterprise_edition: '企业版',
|
||||
contact_us: '联系我们',
|
||||
demo_video_hint: '如何3分钟制作一个DataEase 数据看板、并分享给他人',
|
||||
online_document_hint: '涵盖DataEase的安装步骤、用户手册、使用教程、常见问题的解决方案、以及二次开发等',
|
||||
teaching_video_bottom_hint: '更多视频资料',
|
||||
enterprise_edition_hint1: '提供企业级应用场景X-Pack增强包',
|
||||
enterprise_edition_hint2: '提供高等级原厂服务支持',
|
||||
enterprise_edition_hint3: '提供DataEase 运维安全最佳实践',
|
||||
open_source_community: '开源社区',
|
||||
click_show: '点击查看',
|
||||
show_more: '查看更多',
|
||||
click_inner: '点击进入'
|
||||
}
|
||||
}
|
||||
|
@ -14,10 +14,8 @@
|
||||
>
|
||||
<div v-for="item in permission_routes" :key="item.path" class="nav-item">
|
||||
<app-link :to="resolvePath(item)">
|
||||
<el-menu-item
|
||||
v-if="!item.hidden"
|
||||
:index="item.path"
|
||||
>{{ item.meta ? item.meta.title : item.children[0].meta.title }}</el-menu-item>
|
||||
<el-menu-item v-if="!item.hidden" :index="item.path">
|
||||
{{ item.meta ? item.meta.title : item.children[0].meta.title }}</el-menu-item>
|
||||
</app-link>
|
||||
</div>
|
||||
</el-menu>
|
||||
@ -28,13 +26,22 @@
|
||||
<notification class="right-menu-item hover-effect" />
|
||||
<lang-select class="right-menu-item hover-effect" />
|
||||
<div style="height: 100%;padding: 0 8px;" class="right-menu-item hover-effect">
|
||||
<a href="https://dataease.io/docs/" target="_blank" style="display: flex;height: 100%;width: 100%;justify-content: center;align-items: center;">
|
||||
<a
|
||||
href="https://dataease.io/docs/"
|
||||
target="_blank"
|
||||
style="display: flex;height: 100%;width: 100%;justify-content: center;align-items: center;"
|
||||
>
|
||||
<svg-icon icon-class="docs" />
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-dropdown class="top-dropdown" style="display: flex;align-items: center; width:100px;" trigger="click">
|
||||
<el-dropdown
|
||||
ref="my-drop"
|
||||
class="top-dropdown"
|
||||
style="display: flex;align-items: center; width:100px;"
|
||||
trigger="click"
|
||||
>
|
||||
<div class="el-dropdown-link" style="display: flex;color: var(--TopTextColor);font-size: 14px; width:100%;">
|
||||
|
||||
<span style="max-width:80px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;">{{ name }}</span>
|
||||
@ -62,21 +69,32 @@
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import {
|
||||
mapGetters
|
||||
} from 'vuex'
|
||||
import AppLink from './Sidebar/Link'
|
||||
import variables from '@/styles/variables.scss'
|
||||
import { isExternal } from '@/utils/validate'
|
||||
import {
|
||||
isExternal
|
||||
} from '@/utils/validate'
|
||||
import Notification from '@/components/Notification'
|
||||
import bus from '@/utils/bus'
|
||||
import LangSelect from '@/components/LangSelect'
|
||||
import { getSysUI } from '@/utils/auth'
|
||||
import { pluginLoaded } from '@/api/user'
|
||||
import { initTheme } from '@/utils/ThemeUtil'
|
||||
import {
|
||||
getSysUI
|
||||
} from '@/utils/auth'
|
||||
import {
|
||||
pluginLoaded
|
||||
} from '@/api/user'
|
||||
import {
|
||||
initTheme
|
||||
} from '@/utils/ThemeUtil'
|
||||
export default {
|
||||
name: 'Topbar',
|
||||
components: {
|
||||
@ -85,6 +103,12 @@ export default {
|
||||
LangSelect
|
||||
|
||||
},
|
||||
props: {
|
||||
showTips: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
uiInfo: null,
|
||||
@ -100,27 +124,42 @@ export default {
|
||||
},
|
||||
|
||||
topMenuColor() {
|
||||
if (this.$store.getters.uiInfo && this.$store.getters.uiInfo['ui.topMenuColor'] && this.$store.getters.uiInfo['ui.topMenuColor'].paramValue) { return this.$store.getters.uiInfo['ui.topMenuColor'].paramValue }
|
||||
if (this.$store.getters.uiInfo && this.$store.getters.uiInfo['ui.topMenuColor'] && this.$store.getters.uiInfo[
|
||||
'ui.topMenuColor'].paramValue) {
|
||||
return this.$store.getters.uiInfo['ui.topMenuColor'].paramValue
|
||||
}
|
||||
return this.variables.topBarBg
|
||||
},
|
||||
topMenuActiveColor() {
|
||||
if (this.$store.getters.uiInfo && this.$store.getters.uiInfo['ui.topMenuActiveColor'] && this.$store.getters.uiInfo['ui.topMenuActiveColor'].paramValue) { return this.$store.getters.uiInfo['ui.topMenuActiveColor'].paramValue }
|
||||
if (this.$store.getters.uiInfo && this.$store.getters.uiInfo['ui.topMenuActiveColor'] && this.$store.getters
|
||||
.uiInfo['ui.topMenuActiveColor'].paramValue) {
|
||||
return this.$store.getters.uiInfo['ui.topMenuActiveColor'].paramValue
|
||||
}
|
||||
return this.variables.topBarMenuActive
|
||||
},
|
||||
topMenuTextColor() {
|
||||
if (this.$store.getters.uiInfo && this.$store.getters.uiInfo['ui.topMenuTextColor'] && this.$store.getters.uiInfo['ui.topMenuTextColor'].paramValue) { return this.$store.getters.uiInfo['ui.topMenuTextColor'].paramValue }
|
||||
if (this.$store.getters.uiInfo && this.$store.getters.uiInfo['ui.topMenuTextColor'] && this.$store.getters
|
||||
.uiInfo['ui.topMenuTextColor'].paramValue) {
|
||||
return this.$store.getters.uiInfo['ui.topMenuTextColor'].paramValue
|
||||
}
|
||||
return this.variables.topBarMenuText
|
||||
},
|
||||
topMenuTextActiveColor() {
|
||||
if (this.$store.getters.uiInfo && this.$store.getters.uiInfo['ui.topMenuTextActiveColor'] && this.$store.getters.uiInfo['ui.topMenuTextActiveColor'].paramValue) { return this.$store.getters.uiInfo['ui.topMenuTextActiveColor'].paramValue }
|
||||
if (this.$store.getters.uiInfo && this.$store.getters.uiInfo['ui.topMenuTextActiveColor'] && this.$store.getters
|
||||
.uiInfo['ui.topMenuTextActiveColor'].paramValue) {
|
||||
return this.$store.getters.uiInfo['ui.topMenuTextActiveColor'].paramValue
|
||||
}
|
||||
return this.variables.topBarMenuTextActive
|
||||
},
|
||||
/* topMenuColor() {
|
||||
return this.$store.getters.uiInfo.topMenuColor
|
||||
}, */
|
||||
return this.$store.getters.uiInfo.topMenuColor
|
||||
}, */
|
||||
activeMenu() {
|
||||
const route = this.$route
|
||||
const { meta, path } = route
|
||||
const {
|
||||
meta,
|
||||
path
|
||||
} = route
|
||||
// if set path, the sidebar will highlight the path you set
|
||||
if (meta.activeMenu) {
|
||||
// return meta.activeMenu
|
||||
@ -152,6 +191,10 @@ export default {
|
||||
bus.$on('set-top-menu-active-info', this.setTopMenuActiveInfo)
|
||||
bus.$on('set-top-text-info', this.setTopTextInfo)
|
||||
bus.$on('set-top-text-active-info', this.setTopTextActiveInfo)
|
||||
this.showTips && this.$nextTick(() => {
|
||||
const drop = this.$refs['my-drop']
|
||||
drop && drop.show && drop.show()
|
||||
})
|
||||
},
|
||||
created() {
|
||||
this.loadUiInfo()
|
||||
@ -159,13 +202,17 @@ export default {
|
||||
beforeCreate() {
|
||||
pluginLoaded().then(res => {
|
||||
this.isPluginLoaded = res.success && res.data
|
||||
if (this.isPluginLoaded) { initTheme() }
|
||||
if (this.isPluginLoaded) {
|
||||
initTheme()
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
// 通过当前路径找到二级菜单对应项,存到store,用来渲染左侧菜单
|
||||
initCurrentRoutes() {
|
||||
const { path } = this.$route
|
||||
const {
|
||||
path
|
||||
} = this.$route
|
||||
let route = this.permission_routes.find(
|
||||
item => item.path === '/' + path.split('/')[1]
|
||||
)
|
||||
@ -197,9 +244,9 @@ export default {
|
||||
// 如果有子项,默认跳转第一个子项路由
|
||||
let path = ''
|
||||
/**
|
||||
* item 路由子项
|
||||
* parent 路由父项
|
||||
*/
|
||||
* item 路由子项
|
||||
* parent 路由父项
|
||||
*/
|
||||
const getDefaultPath = (item, parent) => {
|
||||
// 如果path是个外部链接(不建议),直接返回链接,存在个问题:如果是外部链接点击跳转后当前页内容还是上一个路由内容
|
||||
if (isExternal(item.path)) {
|
||||
@ -233,7 +280,7 @@ export default {
|
||||
},
|
||||
// 设置侧边栏的显示和隐藏
|
||||
setSidebarHide(route) {
|
||||
// if (!route.children || route.children.length === 1) {
|
||||
// if (!route.children || route.children.length === 1) {
|
||||
if (route.name !== 'system' && (!route.children || this.showChildLength(route) === 1)) {
|
||||
this.$store.dispatch('app/toggleSideBarHide', true)
|
||||
} else {
|
||||
@ -266,12 +313,12 @@ export default {
|
||||
}
|
||||
|
||||
/* if (this.uiInfo['ui.themeStr'] && this.uiInfo['ui.themeStr'].paramValue) {
|
||||
if (this.uiInfo['ui.themeStr'].paramValue === 'dark') {
|
||||
document.body.className = 'blackTheme'
|
||||
} else if (this.uiInfo['ui.themeStr'].paramValue === 'light') {
|
||||
document.body.className = ''
|
||||
}
|
||||
} */
|
||||
if (this.uiInfo['ui.themeStr'].paramValue === 'dark') {
|
||||
document.body.className = 'blackTheme'
|
||||
} else if (this.uiInfo['ui.themeStr'].paramValue === 'light') {
|
||||
document.body.className = ''
|
||||
}
|
||||
} */
|
||||
this.axiosFinished = true
|
||||
})
|
||||
},
|
||||
@ -291,12 +338,14 @@ export default {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.el-dropdown-link {
|
||||
cursor: pointer;
|
||||
color: #1e212a;
|
||||
}
|
||||
|
||||
.el-icon-arrow-down {
|
||||
font-size: 12px;
|
||||
}
|
||||
@ -312,7 +361,8 @@ export default {
|
||||
}
|
||||
|
||||
.de-top-menu {
|
||||
background-color: var(--MainBG);
|
||||
background-color: var(--MainBG);
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div :class="classObj" class="app-wrapper">
|
||||
<licbar />
|
||||
<topbar v-if="!fullHeightFlag" />
|
||||
<topbar v-if="!fullHeightFlag && finishLoad" :show-tips="showTips" />
|
||||
|
||||
<de-container :style="mainStyle">
|
||||
<de-aside-container v-if="!sidebar.hide" class="le-aside-container">
|
||||
@ -12,6 +12,14 @@
|
||||
<app-main />
|
||||
</de-main-container>
|
||||
</de-container>
|
||||
<div v-if="showTips" class="pwd-tips">
|
||||
<span>{{ $t('commons.first_login_tips') }}</span>
|
||||
<div style="text-align: right; margin-bottom: 10px;">
|
||||
<el-button type="primary" size="mini" @click="showTips = false">{{ $t('commons.roger_that') }}</el-button>
|
||||
</div>
|
||||
<div class="arrow" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -23,6 +31,8 @@ import DeContainer from '@/components/dataease/DeContainer'
|
||||
import DeAsideContainer from '@/components/dataease/DeAsideContainer'
|
||||
import bus from '@/utils/bus'
|
||||
|
||||
import { needModifyPwd } from '@/api/user'
|
||||
|
||||
export default {
|
||||
name: 'Layout',
|
||||
components: {
|
||||
@ -37,7 +47,9 @@ export default {
|
||||
mixins: [ResizeMixin],
|
||||
data() {
|
||||
return {
|
||||
componentName: 'PanelMain'
|
||||
componentName: 'PanelMain',
|
||||
showTips: false,
|
||||
finishLoad: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -76,6 +88,14 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeCreate() {
|
||||
needModifyPwd().then(res => {
|
||||
this.showTips = res.success && res.data
|
||||
this.finishLoad = true
|
||||
}).catch(e => {
|
||||
this.finishLoad = true
|
||||
})
|
||||
},
|
||||
mounted() {
|
||||
bus.$on('PanelSwitchComponent', (c) => {
|
||||
this.componentName = c.name
|
||||
@ -94,6 +114,8 @@ export default {
|
||||
@import "~@/styles/variables.scss";
|
||||
|
||||
.app-wrapper {
|
||||
min-width: 1000px!important;
|
||||
min-height: 600px!important;
|
||||
@include clearfix;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
@ -153,4 +175,29 @@ export default {
|
||||
}
|
||||
|
||||
}
|
||||
.pwd-tips {
|
||||
position: absolute;
|
||||
box-shadow: 0 0 0 1000em rgb(0, 0, 0, 0.3);
|
||||
height: 100px;
|
||||
width: 225px;
|
||||
top: 105px;
|
||||
right: 115px;
|
||||
z-index: 9999;
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
background: #fff;
|
||||
}
|
||||
.arrow{
|
||||
border-bottom: 7px solid #fff;
|
||||
border-right: 7px solid #b5b5b7;
|
||||
border-left: 7px solid #b5b5b7;
|
||||
border-top: 7px solid #b5b5b7;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
position: relative;
|
||||
top:-60px;
|
||||
left:210px;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
import {
|
||||
isMobile
|
||||
} from '@/utils/index'
|
||||
import Layout from '@/layout/index'
|
||||
// import bus from './utils/bus'
|
||||
|
||||
NProgress.configure({
|
||||
@ -97,6 +98,23 @@ export const loadMenus = (next, to) => {
|
||||
const datas = res.data
|
||||
const filterDatas = filterRouter(datas)
|
||||
const asyncRouter = filterAsyncRouter(filterDatas)
|
||||
// 如果包含首页 则默认页面是 首页 否则默认页面是仪表板页面
|
||||
if (JSON.stringify(datas).indexOf('wizard') > -1) {
|
||||
asyncRouter.push({
|
||||
path: '/',
|
||||
component: Layout,
|
||||
redirect: '/wizard/index',
|
||||
hidden: true
|
||||
})
|
||||
} else {
|
||||
asyncRouter.push({
|
||||
path: '/',
|
||||
component: Layout,
|
||||
redirect: '/panel/index',
|
||||
hidden: true
|
||||
})
|
||||
}
|
||||
|
||||
asyncRouter.push({
|
||||
path: '*',
|
||||
redirect: '/404',
|
||||
|
@ -91,12 +91,6 @@ export const constantRoutes = [
|
||||
path: '/previewFullScreen',
|
||||
component: () => import('@/components/canvas/components/Editor/PreviewFullScreen'),
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
component: Layout,
|
||||
redirect: '/panel/index',
|
||||
hidden: true
|
||||
}
|
||||
|
||||
// {
|
||||
|
@ -16,6 +16,7 @@ const getters = {
|
||||
errorLogs: state => state.errorLog.logs,
|
||||
sceneData: state => state.dataset.sceneData,
|
||||
table: state => state.dataset.table,
|
||||
chartTable: state => state.chart.table,
|
||||
hideCustomDs: state => state.dataset.hideCustomDs,
|
||||
loadingMap: state => state.request.loadingMap,
|
||||
currentPath: state => state.permission.currentPath,
|
||||
|
@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 2459092 */
|
||||
src: url('iconfont.woff2?t=1639622225820') format('woff2'),
|
||||
url('iconfont.woff?t=1639622225820') format('woff'),
|
||||
url('iconfont.ttf?t=1639622225820') format('truetype');
|
||||
src: url('iconfont.woff2?t=1642061879222') format('woff2'),
|
||||
url('iconfont.woff?t=1642061879222') format('woff'),
|
||||
url('iconfont.ttf?t=1642061879222') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@ -13,6 +13,22 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-genghuan:before {
|
||||
content: "\e606";
|
||||
}
|
||||
|
||||
.icon-fasongyoujian:before {
|
||||
content: "\e605";
|
||||
}
|
||||
|
||||
.icon-github:before {
|
||||
content: "\e6f8";
|
||||
}
|
||||
|
||||
.icon-dianhua:before {
|
||||
content: "\e681";
|
||||
}
|
||||
|
||||
.icon-guanbi:before {
|
||||
content: "\e60d";
|
||||
}
|
||||
|
@ -5,6 +5,34 @@
|
||||
"css_prefix_text": "icon-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "12851123",
|
||||
"name": "更换",
|
||||
"font_class": "genghuan",
|
||||
"unicode": "e606",
|
||||
"unicode_decimal": 58886
|
||||
},
|
||||
{
|
||||
"icon_id": "1286",
|
||||
"name": "发送邮件",
|
||||
"font_class": "fasongyoujian",
|
||||
"unicode": "e605",
|
||||
"unicode_decimal": 58885
|
||||
},
|
||||
{
|
||||
"icon_id": "7239484",
|
||||
"name": "github",
|
||||
"font_class": "github",
|
||||
"unicode": "e6f8",
|
||||
"unicode_decimal": 59128
|
||||
},
|
||||
{
|
||||
"icon_id": "11810462",
|
||||
"name": "电话",
|
||||
"font_class": "dianhua",
|
||||
"unicode": "e681",
|
||||
"unicode_decimal": 59009
|
||||
},
|
||||
{
|
||||
"icon_id": "1367318",
|
||||
"name": "关闭",
|
||||
|
@ -534,14 +534,7 @@ div:focus {
|
||||
color: var(--Main) !important;
|
||||
}
|
||||
|
||||
/* .blackTheme .el-dialog {
|
||||
background: var(--ContentBG) !important;
|
||||
color: var(--TextPrimary) !important;
|
||||
}
|
||||
*/
|
||||
.blackTheme .el-dialog__title {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
|
||||
.blackTheme .title-text {
|
||||
color: var(--TextPrimary) !important;
|
||||
@ -663,9 +656,7 @@ div:focus {
|
||||
background: #38393a !important;
|
||||
}
|
||||
|
||||
.blackTheme .el-message-box__content {
|
||||
color: #F2F6FC;
|
||||
}
|
||||
|
||||
|
||||
.blackTheme .el-message-box__btns {
|
||||
.el-button--default:not(.el-button--primary) {
|
||||
|
@ -13,11 +13,11 @@ export const DEFAULT_SIZE = {
|
||||
barDefault: true,
|
||||
barWidth: 40,
|
||||
barGap: 0.4,
|
||||
lineWidth: 1,
|
||||
lineWidth: 2,
|
||||
lineType: 'solid',
|
||||
lineSymbol: 'circle',
|
||||
lineSymbolSize: 4,
|
||||
lineSmooth: false,
|
||||
lineSmooth: true,
|
||||
lineArea: false,
|
||||
pieInnerRadius: 0,
|
||||
pieOuterRadius: 80,
|
||||
|
@ -5,7 +5,7 @@ import { DEFAULT_SIZE } from '@/views/chart/chart/chart'
|
||||
export function baseLiquid(plot, container, chart) {
|
||||
let value = 0
|
||||
const colors = []
|
||||
let max, radius, outlineBorder, outlineDistance, waveLength, waveCount, bgColor, shape, labelContent, title
|
||||
let max, radius, bgColor, shape, labelContent, title
|
||||
if (chart.data) {
|
||||
if (chart.data.series.length > 0) {
|
||||
value = chart.data.series[0].data[0]
|
||||
@ -26,10 +26,6 @@ export function baseLiquid(plot, container, chart) {
|
||||
const size = JSON.parse(JSON.stringify(customAttr.size))
|
||||
max = size.liquidMax ? size.liquidMax : DEFAULT_SIZE.liquidMax
|
||||
radius = parseFloat((size.liquidSize ? size.liquidSize : DEFAULT_SIZE.liquidSize) / 100)
|
||||
outlineBorder = parseInt(size.liquidOutlineBorder ? size.liquidOutlineBorder : DEFAULT_SIZE.liquidOutlineBorder)
|
||||
outlineDistance = parseInt((size.liquidOutlineDistance || size.liquidOutlineDistance === 0) ? size.liquidOutlineDistance : DEFAULT_SIZE.liquidOutlineDistance)
|
||||
waveLength = parseInt(size.liquidWaveLength ? size.liquidWaveLength : DEFAULT_SIZE.liquidWaveLength)
|
||||
waveCount = parseInt(size.liquidWaveCount ? size.liquidWaveCount : DEFAULT_SIZE.liquidWaveCount)
|
||||
shape = size.liquidShape ? size.liquidShape : DEFAULT_SIZE.liquidShape
|
||||
}
|
||||
// label
|
||||
@ -86,14 +82,6 @@ export function baseLiquid(plot, container, chart) {
|
||||
percent: (parseFloat(value) / parseFloat(max)),
|
||||
radius: radius,
|
||||
shape: shape,
|
||||
outline: {
|
||||
border: outlineBorder,
|
||||
distance: outlineDistance
|
||||
},
|
||||
wave: {
|
||||
length: waveLength,
|
||||
count: waveCount
|
||||
},
|
||||
statistic: {
|
||||
// title: title,
|
||||
content: labelContent
|
||||
|
@ -26,7 +26,7 @@ export function baseMapOption(chart_option, chart) {
|
||||
// 处理data
|
||||
if (chart.data) {
|
||||
chart_option.title.text = chart.title
|
||||
if (chart.data.series.length > 0) {
|
||||
if (chart.data.series && chart.data.series.length > 0) {
|
||||
chart_option.series[0].name = chart.data.series[0].name
|
||||
// label
|
||||
if (customAttr.label) {
|
||||
|
@ -74,7 +74,7 @@ import {
|
||||
import {
|
||||
baseMixOption
|
||||
} from '@/views/chart/chart/mix/mix'
|
||||
// import eventBus from '@/components/canvas/utils/eventBus'
|
||||
// import eventBus from '@/components/canvas/utils/eventBus'
|
||||
import {
|
||||
uuid
|
||||
} from 'vue-uuid'
|
||||
@ -130,7 +130,8 @@ export default {
|
||||
pointParam: null,
|
||||
|
||||
dynamicAreaCode: null,
|
||||
borderRadius: '0px'
|
||||
borderRadius: '0px',
|
||||
mapCenter: null
|
||||
}
|
||||
},
|
||||
|
||||
@ -276,6 +277,11 @@ export default {
|
||||
const base_json = JSON.parse(JSON.stringify(BASE_MAP))
|
||||
const chart_option = baseMapOption(base_json, chart)
|
||||
this.myEcharts(chart_option)
|
||||
const opt = this.myChart.getOption()
|
||||
if (opt && opt.series) {
|
||||
const center = opt.series[0].center
|
||||
this.mapCenter = center
|
||||
}
|
||||
},
|
||||
myEcharts(option) {
|
||||
// 指定图表的配置项和数据
|
||||
@ -356,6 +362,7 @@ export default {
|
||||
resetZoom() {
|
||||
const options = JSON.parse(JSON.stringify(this.myChart.getOption()))
|
||||
options.series[0].zoom = 1
|
||||
options.series[0].center = this.mapCenter
|
||||
this.myChart.setOption(options)
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
id="label-content"
|
||||
:style="content_class"
|
||||
>
|
||||
<span v-if="quotaShow" :style="label_class">
|
||||
<span :style="label_class">
|
||||
<p v-for="item in chart.data.series" :key="item.name" :style="label_content_class">
|
||||
{{ item.data[0] }}
|
||||
</p>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<el-form-item :label="$t('chart.text_color')" class="form-item">
|
||||
<el-color-picker v-model="labelForm.color" class="color-picker-style" :predefine="predefineColors" @change="changeLabelAttr" />
|
||||
</el-form-item>
|
||||
<el-form-item v-show="chart.type && chart.type !== 'liquid'" :label="$t('chart.label_position')" class="form-item">
|
||||
<el-form-item v-show="chart.type && chart.type !== 'liquid' && !chart.type.includes('line') && chart.type !== 'treemap'" :label="$t('chart.label_position')" class="form-item">
|
||||
<el-select v-model="labelForm.position" :placeholder="$t('chart.label_position')" @change="changeLabelAttr">
|
||||
<el-option v-for="option in labelPosition" :key="option.value" :label="option.name" :value="option.value" />
|
||||
</el-select>
|
||||
@ -84,27 +84,35 @@ export default {
|
||||
labelForm: JSON.parse(JSON.stringify(DEFAULT_LABEL)),
|
||||
fontSize: [],
|
||||
isSetting: false,
|
||||
labelPosition: [
|
||||
labelPosition: [],
|
||||
labelPositionPie: [
|
||||
{ name: this.$t('chart.inside'), value: 'inside' },
|
||||
{ name: this.$t('chart.outside'), value: 'outside' },
|
||||
{ name: this.$t('chart.center'), value: 'center' },
|
||||
{ name: this.$t('chart.text_pos_top'), value: 'top' },
|
||||
{ name: this.$t('chart.text_pos_bottom'), value: 'bottom' },
|
||||
{ name: this.$t('chart.outside'), value: 'outside' }
|
||||
],
|
||||
labelPositionH: [
|
||||
{ name: this.$t('chart.text_pos_left'), value: 'left' },
|
||||
{ name: this.$t('chart.center'), value: 'inside' },
|
||||
{ name: this.$t('chart.text_pos_right'), value: 'right' }
|
||||
],
|
||||
labelPositionV: [
|
||||
{ name: this.$t('chart.text_pos_top'), value: 'top' },
|
||||
{ name: this.$t('chart.center'), value: 'inside' },
|
||||
{ name: this.$t('chart.text_pos_bottom'), value: 'bottom' }
|
||||
],
|
||||
predefineColors: COLOR_PANEL
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'chart': {
|
||||
handler: function() {
|
||||
this.initOptions()
|
||||
this.initData()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
this.initOptions()
|
||||
this.initData()
|
||||
},
|
||||
methods: {
|
||||
@ -140,6 +148,18 @@ export default {
|
||||
this.isSetting = false
|
||||
}
|
||||
this.$emit('onLabelChange', this.labelForm)
|
||||
},
|
||||
initOptions() {
|
||||
const type = this.chart.type
|
||||
if (type) {
|
||||
if (type.includes('horizontal') || type === 'funnel') {
|
||||
this.labelPosition = this.labelPositionH
|
||||
} else if (type.includes('pie')) {
|
||||
this.labelPosition = this.labelPositionPie
|
||||
} else {
|
||||
this.labelPosition = this.labelPositionV
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
<el-form-item :label="$t('chart.text_color')" class="form-item">
|
||||
<el-color-picker v-model="labelForm.color" class="color-picker-style" :predefine="predefineColors" @change="changeLabelAttr" />
|
||||
</el-form-item>
|
||||
<el-form-item v-show="chart.type && chart.type !== 'liquid' && chart.type !== 'pie-rose'" :label="$t('chart.label_position')" class="form-item">
|
||||
<el-form-item v-show="chart.type && chart.type !== 'liquid' && chart.type !== 'pie-rose' && !chart.type.includes('line') && chart.type !== 'treemap'" :label="$t('chart.label_position')" class="form-item">
|
||||
<el-select v-model="labelForm.position" :placeholder="$t('chart.label_position')" @change="changeLabelAttr">
|
||||
<el-option v-for="option in labelPosition" :key="option.value" :label="option.name" :value="option.value" />
|
||||
</el-select>
|
||||
@ -62,29 +62,35 @@ export default {
|
||||
labelForm: JSON.parse(JSON.stringify(DEFAULT_LABEL)),
|
||||
fontSize: [],
|
||||
isSetting: false,
|
||||
labelPosition: [
|
||||
{ name: this.$t('chart.inside'), value: 'middle' },
|
||||
{ name: this.$t('chart.outside'), value: 'outside' },
|
||||
{ name: this.$t('chart.center'), value: 'center' },
|
||||
{ name: this.$t('chart.text_pos_top'), value: 'top' },
|
||||
{ name: this.$t('chart.text_pos_bottom'), value: 'bottom' },
|
||||
labelPosition: [],
|
||||
labelPositionPie: [
|
||||
{ name: this.$t('chart.inside'), value: 'inner' },
|
||||
{ name: this.$t('chart.outside'), value: 'outer' }
|
||||
],
|
||||
labelPositionH: [
|
||||
{ name: this.$t('chart.text_pos_left'), value: 'left' },
|
||||
{ name: this.$t('chart.center'), value: 'middle' },
|
||||
{ name: this.$t('chart.text_pos_right'), value: 'right' }
|
||||
],
|
||||
labelPositionV: [
|
||||
{ name: this.$t('chart.text_pos_top'), value: 'top' },
|
||||
{ name: this.$t('chart.center'), value: 'middle' },
|
||||
{ name: this.$t('chart.text_pos_bottom'), value: 'bottom' }
|
||||
],
|
||||
predefineColors: COLOR_PANEL
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'chart': {
|
||||
handler: function() {
|
||||
this.initLabelPosition()
|
||||
this.initOptions()
|
||||
this.initData()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
this.initLabelPosition()
|
||||
this.initOptions()
|
||||
this.initData()
|
||||
},
|
||||
methods: {
|
||||
@ -121,22 +127,16 @@ export default {
|
||||
}
|
||||
this.$emit('onLabelChange', this.labelForm)
|
||||
},
|
||||
initLabelPosition() {
|
||||
if (this.chart && this.chart.type && this.chart.type.includes('pie')) {
|
||||
this.labelPosition = [
|
||||
{ name: this.$t('chart.inside'), value: 'inner' },
|
||||
{ name: this.$t('chart.outside'), value: 'outer' }
|
||||
]
|
||||
} else {
|
||||
this.labelPosition = [
|
||||
{ name: this.$t('chart.inside'), value: 'middle' },
|
||||
{ name: this.$t('chart.outside'), value: 'outside' },
|
||||
{ name: this.$t('chart.center'), value: 'center' },
|
||||
{ name: this.$t('chart.text_pos_top'), value: 'top' },
|
||||
{ name: this.$t('chart.text_pos_bottom'), value: 'bottom' },
|
||||
{ name: this.$t('chart.text_pos_left'), value: 'left' },
|
||||
{ name: this.$t('chart.text_pos_right'), value: 'right' }
|
||||
]
|
||||
initOptions() {
|
||||
const type = this.chart.type
|
||||
if (type) {
|
||||
if (type.includes('horizontal') || type === 'funnel') {
|
||||
this.labelPosition = this.labelPositionH
|
||||
} else if (type.includes('pie')) {
|
||||
this.labelPosition = this.labelPositionPie
|
||||
} else {
|
||||
this.labelPosition = this.labelPositionV
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,9 +128,6 @@
|
||||
</el-form>
|
||||
|
||||
<el-form v-show="chart.type && chart.type.includes('text')" ref="sizeFormPie" :disabled="param && !hasDataPermission('manage',param.privileges)" :model="sizeForm" label-width="100px" size="mini">
|
||||
<el-form-item :label="$t('chart.quota_show')" class="form-item">
|
||||
<el-checkbox v-model="sizeForm.quotaShow" @change="changeBarSizeCase">{{ $t('chart.show') }}</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('chart.quota_font_size')" class="form-item">
|
||||
<el-select v-model="sizeForm.quotaFontSize" :placeholder="$t('chart.quota_font_size')" @change="changeBarSizeCase">
|
||||
<el-option v-for="option in fontSize" :key="option.value" :label="option.name" :value="option.value" />
|
||||
|
@ -125,9 +125,6 @@
|
||||
</el-form>
|
||||
|
||||
<el-form v-show="chart.type && chart.type.includes('text')" ref="sizeFormPie" :disabled="param && !hasDataPermission('manage',param.privileges)" :model="sizeForm" label-width="100px" size="mini">
|
||||
<el-form-item :label="$t('chart.quota_show')" class="form-item">
|
||||
<el-checkbox v-model="sizeForm.quotaShow" @change="changeBarSizeCase">{{ $t('chart.show') }}</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('chart.quota_font_size')" class="form-item">
|
||||
<el-select v-model="sizeForm.quotaFontSize" :placeholder="$t('chart.quota_font_size')" @change="changeBarSizeCase">
|
||||
<el-option v-for="option in fontSize" :key="option.value" :label="option.name" :value="option.value" />
|
||||
@ -244,18 +241,6 @@
|
||||
<el-form-item :label="$t('chart.radar_size')" class="form-item form-item-slider">
|
||||
<el-slider v-model="sizeForm.liquidSize" show-input :show-input-controls="false" input-size="mini" :min="1" :max="100" @change="changeBarSizeCase" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('chart.liquid_outline_border')" class="form-item form-item-slider">
|
||||
<el-slider v-model="sizeForm.liquidOutlineBorder" show-input :show-input-controls="false" input-size="mini" :min="1" :max="20" @change="changeBarSizeCase" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('chart.liquid_outline_distance')" class="form-item form-item-slider">
|
||||
<el-slider v-model="sizeForm.liquidOutlineDistance" show-input :show-input-controls="false" input-size="mini" :min="0" :max="20" @change="changeBarSizeCase" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('chart.liquid_wave_length')" class="form-item form-item-slider">
|
||||
<el-slider v-model="sizeForm.liquidWaveLength" show-input :show-input-controls="false" input-size="mini" :min="10" :max="500" @change="changeBarSizeCase" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('chart.liquid_wave_count')" class="form-item form-item-slider">
|
||||
<el-slider v-model="sizeForm.liquidWaveCount" show-input :show-input-controls="false" input-size="mini" :min="2" :max="10" @change="changeBarSizeCase" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</div>
|
||||
|
@ -196,9 +196,9 @@
|
||||
:options="chartGroupTreeAvailable"
|
||||
:normalizer="normalizer"
|
||||
:placeholder="$t('chart.select_group')"
|
||||
:noChildrenText="$t('commons.treeselect.no_children_text')"
|
||||
:noOptionsText="$t('commons.treeselect.no_options_text')"
|
||||
:noResultsText="$t('commons.treeselect.no_results_text')"
|
||||
:no-children-text="$t('commons.treeselect.no_children_text')"
|
||||
:no-options-text="$t('commons.treeselect.no_options_text')"
|
||||
:no-results-text="$t('commons.treeselect.no_results_text')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -558,7 +558,7 @@ export default {
|
||||
showClose: true
|
||||
})
|
||||
this.treeNode()
|
||||
this.$store.dispatch('chart/setTable', null)
|
||||
this.$store.dispatch('chart/setTable', new Date().getTime())
|
||||
})
|
||||
} else {
|
||||
// this.$message({
|
||||
@ -773,6 +773,7 @@ export default {
|
||||
view.customFilter = JSON.stringify([])
|
||||
view.drillFields = JSON.stringify([])
|
||||
view.extBubble = JSON.stringify([])
|
||||
this.setChartDefaultOptions(view)
|
||||
const _this = this
|
||||
post('/chart/view/save', view).then(response => {
|
||||
this.closeCreateChart()
|
||||
@ -788,6 +789,33 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
setChartDefaultOptions(view) {
|
||||
const type = view.type
|
||||
const attr = JSON.parse(view.customAttr)
|
||||
if (type.includes('pie')) {
|
||||
if (view.render === 'echarts') {
|
||||
attr.label.position = 'inside'
|
||||
} else {
|
||||
attr.label.position = 'inner'
|
||||
}
|
||||
} else if (type.includes('line')) {
|
||||
attr.label.position = 'top'
|
||||
} else if (type.includes('treemap')) {
|
||||
if (view.render === 'echarts') {
|
||||
attr.label.position = 'inside'
|
||||
} else {
|
||||
attr.label.position = 'middle'
|
||||
}
|
||||
} else {
|
||||
if (view.render === 'echarts') {
|
||||
attr.label.position = 'inside'
|
||||
} else {
|
||||
attr.label.position = 'middle'
|
||||
}
|
||||
}
|
||||
view.customAttr = JSON.stringify(attr)
|
||||
},
|
||||
|
||||
getTable(table) {
|
||||
this.table = JSON.parse(JSON.stringify(table))
|
||||
},
|
||||
|
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<el-row v-loading="loading" style="height: 100%;overflow-y: hidden;width: 100%;">
|
||||
<el-row style="height: 40px;" class="padding-lr">
|
||||
<span v-show="false">{{ refreshPage }}</span>
|
||||
<span class="title-text" style="line-height: 40px;">{{ view.name }}</span>
|
||||
<el-popover
|
||||
placement="right-start"
|
||||
@ -141,7 +142,7 @@
|
||||
class="render-select"
|
||||
style="width: 100px"
|
||||
size="mini"
|
||||
@change="calcData(true,'chart',true,true)"
|
||||
@change="changeChartType()"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in renderOptions"
|
||||
@ -158,7 +159,7 @@
|
||||
v-model="view.type"
|
||||
style="width: 100%"
|
||||
:disabled="!hasDataPermission('manage',param.privileges)"
|
||||
@change="calcData(true,'chart',true,true)"
|
||||
@change="changeChartType()"
|
||||
>
|
||||
<chart-type :chart="view" style="height: 480px" />
|
||||
</el-radio-group>
|
||||
@ -1105,11 +1106,10 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// vId() {
|
||||
// // console.log(this.$store.state.chart.viewId);
|
||||
// this.getData(this.$store.state.chart.viewId)
|
||||
// return this.$store.state.chart.viewId
|
||||
// }
|
||||
refreshPage: function() {
|
||||
this.getChart(this.param.id)
|
||||
return this.$store.getters.chartTable
|
||||
},
|
||||
chartType() {
|
||||
return this.chart.type
|
||||
}
|
||||
@ -2066,6 +2066,36 @@ export default {
|
||||
|
||||
reset() {
|
||||
this.getData(this.param.id)
|
||||
},
|
||||
|
||||
changeChartType() {
|
||||
this.setChartDefaultOptions()
|
||||
this.calcData(true, 'chart', true, true)
|
||||
},
|
||||
|
||||
setChartDefaultOptions() {
|
||||
const type = this.view.type
|
||||
if (type.includes('pie')) {
|
||||
if (this.view.render === 'echarts') {
|
||||
this.view.customAttr.label.position = 'inside'
|
||||
} else {
|
||||
this.view.customAttr.label.position = 'inner'
|
||||
}
|
||||
} else if (type.includes('line')) {
|
||||
this.view.customAttr.label.position = 'top'
|
||||
} else if (type.includes('treemap')) {
|
||||
if (this.view.render === 'echarts') {
|
||||
this.view.customAttr.label.position = 'inside'
|
||||
} else {
|
||||
this.view.customAttr.label.position = 'middle'
|
||||
}
|
||||
} else {
|
||||
if (this.view.render === 'echarts') {
|
||||
this.view.customAttr.label.position = 'inside'
|
||||
} else {
|
||||
this.view.customAttr.label.position = 'middle'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-row style="height: 100%;overflow-y: hidden;width: 100%;">
|
||||
<!-- <span v-show="false">{{ tableRefresh }}</span>-->
|
||||
<span v-show="false">{{ refreshPage }}</span>
|
||||
<el-row style="height: 26px;">
|
||||
<span class="title-text" style="line-height: 26px;">
|
||||
{{ table.name }}
|
||||
@ -57,7 +57,7 @@
|
||||
<update-info v-if="tabActive=='updateInfo'" :param="param" :table="table" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane v-if="isPluginLoaded && hasDataPermission('manage',param.privileges)" :lazy="true" :label="$t('dataset.row_permissions')" name="rowPermissions">
|
||||
<plugin-com v-if="isPluginLoaded && tabActive=='rowPermissions'" ref="RowPermissions" component-name="RowPermissions" :obj="table"/>
|
||||
<plugin-com v-if="isPluginLoaded && tabActive=='rowPermissions'" ref="RowPermissions" component-name="RowPermissions" :obj="table" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane v-if="isPluginLoaded && hasDataPermission('manage',param.privileges)" :lazy="true" :label="$t('dataset.column_permissions')" name="columnPermissions">
|
||||
<plugin-com v-if="isPluginLoaded && tabActive=='columnPermissions'" ref="ColumnPermissions" component-name="ColumnPermissions" :obj="table" />
|
||||
@ -78,7 +78,7 @@ import PluginCom from '@/views/system/plugin/PluginCom'
|
||||
|
||||
export default {
|
||||
name: 'ViewTable',
|
||||
components: {FieldEdit, UnionView, DatasetChartDetail, UpdateInfo, TabDataPreview, PluginCom },
|
||||
components: { FieldEdit, UnionView, DatasetChartDetail, UpdateInfo, TabDataPreview, PluginCom },
|
||||
props: {
|
||||
param: {
|
||||
type: Object,
|
||||
@ -105,14 +105,13 @@ export default {
|
||||
isPluginLoaded: false
|
||||
}
|
||||
},
|
||||
beforeCreate() {
|
||||
pluginLoaded().then(res => {
|
||||
this.isPluginLoaded = res.success && res.data
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
hideCustomDs: function() {
|
||||
return this.$store.getters.hideCustomDs
|
||||
},
|
||||
refreshPage: function() {
|
||||
this.initTable(this.param.id)
|
||||
return this.$store.getters.table
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -121,6 +120,11 @@ export default {
|
||||
this.initTable(this.param.id)
|
||||
}
|
||||
},
|
||||
beforeCreate() {
|
||||
pluginLoaded().then(res => {
|
||||
this.isPluginLoaded = res.success && res.data
|
||||
})
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
|
@ -688,7 +688,7 @@ export default {
|
||||
},
|
||||
cancelFilter() {
|
||||
this.closeFilter()
|
||||
if(this.filterFromDrag){
|
||||
if (this.filterFromDrag) {
|
||||
bus.$emit('onRemoveLastItem')
|
||||
}
|
||||
},
|
||||
@ -697,6 +697,7 @@ export default {
|
||||
this.$store.commit('setComponentWithId', this.currentFilterCom)
|
||||
this.$store.commit('recordSnapshot', 'sureFilter')
|
||||
this.$store.commit('setCurComponent', { component: this.currentFilterCom, index: this.curComponentIndex })
|
||||
bus.$emit('reset-default-value', this.currentFilterCom.id)
|
||||
this.closeFilter()
|
||||
},
|
||||
reFreshComponent(component) {
|
||||
|
@ -4,8 +4,14 @@
|
||||
|
||||
<el-form-item :label="$t('dynamic_time.set_default')">
|
||||
<el-radio-group v-model="element.options.attrs.default.isDynamic" @change="dynamicChange">
|
||||
<el-radio :label="false">{{ $t('dynamic_time.fix') }}</el-radio>
|
||||
<el-radio :label="true">{{ $t('dynamic_time.dynamic') }}</el-radio>
|
||||
|
||||
<el-radio
|
||||
v-for="(item, index) in defaultSetting.radioOptions"
|
||||
:key="index"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ $t(item.text) }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
@ -17,10 +23,13 @@
|
||||
class="relative-time"
|
||||
@change="dkeyChange"
|
||||
>
|
||||
<el-option :label="$t('dynamic_time.today')" :value="0" />
|
||||
<el-option :label="$t('dynamic_time.yesterday')" :value="1" />
|
||||
<el-option :label="$t('dynamic_time.firstOfMonth')" :value="2" />
|
||||
<el-option :label="$t('dynamic_time.custom')" :value="3" />
|
||||
<el-option
|
||||
v-for="(item, index) in defaultSetting.relativeOptions"
|
||||
:key="item.value + index"
|
||||
:label="$t(item.text)"
|
||||
:value="item.value"
|
||||
/>
|
||||
|
||||
</el-select>
|
||||
|
||||
</el-form-item>
|
||||
@ -28,7 +37,7 @@
|
||||
<div class="inline">
|
||||
|
||||
<el-form-item
|
||||
v-if="element.options.attrs.default.isDynamic && element.options.attrs.default.dkey === 3"
|
||||
v-if="element.options.attrs.default.isDynamic && element.options.attrs.default.dkey === (defaultSetting.relativeOptions.length - 1)"
|
||||
label=""
|
||||
>
|
||||
<el-input
|
||||
@ -42,7 +51,7 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
v-if="element.options.attrs.default.isDynamic && element.options.attrs.default.dkey === 3"
|
||||
v-if="element.options.attrs.default.isDynamic && element.options.attrs.default.dkey === (defaultSetting.relativeOptions.length - 1)"
|
||||
label=""
|
||||
class="no-label-item"
|
||||
>
|
||||
@ -50,17 +59,21 @@
|
||||
v-model="element.options.attrs.default.dynamicInfill"
|
||||
size="mini"
|
||||
placeholder=""
|
||||
:disabled="defaultSetting.custom && defaultSetting.custom.unitsOptions && defaultSetting.custom.unitsOptions.length === 1"
|
||||
@change="dynamicInfillChange"
|
||||
>
|
||||
<el-option :label="$t('dynamic_time.date')" value="day" />
|
||||
<el-option :label="$t('dynamic_time.week')" value="week" />
|
||||
<el-option :label="$t('dynamic_time.month')" value="month" />
|
||||
<el-option :label="$t('dynamic_time.year')" value="year" />
|
||||
<el-option
|
||||
v-for="(item, index) in defaultSetting.custom.unitsOptions"
|
||||
:key="item.value + index"
|
||||
:label="$t(item.text)"
|
||||
:value="item.value"
|
||||
/>
|
||||
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
v-if="element.options.attrs.default.isDynamic && element.options.attrs.default.dkey === 3"
|
||||
v-if="element.options.attrs.default.isDynamic && element.options.attrs.default.dkey === (defaultSetting.relativeOptions.length - 1)"
|
||||
label=""
|
||||
class="no-label-item"
|
||||
>
|
||||
@ -79,7 +92,13 @@
|
||||
</div>
|
||||
|
||||
<el-form-item v-if="element.options.attrs.default.isDynamic" :label="$t('dynamic_time.preview')">
|
||||
<el-date-picker v-model="dval" type="date" disabled placeholder="" class="relative-time" />
|
||||
<el-date-picker
|
||||
v-model="dval"
|
||||
:type="element.options.attrs.type"
|
||||
disabled
|
||||
placeholder=""
|
||||
class="relative-time"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item v-else :label="$t('dynamic_time.set')">
|
||||
@ -115,6 +134,13 @@ export default {
|
||||
dval: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
defaultSetting() {
|
||||
const widget = ApplicationContext.getService(this.element.serviceName)
|
||||
const setting = widget.defaultSetting()
|
||||
return setting
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.setDval()
|
||||
},
|
||||
@ -143,6 +169,7 @@ export default {
|
||||
const widget = ApplicationContext.getService(this.element.serviceName)
|
||||
const time = widget.dynamicDateFormNow(this.element)
|
||||
this.dval = time
|
||||
this.element.options.manualModify = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -213,6 +213,7 @@ export default {
|
||||
const time = widget.dynamicDateFormNow(this.element)
|
||||
this.dval = time
|
||||
bus.$emit('valid-values-change', (!time || time.length === 0 || time[1] > time[0]))
|
||||
this.element.options.manualModify = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,11 @@
|
||||
<el-col :span="24">
|
||||
<div class="filter-content">
|
||||
<el-card
|
||||
v-if="element.serviceName && element.serviceName !== 'timeDateWidget' && element.serviceName !== 'timeDateRangeWidget'"
|
||||
v-if="element.component && element.component !== 'de-date'"
|
||||
class="box-card"
|
||||
>
|
||||
<div style="margin-bottom: 10px;">
|
||||
<span>默认值设置</span>
|
||||
<span>{{ $t('dynamic_time.set_default') }}</span>
|
||||
</div>
|
||||
<div class="custom-component-class">
|
||||
<component
|
||||
@ -22,13 +22,13 @@
|
||||
|
||||
</el-card>
|
||||
|
||||
<el-card v-if="element.serviceName && element.serviceName === 'timeDateWidget'" class="box-card">
|
||||
<de-date-default v-if="element.serviceName && element.serviceName === 'timeDateWidget'" :element="element" />
|
||||
<el-card v-if="element.component && element.component === 'de-date' && element.serviceName && element.serviceName !== 'timeDateRangeWidget'" class="box-card">
|
||||
<de-date-default v-if="element.component === 'de-date' && element.serviceName !== 'timeDateRangeWidget'" :element="element" />
|
||||
</el-card>
|
||||
|
||||
<el-card v-if="element.serviceName && element.serviceName === 'timeDateRangeWidget'" class="box-card">
|
||||
<el-card v-if="element.component && element.component === 'de-date' && element.serviceName && element.serviceName === 'timeDateRangeWidget'" class="box-card">
|
||||
<de-date-range-default
|
||||
v-if="element.serviceName && element.serviceName === 'timeDateRangeWidget'"
|
||||
v-if="element.component === 'de-date' && element.serviceName === 'timeDateRangeWidget'"
|
||||
:element="element"
|
||||
/>
|
||||
</el-card>
|
||||
|
@ -13,12 +13,12 @@
|
||||
<el-form-item :label="$t('commons.email')" prop="email">
|
||||
<el-input v-model="form.email" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="formType !== 'modify'" :label="$t('commons.password')" prop="password">
|
||||
<!-- <el-form-item v-if="formType !== 'modify'" :label="$t('commons.password')" prop="password">
|
||||
<el-input v-model="form.password" autocomplete="off" show-password />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="formType !== 'modify'" :label="$t('commons.confirmPassword')" prop="confirmPassword">
|
||||
<el-input v-model="form.confirmPassword" autocomplete="off" show-password />
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
|
||||
<el-form-item :label="$t('commons.gender')" prop="gender">
|
||||
<el-radio-group v-model="form.gender" style="width: 178px">
|
||||
@ -40,9 +40,9 @@
|
||||
:load-options="loadDepts"
|
||||
:auto-load-root-options="false"
|
||||
:placeholder="$t('user.choose_org')"
|
||||
:noChildrenText="$t('commons.treeselect.no_children_text')"
|
||||
:noOptionsText="$t('commons.treeselect.no_options_text')"
|
||||
:noResultsText="$t('commons.treeselect.no_results_text')"
|
||||
:no-children-text="$t('commons.treeselect.no_children_text')"
|
||||
:no-options-text="$t('commons.treeselect.no_options_text')"
|
||||
:no-results-text="$t('commons.treeselect.no_results_text')"
|
||||
@open="filterData"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
60
frontend/src/views/wizard/card.vue
Normal file
@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<el-col :span="8" class="card_main">
|
||||
<el-row>
|
||||
<el-col :span="8" class="card_head">
|
||||
<span>{{ headInfo }}</span>
|
||||
</el-col>
|
||||
<el-col :span="1" class="triangle" />
|
||||
</el-row>
|
||||
<el-row class="card_content">
|
||||
<slot />
|
||||
</el-row>
|
||||
</el-col>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'Card',
|
||||
props: {
|
||||
headInfo: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card_main{
|
||||
padding: 40px 30px 30px 30px;
|
||||
height: 33vh;
|
||||
}
|
||||
.card_head{
|
||||
padding-left: 15px;
|
||||
color: white;
|
||||
line-height: 30px;
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
background-color: var(--MenuActiveBG, #409EFF);
|
||||
}
|
||||
.triangle{
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-bottom: 30px solid var(--MenuActiveBG, #409EFF);
|
||||
border-right: 30px solid transparent;
|
||||
-webkit-transform: rotate(180deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
.card_content{
|
||||
border: lightgray solid 1px;
|
||||
border-radius: 0px 5px 5px 5px;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
</style>
|
51
frontend/src/views/wizard/details/ContactUs.vue
Normal file
@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<el-row class="demo_main">
|
||||
<el-row style="margin-top: 5%" class="demo_content">
|
||||
<span class="icon iconfont icon-fasongyoujian" />
|
||||
<span style="margin-left: 10px">dataease@fit2cloud.com</span>
|
||||
</el-row>
|
||||
<el-row class="demo_content">
|
||||
<span class="icon iconfont icon-dianhua" />
|
||||
<span style="margin-left: 10px">400-052-0755</span>
|
||||
</el-row>
|
||||
<el-row class="demo_content">
|
||||
<span class="icon iconfont icon-github" />
|
||||
<span class="demo_git"><a href="https://github.com/dataease/dataease/issues" target="_blank">{{ $t('wizard.open_source_community') }}</a></span>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'ContactUs',
|
||||
data() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.demo_main{
|
||||
height: 100%;
|
||||
padding: 10px 20px 10px 20px;
|
||||
}
|
||||
.demo_content{
|
||||
padding-left: 10px;
|
||||
height: 30%;
|
||||
}
|
||||
.demo_git{
|
||||
margin-left: 10px;
|
||||
color: var(--MenuActiveBG, #409EFF);
|
||||
}
|
||||
|
||||
.demo_bottom{
|
||||
position: absolute;
|
||||
left: 30px;
|
||||
bottom: 10px;
|
||||
font-weight: 500;
|
||||
color: var(--MenuActiveBG, #409EFF);
|
||||
}
|
||||
|
||||
</style>
|
49
frontend/src/views/wizard/details/DemoVideo.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<el-row class="demo_main">
|
||||
<div class="demo_title" />
|
||||
<div class="demo_content">
|
||||
<a href="https://www.bilibili.com/video/BV1UB4y1K7jA" target="_blank">{{ $t('wizard.demo_video_hint') }}</a>
|
||||
</div>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'DemoVideo',
|
||||
props: {
|
||||
headInfo: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.demo_main{
|
||||
height: 100%;
|
||||
padding: 10px 20px 10px 20px;
|
||||
}
|
||||
.demo_title{
|
||||
float: left;
|
||||
height: 100%;
|
||||
width: 50%;
|
||||
background-size: 100% 100% !important;
|
||||
background-image: url('../../../assets/deV.png');
|
||||
}
|
||||
.demo_content{
|
||||
margin: auto;
|
||||
padding-left: 10px;
|
||||
float: left;
|
||||
width: 50%;
|
||||
font-weight: 500;
|
||||
color: var(--MenuActiveBG, #409EFF);
|
||||
|
||||
}
|
||||
|
||||
</style>
|
60
frontend/src/views/wizard/details/EnterpriseEdition.vue
Normal file
@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<el-row class="demo_main">
|
||||
<el-row class="demo_content">
|
||||
<span>
|
||||
{{ $t('wizard.enterprise_edition_hint1') }}
|
||||
</span>
|
||||
<br>
|
||||
<span>
|
||||
{{ $t('wizard.enterprise_edition_hint2') }}
|
||||
</span>
|
||||
<br>
|
||||
<span>
|
||||
{{ $t('wizard.enterprise_edition_hint3') }}
|
||||
</span>
|
||||
</el-row>
|
||||
<el-row class="demo_bottom">
|
||||
<a href="https://jinshuju.net/f/TK5TTd" target="_blank"> {{ $t('wizard.click_inner') }}</a>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'TeachingVideo',
|
||||
props: {
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.demo_main{
|
||||
height: 100%;
|
||||
padding: 10px 20px 10px 20px;
|
||||
}
|
||||
.demo_content{
|
||||
padding-left: 10px;
|
||||
float: left;
|
||||
font-weight: 400;
|
||||
max-height: 80%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.demo_bottom{
|
||||
position: absolute;
|
||||
left: 30px;
|
||||
bottom: 10px;
|
||||
font-weight: 500;
|
||||
color: var(--MenuActiveBG, #409EFF);
|
||||
}
|
||||
|
||||
.title{
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
</style>
|
65
frontend/src/views/wizard/details/LatestDevelopments.vue
Normal file
@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<el-row class="demo_main">
|
||||
<el-row class="demo_content">
|
||||
<a :href="href" target="_blank">{{ title }}</a>
|
||||
<br>
|
||||
<span style="color: lightgray">{{ time }}</span>
|
||||
</el-row>
|
||||
<el-row class="demo_bottom">
|
||||
<a href="https://blog.fit2cloud.com/?cat=321" target="_blank">{{ $t('wizard.show_more') }}</a>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { blogLastActive } from '@/api/wizard/wizard'
|
||||
|
||||
export default {
|
||||
name: 'LatestDevelopments',
|
||||
data() {
|
||||
return {
|
||||
title: '',
|
||||
href: '',
|
||||
time: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
blogLastActive().then(res => {
|
||||
this.title = res.data.title
|
||||
this.href = res.data.href
|
||||
this.time = res.data.time
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.demo_main{
|
||||
height: 100%;
|
||||
padding: 10px 20px 10px 20px;
|
||||
}
|
||||
.demo_content{
|
||||
padding-left: 10px;
|
||||
float: left;
|
||||
font-weight: 500;
|
||||
color: var(--MenuActiveBG, #409EFF);
|
||||
max-height: 80%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.demo_bottom{
|
||||
position: absolute;
|
||||
left: 30px;
|
||||
bottom: 10px;
|
||||
font-weight: 500;
|
||||
color: var(--MenuActiveBG, #409EFF);
|
||||
}
|
||||
|
||||
</style>
|
50
frontend/src/views/wizard/details/OnlineDocument.vue
Normal file
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<el-row class="demo_main">
|
||||
<el-row class="demo_content">
|
||||
<span>{{ $t('wizard.online_document_hint') }}</span>
|
||||
</el-row>
|
||||
<el-row class="demo_bottom">
|
||||
<a href="https://dataease.io/docs/dev_manual/dev_manual/" target="_blank">{{ $t('wizard.click_show') }}</a>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'OnlineDocument',
|
||||
props: {
|
||||
headInfo: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.demo_main{
|
||||
height: 100%;
|
||||
padding: 10px 20px 10px 20px;
|
||||
}
|
||||
.demo_content{
|
||||
padding-left: 10px;
|
||||
float: left;
|
||||
font-weight: 400;
|
||||
max-height: 80%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.demo_bottom{
|
||||
position: absolute;
|
||||
left: 30px;
|
||||
bottom: 10px;
|
||||
font-weight: 500;
|
||||
color: var(--MenuActiveBG, #409EFF);
|
||||
}
|
||||
|
||||
</style>
|
59
frontend/src/views/wizard/details/TeachingVideo.vue
Normal file
@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<el-row class="demo_main">
|
||||
<el-row class="demo_content">
|
||||
<span class="title">
|
||||
<a href="https://live.vhall.com/v3/lives/subscribe/533874762" target="_blank">40分钟带你玩转 DataEase </a>
|
||||
</span>
|
||||
<br>
|
||||
<span class="title">
|
||||
<a href="https://live.vhall.com/v3/lives/subscribe/903960272" target="_blank">用DataEase开源工具可视化 ClickHouse数据 </a>
|
||||
</span>
|
||||
</el-row>
|
||||
<el-row class="demo_bottom">
|
||||
<span style="color: black">{{ $t('wizard.teaching_video_bottom_hint') }}</span><a href="https://e.vhall.com/v3/user/home/45637107" target="_blank">{{ $t('wizard.click_inner') }}</a>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'OnlineDocument',
|
||||
props: {
|
||||
headInfo: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.demo_main{
|
||||
height: 100%;
|
||||
padding: 10px 20px 10px 20px;
|
||||
}
|
||||
.demo_content{
|
||||
padding-left: 10px;
|
||||
float: left;
|
||||
font-weight: 400;
|
||||
color: var(--MenuActiveBG, #409EFF);
|
||||
}
|
||||
|
||||
.demo_bottom{
|
||||
position: absolute;
|
||||
left: 30px;
|
||||
bottom: 10px;
|
||||
font-weight: 500;
|
||||
color: var(--MenuActiveBG, #409EFF);
|
||||
}
|
||||
|
||||
.title{
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
</style>
|
84
frontend/src/views/wizard/index.vue
Normal file
@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<el-row class="main_container">
|
||||
<el-row class="head">
|
||||
<span class="hint_head">{{ $t('wizard.welcome_title') }}</span> <br>
|
||||
<span class="hint_content">{{ $t('wizard.welcome_hint') }}</span>
|
||||
</el-row>
|
||||
<el-row class="card_container">
|
||||
<card v-for="(cardDetail,index) in cardList" :key="index" :head-info="cardDetail.headInfo">
|
||||
<component :is="cardDetail.component" />
|
||||
</card>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import Card from '@/views/wizard/card'
|
||||
import DemoVideo from '@/views/wizard/details/DemoVideo'
|
||||
import OnlineDocument from '@/views/wizard/details/OnlineDocument'
|
||||
import LatestDevelopments from '@/views/wizard/details/LatestDevelopments'
|
||||
import TeachingVideo from '@/views/wizard/details/TeachingVideo'
|
||||
import EnterpriseEdition from '@/views/wizard/details/EnterpriseEdition'
|
||||
import ContactUs from '@/views/wizard/details/ContactUs'
|
||||
export default {
|
||||
name: 'Wizard',
|
||||
components: { Card, DemoVideo, OnlineDocument, LatestDevelopments, TeachingVideo, EnterpriseEdition, ContactUs },
|
||||
data() {
|
||||
return {
|
||||
cardList: [
|
||||
{
|
||||
headInfo: this.$t('wizard.demo_video'),
|
||||
component: 'DemoVideo'
|
||||
},
|
||||
{
|
||||
headInfo: this.$t('wizard.online_document'),
|
||||
component: 'OnlineDocument'
|
||||
},
|
||||
{
|
||||
headInfo: this.$t('wizard.latest_developments'),
|
||||
component: 'LatestDevelopments'
|
||||
},
|
||||
{
|
||||
headInfo: this.$t('wizard.teaching_video'),
|
||||
component: 'TeachingVideo'
|
||||
},
|
||||
{
|
||||
headInfo: this.$t('wizard.enterprise_edition'),
|
||||
component: 'EnterpriseEdition'
|
||||
},
|
||||
{
|
||||
headInfo: this.$t('wizard.contact_us'),
|
||||
component: 'ContactUs'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.main_container {
|
||||
}
|
||||
.head {
|
||||
background-color: var(--MenuActiveBG, #409EFF);
|
||||
text-align: center;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
margin-top: 25px;
|
||||
}
|
||||
.hint_head {
|
||||
line-height: 40px;
|
||||
font-weight: bold;
|
||||
font-size: 25px;
|
||||
}
|
||||
.hint_content {
|
||||
line-height: 40px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.card_container {
|
||||
|
||||
}
|
||||
</style>
|
5
mobile/dist/build/h5/index.html
vendored
@ -1,5 +0,0 @@
|
||||
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title></title><script>document.addEventListener('DOMContentLoaded', function() {
|
||||
document.documentElement.style.fontSize = document.documentElement.clientWidth / 20 + 'px'
|
||||
})
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
|
||||
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')</script><link rel="stylesheet" href="/de-app/static/index.a5c69d49.css"></head><body><noscript><strong>Please enable JavaScript to continue.</strong></noscript><div id="app"></div><script src="/de-app/static/js/chunk-vendors.2822c2ee.js"></script><script src="/de-app/static/js/index.12bd8b7a.js"></script></body></html>
|
BIN
mobile/dist/build/h5/static/DataEase-01.png
vendored
Before Width: | Height: | Size: 28 KiB |
BIN
mobile/dist/build/h5/static/about.png
vendored
Before Width: | Height: | Size: 15 KiB |
BIN
mobile/dist/build/h5/static/dir.png
vendored
Before Width: | Height: | Size: 4.6 KiB |
BIN
mobile/dist/build/h5/static/folder-close.png
vendored
Before Width: | Height: | Size: 2.4 KiB |
BIN
mobile/dist/build/h5/static/folder-open.png
vendored
Before Width: | Height: | Size: 3.4 KiB |
BIN
mobile/dist/build/h5/static/folder.png
vendored
Before Width: | Height: | Size: 4.7 KiB |
BIN
mobile/dist/build/h5/static/fonts/uni.75745d34.ttf
vendored
BIN
mobile/dist/build/h5/static/home.png
vendored
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 28 KiB |
BIN
mobile/dist/build/h5/static/img/logo-bg.e3894578.jpg
vendored
Before Width: | Height: | Size: 561 KiB |
BIN
mobile/dist/build/h5/static/img/user.1e5d0b29.png
vendored
Before Width: | Height: | Size: 12 KiB |