advfilter

This commit is contained in:
FangfangZhao 2018-11-07 01:13:26 +08:00
parent 8f0f5b28de
commit 68813aa747
11 changed files with 385 additions and 107 deletions

View file

@ -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();

View file

@ -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);
}

View file

@ -18,9 +18,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
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);
// <Name, [ID, COMMENTS, ICON]>
private static final Map<String, Object[]> ENTITY_EXTMETA = new HashMap<>();
private static final Map<String, Object[]> ENTITY_EXTMETA = new CaseInsensitiveMap<>();
// <Name, [ID, COMMENTS]>
private static final Map<String, Object[]> FIELD_EXTMETA = new HashMap<>();
private static final Map<String, Object[]> 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);
}
}

View file

@ -19,6 +19,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
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<BaseMeta>() {
// @Override
// public int compare(BaseMeta a, BaseMeta b) {
// int c = EasyMeta.getLabel(a).compareToIgnoreCase(EasyMeta.getLabel(b));
// return c;
// }
// });
Arrays.sort(metas, new Comparator<BaseMeta>() {
@Override
public int compare(BaseMeta o1, BaseMeta o2) {
return EasyMeta.getLabel(o1).compareToIgnoreCase(EasyMeta.getLabel(o2));
}
});
}
}

View file

@ -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<String> 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<String> 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 + "]");
}
}

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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 .select2-container--default .select2-selection--multiple .select2-selection__rendered,
.adv-filter .form-control-sm {
height: 34px !important;
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 {

View file

@ -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 {
<div className="adv-filter">
<div className="filter-option">
</div>
<div className="filter-items">
{(this.state.items || []).map((item)=>{
<div className="filter-items" ref="items">
{this.state.items.map((item)=>{
return item
//return React.cloneElement(item, { ref: item.id })
})}
<div className="item plus"><a href="javascript:;" onClick={()=>this.addItem()}><i className="zmdi zmdi-plus-circle icon"></i> 新增条件</a></div>
<div className="item plus"><a href="javascript:;" onClick={()=>this.addItem()}><i className="zmdi zmdi-plus-circle icon"></i> 添加条件</a></div>
</div>
</div>
<div className="adv-filter">
@ -26,11 +33,11 @@ class AdvFilter extends React.Component {
</div>
{this.state.enableAdvexp !== true ? null :
<div className="mb-3">
<input className="form-control form-control-sm form-control-success" ref="adv-exp" value={this.state.advexp} />
<input className="form-control form-control-sm form-control-success" ref="adv-exp" value={this.state.advexp} onChange={()=>this.handleChange()} />
</div>
}
<div className="item">
<button className="btn btn-primary" type="button">应用</button>
<button className="btn btn-primary" type="button" onClick={()=>this.toFilterJson()}>应用</button>
&nbsp;&nbsp;
<button className="btn btn-secondary" type="button">取消</button>
</div>
@ -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(<FilterItem index={_items.length + 1} fields={this.fields} $$$parent={this} key={id} id={id} onRef={this.onRef} />)
_items.push(<FilterItem index={_items.length + 1} fields={this.fields} $$$parent={this} key={'item-' + $random()} />)
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)
}
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 (
<div className="row item" key={'item-' + this.state.index}>
<div className="row item">
<div className="col-sm-5 field">
<em>{this.state.index}</em>
<i className="zmdi zmdi-minus-circle" title="移除条件" onClick={()=>this.props.$$$parent.delItem(this)}></i>
<select className="form-control form-control-sm" ref="filter-field">
<em className={this.state.hasError ? 'text-danger' : ''}>{this.state.index}</em>
<i className="zmdi zmdi-minus-circle" title="移除条件" onClick={()=>this.props.$$$parent.removeItem(this.props.id)}></i>
<select className="form-control form-control-sm" ref="filter-field" value={this.state.field}>
{this.state.fields.map((item)=>{
return <option value={item.name + '----' + item.type} key={'field-' + item.name}>{item.label}</option>
})}
@ -91,39 +143,58 @@ class FilterItem extends React.Component {
<div className="col-sm-2 op">
{this.renderOp()}
</div>
<div className="col-sm-5 val">
<div className={'col-sm-5 val' + (this.state.op == 'NL' || this.state.op == 'NT' ? ' hide' : '')}>
{this.renderVal()}
</div>
</div>
)
}
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 (
<select className="form-control form-control-sm" ref="filter-op">
<select className="form-control form-control-sm" ref="filter-op" value={this.state.op}>
{op.map((item)=>{
return <option value={item[0]} key={'op-' + item.join('-')}>{item[1]}</option>
return <option value={item} key={'op-' + item}>{OP_TYPE[item]}</option>
})}
</select>
)
}
renderVal(){
return this.state.op != 'bw' ? (this.state.op == 'nl' || this.state.op == 'nt' ? null : <input className="form-control form-control-sm" ref="filter-val" />) : (<div>
<input className="form-control form-control-sm" ref="filter-val" />
<input className="form-control form-control-sm" ref="filter-val-2" />
let val = <input className="form-control form-control-sm" ref="filter-val" onChange={this.handleChange} value={this.state.value || ''} />
if (this.state.op == 'BW'){
val = (
<div className="val-range">
<input className="form-control form-control-sm" ref="filter-val" onChange={this.handleChange} value={this.state.value || ''} />
<input className="form-control form-control-sm" ref="filter-val2" onChange={this.handleChange} data-at="2" value={this.state.value2 || ''} />
<span></span>
<span className="end"></span>
</div>)
} else if (this.state.type == 'PICKLIST'){
val = (
<select className="form-control form-control-sm" multiple="true" ref="filter-val">
{(this.state.picklist || []).map((item) => {
return <option value={item.id} key={'val-' + item.id}>{item.text}</option>
})}
</select>)
}
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
}
}

View file

@ -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)

View file

@ -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);
})
}