Browse Source

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

4.0
yaoq 2 years ago
parent
commit
0710dffb07
42 changed files with 2636 additions and 99 deletions
  1. +2
    -2
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileDownloadController.java
  2. +4
    -0
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/common/BpmConst.java
  3. +2
    -0
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/common/BpmEnum.java
  4. +117
    -62
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/engine/dynPage/DynPageHelper.java
  5. +2
    -0
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/engine/model/common/FlowModelService.java
  6. +1
    -0
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/engine/model/flow/listcard/lclc1/FlowLcLc1Service.java
  7. +1
    -0
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/engine/model/flow/listcard/lcms/FlowLcMsService.java
  8. +1
    -0
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/login/AuthService.java
  9. +9
    -3
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/AbsTreeDataRightHandler.java
  10. +20
    -0
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/DataRightGroup.java
  11. +5
    -0
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/DataRightGroupItem.java
  12. +30
    -2
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/DataRightHelper.java
  13. +1
    -1
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/IDataRightHandler.java
  14. +9
    -1
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/IDataRightTreeFactory.java
  15. +229
    -4
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/impl/PartyDataRightHandler.java
  16. +0
    -1
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/menuPlan/MenuPlanCache.java
  17. +21
    -0
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/menuPlan/MenuPlanHelper.java
  18. +45
    -0
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/menuPlan/MenuPlanItemProvider.java
  19. +55
    -3
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/role/RoleHelper.java
  20. +21
    -0
      smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/role/RoleRightContent.java
  21. +15
    -1
      smtweb-framework/bpm/src/main/resources/static/template/default/incModel/inc_card_fields_only.ftl
  22. +17
    -3
      smtweb-framework/bpm/src/main/resources/static/template/default/incModel/inc_list_dialog.ftl
  23. +15
    -1
      smtweb-framework/bpm/src/main/resources/static/template/default/incModel/inc_list_query.ftl
  24. +17
    -3
      smtweb-framework/bpm/src/main/resources/static/template/default/incModel/inc_query_sfilters.ftl
  25. +30
    -2
      smtweb-framework/bpm/src/main/resources/static/template/default/model_card_flow.ftl
  26. +15
    -1
      smtweb-framework/bpm/src/main/resources/static/template/default/model_card_ms.ftl
  27. +15
    -1
      smtweb-framework/bpm/src/main/resources/static/template/default/model_card_normal.ftl
  28. +15
    -1
      smtweb-framework/bpm/src/main/resources/static/template/default/model_list_card.ftl
  29. +10
    -0
      smtweb-framework/core/pom.xml
  30. +2
    -0
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/common/SwConsts.java
  31. +1
    -0
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/common/SwEnum.java
  32. +21
    -1
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/binder/body/SwMapBodyEditor.java
  33. +8
    -0
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/service/AbstractListHandler.java
  34. +15
    -1
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/service/TreeHelper.java
  35. +0
    -1
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/session/SessionUtil.java
  36. +1081
    -0
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/ExcelExportUtil.java
  37. +131
    -0
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/ExcelUtil.java
  38. +54
    -0
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/ExportUtil.java
  39. +19
    -0
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/FileUtil.java
  40. +24
    -4
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/HttpUtil.java
  41. +507
    -0
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/MathUtil.java
  42. +49
    -0
      smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/StringUtil.java

+ 2
- 2
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/spring/controller/FileDownloadController.java View File

@@ -41,7 +41,7 @@ public class FileDownloadController {
@RequestParam(value = "absolutePath", required = false) Boolean absolutePath,
HttpServletRequest request
) throws FileNotFoundException {
String filePath = request.getRequestURI().substring(10);
String filePath = request.getServletPath().substring(10);
return download(filePath, name, noCache,absolutePath, request);
}

