From 749259238dd1c94b94903278aa1944dac2567dd6 Mon Sep 17 00:00:00 2001 From: devezhao-mbp Date: Thu, 29 Aug 2019 02:24:31 +0800 Subject: [PATCH] =?UTF-8?q?=E6=98=A8=E5=A4=A9=E4=BB=8A=E5=A4=A9=E6=98=8E?= =?UTF-8?q?=E5=A4=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/service/query/AdvFilterParser.java | 156 ++++++++++-------- src/main/webapp/assets/js/rb-advfilter.jsx | 6 +- 2 files changed, 93 insertions(+), 69 deletions(-) diff --git a/src/main/java/com/rebuild/server/service/query/AdvFilterParser.java b/src/main/java/com/rebuild/server/service/query/AdvFilterParser.java index bb8cb3f0f..8d09d1da1 100644 --- a/src/main/java/com/rebuild/server/service/query/AdvFilterParser.java +++ b/src/main/java/com/rebuild/server/service/query/AdvFilterParser.java @@ -18,19 +18,11 @@ along with this program. If not, see . package com.rebuild.server.service.query; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.lang.StringEscapeUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.math.NumberUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - +import cn.devezhao.commons.CalendarUtils; +import cn.devezhao.persist4j.Entity; +import cn.devezhao.persist4j.Field; +import cn.devezhao.persist4j.dialect.FieldType; +import cn.devezhao.persist4j.dialect.Type; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -42,12 +34,20 @@ import com.rebuild.server.metadata.entity.EasyMeta; import com.rebuild.server.service.bizz.UserHelper; import com.rebuild.server.service.bizz.privileges.Department; import com.rebuild.web.IllegalParameterException; +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.NumberUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; -import cn.devezhao.commons.CalendarUtils; -import cn.devezhao.persist4j.Entity; -import cn.devezhao.persist4j.Field; -import cn.devezhao.persist4j.dialect.FieldType; -import cn.devezhao.persist4j.dialect.Type; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static cn.devezhao.commons.DateFormatUtils.getUTCDateFormat; /** * 高级查询解析器 @@ -58,6 +58,9 @@ import cn.devezhao.persist4j.dialect.Type; public class AdvFilterParser { private static final Log LOG = LogFactory.getLog(AdvFilterParser.class); + + private static final String ZERO_TIME = " 00:00:00"; + private static final String FULL_TIME = " 23:59:59"; private JSONObject filterExp; private Entity rootEntity; @@ -120,38 +123,37 @@ public class AdvFilterParser { return "( " + StringUtils.join(indexItemSqls.values(), " and ") + " )"; } else { // 高级表达式 eg. (1 AND 2) or (3 AND 4) - String tokens[] = equation.toLowerCase().split(" "); + String[] tokens = equation.toLowerCase().split(" "); List itemSqls = new ArrayList<>(); - for (int i = 0; i < tokens.length; i++) { - String token = tokens[i]; - if (StringUtils.isBlank(token)) { - continue; - } - - boolean hasRP = false; // the `)` - if (token.length() > 1) { - if (token.startsWith("(")) { - itemSqls.add("("); - token = token.substring(1); - } else if (token.endsWith(")")) { - hasRP = true; - token = token.substring(0, token.length() - 1); - } - } - - if (NumberUtils.isDigits(token)) { - String itemSql = StringUtils.defaultIfBlank(indexItemSqls.get(Integer.valueOf(token)), "(9=9)"); - itemSqls.add(itemSql); - } else if (token.equals("(") || token.equals(")") || token.equals("or") || token.equals("and")) { - itemSqls.add(token); - } else { - LOG.warn("Invalid equation token : " + token); - } - - if (hasRP) { - itemSqls.add(")"); - } - } + for (String token : tokens) { + if (StringUtils.isBlank(token)) { + continue; + } + + boolean hasRP = false; // the `)` + if (token.length() > 1) { + if (token.startsWith("(")) { + itemSqls.add("("); + token = token.substring(1); + } else if (token.endsWith(")")) { + hasRP = true; + token = token.substring(0, token.length() - 1); + } + } + + if (NumberUtils.isDigits(token)) { + String itemSql = StringUtils.defaultIfBlank(indexItemSqls.get(Integer.valueOf(token)), "(9=9)"); + itemSqls.add(itemSql); + } else if (token.equals("(") || token.equals(")") || token.equals("or") || token.equals("and")) { + itemSqls.add(token); + } else { + LOG.warn("Invalid equation token : " + token); + } + + if (hasRP) { + itemSqls.add(")"); + } + } return "( " + StringUtils.join(itemSqls, " ") + " )"; } } @@ -194,7 +196,7 @@ public class AdvFilterParser { final String op = item.getString("op"); - StringBuffer sb = new StringBuffer(field) + StringBuilder sb = new StringBuilder(field) .append(' ') .append(convOp(op)) .append(' '); @@ -203,23 +205,35 @@ public class AdvFilterParser { } String value = item.getString("value"); + String valueEnd = null; // TODO 自定义函数 - String zeroTime = " 00:00:00"; - String fullTime = " 23:59:59"; + if ("BFD".equalsIgnoreCase(op)) { - value = CalendarUtils.getUTCDateFormat().format(CalendarUtils.addDay(-NumberUtils.toInt(value))) + fullTime; + value = getUTCDateFormat().format(CalendarUtils.addDay(-NumberUtils.toInt(value))) + FULL_TIME; } else if ("AFD".equalsIgnoreCase(op)) { - value = CalendarUtils.getUTCDateFormat().format(CalendarUtils.addDay(NumberUtils.toInt(value))) + zeroTime; + value = getUTCDateFormat().format(CalendarUtils.addDay(NumberUtils.toInt(value))) + ZERO_TIME; } else if ("BFM".equalsIgnoreCase(op)) { - value = CalendarUtils.getUTCDateFormat().format(CalendarUtils.addMonth(-NumberUtils.toInt(value))) + fullTime; + value = getUTCDateFormat().format(CalendarUtils.addMonth(-NumberUtils.toInt(value))) + FULL_TIME; } else if ("AFM".equalsIgnoreCase(op)) { - value = CalendarUtils.getUTCDateFormat().format(CalendarUtils.addMonth(NumberUtils.toInt(value))) + zeroTime; + value = getUTCDateFormat().format(CalendarUtils.addMonth(NumberUtils.toInt(value))) + ZERO_TIME; } else if ("RED".equalsIgnoreCase(op)) { - value = CalendarUtils.getUTCDateFormat().format(CalendarUtils.addDay(-NumberUtils.toInt(value))) + fullTime; + value = getUTCDateFormat().format(CalendarUtils.addDay(-NumberUtils.toInt(value))) + FULL_TIME; } else if ("REM".equalsIgnoreCase(op)) { - value = CalendarUtils.getUTCDateFormat().format(CalendarUtils.addMonth(-NumberUtils.toInt(value))) + fullTime; - } else if ("SFU".equalsIgnoreCase(op)) { + value = getUTCDateFormat().format(CalendarUtils.addMonth(-NumberUtils.toInt(value))) + FULL_TIME; + } else if ("YTA".equalsIgnoreCase(op)) { + value = getUTCDateFormat().format(CalendarUtils.addDay(-1)); + valueEnd = value + FULL_TIME; + value = value + ZERO_TIME; + } else if ("TDA".equalsIgnoreCase(op)) { + value = getUTCDateFormat().format(CalendarUtils.now()); + valueEnd = value + FULL_TIME; + value = value + ZERO_TIME; + } else if ("TTA".equalsIgnoreCase(op)) { + value = getUTCDateFormat().format(CalendarUtils.addDay(1)); + valueEnd = value + FULL_TIME; + value = value + ZERO_TIME; + } else if ("SFU".equalsIgnoreCase(op)) { value = Application.getCurrentUser().toLiteral(); } else if ("SFB".equalsIgnoreCase(op)) { Department dept = UserHelper.getDepartment(Application.getCurrentUser()); @@ -269,10 +283,10 @@ public class AdvFilterParser { // 区间 boolean isBetween = op.equalsIgnoreCase("BW"); - String value2 = isBetween ? parseValue(item.getString("value2"), op, fieldMeta) : null; - if (isBetween && value2 == null) { - value2 = value; - } + valueEnd = isBetween ? parseValue(item.getString("value2"), op, fieldMeta) : valueEnd; + if (isBetween && valueEnd == null) { + valueEnd = value; + } if (op.equalsIgnoreCase("IN") || op.equalsIgnoreCase("NIN") || op.equalsIgnoreCase("SFD")) { sb.append(value); @@ -284,8 +298,15 @@ public class AdvFilterParser { } if (isBetween) { - sb.append(" and ").append(quoteValue(value2, fieldMeta.getType())); - } + sb.append(" and ").append(quoteValue(valueEnd, fieldMeta.getType())); + } else if (valueEnd != null) { + sb.insert(0, '(') + .append(" and ") + .append(field) + .append(" <= ") + .append(quoteValue(valueEnd, fieldMeta.getType())) + .append(')'); + } return sb.toString(); } @@ -296,7 +317,7 @@ public class AdvFilterParser { * @return */ private String parseValue(Object val, String op, Field field) { - String value = null; + String value; // IN if (val instanceof JSONArray) { Set inVals = new HashSet<>(); @@ -375,6 +396,9 @@ public class AdvFilterParser { else if ("SFU".equalsIgnoreCase(op)) return "="; else if ("SFB".equalsIgnoreCase(op)) return "="; else if ("SFD".equalsIgnoreCase(op)) return "in"; + else if ("YTA".equalsIgnoreCase(op)) return ">="; + else if ("TDA".equalsIgnoreCase(op)) return ">="; + else if ("TTA".equalsIgnoreCase(op)) return ">="; throw new UnsupportedOperationException("Unsupported token [" + op + "]"); } diff --git a/src/main/webapp/assets/js/rb-advfilter.jsx b/src/main/webapp/assets/js/rb-advfilter.jsx index 5a16ba573..a4194663f 100644 --- a/src/main/webapp/assets/js/rb-advfilter.jsx +++ b/src/main/webapp/assets/js/rb-advfilter.jsx @@ -207,9 +207,9 @@ class AdvFilter extends React.Component { } } -const OP_TYPE = { LK: '包含', NLK: '不包含', IN: '包含', NIN: '不包含', EQ: '等于', NEQ: '不等于', GT: '大于', LT: '小于', BW: '区间', NL: '为空', NT: '不为空', BFD: '...天前', BFM: '...月前', AFD: '...天后', AFM: '...月后', RED: '最近...天', REM: '最近...月', SFU: '本人', SFB: '本部门', SFD: '本部门及子部门' } +const OP_TYPE = { LK: '包含', NLK: '不包含', IN: '包含', NIN: '不包含', EQ: '等于', NEQ: '不等于', GT: '大于', LT: '小于', BW: '区间', NL: '为空', NT: '不为空', BFD: '...天前', BFM: '...月前', AFD: '...天后', AFM: '...月后', RED: '最近...天', REM: '最近...月', SFU: '本人', SFB: '本部门', SFD: '本部门及子部门', YTA:'昨天', TDA:'今天', TTA:'明天' } const OP_DATE_NOPICKER = ['BFD', 'BFM', 'AFD', 'AFM', 'RED', 'REM'] -const OP_NOVALUE = ['NL', 'NT', 'SFU', 'SFB', 'SFD'] +const OP_NOVALUE = ['NL', 'NT', 'SFU', 'SFB', 'SFD', 'YTA', 'TDA', 'TTA'] const PICKLIST_CACHE = {} const REFMETA_CACHE = {} const INPUTVALS_HOLD = {} // 输入值保持 @@ -259,7 +259,7 @@ class FilterItem extends React.Component { if (fieldType === 'NUMBER' || fieldType === 'DECIMAL') { op = ['GT', 'LT', 'BW', 'EQ'] } else if (fieldType === 'DATE' || fieldType === 'DATETIME') { - op = ['GT', 'LT', 'BW', 'RED', 'REM', 'BFD', 'BFM', 'AFD', 'AFM'] + op = ['YTA', 'TDA', 'TTA', 'GT', 'LT', 'BW', 'RED', 'REM', 'BFD', 'BFM', 'AFD', 'AFM'] } else if (fieldType === 'FILE' || fieldType === 'IMAGE') { op = [] } else if (fieldType === 'PICKLIST') {