From 68813aa747caf80aa3ffb944740293c4cdabefec Mon Sep 17 00:00:00 2001 From: FangfangZhao Date: Wed, 7 Nov 2018 01:13:26 +0800 Subject: [PATCH] advfilter --- .../server/entityhub/Entity2Schema.java | 14 +- .../server/entityhub/Field2Schema.java | 10 +- .../metadata/DynamicMetadataFactory.java | 33 +- .../server/metadata/PortalMetaSorter.java | 21 +- .../rebuild/server/query/AdvFilterParser.java | 53 ++-- .../com/rebuild/web/base/MetadataGet.java | 14 +- src/main/webapp/assets/css/rb-base.css | 4 +- src/main/webapp/assets/css/rb-page.css | 45 ++- src/main/webapp/assets/js/rb-advfilter.jsx | 293 ++++++++++++++++-- src/main/webapp/assets/js/rb-forms.jsx | 1 + src/main/webapp/assets/js/rb-page.js | 4 +- 11 files changed, 385 insertions(+), 107 deletions(-) diff --git a/src/main/java/com/rebuild/server/entityhub/Entity2Schema.java b/src/main/java/com/rebuild/server/entityhub/Entity2Schema.java index 8174863f8..1114997a4 100644 --- a/src/main/java/com/rebuild/server/entityhub/Entity2Schema.java +++ b/src/main/java/com/rebuild/server/entityhub/Entity2Schema.java @@ -25,13 +25,13 @@ import org.apache.commons.logging.LogFactory; import com.rebuild.server.Application; import com.rebuild.server.metadata.EntityHelper; +import com.rebuild.server.metadata.MetadataHelper; import cn.devezhao.commons.ObjectUtils; import cn.devezhao.persist4j.Entity; import cn.devezhao.persist4j.Record; import cn.devezhao.persist4j.dialect.Dialect; import cn.devezhao.persist4j.engine.ID; -import cn.devezhao.persist4j.util.StringHelper; import cn.devezhao.persist4j.util.support.Table; /** @@ -61,20 +61,16 @@ public class Entity2Schema extends Field2Schema { * @return */ public String create(String entityLabel, String comments) { - String entityName = toPinyinString(entityLabel); + String entityName = toPinyinName(entityLabel); while (true) { - Object exists = Application.createQueryNoFilter( - "select entityId from MetaEntity where entityName = ?") - .setParameter(1, entityName) - .unique(); - if (exists != null) { - entityName += (1000 + RandomUtils.nextInt(8999)); + if (MetadataHelper.containsEntity(entityName)) { + entityName += (10 + RandomUtils.nextInt(89)); } else { break; } } - String physicalName = "T__" + StringHelper.hyphenate(entityName).toUpperCase(); + String physicalName = "T__" + entityName.toUpperCase(); Object maxTypeCode[] = Application.createQueryNoFilter( "select min(typeCode) from MetaEntity").unique(); diff --git a/src/main/java/com/rebuild/server/entityhub/Field2Schema.java b/src/main/java/com/rebuild/server/entityhub/Field2Schema.java index 2dcec5b85..19ad1eb57 100644 --- a/src/main/java/com/rebuild/server/entityhub/Field2Schema.java +++ b/src/main/java/com/rebuild/server/entityhub/Field2Schema.java @@ -72,10 +72,10 @@ public class Field2Schema { * @return */ public String create(Entity entity, String fieldLabel, DisplayType type, String comments, String refEntity) { - String fieldName = toPinyinString(fieldLabel); + String fieldName = toPinyinName(fieldLabel); while (true) { if (entity.containsField(fieldName)) { - fieldName += (1000 + RandomUtils.nextInt(8999)); + fieldName += (10 + RandomUtils.nextInt(89)); } else { break; } @@ -128,7 +128,7 @@ public class Field2Schema { Record record = EntityHelper.forNew(EntityHelper.MetaField, user); record.setString("belongEntity", entity.getName()); record.setString("fieldName", fieldName); - String physicalName = StringHelper.hyphenate(fieldName).toUpperCase(); + String physicalName = fieldName.toUpperCase(); record.setString("physicalName", physicalName); record.setString("fieldLabel", fieldLabel); record.setString("displayType", displayType.name()); @@ -172,7 +172,7 @@ public class Field2Schema { * @param text * @return */ - protected String toPinyinString(final String text) { + protected String toPinyinName(final String text) { String identifier = text; try { identifier = PinyinHelper.convertToPinyinString(text, "", PinyinFormat.WITHOUT_TONE); @@ -188,10 +188,12 @@ public class Field2Schema { if (!CharSet.ASCII_ALPHA.contains(start)) { identifier = "a" + identifier; } + identifier = identifier.toLowerCase(); if (identifier.length() > 42) { identifier = identifier.substring(0, 42); } + if (!StringHelper.isIdentifier(identifier)) { throw new MetadataException("无效名称 : " + text); } diff --git a/src/main/java/com/rebuild/server/metadata/DynamicMetadataFactory.java b/src/main/java/com/rebuild/server/metadata/DynamicMetadataFactory.java index 8bd22b30a..aa338a555 100644 --- a/src/main/java/com/rebuild/server/metadata/DynamicMetadataFactory.java +++ b/src/main/java/com/rebuild/server/metadata/DynamicMetadataFactory.java @@ -18,9 +18,9 @@ along with this program. If not, see . package com.rebuild.server.metadata; -import java.util.HashMap; import java.util.Map; +import org.apache.commons.collections4.map.CaseInsensitiveMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Document; @@ -44,9 +44,9 @@ public class DynamicMetadataFactory extends ConfigurationMetadataFactory { private static final Log LOG = LogFactory.getLog(DynamicMetadataFactory.class); // - private static final Map ENTITY_EXTMETA = new HashMap<>(); + private static final Map ENTITY_EXTMETA = new CaseInsensitiveMap<>(); // - private static final Map FIELD_EXTMETA = new HashMap<>(); + private static final Map FIELD_EXTMETA = new CaseInsensitiveMap<>(); public DynamicMetadataFactory(String configLocation, Dialect dialect) { super(configLocation, dialect); @@ -69,30 +69,26 @@ public class DynamicMetadataFactory extends ConfigurationMetadataFactory { private void appendConfig4Db(Document config) { final Element rootElement = config.getRootElement(); - Object[][] customentity = Application.createQueryNoFilter( + Object[][] customEntity = Application.createQueryNoFilter( "select typeCode,entityName,physicalName,entityLabel,entityId,comments,icon,nameField from MetaEntity order by createdOn") .array(); - for (Object[] custom : customentity) { - int typeCode = (int) custom[0]; + for (Object[] custom : customEntity) { String name = (String) custom[1]; - String physicalName = (String) custom[2]; - String description = (String) custom[3]; - Element entity = rootElement.addElement("entity"); - entity.addAttribute("type-code", typeCode + "") + entity.addAttribute("type-code", custom[0] + "") .addAttribute("name", name) - .addAttribute("physical-name", physicalName) - .addAttribute("description", description) + .addAttribute("physical-name", (String) custom[2]) + .addAttribute("description", (String) custom[3]) .addAttribute("parent", "false") .addAttribute("name-field", (String) custom[7]); ENTITY_EXTMETA.put(name, new Object[] { custom[4], custom[5], custom[6] }); } - Object[][] customfield = Application.createQueryNoFilter( - "select belongEntity,fieldName,physicalName,fieldLabel,displayType,nullable,creatable,updatable,precision,maxLength,defaultValue,refEntity,cascade,fieldId,comments,extConfig" - + " from MetaField order by createdOn") + Object[][] customFields = Application.createQueryNoFilter( + "select belongEntity,fieldName,physicalName,fieldLabel,displayType,nullable,creatable,updatable,precision," + + "maxLength,defaultValue,refEntity,cascade,fieldId,comments,extConfig from MetaField order by createdOn") .array(); - for (Object[] custom : customfield) { + for (Object[] custom : customFields) { String entityName = (String) custom[0]; String fieldName = (String) custom[1]; Element entityElement = (Element) rootElement.selectSingleNode("entity[@name='" + entityName + "']"); @@ -117,7 +113,7 @@ public class DynamicMetadataFactory extends ConfigurationMetadataFactory { DisplayType dt = DisplayType.valueOf((String) custom[4]); field.addAttribute("type", dt.getFieldType().getName()); - FIELD_EXTMETA.put(entityName + "__" + fieldName, new Object[] { custom[13], custom[14], dt, custom[15] }); + FIELD_EXTMETA.put(entityName + "." + fieldName, new Object[] { custom[13], custom[14], dt, custom[15] }); } if (LOG.isDebugEnabled()) { @@ -139,7 +135,6 @@ public class DynamicMetadataFactory extends ConfigurationMetadataFactory { * @return */ protected Object[] getFieldExtmeta(String entity, String field) { - String key = entity + "__" + field; - return FIELD_EXTMETA.get(key); + return FIELD_EXTMETA.get(entity + "." + field); } } diff --git a/src/main/java/com/rebuild/server/metadata/PortalMetaSorter.java b/src/main/java/com/rebuild/server/metadata/PortalMetaSorter.java index 6dcaf2258..809c2af6e 100644 --- a/src/main/java/com/rebuild/server/metadata/PortalMetaSorter.java +++ b/src/main/java/com/rebuild/server/metadata/PortalMetaSorter.java @@ -19,6 +19,8 @@ along with this program. If not, see . package com.rebuild.server.metadata; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; import java.util.List; import com.rebuild.server.entityhub.DisplayType; @@ -114,21 +116,16 @@ public class PortalMetaSorter { } /** - * 排序 + * 按 Label 排序 * * @param metas */ private static void sortBaseMeta(BaseMeta[] metas) { -// ArrayUtils.reverse(metas); - - // TODO 元数据排序算法 - -// Arrays.sort(metas, new Comparator() { -// @Override -// public int compare(BaseMeta a, BaseMeta b) { -// int c = EasyMeta.getLabel(a).compareToIgnoreCase(EasyMeta.getLabel(b)); -// return c; -// } -// }); + Arrays.sort(metas, new Comparator() { + @Override + public int compare(BaseMeta o1, BaseMeta o2) { + return EasyMeta.getLabel(o1).compareToIgnoreCase(EasyMeta.getLabel(o2)); + } + }); } } diff --git a/src/main/java/com/rebuild/server/query/AdvFilterParser.java b/src/main/java/com/rebuild/server/query/AdvFilterParser.java index 79f4c8c08..9296d5396 100644 --- a/src/main/java/com/rebuild/server/query/AdvFilterParser.java +++ b/src/main/java/com/rebuild/server/query/AdvFilterParser.java @@ -69,12 +69,12 @@ public class AdvFilterParser { public String toSqlWhere() { JSONArray items = filterExp.getJSONArray("items"); - JSONObject qvalues = filterExp.getJSONObject("values"); + JSONObject values = filterExp.getJSONObject("values"); String equation = StringUtils.defaultIfBlank(filterExp.getString("equation"), "OR"); List itemsSql = new ArrayList<>(); for (Object item : items) { - String itemSql = parseItem((JSONObject) item, qvalues); + String itemSql = parseItem((JSONObject) item, values); if (itemSql != null) { itemsSql.add(itemSql); } @@ -89,17 +89,18 @@ public class AdvFilterParser { return "( " + StringUtils.join(itemsSql, " and ") + " )"; } - // TODO 高级表达式 + // TODO 高级表达式 eg. (1 AND 2) or (3 AND 4) + return null; } /** * @param item - * @param qvalues + * @param values * @return */ - protected String parseItem(JSONObject item, JSONObject qvalues) { + protected String parseItem(JSONObject item, JSONObject values) { String field = item.getString("field"); if (!rootEntity.containsField(field)) { return null; @@ -113,17 +114,22 @@ public class AdvFilterParser { String op = convOp(item.getString("op")); String value = item.getString("value"); + // 占位 if (value.matches("\\{\\d+\\}")) { + if (values == null) { + return null; + } + String valIndex = value.replaceAll("[\\{\\}]", ""); - Object valHold = qvalues.get(valIndex); - if (valHold == null) { + Object valReady = values.get(valIndex); + if (valReady == null) { return null; } // in - if (valHold instanceof JSONArray) { + if (valReady instanceof JSONArray) { Set valArray = new HashSet<>(); - for (Object o : (JSONArray) valHold) { + for (Object o : (JSONArray) valReady) { valArray.add(quote(o.toString())); } @@ -134,7 +140,7 @@ public class AdvFilterParser { } } else { - value = valHold.toString(); + value = valReady.toString(); if (StringUtils.isBlank(value)) { return null; } @@ -169,17 +175,22 @@ public class AdvFilterParser { * @return */ protected String convOp(String op) { - if ("eq".equals(op)) return "="; - if ("neq".equals(op)) return "<>"; - if ("gt".equals(op)) return ">"; - if ("lt".equals(op)) return "<"; - if ("ge".equals(op)) return ">="; - if ("le".equals(op)) return "<="; - if ("nl".equals(op)) return "is null"; - if ("nt".equals(op)) return "is not null"; - if ("lk".equals(op)) return "like"; - if ("nlk".equals(op)) return "not like"; - if ("in".equals(op)) return "in"; + if ("EQ".equalsIgnoreCase(op)) return "="; + else if ("NEQ".equalsIgnoreCase(op)) return "<>"; + else if ("GT".equalsIgnoreCase(op)) return ">"; + else if ("LT".equalsIgnoreCase(op)) return "<"; + else if ("GE".equalsIgnoreCase(op)) return ">="; + else if ("LE".equalsIgnoreCase(op)) return "<="; + else if ("NL".equalsIgnoreCase(op)) return "is null"; + else if ("NT".equalsIgnoreCase(op)) return "is not null"; + else if ("LK".equalsIgnoreCase(op)) return "like"; + else if ("NLK".equalsIgnoreCase(op)) return "not like"; + else if ("IN".equalsIgnoreCase(op)) return "in"; + else if ("BW".equalsIgnoreCase(op)) return "between"; + else if ("BFD".equalsIgnoreCase(op)) return "$before_day(%d)"; + else if ("BFM".equalsIgnoreCase(op)) return "$before_month(%d)"; + else if ("AFD".equalsIgnoreCase(op)) return "$after_day(%d)"; + else if ("AFM".equalsIgnoreCase(op)) return "$after_month(%d)"; throw new UnsupportedOperationException("Unsupported token [" + op + "]"); } } diff --git a/src/main/java/com/rebuild/web/base/MetadataGet.java b/src/main/java/com/rebuild/web/base/MetadataGet.java index 6943fb37f..2a883baaf 100644 --- a/src/main/java/com/rebuild/web/base/MetadataGet.java +++ b/src/main/java/com/rebuild/web/base/MetadataGet.java @@ -32,7 +32,9 @@ import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; +import com.alibaba.fastjson.JSON; import com.rebuild.server.entityhub.EasyMeta; +import com.rebuild.server.helper.manager.PickListManager; import com.rebuild.server.metadata.MetadataHelper; import com.rebuild.server.metadata.PortalMetaSorter; import com.rebuild.web.BaseControll; @@ -80,8 +82,9 @@ public class MetadataGet extends BaseControll { writeSuccess(response, list); } + // 指定实体所引用的字段实体 @RequestMapping("references") - public void ref(HttpServletRequest request, HttpServletResponse response) throws IOException { + public void references(HttpServletRequest request, HttpServletResponse response) throws IOException { String entity = getParameterNotNull(request, "entity"); Entity entityMeta = MetadataHelper.getEntity(entity); @@ -100,4 +103,13 @@ public class MetadataGet extends BaseControll { } writeSuccess(response, list); } + + // PickList 值列表 + @RequestMapping("picklist") + public void ref(HttpServletRequest request, HttpServletResponse response) throws IOException { + String entity = getParameterNotNull(request, "entity"); + String field = getParameterNotNull(request, "field"); + JSON list = PickListManager.getPickList(entity, field, false); + writeSuccess(response, list); + } } diff --git a/src/main/webapp/assets/css/rb-base.css b/src/main/webapp/assets/css/rb-base.css index 88c0779ad..78d551b64 100644 --- a/src/main/webapp/assets/css/rb-base.css +++ b/src/main/webapp/assets/css/rb-base.css @@ -23614,7 +23614,9 @@ div.dataTables_wrapper div.dataTables_filter label select { .datetimepicker table tbody tr td { line-height: 31px; - padding: 0 8px + padding: 0 8px; + line-height: 28px; + padding: 0 7px; } .datetimepicker table tbody tr td.day { diff --git a/src/main/webapp/assets/css/rb-page.css b/src/main/webapp/assets/css/rb-page.css index be2f9915c..fd132250e 100644 --- a/src/main/webapp/assets/css/rb-page.css +++ b/src/main/webapp/assets/css/rb-page.css @@ -978,8 +978,10 @@ i.split.ui-draggable-dragging { margin-left: -25px; font-size: 12px; font-style: normal; + font-weight: bold; padding-top: 10px; color: #777; + padding-left: 5px; } .adv-filter .item .field i.zmdi { position: absolute; @@ -989,6 +991,7 @@ i.split.ui-draggable-dragging { color: #999; display: none; cursor: pointer; + background-color: #fff; } .adv-filter .item .field i.zmdi:hover{ color: #0d5bdd; @@ -996,6 +999,9 @@ i.split.ui-draggable-dragging { .adv-filter .item:hover .field i.zmdi { display: block; } +.adv-filter .item:hover .field em { + display: none; +} .adv-filter .item .op { padding-left: 0; @@ -1005,25 +1011,54 @@ i.split.ui-draggable-dragging { margin-top: 6px; } -.adv-filter .select2-container--default .select2-selection--single { +.adv-filter .item .val .val-range { + position: relative; +} +.adv-filter .item .val .val-range > span { + position: absolute; + right: 6px; + top: 6px; + height: 22px; + width: 22px; + line-height: 22px; + text-align: center; + background-color: #eee; + color: #999; + border-radius: 50%; + font-size: 12px; +} +.adv-filter .item .val .val-range > span.end { + top: 46px; +} + +.adv-filter .select2-container--default .select2-selection--single, .adv-filter .select2-container--default .select2-selection--multiple { height: 34px; } +.adv-filter .select2-container--default .select2-selection--multiple { + min-height: 34px; +} .adv-filter .select2-container--default .select2-selection--single .select2-selection__rendered, - .adv-filter .form-control-sm { - height: 34px !important; +.adv-filter .select2-container--default .select2-selection--multiple .select2-selection__rendered, +.adv-filter .form-control-sm { + height: 34px; line-height: 34px; padding-left: 8px; padding-right: 8px; } .adv-filter .form-control-sm { + height: 34px !important; padding-top: 2px; padding-bottom: 2px; } -.adv-filter .select2-container--default .select2-selection--single .select2-selection__arrow b:after - { +.adv-filter .select2-container .select2-search--inline .select2-search__field, +.adv-filter .select2-container--default .select2-selection--multiple .select2-selection__choice { + margin-top: 3px; +} + +.adv-filter .select2-container--default .select2-selection--single .select2-selection__arrow b:after { line-height: 34px; } .adv-filter+.adv-filter { diff --git a/src/main/webapp/assets/js/rb-advfilter.jsx b/src/main/webapp/assets/js/rb-advfilter.jsx index b2e41a893..f1d2e096c 100644 --- a/src/main/webapp/assets/js/rb-advfilter.jsx +++ b/src/main/webapp/assets/js/rb-advfilter.jsx @@ -2,7 +2,13 @@ class AdvFilter extends React.Component { constructor(props) { super(props) - this.state = { ...props } + + // TODO parse exists items + let items = [] + this.filterItems = {} + this.state = { ...props, items: items } + + this.childrenRef = [] } render() { return ( @@ -10,11 +16,12 @@ class AdvFilter extends React.Component {
-
- {(this.state.items || []).map((item)=>{ +
+ {this.state.items.map((item)=>{ return item + //return React.cloneElement(item, { ref: item.id }) })} - +
@@ -26,11 +33,11 @@ class AdvFilter extends React.Component {
{this.state.enableAdvexp !== true ? null :
- + this.handleChange()} />
}
- +   
@@ -41,48 +48,93 @@ class AdvFilter extends React.Component { componentDidMount() { let that = this $.get(rb.baseUrl + '/commons/metadata/fields?entity=' + this.state.entity, function(res){ - that.fields = res.data + that.fields = res.data.map((item) => { + if (item.type == 'DATETIME') item.type = 'DATE' + return item + }) }) } + onRef = (child) => { + console.log('onRef ... ' + child) + this.childrenRef.push(child) + } + handleChange(event) { + let v = event.target.value + console.log(v) + } addItem(){ if (!this.fields) return let _items = this.state.items || [] - if (_items.length >= 10){ rb.notice('最多可设置10个条件'); return} + if (_items.length >= 10){ rb.notice('最多可添加10个条件'); return } + + let id = 'item-' + $random() + _items.push() - _items.push() let advexp = [] for (let i = 1; i <= _items.length; i++) advexp.push(i) this.setState({ items: _items, advexp: advexp.join(' OR ') }) } - delItem(del){ + removeItem(id){ let _items = [] - for (let i = 0; i < this.state.items.length; i++){ - let item = this.state.items[i] - if (item.props.index != del.props.index) _items.push(item) - } - let advexp = [] + this.state.items.forEach((item)=>{ + if (item.props.id != id) _items.push(item) + }) + let _children = [] + this.childrenRef.forEach((item)=>{ + if (item.props.id != id) _children.push(item) + }) + this.childrenRef = _children + + let that = this + let advexp = [] for (let i = 1; i <= _items.length; i++) advexp.push(i) - this.setState({ items: _items, advexp: advexp.join(' OR ') }) + this.setState({ items: _items, advexp: advexp.join(' OR ') }, ()=>{ + that.childrenRef.forEach((child, idx)=>{ + child.setIndex(idx + 1) + }) + }) } toggleAdvexp() { this.setState({ enableAdvexp: this.state.enableAdvexp !== true }) } + + toFilterJson() { + let filters = [] + let hasError = false + for (let i = 0; i < this.childrenRef.length; i++){ + let fj = this.childrenRef[i].getFilterJson() + if (!!!fj) hasError = true + else filters.push(fj) + } + if (hasError){ rb.notice('部分条件设置有误,请检查'); return } + + let adv = { items: filters } + if (this.state.enableAdvexp == true) adv.equation = this.state.advexp + console.log(JSON.stringify(adv)) + } } +const OP_TYPE = { LK:'包含', NLK:'不包含', EQ:'等于', NEQ:'不等于', GT:'大于', LT:'小于', BW:'区间', NL:'为空', NT:'不为空', BFD:'...天前', BFM:'...月前', AFD:'...天后', AFM:'...月后' } +const OP_DATE_NOPICKER = ['BFD','BFM','AFD','AFM'] +const PICKLIST_CACHE = {} + class FilterItem extends React.Component { constructor(props) { super(props) this.state = { ...props } + console.log(props) + + this.handleChange = this.handleChange.bind(this) } render() { return ( -
+
- {this.state.index} - this.props.$$$parent.delItem(this)}> - {this.state.fields.map((item)=>{ return })} @@ -91,39 +143,58 @@ class FilterItem extends React.Component {
{this.renderOp()}
-
+
{this.renderVal()}
) } renderOp(){ - let op = [ ['lk','包含'], ['nlk','不包含'], ['eq','等于'], ['neq','不等于'], ['nl','为空'], ['nt','不为空'] ] + let op = [ 'LK', 'NLK', 'EQ', 'NEQ' ] if (this.state.type == 'NUMBER' || this.state.type == 'DECIMAL'){ - op = [ ['gt','大于'], ['lt','小于'], ['bw','区间'], ['eq','等于'] ] + op = [ 'GT', 'LT', 'BW', 'EQ' ] } else if (this.state.type == 'DATE' || this.state.type == 'DATETIME'){ - op = [ ['gt','大于'], ['lt','小于'], ['bw','区间'], ['bfd','...天前'], ['bfm','...月前'], ['afd','...天后'], ['afm','...月后'] ] + op = [ 'GT', 'LT', 'BW', 'BFD', 'BFM', 'AFD', 'AFM' ] } else if (this.state.type == 'FILE' || this.state.type == 'IMAGE'){ - op = [ ['nl','为空'], ['nt','不为空'] ] + op = [] + } else if (this.state.type == 'PICKLIST'){ + op = [ 'LK', 'NLK' ] } + op.push('NL', 'NT') this.__op = op return ( - {op.map((item)=>{ - return + return })} ) } renderVal(){ - return this.state.op != 'bw' ? (this.state.op == 'nl' || this.state.op == 'nt' ? null : ) : (
- - -
) + let val = + if (this.state.op == 'BW'){ + val = ( +
+ + + + +
) + } else if (this.state.type == 'PICKLIST'){ + val = ( + ) + } + return (val) } componentDidMount() { + this.props.onRef(this) + let that = this let s2field = $(this.refs['filter-field']).select2({ language: 'zh-CN', @@ -132,7 +203,7 @@ class FilterItem extends React.Component { }).on('change.select2', function(e){ let ft = e.target.value.split('----') that.setState({ field: ft[0], type: ft[1] }, function(){ - s2op.val(that.__op[0][0]).trigger('change') + s2op.val(that.__op[0]).trigger('change') }) }) let s2op = $(this.refs['filter-op']).select2({ @@ -141,9 +212,165 @@ class FilterItem extends React.Component { width: '100%', }).on('change.select2', function(e){ that.setState({ op: e.target.value }, function(){ - $(that.refs['filter-val']).focus() + $setTimeout(function(){ + //ReactDOM.findDOMNode(that.refs['filter-val']).focus() + }, 200, 'filter-val-focus') }) }) + this.__select2 = [s2field, s2op] + s2field.trigger('change') + } + componentDidUpdate(prevProps, prevState) { + let thisEnter = this.state.field + '----' + this.state.type + '----' + (this.state.op == 'BW')/*区间*/ + '----' + (OP_DATE_NOPICKER.contains(this.state.op)) + if (this.__lastEnter == thisEnter) return + console.log(thisEnter) + let lastType = this.__lastEnter ? this.__lastEnter.split('----')[1] : null + this.__lastEnter = thisEnter + + if (this.state.type == 'PICKLIST') { + this.renderPickList(this.state.field) + } else if (lastType == 'PICKLIST') { + this.removePickList() + } + + if (this.state.type == 'DATE') { + this.removeDatepicker() + if (OP_DATE_NOPICKER.contains(this.state.op)){ + // 无需日期组件 + } else { + this.renderDatepicker() + } + } else if (lastType == 'DATE'){ + this.removeDatepicker() + } + } + componentWillUnmount() { + this.__select2.forEach((item, index) => { + item.select2('destroy') + }) + this.__select2 = null + this.removePickList() + this.removeDatepicker() + } + + handleChange(event) { + let that = this + let val = event.target.value + if (event.target.dataset.at == 2) { + this.setState({ value2: val }, function(){ + }) + } else { + this.setState({ value: val }, function(){ + }) + } + } + + renderPickList(field) { + let that = this + if (PICKLIST_CACHE[field]) { + this.setState({ picklist: PICKLIST_CACHE[field] }, function(){ + that.renderPickListAfter() + }) + } else { + $.get(rb.baseUrl + '/commons/metadata/picklist?entity=' + this.props.$$$parent.props.entity + '&field=' + field, function(res){ + if (res.error_code == 0){ + PICKLIST_CACHE[field] = res.data + that.setState({ picklist: PICKLIST_CACHE[field] }, function(){ + that.renderPickListAfter() + }) + } else{ + rb.notice(res.error_msg, 'danger') + } + }) + } + } + renderPickListAfter(){ + console.log('render PickList ...') + let that = this + let s2val = $(this.refs['filter-val']).select2({ + language: 'zh-CN', + placeholder: '选择值', + width: '100%', + }).on('change.select2', function(e){ + let val = s2val.val() + that.setState({ value: val.join(',') }, function(){ + }) + }) + this.__select2_PickList = s2val + } + removePickList(){ + if (this.__select2_PickList) { + console.log('remove PickList ...') + this.__select2_PickList.select2('destroy') + this.__select2_PickList = null + } + } + + renderDatepicker(){ + console.log('render Datepicker ...') + let cfg = { + componentIcon:'zmdi zmdi-calendar', + navIcons: { rightIcon:'zmdi zmdi-chevron-right', leftIcon:'zmdi zmdi-chevron-left'}, + format: 'yyyy-mm-dd', + minView: 2, + startView: 'month', + weekStart: 1, + autoclose: true, + language: 'zh', + todayHighlight: true, + showMeridian: false, + keyboardNavigation: false, + } + + let that = this + let dp1 = $(this.refs['filter-val']).datetimepicker(cfg) + dp1.on('change.select2', function(e){ + that.setState({ value: e.target.value }, function(){ + }) + }) + this.__datepicker = [dp1] + + if (this.refs['filter-val2']) { + let dp2 = $(this.refs['filter-val2']).datetimepicker(cfg) + dp2.on('change.select2', function(e){ + that.setState({ value2: e.target.value }, function(){ + }) + }) + this.__datepicker.push(dp2) + } + } + removeDatepicker(){ + if (this.__datepicker) { + console.log('remove Datepicker ...') + this.__datepicker.forEach((item) => { + item.datetimepicker('remove') + }) + this.__datepicker = null + } + } + + setIndex(idx) { + this.setState({ index: idx }) + } + getFilterJson(){ + let s = this.state + if (!!!s.value) { + if (s.op == 'NL' || s.op == 'NT'){ + // 允许无值 + } else { + this.setState({ hasError: true }) + return + } + } + if (s.op == 'BW' && !!!s.value2){ + this.setState({ hasError: true }) + return + } + + let item = { index: s.index, field: s.field, op: s.op, value: s.value } + if (s.value2) item.value2 = s.value2 + this.setState({ hasError: false }) + return item } } diff --git a/src/main/webapp/assets/js/rb-forms.jsx b/src/main/webapp/assets/js/rb-forms.jsx index 436f4d7fc..9dd4e87e7 100644 --- a/src/main/webapp/assets/js/rb-forms.jsx +++ b/src/main/webapp/assets/js/rb-forms.jsx @@ -403,6 +403,7 @@ class RbFormDateTime extends RbFormElement { todayHighlight: true, showMeridian: false, keyboardNavigation: false, + minuteStep: 5, }).on('changeDate', function(){ let val = $(this).val() that.handleChange({ target: { value: val } }, true) diff --git a/src/main/webapp/assets/js/rb-page.js b/src/main/webapp/assets/js/rb-page.js index 530d0d6c0..a69594176 100644 --- a/src/main/webapp/assets/js/rb-page.js +++ b/src/main/webapp/assets/js/rb-page.js @@ -80,7 +80,7 @@ const __initNavs = function(){ }) $(document.body).click(function(){ // MinNav && SubnavOpen - if ($('.rb-collapsible-sidebar').hasClass('rb-collapsible-sidebar-collapsed') && currsntSubnav.hasClass('open')) { + if ($('.rb-collapsible-sidebar').hasClass('rb-collapsible-sidebar-collapsed') && currsntSubnav && currsntSubnav.hasClass('open')) { currsntSubnav.removeClass('open') currsntSubnav.find('.sub-menu').removeClass('visible') } @@ -133,7 +133,7 @@ const __checkMessage = function(){ $('.rb-notifications span.badge').text('0') __checkMessage_status = 0 } - setTimeout(__checkMessage, 3000); +// setTimeout(__checkMessage, 3000); }) }