@@ -91,7 +91,7 @@ public class FileDownloadController {
@RequestParam(value = "noCache", required = false) Boolean noCache,
@RequestHeader(value = "If-Modified-Since", required = false) String ifModifiedSince,
HttpServletRequest request) throws FileNotFoundException {
String filePath = request.getRequestURI().substring(11);
String filePath = request.getServletPath().substring(11);

HttpHeaders headers = new HttpHeaders();



+ 4
- 0
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/common/BpmConst.java View File

@@ -12,5 +12,9 @@ public interface BpmConst {
interface DataRight {
public final static Long CUR_VALUE = 999L;//本机构,本部门
public final static Long ALL_DEPT = 998L;//全部门权限
public final static int V_SELF = 0;//本级
public final static int V_INCLUDE_CHILDREN = 1;//含下级
public final static int V_INCLUDE = 0;//包含
public final static int V_EXCEPT = 1;//排除
}
}

+ 2
- 0
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/common/BpmEnum.java View File

@@ -29,6 +29,8 @@ public interface BpmEnum {
public static MenuFuncRight instance = new MenuFuncRight();
public static StrEnumBean READ = instance.addEnum("read", "查看");
public static StrEnumBean WRITE = instance.addEnum("write", "修改");
public static StrEnumBean EXPORT = instance.addEnum("export", "导出");
public static StrEnumBean AUDIT = instance.addEnum("audit", "审核");
}

class UserStatu extends IntEnum {


+ 117
- 62
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/engine/dynPage/DynPageHelper.java View File

@@ -12,11 +12,17 @@ import cc.smtweb.framework.core.db.vo.ModelTable;
import cc.smtweb.framework.core.exception.BizException;
import cc.smtweb.framework.core.exception.SwException;
import cc.smtweb.framework.core.mvc.service.SqlNamedPara;
import cc.smtweb.framework.core.mvc.service.TreeHelper;
import cc.smtweb.framework.core.util.MapUtil;
import cc.smtweb.framework.core.util.NumberUtil;
import cc.smtweb.framework.core.util.SqlUtil;
import cc.smtweb.framework.core.util.StringUtil;
import cc.smtweb.system.bpm.web.design.form.define.*;
import cc.smtweb.system.bpm.web.sys.user.dataRight.DataRightDefine;
import cc.smtweb.system.bpm.web.sys.user.dataRight.DataRightDefineCache;
import cc.smtweb.system.bpm.web.sys.user.dataRightGroup.IDataRightHandler;
import cc.smtweb.system.bpm.web.sys.user.dataRightGroup.IDataRightTreeFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.NonNull;

@@ -31,6 +37,7 @@ import static cc.smtweb.framework.core.common.SwConsts.TOTAL_KEY;
* Created by Akmm at 2022/4/23 10:01
* 动态页面辅助类
*/
@Slf4j
public class DynPageHelper {
/**
* 新建bean
@@ -137,29 +144,50 @@ public class DynPageHelper {
buildSelectSql(dataSet, params, sqlNamedPara, null);
return sqlNamedPara;
}
private static Map<String, IBuilderExpr> mapBuilder;
private static IBuilderExpr baseBuilder;
static {
baseBuilder = (opt, field, name, value, args, filter) -> {
args.put(name, value);
return field + " " + opt + " :" + name;
};
mapBuilder = new HashMap<>();
mapBuilder.put(SwEnum.OptType.LIKE.value, (opt, field, name, value, args, filter) -> {
args.put(name, "%" + value + "%");
return field + " like :" + name;
});

/**
* 构建合计栏sql
*
* @param dataSet
* @param params
* @return
*/
public static SqlNamedPara buildSumSql(PageDataset dataSet, @NonNull SqlNamedPara sqlNamedPara) {
StringBuilder sql = new StringBuilder(256);
sql.append("select count(1) " + TOTAL_KEY);
for (PageDatasetField field : dataSet.fields) {
if (StringUtils.isEmpty(field.summary)) continue;
if (field.fieldIsCalc()) continue;
sql.append(",");
if (!SwEnum.SummaryType.instance.isText(field.summary)) {
sql.append(field.summary).append("(").append(field.name).append(") ").append(field.name);
} else {
sql.append("'").append(field.summary).append("' ").append(field.name);
mapBuilder.put(SwEnum.OptType.PLIKE.value, (opt, field, name, value, args, filter) -> {
args.put(name, value + "%");
return field + " like :" + name;
});

mapBuilder.put(SwEnum.OptType.BT.value, (opt, field, name, value, args, filter) -> {
String[] ss = value.toString().split(",");
if (ss.length != 2) throw new BizException("介于条件,参数值个数错误!");
args.put(name + "_1", ss[0]);
args.put(name + "_2", ss[1]);
return "(" + field + ">=:" + name + "_1 and " + field + "<=:" + name + "_2)";
});

mapBuilder.put(SwEnum.OptType.IN.value, (opt, field, name, value, args, filter) -> {
if (StringUtil.isEmpty(value.toString())) return "";
args.put(name, value);
return field + " in (:" + name + ") ";
});

mapBuilder.put(SwEnum.OptType.NOT_IN.value, (opt, field, name, value, args, filter) -> {
if (StringUtil.isEmpty(value.toString())) return "";
args.put(name, value);
return field + " not in (:" + name + ") ";
});
mapBuilder.put(SwEnum.OptType.IN_CHILD.value, (opt, field, name, value, args, filter) -> {
ModelTable table = ModelTableCache.getInstance().get(filter.link);
if(table==null){
return "";
}
}
sqlNamedPara.sql = sql.toString() + " from (" + sqlNamedPara.sql + ") xxxxa";
return sqlNamedPara;
return TreeHelper.getTreeHelper(table.getName()).buildLikeFrSql(Long.parseLong(value.toString()),field);
});
}

private static String buildSelFieldsSql(PageDataset dataSet, SqlNamedPara sqlNamedPara, IBuildSqlListener listener) {
@@ -189,6 +217,30 @@ public class DynPageHelper {
}

/**
* 构建合计栏sql
*
* @param dataSet
* @param sqlNamedPara
* @return
*/
public static SqlNamedPara buildSumSql(PageDataset dataSet, @NonNull SqlNamedPara sqlNamedPara) {
StringBuilder sql = new StringBuilder(256);
sql.append("select count(1) " + TOTAL_KEY);
for (PageDatasetField field : dataSet.fields) {
if (StringUtils.isEmpty(field.summary)) continue;
if (field.fieldIsCalc()) continue;
sql.append(",");
if (!SwEnum.SummaryType.instance.isText(field.summary)) {
sql.append(field.summary).append("(").append(field.name).append(") ").append(field.name);
} else {
sql.append("'").append(field.summary).append("' ").append(field.name);
}
}
sqlNamedPara.sql = sql.toString() + " from (" + sqlNamedPara.sql + ") xxxxa";
return sqlNamedPara;
}

/**
* 构建where条件:组合固定和动态条件
*
* @param dataSet
@@ -218,6 +270,12 @@ public class DynPageHelper {
args.put(s, MapUtil.readString(params, s, ""));
}
if (listener != null) listener.buildWhere(dataSet, sql, args);
// 设置固定条件数据权限
for (PageDatasetFilter filter : dataSet.filters) {
if(!setFixedFilter.contains(filter.name))break;
if(filter.dataRightType<=0L)break;
buildDataRight(filter.dataRightType,filter.sqlName,MapUtil.readString(params, filter.name, ""),sql,args);
}
return new SqlNamedPara(sql.toString(), args);
}

@@ -265,6 +323,11 @@ public class DynPageHelper {
value = params.get(filter.name);
}
if (value == null || StringUtils.isEmpty(value.toString())) {
if(filter.dataRightType>0L){
StringBuilder frSql = new StringBuilder();
buildDataRight(filter.dataRightType,filter.sqlName,value.toString(),frSql,args);
return frSql.toString();
}
if (filter.required) {
throw new BizException("过滤条件不能为空(" + filter.name + ")!");
}
@@ -272,9 +335,21 @@ public class DynPageHelper {
}
IBuilderExpr builder = getBuilder(dynCond.opt);
String ns = isNameSelf ? filter.name: filter.name + "_" + dynCond.hashCode();
return builder.build(dynCond.opt, filter.sqlName, ns, value, args);
String optWhere = builder.build(dynCond.opt, filter.sqlName, ns, value, args,filter);
// 添加数据权限
if(filter.dataRightType>0L){
StringBuilder frSql = new StringBuilder();
buildDataRight(filter.dataRightType,filter.sqlName,value.toString(),frSql,args);
if(frSql.length()>0){
if(StringUtil.isEmpty(optWhere)){
optWhere = frSql.toString();
}else {
optWhere+= " and "+ frSql.toString();
}
}
}
return optWhere;
}

/**
* 处理计算字段
*
@@ -289,44 +364,24 @@ public class DynPageHelper {
}
}

private static Map<String, IBuilderExpr> mapBuilder;
private static IBuilderExpr baseBuilder;

static {
baseBuilder = (opt, field, name, value, args) -> {
args.put(name, value);
return field + " " + opt + " :" + name;
};
mapBuilder = new HashMap<>();
mapBuilder.put(SwEnum.OptType.LIKE.value, (opt, field, name, value, args) -> {
args.put(name, "%" + value + "%");
return field + " like :" + name;
});

mapBuilder.put(SwEnum.OptType.PLIKE.value, (opt, field, name, value, args) -> {
args.put(name, value + "%");
return field + " like :" + name;
});

mapBuilder.put(SwEnum.OptType.BT.value, (opt, field, name, value, args) -> {
String[] ss = value.toString().split(",");
if (ss.length != 2) throw new BizException("介于条件,参数值个数错误!");
args.put(name + "_1", ss[0]);
args.put(name + "_2", ss[1]);
return "(" + field + ">=:" + name + "_1 and " + field + "<=:" + name + "_2)";
});

mapBuilder.put(SwEnum.OptType.IN.value, (opt, field, name, value, args) -> {
if (StringUtil.isEmpty(value.toString())) return "";
args.put(name, value);
return field + " in (:" + name + ") ";
});

mapBuilder.put(SwEnum.OptType.NOT_IN.value, (opt, field, name, value, args) -> {
if (StringUtil.isEmpty(value.toString())) return "";
args.put(name, value);
return field + " not in (:" + name + ") ";
});
/**
* 构建数据权限
* @param dsType 数据权限定义ID
* @param sqlField sql字段名
* @param value 值
* @param sql sql语句
* @param args 参数
*/
private static void buildDataRight(long dsType,String sqlField,String value,StringBuilder sql,SwMap args){
DataRightDefine drd = DataRightDefineCache.getInstance().get(dsType);
if(drd==null){return;}
try{
IDataRightHandler dataRightHandler = IDataRightTreeFactory.getInstance().getHandler(drd.getCode());
dataRightHandler.buildSqlWhere(true,sqlField,value,sql,args);
}catch (Exception e){
log.error("加载数据权限失败:",e);
throw new SwException(e);
}
}

private static IBuilderExpr getBuilder(String opt) {
@@ -335,7 +390,7 @@ public class DynPageHelper {
}

interface IBuilderExpr {
String build(String opt, String field, String name, Object value, Map<String, Object> args);
String build(String opt, String field, String name, Object value, Map<String, Object> args,PageDatasetFilter filter);
}

}

+ 2
- 0
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/engine/model/common/FlowModelService.java View File

@@ -28,6 +28,8 @@ public class FlowModelService extends LCSingleService {
return new FlowModelSaveHandler<>();
case TYPE_MODEL_DEL:
return new FlowModelDelHandler();
case TYPE_FLOW:
return new FlowTransHandler();
}
return super.createHandler(type);
}


+ 1
- 0
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/engine/model/flow/listcard/lclc1/FlowLcLc1Service.java View File

@@ -25,6 +25,7 @@ public class FlowLcLc1Service extends FlowModelService {
case TYPE_MODEL_LOAD:
case TYPE_MODEL_SAVE:
case TYPE_MODEL_DEL:
case TYPE_FLOW:
return super.createHandler(type);
}
return worker.createHandler(type);


+ 1
- 0
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/engine/model/flow/listcard/lcms/FlowLcMsService.java View File

@@ -22,6 +22,7 @@ public class FlowLcMsService extends FlowModelService {
switch (type) {
case TYPE_MODEL_LIST:
case TYPE_MODEL_LOAD:
case TYPE_FLOW:
return super.createHandler(type);
case TYPE_MODEL_SAVE:
return new FlowLcMsSaveHandler();


+ 1
- 0
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/login/AuthService.java View File

@@ -61,6 +61,7 @@ public class AuthService {
User user = UserCache.getInstance().get(mappingUserRet.getUserId());
if(user==null){
data.put("isOk", false);
data.put("extra", mappingUserRet.getExtra());
data.put("msg", "映射登录失败!");
return R.success(data);
}


+ 9
- 3
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/AbsTreeDataRightHandler.java View File

@@ -1,5 +1,6 @@
package cc.smtweb.system.bpm.web.sys.user.dataRightGroup;

import cc.smtweb.framework.core.common.SwConsts;
import cc.smtweb.framework.core.common.SwMap;
import cc.smtweb.framework.core.session.UserSession;
import cc.smtweb.framework.core.util.StringUtil;
@@ -12,7 +13,7 @@ import java.util.Map;
* 数据权限计算处理抽象类
*/
public abstract class AbsTreeDataRightHandler implements IDataRightHandler{
protected final static String menuIdKey = "_menuId";
protected final static String KEY_HEADER_MENU = "hmk";
//权限查找结果常量定义
protected final static int RIGHT_RET_NONE = 0; //未找到
protected final static int RIGHT_RET_IN_CHILD = 1;//找到,包含,且含下级
@@ -35,11 +36,16 @@ public abstract class AbsTreeDataRightHandler implements IDataRightHandler{
}
@Override
public void init(UserSession us,SwMap params) {
this.isByRight = true;
this.us = us;
this.params = params;
String menuId = params.readString("_menuId");
// 获取header中的菜单ID
SwMap header = params.readMap(SwConsts.PARAMS_HEADER_KEY);
long menuId = 0L;
if(header!=null){
menuId = header.readLong(KEY_HEADER_MENU);
}
if (us == null) return;
this.isByRight = true;
mapRight = DataRightHelper.getDataRightItemMap(getDataRightType(), menuId, us);
if (mapRight == null) return;
//将本单位处理下


+ 20
- 0
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/DataRightGroup.java View File

@@ -2,6 +2,12 @@ package cc.smtweb.system.bpm.web.sys.user.dataRightGroup;

import cc.smtweb.framework.core.annotation.SwTable;
import cc.smtweb.framework.core.db.impl.DefaultEntity;
import cc.smtweb.framework.core.util.CommUtil;
import cc.smtweb.framework.core.util.JsonUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* Created by 1 at 2022-08-04 17:45:35
@@ -98,4 +104,18 @@ public class DataRightGroup extends DefaultEntity {
public void setSdrdId(long sdrg_sdrd_id) {
put("sdrg_sdrd_id", sdrg_sdrd_id);
}
// 获取权限明细集合
public List<DataRightGroupItem> getDataRightItemList(){
List<DataRightGroupItem> rtList = new ArrayList<>();
List<Map<String, Object>> listItem = data.readListMap("sdrg_content");
if(!CommUtil.isEmpty(listItem)){
listItem.forEach(map-> {
DataRightGroupItem item = JsonUtil.parse(map,DataRightGroupItem.class);
if(item!=null){
rtList.add(item);
}
});
}
return rtList;
}
}

+ 5
- 0
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/DataRightGroupItem.java View File

@@ -1,6 +1,7 @@
package cc.smtweb.system.bpm.web.sys.user.dataRightGroup;

import cc.smtweb.framework.core.db.impl.BaseBean;
import cc.smtweb.system.bpm.web.common.BpmConst;

/**
* @Author: tanghp
@@ -31,4 +32,8 @@ public class DataRightGroupItem extends BaseBean {
public void setType(int type) {
put("type",type);
}
// 包含
public boolean isInclude(){
return getKind() == BpmConst.DataRight.V_INCLUDE;
}
}

+ 30
- 2
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/DataRightHelper.java View File

@@ -1,8 +1,13 @@
package cc.smtweb.system.bpm.web.sys.user.dataRightGroup;

import cc.smtweb.framework.core.session.UserSession;
import cc.smtweb.system.bpm.web.common.BpmConst;
import cc.smtweb.system.bpm.web.sys.user.role.RoleHelper;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* @Author: tanghp
@@ -18,7 +23,30 @@ public class DataRightHelper {
* @param us 用户session
* @return
*/
public static Map<String,DataRightGroupItem> getDataRightItemMap(String dType, String menuId, UserSession us ){
return null;
public static Map<String,DataRightGroupItem> getDataRightItemMap(String dType, long menuId, UserSession us ){
Set<DataRightGroup> setGroup = RoleHelper.getDataRightGroup(us.getUserId(), us.getPartyId(), menuId,dType);
//以value作为key
Map<String, DataRightGroupItem> map = new HashMap<>();
for (DataRightGroup group : setGroup) {
List<DataRightGroupItem> items = group.getDataRightItemList();
for (DataRightGroupItem item : items) {
if (!map.containsKey(item.getValue())) {
map.put(item.getValue(), item);
}
DataRightGroupItem i = map.get(item.getValue());
if ((!i.isInclude() && item.isInclude()) || (i.isInclude() == item.isInclude() && item.getType() == BpmConst.DataRight.V_INCLUDE_CHILDREN)) {
map.put(item.getValue(), item);
}
}
}
// 如果没有配置数据权限,默认设置个本级及下级
if(map.size()==0){
DataRightGroupItem drgi = new DataRightGroupItem();
drgi.setKind(BpmConst.DataRight.V_INCLUDE);
drgi.setType(BpmConst.DataRight.V_INCLUDE_CHILDREN);
drgi.setValue(BpmConst.DataRight.CUR_VALUE.toString());
map.put(drgi.getValue(),drgi);
}
return map;
}
}

+ 1
- 1
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/IDataRightHandler.java View File

@@ -12,5 +12,5 @@ import java.util.List;
public interface IDataRightHandler {
void init(UserSession us,SwMap params);
//构建sql
boolean buildSqlWhere(boolean where, String sqlField, String value, StringBuilder sql, List<Object> args);
boolean buildSqlWhere(boolean where, String sqlField, String value, StringBuilder sql, SwMap args);
}

+ 9
- 1
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/IDataRightTreeFactory.java View File

@@ -3,6 +3,7 @@ package cc.smtweb.system.bpm.web.sys.user.dataRightGroup;
import cc.smtweb.framework.core.exception.SwException;
import cc.smtweb.system.bpm.web.common.BpmEnum;
import cc.smtweb.system.bpm.web.sys.user.dataRightGroup.impl.DeptDataRightTreeWork;
import cc.smtweb.system.bpm.web.sys.user.dataRightGroup.impl.PartyDataRightHandler;
import cc.smtweb.system.bpm.web.sys.user.dataRightGroup.impl.PartyDataRightTreeWork;

import java.util.HashMap;
@@ -27,11 +28,13 @@ public class IDataRightTreeFactory {
}

private Map<String, Class<? extends IDataRightTreeWorker>> mapWorks;
private Map<String, Class<? extends IDataRightHandler>> mapHandlers;

private IDataRightTreeFactory() {
mapWorks = new HashMap<>();
mapHandlers = new HashMap<>();
mapWorks.put(BpmEnum.DataRightType.PARTY.value, PartyDataRightTreeWork.class);
mapHandlers.put(BpmEnum.DataRightType.PARTY.value, PartyDataRightHandler.class);
mapWorks.put(BpmEnum.DataRightType.DEPT.value, DeptDataRightTreeWork.class);
}

@@ -40,4 +43,9 @@ public class IDataRightTreeFactory {
if (cls == null) throw new SwException("暂不支持[" + key + "]类型权限!");
return cls.newInstance();
}
public IDataRightHandler getHandler(String key) throws Exception {
Class<? extends IDataRightHandler> cls = mapHandlers.get(key);
if (cls == null) throw new SwException("暂不支持[" + key + "]类型权限!");
return cls.newInstance();
}
}

+ 229
- 4
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/dataRightGroup/impl/PartyDataRightHandler.java View File

@@ -1,13 +1,24 @@
package cc.smtweb.system.bpm.web.sys.user.dataRightGroup.impl;

import cc.smtweb.framework.core.common.SwConsts;
import cc.smtweb.framework.core.common.SwMap;
import cc.smtweb.framework.core.db.EntityHelper;
import cc.smtweb.framework.core.util.CommUtil;
import cc.smtweb.system.bpm.web.common.BpmConst;
import cc.smtweb.system.bpm.web.common.BpmEnum;
import cc.smtweb.system.bpm.web.sys.user.dataRightGroup.AbsTreeDataRightHandler;
import cc.smtweb.system.bpm.web.sys.user.dataRightGroup.DataRightGroupItem;
import cc.smtweb.system.bpm.web.sys.user.party.Party;
import cc.smtweb.system.bpm.web.sys.user.party.PartyCache;

import java.util.*;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

/**
* @Author: tanghp
* @Date: 2022-09-22 15:17
* @Desc:
* @Desc: 单位数据权限
*/
public class PartyDataRightHandler extends AbsTreeDataRightHandler {
@Override
@@ -18,11 +29,225 @@ public class PartyDataRightHandler extends AbsTreeDataRightHandler {

@Override
protected String getDataRightType() {
return "partyId";
return BpmEnum.DataRightType.PARTY.value;
}

@Override
public boolean buildSqlWhere(boolean where, String sqlField, String value, StringBuilder sql, List<Object> args) {
public boolean buildSqlWhere(boolean where, String sqlField, String value, StringBuilder sql, SwMap args) {
return false;
}
/**
* 根据菜单数据权限,找有权限的顶级机构列表
*
* @return
*/
public Set<Party> getTopList() {
if (!isByRight || mapRight == null) { //不控制权限,直接取吧
return PartyCache.getInstance().getChildren(SwConsts.DEF_ROOT_ID_LONG);
}

Set<Party> list = new HashSet<>();
if (mapRight.isEmpty()) return list;
Set<String> setExists = new HashSet<>();
for (DataRightGroupItem item : mapRight.values()) {
if (!item.isInclude()) continue; //不包含的对象,这里是计算根节点,不管就是了
//本单位之类的已处理
Party party = PartyCache.getInstance().get(item.getValue());
if (party == null) continue;
boolean isParentExists = false;
//添加节点,注意:如果是已经添加了的单位的下级,则不要添加
String[] pids = party.getLevelCode().split(SwConsts.SPLIT_CHAR);
for (String pid : pids) {
if (setExists.contains(pid)) {
isParentExists = true;
break;
}
}
if (!isParentExists) {
list.add(party);
setExists.add(String.valueOf(party.getEntityId()));
}
}
return list;
}

/**
* 获取下级节点
*
* @param parentId 上级机构id
* @return
*/
public Set<Party> getChildren(long parentId) {
Set<Party> children = PartyCache.getInstance().getChildren(parentId);
if (!isByRight || mapRight == null || CommUtil.isEmpty(children)) { //不控制权限,直接取吧
return children;
}

if (mapRight.isEmpty()) return null;

children.removeIf(party -> !hasRight(party));
return children;
}

/**
* 是否拥有此单位权限
*
* @param party
* @return
*/
private boolean hasRight(Party party) {
int nret = hasRight(party.getEntityId());
if (nret != RIGHT_RET_NONE) return nret != RIGHT_RET_EX;
String[] pids = party.getLevelCode().split(SwConsts.SPLIT_CHAR);
for (String pid : pids) {
nret = hasRight(Long.parseLong(pid));
if (nret == RIGHT_RET_IN_CHILD) return true;
if (nret == RIGHT_RET_IN_NOCHILD || nret == RIGHT_RET_EX) return false;
}
return false;
}

private int hasRight(long id) {
if (mapRight == null || !mapRight.containsKey(String.valueOf(id))) return RIGHT_RET_NONE;
DataRightGroupItem item = mapRight.get(String.valueOf(id));
if (item.isInclude()) {
if (item.getType()== BpmConst.DataRight.V_INCLUDE_CHILDREN) return RIGHT_RET_IN_CHILD;
return RIGHT_RET_IN_NOCHILD;
}
if (!item.isInclude()) return RIGHT_RET_EX;
return 0;
}


/**
* 判断childId是否是parentId的子孙
*
* @param childId
* @param parentId
* @return
*/
public boolean isChild(long childId, long parentId) {
if (parentId<=0L) return true;
Party party = PartyCache.getInstance().get(childId);
if (party == null) return false;
String parentIdStr = SwConsts.SPLIT_CHAR+parentId+SwConsts.SPLIT_CHAR;
return (party.getLevelCode() + SwConsts.SPLIT_CHAR).contains(parentIdStr);
}
/**
* 获取查询语句,使用子查询的方式,数据权限越复杂,构建的语句就越复杂
*
* @param where 是否带的有where了,确定是where还是and
* @param sqlField 查询的表的单位字段
* @param partyId 查询条件机构的值,可以为空
* @param qnext 是否带下级 注意:此方法仅单位管理使用。
* @param includeSelf 是否包含自己
* @param sql sql
* @param args 参数
*/
public boolean buildSqlWhere(boolean where, String sqlField, long partyId, boolean qnext,
boolean includeSelf, StringBuilder sql, SwMap args) {
if (partyId>0L) {//前端页面传入了单位id
Party party = PartyCache.getInstance().get(partyId);
if (isByRight&&party==null) {
if (where) sql.append(" and ");
else sql.append(" where ");
sql.append(" 1 <> 1 ");
return true;
}
if (party != null) {//单位不存在,则默认查所有,押后
int nret = hasRight(partyId);
if (nret == RIGHT_RET_IN_NOCHILD) {//不包含下级,则直接等于即可
if (where) sql.append(" and ");
else sql.append(" where ");
sql.append(" ").append(sqlField).append(" =:_dr_partyId ");
args.put("_dr_partyId",partyId);
return true;
}
if (nret == RIGHT_RET_EX) {//不包含,直接用顶级单位的id来筛选,应该是无数据返回
if (where) sql.append(" and ");
else sql.append(" where ");
sql.append(" 1 <> 1 ");
return true;
}
} else {
partyId = SwConsts.DEF_ROOT_ID_LONG;
}
}

StringBuilder sqlAnd = new StringBuilder(128);
StringBuilder sqlOr = new StringBuilder(128);

addPartySql(partyId, true, true, qnext, includeSelf, sqlAnd, sqlOr, args);

if (mapRight != null) {
for (DataRightGroupItem item : mapRight.values()) {
long itemPartyId = Long.parseLong(item.getValue());
if (item.getValue().equalsIgnoreCase(String.valueOf(partyId))) continue;
if (!isChild(itemPartyId, partyId)) continue; //非指定partyId的下级,不用搭理
addPartySql(itemPartyId, item.isInclude(), item.getType() == BpmConst.DataRight.V_INCLUDE_CHILDREN, true, true, sqlAnd, sqlOr, args);
}
}

if (sqlAnd.length() == 0 && sqlOr.length() == 0) {
return where;
}

if (where) sql.append(" and ");
else sql.append(" where ");

if (sqlOr.length() > 0) {
sql.append("\nEXISTS(\n" +
" SELECT pt_id FROM " + EntityHelper.getSchemaTableName(Party.ENTITY_NAME) + " r2 WHERE r2.party_id=" + sqlField);
sql.append(" and (").append(sqlOr.substring(4)).append("))");
return true;
}
if (sqlAnd.length() > 0) {
sql.append("\nand not EXISTS(\n" +
" SELECT pt_id FROM " + EntityHelper.getSchemaTableName(Party.ENTITY_NAME)+ " r2 WHERE r2.party_id=" + sqlField);
sql.append(" and (").append(sqlAnd.substring(4)).append("))");
return true;
}
return false;


}
private void addPartySql(long partyId, boolean isInclude, boolean hasChild, boolean qnext, boolean includeSelf, StringBuilder sqlAnd, StringBuilder sqlOr, SwMap args) {
if (partyId<=0L) return;
if (!hasChild && isInclude) {//不包含下级
String p = String.format("_dr_pt_id_%s", new Random().nextInt(10));
sqlOr.append(String.format(" or r2.pt_id=:%s",p));
args.put(p,partyId);
return;
}
Party party = PartyCache.getInstance().get(partyId);
if (party == null) return;
if (isInclude) {
localBuildSqlPara(qnext, includeSelf, sqlOr, args, party);
} else {
localBuildSqlPara(qnext, includeSelf, sqlAnd, args, party);
}
}

//构建子查询语句
private void localBuildSqlPara(boolean qnext, boolean includeSelf, StringBuilder sqlOr, SwMap args, Party party) {
sqlOr.append(" or ( ");
if (includeSelf) {
String p = String.format("_dr_pt_id_%s", new Random().nextInt(10));
sqlOr.append(String.format("(r2.pt_id=:%s or ",p));
args.put(p,party.getId());
}
if (qnext) {
String p = String.format("_dr_pt_level_code_%s", new Random().nextInt(10));
sqlOr.append(String.format(" r2.pt_level_code like :%s",p));
args.put(p,party.getLevelCode() + SwConsts.SPLIT_CHAR + party.getId() + "%");
} else {
String p = String.format("_dr_pt_parent_id_%s", new Random().nextInt(10));
sqlOr.append(String.format(" r2.pt_parent_id = :%s",p));
args.put(p,party.getId());
}

if (includeSelf) sqlOr.append("))");
else sqlOr.append(")");
}

}

+ 0
- 1
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/menuPlan/MenuPlanCache.java View File

@@ -14,7 +14,6 @@ import java.util.Set;
public class MenuPlanCache extends AbstractEntityCache<MenuPlan> {
//缓存key:按项目缓存
public final static String mk_p = "p";

public static MenuPlanCache getInstance() {
return CacheManager.getIntance().getCache(MenuPlanCache.class);
}


+ 21
- 0
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/menuPlan/MenuPlanHelper.java View File

@@ -0,0 +1,21 @@
package cc.smtweb.system.bpm.web.sys.user.menuPlan;

/**
* @Author: tanghp
* @Date: 2022-09-26 10:19
* @Desc: 菜单方案辅助类
*/
public class MenuPlanHelper {
/**
* 获取命中菜单方案明细ID
* @param menuId 菜单方案明细ID
* @param pageId 页面ID
* @param fullPath 带参数的路径
* @return
*/
public long findMenuId(long menuId,long pageId,String fullPath){
//

return 0L;
}
}

+ 45
- 0
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/menuPlan/MenuPlanItemProvider.java View File

@@ -0,0 +1,45 @@
package cc.smtweb.system.bpm.web.sys.user.menuPlan;

import cc.smtweb.framework.core.cache.SessionCacheFactory;
import cc.smtweb.framework.core.util.CommUtil;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
* @Author: tanghp
* @Date: 2022-09-26 11:12
* @Desc: 菜单明细加载类
*/
public class MenuPlanItemProvider {
private volatile MenuPlanItemProvider provider;
private Map<Long, MenuPlanItem> map = new HashMap<>();
private MenuPlanItemProvider() {
}
public MenuPlanItemProvider getInstance(){
if (provider == null) {
synchronized (SessionCacheFactory.class) {
if (provider == null) {
provider = new MenuPlanItemProvider();
}
}
}
return provider;
}
// 获取菜单方案明细ID
public MenuPlanItem getMenuPlanItem(long menuId){
MenuPlanItem menuPlanItem = map.get(menuId);
if(menuPlanItem!=null)return menuPlanItem;
Collection<MenuPlan> plans = MenuPlanCache.getInstance().getAll();
if(CommUtil.isEmpty(plans))return null;
for(MenuPlan menuPlan: plans){
menuPlanItem = MenuPlanCache.getInstance().getById(menuPlan.getEntityId(),menuId);
if(menuPlanItem!=null){
map.put(menuId,menuPlanItem);
return menuPlanItem;
}
}
return null;
}
}

+ 55
- 3
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/role/RoleHelper.java View File

@@ -1,5 +1,9 @@
package cc.smtweb.system.bpm.web.sys.user.role;

import cc.smtweb.system.bpm.web.sys.user.dataRight.DataRightDefine;
import cc.smtweb.system.bpm.web.sys.user.dataRight.DataRightDefineCache;
import cc.smtweb.system.bpm.web.sys.user.dataRightGroup.DataRightGroup;
import cc.smtweb.system.bpm.web.sys.user.dataRightGroup.DataRightGroupCache;
import cc.smtweb.system.bpm.web.sys.user.menuPlan.MenuPlan;
import cc.smtweb.system.bpm.web.sys.user.menuPlan.MenuPlanCache;
import cc.smtweb.system.bpm.web.sys.user.menuPlan.MenuPlanContent;
@@ -8,9 +12,7 @@ import cc.smtweb.system.bpm.web.sys.user.user.User;
import cc.smtweb.system.bpm.web.sys.user.user.UserCache;
import cc.smtweb.system.bpm.web.sys.user.user.UserRoleCache;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;

/**
* @Author: tanghp
@@ -127,4 +129,54 @@ public final class RoleHelper {
});
return mpList;
}

/**
* 获取用户指定类型的数据权限组
* @param userId 用户ID
* @param partyId 登录的单位
* @param menuId 菜单ID
* @param dsType 数据权限类型编码
* @return 数据权限组集合
*/
public static Set<DataRightGroup> getDataRightGroup(long userId,long partyId,long menuId,String dsType){
Set<Long> mpIds = getMenuPlanIds(userId,partyId);
if(mpIds.size()==0){
return new HashSet<>();
}
// 没传菜单方案ID,随机取一个菜单方案
return getDataRightGroup(userId,partyId,menuId,dsType,mpIds.iterator().next());
}

/**
* 获取用户指定类型的数据权限组
* @param userId 用户ID
* @param partyId 登录单位
* @param dsType 数据权限类型编码 参见 BpmEnum.DataRightType
* @param menuPlanId 菜单方案id
* @return 据权限组集合
*/
public static Set<DataRightGroup> getDataRightGroup(long userId,long partyId,long menuId,String dsType,long menuPlanId){
Map<Long,DataRightGroup> mapGroup = new HashMap<>();
//先看数据权限类型存在不
DataRightDefine drd = DataRightDefineCache.getInstance().getByCode(dsType);
if(drd==null)return new HashSet<>();

Set<Long> roleIds = UserRoleCache.getInstance().getRoleIdByUP(userId,partyId);
RoleCache roleCache = RoleCache.getInstance();
roleIds.forEach((roleId)-> {
Role role = roleCache.get(roleId);
if(role==null || role.getSmpId()!=menuPlanId){
return;
}
RoleRightContent roleRightContent = new RoleRightContent(role.getPrivilege());
long groupId =roleRightContent.getDataRightGroupId(menuId,drd.getEntityId());
if(groupId>0L){
DataRightGroup dataRightGroup = DataRightGroupCache.getInstance().get(groupId);
if(dataRightGroup!=null){
mapGroup.put(groupId,dataRightGroup);
}
}
});
return new HashSet<>(mapGroup.values());
}
}

+ 21
- 0
smtweb-framework/bpm/src/main/java/cc/smtweb/system/bpm/web/sys/user/role/RoleRightContent.java View File

@@ -112,4 +112,25 @@ public class RoleRightContent {
});
return cache;
}

/**
* 获取菜单的数据权限组ID
* @param menuId 菜单id
* @param dataRightId 数据权限定义id
* @return 数据权限组ID
*/
public long getDataRightGroupId(long menuId, long dataRightId){
RoleRight right = getRoleRight(menuId);
List<Map<String, Object>> list = right.getRightData();
if(CommUtil.isEmpty(list))return 0L;
for(Map<String,Object> map :list){
SwMap swMap = new SwMap();
swMap.putAll(map);
long key = swMap.readLong("key");
if(key ==dataRightId){
return swMap.readLong("value");
}
}
return 0L;
}
}

+ 15
- 1
smtweb-framework/bpm/src/main/resources/static/template/default/incModel/inc_card_fields_only.ftl View File

@@ -34,7 +34,21 @@
<#if fields.lookup??>
"lookup": {
<#list fields.lookup as k, v>
"${k}": "${v}" <#if k_has_next>,</#if>
<#if v?is_enumerable>
"${k}": [
<#list v as v1>
{
<#list v1 as vk1, vv1>
"${vk1}": "${vv1}"<#if vk1_has_next>,</#if>
</#list>
}
<#if v1_has_next>,</#if>
</#list>
]
<#else>
"${k}": "${v}"
</#if>
<#if k_has_next>,</#if>
</#list>
},
</#if>


+ 17
- 3
smtweb-framework/bpm/src/main/resources/static/template/default/incModel/inc_list_dialog.ftl View File

@@ -25,9 +25,23 @@
"required": "${dfield.required}",
<#if dfield.lookup??>
"lookup": {
<#list dfield.lookup as k, v>
"${k}": "${v}" <#if k_has_next>,</#if>
</#list>
<#list dfield.lookup as k, v>
<#if v?is_enumerable>
"${k}": [
<#list v as v1>
{
<#list v1 as vk1, vv1>
"${vk1}": "${vv1}"<#if vk1_has_next>,</#if>
</#list>
}
<#if v1_has_next>,</#if>
</#list>
]
<#else>
"${k}": "${v}"
</#if>
<#if k_has_next>,</#if>
</#list>
},
</#if>
<#if dfield.maxlength gt 0>


+ 15
- 1
smtweb-framework/bpm/src/main/resources/static/template/default/incModel/inc_list_query.ftl View File

@@ -33,7 +33,21 @@
<#if filter.lookup??>
"lookup": {
<#list filter.lookup as k, v>
"${k}": "${v}" <#if k_has_next>,</#if>
<#if v?is_enumerable>
"${k}": [
<#list v as v1>
{
<#list v1 as vk1, vv1>
"${vk1}": "${vv1}"<#if vk1_has_next>,</#if>
</#list>
}
<#if v1_has_next>,</#if>
</#list>
]
<#else>
"${k}": "${v}"
</#if>
<#if k_has_next>,</#if>
</#list>
},
</#if>


+ 17
- 3
smtweb-framework/bpm/src/main/resources/static/template/default/incModel/inc_query_sfilters.ftl View File

@@ -59,9 +59,23 @@
"field": "${filter.id}",
<#if filter.lookup??>
"lookup": {
<#list filter.lookup as k, v>
"${k}": "${v}" <#if k_has_next>,</#if>
</#list>
<#list filter.lookup as k, v>
<#if v?is_enumerable>
"${k}": [
<#list v as v1>
{
<#list v1 as vk1, vv1>
"${vk1}": "${vv1}"<#if vk1_has_next>,</#if>
</#list>
}
<#if v1_has_next>,</#if>
</#list>
]
<#else>
"${k}": "${v}"
</#if>
<#if k_has_next>,</#if>
</#list>
},
</#if>
"name": "${filter.name}"


+ 30
- 2
smtweb-framework/bpm/src/main/resources/static/template/default/model_card_flow.ftl View File

@@ -184,7 +184,21 @@
<#if fields.lookup??>
"lookup": {
<#list fields.lookup as k, v>
"${k}": "${v}" <#if k_has_next>,</#if>
<#if v?is_enumerable>
"${k}": [
<#list v as v1>
{
<#list v1 as vk1, vv1>
"${vk1}": "${vv1}"<#if vk1_has_next>,</#if>
</#list>
}
<#if v1_has_next>,</#if>
</#list>
]
<#else>
"${k}": "${v}"
</#if>
<#if k_has_next>,</#if>
</#list>
},
</#if>
@@ -293,7 +307,21 @@
<#if fields.lookup??>
"lookup": {
<#list fields.lookup as k, v>
"${k}": "${v}" <#if k_has_next>,</#if>
<#if v?is_enumerable>
"${k}": [
<#list v as v1>
{
<#list v1 as vk1, vv1>
"${vk1}": "${vv1}"<#if vk1_has_next>,</#if>
</#list>
}
<#if v1_has_next>,</#if>
</#list>
]
<#else>
"${k}": "${v}"
</#if>
<#if k_has_next>,</#if>
</#list>
},
</#if>


+ 15
- 1
smtweb-framework/bpm/src/main/resources/static/template/default/model_card_ms.ftl View File

@@ -80,7 +80,21 @@
<#if field.lookup??>
"lookup": {
<#list field.lookup as k, v>
"${k}": "${v}" <#if k_has_next>,</#if>
<#if v?is_enumerable>
"${k}": [
<#list v as v1>
{
<#list v1 as vk1, vv1>
"${vk1}": "${vv1}"<#if vk1_has_next>,</#if>
</#list>
}
<#if v1_has_next>,</#if>
</#list>
]
<#else>
"${k}": "${v}"
</#if>
<#if k_has_next>,</#if>
</#list>
},
</#if>


+ 15
- 1
smtweb-framework/bpm/src/main/resources/static/template/default/model_card_normal.ftl View File

@@ -165,7 +165,21 @@
<#if field.lookup??>
"lookup": {
<#list field.lookup as k, v>
"${k}": "${v}" <#if k_has_next>,</#if>
<#if v?is_enumerable>
"${k}": [
<#list v as v1>
{
<#list v1 as vk1, vv1>
"${vk1}": "${vv1}"<#if vk1_has_next>,</#if>
</#list>
}
<#if v1_has_next>,</#if>
</#list>
]
<#else>
"${k}": "${v}"
</#if>
<#if k_has_next>,</#if>
</#list>
},
</#if>


+ 15
- 1
smtweb-framework/bpm/src/main/resources/static/template/default/model_list_card.ftl View File

@@ -168,7 +168,21 @@
<#if dfield.lookup??>
"lookup": {
<#list dfield.lookup as k, v>
"${k}": "${v}" <#if k_has_next>,</#if>
<#if v?is_enumerable>
"${k}": [
<#list v as v1>
{
<#list v1 as vk1, vv1>
"${vk1}": "${vv1}"<#if vk1_has_next>,</#if>
</#list>
}
<#if v1_has_next>,</#if>
</#list>
]
<#else>
"${k}": "${v}"
</#if>
<#if k_has_next>,</#if>
</#list>
},
</#if>


+ 10
- 0
smtweb-framework/core/pom.xml View File

@@ -168,6 +168,16 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.2</version>
</dependency>
</dependencies>
<build>
<plugins>


+ 2
- 0
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/common/SwConsts.java View File

@@ -62,4 +62,6 @@ public interface SwConsts {

//定时任务key
String REDIS_KEY_BASE_JOB = "jobexe";
// params 参数中的header key
String PARAMS_HEADER_KEY ="_header";
}

+ 1
- 0
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/common/SwEnum.java View File

@@ -314,6 +314,7 @@ public interface SwEnum {
public static StrEnumBean LIKE = instance.addEnum("like", "包含");
public static StrEnumBean IN = instance.addEnum("in", "在列表");
public static StrEnumBean NOT_IN = instance.addEnum("not in", "不在列表");
public static StrEnumBean IN_CHILD = instance.addEnum("inChild", "本级及下级");
}

//合计栏类型 "summary": "COUNT/SUM/AVG/MAX/MIN/其他为文本"


+ 21
- 1
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/controller/binder/body/SwMapBodyEditor.java View File

@@ -8,6 +8,7 @@ import cc.smtweb.framework.core.util.JsonUtil;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Map;

/**
@@ -32,6 +33,10 @@ public class SwMapBodyEditor implements IEditor {

private Object getGetValue(String paramName, Class<?> paramType, Map<String, Object> params, HttpServletRequest request) {
SwMap result = JsonUtil.parseSimple(params, SwMap.class);
if(result!=null){
SwMap header = getHeaderMap(request);
result.put("_header",header);
}
request.setAttribute(BODY_MAP, result);
return getFieldValue(result, paramName);
}
@@ -42,10 +47,25 @@ public class SwMapBodyEditor implements IEditor {
}

SwMap result = JsonUtil.parse(body, SwMap.class);
if(result!=null){
SwMap header = getHeaderMap(request);
result.put("_header",header);
}
request.setAttribute(BODY_MAP, result);
return getFieldValue(result, paramName);
}

private SwMap getHeaderMap( HttpServletRequest request){
SwMap header = new SwMap();
Enumeration<String> headerNames = request.getHeaderNames();
if (null != headerNames) {
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
header.put(headerName,headerValue);
}
}
return header;
}
private Object getFieldValue(SwMap result, String paramName) {
if (paramName != null) {
Object value = result.get(paramName);


+ 8
- 0
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/service/AbstractListHandler.java View File

@@ -54,6 +54,14 @@ public abstract class AbstractListHandler extends AbstractHandler {
return R.success(buildListData());
}

/**
* 导出excel
* @return R:{ file: fileName@@filePath }
*/
public R exportExcel() {
return R.success(buildListData());
}

public SwListData buildListData() {
List<SwMap> listData;
SqlPara sqlPara = buildDataSql();


+ 15
- 1
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/mvc/service/TreeHelper.java View File

@@ -6,6 +6,7 @@ import cc.smtweb.framework.core.common.SwConsts;
import cc.smtweb.framework.core.common.SwEnum;
import cc.smtweb.framework.core.db.DbEngine;
import cc.smtweb.framework.core.db.EntityDao;
import cc.smtweb.framework.core.db.EntityHelper;
import cc.smtweb.framework.core.db.cache.ModelTableCache;
import cc.smtweb.framework.core.db.impl.DefaultEntity;
import cc.smtweb.framework.core.db.vo.ModelTable;
@@ -36,6 +37,7 @@ public class TreeHelper<T extends DefaultEntity> {
private String fieldParent;
private String fieldLevel;
private String fieldLevelCode;
private String fieldId;


public static TreeHelper getTreeHelper(String tableName) {
@@ -69,6 +71,7 @@ public class TreeHelper<T extends DefaultEntity> {
fieldParent = table.findFieldNameByType(SwEnum.FieldType.PARENT_ID.value);
fieldLevelCode = table.findFieldNameByType(SwEnum.FieldType.LEVEL_CODE.value);
fieldLevel = table.findFieldNameByType(SwEnum.FieldType.LEVEL.value);
fieldId = table.getIdField();
}

public long getParentId(T bean) {
@@ -125,13 +128,24 @@ public class TreeHelper<T extends DefaultEntity> {
}
return list;
}
// 拼接查询本级及下级sql片段
public String buildLikeFrSql(long id,String sqlField){
T bean = cache.get(id);
if(bean==null){
return "1<>1";
}
String childStr = "'"+getLevelCode(bean)+ SwConsts.SPLIT_CHAR+ bean.getEntityId()+"'";
String schemaTableName = EntityHelper.getSchemaTableName(tableName);
return String.format(" exists ( select %s from %s tt where tt.%s = %s and (tt.%s=%s or tt.%s like %s))",
fieldId,schemaTableName,fieldId,sqlField,fieldId,id,fieldLevelCode,childStr);
}

private void resetParentChildren(T bean, List<T> list) {
T parent = cache.get(getParentId(bean));
if (parent != null) {
bean.put(fieldLevelCode, getLevelCode(parent) + SwConsts.SPLIT_CHAR + parent.getEntityId());
bean.put(fieldLevel, getLevel(parent) + 1);
dao.updateEntity(bean, fieldLevelCode, fieldLevel);
dao.updateEntity(bean, fieldLevelCode+","+fieldLevel);
list.add(bean);
}
Collection<T> children = getChildren(bean);


+ 0
- 1
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/session/SessionUtil.java View File

@@ -37,7 +37,6 @@ public class SessionUtil {
//url参数名
private final static String KEY_PARAM_FP_KEY = "fpk";
private final static String KEY_PARAM_FP_VAL = "fpv";

//不需要校验登录的url
public static List<String> notLoginUrl = new ArrayList<>();
/*//不需要切换数据源的url,强制用主库


+ 1081
- 0
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/ExcelExportUtil.java
File diff suppressed because it is too large
View File


+ 131
- 0
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/ExcelUtil.java View File

@@ -0,0 +1,131 @@
package cc.smtweb.framework.core.util;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;

import java.util.ArrayList;
import java.util.List;

public class ExcelUtil {
private static int xy(int x, int y) {
if (y == 0) return 1;
if (y == 1) return x;
int f = x * x;
for (int i = 0; i < (y - 2); ++i) {
f *= x;
}
return f;
}

// Z==> 26, AA == > 27 , AB ==> 28
public static int toColInt(String col) {
col = col.toUpperCase();
int colv = 0, left = 0;
for (int i = col.length(); i > 0; --i) {
char c = col.charAt(i - 1);
colv += (c - 'A' + 1) * xy(26, left);
++left;
}
return colv - 1; // excel是从0开始的
}

/**
* 数字下标转列
* @param index
* @return
*/
public static String toColExcel(int index) {
int shang = 0;
int yu = 0;
List<Integer> list = new ArrayList<Integer>(); //10进制转26进制 倒序
do {
shang = index / 26;
yu = index % 26;
index = shang;
list.add(yu);
} while (shang != 0);
StringBuilder sb = new StringBuilder();
for (int j = list.size() - 1; j >= 0; j--) {
sb.append((char) (list.get(j) + 'A' - (Math.min(j, 1)))); //倒序拼接 序号转字符 非末位 序号减去 1
}
return sb.toString();
}


// 注意col要大写字母
public static String getStr(Row row, char col) {
int i = col - 'A';
return getStr(row, i);
}

public static String getStr(Row row, int col) {
if(col <0) return "";
Cell cell = row.getCell(col);
if (null == cell) return "";
if (cell.getCellType() == CellType.BLANK || cell.getCellType() == CellType.ERROR) {
return "";
}
// AKzz : cell 是数字时,会报错误,
if (cell.getCellType() == CellType.NUMERIC) {
// 非日期格式
if (!org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
double d = cell.getNumericCellValue();
// long x = (long) d;
return MathUtil.getDoubleStr(d);
} else {
return cc.smtweb.framework.core.util.DateUtil.toStdDateString(cell.getDateCellValue());
}
}

if (cell.getCellType() == CellType.STRING) {
return StringUtil.checkNull(cell.getStringCellValue());
}

if (cell.getCellType() == CellType.FORMULA) {
return getFormulaStr(cell);
}
return "";
}

// 注意col要大写字母
public static int getInt(Row row, char col) {
int i = col - 'A';
return getInt(row, i);
}

public static int getInt(Row row, int col) {
if(col <0) return 0;
Cell cell = row.getCell(col);
if (null == cell) return 0;
if (cell.getCellType() == CellType.NUMERIC && !org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
double d = cell.getNumericCellValue();
return (int) d;
} else if (cell.getCellType() == CellType.STRING) {
return MathUtil.toint(cell.getStringCellValue(), 0);
} else if (cell.getCellType() == CellType.FORMULA) {
return (int) getFormulaDbl(cell);
}
return 0;
}

private static String getFormulaStr(Cell cell) {
try {
return StringUtil.checkNull(cell.getStringCellValue());
} catch (Exception e) {
// UtilLogger.warn("读取数据出错:"+cell, e);
System.err.println("读取数据出错");
String v = MathUtil.toStdNumberString(cell.getNumericCellValue());
if (v.endsWith(".00")) v = v.substring(0, v.length() - 3);
return v;
}
}

private static double getFormulaDbl(Cell cell) {
try {
return cell.getNumericCellValue();
} catch (Exception e) {
return MathUtil.todouble(cell.getStringCellValue());
}
}
}

+ 54
- 0
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/ExportUtil.java View File

@@ -0,0 +1,54 @@
package cc.smtweb.framework.core.util;

import java.util.HashMap;
import java.util.Map;

public class ExportUtil {
//填充变量
public static String myReplaceStr(String s, Map<String, String> map) {
boolean isDouble = s.startsWith("[@exprd");
boolean isInt = s.startsWith("[@expri@]");
if (isDouble || isInt) {
s = s.substring(s.indexOf("@]") + 2);
String b = "[#", e = "#]", svar;
int n = s.indexOf(b), lb = b.length();
Map<String, Object> mapvar = new HashMap<>();
int i = 0;
while (n >= 0) {
svar = "a" + (++i);
String fn = s.substring(n + lb, s.indexOf(e));
s = s.replace(b + fn + e, svar);
n = s.indexOf(b);
mapvar.put(svar, StringUtil.getDoubleIgnoreErr(map.get(fn)));
}
double d;
try {
d = MathUtil.calcExprMapDouble(s, mapvar);
} catch (Exception e1) {
d = 0.0;
// UtilLogger.error("计算错误:", e1);
}
if (isDouble) {
String v = MathUtil.getAmountStr(d);
v = v.replace(".00", "").replaceAll(",", "");
if (v.contains(".") && v.endsWith("0")) v = v.substring(0, v.length() - 1);
return v;
}
return MathUtil.toStdNumberString(d, 0);
} else if (s.startsWith("[@d") || s.startsWith("[@i@]")) s = s.substring(s.indexOf("@]") + 2);
else if (s.startsWith("[@expfml@]")) s = s.substring(10);

return myReplaceStrEx(s, "[#", "#]", map);
}

//填充变量
public static String myReplaceStrEx(String s, String b, String e, Map<String, String> map) {
int n = s.indexOf(b), lb = b.length();
while (n >= 0) {
String fn = s.substring(n + lb, s.indexOf(e));
s = s.replace(b + fn + e, StringUtil.checkNull(map.get(fn)));
n = s.indexOf(b);
}
return s;
}
}

+ 19
- 0
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/FileUtil.java View File

@@ -3,6 +3,7 @@ package cc.smtweb.framework.core.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
@@ -98,6 +99,24 @@ public class FileUtil {
return "data:image/png;base64," + png_base64;
}

/**
* 判断是否是图片
*
* @param base64Str
* @return
*/
public static boolean isImageFromBase64(String base64Str) {
try {
BufferedImage bufImg = ImageIO.read(new ByteArrayInputStream(new BASE64Decoder().decodeBuffer(base64Str)));
if (null == bufImg) {
return false;
}
} catch (Exception e) {
return false;
}
return true;
}

public static boolean copyFile(File oldfile, String newPath, boolean isDelOld) {
if (!oldfile.exists()) return true;
int byteread;


+ 24
- 4
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/HttpUtil.java View File

@@ -107,7 +107,12 @@ public class HttpUtil {
public static SwMap post(String url, Map<String, String> paras) throws Exception {
String json_resp = post(url, null, paras, null);
if (StringUtils.isEmpty(json_resp) || !json_resp.startsWith("{")) return null;
return (SwMap) JsonUtil.parseMap(json_resp);
SwMap swMap = new SwMap();
Map map = JsonUtil.parseMap(json_resp);
if(map!=null){
swMap.putAll(map);
}
return swMap;
}

/**
@@ -147,7 +152,12 @@ public class HttpUtil {
json_resp = new String(Base64.decodeBase64(json_resp), charset);
}
if (StringUtils.isEmpty(json_resp) || !json_resp.startsWith("{")) return null;
return (SwMap) JsonUtil.parseMap(json_resp);
SwMap swMap = new SwMap();
Map map = JsonUtil.parseMap(json_resp);
if(map!=null){
swMap.putAll(map);
}
return swMap;
}

/**
@@ -169,14 +179,24 @@ public class HttpUtil {
json_resp = new String(Base64.decodeBase64(json_resp), charset);
}
if (StringUtils.isEmpty(json_resp) || !json_resp.startsWith("{")) return null;
return (SwMap) JsonUtil.parseMap(json_resp);
SwMap swMap = new SwMap();
Map map = JsonUtil.parseMap(json_resp);
if(map!=null){
swMap.putAll(map);
}
return swMap;
}


public static SwMap post(String url, Map<String, String> header, Map<String, String> paras) throws Exception {
String json_resp = post(url, header, paras, null);
if (StringUtils.isEmpty(json_resp) || !json_resp.startsWith("{")) return null;
return (SwMap) JsonUtil.parseMap(json_resp);
SwMap swMap = new SwMap();
Map map = JsonUtil.parseMap(json_resp);
if(map!=null){
swMap.putAll(map);
}
return swMap;
}

/**


+ 507
- 0
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/MathUtil.java View File

@@ -0,0 +1,507 @@
package cc.smtweb.framework.core.util;

import org.apache.commons.jexl3.*;
import org.apache.commons.jexl3.internal.Engine;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Map;

public class MathUtil {
//整数
private static DecimalFormat dfLng = new DecimalFormat("##############0");
private static DecimalFormat dfLong = new DecimalFormat("###,###,###,###,##0");
//一位小数
private static DecimalFormat df1 = new DecimalFormat("##############0.0");
private static DecimalFormat df1Format = new DecimalFormat("###,###,###,###,##0.0");
//两位小数
private static DecimalFormat df2 = new DecimalFormat("##############0.00");
private static DecimalFormat df2Format = new DecimalFormat("###,###,###,###,##0.00");
//四位小数
private static DecimalFormat df4 = new DecimalFormat("###,###,###,###,##0.0000");
//六位小数
private static DecimalFormat df6Number = new DecimalFormat("#######################0.000000");
private static DecimalFormat df6NumberF = new DecimalFormat("#,###,###,###,###,###,##0.000000");

public final static DecimalFormat stdAmountFormat = new DecimalFormat("###,###,###,###,##0.00");
public final static DecimalFormat stdNumberFormat = new DecimalFormat("#0.00");
public final static String DEF_NUM_TEN_THOUSAND = "10000";//万
public static final double MAX_VALUE = 9999999999999.99D;
public static final double MIN_VALUE = -9999999999999.99D;

private final static BigDecimal ONE_BIG = new BigDecimal(1.00D);
private static final String UNIT = "万仟佰拾亿仟佰拾万仟佰拾元角分";
private static final String DIGIT = "零壹贰叁肆伍陆柒捌玖";

/**
* 4舍5入double,2位小数
*/
public static double roundDouble(double src) {
return roundDouble(src, 2);
}

/**
* 4舍5入double,N 位小数
*
* @param src
* @param scale 小数位数
* @return
*/
public static double roundDouble(Object src, int scale) {
if (src == null) return 0.0;
String v = src.toString();
if (StringUtil.isEmpty(v)) return 0.0;
if (scale < 0) scale = 2;

BigDecimal src_b = new BigDecimal(v);
BigDecimal src_v = src_b.divide(ONE_BIG, scale + 2, BigDecimal.ROUND_HALF_UP);// 4舍5入
src_v = src_v.divide(ONE_BIG, scale, BigDecimal.ROUND_HALF_UP);// 4舍5入
return src_v.doubleValue();
}

/**
* 舍位处理,原生floor有坑,部分浮点数记录为.99999999999形式,导致floor结果错误
*
* @param d
* @return
*/
public static double floor(double d) {
return Math.floor(MathUtil.roundDouble(d, 2));
}

/**
* 比较两Double是否相等,将会吧他们专程BigDecimal进行比较;
*
* @param src double1
* @param tag double2
* @return src > tag 返回1, src < tag 返回-1, 否则返回0
*/
public static int compare(double src, double tag) {
BigDecimal src_b = new BigDecimal(src);
BigDecimal src_v = src_b.divide(ONE_BIG, 2, BigDecimal.ROUND_HALF_UP);// 4舍5入

BigDecimal tag_b = new BigDecimal(tag);
BigDecimal tag_v = tag_b.divide(ONE_BIG, 2, BigDecimal.ROUND_HALF_UP);// 4舍5入

return src_v.compareTo(tag_v);
}

/**
* 自动过滤金额中的逗号转换为double,如果出错,则返回0
*
* @param s 源串,可能为带逗号的金额串;
* @return double
*/
public static Double toDouble(String s) {
return todouble(s);
}

/**
* 自动过滤金额中的逗号转换为double,如果出错,则返回0
*
* @param s 源串,可能为带逗号的金额串;
* @return double
*/
public static double todouble(String s) {
try {
return Double.parseDouble(s.replaceAll(",", ""));
} catch (Exception e) {
return 0.00;
}
}

/**
* 获取double,主要过滤d为null的情况;
*
* @param d Double对象;
* @return double
*/
public static double todouble(Double d) {
if (d == null) return 0.0d;
return d.doubleValue();
}

/**
* 自动过滤金额中的逗号转换为float,如果出错,则返回0
*
* @param s 源串,可能为带逗号的金额串;
* @return Float
*/
public static Float toFloat(String s) {
return tofloat(s);
}

/**
* 自动过滤金额中的逗号转换为float,如果出错,则返回0
*
* @param s 源串,可能为带逗号的金额串;
* @return Float
*/
public static float tofloat(String s) {
try {
return Float.parseFloat(s.replaceAll(",", ""));
} catch (Exception e) {
return 0.0f;
}
}

public static long tolong(String src, long defaultvalue) {
try {
return Long.parseLong(src);
} catch (Exception e) {
return defaultvalue;
}
}

public static int toint(String src, int defaultvalue) {
try {
return Integer.parseInt(src);
} catch (Exception e) {
return defaultvalue;
}
}

/**
* 考虑使用中的精度,判断一个Value是否>0,实际是>0.00001
*
* @param value double类型
* @return boolean
*/
public static boolean isBigThanZero(double value) {
return (value > 0.00001);
}

/**
* 考虑使用中的精度,判断一个Value是否>0,实际是>0.00001
*
* @param value String类型
* @return boolean
*/
public static boolean isBigThanZero(String value) {
return !StringUtil.isEmpty(value) && isBigThanZero(toDouble(value));
}

/**
* 考虑使用中的精度,判断一个Value是否=0,实际是给出一个值范围。
*
* @param value double类型
* @return boolean
*/
public static boolean isEqualsZero(double value) {
return (-0.00001 < value && value < 0.00001);
}

/**
* 考虑使用中的精度,判断一个Value是否=0,实际是给出一个值范围。
*
* @param value String类型
* @return boolean
*/
public static boolean isEqualsZero(String value) {
return StringUtil.isEmpty(value) || isEqualsZero(toDouble(value));
}

/**
* 是否是负数
*
* @param db_val 要判断的double
* @return 负数则返回true;
*/
public static boolean isNegative(double db_val) {
return (compare(db_val, 0.00D) == -1);
}

/**
* 是否是正数
*
* @param db_val 要判断的double
* @return 正数则返回true;
*/
public static boolean isPlus(double db_val) {
return (compare(db_val, 0.00D) == 1);
}

/**
* 得到金额字符串,保持小数点2位
*
* @param db 将double转换为金额字符串;
* @return 金额字符串#0.00;
*/
public static String toStdNumberString(double db) {
try {
return stdNumberFormat.format(db);
} catch (Exception e) {
return "0.00";
}
}

public static String toStdNumberStringEx(double db) {
try {
if (compare(db, -1d) == 0) return "-";
return stdNumberFormat.format(db);
} catch (Exception e) {
return "0.00";
}
}

/**
* 将金额格式字符串,如23,333,093.01 去掉逗号
*
* @param s 金额串
* @return String 去掉逗号后的串,如果amount为空,则返回0.00
*/
public static String toStdNumberString(String s) {
if (StringUtil.isEmpty(s))
return "0.00";
return stdNumberFormat.format(MathUtil.todouble(s));
}

/**
* 将数据转换为两位小数的数字格式;
*
* @param d 数据
* @param isZeroToEmpty 如果未0,是否返回“”;
* @return 两位小数的字符串;
*/
public static String toStdNumberString(double d, boolean isZeroToEmpty) {
if (isEqualsZero(d)) {
return isZeroToEmpty ? "" : "0.00";
}
return stdNumberFormat.format(d);
}

public static String toStdNumberString(String s, boolean isZeroToEmpty) {
return toStdNumberString(MathUtil.todouble(s), isZeroToEmpty);
}

public static String toStdNumberString(double d, int scale) {
DecimalFormat dfn = null;
if (scale == 1) dfn = df1Format;
if (scale == 2) dfn = df2Format;
else if (scale == 4) dfn = df4;
else if (scale == 6) dfn = df6NumberF;
else if (scale <= 0) dfn = dfLong;
else {
StringBuilder sb = new StringBuilder("###,###,###,###,##0.");
for (int i = 0; i < scale; i++) sb.append("0");
dfn = new DecimalFormat(sb.toString());
}
return dfn.format(d);
}

/**
* 将数字乘100,保留小数点后两位, 然后后面添加%
*
* @param d 值
* @param isZeroToEmpty,如果值为0,是否返回空;
* @return 字符串;
*/
public static String toStdPercentNumberStr(double d, boolean isZeroToEmpty) {
if (d > -0.00000000001 && d < 0.00000000001) {
return isZeroToEmpty ? "" : "0.00%";
}
return toStdNumberString(d * 100) + "%";
}


public static String toStdAmountString(double d) {
return toStdAmountString(d, false);
}

/**
* 将数据转换为两位小数的金额格式,带逗号;
*
* @param d 数据
* @param isZeroToEmpty 如果未0,是否返回“”;
* @return 金额格式的字符串;
*/
public static String toStdAmountString(double d, boolean isZeroToEmpty) {
if (isEqualsZero(d)) {
return isZeroToEmpty ? "" : "0.00";
}
return stdAmountFormat.format(d);
}

public static String toStdAmountString(String s) {
return toStdAmountString(MathUtil.todouble(s), false);
}

public static String toStdAmountString(String s, boolean isZeroToEmpty) {
return toStdAmountString(MathUtil.todouble(s), isZeroToEmpty);
}


/**
* 将小写金额转换为人民币大写金额
*
* @param s 金额格式的串
* @return String 转换结果
*/
public static String toCapsAmountString(String s) {
if (StringUtil.isEmpty(s)) return "";
return toCapsAmountString(todouble(s));
}

/**
* 将小写金额转换为人民币大写金额
*
* @param v double
* @return String 转换结果
*/
public static String toCapsAmountString(double v) {
if (v < MIN_VALUE || v > MAX_VALUE) return "参数非法!";

boolean negative = isNegative(v);

if (negative) v = Math.abs(v);
long l = Math.round(v * 100);
if (l == 0) return "零元整";

String strValue = String.valueOf(l);
// i用来控制数
int i = 0;
// j用来控制单位
int j = UNIT.length() - strValue.length();
StringBuilder rs = new StringBuilder(32);
boolean isZero = false;
for (; i < strValue.length(); i++, j++) {
char ch = strValue.charAt(i);
if (ch == '0') {
isZero = true;
if (UNIT.charAt(j) == '亿' || UNIT.charAt(j) == '万' || UNIT.charAt(j) == '元') {
rs.append(UNIT.charAt(j));
isZero = false;
}
} else {
if (isZero) {
rs.append('零');
isZero = false;
}
rs.append(DIGIT.charAt(ch - '0')).append(UNIT.charAt(j));
}
}
if (rs.charAt(rs.length() - 1) != '分')
rs.append('整');

i = rs.indexOf("亿万");
if (i > 0) rs.delete(i + 1, i + 2); // i+1 ->万

if (negative)
return rs.insert(0, '负').toString();
else
return rs.toString();
}

/**
* 返回0 到 maxvalue的随机数
*
* @param maxvalue 随机数的最大值
* @return int
*/
public static int rnd(int maxvalue) {
return (int) (Math.random() * (maxvalue + 1));
}


public static double chkDbNull(Double v) {
return v == null ? 0 : v;
}

public static double max(double d1, double d2) {
return compare(d1, d2) < 0 ? d2 : d1;
}

public static double min(double d1, double d2) {
return compare(d1, d2) < 0 ? d1 : d2;
}

/**
* double 去尾法
*
* @param src 待处理数据
* @param scale 保留小数位数
* @return
*/
public static double cutDouble(double src, int scale) {
String v = toStdNumberString(src, 6);//先到6位小数,再去计算,否则容易出错,如8.3成8.29999999999,舍位就成了8.29了
DecimalFormat formater = new DecimalFormat();
formater.setMaximumFractionDigits(scale);
formater.setGroupingSize(0);
formater.setRoundingMode(RoundingMode.FLOOR);
return new BigDecimal(formater.format(toDouble(v))).doubleValue();
}

public static String getAmountStr(double amount) {
return df2Format.format(amount);
}

//数字转字符串,如无小数,则去掉.00
public static String getDoubleStr(double d) {
return getAmountStr(d).replaceAll(",", "").replaceAll("\\.00", "");
}

/**
* double 进位法
*
* @param src 待处理数据
* @param scale 保留小数位数
* @return
*/
public static double upDouble(double src, int scale) {
String v = toStdNumberString(src, 6);//先到6位小数,再去计算
DecimalFormat formater = new DecimalFormat();
formater.setMaximumFractionDigits(scale);
formater.setGroupingSize(0);
formater.setRoundingMode(RoundingMode.UP);
return new BigDecimal(formater.format(toDouble(v))).doubleValue();
}

/**
* 计算公式 参数以Map方式传入
*
* @param expr 表达式
* @param mapVar 变量
* @return 计算结果
*/
public static Object calcExprMapObject(String expr, Map<String, Object> mapVar) {
if (StringUtil.isEmpty(expr)) return "";
JexlContext jc = new MapContext();
jc.set("Math", Math.class);
jc.set("UtilPub", StringUtil.class);
for (String k : mapVar.keySet()) jc.set(k, mapVar.get(k));
JexlExpression e = new Engine().createExpression(expr);
return e.evaluate(jc);
}

/**
* 计算公式,参数以数组方式传入,key、value交替
*
* @param expr 表达式
* @param vars 变量
* @return
*/
public static Object calcExprObjectEx(String expr, Object... vars) {
if (StringUtil.isEmpty(expr)) return "";
JexlContext jc = new MapContext();
jc.set("Math", Math.class);
jc.set("UtilPub", StringUtil.class);
for (int i = 0, len = vars.length; i < len; ) {
jc.set((String) vars[i++], vars[i++]);
}
JexlExpression e = new Engine().createExpression(expr);
return e.evaluate(jc);
}

public static double calcExprMapDouble(String expr, Map<String, Object> mapVar) {
Object o = calcExprMapObject(expr, mapVar);
if (o != null) return StringUtil.getDoubleIgnoreErr(o.toString());
return 0.0;
}

public static double calcExprDoubleEx(String expr, Object... vars) {
Object o = calcExprObjectEx(expr, vars);
if (o != null) return StringUtil.getDoubleIgnoreErr(o.toString());
return 0.0;
}
}

+ 49
- 0
smtweb-framework/core/src/main/java/cc/smtweb/framework/core/util/StringUtil.java View File

@@ -5,6 +5,7 @@ import org.apache.commons.lang3.StringUtils;

import java.nio.charset.StandardCharsets;
import java.text.Collator;
import java.text.DecimalFormat;
import java.util.*;

/**
@@ -15,6 +16,8 @@ import java.util.*;
*/
@SuppressWarnings("UnusedDeclaration")
public class StringUtil {
private static DecimalFormat df2Format = new DecimalFormat("###,###,###,###,##0.00");

private static Collator chineseCollator = Collator.getInstance(Locale.CHINA);

public static boolean isEmpty(String str) {
@@ -182,6 +185,52 @@ public class StringUtil {
}

/**
* 获取浮点数(有错误默认为0),可以识别金额中的逗号格式
*
* @param str 带转换的字符串
* @return 浮点数
*/
public static double getDoubleIgnoreErr(String str) {
if (str == null)
return 0.0;
str = str.trim();
if (str.equals(""))
return 0.0;
str = str.replaceAll(",", "").replaceAll(",", "");
try {
return Double.valueOf(str);
} catch (Exception e) {
return 0.0;
}
}

/**
* 得到int 获取转换的int值,有错返回0
*
* @param str 带转换的字符串
* @return int
*/
public static int getIntIgnoreErr(String str) {
return getIntIgnoreErr(str, 0);
}

public static int getIntIgnoreErr(String str, int defValue) {
if (str == null)
return defValue;
str = str.trim();
if (str.equals(""))
return defValue;
str = str.replaceAll(",", "").replaceAll(",", "");
if (str.contains("."))
str = str.substring(0, str.indexOf('.'));
try {
return Integer.valueOf(str);
} catch (Exception e) {
return defValue;
}
}

/**
* 取得重复字串
*
* @param repeatString 重复字串


Loading…
Cancel
Save