mirror of https://github.com/jeecgboot/jeecg-boot
v3.7.2 版本代码合并
parent
64b29f47e0
commit
b0c4194602
File diff suppressed because one or more lines are too long
|
@ -84,6 +84,12 @@ public class MessageDTO implements Serializable {
|
|||
* 邮件抄送地址
|
||||
*/
|
||||
protected Set<String> ccEmailList;
|
||||
|
||||
/**
|
||||
* 是否为定时任务推送email
|
||||
*/
|
||||
private Boolean isTimeJob = false;
|
||||
|
||||
//---【邮件相关参数】-------------------------------------------------------------
|
||||
|
||||
public MessageDTO(){
|
||||
|
|
|
@ -604,6 +604,11 @@ public interface CommonConstant {
|
|||
*/
|
||||
String CHANGE_PHONE_REDIS_KEY_PRE = "sys:cache:phone:change_phone_msg:";
|
||||
|
||||
/**
|
||||
* 手机号短信验证码redis-key的前缀
|
||||
*/
|
||||
String LOG_OFF_PHONE_REDIS_KEY_PRE = "sys:cache:phone:qqy_log_off_user_msg:";
|
||||
|
||||
/**
|
||||
* 缓存用户最后一次收到消息通知的时间 KEY
|
||||
*/
|
||||
|
|
|
@ -15,15 +15,7 @@ public enum DySmsEnum {
|
|||
/**修改密码短信模板编码*/
|
||||
CHANGE_PASSWORD_TEMPLATE_CODE("SMS_465391221","敲敲云","code"),
|
||||
/**注册账号短信模板编码*/
|
||||
REGISTER_TEMPLATE_CODE("SMS_175430166","敲敲云","code"),
|
||||
/**会议通知*/
|
||||
MEET_NOTICE_TEMPLATE_CODE("SMS_201480469","JEECG","username,title,minute,time"),
|
||||
/**我的计划通知*/
|
||||
PLAN_NOTICE_TEMPLATE_CODE("SMS_201470515","JEECG","username,title,time"),
|
||||
/**支付成功短信通知*/
|
||||
PAY_SUCCESS_NOTICE_CODE("SMS_461735163","敲敲云","realname,money,endTime"),
|
||||
/**会员到期通知提醒*/
|
||||
VIP_EXPIRE_NOTICE_CODE("SMS_461885023","敲敲云","realname,endTime");
|
||||
REGISTER_TEMPLATE_CODE("SMS_175430166","敲敲云","code");
|
||||
|
||||
/**
|
||||
* 短信模板编码
|
||||
|
|
|
@ -805,7 +805,9 @@ public class QueryGenerator {
|
|||
addEasyQuery(queryWrapper, name, rule, DateUtils.str2Date(dateStr,DateUtils.datetimeFormat.get()));
|
||||
}
|
||||
}else {
|
||||
addEasyQuery(queryWrapper, name, rule, NumberUtils.parseNumber(dataRule.getRuleValue(), propertyType));
|
||||
//update-begin---author:chenrui ---date:20241125 for:[issues/7481]多租户模式下 数据权限使用变量:#{tenant_id} 报错------------
|
||||
addEasyQuery(queryWrapper, name, rule, NumberUtils.parseNumber(converRuleValue(dataRule.getRuleValue()), propertyType));
|
||||
//update-end---author:chenrui ---date:20241125 for:[issues/7481]多租户模式下 数据权限使用变量:#{tenant_id} 报错------------
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,8 +54,10 @@ public enum QueryRuleEnum {
|
|||
NOT_EMPTY("NOT_EMPTY","not_empty","值不为空"),
|
||||
/**查询规则 不包含*/
|
||||
NOT_IN("NOT_IN","not_in","不包含"),
|
||||
/**查询规则 多词匹配*/
|
||||
/**查询规则 多词精确匹配*/
|
||||
ELE_MATCH("ELE_MATCH","elemMatch","多词匹配"),
|
||||
/**查询规则 多词精确不匹配*/
|
||||
ELE_NOT_MATCH("ELE_NOT_MATCH","elemNotMatch","多词精确不匹配"),
|
||||
/**查询规则 范围查询*/
|
||||
RANGE("RANGE","range","范围查询"),
|
||||
/**查询规则 不在范围内查询*/
|
||||
|
|
|
@ -63,7 +63,7 @@ public class JwtUtil {
|
|||
os.flush();
|
||||
os.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,8 @@ public class JwtUtil {
|
|||
// 效验TOKEN
|
||||
DecodedJWT jwt = verifier.verify(token);
|
||||
return true;
|
||||
} catch (Exception exception) {
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -97,6 +98,7 @@ public class JwtUtil {
|
|||
DecodedJWT jwt = JWT.decode(token);
|
||||
return jwt.getClaim("username").asString();
|
||||
} catch (JWTDecodeException e) {
|
||||
log.warn(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.jeecg.common.util;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.aliyuncs.DefaultAcsClient;
|
||||
import com.aliyuncs.IAcsClient;
|
||||
|
@ -8,11 +9,15 @@ import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
|
|||
import com.aliyuncs.exceptions.ClientException;
|
||||
import com.aliyuncs.profile.DefaultProfile;
|
||||
import com.aliyuncs.profile.IClientProfile;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.common.constant.enums.DySmsEnum;
|
||||
import org.jeecg.config.JeecgSmsTemplateConfig;
|
||||
import org.jeecg.config.StaticConfig;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created on 17/6/7.
|
||||
* 短信API产品的DEMO程序,工程中包含了一个SmsDemo类,直接通过
|
||||
|
@ -75,15 +80,33 @@ public class DySmsHelper {
|
|||
|
||||
//验证json参数
|
||||
validateParam(templateParamJson,dySmsEnum);
|
||||
|
||||
//update-begin---author:wangshuai---date:2024-11-05---for:【QQYUN-9422】短信模板管理,阿里云---
|
||||
String templateCode = dySmsEnum.getTemplateCode();
|
||||
JeecgSmsTemplateConfig baseConfig = SpringContextUtils.getBean(JeecgSmsTemplateConfig.class);
|
||||
if(baseConfig != null && CollectionUtil.isNotEmpty(baseConfig.getTemplateCode())){
|
||||
Map<String, String> smsTemplate = baseConfig.getTemplateCode();
|
||||
if(smsTemplate.containsKey(templateCode) && StringUtils.isNotEmpty(smsTemplate.get(templateCode))){
|
||||
templateCode = smsTemplate.get(templateCode);
|
||||
logger.info("yml中读取短信code{}",templateCode);
|
||||
}
|
||||
}
|
||||
//签名名称
|
||||
String signName = dySmsEnum.getSignName();
|
||||
if(baseConfig != null && StringUtils.isNotEmpty(baseConfig.getSignature())){
|
||||
logger.info("yml中读取签名名称{}",baseConfig.getSignature());
|
||||
signName = baseConfig.getSignature();
|
||||
}
|
||||
//update-end---author:wangshuai---date:2024-11-05---for:【QQYUN-9422】短信模板管理,阿里云---
|
||||
|
||||
//组装请求对象-具体描述见控制台-文档部分内容
|
||||
SendSmsRequest request = new SendSmsRequest();
|
||||
//必填:待发送手机号
|
||||
request.setPhoneNumbers(phone);
|
||||
//必填:短信签名-可在短信控制台中找到
|
||||
request.setSignName(dySmsEnum.getSignName());
|
||||
request.setSignName(signName);
|
||||
//必填:短信模板-可在短信控制台中找到
|
||||
request.setTemplateCode(dySmsEnum.getTemplateCode());
|
||||
request.setTemplateCode(templateCode);
|
||||
//可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
|
||||
request.setTemplateParam(templateParamJson.toJSONString());
|
||||
|
||||
|
|
|
@ -6,7 +6,11 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.common.constant.SymbolConstant;
|
||||
import org.jeecg.common.handler.IFillRuleHandler;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -42,6 +46,30 @@ public class FillRuleUtil {
|
|||
if (params == null) {
|
||||
params = new JSONObject();
|
||||
}
|
||||
|
||||
HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
|
||||
|
||||
// 解析 params 中的变量
|
||||
// 优先级:queryString > 系统变量 > 默认值
|
||||
for (String key : params.keySet()) {
|
||||
// 1. 判断 queryString 中是否有该参数,如果有就优先取值
|
||||
//noinspection ConstantValue
|
||||
if (request != null) {
|
||||
String parameter = request.getParameter(key);
|
||||
if (oConvertUtils.isNotEmpty(parameter)) {
|
||||
params.put(key, parameter);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
String value = params.getString(key);
|
||||
// 2. 用于替换 系统变量的值 #{sys_user_code}
|
||||
if (value != null && value.contains(SymbolConstant.SYS_VAR_PREFIX)) {
|
||||
value = QueryGenerator.getSqlRuleValue(value);
|
||||
params.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (formData == null) {
|
||||
formData = new JSONObject();
|
||||
}
|
||||
|
|
|
@ -57,8 +57,8 @@ public class RestUtil {
|
|||
|
||||
static {
|
||||
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
|
||||
requestFactory.setConnectTimeout(3000);
|
||||
requestFactory.setReadTimeout(3000);
|
||||
requestFactory.setConnectTimeout(30000);
|
||||
requestFactory.setReadTimeout(30000);
|
||||
RT = new RestTemplate(requestFactory);
|
||||
// 解决乱码问题
|
||||
RT.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
|
||||
|
|
|
@ -84,6 +84,10 @@ public class DynamicDBUtil {
|
|||
} else {
|
||||
DruidDataSource dataSource = getJdbcDataSource(dbSource);
|
||||
if(dataSource!=null && dataSource.isEnable()){
|
||||
|
||||
// 【TV360X-2060】设置超时时间 6秒
|
||||
dataSource.setMaxWait(6000);
|
||||
|
||||
DataSourceCachePool.putCacheBasicDataSource(dbKey, dataSource);
|
||||
}else{
|
||||
throw new JeecgBootException("动态数据源连接失败,dbKey:"+dbKey);
|
||||
|
@ -109,7 +113,7 @@ public class DynamicDBUtil {
|
|||
DataSourceCachePool.removeCache(dbKey);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.info(e.getMessage(), e);
|
||||
log.warn(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,12 @@ public class JSqlParserUtils {
|
|||
* @return
|
||||
*/
|
||||
private static SelectSqlInfo parseBySelectBody(SelectBody selectBody) {
|
||||
// 判断是否使用了union等操作
|
||||
if (selectBody instanceof SetOperationList) {
|
||||
// 如果使用了union等操作,则只解析第一个查询
|
||||
List<SelectBody> selectBodyList = ((SetOperationList) selectBody).getSelects();
|
||||
return JSqlParserUtils.parseBySelectBody(selectBodyList.get(0));
|
||||
}
|
||||
// 简单的select查询
|
||||
if (selectBody instanceof PlainSelect) {
|
||||
SelectSqlInfo sqlInfo = new SelectSqlInfo(selectBody);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package org.jeecg.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Description: 短信模板
|
||||
*
|
||||
* @author: wangshuai
|
||||
* @date: 2024/11/5 下午3:44
|
||||
*/
|
||||
@Data
|
||||
@Component("jeecgSmsTemplateConfig")
|
||||
@ConfigurationProperties(prefix = "jeecg.oss.sms-template")
|
||||
public class JeecgSmsTemplateConfig {
|
||||
|
||||
/**
|
||||
* 短信签名
|
||||
*/
|
||||
private String signature;
|
||||
|
||||
|
||||
/**
|
||||
* 短信模板code
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Map<String,String> templateCode;
|
||||
|
||||
}
|
|
@ -21,6 +21,12 @@ public class StaticConfig {
|
|||
@Value(value = "${spring.mail.username:}")
|
||||
private String emailFrom;
|
||||
|
||||
/**
|
||||
* 是否开启定时发送
|
||||
*/
|
||||
@Value(value = "${spring.mail.timeJobSend:false}")
|
||||
private Boolean timeJobSend;
|
||||
|
||||
// /**
|
||||
// * 签名密钥串
|
||||
// */
|
||||
|
|
|
@ -31,7 +31,7 @@ public class WebSocketConfig {
|
|||
FilterRegistrationBean bean = new FilterRegistrationBean();
|
||||
bean.setFilter(websocketFilter());
|
||||
//TODO 临时注释掉,测试下线上socket总断的问题
|
||||
bean.addUrlPatterns("/taskCountSocket/*", "/websocket/*","/eoaSocket/*","/eoaNewChatSocket/*", "/newsWebsocket/*", "/vxeSocket/*");
|
||||
bean.addUrlPatterns("/taskCountSocket/*", "/websocket/*","/eoaSocket/*","/eoaNewChatSocket/*", "/newsWebsocket/*", "/dragChannelSocket/*", "/vxeSocket/*");
|
||||
return bean;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,15 +17,17 @@ import org.jeecg.config.shiro.filters.CustomShiroFilterFactoryBean;
|
|||
import org.jeecg.config.shiro.filters.JwtFilter;
|
||||
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
import redis.clients.jedis.HostAndPort;
|
||||
import redis.clients.jedis.JedisCluster;
|
||||
|
@ -33,6 +35,7 @@ import redis.clients.jedis.JedisCluster;
|
|||
import javax.annotation.Resource;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.Filter;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
|
@ -123,7 +126,6 @@ public class ShiroConfig {
|
|||
filterChainDefinitionMap.put("/**/*.ttf", "anon");
|
||||
filterChainDefinitionMap.put("/**/*.woff", "anon");
|
||||
filterChainDefinitionMap.put("/**/*.woff2", "anon");
|
||||
|
||||
filterChainDefinitionMap.put("/**/*.glb", "anon");
|
||||
filterChainDefinitionMap.put("/**/*.wasm", "anon");
|
||||
//update-end--Author:scott Date:20221116 for:排除静态资源后缀
|
||||
|
@ -146,9 +148,15 @@ public class ShiroConfig {
|
|||
//拖拽仪表盘设计器排除
|
||||
filterChainDefinitionMap.put("/drag/view", "anon");
|
||||
filterChainDefinitionMap.put("/drag/page/queryById", "anon");
|
||||
filterChainDefinitionMap.put("/drag/page/addVisitsNumber", "anon");
|
||||
filterChainDefinitionMap.put("/drag/page/queryTemplateList", "anon");
|
||||
filterChainDefinitionMap.put("/drag/share/view/**", "anon");
|
||||
filterChainDefinitionMap.put("/drag/onlDragDatasetHead/getAllChartData", "anon");
|
||||
filterChainDefinitionMap.put("/drag/onlDragDatasetHead/getTotalData", "anon");
|
||||
filterChainDefinitionMap.put("/drag/mock/json/**", "anon");
|
||||
filterChainDefinitionMap.put("/jimubi/view", "anon");
|
||||
filterChainDefinitionMap.put("/jimubi/share/view/**", "anon");
|
||||
|
||||
//大屏模板例子
|
||||
filterChainDefinitionMap.put("/test/bigScreen/**", "anon");
|
||||
filterChainDefinitionMap.put("/bigscreen/template1/**", "anon");
|
||||
|
|
|
@ -168,8 +168,8 @@ public class ShiroRealm extends AuthorizingRealm {
|
|||
|
||||
//*********************************************
|
||||
if(!isAuthorization){
|
||||
log.warn("租户异常——当前登录的租户是:" + contextTenantId);
|
||||
log.warn("租户异常——用户拥有的租户是:" + userTenantIds);
|
||||
log.info("租户异常——登录租户:" + contextTenantId);
|
||||
log.info("租户异常——用户拥有租户组:" + userTenantIds);
|
||||
throw new AuthenticationException("登录租户授权变更,请重新登陆!");
|
||||
}
|
||||
//*********************************************
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,370 @@
|
|||
{
|
||||
"list": [
|
||||
{
|
||||
"key": "1717072932495_439966",
|
||||
"type": "card",
|
||||
"isAutoGrid": true,
|
||||
"isContainer": true,
|
||||
"list": [
|
||||
{
|
||||
"type": "input",
|
||||
"name": "名称",
|
||||
"className": "form-input",
|
||||
"icon": "icon-input",
|
||||
"hideTitle": false,
|
||||
"options": {
|
||||
"width": "100%",
|
||||
"defaultValue": "",
|
||||
"required": true,
|
||||
"dataType": null,
|
||||
"pattern": "",
|
||||
"placeholder": "",
|
||||
"clearable": false,
|
||||
"readonly": false,
|
||||
"disabled": false,
|
||||
"fillRuleCode": "",
|
||||
"showPassword": false,
|
||||
"unique": false,
|
||||
"hidden": false,
|
||||
"hiddenOnAdd": false,
|
||||
"fieldNote": "",
|
||||
"autoWidth": 50
|
||||
},
|
||||
"advancedSetting": {
|
||||
"defaultValue": {
|
||||
"type": "compose",
|
||||
"value": "",
|
||||
"format": "string",
|
||||
"allowFunc": true,
|
||||
"valueSplit": "",
|
||||
"customConfig": false
|
||||
}
|
||||
},
|
||||
"remoteAPI": {
|
||||
"url": "",
|
||||
"executed": false
|
||||
},
|
||||
"key": "1717072932495_556479",
|
||||
"model": "input_1717072932495_556479",
|
||||
"modelType": "main",
|
||||
"rules": [
|
||||
{
|
||||
"required": true,
|
||||
"message": "${title}必须填写"
|
||||
}
|
||||
],
|
||||
"isSubItem": false
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"name": "数字",
|
||||
"className": "form-number",
|
||||
"icon": "icon-number",
|
||||
"hideTitle": false,
|
||||
"options": {
|
||||
"width": "",
|
||||
"required": false,
|
||||
"defaultValue": 0,
|
||||
"placeholder": "",
|
||||
"controls": false,
|
||||
"min": 0,
|
||||
"minUnlimited": true,
|
||||
"max": 100,
|
||||
"maxUnlimited": true,
|
||||
"step": 1,
|
||||
"disabled": false,
|
||||
"controlsPosition": "right",
|
||||
"unitText": "",
|
||||
"unitPosition": "suffix",
|
||||
"showPercent": false,
|
||||
"align": "left",
|
||||
"hidden": false,
|
||||
"hiddenOnAdd": false,
|
||||
"fieldNote": "",
|
||||
"autoWidth": 50
|
||||
},
|
||||
"advancedSetting": {
|
||||
"defaultValue": {
|
||||
"type": "compose",
|
||||
"value": "",
|
||||
"format": "number",
|
||||
"allowFunc": true,
|
||||
"valueSplit": "",
|
||||
"customConfig": false
|
||||
}
|
||||
},
|
||||
"remoteAPI": {
|
||||
"url": "",
|
||||
"executed": false
|
||||
},
|
||||
"key": "1717072985868_606195",
|
||||
"model": "number_1717072985868_606195",
|
||||
"modelType": "main",
|
||||
"rules": [],
|
||||
"isSubItem": false
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"required": false,
|
||||
"hiddenOnAdd": false,
|
||||
"hidden": false,
|
||||
"fieldNote": ""
|
||||
},
|
||||
"model": "card_1717072932495_439966",
|
||||
"hideTitle": false,
|
||||
"modelType": "main"
|
||||
},
|
||||
{
|
||||
"key": "1717072988159_545097",
|
||||
"type": "card",
|
||||
"isAutoGrid": true,
|
||||
"isContainer": true,
|
||||
"list": [
|
||||
{
|
||||
"type": "money",
|
||||
"name": "金额",
|
||||
"className": "form-money",
|
||||
"icon": "icon-money",
|
||||
"hideTitle": false,
|
||||
"options": {
|
||||
"width": "180px",
|
||||
"placeholder": "请输入金额",
|
||||
"required": false,
|
||||
"unitText": "元",
|
||||
"unitPosition": "suffix",
|
||||
"precision": 2,
|
||||
"hidden": false,
|
||||
"disabled": false,
|
||||
"hiddenOnAdd": false,
|
||||
"fieldNote": "",
|
||||
"autoWidth": 50
|
||||
},
|
||||
"advancedSetting": {
|
||||
"defaultValue": {
|
||||
"type": "compose",
|
||||
"value": "",
|
||||
"format": "number",
|
||||
"allowFunc": true,
|
||||
"valueSplit": "",
|
||||
"customConfig": false
|
||||
}
|
||||
},
|
||||
"remoteAPI": {
|
||||
"url": "",
|
||||
"executed": false
|
||||
},
|
||||
"key": "1717072988159_568693",
|
||||
"model": "money_1717072988159_568693",
|
||||
"modelType": "main",
|
||||
"rules": [],
|
||||
"isSubItem": false
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"name": "下拉选择框",
|
||||
"className": "form-select",
|
||||
"icon": "icon-select",
|
||||
"hideTitle": false,
|
||||
"options": {
|
||||
"defaultValue": "",
|
||||
"multiple": false,
|
||||
"disabled": false,
|
||||
"clearable": true,
|
||||
"placeholder": "",
|
||||
"required": false,
|
||||
"showLabel": false,
|
||||
"showType": "default",
|
||||
"width": "",
|
||||
"useColor": false,
|
||||
"colorIteratorIndex": 3,
|
||||
"options": [
|
||||
{
|
||||
"value": "下拉框1",
|
||||
"itemColor": "#2196F3"
|
||||
},
|
||||
{
|
||||
"value": "下拉框2",
|
||||
"itemColor": "#08C9C9"
|
||||
},
|
||||
{
|
||||
"value": "下拉框3",
|
||||
"itemColor": "#00C345"
|
||||
}
|
||||
],
|
||||
"remote": false,
|
||||
"filterable": false,
|
||||
"remoteOptions": [],
|
||||
"props": {
|
||||
"value": "value",
|
||||
"label": "label"
|
||||
},
|
||||
"remoteFunc": "",
|
||||
"hidden": false,
|
||||
"hiddenOnAdd": false,
|
||||
"fieldNote": "",
|
||||
"autoWidth": 50
|
||||
},
|
||||
"advancedSetting": {
|
||||
"defaultValue": {
|
||||
"type": "compose",
|
||||
"value": "",
|
||||
"format": "string",
|
||||
"allowFunc": true,
|
||||
"valueSplit": ",",
|
||||
"customConfig": true
|
||||
}
|
||||
},
|
||||
"remoteAPI": {
|
||||
"url": "",
|
||||
"executed": false
|
||||
},
|
||||
"key": "1717072991431_622198",
|
||||
"model": "select_1717072991431_622198",
|
||||
"modelType": "main",
|
||||
"rules": [],
|
||||
"isSubItem": false
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"required": false,
|
||||
"hiddenOnAdd": false,
|
||||
"hidden": false,
|
||||
"fieldNote": ""
|
||||
},
|
||||
"model": "card_1717072988159_545097",
|
||||
"hideTitle": false,
|
||||
"modelType": "main"
|
||||
},
|
||||
{
|
||||
"key": "1717072932495_382575",
|
||||
"type": "card",
|
||||
"isAutoGrid": true,
|
||||
"isContainer": true,
|
||||
"list": [
|
||||
{
|
||||
"type": "imgupload",
|
||||
"name": "图片上传",
|
||||
"className": "form-tupian",
|
||||
"icon": "icon-tupian",
|
||||
"hideTitle": false,
|
||||
"options": {
|
||||
"defaultValue": [],
|
||||
"size": {
|
||||
"width": 100,
|
||||
"height": 100
|
||||
},
|
||||
"width": "",
|
||||
"tokenFunc": "funcGetToken",
|
||||
"token": "",
|
||||
"domain": "http://img.h5huodong.com",
|
||||
"disabled": false,
|
||||
"length": 9,
|
||||
"multiple": true,
|
||||
"hidden": false,
|
||||
"hiddenOnAdd": false,
|
||||
"required": false,
|
||||
"fieldNote": "",
|
||||
"autoWidth": 50
|
||||
},
|
||||
"key": "1717072996509_795340",
|
||||
"model": "imgupload_1717072996509_795340",
|
||||
"modelType": "main",
|
||||
"rules": [],
|
||||
"isSubItem": false
|
||||
},
|
||||
{
|
||||
"type": "file-upload",
|
||||
"name": "附件",
|
||||
"className": "form-file-upload",
|
||||
"icon": "icon-shangchuan",
|
||||
"hideTitle": false,
|
||||
"options": {
|
||||
"defaultValue": [],
|
||||
"token": "",
|
||||
"length": 1,
|
||||
"drag": false,
|
||||
"multiple": false,
|
||||
"disabled": false,
|
||||
"buttonText": "添加附件",
|
||||
"tokenFunc": "funcGetToken",
|
||||
"hidden": false,
|
||||
"hiddenOnAdd": false,
|
||||
"required": false,
|
||||
"fieldNote": "",
|
||||
"autoWidth": 50
|
||||
},
|
||||
"key": "1717072932495_669325",
|
||||
"model": "file_upload_1717072932495_669325",
|
||||
"modelType": "main",
|
||||
"rules": [],
|
||||
"isSubItem": false
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"required": false,
|
||||
"hiddenOnAdd": false,
|
||||
"hidden": false,
|
||||
"fieldNote": ""
|
||||
},
|
||||
"model": "card_1717072932495_382575",
|
||||
"hideTitle": false,
|
||||
"modelType": "main"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"titleField": "input_1717072932495_556479",
|
||||
"showHeaderTitle": true,
|
||||
"labelWidth": 100,
|
||||
"labelPosition": "top",
|
||||
"size": "small",
|
||||
"dialogOptions": {
|
||||
"top": 20,
|
||||
"width": 1000,
|
||||
"padding": {
|
||||
"top": 25,
|
||||
"right": 25,
|
||||
"bottom": 30,
|
||||
"left": 25
|
||||
}
|
||||
},
|
||||
"disabledAutoGrid": false,
|
||||
"designMobileView": false,
|
||||
"enableComment": true,
|
||||
"hasWidgets": [
|
||||
"input",
|
||||
"number",
|
||||
"card",
|
||||
"money",
|
||||
"select",
|
||||
"imgupload",
|
||||
"file-upload"
|
||||
],
|
||||
"expand": {
|
||||
"js": "",
|
||||
"css": "",
|
||||
"url": {
|
||||
"js": "",
|
||||
"css": ""
|
||||
}
|
||||
},
|
||||
"transactional": true,
|
||||
"customRequestURL": [
|
||||
{
|
||||
"url": ""
|
||||
}
|
||||
],
|
||||
"allowExternalLink": false,
|
||||
"externalLinkShowData": false,
|
||||
"headerImgUrl": "",
|
||||
"externalTitle": "",
|
||||
"enableNotice": false,
|
||||
"noticeMode": "external",
|
||||
"noticeType": "system",
|
||||
"noticeReceiver": "",
|
||||
"allowPrint": false,
|
||||
"allowJmReport": false,
|
||||
"jmReportURL": "",
|
||||
"bizRuleConfig": [],
|
||||
"bigDataMode": false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,496 @@
|
|||
{
|
||||
"list": [
|
||||
{
|
||||
"hideTitle": false,
|
||||
"options": {
|
||||
"hidden": false,
|
||||
"hiddenOnAdd": false,
|
||||
"fieldNote": "",
|
||||
"required": false
|
||||
},
|
||||
"isContainer": true,
|
||||
"model": "card_1717072902303_783177",
|
||||
"modelType": "main",
|
||||
"type": "card",
|
||||
"isAutoGrid": true,
|
||||
"list": [
|
||||
{
|
||||
"isSubItem": false,
|
||||
"remoteAPI": {
|
||||
"executed": false,
|
||||
"url": ""
|
||||
},
|
||||
"icon": "icon-input",
|
||||
"className": "form-input",
|
||||
"rules": [
|
||||
{
|
||||
"required": true,
|
||||
"message": "${title}必须填写"
|
||||
}
|
||||
],
|
||||
"modelType": "main",
|
||||
"type": "input",
|
||||
"hideTitle": false,
|
||||
"name": "名称",
|
||||
"options": {
|
||||
"clearable": false,
|
||||
"hidden": false,
|
||||
"defaultValue": "",
|
||||
"pattern": "",
|
||||
"fillRuleCode": "",
|
||||
"fieldNote": "",
|
||||
"required": true,
|
||||
"readonly": false,
|
||||
"unique": false,
|
||||
"hiddenOnAdd": false,
|
||||
"width": "100%",
|
||||
"autoWidth": 100,
|
||||
"showPassword": false,
|
||||
"disabled": false,
|
||||
"placeholder": ""
|
||||
},
|
||||
"model": "input_1717072902303_477529",
|
||||
"advancedSetting": {
|
||||
"defaultValue": {
|
||||
"type": "compose",
|
||||
"value": "",
|
||||
"format": "string",
|
||||
"allowFunc": true,
|
||||
"valueSplit": "",
|
||||
"customConfig": false
|
||||
}
|
||||
},
|
||||
"key": "1717072902303_477529"
|
||||
}
|
||||
],
|
||||
"key": "1717072902303_783177"
|
||||
},
|
||||
{
|
||||
"options": {
|
||||
"required": false,
|
||||
"hiddenOnAdd": false,
|
||||
"hidden": false,
|
||||
"fieldNote": ""
|
||||
},
|
||||
"isContainer": true,
|
||||
"model": "card_1717073019436_526262",
|
||||
"type": "card",
|
||||
"isAutoGrid": true,
|
||||
"list": [
|
||||
{
|
||||
"isSubItem": false,
|
||||
"remoteAPI": {
|
||||
"executed": false,
|
||||
"url": ""
|
||||
},
|
||||
"icon": "icon-number",
|
||||
"className": "form-number",
|
||||
"rules": [],
|
||||
"modelType": "main",
|
||||
"type": "number",
|
||||
"hideTitle": false,
|
||||
"name": "数字",
|
||||
"options": {
|
||||
"controls": false,
|
||||
"showPercent": false,
|
||||
"hidden": false,
|
||||
"max": 100,
|
||||
"defaultValue": 0,
|
||||
"unitPosition": "suffix",
|
||||
"fieldNote": "",
|
||||
"maxUnlimited": true,
|
||||
"align": "left",
|
||||
"required": false,
|
||||
"min": 0,
|
||||
"minUnlimited": true,
|
||||
"hiddenOnAdd": false,
|
||||
"width": "",
|
||||
"autoWidth": 50,
|
||||
"step": 1,
|
||||
"disabled": false,
|
||||
"placeholder": "",
|
||||
"controlsPosition": "right",
|
||||
"unitText": ""
|
||||
},
|
||||
"model": "number_1717073019436_586474",
|
||||
"advancedSetting": {
|
||||
"defaultValue": {
|
||||
"type": "compose",
|
||||
"value": "",
|
||||
"format": "number",
|
||||
"allowFunc": true,
|
||||
"valueSplit": "",
|
||||
"customConfig": false
|
||||
}
|
||||
},
|
||||
"key": "1717073019436_586474"
|
||||
},
|
||||
{
|
||||
"isSubItem": false,
|
||||
"remoteAPI": {
|
||||
"executed": false,
|
||||
"url": ""
|
||||
},
|
||||
"icon": "icon-money",
|
||||
"className": "form-money",
|
||||
"rules": [],
|
||||
"modelType": "main",
|
||||
"type": "money",
|
||||
"hideTitle": false,
|
||||
"name": "金额",
|
||||
"options": {
|
||||
"hidden": false,
|
||||
"precision": 2,
|
||||
"hiddenOnAdd": false,
|
||||
"width": "180px",
|
||||
"autoWidth": 50,
|
||||
"unitPosition": "suffix",
|
||||
"disabled": false,
|
||||
"fieldNote": "",
|
||||
"placeholder": "请输入金额",
|
||||
"required": false,
|
||||
"unitText": "元"
|
||||
},
|
||||
"model": "money_1717073021100_526660",
|
||||
"advancedSetting": {
|
||||
"defaultValue": {
|
||||
"type": "compose",
|
||||
"value": "",
|
||||
"format": "number",
|
||||
"allowFunc": true,
|
||||
"valueSplit": "",
|
||||
"customConfig": false
|
||||
}
|
||||
},
|
||||
"key": "1717073021100_526660"
|
||||
}
|
||||
],
|
||||
"key": "1717073019436_526262",
|
||||
"hideTitle": false,
|
||||
"modelType": "main"
|
||||
},
|
||||
{
|
||||
"hideTitle": false,
|
||||
"options": {
|
||||
"hidden": false,
|
||||
"hiddenOnAdd": false,
|
||||
"fieldNote": "",
|
||||
"required": false
|
||||
},
|
||||
"isContainer": true,
|
||||
"model": "card_1717072902303_118977",
|
||||
"modelType": "main",
|
||||
"type": "card",
|
||||
"isAutoGrid": true,
|
||||
"list": [
|
||||
{
|
||||
"isSubItem": false,
|
||||
"remoteAPI": {
|
||||
"executed": false,
|
||||
"url": ""
|
||||
},
|
||||
"icon": "icon-select",
|
||||
"className": "form-select",
|
||||
"rules": [],
|
||||
"modelType": "main",
|
||||
"type": "select",
|
||||
"hideTitle": false,
|
||||
"name": "下拉选择框",
|
||||
"options": {
|
||||
"remoteFunc": "",
|
||||
"filterable": false,
|
||||
"clearable": true,
|
||||
"hidden": false,
|
||||
"defaultValue": "",
|
||||
"remoteOptions": [],
|
||||
"multiple": false,
|
||||
"fieldNote": "",
|
||||
"remote": false,
|
||||
"required": false,
|
||||
"showLabel": false,
|
||||
"useColor": false,
|
||||
"props": {
|
||||
"label": "label",
|
||||
"value": "value"
|
||||
},
|
||||
"colorIteratorIndex": 3,
|
||||
"hiddenOnAdd": false,
|
||||
"width": "",
|
||||
"options": [
|
||||
{
|
||||
"itemColor": "#2196F3",
|
||||
"value": "下拉框1"
|
||||
},
|
||||
{
|
||||
"itemColor": "#08C9C9",
|
||||
"value": "下拉框2"
|
||||
},
|
||||
{
|
||||
"itemColor": "#00C345",
|
||||
"value": "下拉框3"
|
||||
}
|
||||
],
|
||||
"autoWidth": 50,
|
||||
"showType": "default",
|
||||
"disabled": false,
|
||||
"placeholder": ""
|
||||
},
|
||||
"model": "select_1717073033259_273399",
|
||||
"advancedSetting": {
|
||||
"defaultValue": {
|
||||
"type": "compose",
|
||||
"value": "",
|
||||
"format": "string",
|
||||
"allowFunc": true,
|
||||
"valueSplit": ",",
|
||||
"customConfig": true
|
||||
}
|
||||
},
|
||||
"key": "1717073033259_273399"
|
||||
},
|
||||
{
|
||||
"isSubItem": false,
|
||||
"remoteAPI": {
|
||||
"executed": false,
|
||||
"url": ""
|
||||
},
|
||||
"icon": "icon-textarea",
|
||||
"className": "form-textarea",
|
||||
"rules": [],
|
||||
"modelType": "main",
|
||||
"type": "textarea",
|
||||
"hideTitle": false,
|
||||
"name": "描述",
|
||||
"options": {
|
||||
"readonly": false,
|
||||
"hidden": false,
|
||||
"defaultValue": "",
|
||||
"unique": false,
|
||||
"hiddenOnAdd": false,
|
||||
"width": "100%",
|
||||
"pattern": "",
|
||||
"autoWidth": 50,
|
||||
"disabled": false,
|
||||
"fieldNote": "",
|
||||
"placeholder": "",
|
||||
"required": false
|
||||
},
|
||||
"model": "textarea_1717072902303_129466",
|
||||
"advancedSetting": {
|
||||
"defaultValue": {
|
||||
"type": "compose",
|
||||
"value": "",
|
||||
"format": "string",
|
||||
"allowFunc": true,
|
||||
"valueSplit": "",
|
||||
"customConfig": false
|
||||
}
|
||||
},
|
||||
"key": "1717072902303_129466"
|
||||
}
|
||||
],
|
||||
"key": "1717072902303_118977"
|
||||
},
|
||||
{
|
||||
"hideTitle": false,
|
||||
"options": {
|
||||
"hidden": false,
|
||||
"hiddenOnAdd": false,
|
||||
"fieldNote": "",
|
||||
"required": false
|
||||
},
|
||||
"isContainer": true,
|
||||
"model": "card_1717072902304_736053",
|
||||
"modelType": "main",
|
||||
"type": "card",
|
||||
"isAutoGrid": true,
|
||||
"list": [
|
||||
{
|
||||
"hideTitle": false,
|
||||
"isSubItem": false,
|
||||
"name": "图片上传",
|
||||
"icon": "icon-tupian",
|
||||
"options": {
|
||||
"hidden": false,
|
||||
"defaultValue": [],
|
||||
"length": 9,
|
||||
"multiple": true,
|
||||
"fieldNote": "",
|
||||
"required": false,
|
||||
"token": "",
|
||||
"size": {
|
||||
"width": 100,
|
||||
"height": 100
|
||||
},
|
||||
"tokenFunc": "funcGetToken",
|
||||
"domain": "http://img.h5huodong.com",
|
||||
"hiddenOnAdd": false,
|
||||
"width": "",
|
||||
"autoWidth": 50,
|
||||
"disabled": false
|
||||
},
|
||||
"className": "form-tupian",
|
||||
"model": "imgupload_1717073025137_563739",
|
||||
"rules": [],
|
||||
"modelType": "main",
|
||||
"type": "imgupload",
|
||||
"key": "1717073025137_563739"
|
||||
},
|
||||
{
|
||||
"hideTitle": false,
|
||||
"isSubItem": false,
|
||||
"name": "附件",
|
||||
"icon": "icon-shangchuan",
|
||||
"options": {
|
||||
"buttonText": "添加附件",
|
||||
"hidden": false,
|
||||
"defaultValue": [],
|
||||
"length": 1,
|
||||
"multiple": false,
|
||||
"fieldNote": "",
|
||||
"required": false,
|
||||
"token": "",
|
||||
"tokenFunc": "funcGetToken",
|
||||
"hiddenOnAdd": false,
|
||||
"autoWidth": 50,
|
||||
"disabled": false,
|
||||
"drag": false
|
||||
},
|
||||
"className": "form-file-upload",
|
||||
"model": "file_upload_1717072902304_442777",
|
||||
"rules": [],
|
||||
"modelType": "main",
|
||||
"type": "file-upload",
|
||||
"key": "1717072902304_442777"
|
||||
}
|
||||
],
|
||||
"key": "1717072902304_736053"
|
||||
},
|
||||
{
|
||||
"isSubItem": false,
|
||||
"remoteAPI": {
|
||||
"url": "",
|
||||
"executed": false
|
||||
},
|
||||
"icon": "icon-link",
|
||||
"className": "form-link-record",
|
||||
"rules": [],
|
||||
"modelType": "main",
|
||||
"type": "link-record",
|
||||
"hideTitle": false,
|
||||
"name": "主表@表单控件",
|
||||
"options": {
|
||||
"sourceCode": "ai_control_main",
|
||||
"showMode": "single",
|
||||
"showType": "card",
|
||||
"titleField": "wen_ben",
|
||||
"showFields": [],
|
||||
"allowView": true,
|
||||
"allowEdit": true,
|
||||
"allowAdd": true,
|
||||
"allowSelect": true,
|
||||
"buttonText": "添加记录",
|
||||
"twoWayModel": "sub_table_design_1717137038626_791984",
|
||||
"dataSelectAuth": "all",
|
||||
"filters": [
|
||||
{
|
||||
"matchType": "AND",
|
||||
"rules": []
|
||||
}
|
||||
],
|
||||
"search": {
|
||||
"enabled": false,
|
||||
"field": "",
|
||||
"rule": "like",
|
||||
"afterShow": false,
|
||||
"fields": []
|
||||
},
|
||||
"createMode": {
|
||||
"add": true,
|
||||
"select": false,
|
||||
"params": {
|
||||
"selectLinkModel": ""
|
||||
}
|
||||
},
|
||||
"width": "100%",
|
||||
"defaultValue": "",
|
||||
"defaultValType": "none",
|
||||
"required": false,
|
||||
"disabled": false,
|
||||
"hidden": false,
|
||||
"hiddenOnAdd": false,
|
||||
"fieldNote": ""
|
||||
},
|
||||
"model": "link_record_1717137044235_306956",
|
||||
"advancedSetting": {
|
||||
"defaultValue": {
|
||||
"type": "compose",
|
||||
"value": "",
|
||||
"format": "string",
|
||||
"allowFunc": true,
|
||||
"valueSplit": "",
|
||||
"customConfig": true
|
||||
}
|
||||
},
|
||||
"key": "1717137044235_306956"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"jmReportURL": "",
|
||||
"enableComment": true,
|
||||
"dialogOptions": {
|
||||
"padding": {
|
||||
"top": 25,
|
||||
"left": 25,
|
||||
"bottom": 30,
|
||||
"right": 25
|
||||
},
|
||||
"top": 20,
|
||||
"width": 1000
|
||||
},
|
||||
"allowJmReport": false,
|
||||
"labelWidth": 100,
|
||||
"headerImgUrl": "",
|
||||
"noticeMode": "external",
|
||||
"noticeReceiver": "",
|
||||
"designMobileView": false,
|
||||
"labelPosition": "top",
|
||||
"allowPrint": false,
|
||||
"enableNotice": false,
|
||||
"bizRuleConfig": [],
|
||||
"showHeaderTitle": true,
|
||||
"bigDataMode": false,
|
||||
"titleField": "input_1717072902303_477529",
|
||||
"externalTitle": "",
|
||||
"noticeType": "system",
|
||||
"customRequestURL": [
|
||||
{
|
||||
"url": ""
|
||||
}
|
||||
],
|
||||
"hasWidgets": [
|
||||
"input",
|
||||
"card",
|
||||
"number",
|
||||
"money",
|
||||
"select",
|
||||
"textarea",
|
||||
"imgupload",
|
||||
"file-upload",
|
||||
"link-record"
|
||||
],
|
||||
"expand": {
|
||||
"css": "",
|
||||
"js": "",
|
||||
"url": {
|
||||
"css": "",
|
||||
"js": ""
|
||||
}
|
||||
},
|
||||
"size": "small",
|
||||
"disabledAutoGrid": false,
|
||||
"allowExternalLink": false,
|
||||
"externalLinkShowData": false,
|
||||
"transactional": true
|
||||
}
|
||||
}
|
|
@ -5,12 +5,15 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.jeecg.common.api.dto.message.MessageDTO;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.enums.MessageTypeEnum;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.StaticConfig;
|
||||
import org.jeecg.modules.message.entity.SysMessage;
|
||||
import org.jeecg.modules.message.handle.ISendMsgHandle;
|
||||
import org.jeecg.modules.message.mapper.SysMessageMapper;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.mapper.SysUserMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -43,6 +46,9 @@ public class EmailSendMsgHandle implements ISendMsgHandle {
|
|||
|
||||
@Autowired
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Autowired
|
||||
private SysMessageMapper sysMessageMapper;
|
||||
|
||||
/**
|
||||
* 真实姓名变量
|
||||
|
@ -78,6 +84,23 @@ public class EmailSendMsgHandle implements ISendMsgHandle {
|
|||
|
||||
@Override
|
||||
public void sendMessage(MessageDTO messageDTO) {
|
||||
String content = messageDTO.getContent();
|
||||
String title = messageDTO.getTitle();
|
||||
//update-begin---author:wangshuai---date:2024-11-20---for:【QQYUN-8523】敲敲云发邮件通知,不稳定---
|
||||
boolean timeJobSendEmail = this.isTimeJobSendEmail(messageDTO.getToUser(), title, content);
|
||||
if(timeJobSendEmail){
|
||||
return;
|
||||
}
|
||||
//update-end---author:wangshuai---date:2024-11-20---for:【QQYUN-8523】敲敲云发邮件通知,不稳定---
|
||||
this.sendEmailMessage(messageDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接发送邮件
|
||||
*
|
||||
* @param messageDTO
|
||||
*/
|
||||
public void sendEmailMessage(MessageDTO messageDTO) {
|
||||
String[] arr = messageDTO.getToUser().split(",");
|
||||
LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<SysUser>().in(SysUser::getUsername, arr);
|
||||
List<SysUser> list = sysUserMapper.selectList(query);
|
||||
|
@ -213,4 +236,35 @@ public class EmailSendMsgHandle implements ISendMsgHandle {
|
|||
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 1 / 1000);
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否定时发送邮箱
|
||||
* @param toUser
|
||||
* @param title
|
||||
* @param content
|
||||
* @return
|
||||
*/
|
||||
private boolean isTimeJobSendEmail(String toUser, String title, String content) {
|
||||
StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
|
||||
Boolean timeJobSend = staticConfig.getTimeJobSend();
|
||||
if(null != timeJobSend && timeJobSend){
|
||||
this.addSysSmsSend(toUser,title,content);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存到短信发送表
|
||||
*/
|
||||
private void addSysSmsSend(String toUser, String title, String content) {
|
||||
SysMessage sysMessage = new SysMessage();
|
||||
sysMessage.setEsTitle(title);
|
||||
sysMessage.setEsContent(content);
|
||||
sysMessage.setEsReceiver(toUser);
|
||||
sysMessage.setEsSendStatus("0");
|
||||
sysMessage.setEsSendNum(0);
|
||||
sysMessage.setEsType(MessageTypeEnum.YJ.getType());
|
||||
sysMessageMapper.insert(sysMessage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,9 @@ public class SendMsgJob implements Job {
|
|||
md.setToUser(sysMessage.getEsReceiver());
|
||||
md.setType(sysMessage.getEsType());
|
||||
md.setToAll(false);
|
||||
//update-begin---author:wangshuai---date:2024-11-12---for:【QQYUN-8523】敲敲云发邮件通知,不稳定---
|
||||
md.setIsTimeJob(true);
|
||||
//update-end---author:wangshuai---date:2024-11-12---for:【QQYUN-8523】敲敲云发邮件通知,不稳定---
|
||||
sysBaseAPI.sendTemplateMessage(md);
|
||||
//发送消息成功
|
||||
sysMessage.setEsSendStatus(SendMsgStatusEnum.SUCCESS.getCode());
|
||||
|
|
|
@ -18,7 +18,7 @@ import static org.springframework.boot.actuate.endpoint.annotation.Selector.Matc
|
|||
* @Date: 2024/5/13 17:02
|
||||
*/
|
||||
@Component
|
||||
@Endpoint(id = "httptrace-new")
|
||||
@Endpoint(id = "jeecghttptrace")
|
||||
public class CustomHttpTraceEndpoint{
|
||||
private final CustomInMemoryHttpTraceRepository repository;
|
||||
|
||||
|
|
|
@ -1276,12 +1276,6 @@ public class SysUserController {
|
|||
updateUser.setUpdateBy(JwtUtil.getUserNameByToken(request));
|
||||
updateUser.setUpdateTime(new Date());
|
||||
sysUserService.revertLogicDeleted(Arrays.asList(userIds.split(",")), updateUser);
|
||||
// 用户变更,触发同步工作流
|
||||
List<String> userNameList = sysUserService.userIdToUsername(Arrays.asList(userIds.split(",")));
|
||||
if (!userNameList.isEmpty()) {
|
||||
String joinedString = String.join(",", userNameList);
|
||||
}
|
||||
|
||||
}
|
||||
return Result.ok("还原成功");
|
||||
}
|
||||
|
|
|
@ -557,4 +557,64 @@ public class ThirdLoginController {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新版钉钉登录
|
||||
*
|
||||
* @param authCode
|
||||
* @param state
|
||||
* @param tenantId
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping("/oauth2/dingding/login")
|
||||
public String OauthDingDingLogin(@RequestParam(value = "authCode", required = false) String authCode,
|
||||
@RequestParam("state") String state,
|
||||
@RequestParam(name = "tenantId",defaultValue = "0") String tenantId,
|
||||
HttpServletResponse response) {
|
||||
SysUser loginUser = thirdAppDingtalkService.oauthDingDingLogin(authCode,Integer.valueOf(tenantId));
|
||||
try {
|
||||
String redirect = "";
|
||||
if (state.indexOf("?") > 0) {
|
||||
String[] arr = state.split("\\?");
|
||||
state = arr[0];
|
||||
if(arr.length>1){
|
||||
redirect = arr[1];
|
||||
}
|
||||
}
|
||||
String token = saveToken(loginUser);
|
||||
state += "/oauth2-app/login?oauth2LoginToken=" + URLEncoder.encode(token, "UTF-8") + "&tenantId=" + URLEncoder.encode(tenantId, "UTF-8");
|
||||
state += "&thirdType=DINGTALK";
|
||||
if (redirect != null && redirect.length() > 0) {
|
||||
state += "&" + redirect;
|
||||
}
|
||||
log.info("OAuth2登录重定向地址: " + state);
|
||||
try {
|
||||
response.sendRedirect(state);
|
||||
return "ok";
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(),e);
|
||||
return "重定向失败";
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.error(e.getMessage(),e);
|
||||
return "解码失败";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取企业id和应用id
|
||||
* @param tenantId
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping("/get/corpId/clientId")
|
||||
public Result<SysThirdAppConfig> getCorpIdClientId(@RequestParam(value = "tenantId", defaultValue = "0") String tenantId){
|
||||
Result<SysThirdAppConfig> result = new Result<>();
|
||||
SysThirdAppConfig sysThirdAppConfig = thirdAppDingtalkService.getCorpIdClientId(Integer.valueOf(tenantId));
|
||||
result.setSuccess(true);
|
||||
result.setResult(sysThirdAppConfig);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -51,10 +51,10 @@ public class SysThirdAppConfig {
|
|||
@ApiModelProperty(value = "钉钉/企业微信应用id对应的秘钥")
|
||||
private String clientSecret;
|
||||
|
||||
/**企业微信自建应用Secret*/
|
||||
@Excel(name = "企业微信自建应用Secret", width = 15)
|
||||
@ApiModelProperty(value = "企业微信自建应用Secret")
|
||||
private String agentAppSecret;
|
||||
/**钉钉企业id*/
|
||||
@Excel(name = "钉钉企业id", width = 15)
|
||||
@ApiModelProperty(value = "钉钉企业id")
|
||||
private String corpId;
|
||||
|
||||
/**第三方类别(dingtalk 钉钉 wechat_enterprise 企业微信)*/
|
||||
@Excel(name = "第三方类别(dingtalk 钉钉 wechat_enterprise 企业微信)", width = 15)
|
||||
|
|
|
@ -443,4 +443,19 @@ public interface ISysUserService extends IService<SysUser> {
|
|||
* @param ipAddress ip地址
|
||||
*/
|
||||
void sendChangePhoneSms(JSONObject jsonObject, String username, String ipAddress);
|
||||
|
||||
/**
|
||||
* 发送注销用户手机号验证密码[敲敲云专用]
|
||||
* @param jsonObject
|
||||
* @param username
|
||||
* @param ipAddress
|
||||
*/
|
||||
void sendLogOffPhoneSms(JSONObject jsonObject, String username, String ipAddress);
|
||||
|
||||
/**
|
||||
* 用户注销[敲敲云专用]
|
||||
* @param jsonObject
|
||||
* @param username
|
||||
*/
|
||||
void userLogOff(JSONObject jsonObject, String username);
|
||||
}
|
||||
|
|
|
@ -1597,7 +1597,13 @@ public class SysBaseApiImpl implements ISysBaseAPI {
|
|||
// 邮件消息要解析Markdown
|
||||
message.setContent(HTMLUtils.parseMarkdown(message.getContent()));
|
||||
}
|
||||
emailSendMsgHandle.sendMessage(message);
|
||||
//update-begin---author:wangshuai---date:2024-11-20---for:【QQYUN-8523】敲敲云发邮件通知,不稳定---
|
||||
if(message.getIsTimeJob() != null && message.getIsTimeJob()){
|
||||
emailSendMsgHandle.sendEmailMessage(message);
|
||||
}else{
|
||||
emailSendMsgHandle.sendMessage(message);
|
||||
}
|
||||
//update-end---author:wangshuai---date:2024-11-20---for:【QQYUN-8523】敲敲云发邮件通知,不稳定---
|
||||
}else if(MessageTypeEnum.DD.getType().equals(messageType)){
|
||||
ddSendMsgHandle.sendMessage(message);
|
||||
}else if(MessageTypeEnum.QYWX.getType().equals(messageType)){
|
||||
|
|
|
@ -1978,15 +1978,50 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||
}
|
||||
}
|
||||
//step4 发送短信验证码
|
||||
this.sendPhoneSms(phone, ipAddress);
|
||||
String redisKey = CommonConstant.CHANGE_PHONE_REDIS_KEY_PRE+phone;
|
||||
this.sendPhoneSms(phone, ipAddress,redisKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendLogOffPhoneSms(JSONObject jsonObject, String username, String ipAddress) {
|
||||
String phone = jsonObject.getString("phone");
|
||||
//通过用户名查询数据库中的手机号
|
||||
SysUser userByNameAndPhone = userMapper.getUserByNameAndPhone(phone, username);
|
||||
if (null == userByNameAndPhone) {
|
||||
throw new JeecgBootException("当前用户手机号不匹配,无法修改!");
|
||||
}
|
||||
String code = CommonConstant.LOG_OFF_PHONE_REDIS_KEY_PRE + phone;
|
||||
this.sendPhoneSms(phone, ipAddress, code);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void userLogOff(JSONObject jsonObject, String username) {
|
||||
String phone = jsonObject.getString("phone");
|
||||
String smsCode = jsonObject.getString("smscode");
|
||||
//通过用户名查询数据库中的手机号
|
||||
SysUser userByNameAndPhone = userMapper.getUserByNameAndPhone(phone, username);
|
||||
if (null == userByNameAndPhone) {
|
||||
throw new JeecgBootException("当前用户手机号不匹配,无法注销!");
|
||||
}
|
||||
String code = CommonConstant.LOG_OFF_PHONE_REDIS_KEY_PRE + phone;
|
||||
Object redisSmdCode = redisUtil.get(code);
|
||||
if (null == redisSmdCode) {
|
||||
throw new JeecgBootException("验证码失效,无法注销!");
|
||||
}
|
||||
if (!redisSmdCode.toString().equals(smsCode)) {
|
||||
throw new JeecgBootException("验证码不匹配,无法注销!");
|
||||
}
|
||||
this.deleteUser(userByNameAndPhone.getId());
|
||||
redisUtil.removeAll(code);
|
||||
redisUtil.removeAll(CacheConstant.SYS_USERS_CACHE + phone);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送短信验证码
|
||||
* @param phone
|
||||
*/
|
||||
private void sendPhoneSms(String phone, String clientIp) {
|
||||
String redisKey = CommonConstant.CHANGE_PHONE_REDIS_KEY_PRE+phone;
|
||||
private void sendPhoneSms(String phone, String clientIp,String redisKey) {
|
||||
Object object = redisUtil.get(redisKey);
|
||||
|
||||
if (object != null) {
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.jeecg.dingtalk.api.base.JdtBaseAPI;
|
||||
import com.jeecg.dingtalk.api.core.response.Response;
|
||||
import com.jeecg.dingtalk.api.core.util.HttpUtil;
|
||||
import com.jeecg.dingtalk.api.core.vo.AccessToken;
|
||||
import com.jeecg.dingtalk.api.core.vo.PageResult;
|
||||
import com.jeecg.dingtalk.api.department.JdtDepartmentAPI;
|
||||
|
@ -46,10 +47,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
|
@ -1254,4 +1252,57 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=================================== begin 新版钉钉登录 ============================================
|
||||
/**
|
||||
* 钉钉登录获取用户信息
|
||||
* 【QQYUN-9421】钉钉登录后打开了敲敲云,换其他账号登录后,再打开敲敲云显示的是原来账号的应用
|
||||
* @param authCode
|
||||
* @param tenantId
|
||||
* @return
|
||||
*/
|
||||
public SysUser oauthDingDingLogin(String authCode, Integer tenantId) {
|
||||
Long count = tenantMapper.tenantIzExist(tenantId);
|
||||
if(ObjectUtil.isEmpty(count) || 0 == count){
|
||||
throw new JeecgBootException("租户不存在!");
|
||||
}
|
||||
SysThirdAppConfig config = configMapper.getThirdConfigByThirdType(tenantId, MessageTypeEnum.DD.getType());
|
||||
String accessToken = this.getTenantAccessToken(config);
|
||||
if(StringUtils.isEmpty(accessToken)){
|
||||
throw new JeecgBootBizTipException("accessToken获取失败");
|
||||
}
|
||||
String getUserInfoUrl = "https://oapi.dingtalk.com/topapi/v2/user/getuserinfo?access_token=" + accessToken;
|
||||
Map<String,String> params = new HashMap<>();
|
||||
params.put("code",authCode);
|
||||
Response<JSONObject> userInfoResponse = HttpUtil.post(getUserInfoUrl, JSON.toJSONString(params));
|
||||
if (userInfoResponse.isSuccess()) {
|
||||
String userId = userInfoResponse.getResult().getString("userid");
|
||||
// 判断第三方用户表有没有这个人
|
||||
LambdaQueryWrapper<SysThirdAccount> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysThirdAccount::getThirdType, THIRD_TYPE);
|
||||
queryWrapper.eq(SysThirdAccount::getTenantId, tenantId);
|
||||
queryWrapper.and((wrapper)->wrapper.eq(SysThirdAccount::getThirdUserUuid,userId).or().eq(SysThirdAccount::getThirdUserId,userId));
|
||||
SysThirdAccount thirdAccount = sysThirdAccountService.getOne(queryWrapper);
|
||||
if (thirdAccount != null) {
|
||||
return this.getSysUserByThird(thirdAccount, null, userId, accessToken, tenantId);
|
||||
}else{
|
||||
throw new JeecgBootException("该用户没有同步,请先同步!");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据租户id获取企业id和应用id
|
||||
* 【QQYUN-9421】钉钉登录后打开了敲敲云,换其他账号登录后,再打开敲敲云显示的是原来账号的应用
|
||||
* @param tenantId
|
||||
*/
|
||||
public SysThirdAppConfig getCorpIdClientId(Integer tenantId) {
|
||||
LambdaQueryWrapper<SysThirdAppConfig> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysThirdAppConfig::getThirdType, THIRD_TYPE);
|
||||
queryWrapper.eq(SysThirdAppConfig::getTenantId, tenantId);
|
||||
queryWrapper.select(SysThirdAppConfig::getCorpId,SysThirdAppConfig::getClientId);
|
||||
return configMapper.selectOne(queryWrapper);
|
||||
}
|
||||
//=================================== end 新版钉钉登录 ============================================
|
||||
}
|
|
@ -119,12 +119,9 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
|
|||
public String getAppAccessToken(SysThirdAppConfig config) {
|
||||
//update-begin---author:wangshuai ---date:20230224 for:[QQYUN-3440]新建企业微信和钉钉配置表,通过租户模式隔离------------
|
||||
String corpId = config.getClientId();
|
||||
String secret = config.getAgentAppSecret();
|
||||
// 如果没有配置APP秘钥,就说明是老企业,可以通用秘钥
|
||||
if (oConvertUtils.isEmpty(secret)) {
|
||||
secret = config.getClientSecret();
|
||||
String secret = config.getClientSecret();
|
||||
//update-end---author:wangshuai ---date:20230224 for:[QQYUN-3440]新建企业微信和钉钉配置表,通过租户模式隔离------------
|
||||
}
|
||||
|
||||
AccessToken accessToken = JwAccessTokenAPI.getAccessToken(corpId, secret);
|
||||
if (accessToken != null) {
|
||||
|
|
|
@ -147,6 +147,7 @@
|
|||
fixed:'right'
|
||||
},
|
||||
beforeFetch: (params) => {
|
||||
params.hasQuery = "true";
|
||||
return Object.assign(params, queryParam);
|
||||
},
|
||||
},
|
||||
|
|
|
@ -202,6 +202,7 @@
|
|||
fixed: 'right',
|
||||
},
|
||||
beforeFetch: async (params) => {
|
||||
params.hasQuery = "true";
|
||||
<#if is_range>
|
||||
let rangerQuery = await setRangeQuery();
|
||||
return Object.assign(params, rangerQuery);
|
||||
|
|
|
@ -931,6 +931,11 @@ export const ${sub.entityName?uncap_first}JVxeColumns: JVxeColumn[] = [
|
|||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
<#elseif col.classType=='pca'>
|
||||
type: JVxeTypes.pca,
|
||||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
<#elseif col.classType =='popup'>
|
||||
<#if popupBackFields?length gt 0>
|
||||
<#assign popupBackFields = "${popupBackFields}"+","+"${col.dictText}">
|
||||
|
|
|
@ -858,6 +858,11 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [
|
|||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
<#elseif col.classType=='pca'>
|
||||
type: JVxeTypes.pca,
|
||||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
<#elseif col.classType =='popup'>
|
||||
<#if popupBackFields?length gt 0>
|
||||
<#assign popupBackFields = "${popupBackFields}"+","+"${col.dictText}">
|
||||
|
|
|
@ -187,6 +187,11 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [
|
|||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
<#elseif col.classType=='pca'>
|
||||
type: JVxeTypes.pca,
|
||||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
<#elseif col.classType =='popup'>
|
||||
<#if popupBackFields?length gt 0>
|
||||
<#assign popupBackFields = "${popupBackFields}"+","+"${col.dictText}">
|
||||
|
|
|
@ -53,9 +53,13 @@
|
|||
</JFormContainer>
|
||||
|
||||
<!-- 子表单区域 -->
|
||||
<a-tabs v-model:activeKey="activeKey" animated>
|
||||
<a-tabs v-model:activeKey="activeKey" animated style="overflow:hidden;">
|
||||
<#list subTables as sub><#rt/>
|
||||
<#if sub.foreignRelationType =='1'>
|
||||
<a-tab-pane class="sub-one-form" tab="${sub.ftlDescription}" key="${sub.entityName?uncap_first}" :forceRender="true">
|
||||
<#else>
|
||||
<a-tab-pane tab="${sub.ftlDescription}" key="${sub.entityName?uncap_first}" :forceRender="true">
|
||||
</#if>
|
||||
<#if sub.foreignRelationType =='1'>
|
||||
<${Format.humpToShortbar(sub.entityName)}-form ref="${sub.entityName?uncap_first}FormRef" :disabled="disabled"></${Format.humpToShortbar(sub.entityName)}-form>
|
||||
<#else>
|
||||
|
@ -354,4 +358,9 @@
|
|||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped></style>
|
||||
<style lang="less" scoped>
|
||||
.ant-tabs-tabpane.sub-one-form {
|
||||
max-height: 340px;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -179,11 +179,6 @@
|
|||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.antd-modal-form {
|
||||
max-height: 340px;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped></style>
|
||||
</#if>
|
||||
</#list>
|
||||
|
|
|
@ -871,6 +871,11 @@ export const ${sub.entityName?uncap_first}Columns: JVxeColumn[] = [
|
|||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
<#elseif col.classType=='pca'>
|
||||
type: JVxeTypes.pca,
|
||||
<#if col.readonly=='Y'>
|
||||
disabled:true,
|
||||
</#if>
|
||||
<#elseif col.classType =='popup'>
|
||||
<#if popupBackFields?length gt 0>
|
||||
<#assign popupBackFields = "${popupBackFields}"+","+"${col.dictText}">
|
||||
|
|
|
@ -17,7 +17,7 @@ management:
|
|||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: metrics,httptrace-new
|
||||
include: metrics,jeecghttptrace
|
||||
|
||||
spring:
|
||||
# flyway配置
|
||||
|
@ -48,6 +48,8 @@ spring:
|
|||
max-file-size: 10MB
|
||||
max-request-size: 10MB
|
||||
mail:
|
||||
# 定时任务发送邮件
|
||||
timeJobSend: false
|
||||
host: smtp.163.com
|
||||
username: jeecgos@163.com
|
||||
password: ??
|
||||
|
@ -226,6 +228,18 @@ jeecg:
|
|||
secretKey: ??
|
||||
endpoint: oss-cn-beijing.aliyuncs.com
|
||||
bucketName: jeecgdev
|
||||
# 短信模板
|
||||
sms-template:
|
||||
# 签名
|
||||
signature:
|
||||
# 模板code
|
||||
templateCode:
|
||||
# 登录短信、忘记密码模板编码
|
||||
SMS_175435174:
|
||||
# 修改密码短信模板编码
|
||||
SMS_465391221:
|
||||
# 注册账号短信模板编码
|
||||
SMS_175430166:
|
||||
# ElasticSearch 6设置
|
||||
elasticsearch:
|
||||
cluster-name: jeecg-ES
|
||||
|
|
|
@ -17,7 +17,7 @@ management:
|
|||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: metrics,httptrace-new
|
||||
include: metrics,jeecghttptrace
|
||||
|
||||
spring:
|
||||
# flyway配置
|
||||
|
@ -48,6 +48,8 @@ spring:
|
|||
max-file-size: 10MB
|
||||
max-request-size: 10MB
|
||||
mail:
|
||||
# 定时任务发送邮件
|
||||
timeJobSend: false
|
||||
host: smtp.163.com
|
||||
username: jeecgos@163.com
|
||||
password: ??
|
||||
|
@ -227,6 +229,18 @@ jeecg:
|
|||
endpoint: oss-cn-beijing.aliyuncs.com
|
||||
bucketName: jeecgdev
|
||||
staticDomain: https://static.jeecg.com
|
||||
# 短信模板
|
||||
sms-template:
|
||||
# 签名
|
||||
signature:
|
||||
# 模板code
|
||||
templateCode:
|
||||
# 登录短信、忘记密码模板编码
|
||||
SMS_175435174:
|
||||
# 修改密码短信模板编码
|
||||
SMS_465391221:
|
||||
# 注册账号短信模板编码
|
||||
SMS_175430166:
|
||||
# ElasticSearch 设置
|
||||
elasticsearch:
|
||||
cluster-name: jeecg-ES
|
||||
|
|
|
@ -17,7 +17,7 @@ management:
|
|||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: metrics,httptrace-new
|
||||
include: metrics,jeecghttptrace
|
||||
|
||||
spring:
|
||||
# flyway配置
|
||||
|
@ -48,6 +48,8 @@ spring:
|
|||
max-file-size: 10MB
|
||||
max-request-size: 10MB
|
||||
mail:
|
||||
# 定时任务发送邮件
|
||||
timeJobSend: false
|
||||
host: smtp.163.com
|
||||
username: jeecgos@163.com
|
||||
password: ??
|
||||
|
@ -227,6 +229,18 @@ jeecg:
|
|||
endpoint: oss-cn-beijing.aliyuncs.com
|
||||
bucketName: jeecgdev
|
||||
staticDomain: https://static.jeecg.com
|
||||
# 短信模板
|
||||
sms-template:
|
||||
# 签名
|
||||
signature:
|
||||
# 模板code
|
||||
templateCode:
|
||||
# 登录短信、忘记密码模板编码
|
||||
SMS_175435174:
|
||||
# 修改密码短信模板编码
|
||||
SMS_465391221:
|
||||
# 注册账号短信模板编码
|
||||
SMS_175430166:
|
||||
# ElasticSearch 设置
|
||||
elasticsearch:
|
||||
cluster-name: jeecg-ES
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
-- ---author:wangshuai---date:20241108-----for: 修改字段变更为为钉钉企业id---
|
||||
ALTER TABLE sys_third_app_config
|
||||
CHANGE COLUMN agent_app_secret corp_id varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '钉钉企业id' AFTER client_secret;
|
||||
|
||||
UPDATE `sys_gateway_route` SET `predicates` = '[{\"args\":[\"/websocket/**\",\"/eoaSocket/**\",\"/newsWebsocket/**\",\"/dragChannelSocket/**\"],\"name\":\"Path\"}]' WHERE `id` = 'jeecg-cloud-websocket';
|
||||
|
||||
-- ---author:sunjianlei---date:20240930-----for: 【TV360X-2604】【Online表单】按钮权限未激活时增加提示,添加查询索引 ---
|
||||
ALTER TABLE onl_auth_page ADD INDEX idx_onl_auth_page_code(code);
|
||||
ALTER TABLE onl_auth_page ADD INDEX idx_onl_auth_page_cgform_id(cgform_id);
|
File diff suppressed because one or more lines are too long
|
@ -462,6 +462,9 @@
|
|||
<nonFilteredFileExtension>eot</nonFilteredFileExtension>
|
||||
<nonFilteredFileExtension>ttf</nonFilteredFileExtension>
|
||||
<nonFilteredFileExtension>svg</nonFilteredFileExtension>
|
||||
<nonFilteredFileExtension>glb</nonFilteredFileExtension>
|
||||
<nonFilteredFileExtension>wasm</nonFilteredFileExtension>
|
||||
<nonFilteredFileExtension>ico</nonFilteredFileExtension>
|
||||
</nonFilteredFileExtensions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
|
|
@ -19,3 +19,9 @@ VITE_GLOB_API_URL_PREFIX=
|
|||
|
||||
#微前端qiankun应用,命名必须以VITE_APP_SUB_开头,jeecg-app-1为子应用的项目名称,也是子应用的路由父路径
|
||||
VITE_APP_SUB_jeecg-app-1 = '//localhost:8092'
|
||||
|
||||
|
||||
# 填写后将作为乾坤子应用启动,主应用注册时AppName需保持一致(放开 VITE_GLOB_QIANKUN_MICRO_APP_NAME 参数表示jeecg-vue3将以乾坤子应用模式启动)
|
||||
#VITE_GLOB_QIANKUN_MICRO_APP_NAME=jeecg-vue3
|
||||
# 作为乾坤子应用启动时必填,需与qiankun主应用注册子应用时填写的 entry 保持一致
|
||||
#VITE_GLOB_QIANKUN_MICRO_APP_ENTRY=//localhost:3001/jeecg-vue3
|
||||
|
|
|
@ -20,3 +20,9 @@ VITE_GLOB_DOMAIN_URL=http://jeecg-boot-system:8080/jeecg-boot
|
|||
|
||||
# 接口父路径前缀
|
||||
VITE_GLOB_API_URL_PREFIX=
|
||||
|
||||
|
||||
# 填写后将作为乾坤子应用启动,主应用注册时AppName需保持一致(放开 VITE_GLOB_QIANKUN_MICRO_APP_NAME 参数表示jeecg-vue3将以乾坤子应用模式启动)
|
||||
#VITE_GLOB_QIANKUN_MICRO_APP_NAME=jeecg-vue3
|
||||
# 作为乾坤子应用启动时必填,需与qiankun主应用注册子应用时填写的 entry 保持一致
|
||||
#VITE_GLOB_QIANKUN_MICRO_APP_ENTRY=//qiankun.boot3.jeecg.com/jeecg-vue3
|
||||
|
|
|
@ -7,7 +7,7 @@ import { createHtmlPlugin } from 'vite-plugin-html';
|
|||
import pkg from '../../../package.json';
|
||||
import { GLOB_CONFIG_FILE_NAME } from '../../constant';
|
||||
|
||||
export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
|
||||
export function configHtmlPlugin(env: ViteEnv, isBuild: boolean, isQiankunMicro: boolean) {
|
||||
const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env;
|
||||
|
||||
const path = VITE_PUBLIC_PATH.endsWith('/') ? VITE_PUBLIC_PATH : `${VITE_PUBLIC_PATH}/`;
|
||||
|
@ -16,12 +16,17 @@ export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
|
|||
return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`;
|
||||
};
|
||||
|
||||
// 【JEECG作为乾坤子应用】补充静态资源前缀
|
||||
const {VITE_GLOB_QIANKUN_MICRO_APP_ENTRY} = env;
|
||||
const basePublicPath = isQiankunMicro ? VITE_GLOB_QIANKUN_MICRO_APP_ENTRY : '';
|
||||
|
||||
const htmlPlugin: PluginOption[] = createHtmlPlugin({
|
||||
minify: isBuild,
|
||||
inject: {
|
||||
// 修改模板html的标题
|
||||
data: {
|
||||
title: VITE_GLOB_APP_TITLE,
|
||||
basePublicPath: basePublicPath,
|
||||
},
|
||||
// 将app.config.js文件注入到模板html中
|
||||
tags: isBuild
|
||||
|
|
|
@ -15,11 +15,18 @@ import { configCompressPlugin } from './compress';
|
|||
import { configVisualizerConfig } from './visualizer';
|
||||
import { configThemePlugin } from './theme';
|
||||
import { configSvgIconsPlugin } from './svgSprite';
|
||||
import { configQiankunMicroPlugin } from './qiankunMicro';
|
||||
// //预编译加载插件(不支持vite3作废)
|
||||
// import OptimizationPersist from 'vite-plugin-optimize-persist';
|
||||
// import PkgConfig from 'vite-plugin-package-config';
|
||||
|
||||
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
|
||||
/**
|
||||
*
|
||||
* @param viteEnv
|
||||
* @param isBuild
|
||||
* @param isQiankunMicro 是否【JEECG作为乾坤子应用】
|
||||
*/
|
||||
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean, isQiankunMicro: boolean) {
|
||||
const { VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv;
|
||||
|
||||
const vitePlugins: (PluginOption | PluginOption[])[] = [
|
||||
|
@ -38,7 +45,7 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
|
|||
vitePlugins.push(UnoCSS({ presets: [presetUno(), presetTypography()] }));
|
||||
|
||||
// vite-plugin-html
|
||||
vitePlugins.push(configHtmlPlugin(viteEnv, isBuild));
|
||||
vitePlugins.push(configHtmlPlugin(viteEnv, isBuild, isQiankunMicro));
|
||||
|
||||
// vite-plugin-svg-icons
|
||||
vitePlugins.push(configSvgIconsPlugin(isBuild));
|
||||
|
@ -55,6 +62,12 @@ export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
|
|||
// vite-plugin-theme
|
||||
vitePlugins.push(configThemePlugin(isBuild));
|
||||
|
||||
// 【JEECG作为乾坤子应用】注册乾坤子应用模式插件
|
||||
if (isQiankunMicro) {
|
||||
// vite-plugin-qiankun
|
||||
vitePlugins.push(...configQiankunMicroPlugin(viteEnv))
|
||||
}
|
||||
|
||||
// The following plugins only work in the production environment
|
||||
if (isBuild) {
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import qiankun from 'vite-plugin-qiankun';
|
||||
|
||||
/**
|
||||
* 【JEECG作为乾坤子应用】Vite适配乾坤以子应用模式运行
|
||||
* @param env
|
||||
*/
|
||||
export function configQiankunMicroPlugin(env: ViteEnv) {
|
||||
const {VITE_GLOB_QIANKUN_MICRO_APP_NAME} = env
|
||||
|
||||
return [
|
||||
qiankun(VITE_GLOB_QIANKUN_MICRO_APP_NAME!, {
|
||||
useDevMode: true,
|
||||
})
|
||||
]
|
||||
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
/>
|
||||
|
||||
<title><%= title %></title>
|
||||
<link rel="icon" href="/logo.png" />
|
||||
<link rel="icon" href="<%= basePublicPath %>/logo.png" />
|
||||
<!-- 全局配置 -->
|
||||
<script>
|
||||
window._CONFIG = {};
|
||||
|
@ -157,7 +157,7 @@
|
|||
</style>
|
||||
<div class="app-loading">
|
||||
<div class="app-loading-wrap">
|
||||
<img src="/resource/img/logo.png" class="app-loading-logo" alt="Logo" />
|
||||
<img src="<%= basePublicPath %>/resource/img/logo.png" class="app-loading-logo" alt="Logo" />
|
||||
<div class="app-loading-dots">
|
||||
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
|
||||
</div>
|
||||
|
|
|
@ -153,11 +153,14 @@
|
|||
"vite-plugin-package-config": "^0.1.1",
|
||||
"vite-plugin-purge-icons": "^0.10.0",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vite-plugin-qiankun": "^1.0.15",
|
||||
"@rys-fe/vite-plugin-theme": "^0.8.6",
|
||||
"vite-plugin-vue-setup-extend-plus": "^0.1.0",
|
||||
"unocss": "^0.58.5",
|
||||
"vue-eslint-parser": "^9.4.2",
|
||||
"vue-tsc": "^1.8.27"
|
||||
"vue-tsc": "^1.8.27",
|
||||
"dingtalk-jsapi": "^3.0.25",
|
||||
"big.js": "^6.2.2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -84,11 +84,14 @@ export default function ({ advanceState, emit, getProps, getSchema, formModel, d
|
|||
advanceState.isAdvanced = true;
|
||||
} else */
|
||||
// update-end--author:sunjianlei---date:20211108---for: 注释掉该逻辑,使小于等于2行时,也显示展开收起按钮
|
||||
if (itemColSum > BASIC_COL_LEN * 2 && itemColSum <= BASIC_COL_LEN * (unref(getProps).autoAdvancedLine || 3)) {
|
||||
// update-begin--author:liaozhiyang---date:202401009---for:【issues/7261】表格上方查询项autoAdvancedLine配置没有效果(删除autoAdvancedLine)
|
||||
/*if (itemColSum > BASIC_COL_LEN * 2 && itemColSum <= BASIC_COL_LEN * (unref(getProps).autoAdvancedLine || 3)) {
|
||||
advanceState.hideAdvanceBtn = false;
|
||||
|
||||
// 默认超过 3 行折叠
|
||||
} else if (!advanceState.isLoad) {
|
||||
} else*/
|
||||
// update-end--author:liaozhiyang---date:202401009---for:【issues/7261】表格上方查询项autoAdvancedLine配置没有效果(删除autoAdvancedLine)
|
||||
if (!advanceState.isLoad) {
|
||||
advanceState.isLoad = true;
|
||||
advanceState.isAdvanced = !advanceState.isAdvanced;
|
||||
// update-begin--author:sunjianlei---date:20211108---for: 如果总列数大于 autoAdvancedCol,就默认折叠
|
||||
|
|
|
@ -79,13 +79,8 @@
|
|||
function transform(arr) {
|
||||
let result: any = [];
|
||||
if (props.saveCode === 'region') {
|
||||
// 81 香港、82 澳门
|
||||
const regionCode = arr[0];
|
||||
if (['82', '81'].includes(regionCode.substring(0, 2))) {
|
||||
result = [`${regionCode.substring(0, 2)}0000`, regionCode];
|
||||
} else {
|
||||
result = [`${regionCode.substring(0, 2)}0000`, `${regionCode.substring(0, 2)}${regionCode.substring(2, 4)}00`, regionCode];
|
||||
}
|
||||
result = [`${regionCode.substring(0, 2)}0000`, `${regionCode.substring(0, 2)}${regionCode.substring(2, 4)}00`, regionCode];
|
||||
} else if (props.saveCode === 'city') {
|
||||
const cityCode = arr[0];
|
||||
result = [`${cityCode.substring(0, 2)}0000`, cityCode];
|
||||
|
|
|
@ -26,72 +26,74 @@
|
|||
</a-tabs>
|
||||
<a-divider />
|
||||
<!-- 执行时间预览 -->
|
||||
<a-row :gutter="8">
|
||||
<a-col :span="18" style="margin-top: 22px">
|
||||
<a-row :gutter="8">
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.second" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'second'">秒</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.minute" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'minute'">分</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.hour" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'hour'">时</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.day" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'day'">日</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.month" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'month'">月</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.week" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'week'">周</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-input v-model:value="inputValues.year" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'year'">年</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="16">
|
||||
<a-input v-model:value="inputValues.cron" @blur="onInputCronBlur">
|
||||
<template #addonBefore>
|
||||
<a-tooltip title="Cron表达式">式</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<div>近十次执行时间(不含年)</div>
|
||||
<a-textarea type="textarea" :value="preTimeList" :rows="5" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
<div style="overflow: hidden">
|
||||
<a-row :gutter="8">
|
||||
<a-col :span="18" style="margin-top: 22px">
|
||||
<a-row :gutter="8">
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.second" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'second'">秒</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.minute" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'minute'">分</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.hour" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'hour'">时</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.day" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'day'">日</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.month" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'month'">月</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8" style="margin-bottom: 12px">
|
||||
<a-input v-model:value="inputValues.week" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'week'">周</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-input v-model:value="inputValues.year" @blur="onInputBlur">
|
||||
<template #addonBefore>
|
||||
<span class="allow-click" @click="activeKey = 'year'">年</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
<a-col :span="16">
|
||||
<a-input v-model:value="inputValues.cron" @blur="onInputCronBlur">
|
||||
<template #addonBefore>
|
||||
<a-tooltip title="Cron表达式">式</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<div>近十次执行时间(不含年)</div>
|
||||
<a-textarea type="textarea" :value="preTimeList" :rows="5" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<BasicModal @register="registerModal" title="Cron表达式" width="800px" @ok="onOk">
|
||||
<BasicModal @register="registerModal" title="Cron表达式" width="1000px" @ok="onOk">
|
||||
<EasyCron v-bind="attrs" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
|
|
@ -395,7 +395,14 @@
|
|||
// update-end--author:liaozhiyang---date:20240809---for:【TV360X-2062】下拉搜索选择第二页数据后,第一次点击时(得到焦点)滚动条没复原到初始位置且数据会加载第二页数据(应该只加载第一页数据)
|
||||
initDictTableData();
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20240709---for:【issues/6681】异步查询不生效
|
||||
// update-begin--author:liaozhiyang---date:20240919---for:【TV360X-2348】得到焦点时options选项显示第一页内容(解决新增时显示非第一页内容)
|
||||
if (Array.isArray(selectedAsyncValue.value) && selectedAsyncValue.value.length === 0 && isDictTable.value && props.async) {
|
||||
if (pageNo > 2) {
|
||||
options.value = [];
|
||||
initDictTableData();
|
||||
}
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20240919---for:【TV360X-2348】得到焦点时options选项显示第一页内容(解决新增时显示非第一页内容)
|
||||
attrs.onFocus?.();
|
||||
};
|
||||
// update-end--author:liaozhiyang---date:20240523---for:【TV360X-26】下拉搜索控件选中选项后再次点击下拉应该显示初始的下拉选项,而不是只展示选中结果
|
||||
|
|
|
@ -67,8 +67,10 @@ export const basicProps = {
|
|||
rulesMessageJoinLabel: propTypes.bool.def(true),
|
||||
// 【jeecg】超过3列自动折叠
|
||||
autoAdvancedCol: propTypes.number.def(3),
|
||||
// update-begin--author:liaozhiyang---date:202401009---for:【issues/7261】表格上方查询项autoAdvancedLine配置没有效果(删除autoAdvancedLine)
|
||||
// 超过3行自动折叠
|
||||
autoAdvancedLine: propTypes.number.def(3),
|
||||
// autoAdvancedLine: propTypes.number.def(3),
|
||||
// update-end--author:liaozhiyang---date:202401009---for:【issues/7261】表格上方查询项autoAdvancedLine配置没有效果(删除autoAdvancedLine)
|
||||
// 不受折叠影响的行数
|
||||
alwaysShowLines: propTypes.number.def(1),
|
||||
|
||||
|
|
|
@ -99,7 +99,9 @@ export interface FormProps {
|
|||
// 【jeecg】如果 showAdvancedButton 为 true,超过指定列数默认折叠,默认为3
|
||||
autoAdvancedCol?: number;
|
||||
// 如果 showAdvancedButton 为 true,超过指定行数行默认折叠
|
||||
autoAdvancedLine?: number;
|
||||
// update-begin--author:liaozhiyang---date:202401009---for:【issues/7261】表格上方查询项autoAdvancedLine配置没有效果(删除autoAdvancedLine)
|
||||
// autoAdvancedLine?: number;
|
||||
// update-end--author:liaozhiyang---date:202401009---for:【issues/7261】表格上方查询项autoAdvancedLine配置没有效果(删除autoAdvancedLine)
|
||||
// 折叠时始终保持显示的行数
|
||||
alwaysShowLines?: number;
|
||||
// Whether to show the operation button
|
||||
|
|
|
@ -101,11 +101,6 @@ const jeecgAreaData = new Area();
|
|||
// 根据code找文本
|
||||
const getAreaTextByCode = function (code) {
|
||||
let index = 3;
|
||||
// update-begin--author:liaozhiyang---date:20240617---for:【TV360X-1210】online列表香港、澳门没翻译(香港、澳门只有两级其它省份是三级)
|
||||
if (code && ['82', '81'].includes(code.substring(0, 2))) {
|
||||
index = 2;
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20240617---for:【TV360X-1210】online列表香港、澳门没翻译(香港、澳门只有两级其它省份是三级)
|
||||
//update-begin-author:liusq---date:20220531--for: 判断code是否是多code逗号分割的字符串,是的话,获取最后一位的code ---
|
||||
if (code && code.includes(',')) {
|
||||
index = code.split(",").length;
|
||||
|
|
|
@ -36,8 +36,10 @@ export function handleRangeTimeValue(props, values) {
|
|||
timeValue = timeValue.split(',');
|
||||
}
|
||||
const [startTime, endTime]: string[] = timeValue;
|
||||
values[startTimeKey] = dateUtil(startTime).format(format);
|
||||
values[endTimeKey] = dateUtil(endTime).format(format);
|
||||
//update-begin---author:wangshuai---date:2024-10-08---for:【issues/7216】当RangePicker组件值允许开始/结束为空时,表单的fieldMapToTime处理异常---
|
||||
startTime && (values[startTimeKey] = dateUtil(startTime).format(format));
|
||||
endTime && (values[endTimeKey] = dateUtil(endTime).format(format));
|
||||
//update-end---author:wangshuai---date:2024-10-08---for:【issues/7216】当RangePicker组件值允许开始/结束为空时,表单的fieldMapToTime处理异常---
|
||||
Reflect.deleteProperty(values, field);
|
||||
}
|
||||
return values;
|
||||
|
|
|
@ -1,10 +1,23 @@
|
|||
<template>
|
||||
<a-input :disabled="disabled" :style="{ width }" readOnly :placeholder="t('component.icon.placeholder')" :class="prefixCls" v-model:value="currentSelect">
|
||||
<a-input
|
||||
:class="prefixCls"
|
||||
:value="currentSelect"
|
||||
readOnly
|
||||
:disabled="disabled"
|
||||
:placeholder="t('component.icon.placeholder')"
|
||||
:style="{ width }"
|
||||
@click="currentSelectClick"
|
||||
>
|
||||
<template #addonAfter>
|
||||
<span class="cursor-pointer px-2 py-1 flex items-center" v-if="isSvgMode && currentSelect">
|
||||
<SvgIcon :name="currentSelect" @click="currentSelectClick"/>
|
||||
</span>
|
||||
<Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" v-else @click="currentSelectClick"/>
|
||||
<Icon v-else :icon="currentSelect || 'ion:apps-outline'" :class="['px-2 py-1', {
|
||||
'cursor-pointer': !disabled,
|
||||
'cursor-not-allowed': disabled,
|
||||
}]"
|
||||
@click="currentSelectClick"
|
||||
/>
|
||||
</template>
|
||||
</a-input>
|
||||
<a-modal :bodyStyle="{ padding: '24px'}" v-bind="$attrs" v-model:open="iconOpen" :keyboard="false" :width="800" @ok="handleOk" :ok-text="t('common.okText')" :cancel-text="t('common.cancelText')">
|
||||
|
@ -84,7 +97,7 @@
|
|||
width: propTypes.string.def('100%'),
|
||||
copy: propTypes.bool.def(false),
|
||||
mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'),
|
||||
disabled: propTypes.bool.def(true),
|
||||
disabled: propTypes.bool.def(false),
|
||||
clearSelect: propTypes.bool.def(false),
|
||||
iconPrefixSave: propTypes.bool.def(true),
|
||||
});
|
||||
|
@ -149,6 +162,9 @@
|
|||
* 图标点击重置页数
|
||||
*/
|
||||
function currentSelectClick() {
|
||||
if (props.disabled) {
|
||||
return
|
||||
}
|
||||
iconOpen.value = true;
|
||||
setTimeout(()=>{
|
||||
iconListRef.value.currentSelectClick();
|
||||
|
@ -185,6 +201,12 @@
|
|||
@prefix-cls: ~'@{namespace}-icon-picker';
|
||||
|
||||
.@{prefix-cls} {
|
||||
|
||||
// 输入框手势图标
|
||||
.ant-input:not([disabled]) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ant-input-group-addon {
|
||||
padding: 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
<template>
|
||||
<div>
|
||||
<keep-alive>
|
||||
<component
|
||||
v-if="currentModal"
|
||||
v-bind="bindParams"
|
||||
:key="currentModal"
|
||||
:is="currentModal"
|
||||
@register="modalRegCache[currentModal].register"
|
||||
@reply="handReply"
|
||||
@selected="reloadPage"
|
||||
/>
|
||||
</keep-alive>
|
||||
<!-- 历史弹出框 -->
|
||||
<HisTaskDealModal ref="taskDealRef" v-bind="bindParams" />
|
||||
<!-- 系统公告弹窗 -->
|
||||
<DynamicNotice ref="showDynamNotice" v-bind="bindParams" />
|
||||
<!-- eoa查看详情 -->
|
||||
<EoaDetailModal ref="detailRef" />
|
||||
<!-- 表单设计器弹窗 -->
|
||||
<DesformDataModal ref="desformRef" v-bind="bindParams" @added="handleDesformDataAdded" />
|
||||
<!-- 我的计划弹窗 -->
|
||||
<PlanModal ref="planRef" v-bind="bindParams" @success="reloadPage" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted } from 'vue';
|
||||
import { useDragNotice } from '/@/hooks/web/useDragNotice';
|
||||
import EoaMailBoxInModal from '/@/views/super/eoa/email/components/EoaMailBoxInModal.vue';
|
||||
import DynamicNotice from '@/views/monitor/mynews/DynamicNotice.vue';
|
||||
import EoaDetailModal from '@/views/super/eoa/cmsoa/modules/EoaDetailModal.vue';
|
||||
import PlanModal from '/@/views/super/eoa/plan/components/PlanModal.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'JDragNotice',
|
||||
components: {
|
||||
EoaDetailModal,
|
||||
DynamicNotice,
|
||||
EoaMailBoxInModal,
|
||||
PlanModal,
|
||||
},
|
||||
setup() {
|
||||
const {
|
||||
initDragWebSocket,
|
||||
currentModal,
|
||||
modalParams,
|
||||
modalRegCache,
|
||||
bindParams,
|
||||
taskDealRef,
|
||||
desformRef,
|
||||
handleDesformDataAdded,
|
||||
handReply,
|
||||
reloadPage,
|
||||
} = useDragNotice();
|
||||
|
||||
onMounted(() => {
|
||||
initDragWebSocket();
|
||||
});
|
||||
|
||||
return {
|
||||
currentModal,
|
||||
modalParams,
|
||||
modalRegCache,
|
||||
bindParams,
|
||||
taskDealRef,
|
||||
desformRef,
|
||||
handleDesformDataAdded,
|
||||
handReply,
|
||||
reloadPage,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
|
@ -112,7 +112,10 @@
|
|||
|
||||
//整合warpClassName
|
||||
const getWrapClassName = computed(() => {
|
||||
const clsName = toRef(getMergeProps.value, 'wrapClassName').value || '';
|
||||
let clsName = toRef(getMergeProps.value, 'wrapClassName').value || '';
|
||||
// update-begin--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
clsName = `${clsName} jeecg-modal-code-generate`;
|
||||
// update-end--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
return unref(fullScreenRef) ? `jeecg-full-screen-modal-code-generate ${clsName} ` : unref(clsName);
|
||||
});
|
||||
|
||||
|
@ -324,4 +327,13 @@
|
|||
}
|
||||
}
|
||||
/*end 全屏弹窗modal样式*/
|
||||
// update-begin--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
.jeecg-modal-code-generate {
|
||||
.ant-modal {
|
||||
.ant-modal-close {
|
||||
top: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
</style>
|
||||
|
|
|
@ -120,7 +120,9 @@
|
|||
display: flex;
|
||||
height: 95%;
|
||||
align-items: center;
|
||||
|
||||
// update-begin--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
margin-top: -2px;
|
||||
// update-end--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
> span {
|
||||
margin-left: 48px;
|
||||
font-size: 16px;
|
||||
|
|
|
@ -76,10 +76,12 @@
|
|||
}
|
||||
|
||||
.ant-modal-close-x {
|
||||
display: inline-block;
|
||||
width: 96px;
|
||||
height: 56px;
|
||||
line-height: 56px;
|
||||
// update-begin--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
// display: inline-block;
|
||||
// width: 96px;
|
||||
// height: 56px;
|
||||
// line-height: 56px;
|
||||
// update-end--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
}
|
||||
|
||||
.ant-modal-confirm-body {
|
||||
|
|
|
@ -48,6 +48,11 @@
|
|||
const renderValue = String(value);
|
||||
const wrapEl = unref(wrapRef);
|
||||
|
||||
// 无值不生成
|
||||
if (renderValue == null || renderValue === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wrapEl) return;
|
||||
|
||||
if (tag === 'canvas') {
|
||||
|
|
|
@ -161,11 +161,8 @@ export function useColumns(
|
|||
const viewColumns = sortFixedColumn(unref(getColumnsRef));
|
||||
|
||||
const columns = cloneDeep(viewColumns);
|
||||
const result = columns
|
||||
.filter((column) => {
|
||||
return hasPermission(column.auth) && isIfShow(column);
|
||||
})
|
||||
.map((column) => {
|
||||
const formatEditColumn = (columns) => {
|
||||
return columns.map((column) => {
|
||||
// update-begin--author:liaozhiyang---date:20230718---for: 【issues-179】antd3 一些警告以及报错(针对表格)
|
||||
if(column.slots?.customRender) {
|
||||
// slots的备份,兼容老的写法,转成新写法避免控制台警告
|
||||
|
@ -198,8 +195,17 @@ export function useColumns(
|
|||
if ((edit || editRow) && !isDefaultAction) {
|
||||
column.customRender = renderEditCell(column);
|
||||
}
|
||||
// update-begin--author:liaozhiyang---date:20241021---for:【pull/7333】修复分组表头可编辑表格失效问题
|
||||
if (column.children?.length) {
|
||||
formatEditColumn(column.children.filter((item) => hasPermission(column.auth) && isIfShow(column)));
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20241021---for:【pull/7333】修复分组表头可编辑表格失效问题
|
||||
return reactive(column);
|
||||
});
|
||||
};
|
||||
// update-begin--author:liaozhiyang---date:20241021---for:【pull/7333】修复分组表头可编辑表格失效问题
|
||||
const result = formatEditColumn(columns.filter((item) => hasPermission(item.auth) && isIfShow(item)));
|
||||
// update-end--author:liaozhiyang---date:20241021---for:【pull/7333】修复分组表头可编辑表格失效问题
|
||||
// update-begin--author:liaozhiyang---date:20230919---for:【QQYUN-6387】展开写法(去掉报错)
|
||||
if (propsRef.value.expandedRowKeys && !propsRef.value.isTreeTable) {
|
||||
let index = 0;
|
||||
|
|
|
@ -198,17 +198,9 @@ export function useCustomSelection(
|
|||
bodyHeight.value = Math.ceil(height);
|
||||
}
|
||||
}
|
||||
updateRowHeight();
|
||||
});
|
||||
bodyResizeObserver.observe(bodyEl.value);
|
||||
const el = bodyEl.value?.querySelector('tbody.ant-table-tbody tr.ant-table-row') as HTMLDivElement;
|
||||
if (el) {
|
||||
// update-begin--author:liaozhiyang---date:20241111---for:【issues/7442】basicTable从默认切换到宽松紧凑时多选框显示异常
|
||||
nextTick(() => {
|
||||
rowHeight.value = el.offsetHeight;
|
||||
});
|
||||
// update-end--author:liaozhiyang---date:20241111---for:【issues/7442】basicTable从默认切换到宽松紧凑时多选框显示异常
|
||||
return;
|
||||
}
|
||||
}
|
||||
rowHeight.value = 50;
|
||||
});
|
||||
|
@ -226,6 +218,16 @@ export function useCustomSelection(
|
|||
}
|
||||
});
|
||||
|
||||
// 更新首行行高
|
||||
function updateRowHeight() {
|
||||
const el = bodyEl.value?.querySelector('tbody.ant-table-tbody tr.ant-table-row') as HTMLDivElement;
|
||||
if (el) {
|
||||
// update-begin--author:liaozhiyang---date:20241111---for:【issues/7442】basicTable从默认切换到宽松紧凑时多选框显示异常
|
||||
nextTick(() => rowHeight.value = el.offsetHeight);
|
||||
// update-end--author:liaozhiyang---date:20241111---for:【issues/7442】basicTable从默认切换到宽松紧凑时多选框显示异常
|
||||
}
|
||||
}
|
||||
|
||||
// 选择全部
|
||||
function onSelectAll(checked: boolean, flag = 'currentPage') {
|
||||
// update-begin--author:liaozhiyang---date:20231122---for:【issues/5577】BasicTable组件全选和取消全选时不触发onSelectAll事件
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { BasicTableProps, TableRowSelection, BasicColumn } from '../types/table';
|
||||
import type { Ref, ComputedRef } from 'vue';
|
||||
import type { Ref, ComputedRef, Slots } from 'vue';
|
||||
import { computed, unref, ref, nextTick, watch } from 'vue';
|
||||
import { getViewportOffset } from '/@/utils/domUtils';
|
||||
import { isBoolean } from '/@/utils/is';
|
||||
|
@ -14,7 +14,8 @@ export function useTableScroll(
|
|||
tableElRef: Ref<ComponentRef>,
|
||||
columnsRef: ComputedRef<BasicColumn[]>,
|
||||
rowSelectionRef: ComputedRef<TableRowSelection<any> | null>,
|
||||
getDataSourceRef: ComputedRef<Recordable[]>
|
||||
getDataSourceRef: ComputedRef<Recordable[]>,
|
||||
slots: Slots
|
||||
) {
|
||||
const tableHeightRef: Ref<Nullable<number>> = ref(null);
|
||||
|
||||
|
@ -175,7 +176,11 @@ export function useTableScroll(
|
|||
if (len !== 0) {
|
||||
width += len * NORMAL_WIDTH;
|
||||
}
|
||||
|
||||
// update-begin--author:liaozhiyang---date:202401009---for:【TV360X-116】内嵌风格字段较多时表格错位
|
||||
if (slots.expandedRowRender) {
|
||||
width += propsRef.value.expandColumnWidth;
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:202401009---for:【TV360X-116】内嵌风格字段较多时表格错位
|
||||
const table = unref(tableElRef);
|
||||
const tableWidth = table?.$el?.offsetWidth ?? 0;
|
||||
return tableWidth > width ? '100%' : width;
|
||||
|
|
|
@ -108,6 +108,9 @@ export const basicProps = {
|
|||
},
|
||||
minHeight: propTypes.number,
|
||||
maxHeight: propTypes.number,
|
||||
// update-begin--author:liaozhiyang---date:202401009---for:【TV360X-116】内嵌风格字段较多时表格错位
|
||||
expandColumnWidth: propTypes.number.def(48),
|
||||
// update-end--author:liaozhiyang---date:202401009---for:【TV360X-116】内嵌风格字段较多时表格错位
|
||||
// 统一设置列最大宽度
|
||||
maxColumnWidth: propTypes.number,
|
||||
dataSource: {
|
||||
|
|
|
@ -199,7 +199,7 @@ export interface BasicTableProps<T = any> {
|
|||
// 是否显示操作列
|
||||
showActionColumn?: boolean;
|
||||
// 操作列配置
|
||||
actionColumn?: BasicColumn;
|
||||
actionColumn?: Partial<BasicColumn>;
|
||||
// 文本超过宽度是否显示。。。
|
||||
ellipsis?: boolean;
|
||||
// 是否可以自适应高度
|
||||
|
@ -220,6 +220,10 @@ export interface BasicTableProps<T = any> {
|
|||
maxHeight?: number;
|
||||
// 是否显示边框
|
||||
bordered?: boolean;
|
||||
// update-begin--author:liaozhiyang---date:202401009---for:【TV360X-116】内嵌风格字段较多时表格错位
|
||||
// 展开列宽度
|
||||
expandColumnWidth: number;
|
||||
// update-end--author:liaozhiyang---date:202401009---for:【TV360X-116】内嵌风格字段较多时表格错位
|
||||
// 分页配置
|
||||
pagination?: PaginationProps | boolean;
|
||||
// loading加载
|
||||
|
|
|
@ -29,5 +29,5 @@ export interface PopConfirm {
|
|||
icon?: string;
|
||||
placement?: string;
|
||||
overlayClassName?: string;
|
||||
getPopupContainer: Fn;
|
||||
getPopupContainer?: Fn;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<ImgUpload
|
||||
:fullscreen="fullscreen"
|
||||
@uploading="handleImageUploading"
|
||||
@loading="handleLoading"
|
||||
@done="handleDone"
|
||||
v-show="editorRef"
|
||||
:disabled="disabled"
|
||||
|
@ -13,6 +14,7 @@
|
|||
<!-- update-end--author:liaozhiyang---date:20240517---for:【TV360X-35】富文本,图片上传遮挡其他按钮 -->
|
||||
<Editor :id="tinymceId" ref="elRef" :disabled="disabled" :init="initOptions" :style="{ visibility: 'hidden' }" v-if="!initOptions.inline"></Editor>
|
||||
<slot v-else></slot>
|
||||
<ProcessMask ref="processMaskRef" :show="showUploadMask"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -33,6 +35,7 @@
|
|||
import 'tinymce/plugins/image';
|
||||
import { defineComponent, computed, nextTick, ref, unref, watch, onDeactivated, onBeforeUnmount, onMounted } from 'vue';
|
||||
import ImgUpload from './ImgUpload.vue';
|
||||
import ProcessMask from './ProcessMask.vue';
|
||||
import {simpleToolbar, menubar, simplePlugins} from './tinymce';
|
||||
import { buildShortUUID } from '/@/utils/uuid';
|
||||
import { bindHandlers } from './helper';
|
||||
|
@ -82,6 +85,10 @@
|
|||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
showUploadMask: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
//是否聚焦
|
||||
autoFocus:{
|
||||
type: Boolean,
|
||||
|
@ -91,9 +98,9 @@
|
|||
|
||||
export default defineComponent({
|
||||
name: 'Tinymce',
|
||||
components: { ImgUpload,Editor },
|
||||
components: { ImgUpload,Editor,ProcessMask },
|
||||
inheritAttrs: false,
|
||||
props: tinymceProps,
|
||||
props: tinymceProps as any,
|
||||
emits: ['change', 'update:modelValue', 'inited', 'init-error'],
|
||||
setup(props, { emit, attrs }) {
|
||||
console.log("---Tinymce---初始化---")
|
||||
|
@ -103,6 +110,7 @@
|
|||
const tinymceId = ref<string>(buildShortUUID('tiny-vue'));
|
||||
const elRef = ref<Nullable<HTMLElement>>(null);
|
||||
const editorRootRef = ref<Nullable<HTMLElement>>(null);
|
||||
const processMaskRef = ref<any>(null);
|
||||
const imgUploadShow = ref(false);
|
||||
const targetElem = ref<null | HTMLDivElement>(null);
|
||||
|
||||
|
@ -325,6 +333,20 @@
|
|||
setValue(editor, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传进度计算
|
||||
* @param file
|
||||
* @param fileList
|
||||
*/
|
||||
function handleLoading(fileLength,showMask){
|
||||
if(fileLength && fileLength > 0){
|
||||
setTimeout(() => {
|
||||
props?.showUploadMask && processMaskRef.value.calcProcess(fileLength)
|
||||
},100)
|
||||
}else{
|
||||
props?.showUploadMask && (processMaskRef.value.showMask = showMask);
|
||||
}
|
||||
}
|
||||
function getUploadingImgName(name: string) {
|
||||
return `[uploading:${name}]`;
|
||||
}
|
||||
|
@ -397,6 +419,9 @@
|
|||
editorRootRef,
|
||||
imgUploadShow,
|
||||
targetElem,
|
||||
|
||||
handleLoading,
|
||||
processMaskRef
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@ -428,6 +453,7 @@
|
|||
}
|
||||
// update-end--author:liaozhiyang---date:20240527---for:【TV360X-329】富文本禁用状态下工具栏划过边框丢失
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
.@{prefix-cls} {
|
||||
.tox .tox-edit-area__iframe {background-color: #141414;}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
:showUploadList="false"
|
||||
:data="getBizData()"
|
||||
:headers="getheader()"
|
||||
:before-upload="beforeUpload"
|
||||
accept=".jpg,.jpeg,.gif,.png,.webp"
|
||||
>
|
||||
<a-button type="primary" v-bind="{ ...getButtonProps }">
|
||||
|
@ -37,10 +38,8 @@
|
|||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['uploading', 'done', 'error'],
|
||||
emits: ['uploading', 'done', 'error', 'loading'],
|
||||
setup(props, { emit }) {
|
||||
let uploading = false;
|
||||
|
||||
//update-begin-author:taoyan date:2022-5-13 for: 富文本上传图片不支持
|
||||
function getheader() {
|
||||
return getHeaders();
|
||||
|
@ -67,33 +66,37 @@
|
|||
};
|
||||
});
|
||||
|
||||
let uploadLength = 0;
|
||||
function handleChange({ file, fileList }) {
|
||||
if (file.status === 'error') {
|
||||
emit('error');
|
||||
uploading = false;
|
||||
// 过滤掉已经存在的文件
|
||||
fileList = fileList.filter((file) => {
|
||||
const existFile = uploadFileList.value.find(({ uid }) => uid === file.uid);
|
||||
return existFile ? false : true;
|
||||
});
|
||||
uploadLength == 0 && (uploadLength = fileList.length);
|
||||
if (file.status != 'uploading') {
|
||||
emit('loading', uploadLength, true);
|
||||
}
|
||||
let files = [] as any;
|
||||
let noUploadingFileCount = 0;
|
||||
// 处理上传好的文件
|
||||
if (file.status != 'uploading') {
|
||||
fileList.forEach((file) => {
|
||||
if (file.status === 'done' && file.response.success) {
|
||||
files.push(file);
|
||||
const name = file?.name;
|
||||
let realUrl = getFileAccessHttpUrl(file.response.message);
|
||||
uploadFileList.value.push(file);
|
||||
emit('done', name, realUrl);
|
||||
}
|
||||
if (file.status != 'uploading') {
|
||||
noUploadingFileCount++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (noUploadingFileCount == fileList.length) {
|
||||
fileList.forEach((file) => {
|
||||
const name = file?.name;
|
||||
let realUrl = getFileAccessHttpUrl(file.response.message);
|
||||
emit('done', name, realUrl);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//上传之前
|
||||
function beforeUpload() {
|
||||
uploadLength = 0;
|
||||
emit('loading', null, true);
|
||||
setTimeout(() => {
|
||||
emit('loading', null, false);
|
||||
}, 10000);
|
||||
}
|
||||
return {
|
||||
prefixCls,
|
||||
handleChange,
|
||||
|
@ -102,7 +105,8 @@
|
|||
getBizData,
|
||||
t,
|
||||
getButtonProps,
|
||||
uploadFileList
|
||||
uploadFileList,
|
||||
beforeUpload,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
<template>
|
||||
<div :class="[prefixCls]" v-if="showMask && show">
|
||||
<div class="progress-bar-rear">
|
||||
<div class="progress-bar-front" :style="{ width: progressBarWidth }"></div>
|
||||
</div>
|
||||
<div class="value">{{ percentage }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import {useDesign} from "@/hooks/web/useDesign";
|
||||
|
||||
const props = defineProps({
|
||||
backColor: {
|
||||
type: [String],
|
||||
default: 'white',
|
||||
},
|
||||
processColor: {
|
||||
type: String,
|
||||
default: '#018FFB',
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
const { prefixCls } = useDesign('tinymce-process-mask');
|
||||
|
||||
//显示遮罩
|
||||
const showMask = ref(false);
|
||||
//进度值占比
|
||||
const progressValue = ref<any>(0);
|
||||
//当前数量
|
||||
const currentNum = ref(0);
|
||||
// 计算进度条宽度的计算属性
|
||||
const progressBarWidth = computed(() => {
|
||||
return progressValue.value > 0 ? `${progressValue.value}px` : '0px';
|
||||
});
|
||||
// 计算进度条百分比
|
||||
const percentage = computed(() => {
|
||||
return `${progressValue.value}%`;
|
||||
});
|
||||
// 进度色
|
||||
const frontColor = computed(() => {
|
||||
return props.processColor;
|
||||
});
|
||||
// 后置背景色
|
||||
const rearColor = computed(() => {
|
||||
return props.backColor;
|
||||
});
|
||||
function calcProcess(totalNum) {
|
||||
!showMask.value && (showMask.value = true);
|
||||
currentNum.value += 1;
|
||||
progressValue.value = ((currentNum.value / totalNum) * 100).toFixed(2);
|
||||
console.log('currentNum.value', currentNum.value);
|
||||
console.log('totalNum.value', totalNum);
|
||||
if (currentNum.value == totalNum) {
|
||||
showMask.value = false;
|
||||
currentNum.value = 0;
|
||||
progressValue.value = 0;
|
||||
}
|
||||
}
|
||||
defineExpose({
|
||||
calcProcess,
|
||||
showMask,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
//noinspection LessUnresolvedVariable
|
||||
@prefix-cls: ~'@{namespace}-tinymce-process-mask';
|
||||
|
||||
.@{prefix-cls} {
|
||||
|
||||
& {
|
||||
position: absolute; /* 或者使用固定定位等其他方式 */
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5); /* 半透明遮罩 */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.progress-bar-rear {
|
||||
width: 100px; /* 进度条宽度 */
|
||||
height: 10px; /* 进度条高度 */
|
||||
background-color: v-bind(rearColor); /* 进度条颜色 */
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.progress-bar-front {
|
||||
height: 10px; /* 进度条高度 */
|
||||
background-color: v-bind(frontColor); /* 进度条颜色 */
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #fff;
|
||||
margin-left: 5px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -94,4 +94,15 @@ export function definedComponent() {
|
|||
// addComponent(JVxeTypes.userSelect, JVxeUserSelectCell)
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空注册的组件
|
||||
*/
|
||||
export function clearComponent() {
|
||||
componentMap.clear();
|
||||
|
||||
// update-begin--author:liaozhiyang---date:20231208---for:【issues/860】生成的一对多代码,热更新之后点击新增卡死[暂时先解决]
|
||||
import.meta.env.DEV && (window[JVxeComponents] = componentMap);
|
||||
// update-end--author:liaozhiyang---date:20231208---for:【issues/860】生成的一对多代码,热更新之后点击新增卡死[暂时先解决]
|
||||
}
|
||||
|
||||
export { componentMap };
|
||||
|
|
|
@ -5,15 +5,17 @@
|
|||
<template #buttons>
|
||||
<div :class="`${prefixCls}-button div`" :size="btnSize">
|
||||
<slot v-if="showPrefix" name="toolbarPrefix" :size="btnSize" />
|
||||
<a-button v-if="showAdd" type="primary" preIcon="ant-design:plus-outlined" :disabled="disabled" :loading="deleting" @click="trigger('add')">
|
||||
<span>新增</span>
|
||||
<a-button v-if="addBtnCfg.enabled && showAdd" type="primary" :preIcon="addBtnCfg.buttonIcon" :disabled="disabled" :loading="deleting" @click="trigger('add')">
|
||||
<span>{{ addBtnCfg.buttonName }}</span>
|
||||
</a-button>
|
||||
<a-button v-if="showSave" preIcon="ant-design:save-outlined" :disabled="disabled" @click="trigger('save')">
|
||||
<span>保存</span>
|
||||
</a-button>
|
||||
<template v-if="deleting || selectedRowIds.length > 0">
|
||||
<Popconfirm v-if="showRemove" :title="`确定要删除这 ${selectedRowIds.length} 项吗?`" :disabled="deleting" @confirm="onRemove">
|
||||
<a-button preIcon="ant-design:minus-outlined" :disabled="disabled" :loading="deleting">删除</a-button>
|
||||
<Popconfirm v-if="removeBtnCfg.enabled && showRemove" :title="`确定要删除这 ${selectedRowIds.length} 项吗?`" :disabled="deleting" @confirm="onRemove">
|
||||
<a-button :preIcon="removeBtnCfg.buttonIcon" :disabled="disabled" :loading="deleting">
|
||||
<span>{{ removeBtnCfg.buttonName }}</span>
|
||||
</a-button>
|
||||
</Popconfirm>
|
||||
<template v-if="showClearSelection">
|
||||
<a-button preIcon="ant-design:delete-outlined" @click="trigger('clearSelection')">清空选择</a-button>
|
||||
|
@ -46,6 +48,16 @@
|
|||
disabledRows: propTypes.object,
|
||||
hasBtnAuth: propTypes.func,
|
||||
selectedRowIds: propTypes.array.def(() => []),
|
||||
addBtnCfg: propTypes.object.def(() => ({
|
||||
enabled: true,
|
||||
buttonIcon: 'ant-design:plus-outlined',
|
||||
buttonName: '新增',
|
||||
})),
|
||||
removeBtnCfg: propTypes.object.def(() => ({
|
||||
enabled: true,
|
||||
buttonIcon: 'ant-design:minus-outlined',
|
||||
buttonName: '删除',
|
||||
})),
|
||||
});
|
||||
const emit = defineEmits(['save', 'add', 'remove', 'clearSelection', 'register']);
|
||||
const xToolbarRef = ref({} as VxeToolbarInstance);
|
||||
|
|
|
@ -10,8 +10,10 @@
|
|||
<a-menu>
|
||||
<a-menu-item key="0" :disabled="disabledMoveUp" @click="handleRowMoveUp">向上移</a-menu-item>
|
||||
<a-menu-item key="1" :disabled="disabledMoveDown" @click="handleRowMoveDown">向下移</a-menu-item>
|
||||
<a-menu-divider />
|
||||
<a-menu-item key="3" @click="handleRowInsertDown">插入一行</a-menu-item>
|
||||
<template v-if="allowInsertRow">
|
||||
<a-menu-divider />
|
||||
<a-menu-item key="3" @click="handleRowInsertDown">插入一行</a-menu-item>
|
||||
</template>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
|
@ -48,6 +50,9 @@
|
|||
const disabledMoveUp = computed(() => rowIndex.value === 0);
|
||||
const disabledMoveDown = computed(() => rowIndex.value === fullDataLength.value - 1);
|
||||
|
||||
// 是否允许插入行
|
||||
const allowInsertRow = computed(() => originColumn.value.insertRow);
|
||||
|
||||
/** 向上移 */
|
||||
function handleRowMoveUp() {
|
||||
if (!disabledMoveUp.value) {
|
||||
|
@ -79,7 +84,8 @@
|
|||
handleRowMoveUp,
|
||||
handleRowMoveDown,
|
||||
handleRowInsertDown,
|
||||
isAllowDrag
|
||||
isAllowDrag,
|
||||
allowInsertRow,
|
||||
};
|
||||
},
|
||||
// 【组件增强】注释详见:JVxeComponent.Enhanced
|
||||
|
|
|
@ -30,7 +30,8 @@ export function useColumns(props: JVxeTableProps, data: JVxeDataProps, methods:
|
|||
// handle 方法参数
|
||||
const args: HandleArgs = { props, slots, data, methods, columns };
|
||||
let seqColumn, selectionColumn, expandColumn, dragSortColumn;
|
||||
props.columns.forEach((column: JVxeColumn) => {
|
||||
|
||||
const handleColumn = (column: JVxeColumn, container: JVxeColumn[]) => {
|
||||
// 排除未授权的列 1 = 显示/隐藏; 2 = 禁用
|
||||
let auth = methods.getColAuth(column.key);
|
||||
if (auth?.type == '1' && !auth.isAuth) {
|
||||
|
@ -47,6 +48,15 @@ export function useColumns(props: JVxeTableProps, data: JVxeDataProps, methods:
|
|||
if (col.type === JVxeTypes.hidden) {
|
||||
return handleInnerColumn(args, col, handleHiddenColumn);
|
||||
}
|
||||
// 处理子级列
|
||||
// 判断是否是分组列,如果当前是父级,则无需处理 render
|
||||
if (Array.isArray(col.children) && col.children.length > 0) {
|
||||
const children: JVxeColumn[] = [];
|
||||
col.children.forEach((child: JVxeColumn) => handleColumn(child, children));
|
||||
col.children = children;
|
||||
container.push(col);
|
||||
return;
|
||||
}
|
||||
// 组件未注册,自动设置为 normal
|
||||
if (!isRegistered(col.type)) {
|
||||
col.type = JVxeTypes.normal;
|
||||
|
@ -72,21 +82,25 @@ export function useColumns(props: JVxeTableProps, data: JVxeDataProps, methods:
|
|||
};
|
||||
if (col.type === JVxeTypes.rowNumber) {
|
||||
seqColumn = col;
|
||||
columns.push(col);
|
||||
container.push(col);
|
||||
} else if (col.type === JVxeTypes.rowRadio || col.type === JVxeTypes.rowCheckbox) {
|
||||
selectionColumn = col;
|
||||
columns.push(col);
|
||||
container.push(col);
|
||||
} else if (col.type === JVxeTypes.rowExpand) {
|
||||
expandColumn = col;
|
||||
columns.push(col);
|
||||
container.push(col);
|
||||
} else if (col.type === JVxeTypes.rowDragSort) {
|
||||
dragSortColumn = col;
|
||||
columns.push(col);
|
||||
container.push(col);
|
||||
} else {
|
||||
col.params = column;
|
||||
args.columns = container;
|
||||
handlerCol(args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
props.columns.forEach((column: JVxeColumn) => handleColumn(column, columns));
|
||||
|
||||
handleInnerColumn(args, seqColumn, handleSeqColumn);
|
||||
handleInnerColumn(args, selectionColumn, handleSelectionColumn);
|
||||
handleInnerColumn(args, expandColumn, handleExpandColumn);
|
||||
|
@ -250,6 +264,7 @@ function handleDragSortColumn({ props, data, col, columns, renderOptions }: Hand
|
|||
align: 'center',
|
||||
// update-begin--author:liaozhiyang---date:20240417---for:【QQYUN-8785】online表单列位置的id未做限制,拖动其他列到id列上面,同步数据库时报错
|
||||
params: {
|
||||
insertRow: props.insertRow,
|
||||
notAllowDrag: props.notAllowDrag,
|
||||
...col?.params,
|
||||
},
|
||||
|
|
|
@ -16,6 +16,8 @@ export function useToolbar(props: JVxeTableProps, data: JVxeDataProps, methods:
|
|||
hasBtnAuth: methods.hasBtnAuth,
|
||||
selectedRowIds: data.selectedRowIds.value,
|
||||
custom: props.custom,
|
||||
addBtnCfg: props.addBtnCfg,
|
||||
removeBtnCfg: props.removeBtnCfg,
|
||||
// 新增事件
|
||||
onAdd: () => {
|
||||
// update-begin--author:liaozhiyang---date:20240521---for:【TV360X-212】online新增字段就出校验提示
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
/* JVxeTable 行编辑 权限 */
|
||||
import { usePermissionStoreWithOut } from '/@/store/modules/permission';
|
||||
|
||||
const permissionStore = usePermissionStoreWithOut();
|
||||
|
||||
/**
|
||||
* JVxe 专用,获取权限
|
||||
* @param prefix
|
||||
*/
|
||||
export function getJVxeAuths(prefix) {
|
||||
const permissionStore = usePermissionStoreWithOut();
|
||||
prefix = getPrefix(prefix);
|
||||
let { authList, allAuthList } = permissionStore;
|
||||
let authsMap = new Map<string, typeof allAuthList[0]>();
|
||||
|
|
|
@ -42,6 +42,8 @@ export const vxeProps = () => ({
|
|||
rowExpand: propTypes.bool.def(false),
|
||||
// 展开行配置
|
||||
expandConfig: propTypes.object.def(() => ({})),
|
||||
// 是否可插入行
|
||||
insertRow: propTypes.bool.def(true),
|
||||
// 页面是否在加载中
|
||||
loading: propTypes.bool.def(false),
|
||||
// 表格高度
|
||||
|
@ -113,6 +115,11 @@ export const vxeProps = () => ({
|
|||
// 不允许拖拽的行 [{'key':field,'value':value}]
|
||||
notAllowDrag: propTypes.array.def(() => []),
|
||||
// update-end--author:liaozhiyang---date:20240417---for:【QQYUN-8785】online表单列位置的id未做限制,拖动其他列到id列上面,同步数据库时报错
|
||||
|
||||
// 新增按钮配置
|
||||
addBtnCfg: propTypes.object,
|
||||
// 删除按钮配置
|
||||
removeBtnCfg: propTypes.object,
|
||||
});
|
||||
|
||||
export const vxeEmits = ['save', 'added', 'removed', 'inserted', 'dragged', 'selectRowChange', 'pageChange', 'valueChange', 'blur'];
|
||||
|
|
|
@ -70,9 +70,12 @@
|
|||
// update-begin--author:liaozhiyang---date:20231218---for:【QQYUN-6366】升级到antd4.x
|
||||
.ant-modal {
|
||||
.ant-modal-close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
// update-begin--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// right: 0;
|
||||
top: 13px;
|
||||
// update-end--author:liaozhiyang---date:20241010---for:【issues/7260】原生a-modal关闭按钮位置偏移
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,10 @@ export const useGlobSetting = (): Readonly<GlobConfig> => {
|
|||
VITE_GLOB_APP_OPEN_QIANKUN,
|
||||
VITE_GLOB_DOMAIN_URL,
|
||||
VITE_GLOB_ONLINE_VIEW_URL,
|
||||
|
||||
// 【JEECG作为乾坤子应用】
|
||||
VITE_GLOB_QIANKUN_MICRO_APP_NAME,
|
||||
VITE_GLOB_QIANKUN_MICRO_APP_ENTRY,
|
||||
} = getAppEnvConfig();
|
||||
|
||||
// if (!/[a-zA-Z\_]*/.test(VITE_GLOB_APP_SHORT_NAME)) {
|
||||
|
@ -36,7 +40,19 @@ export const useGlobSetting = (): Readonly<GlobConfig> => {
|
|||
urlPrefix: VITE_GLOB_API_URL_PREFIX,
|
||||
uploadUrl: VITE_GLOB_DOMAIN_URL,
|
||||
viewUrl: VITE_GLOB_ONLINE_VIEW_URL,
|
||||
|
||||
// 【JEECG作为乾坤子应用】是否以乾坤子应用模式启动
|
||||
isQiankunMicro: VITE_GLOB_QIANKUN_MICRO_APP_NAME != null && VITE_GLOB_QIANKUN_MICRO_APP_NAME !== '',
|
||||
// 【JEECG作为乾坤子应用】乾坤子应用入口
|
||||
qiankunMicroAppEntry: VITE_GLOB_QIANKUN_MICRO_APP_ENTRY,
|
||||
};
|
||||
|
||||
// 【JEECG作为乾坤子应用】乾坤子应用下,需要定义一下
|
||||
if (!window['_CONFIG']) {
|
||||
window['_CONFIG'] = {}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
window._CONFIG['domianURL'] = VITE_GLOB_DOMAIN_URL;
|
||||
return glob as Readonly<GlobConfig>;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,349 @@
|
|||
import { ref, nextTick, getCurrentInstance, watch } from 'vue';
|
||||
import { getToken } from '/@/utils/auth';
|
||||
import md5 from 'crypto-js/md5';
|
||||
import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket';
|
||||
import { useGlobSetting } from '/@/hooks/setting';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
//弹窗业务需求引用的
|
||||
import { useMyRunningTaskList } from '@/hooks/jeecg/process/useMyRunningTaskList';
|
||||
import { hisProcessNodeInfo } from '@/hooks/jeecg/process/useBpmNodeInfo';
|
||||
import { queryByCode, save } from '@/views/super/eoa/cmsbpm/cmsbpm.api';
|
||||
import { isUrl } from '@/utils/is';
|
||||
import { getQueryVariable, getUrlParams } from '@/utils';
|
||||
import { backProcess, invalidProcess } from '@/views/super/eoa/cmsbpm/cmsbpm.api';
|
||||
import { editReadStatus } from '@/views/super/eoa/cmsoa/cmsoa.api';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
const { createMessage } = useMessage();
|
||||
export function useDragNotice() {
|
||||
//*********************************websocket配置begin******************************************
|
||||
const glob = useGlobSetting();
|
||||
const { push, currentRoute } = useRouter();
|
||||
const userStore = useUserStore();
|
||||
const instance: any = getCurrentInstance();
|
||||
const taskDealRef = ref<any>(null);
|
||||
const desformRef = ref<any>(null);
|
||||
// 初始化 WebSocket
|
||||
function initWebSocket() {
|
||||
const token = getToken();
|
||||
//将登录token生成一个短的标识
|
||||
const wsClientId = md5(token);
|
||||
// WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
|
||||
const url = glob.domainUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/dragChannelSocket/' + wsClientId;
|
||||
connectWebSocket(url);
|
||||
onWebSocket(onWebSocketMessage);
|
||||
}
|
||||
|
||||
async function onWebSocketMessage(data) {
|
||||
console.log('仪表盘监听按钮点击事件websocket', data);
|
||||
if (data?.CMD === 'drag') {
|
||||
//触发动作: url:路径 modal:弹窗
|
||||
const action = data.result.action;
|
||||
//弹窗类型: 点击按钮打开什么弹窗,根据type打开不同的弹窗
|
||||
const type = data.result.type;
|
||||
//url地址,可以是路由,也可以是外部链接
|
||||
let url = data.result.url;
|
||||
//弹窗参数或者url参数
|
||||
const record = data.result.records || {};
|
||||
console.log('仪表盘监听点击事件类型type', type);
|
||||
console.log('仪表盘监听点击事件动作action', action);
|
||||
console.log('仪表盘监听点击事件路径url', url);
|
||||
console.log('仪表盘监听点击事件参数', record);
|
||||
//1.路径的话,判断外部链接还是内部路由跳转
|
||||
if (action == 'url') {
|
||||
//常用下載特殊处理
|
||||
if (url == 'fileUrl') {
|
||||
url = record[url];
|
||||
}
|
||||
const urlParamsObj = getUrlParams(url);
|
||||
if (url.startsWith('http')) {
|
||||
window.open(url, '_blank');
|
||||
} else {
|
||||
push({ path: urlParamsObj.url, query: { ...urlParamsObj.params, ...record } });
|
||||
}
|
||||
} else {
|
||||
//2.弹窗方式打开项目组件
|
||||
switch (type) {
|
||||
case 'task':
|
||||
//流程办理弹窗
|
||||
const { formData, formUrl } = await getTaskNodeInfo(record);
|
||||
formData['PROCESS_TAB_TYPE'] = 'run';
|
||||
handleOpenType('task', { formData, formUrl, title: '流程办理' });
|
||||
break;
|
||||
case 'history':
|
||||
//历史流程弹窗
|
||||
hisProcessNodeInfo({ procInstId: record.processInstanceId }).then((res) => {
|
||||
console.log('获取流程节点信息', res);
|
||||
if (res.success) {
|
||||
const formData = {
|
||||
dataId: res.result.dataId,
|
||||
taskId: record.id,
|
||||
taskDefKey: record.taskId,
|
||||
procInsId: record.processInstanceId,
|
||||
tableName: res.result.tableName,
|
||||
vars: res.result.records,
|
||||
};
|
||||
let tempFormUrl = res.result.formUrl;
|
||||
//节点配置表单URL,VUE组件类型对应的拓展参数
|
||||
if (tempFormUrl && tempFormUrl.indexOf('?') != -1 && !isUrl(tempFormUrl) && tempFormUrl.indexOf('{{DOMAIN_URL}}') == -1) {
|
||||
tempFormUrl = res.result.formUrl.split('?')[0];
|
||||
formData['extendUrlParams'] = getQueryVariable(res.result.formUrl);
|
||||
}
|
||||
currentModal.value = null;
|
||||
modalParams.value = { path: tempFormUrl, formData };
|
||||
taskDealRef.value.deal(record);
|
||||
taskDealRef.value.data.title = '流程历史';
|
||||
console.log('taskDealRef', taskDealRef.value);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'entrust':
|
||||
//委托办理
|
||||
handleOpenType('entrust', { taskId: record.id });
|
||||
break;
|
||||
case 'taskNotify':
|
||||
//催办任务
|
||||
handleOpenType('taskNotify', {
|
||||
title: '催办提醒',
|
||||
procInstId: record.processInstanceId,
|
||||
});
|
||||
break;
|
||||
case 'invalid':
|
||||
//作废流程
|
||||
await invalidProcess({
|
||||
processInstanceId: record.processInstanceId,
|
||||
});
|
||||
reloadPage();
|
||||
break;
|
||||
case 'backTask':
|
||||
//取回流程
|
||||
await backProcess({
|
||||
processInstanceId: record.processInstanceId,
|
||||
});
|
||||
reloadPage();
|
||||
break;
|
||||
case 'sysNotice':
|
||||
//通知公告弹窗
|
||||
await editReadStatus({ anntId: record.anntId });
|
||||
currentModal.value = null;
|
||||
if (record.openType === 'component') {
|
||||
modalParams.value = { path: record.openPage, formData: { id: record.busId } };
|
||||
instance.refs.dynamicNoticeRef?.detail(record.openPage);
|
||||
} else {
|
||||
instance.refs.detailRef?.show({
|
||||
record,
|
||||
isUpdate: true,
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'email':
|
||||
//邮箱查看弹窗
|
||||
handleOpenType('email', { record });
|
||||
break;
|
||||
case 'plan':
|
||||
//我的计划弹窗
|
||||
let data = {};
|
||||
if (!!record?.id) {
|
||||
data = { id: record?.id };
|
||||
instance.refs.planRef?.show({
|
||||
isUpdate: !!record?.id,
|
||||
record: data,
|
||||
});
|
||||
} else {
|
||||
data = { joinPerson: userStore.getUserInfo.username, ...record };
|
||||
instance.refs.planRef?.show({
|
||||
isUpdate: !!record?.id,
|
||||
...data,
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
case 'desform':
|
||||
const title = '表单【' + record.desformName + '】发起申请';
|
||||
bindParams.value = { dialogOptions: { top: 60, width: 1000, padding: { top: 25, right: 25, bottom: 30, left: 25 } } };
|
||||
openDesformModal('add', record, title);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//*********************************websocket配置end******************************************
|
||||
|
||||
//*********************************打开弹窗修改,动态设置弹窗begin*******************************
|
||||
//当前表单弹窗
|
||||
const currentModal = ref<string | null>(null);
|
||||
//当前表单参数
|
||||
const modalParams = ref<Recordable>({});
|
||||
//表单注册缓存
|
||||
const modalRegCache = ref<Recordable>({});
|
||||
//组件绑定参数
|
||||
const bindParams = ref<Recordable>({});
|
||||
/**
|
||||
* 根据类型打开不同弹窗
|
||||
* @param type
|
||||
* @param params
|
||||
*/
|
||||
async function handleOpenType(type, params) {
|
||||
currentModal.value = null;
|
||||
modalParams.value = { ...params };
|
||||
switch (type) {
|
||||
case 'task':
|
||||
//流程办理
|
||||
currentModal.value = 'TaskHandleModal';
|
||||
break;
|
||||
case 'history':
|
||||
currentModal.value = 'HisTaskDealModal';
|
||||
case 'entrust':
|
||||
//委托
|
||||
currentModal.value = 'SelectEntrusterModal';
|
||||
break;
|
||||
case 'taskNotify':
|
||||
//催办
|
||||
currentModal.value = 'TaskNotifyModal';
|
||||
break;
|
||||
case 'email':
|
||||
//邮件查看
|
||||
currentModal.value = 'EoaMailBoxInModal';
|
||||
break;
|
||||
default:
|
||||
currentModal.value = null;
|
||||
break;
|
||||
}
|
||||
//注册表单弹窗
|
||||
initModalRegister();
|
||||
await nextTick(() => {
|
||||
if (modalRegCache.value[currentModal.value!]?.isRegister) {
|
||||
console.log('已注冊,走缓存');
|
||||
modalRegCache.value[currentModal.value!].modalMethods.openModal(true, modalParams.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 初始化弹窗注册
|
||||
*/
|
||||
function initModalRegister() {
|
||||
//如果当前选择表单为null,就不处理
|
||||
if (!currentModal.value) {
|
||||
return;
|
||||
}
|
||||
//判断缓存中是否存在,不存在就走缓存逻辑
|
||||
if (!modalRegCache.value[currentModal.value]) {
|
||||
const [registerModal, modalMethods] = useModal();
|
||||
modalRegCache.value[currentModal.value] = {
|
||||
isRegister: false,
|
||||
register: bindRegisterModal(registerModal, modalMethods),
|
||||
modalMethods,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定注册弹窗
|
||||
* @param regFn
|
||||
* @param modalMethod
|
||||
*/
|
||||
function bindRegisterModal(regFn, modalMethod) {
|
||||
return async (...args) => {
|
||||
console.log('开始注册:', currentModal.value);
|
||||
await regFn(...args);
|
||||
console.log('注册完成:', currentModal.value);
|
||||
//打开弹窗
|
||||
modalMethod.openModal(true, modalParams.value);
|
||||
//设置缓存标识
|
||||
modalRegCache.value[currentModal.value!].isRegister = true;
|
||||
};
|
||||
}
|
||||
//*********************************打开弹窗修改,动态设置弹窗end******************************************
|
||||
//***********************打开弹窗的业务逻辑处理*********************************************************
|
||||
const { getTaskNodeInfo } = useMyRunningTaskList('run');
|
||||
/**
|
||||
* 打开表单
|
||||
*/
|
||||
function openDesformModal(mode, record, title) {
|
||||
let desform = record,
|
||||
dataId = null;
|
||||
if (mode === 'edit' || mode === 'detail') {
|
||||
let { desformId: id, desformCode, desformDataId } = record;
|
||||
dataId = desformDataId;
|
||||
desform = { id, desformCode };
|
||||
}
|
||||
queryByCode({ desformCode: desform.desformCode }).then((res) => {
|
||||
if (res.success) {
|
||||
const designJson = res.result.desformDesignJson;
|
||||
const json = JSON.parse(designJson);
|
||||
if (json.config.dialogOptions) {
|
||||
bindParams.value = { dialogOptions: json.config.dialogOptions };
|
||||
}
|
||||
desformRef.value.open(mode, desform, dataId, title);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 添加我的申请表单流程
|
||||
*/
|
||||
function handleDesformDataAdded(event) {
|
||||
const flowCodePre = 'desform_';
|
||||
// 将流程保存至后台
|
||||
let { desform, dataId } = event;
|
||||
save({
|
||||
desformId: desform.id,
|
||||
desformCode: desform.desformCode,
|
||||
desformDataId: dataId,
|
||||
desformName: desform.desformName,
|
||||
processName: desform.procName,
|
||||
flowCode: `${flowCodePre}${desform.desformCode}`,
|
||||
titleExp: desform.titleExp,
|
||||
}).then((res) => {
|
||||
if (!res.success) {
|
||||
createMessage.error(res.message);
|
||||
return;
|
||||
}
|
||||
push({ path: '/oaOffice/myOrder' });
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 邮箱回复
|
||||
* @param record
|
||||
*/
|
||||
function handReply(record) {
|
||||
//跳转到邮箱
|
||||
push({ name: 'eoa-email', params: { type: 'process', rec: JSON.stringify(record.value) } });
|
||||
}
|
||||
watch(
|
||||
() => currentRoute.value,
|
||||
(value) => {
|
||||
if (value?.meta?.frameSrc && value?.meta?.frameSrc.indexOf('/drag/view?pageId=') >= 0) {
|
||||
reloadPage();
|
||||
}
|
||||
}
|
||||
);
|
||||
//刷新页面
|
||||
function reloadPage() {
|
||||
const iframes: any = document.getElementsByClassName('jeecg-iframe-page__main');
|
||||
// 将 HTMLCollection 转换为数组
|
||||
const iframeArray = Array.from(iframes);
|
||||
if (currentRoute.value?.meta?.frameSrc && currentRoute.value?.meta?.frameSrc.indexOf('/drag/view?pageId=') >= 0) {
|
||||
const targetIframe: any = iframeArray.find((iframe: any) => iframe.src == currentRoute.value?.meta?.frameSrc);
|
||||
console.log('targetIframe', targetIframe);
|
||||
if (targetIframe) {
|
||||
targetIframe.contentWindow.postMessage({ reload: true }, '*');
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
initDragWebSocket: initWebSocket,
|
||||
handleOpenType,
|
||||
currentModal,
|
||||
modalParams,
|
||||
modalRegCache,
|
||||
bindParams,
|
||||
taskDealRef,
|
||||
desformRef,
|
||||
handleDesformDataAdded,
|
||||
handReply,
|
||||
reloadPage,
|
||||
};
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div :style="getPlaceholderDomStyle" v-if="getIsShowPlaceholderDom"></div>
|
||||
<div :style="getWrapStyle" :class="getClass">
|
||||
<LayoutHeader v-if="getShowInsetHeaderRef" />
|
||||
<LayoutHeader v-if="getShowHeader" />
|
||||
<MultipleTabs v-if="getShowTabs" />
|
||||
</div>
|
||||
</template>
|
||||
|
@ -11,6 +11,8 @@
|
|||
import LayoutHeader from './index.vue';
|
||||
import MultipleTabs from '../tabs/index.vue';
|
||||
|
||||
import { useAppStore } from "@/store/modules/app";
|
||||
import { useGlobSetting } from "/@/hooks/setting";
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useFullContent } from '/@/hooks/web/useFullContent';
|
||||
|
@ -19,6 +21,7 @@
|
|||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { useLayoutHeight } from '../content/useContentViewHeight';
|
||||
import { TabsThemeEnum } from '/@/enums/appEnum';
|
||||
|
||||
// update-begin--author:liaozhiyang---date:20240407---for:【QQYUN-8774】网站header区域加高
|
||||
const HEADER_HEIGHT = 60;
|
||||
// update-begin--author:liaozhiyang---date:20240407---for:【【QQYUN-8774】网站header区域加高
|
||||
|
@ -35,15 +38,30 @@
|
|||
const { setHeaderHeight } = useLayoutHeight();
|
||||
const { prefixCls } = useDesign('layout-multiple-header');
|
||||
|
||||
const appStore = useAppStore()
|
||||
const glob = useGlobSetting()
|
||||
|
||||
const { getCalcContentWidth, getSplit } = useMenuSetting();
|
||||
const { getIsMobile } = useAppInject();
|
||||
const { getFixed, getShowInsetHeaderRef, getShowFullHeaderRef, getHeaderTheme, getShowHeader } = useHeaderSetting();
|
||||
const { getFixed, getShowInsetHeaderRef, getShowFullHeaderRef, getHeaderTheme } = useHeaderSetting();
|
||||
|
||||
const { getFullContent } = useFullContent();
|
||||
|
||||
const { getShowMultipleTab, getTabsTheme } = useMultipleTabSetting();
|
||||
|
||||
const getShowHeader = computed(() => {
|
||||
// 控制是否显示顶部
|
||||
if (appStore.mainAppProps.hideHeader) {
|
||||
return false;
|
||||
}
|
||||
return unref(getShowInsetHeaderRef);
|
||||
})
|
||||
|
||||
const getShowTabs = computed(() => {
|
||||
// 控制是否显示多Tabs切换
|
||||
if (appStore.mainAppProps.hideMultiTabs) {
|
||||
return false;
|
||||
}
|
||||
return unref(getShowMultipleTab) && !unref(getFullContent);
|
||||
});
|
||||
|
||||
|
@ -53,7 +71,7 @@
|
|||
|
||||
const getWrapStyle = computed((): CSSProperties => {
|
||||
const style: CSSProperties = {};
|
||||
if (unref(getFixed)) {
|
||||
if (unref(getFixed) && !glob.isQiankunMicro) {
|
||||
style.width = unref(getIsMobile) ? '100%' : unref(getCalcContentWidth);
|
||||
}
|
||||
if (unref(getShowFullHeaderRef)) {
|
||||
|
@ -83,7 +101,7 @@
|
|||
if ((unref(getShowFullHeaderRef) || !unref(getSplit)) && unref(getShowHeader) && !unref(getFullContent)) {
|
||||
height += HEADER_HEIGHT;
|
||||
}
|
||||
if (unref(getShowMultipleTab) && !unref(getFullContent)) {
|
||||
if (unref(getShowTabs) && !unref(getFullContent)) {
|
||||
height += unref(getTabsThemeHeight);
|
||||
}
|
||||
setHeaderHeight(height);
|
||||
|
@ -93,10 +111,15 @@
|
|||
});
|
||||
|
||||
const getClass = computed(() => {
|
||||
return [prefixCls, `${prefixCls}--${unref(getHeaderTheme)}`, { [`${prefixCls}--fixed`]: unref(getIsFixed) }];
|
||||
return [prefixCls, `${prefixCls}--${unref(getHeaderTheme)}`, {
|
||||
[`${prefixCls}--fixed`]: unref(getIsFixed),
|
||||
// 【JEECG作为乾坤子应用】
|
||||
[`${prefixCls}--qiankun-micro`]: glob.isQiankunMicro,
|
||||
}];
|
||||
});
|
||||
|
||||
return {
|
||||
glob,
|
||||
getClass,
|
||||
prefixCls,
|
||||
getPlaceholderDomStyle,
|
||||
|
@ -104,7 +127,7 @@
|
|||
getWrapStyle,
|
||||
getIsShowPlaceholderDom,
|
||||
getShowTabs,
|
||||
getShowInsetHeaderRef,
|
||||
getShowHeader,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@ -126,5 +149,11 @@
|
|||
z-index: @multiple-tab-fixed-z-index;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// 【JEECG作为乾坤子应用】
|
||||
&--qiankun-micro {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
import { ScrollContainer } from '/@/components/Container';
|
||||
|
||||
import { useGo } from '/@/hooks/web/usePage';
|
||||
import { useGlobSetting } from "/@/hooks/setting";
|
||||
import { useSplitMenu } from './useLayoutMenu';
|
||||
import { openWindow } from '/@/utils';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
|
@ -56,6 +57,8 @@
|
|||
|
||||
const { prefixCls } = useDesign('layout-menu');
|
||||
|
||||
const glob = useGlobSetting()
|
||||
|
||||
const { menusRef } = useSplitMenu(toRef(props, 'splitType'));
|
||||
|
||||
const { getIsMobile } = useAppInject();
|
||||
|
@ -67,6 +70,11 @@
|
|||
const getIsShowLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType));
|
||||
|
||||
const getUseScroll = computed(() => {
|
||||
// 【JEECG作为乾坤子应用】在乾坤子应用下,菜单不固定
|
||||
if (glob.isQiankunMicro) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
!unref(getIsHorizontal) &&
|
||||
(unref(getIsSidebarType) || props.splitType === MenuSplitTyeEnum.LEFT || props.splitType === MenuSplitTyeEnum.NONE)
|
||||
|
|
|
@ -30,12 +30,15 @@
|
|||
|
||||
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
||||
|
||||
import { useAppStore } from "@/store/modules/app";
|
||||
import { useGlobSetting } from "/@/hooks/setting";
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useTrigger, useDragLine, useSiderEvent } from './useLayoutSider';
|
||||
import { useAppInject } from '/@/hooks/web/useAppInject';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
|
||||
import DragBar from './DragBar.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutSideBar',
|
||||
components: { Sider: Layout.Sider, LayoutMenu, DragBar, LayoutTrigger },
|
||||
|
@ -48,6 +51,9 @@
|
|||
|
||||
const { prefixCls } = useDesign('layout-sideBar');
|
||||
|
||||
const glob = useGlobSetting()
|
||||
const appStore = useAppStore()
|
||||
|
||||
const { getIsMobile } = useAppInject();
|
||||
|
||||
const { getTriggerAttr, getShowTrigger } = useTrigger(getIsMobile);
|
||||
|
@ -65,6 +71,10 @@
|
|||
});
|
||||
|
||||
const showClassSideBarRef = computed(() => {
|
||||
// 控制是否显示侧边栏
|
||||
if (appStore.mainAppProps.hideSider) {
|
||||
return false;
|
||||
}
|
||||
return unref(getSplit) ? !unref(getMenuHidden) : true;
|
||||
});
|
||||
|
||||
|
@ -74,6 +84,8 @@
|
|||
{
|
||||
[`${prefixCls}--fixed`]: unref(getMenuFixed),
|
||||
[`${prefixCls}--mix`]: unref(getIsMixMode) && !unref(getIsMobile),
|
||||
// 【JEECG作为乾坤子应用】
|
||||
[`${prefixCls}--qiankun-micro`]: glob.isQiankunMicro,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
@ -131,6 +143,11 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
// 【JEECG作为乾坤子应用】
|
||||
&--qiankun-micro {
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
&--mix {
|
||||
top: @header-height;
|
||||
height: calc(100% - @header-height);
|
||||
|
|
|
@ -145,7 +145,9 @@ html[data-theme='light'] {
|
|||
}
|
||||
|
||||
.ant-tabs-extra-content {
|
||||
margin-top: 2px;
|
||||
// update-begin--author:liaozhiyang---date:20241016---for:【issues/7345】标签样式切换到极简模式样式错乱
|
||||
// margin-top: 2px;
|
||||
// update-end--author:liaozhiyang---date:20241016---for:【issues/7345】标签样式切换到极简模式样式错乱
|
||||
line-height: @multiple-height !important;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,18 +19,20 @@
|
|||
</template>
|
||||
|
||||
<template #rightExtra v-if="getShowRedo || getShowQuick">
|
||||
<TabRedo v-if="getShowRedo" />
|
||||
<!-- <TabContent isExtra :tabItem="$route" v-if="getShowQuick" /> -->
|
||||
<!-- 列表页全屏
|
||||
<FoldButton v-if="getShowFold" />-->
|
||||
<!-- <FullscreenOutlined /> -->
|
||||
<router-link to="/ai" class="ai-icon">
|
||||
<a-tooltip title="AI助手" placement="left">
|
||||
<svg t="1706259688149" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2056" width="17" height="17">
|
||||
<path d="M826.368 325.632c0-7.168 2.048-10.24 10.24-10.24h123.904c7.168 0 10.24 2.048 10.24 10.24v621.568c0 7.168-2.048 10.24-10.24 10.24h-122.88c-8.192 0-10.24-4.096-10.24-10.24l-1.024-621.568z m-8.192-178.176c0-50.176 35.84-79.872 79.872-79.872 48.128 0 79.872 32.768 79.872 79.872 0 52.224-33.792 79.872-81.92 79.872-46.08 1.024-77.824-27.648-77.824-79.872zM462.848 584.704C441.344 497.664 389.12 307.2 368.64 215.04h-2.048c-16.384 92.16-58.368 247.808-92.16 369.664h188.416zM243.712 712.704l-62.464 236.544c-2.048 7.168-4.096 8.192-12.288 8.192H54.272c-8.192 0-10.24-2.048-8.192-12.288l224.256-783.36c4.096-13.312 7.168-26.624 8.192-65.536 0-6.144 2.048-8.192 7.168-8.192H450.56c6.144 0 8.192 2.048 10.24 8.192l250.88 849.92c2.048 7.168 0 10.24-7.168 10.24H573.44c-7.168 0-10.24-2.048-12.288-7.168l-65.536-236.544c1.024 1.024-251.904 0-251.904 0z" fill="#333333" p-id="19816"></path>
|
||||
</svg>
|
||||
</a-tooltip>
|
||||
</router-link>
|
||||
<div class="rightExtra">
|
||||
<TabRedo v-if="getShowRedo" />
|
||||
<!-- <TabContent isExtra :tabItem="$route" v-if="getShowQuick" /> -->
|
||||
<!-- 列表页全屏
|
||||
<FoldButton v-if="getShowFold" />-->
|
||||
<!-- <FullscreenOutlined /> -->
|
||||
<router-link to="/ai" class="ai-icon">
|
||||
<a-tooltip title="AI助手" placement="left">
|
||||
<svg t="1706259688149" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2056" width="17" height="17">
|
||||
<path d="M826.368 325.632c0-7.168 2.048-10.24 10.24-10.24h123.904c7.168 0 10.24 2.048 10.24 10.24v621.568c0 7.168-2.048 10.24-10.24 10.24h-122.88c-8.192 0-10.24-4.096-10.24-10.24l-1.024-621.568z m-8.192-178.176c0-50.176 35.84-79.872 79.872-79.872 48.128 0 79.872 32.768 79.872 79.872 0 52.224-33.792 79.872-81.92 79.872-46.08 1.024-77.824-27.648-77.824-79.872zM462.848 584.704C441.344 497.664 389.12 307.2 368.64 215.04h-2.048c-16.384 92.16-58.368 247.808-92.16 369.664h188.416zM243.712 712.704l-62.464 236.544c-2.048 7.168-4.096 8.192-12.288 8.192H54.272c-8.192 0-10.24-2.048-8.192-12.288l224.256-783.36c4.096-13.312 7.168-26.624 8.192-65.536 0-6.144 2.048-8.192 7.168-8.192H450.56c6.144 0 8.192 2.048 10.24 8.192l250.88 849.92c2.048 7.168 0 10.24-7.168 10.24H573.44c-7.168 0-10.24-2.048-12.288-7.168l-65.536-236.544c1.024 1.024-251.904 0-251.904 0z" fill="#333333" p-id="19816"></path>
|
||||
</svg>
|
||||
</a-tooltip>
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
</Tabs>
|
||||
</div>
|
||||
|
@ -162,16 +164,25 @@
|
|||
:deep(.anticon) {
|
||||
display: inline-block;
|
||||
}
|
||||
.ai-icon{
|
||||
float: right;
|
||||
margin-top: 3px;
|
||||
cursor: pointer;
|
||||
width: 36px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
color: @text-color;
|
||||
text-align: center;
|
||||
border-left: 1px solid @border-color-base;
|
||||
// update-begin--author:liaozhiyang---date:20241016---for:【issues/7345】标签样式切换到极简模式样式错乱
|
||||
.rightExtra {
|
||||
display: flex;
|
||||
:deep(svg) {
|
||||
&:not(.icon) {
|
||||
vertical-align: -0.3em;
|
||||
}
|
||||
}
|
||||
.ai-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
width: 36px;
|
||||
color: @text-color;
|
||||
text-align: center;
|
||||
border-left: 1px solid @border-color-base;
|
||||
}
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20241016---for:【issues/7345】标签样式切换到极简模式样式错乱
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import type { MainAppProps } from "#/main";
|
||||
import 'uno.css';
|
||||
import '/@/design/index.less';
|
||||
import 'ant-design-vue/dist/reset.css';
|
||||
|
@ -8,7 +9,7 @@ import App from './App.vue';
|
|||
import { createApp } from 'vue';
|
||||
import { initAppConfigStore } from '/@/logics/initAppConfig';
|
||||
import { setupErrorHandle } from '/@/logics/error-handle';
|
||||
import { router, setupRouter } from '/@/router';
|
||||
import { router, createRouter, setupRouter } from '/@/router';
|
||||
import { setupRouterGuard } from '/@/router/guard';
|
||||
import { setupStore } from '/@/store';
|
||||
import { setupGlobDirectives } from '/@/directives';
|
||||
|
@ -16,20 +17,47 @@ import { setupI18n } from '/@/locales/setupI18n';
|
|||
import { registerGlobComp } from '/@/components/registerGlobComp';
|
||||
import { registerThirdComp } from '/@/settings/registerThirdComp';
|
||||
import { useSso } from '/@/hooks/web/useSso';
|
||||
import { checkIsQiankunMicro } from "/@/qiankun/micro";
|
||||
import { autoUseQiankunMicro } from "/@/qiankun/micro/qiankunMicro";
|
||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||
|
||||
// 注册online模块lib
|
||||
import { registerPackages } from '/@/utils/monorepo/registerPackages';
|
||||
|
||||
async function bootstrap() {
|
||||
// 程序入口
|
||||
async function main() {
|
||||
if (checkIsQiankunMicro()) {
|
||||
// 【JEECG作为乾坤子应用】以乾坤子应用模式启动
|
||||
// await autoUseQiankunMicro(bootstrap)
|
||||
await autoUseQiankunMicro(bootstrap)
|
||||
} else {
|
||||
// 获取参数
|
||||
const props = getMainAppProps();
|
||||
// 普通启动
|
||||
await bootstrap(props)
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
async function bootstrap(props?: MainAppProps) {
|
||||
// 创建应用实例
|
||||
const app = createApp(App);
|
||||
// 【QQYUN-6329】
|
||||
window.appRootInstance = app;
|
||||
// 多语言配置,异步情况:语言文件可以从服务器端获得
|
||||
await setupI18n(app);
|
||||
window['JAppRootInstance'] = app;
|
||||
|
||||
// 创建路由
|
||||
createRouter();
|
||||
|
||||
// 配置存储
|
||||
setupStore(app);
|
||||
|
||||
// 配置参数
|
||||
setupProps(props);
|
||||
|
||||
// 多语言配置,异步情况:语言文件可以从服务器端获得
|
||||
await setupI18n(app);
|
||||
|
||||
// 初始化内部系统配置
|
||||
initAppConfigStore();
|
||||
|
||||
|
@ -61,9 +89,45 @@ async function bootstrap() {
|
|||
await router.isReady();
|
||||
|
||||
// 挂载应用
|
||||
app.mount('#app', true);
|
||||
app.mount(getMountContainer(props), true);
|
||||
|
||||
console.log(" vue3 app 加载完成!")
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
bootstrap();
|
||||
// 获取应用挂载容器
|
||||
function getMountContainer(props?: MainAppProps) {
|
||||
const id = '#app';
|
||||
if (!props?.container?.querySelector) {
|
||||
return id;
|
||||
}
|
||||
return props.container.querySelector(id) ?? id;
|
||||
}
|
||||
|
||||
// 获取主应用参数
|
||||
function getMainAppProps(): MainAppProps {
|
||||
// 从 queryString 中获取
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
// 隐藏侧边栏(菜单)
|
||||
let hideSider = searchParams.get('hideSider') === 'true';
|
||||
// 隐藏顶部
|
||||
let hideHeader = searchParams.get('hideHeader') === 'true';
|
||||
// 隐藏 多Tab 切换
|
||||
let hideMultiTabs = searchParams.get('hideMultiTabs') === 'true';
|
||||
|
||||
return {
|
||||
hideSider,
|
||||
hideHeader,
|
||||
hideMultiTabs
|
||||
}
|
||||
}
|
||||
|
||||
// 配置主应用参数
|
||||
function setupProps(props?: MainAppProps) {
|
||||
if (!props) {
|
||||
return
|
||||
}
|
||||
const appStore = useAppStoreWithOut();
|
||||
appStore.setMainAppProps(props);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import {qiankunWindow} from 'vite-plugin-qiankun/dist/helper'
|
||||
|
||||
/**
|
||||
* 【JEECG作为乾坤子应用】【判断当前是否是以乾坤子应用的模式运行】
|
||||
*/
|
||||
export function checkIsQiankunMicro(): boolean {
|
||||
return !!qiankunWindow.__POWERED_BY_QIANKUN__;
|
||||
}
|
||||
|
||||
export function getGlobal() {
|
||||
return (checkIsQiankunMicro() ? qiankunWindow : window) as Window
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 【JEECG作为乾坤子应用】
|
||||
*/
|
||||
import type {App} from 'vue';
|
||||
import type {MainAppProps} from "#/main";
|
||||
|
||||
import {destroyStore} from "@/store";
|
||||
import {destroyRouter} from "@/router";
|
||||
import {clearComponent} from "@/components/jeecg/JVxeTable/src/componentMap";
|
||||
|
||||
import {renderWithQiankun} from 'vite-plugin-qiankun/dist/helper';
|
||||
|
||||
/**
|
||||
* 以乾坤子应用模式运行
|
||||
* @param render
|
||||
*/
|
||||
export async function useQiankunMicroApp(render: (props?: MainAppProps) => Promise<App>) {
|
||||
let instance: Nullable<App> = null;
|
||||
|
||||
// 注册乾坤子应用生命周期函数
|
||||
renderWithQiankun({
|
||||
async mount(props) {
|
||||
console.debug('[qiankun-micro] mount - props :', props)
|
||||
instance = await render({
|
||||
container: props.container!,
|
||||
hideSider: props.hideSider,
|
||||
hideHeader: props.hideHeader,
|
||||
hideMultiTabs: props.hideMultiTabs,
|
||||
});
|
||||
},
|
||||
bootstrap() {
|
||||
console.debug('[qiankun-micro] bootstrap');
|
||||
},
|
||||
update(props) {
|
||||
console.debug('[qiankun-micro] update: ', props);
|
||||
},
|
||||
unmount(props) {
|
||||
console.debug('[qiankun-micro] unmount: ', props);
|
||||
|
||||
destroyStore();
|
||||
destroyRouter();
|
||||
|
||||
if (instance) {
|
||||
clearComponent();
|
||||
instance.unmount();
|
||||
instance._container.innerHTML = '';
|
||||
instance = null;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return instance!
|
||||
}
|
||||
|
||||
export async function autoUseQiankunMicro(fn: Fn) {
|
||||
return useQiankunMicroApp(fn)
|
||||
}
|
|
@ -9,7 +9,7 @@ import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
|
|||
|
||||
import { RootRoute } from '/@/router/routes';
|
||||
|
||||
import { isOAuth2AppEnv } from '/@/views/sys/login/useLogin';
|
||||
import {isOAuth2AppEnv, isOAuth2DingAppEnv} from '/@/views/sys/login/useLogin';
|
||||
import { OAUTH2_THIRD_LOGIN_TENANT_ID } from "/@/enums/cacheEnum";
|
||||
import { setAuthCache } from "/@/utils/auth";
|
||||
import { PAGE_NOT_FOUND_NAME_404 } from '/@/router/constant';
|
||||
|
@ -159,7 +159,13 @@ export function createPermissionGuard(router: Router) {
|
|||
//==============================【首次登录并且是企业微信或者钉钉的情况下才会调用】==================
|
||||
//判断是免登录页面,如果页面包含/tenantId/,那么就直接前往主页
|
||||
if(isOAuth2AppEnv() && to.path.indexOf("/tenantId/") != -1){
|
||||
next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
|
||||
//update-begin---author:wangshuai---date:2024-11-08---for:【TV360X-2958】钉钉登录后打开了敲敲云,换其他账号登录后,再打开敲敲云显示的是原来账号的应用---
|
||||
if (isOAuth2DingAppEnv()) {
|
||||
next(OAUTH2_LOGIN_PAGE_PATH);
|
||||
} else {
|
||||
next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
|
||||
}
|
||||
//update-end---author:wangshuai---date:2024-11-08---for:【TV360X-2958】钉钉登录后打开了敲敲云,换其他账号登录后,再打开敲敲云显示的是原来账号的应用---
|
||||
return;
|
||||
}
|
||||
//==============================【首次登录并且是企业微信或者钉钉的情况下才会调用】==================
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
import type { App } from 'vue';
|
||||
|
||||
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router';
|
||||
import { basicRoutes } from './routes';
|
||||
import {createRouter as createVueRouter, destroyRouter, router} from './router'
|
||||
|
||||
// 白名单应该包含基本静态路由
|
||||
const WHITE_NAME_LIST: string[] = [];
|
||||
|
@ -13,22 +13,26 @@ const getRouteNames = (array: any[]) =>
|
|||
});
|
||||
getRouteNames(basicRoutes);
|
||||
|
||||
// app router
|
||||
export const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.VITE_PUBLIC_PATH),
|
||||
routes: basicRoutes as unknown as RouteRecordRaw[],
|
||||
strict: true,
|
||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
||||
});
|
||||
/**
|
||||
* 创建路由实例
|
||||
*/
|
||||
export function createRouter() {
|
||||
let router = createVueRouter({
|
||||
routes: basicRoutes as unknown as RouteRecordRaw[],
|
||||
strict: true,
|
||||
scrollBehavior: () => ({left: 0, top: 0}),
|
||||
})
|
||||
|
||||
// TODO 【QQYUN-4517】【表单设计器】记录分享路由守卫测试
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
//console.group('【QQYUN-4517】beforeEach');
|
||||
//console.warn('from', from);
|
||||
//console.warn('to', to);
|
||||
//console.groupEnd();
|
||||
next();
|
||||
});
|
||||
// TODO 【QQYUN-4517】【表单设计器】记录分享路由守卫测试
|
||||
// @ts-ignore
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
//console.group('【QQYUN-4517】beforeEach');
|
||||
//console.warn('from', from);
|
||||
//console.warn('to', to);
|
||||
//console.groupEnd();
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
// reset router
|
||||
export function resetRouter() {
|
||||
|
@ -44,3 +48,8 @@ export function resetRouter() {
|
|||
export function setupRouter(app: App<Element>) {
|
||||
app.use(router);
|
||||
}
|
||||
|
||||
export {
|
||||
router,
|
||||
destroyRouter,
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 路由实例存储文件,请勿轻易添加其他代码,防止出现 HMR 或其他问题
|
||||
*/
|
||||
import type {Router, RouterHistory} from 'vue-router';
|
||||
import {createRouter as createVueRouter, createWebHistory, RouterOptions} from 'vue-router';
|
||||
|
||||
export let router: Router = null as unknown as Router;
|
||||
|
||||
export function setRouter(r: Router) {
|
||||
router = r
|
||||
}
|
||||
|
||||
let webHistory: Nullable<RouterHistory> = null;
|
||||
|
||||
/**
|
||||
* 创建路由
|
||||
* @param options 参数
|
||||
*/
|
||||
export function createRouter(options: Partial<RouterOptions>) {
|
||||
webHistory = createWebHistory(import.meta.env.VITE_PUBLIC_PATH);
|
||||
// app router
|
||||
let router = createVueRouter({
|
||||
history: webHistory,
|
||||
routes: [],
|
||||
...options,
|
||||
});
|
||||
|
||||
setRouter(router)
|
||||
|
||||
return router
|
||||
}
|
||||
|
||||
// 销毁路由
|
||||
export function destroyRouter() {
|
||||
setRouter(null as unknown as Router);
|
||||
if (webHistory) {
|
||||
webHistory.destroy();
|
||||
}
|
||||
webHistory = null
|
||||
}
|
|
@ -109,6 +109,10 @@ const setting: ProjectConfig = {
|
|||
type: MenuTypeEnum.SIDEBAR,
|
||||
// 菜单主题
|
||||
theme: ThemeEnum.DARK,
|
||||
// update-begin--author:liaozhiyang---date:20241203---for:【issues/7522】解决menuSetting ts警告
|
||||
// 左侧导航栏文字颜色调整区分彩色和暗黑 (不对应配置)
|
||||
isThemeBright: false,
|
||||
// update-end--author:liaozhiyang---date:20241203---for:【issues/7522】解决menuSetting ts警告
|
||||
// 分割菜单
|
||||
split: false,
|
||||
// 顶部菜单布局
|
||||
|
@ -146,7 +150,7 @@ const setting: ProjectConfig = {
|
|||
// 动画配置
|
||||
transitionSetting: {
|
||||
// 是否开启切换动画
|
||||
// The disabled state will also disable pageLoadinng
|
||||
// The disabled state will also disable pageLoading
|
||||
enable: true,
|
||||
|
||||
// 动画名 Route basic switching animation
|
||||
|
|
|
@ -1,9 +1,19 @@
|
|||
import type { App } from 'vue';
|
||||
import type { Pinia } from 'pinia';
|
||||
import { createPinia } from 'pinia';
|
||||
const store = createPinia();
|
||||
|
||||
let store: Nullable<Pinia> = null;
|
||||
|
||||
export function setupStore(app: App<Element>) {
|
||||
if (store == null) {
|
||||
store = createPinia();
|
||||
}
|
||||
app.use(store);
|
||||
}
|
||||
|
||||
// 销毁store
|
||||
export function destroyStore() {
|
||||
store = null;
|
||||
}
|
||||
|
||||
export { store };
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue