field data wrap

This commit is contained in:
devezhao-corp 2018-09-23 22:33:36 +08:00
parent 68d8e8f9b5
commit 06cb381662
27 changed files with 441 additions and 318 deletions

View file

@ -48,14 +48,17 @@ public class DataListManager extends LayoutManager {
* @param entity * @param entity
* @return * @return
*/ */
public static JSON getListColumnConfig(String entity) { public static JSON getColumnLayout(String entity) {
Object[] lcr = getLayoutConfigRaw(entity, TYPE_DATALIST); Object[] raw = getLayoutConfigRaw(entity, TYPE_DATALIST);
List<Map<String, Object>> columnList = new ArrayList<>(); List<Map<String, Object>> columnList = new ArrayList<>();
Entity entityMeta = MetadataHelper.getEntity(entity); Entity entityMeta = MetadataHelper.getEntity(entity);
// 默认配置
if (lcr == null) {
Field nameField = entityMeta.getNameField(); Field nameField = entityMeta.getNameField();
nameField = nameField == null ? entityMeta.getPrimaryField() : nameField;
// 默认配置
if (raw == null) {
if (nameField != null) { if (nameField != null) {
columnList.add(warpColumn(nameField)); columnList.add(warpColumn(nameField));
} }
@ -63,7 +66,7 @@ public class DataListManager extends LayoutManager {
columnList.add(warpColumn(entityMeta.getField(EntityHelper.createdOn))); columnList.add(warpColumn(entityMeta.getField(EntityHelper.createdOn)));
} }
} else { } else {
JSONArray config = (JSONArray) lcr[1]; JSONArray config = (JSONArray) raw[1];
for (Object o : config) { for (Object o : config) {
JSONObject jo = (JSONObject) o; JSONObject jo = (JSONObject) o;
String field = jo.getString("field"); String field = jo.getString("field");
@ -82,6 +85,7 @@ public class DataListManager extends LayoutManager {
Map<String, Object> ret = new HashMap<>(); Map<String, Object> ret = new HashMap<>();
ret.put("entity", entity); ret.put("entity", entity);
ret.put("nameField", nameField.getName());
ret.put("fields", columnList); ret.put("fields", columnList);
return (JSON) JSON.parse(JSON.toJSONString(ret)); return (JSON) JSON.parse(JSON.toJSONString(ret));
} }

View file

@ -0,0 +1,140 @@
/*
Copyright 2018 DEVEZHAO(zhaofang123@gmail.com)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cn.devezhao.rebuild.server.service.base;
import java.text.DecimalFormat;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.Assert;
import cn.devezhao.commons.CalendarUtils;
import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.engine.ID;
import cn.devezhao.rebuild.server.metadata.MetadataHelper;
import cn.devezhao.rebuild.server.service.entitymanage.DisplayType;
import cn.devezhao.rebuild.server.service.entitymanage.EasyMeta;
/**
* 字段值包装
*
* @author zhaofang123@gmail.com
* @since 09/23/2018
*/
public class FieldValueWrapper {
/**
* @param date
* @param field
* @return
*/
public static Object wrapFieldValue(Object value, EasyMeta field) {
if (value == null || StringUtils.isBlank(value.toString())) {
return StringUtils.EMPTY;
}
DisplayType dt = field.getDisplayType();
if (dt == DisplayType.DATE) {
return wrapDate(value, field);
} else if (dt == DisplayType.DATETIME) {
return wrapDatetime(value, field);
} else if (dt == DisplayType.NUMBER) {
return wrapNumber(value, field);
} else if (dt == DisplayType.DECIMAL) {
return wrapDecimal(value, field);
} else if (dt == DisplayType.REFERENCE) {
return wrapReference(value, field);
} else if (/*dt == DisplayType.ID ||*/ dt == DisplayType.PICKLIST
|| dt == DisplayType.IMAGE || dt == DisplayType.FILE || dt == DisplayType.LOCATION) {
// 无需处理
return value;
} else {
return wrapSimple(value, field);
}
}
/**
* @param date
* @param field
* @return
*/
public static String wrapDate(Object date, EasyMeta field) {
String format = field.getFieldExtConfig().getString("dateFormat");
format = StringUtils.defaultIfEmpty(format, field.getDisplayType().getDefaultFormat());
Assert.notNull(format, "No format : " + field.getBaseMeta());
return CalendarUtils.getDateFormat(format).format(date);
}
/**
* @param date
* @param field
* @return
*/
public static String wrapDatetime(Object date, EasyMeta field) {
String format = field.getFieldExtConfig().getString("datetimeFormat");
format = StringUtils.defaultIfEmpty(format, field.getDisplayType().getDefaultFormat());
Assert.notNull(format, "No format : " + field.getBaseMeta());
return CalendarUtils.getDateFormat(format).format(date);
}
/**
* @param number
* @param field
* @return
*/
public static String wrapNumber(Object number, EasyMeta field) {
String format = field.getFieldExtConfig().getString("numberFormat");
format = StringUtils.defaultIfEmpty(format, field.getDisplayType().getDefaultFormat());
Assert.notNull(format, "No format : " + field.getBaseMeta());
return new DecimalFormat(format).format(number);
}
/**
* @param decimal
* @param field
* @return
*/
public static String wrapDecimal(Object decimal, EasyMeta field) {
String format = field.getFieldExtConfig().getString("decimalFormat");
format = StringUtils.defaultIfEmpty(format, field.getDisplayType().getDefaultFormat());
Assert.notNull(format, "No format : " + field.getBaseMeta());
return new DecimalFormat(format).format(decimal);
}
/**
* @param reference
* @param field
* @return
*/
public static Object wrapReference(Object reference, EasyMeta field) {
Object[] referenceValue = (Object[]) reference;
Object[] idNamed = new Object[3];
Entity idEntity = MetadataHelper.getEntity(((ID) referenceValue[0]).getEntityCode());
idNamed[2] = idEntity.getName();
idNamed[1] = referenceValue[1] == null ? StringUtils.EMPTY : referenceValue[1].toString();
idNamed[0] = referenceValue[0].toString();
return idNamed;
}
/**
* @param simple
* @param field
* @return
*/
public static String wrapSimple(Object simple, EasyMeta field) {
return simple.toString().trim();
}
}

View file

@ -108,8 +108,8 @@ public class FormManager extends LayoutManager {
el.put("options", picklist); el.put("options", picklist);
} }
else if (DisplayType.DATETIME.name().equals(dt)) { else if (DisplayType.DATETIME.name().equals(dt)) {
if (!el.containsKey("dateFormat")) { if (!el.containsKey("datetimeFormat")) {
el.put("dateFormat", "yyyy-MM-dd HH:mm:ss"); el.put("datetimeFormat", "yyyy-MM-dd HH:mm:ss");
} }
} }
else if (DisplayType.DATE.name().equals(dt)) { else if (DisplayType.DATE.name().equals(dt)) {
@ -167,7 +167,10 @@ public class FormManager extends LayoutManager {
JSONObject config = (JSONObject) getViewLayout(entity); JSONObject config = (JSONObject) getViewLayout(entity);
JSONArray elements = config.getJSONArray("elements"); JSONArray elements = config.getJSONArray("elements");
Record record = record(recordId, elements); Record record = null;
if (!elements.isEmpty()) {
record = record(recordId, elements);
}
for (Object element : elements) { for (Object element : elements) {
JSONObject el = (JSONObject) element; JSONObject el = (JSONObject) element;

View file

@ -25,29 +25,38 @@ import cn.devezhao.persist4j.dialect.Type;
*/ */
public enum DisplayType { public enum DisplayType {
NUMBER("数字", FieldType.LONG), NUMBER("数字", FieldType.LONG, "##,###"),
DECIMAL("货币", FieldType.DECIMAL), DECIMAL("货币", FieldType.DECIMAL, "##,##0.00"),
DATE("日期", FieldType.DATE),
DATETIME("日期时间", FieldType.TIMESTAMP),
TEXT("文本", FieldType.STRING),
EMAIL("邮箱", FieldType.STRING),
URL("链接", FieldType.STRING),
PHONE("电话", FieldType.STRING),
IMAGE("图片", FieldType.STRING),
FILE("附件", FieldType.STRING),
PICKLIST("列表", FieldType.REFERENCE),
REFERENCE("引用", FieldType.REFERENCE),
ID("主键", FieldType.PRIMARY); DATE("日期", FieldType.DATE, "yyyy-MM-dd"),
DATETIME("日期时间", FieldType.TIMESTAMP, "yyyy-MM-dd HH:mm"),
TEXT("文本", FieldType.STRING, null),
EMAIL("邮箱", FieldType.STRING, null),
URL("链接", FieldType.STRING, null),
PHONE("电话", FieldType.STRING, null),
IMAGE("图片", FieldType.STRING, null),
FILE("附件", FieldType.STRING, null),
PICKLIST("列表", FieldType.REFERENCE, null),
REFERENCE("引用", FieldType.REFERENCE, null),
ID("主键", FieldType.PRIMARY, null),
LOCATION("位置", FieldType.STRING, null),
_BOOL("布尔", FieldType.BOOL, null);
// -- // --
private String displayName; private String displayName;
private Type fieldType; private Type fieldType;
private String defaultFormat;
private DisplayType(String displayName, Type fieldType) { private DisplayType(String displayName, Type fieldType, String defaultFormat) {
this.displayName = displayName; this.displayName = displayName;
this.fieldType = fieldType; this.fieldType = fieldType;
this.defaultFormat = defaultFormat;
} }
public String getDisplayName() { public String getDisplayName() {
@ -58,6 +67,10 @@ public enum DisplayType {
return fieldType; return fieldType;
} }
public String getDefaultFormat() {
return defaultFormat;
}
@Override @Override
public String toString() { public String toString() {
return getDisplayName() + " (" + name().toUpperCase() + ")"; return getDisplayName() + " (" + name().toUpperCase() + ")";

View file

@ -29,8 +29,10 @@ import com.alibaba.fastjson.JSONObject;
import cn.devezhao.persist4j.Entity; import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.Field; import cn.devezhao.persist4j.Field;
import cn.devezhao.persist4j.dialect.FieldType; import cn.devezhao.persist4j.dialect.FieldType;
import cn.devezhao.persist4j.dialect.Type;
import cn.devezhao.persist4j.engine.ID; import cn.devezhao.persist4j.engine.ID;
import cn.devezhao.persist4j.metadata.BaseMeta; import cn.devezhao.persist4j.metadata.BaseMeta;
import cn.devezhao.rebuild.server.RebuildException;
import cn.devezhao.rebuild.server.metadata.EntityHelper; import cn.devezhao.rebuild.server.metadata.EntityHelper;
import cn.devezhao.rebuild.server.metadata.MetadataHelper; import cn.devezhao.rebuild.server.metadata.MetadataHelper;
@ -112,20 +114,44 @@ public class EasyMeta implements BaseMeta {
* @return * @return
*/ */
public String getDisplayType(boolean fullName) { public String getDisplayType(boolean fullName) {
if (baseMeta instanceof Field) { if (isField()) {
Object[] ext = getMetaExt(); DisplayType dt = getDisplayType();
if (ext != null) {
DisplayType dt = (DisplayType) ext[2];
if (fullName) { if (fullName) {
return dt.getDisplayName() + " (" + dt.name() + ")"; return dt.getDisplayName() + " (" + dt.name() + ")";
} else { } else {
return dt.name(); return dt.name();
} }
} else { }
return ((Field) baseMeta).getType().getName().toUpperCase(); throw new UnsupportedOperationException("Non `field` entry");
}
/**
* @return
*/
public DisplayType getDisplayType() {
if (isField()) {
Object[] ext = getMetaExt();
if (ext != null) {
DisplayType dt = (DisplayType) ext[2];
return dt;
}
Type ft = ((Field) baseMeta).getType();
if (ft == FieldType.PRIMARY) {
return DisplayType.ID;
} else if (ft == FieldType.REFERENCE) {
return DisplayType.REFERENCE;
} else if (ft == FieldType.TIMESTAMP) {
return DisplayType.DATETIME;
} else if (ft == FieldType.DATE) {
return DisplayType.DATE;
} else if (ft == FieldType.STRING) {
return DisplayType.TEXT;
} else if (ft == FieldType.BOOL) {
return DisplayType._BOOL;
} }
} }
return null; throw new RebuildException("Unsupported field type : " + this.baseMeta);
} }
/** /**
@ -239,12 +265,7 @@ public class EasyMeta implements BaseMeta {
* @return * @return
*/ */
public static DisplayType getDisplayType(Field field) { public static DisplayType getDisplayType(Field field) {
Object[] ext = MetadataHelper.getFieldExtmeta(field); return new EasyMeta(field).getDisplayType();
if (ext == null) {
return null;
} else {
return (DisplayType) ext[2];
}
} }
/** /**

View file

@ -48,7 +48,7 @@ public class GeneralListControll extends BaseControll {
public ModelAndView pageList(@PathVariable String entity, public ModelAndView pageList(@PathVariable String entity,
HttpServletRequest request) throws IOException { HttpServletRequest request) throws IOException {
ModelAndView mv = createModelAndView("/general-entity/record-list.jsp", entity); ModelAndView mv = createModelAndView("/general-entity/record-list.jsp", entity);
JSON cfg = DataListManager.getListColumnConfig(entity); JSON cfg = DataListManager.getColumnLayout(entity);
mv.getModel().put("DataListConfig", JSON.toJSONString(cfg)); mv.getModel().put("DataListConfig", JSON.toJSONString(cfg));
return mv; return mv;
} }

View file

@ -13,24 +13,27 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package cn.devezhao.rebuild.web.base.entity.datalist; package cn.devezhao.rebuild.web.base.entity.datalist;
import java.text.DecimalFormat;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import cn.devezhao.commons.CalendarUtils;
import cn.devezhao.persist4j.Entity; import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.Field; import cn.devezhao.persist4j.Field;
import cn.devezhao.persist4j.dialect.FieldType; import cn.devezhao.persist4j.dialect.FieldType;
import cn.devezhao.persist4j.dialect.Type;
import cn.devezhao.persist4j.engine.ID; import cn.devezhao.persist4j.engine.ID;
import cn.devezhao.persist4j.query.compiler.SelectItem; import cn.devezhao.persist4j.query.compiler.SelectItem;
import cn.devezhao.rebuild.server.Application;
import cn.devezhao.rebuild.server.metadata.MetadataHelper; import cn.devezhao.rebuild.server.metadata.MetadataHelper;
import cn.devezhao.rebuild.server.service.base.FieldValueWrapper;
import cn.devezhao.rebuild.server.service.entitymanage.EasyMeta;
/** /**
* 数据包装 * 数据包装
@ -39,43 +42,53 @@ import cn.devezhao.rebuild.server.metadata.MetadataHelper;
* @version $Id: DataWrapper.java 1 2014-11-26 17:20:23Z zhaoff@qidapp.com $ * @version $Id: DataWrapper.java 1 2014-11-26 17:20:23Z zhaoff@qidapp.com $
* @since 1.0, 2013-6-20 * @since 1.0, 2013-6-20
*/ */
public class DataWrapper { public class DataWrapper extends FieldValueWrapper {
private static final Log LOG = LogFactory.getLog(DataWrapper.class);
private int total; private int total;
private Object[][] data; private Object[][] data;
private SelectItem[] selectFields; private SelectItem[] selectFields;
private Entity entity;
/** /**
* @param total * @param total
* @param data * @param data
* @param fields * @param selectFields
* @param entity
*/ */
public DataWrapper(int total, Object[][] data, SelectItem[] fields) { public DataWrapper(int total, Object[][] data, SelectItem[] selectFields, Entity entity) {
this.total = total; this.total = total;
this.data = data; this.data = data;
this.selectFields = fields; this.selectFields = selectFields;
this.entity = entity;
} }
/** /**
* @return * @return
*/ */
public String toJson() { public String toJson() {
for (Object[] o : data) { final Field namedFiled = entity.getNameField();
for (Object[] row : data) {
Object namedVal = null;
for (int i = 0; i < selectFields.length; i++) { for (int i = 0; i < selectFields.length; i++) {
if (row[i] == null) {
row[i] = StringUtils.EMPTY;
continue;
}
Field field = selectFields[i].getField(); Field field = selectFields[i].getField();
Type cType = field.getType(); if (field.equals(namedFiled)) {
if (cType == FieldType.DATE) { namedVal = row[i];
o[i] = wrapDate(o[i], field); }
} else if (cType == FieldType.TIMESTAMP) {
o[i] = wrapDatetime(o[i], field); if (field.getType() == FieldType.REFERENCE) {
} else if (cType == FieldType.INT || cType == FieldType.LONG) { row[i] = readReferenceNamed((ID) row[i], null);
o[i] = wrapNumber(o[i], field); } else if (field.getType() == FieldType.PRIMARY) { // Last index always
} else if (cType == FieldType.DOUBLE || cType == FieldType.DECIMAL) { row[i] = readReferenceNamed((ID) row[i], namedVal);
o[i] = wrapDecimal(o[i], field);
} else if (cType == FieldType.BOOL) {
o[i] = wrapBool(o[i], field);
} else { } else {
o[i] = wrapSimple(o[i], field); row[i] = wrapFieldValue(row[i], new EasyMeta(field));
} }
} }
} }
@ -87,84 +100,29 @@ public class DataWrapper {
} }
/** /**
* @param date * 读取 ID 型字段
* @param field *
* @param idVal
* @param namedVal
* @return * @return
*/ */
protected Object wrapDate(Object date, Field field) { protected Object[] readReferenceNamed(ID idVal, Object namedVal) {
if (date == null) { Entity entity = MetadataHelper.getEntity(idVal.getEntityCode());
return StringUtils.EMPTY; Field nameField = entity.getNameField();
if (namedVal == null) {
String sql = String.format("select %s from %s where %s = ?",
nameField.getName(), entity.getName(), entity.getPrimaryField().getName());
Object[] named = Application.createQuery(sql).setParameter(1, idVal).unique();
if (named == null) {
LOG.debug("Reference is deleted : " + idVal);
return null;
} }
return CalendarUtils.getUTCDateFormat().format(date); namedVal = named[0];
} }
/** namedVal = wrapFieldValue(namedVal, new EasyMeta(nameField));
* @param date String[] meta = new String[] { entity.getName(), new EasyMeta(entity).getIcon() };
* @param field return new Object[] { idVal.toLiteral(), namedVal, meta };
* @return
*/
protected Object wrapDatetime(Object date, Field field) {
if (date == null) {
return StringUtils.EMPTY;
}
return CalendarUtils.getUTCDateTimeFormat().format(date);
}
/**
* @param number
* @param field
* @return
*/
protected Object wrapNumber(Object number, Field field) {
if (number == null) {
return StringUtils.EMPTY;
}
String fv = new DecimalFormat("##,###").format(number);
return StringUtils.isEmpty(fv) ? "0" : fv;
}
/**
* @param number
* @param field
* @return
*/
protected Object wrapDecimal(Object number, Field field) {
if (number == null) {
return StringUtils.EMPTY;
}
String fv = new DecimalFormat("##,##0.00").format(number);
return StringUtils.equals(fv, "0.00") ? "0" : fv;
}
/**
* @param bool
* @param field
* @return
*/
protected Object wrapBool(Object bool, Field field) {
return bool == null ? StringUtils.EMPTY : ((Boolean) bool ? "" : "");
}
/**
* @param value
* @param field
* @return
*/
protected Object wrapSimple(Object value, Field field) {
if (value == null) {
return StringUtils.EMPTY;
}
if (value instanceof Object[]) {
Object[] idNamed = (Object[]) value;
Object[] idNamed2 = new Object[3];
Entity idEntity = MetadataHelper.getEntity(((ID) idNamed[0]).getEntityCode());
idNamed2[2] = idEntity.getName();
idNamed2[1] = idNamed[1] == null ? StringUtils.EMPTY : idNamed[1].toString();
idNamed2[0] = idNamed[0].toString();
return idNamed2;
} else {
return value.toString();
}
} }
} }

View file

@ -15,21 +15,10 @@ limitations under the License.
*/ */
package cn.devezhao.rebuild.web.base.entity.datalist; package cn.devezhao.rebuild.web.base.entity.datalist;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.Field;
import cn.devezhao.persist4j.Query; import cn.devezhao.persist4j.Query;
import cn.devezhao.persist4j.engine.ID;
import cn.devezhao.persist4j.query.compiler.SelectItem;
import cn.devezhao.rebuild.server.Application; import cn.devezhao.rebuild.server.Application;
import cn.devezhao.rebuild.server.metadata.MetadataHelper;
import cn.devezhao.rebuild.server.service.base.PickListManager;
import cn.devezhao.rebuild.server.service.entitymanage.DisplayType;
import cn.devezhao.rebuild.server.service.entitymanage.EasyMeta;
/** /**
* 数据列表控制器 * 数据列表控制器
@ -40,7 +29,9 @@ import cn.devezhao.rebuild.server.service.entitymanage.EasyMeta;
*/ */
public class DefaultDataListControl implements DataListControl { public class DefaultDataListControl implements DataListControl {
protected JSONQueryParser queryParser; protected static final int READ_TIMEOUT = 15 * 1000;
protected JsonQueryParser queryParser;
/** /**
*/ */
@ -51,13 +42,13 @@ public class DefaultDataListControl implements DataListControl {
* @param queryElement * @param queryElement
*/ */
public DefaultDataListControl(JSONObject queryElement) { public DefaultDataListControl(JSONObject queryElement) {
this.queryParser = new JSONQueryParser(queryElement, this); this.queryParser = new JsonQueryParser(queryElement, this);
} }
/** /**
* @return * @return
*/ */
public JSONQueryParser getQueryParser() { public JsonQueryParser getQueryParser() {
return queryParser; return queryParser;
} }
@ -68,79 +59,18 @@ public class DefaultDataListControl implements DataListControl {
@Override @Override
public String getResult() { public String getResult() {
int timeout = 10 * 1000;
int total = 0; int total = 0;
if (queryParser.isNeedReload()) { if (queryParser.isNeedReload()) {
String countSql = queryParser.toSqlCount(); String countSql = queryParser.toSqlCount();
total = ((Long) Application.createQuery(countSql).unique()[0]).intValue(); total = ((Long) Application.createQuery(countSql).unique()[0]).intValue();
} }
Query query = Application.createQuery(queryParser.toSql()).setTimeout(timeout); Query query = Application.createQuery(queryParser.toSql()).setTimeout(READ_TIMEOUT);
int[] limit = queryParser.getSqlLimit(); int[] limits = queryParser.getSqlLimit();
Object[][] array = query.setLimit(limit[0], limit[1]).array(); Object[][] array = query.setLimit(limits[0], limits[1]).array();
// 补充引用字段的 NameField DataWrapper wrapper = new DataWrapper(
Field[] fields = queryParser.getFieldList(); total, array, query.getSelectItems(), query.getRootEntity());
for (int i = 0; i < fields.length; i++) {
DisplayType dt = EasyMeta.getDisplayType(fields[i]);
if (dt == DisplayType.REFERENCE) {
for (Object o[] : array) {
o[i] = readReferenceNamed(o[i]);
}
} else if (dt == DisplayType.PICKLIST) {
for (Object o[] : array) {
o[i] = readPickListLabel(o[i], fields[i]);
}
}
}
DataWrapper wrapper = getDataWrapper(total, array, query.getSelectItems());
return wrapper.toJson(); return wrapper.toJson();
} }
/**
* @param total
* @param data
* @param fields
* @return
*/
protected DataWrapper getDataWrapper(int total, Object[][] data, SelectItem[] fields) {
return new DataWrapper(total, data, fields);
}
/**
* @param idVal
* @return
*/
protected Object[] readReferenceNamed(Object idVal) {
if (idVal == null) {
return null;
}
ID id = (ID) idVal;
Entity entity = MetadataHelper.getEntity(id.getEntityCode());
String sql = String.format("select %s from %s where %s = ?",
entity.getNameField().getName(), entity.getName(), entity.getPrimaryField().getName());
Object[] named = Application.createQuery(sql).setParameter(1, id).unique();
return new Object[] { id, named == null ? "" : named[0] };
}
/**
* @param itemId
* @param field
* @return
*/
protected String readPickListLabel(Object itemId, Field field) {
if (itemId == null) {
return null;
}
List<Map<String, Object>> list = PickListManager.getPickListRaw(field.getOwnEntity().getName(), field.getName(), true, false);
for (Map<String, Object> e : list) {
if (itemId.toString().equals(e.get("id"))) {
return (String) e.get("text");
}
}
return "!!!删除!!!";
}
} }

View file

@ -30,6 +30,8 @@ import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.Field; import cn.devezhao.persist4j.Field;
import cn.devezhao.rebuild.server.metadata.EntityHelper; import cn.devezhao.rebuild.server.metadata.EntityHelper;
import cn.devezhao.rebuild.server.metadata.MetadataHelper; import cn.devezhao.rebuild.server.metadata.MetadataHelper;
import cn.devezhao.rebuild.server.service.entitymanage.DisplayType;
import cn.devezhao.rebuild.server.service.entitymanage.EasyMeta;
/** /**
* 列表查询解析 * 列表查询解析
@ -38,7 +40,7 @@ import cn.devezhao.rebuild.server.metadata.MetadataHelper;
* @version $Id: QueryParser.java 1430 2015-04-16 11:29:21Z zhaoff@qidapp.com $ * @version $Id: QueryParser.java 1430 2015-04-16 11:29:21Z zhaoff@qidapp.com $
* @since 1.0, 2013-6-20 * @since 1.0, 2013-6-20
*/ */
public class JSONQueryParser { public class JsonQueryParser {
protected JSONObject queryElement; protected JSONObject queryElement;
@ -56,7 +58,7 @@ public class JSONQueryParser {
* @param queryElement * @param queryElement
* @param dataListControl * @param dataListControl
*/ */
public JSONQueryParser(JSONObject queryElement, DataListControl dataListControl) { public JsonQueryParser(JSONObject queryElement, DataListControl dataListControl) {
this.queryElement = queryElement; this.queryElement = queryElement;
this.dataListControl = dataListControl; this.dataListControl = dataListControl;
@ -107,6 +109,9 @@ public class JSONQueryParser {
StringBuffer sqlBase = new StringBuffer("select "); StringBuffer sqlBase = new StringBuffer("select ");
for (Field field : fieldList) { for (Field field : fieldList) {
if (EasyMeta.getDisplayType(field) == DisplayType.PICKLIST) {
sqlBase.append('&');
}
sqlBase.append(field.getName()).append(','); sqlBase.append(field.getName()).append(',');
} }
// 最后增加一个主键列 // 最后增加一个主键列
@ -195,20 +200,8 @@ public class JSONQueryParser {
*/ */
protected String parseSort(String sort) { protected String parseSort(String sort) {
String[] sort_s = sort.split(":"); String[] sort_s = sort.split(":");
return sort_s[0] + ("desc".equalsIgnoreCase(sort_s[1]) ? " desc" : " asc"); String sortField = sort_s[0];
return sortField + ("desc".equalsIgnoreCase(sort_s[1]) ? " desc" : " asc");
// StringBuffer sb = new StringBuffer();
// int index = 0;
// for (Object o : sortNode) {
// JSONObject el = (JSONObject) o;
// String field = el.getString("field");
// String type = BooleanUtils.toBoolean(el.getString("ascending")) ? " asc" : " desc";
//
// sb.append(index++ == 0 ? ' ' : ',')
// .append(field)
// .append(type);
// }
// return sb.toString();
} }
/** /**

View file

@ -87,7 +87,7 @@
<index type="unique" field-list="belongEntity,physicalName"/> <index type="unique" field-list="belongEntity,physicalName"/>
</entity> </entity>
<entity name="PickList" type-code="012" description="下拉列表配置选项"> <entity name="PickList" type-code="012" name-field="text" description="下拉列表配置选项">
<field name="itemId" type="primary"/> <field name="itemId" type="primary"/>
<field name="belongEntity" type="string" max-length="100" nullable="false" updatable="false" /> <field name="belongEntity" type="string" max-length="100" nullable="false" updatable="false" />
<field name="belongField" type="string" max-length="100" nullable="false" updatable="false" /> <field name="belongField" type="string" max-length="100" nullable="false" updatable="false" />

View file

@ -52,7 +52,7 @@
<servlet> <servlet>
<servlet-name>FileUploader</servlet-name> <servlet-name>FileUploader</servlet-name>
<servlet-class>cn.devezhao.rebuild.web.commons.FileUploader</servlet-class> <servlet-class>cn.devezhao.rebuild.web.common.FileUploader</servlet-class>
</servlet> </servlet>
<servlet-mapping> <servlet-mapping>
<servlet-name>FileUploader</servlet-name> <servlet-name>FileUploader</servlet-name>
@ -60,7 +60,7 @@
</servlet-mapping> </servlet-mapping>
<servlet> <servlet>
<servlet-name>FileDownload</servlet-name> <servlet-name>FileDownload</servlet-name>
<servlet-class>cn.devezhao.rebuild.web.commons.FileDownload</servlet-class> <servlet-class>cn.devezhao.rebuild.web.common.FileDownload</servlet-class>
</servlet> </servlet>
<servlet-mapping> <servlet-mapping>
<servlet-name>FileDownload</servlet-name> <servlet-name>FileDownload</servlet-name>

View file

@ -1,6 +1,6 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/material-design-iconic-font.min.css"> <link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/material-design-iconic-font.min.css">
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/perfect-scrollbar.min.css"> <link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/perfect-scrollbar.min.css">
<link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/bootstrap-datetimepicker.min.css"> <link rel="stylesheet" type="text/css" href="${baseUrl}/assets/lib/bootstrap-datetimepicker.min.css">

View file

@ -5,7 +5,7 @@
<%@ include file="/_include/Head.jsp"%> <%@ include file="/_include/Head.jsp"%>
<title>实体管理</title> <title>实体管理</title>
<style type="text/css"> <style type="text/css">
a#entityIcon{display:inline-block;width:36px;height:36px;background-color:rgb(213, 216, 222);text-align:center;border-radius:2px;} a#entityIcon{display:inline-block;width:36px;height:36px;background-color:#e3e3e3;text-align:center;border-radius:2px;}
a#entityIcon .icon{font-size:26px;color:#555;line-height:36px;} a#entityIcon .icon{font-size:26px;color:#555;line-height:36px;}
a#entityIcon:hover{opacity:0.8} a#entityIcon:hover{opacity:0.8}
</style> </style>

View file

@ -7,10 +7,11 @@
<style type="text/css"> <style type="text/css">
.card.entity:hover{background-color:rgba(255,255,255,.7)} .card.entity:hover{background-color:rgba(255,255,255,.7)}
.card.entity .card-body{padding:14px 20px;color:#333;} .card.entity .card-body{padding:14px 20px;color:#333;}
.card.entity .icon{font-size:32px;margin-right:12px;color:#4285f4;} .card.entity .icon{font-size:32px;color:#4285f4;}
.card.entity .card-body .float-left{width:30px;text-align:center;}
.card.entity span{margin-top:2px;display:block;} .card.entity span{margin-top:2px;display:block;}
.card.entity p{margin:0} .card.entity p{margin:0}
.title{margin-left:43px} .title{margin-left:44px}
</style> </style>
</head> </head>
<body> <body>

View file

@ -71,13 +71,13 @@
<div class="form-group row J_for-DECIMAL hide"> <div class="form-group row J_for-DECIMAL hide">
<label class="col-sm-2 col-form-label text-sm-right">小数位长度</label> <label class="col-sm-2 col-form-label text-sm-right">小数位长度</label>
<div class="col-lg-4 col-sm-10"> <div class="col-lg-4 col-sm-10">
<select class="form-control form-control-sm" id="decimalPrecision"> <select class="form-control form-control-sm" id="decimalFormat">
<option value="1">1位</option> <option value="##,##0.0">1位</option>
<option value="2" selected="selected">2位</option> <option value="##,##0.00" selected="selected">2位</option>
<option value="3">3位</option> <option value="##,##0.000">3位</option>
<option value="4">4位</option> <option value="##,##0.0000">4位</option>
<option value="5">5位</option> <option value="##,##0.00000">5位</option>
<option value="6">6位</option> <option value="##,##0.000000">6位</option>
</select> </select>
</div> </div>
</div> </div>
@ -87,11 +87,20 @@
<div class="form-control-plaintext"><a href="../../${fieldRefentity}/base">${fieldRefentityLabel} (${fieldRefentity})</a></div> <div class="form-control-plaintext"><a href="../../${fieldRefentity}/base">${fieldRefentityLabel} (${fieldRefentity})</a></div>
</div> </div>
</div> </div>
<div class="form-group row J_for-DATETIME hide"> <div class="form-group row J_for-DATE hide">
<label class="col-sm-2 col-form-label text-sm-right">格式</label> <label class="col-sm-2 col-form-label text-sm-right">格式</label>
<div class="col-lg-4 col-sm-10"> <div class="col-lg-4 col-sm-10">
<select class="form-control form-control-sm" id="dateFormat"> <select class="form-control form-control-sm" id="dateFormat">
<option value="yyyy">YYYY</option>
<option value="yyyy-MM">YYYY-MM</option> <option value="yyyy-MM">YYYY-MM</option>
<option value="yyyy-MM-dd" selected="selected">YYYY-MM-DD</option>
</select>
</div>
</div>
<div class="form-group row J_for-DATETIME hide">
<label class="col-sm-2 col-form-label text-sm-right">格式</label>
<div class="col-lg-4 col-sm-10">
<select class="form-control form-control-sm" id="datetimeFormat">
<option value="yyyy-MM-dd">YYYY-MM-DD</option> <option value="yyyy-MM-dd">YYYY-MM-DD</option>
<option value="yyyy-MM-dd HH:mm" selected="selected">YYYY-MM-DD HH:MM</option> <option value="yyyy-MM-dd HH:mm" selected="selected">YYYY-MM-DD HH:MM</option>
<option value="yyyy-MM-dd HH:mm:ss">YYYY-MM-DD HH:MM:SS</option> <option value="yyyy-MM-dd HH:mm:ss">YYYY-MM-DD HH:MM:SS</option>
@ -134,7 +143,7 @@
</div> </div>
<div class="form-group row footer"> <div class="form-group row footer">
<div class="col-lg-4 col-sm-10 offset-sm-2"> <div class="col-lg-4 col-sm-10 offset-sm-2">
<button class="btn btn-primary" type="button">保存</button> <button class="btn btn-primary J_save" type="button">保存</button>
<div class="alert alert-warning alert-icon hide"> <div class="alert alert-warning alert-icon hide">
<div class="icon"><span class="zmdi zmdi-alert-triangle"></span></div> <div class="icon"><span class="zmdi zmdi-alert-triangle"></span></div>
<div class="message">系统内建字段,不允许修改</div> <div class="message">系统内建字段,不允许修改</div>
@ -163,7 +172,7 @@ $(document).ready(function(){
if (dt.indexOf('(') > -1) dt = dt.match('\\((.+?)\\)')[1]; if (dt.indexOf('(') > -1) dt = dt.match('\\((.+?)\\)')[1];
const extConfigOld = JSON.parse('${fieldExtConfig}' || '{}'); const extConfigOld = JSON.parse('${fieldExtConfig}' || '{}');
const btn = $('.btn-primary').click(function(){ const btn = $('.J_save').click(function(){
if (!!!metaId) return; if (!!!metaId) return;
let label = $val('#fieldLabel'), let label = $val('#fieldLabel'),
comments = $val('#comments'), comments = $val('#comments'),

View file

@ -21,6 +21,7 @@
<select class="form-control form-control-sm" id="type"> <select class="form-control form-control-sm" id="type">
<option value="NUMBER">整数</option> <option value="NUMBER">整数</option>
<option value="DECIMAL">货币</option> <option value="DECIMAL">货币</option>
<option value="DATE">日期</option>
<option value="DATETIME">日期时间</option> <option value="DATETIME">日期时间</option>
<option value="TEXT">文本</option> <option value="TEXT">文本</option>
<option value="PHONE">电话</option> <option value="PHONE">电话</option>
@ -83,7 +84,7 @@ $(document).ready(function(){
let referenceLoaded = false; let referenceLoaded = false;
$('#type').change(function(){ $('#type').change(function(){
if (parent && parent.newFieldModal) parent.newFieldModal.loaded() if (parent && parent.newFieldModal) parent.newFieldModal.resize()
if ($(this).val() == 'REFERENCE'){ if ($(this).val() == 'REFERENCE'){
$('.J_dt-REFERENCE').removeClass('hide'); $('.J_dt-REFERENCE').removeClass('hide');
if (referenceLoaded == false){ if (referenceLoaded == false){

View file

@ -94,9 +94,9 @@ $(document).ready(function(){
$(res.data).each(function(){ $(res.data).each(function(){
let tr = $('<tr data-id="' + (this.fieldId || '') + '"></tr>').appendTo(tbody); let tr = $('<tr data-id="' + (this.fieldId || '') + '"></tr>').appendTo(tbody);
$('<td><a href="field/' + this.fieldName + '" class="column-main">' + this.fieldLabel + '</a></td>').appendTo(tr); $('<td><a href="field/' + this.fieldName + '" class="column-main">' + this.fieldLabel + '</a></td>').appendTo(tr);
$('<td>' + this.fieldName + '</td>').appendTo(tr); $('<td><div class="text-muted">' + this.fieldName + '</div></td>').appendTo(tr);
$('<td>' + this.displayType + '</td>').appendTo(tr); $('<td>' + this.displayType + '</td>').appendTo(tr);
$('<td><div style="max-width:300px">' + (this.comments || '--') + '</div></td>').appendTo(tr); $('<td><div>' + (this.comments || '') + '</div></td>').appendTo(tr);
let actions = $('<td class="actions"><a class="icon J_edit" href="field/' + this.fieldName + '"><i class="zmdi zmdi-settings"></i></a><a class="icon J_del"><i class="zmdi zmdi-delete"></i></a></td>').appendTo(tr); let actions = $('<td class="actions"><a class="icon J_edit" href="field/' + this.fieldName + '"><i class="zmdi zmdi-settings"></i></a><a class="icon J_del"><i class="zmdi zmdi-delete"></i></a></td>').appendTo(tr);
actions.find('.J_del').click(function(){ actions.find('.J_del').click(function(){
if (!!!tr.data('id')){ if (!!!tr.data('id')){

View file

@ -57,7 +57,7 @@
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
字段列表 字段列表
<div class="float-right"><span class="not-nullable">必填</span><span class="readonly">只读</span></div> <div class="float-right"><span class="not-nullable">必填字段</span><span class="readonly">只读字段</span></div>
</div> </div>
<div class="card-body" style="padding-top:6px"> <div class="card-body" style="padding-top:6px">
<div class="field-list dd-list connectedSortable"> <div class="field-list dd-list connectedSortable">

View file

@ -120,7 +120,7 @@ const itemRender = function(data, append){
item.find('.dd3-action .J_del').off('click').click(function(){ item.find('.dd3-action .J_del').off('click').click(function(){
$(this).parent().parent().remove() $(this).parent().parent().remove()
}); });
if (data['default'] === true) item.find('.dd3-action .J_default').trigger('click') if (data['default'] === true && append == '.J_showbox') item.find('.dd3-action .J_default').trigger('click')
}; };
</script> </script>
</body> </body>

View file

@ -5844,6 +5844,16 @@ button.close {
margin: -1rem -1rem -1rem auto margin: -1rem -1rem -1rem auto
} }
.modal-header > .icon {
font-size: 2.1rem;
color: #4285f4;
width: 24px;
overflow: hidden;
text-align: center;
margin-right: 9px;
margin-top: 2px;
}
.modal-title { .modal-title {
margin-bottom: 0; margin-bottom: 0;
line-height: 1.428571 line-height: 1.428571
@ -18873,7 +18883,7 @@ pre code {
width: 1.51rem; width: 1.51rem;
height: 1.51rem; height: 1.51rem;
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 3px; border-radius: 2px;
margin: 0 0 margin: 0 0
} }
@ -18885,6 +18895,7 @@ pre code {
font-weight: 400; font-weight: 400;
text-align: center; text-align: center;
line-height: 1.1; line-height: 1.1;
margin-left: -1px;
} }
.custom-radio .custom-control-label:before { .custom-radio .custom-control-label:before {

View file

@ -288,7 +288,7 @@ a {
width: 12px; width: 12px;
height: 32px; height: 32px;
cursor: pointer; cursor: pointer;
padding-top: 10px; padding-top: 12px;
} }
.col-form-label em { .col-form-label em {
@ -308,7 +308,7 @@ a {
} }
.rbnotice { .rbnotice {
position: absolute; position: fixed;
width: 360px; width: 360px;
top: 6px; top: 6px;
left: 50%; left: 50%;
@ -405,6 +405,11 @@ i.split.ui-draggable-dragging {
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
clear: both; clear: both;
max-width: 300px;
}
.data-list .table td, .data-list .table td>div.nmw {
max-width: 1000px;
} }
.data-list td .img-zoom { .data-list td .img-zoom {
@ -436,12 +441,26 @@ i.split.ui-draggable-dragging {
padding-left: 0px; padding-left: 0px;
} }
.column-checkbox .custom-control-label::after {
margin-left: 0 !important;
}
.column-main { .column-main {
border-bottom: 1px dotted; border-bottom: 1px solid;
}
.column-main:hover {
border-bottom: 0 solid;
}
.column-url {
}
.column-url:hover {
text-decoration: underline;
} }
.column-empty { .column-empty {
} }
.text-3dot { .text-3dot {
@ -573,6 +592,7 @@ h5.sortable-box-title {
} }
.rbview-form { .rbview-form {
} }
.rbview-form .card-header-divider { .rbview-form .card-header-divider {
@ -589,3 +609,7 @@ h5.sortable-box-title {
.rbview-form .form-control-plaintext:hover { .rbview-form .form-control-plaintext:hover {
background-color: #f8f8f8 background-color: #f8f8f8
} }
.main-content .card.card-table {
margin-bottom: 0;
}

View file

@ -134,7 +134,7 @@ const $regex = {
_Number:/^[-+]?[0-9]+$/, // 数字 _Number:/^[-+]?[0-9]+$/, // 数字
_Decimal:/^[-+]?\d*\.?\d+$/, // 包括小数点的数字 _Decimal:/^[-+]?\d*\.?\d+$/, // 包括小数点的数字
_Mobile:/^(13[0-9]|15[0-9]|18[0-9]|17[0-9])\d{8}$/, _Mobile:/^(13[0-9]|15[0-9]|18[0-9]|17[0-9])\d{8}$/,
_Tel:/^[0-9-]{4,20}$/, _Tel:/^[0-9-]{4,18}$/,
_Text:/^[a-z\d\u4E00-\u9FA5]+$/i, // 不含特殊字符和标点 _Text:/^[a-z\d\u4E00-\u9FA5]+$/i, // 不含特殊字符和标点
isDate:function(val){ isDate:function(val){
return this._Date.test(val); return this._Date.test(val);

View file

@ -63,14 +63,16 @@ class RbView extends React.Component {
this.state = { ...props, inLoad: true, isShow: false } this.state = { ...props, inLoad: true, isShow: false }
} }
render() { render() {
let adminUrl = rb.baseUrl + '/admin/entity/' + this.props.entity + '/view-design'
return ( return (
<div className={'modal rbview ' + (this.state.isShow == true && 'show')} ref="rbview"> <div className={'modal rbview ' + (this.state.isShow == true && 'show')} ref="rbview">
<div className="modal-dialog"> <div className="modal-dialog">
<div className="modal-content"> <div className="modal-content">
<div className="modal-header"> <div className="modal-header">
<h3 className="modal-title">{this.state.title || 'RbView'}</h3> {this.state.icon ? (<span className={'icon zmdi zmdi-' + this.state.icon}></span>) : '' }
<a className="close admin-settings" href={adminUrl} title="配置布局" target="_blank"><span className="zmdi zmdi-settings"></span></a> <h3 className="modal-title">
{this.state.title || '视图'}
</h3>
<a className="close admin-settings" href={rb.baseUrl + '/admin/entity/' + this.state.entity + '/view-design'} title="配置布局" target="_blank"><span className="zmdi zmdi-settings"></span></a>
<button className="close" type="button" onClick={()=>this.hide()}><span className="zmdi zmdi-close"></span></button> <button className="close" type="button" onClick={()=>this.hide()}><span className="zmdi zmdi-close"></span></button>
</div> </div>
<div className={'modal-body iframe rb-loading ' + (this.state.inLoad == true && 'rb-loading-active')}> <div className={'modal-body iframe rb-loading ' + (this.state.inLoad == true && 'rb-loading-active')}>
@ -102,11 +104,12 @@ class RbView extends React.Component {
this.setState({ inLoad: false }) this.setState({ inLoad: false })
} }
} }
show(url) { show(url, ext) {
this.state.url = url || this.state.url ext = ext || {}
url = url || this.state.url
let root = $(this.refs['rbview']) let root = $(this.refs['rbview'])
let that = this let that = this
this.setState({ isShow: true }, function(){ this.setState({ ...ext, isShow: true, url: url }, function(){
root.find('.modal-content').animate({ 'margin-right': 0 }, 400) root.find('.modal-content').animate({ 'margin-right': 0 }, 400)
setTimeout(function(){ setTimeout(function(){
that.setState({ showAfterUrl: that.state.url }) that.setState({ showAfterUrl: that.state.url })
@ -237,8 +240,8 @@ rb.modal = function(url, title, ext) {
// //
var viewModal var viewModal
rb.recordView = function(id, entity) { rb.recordView = function(id, title, entity, icon) {
let viewUrl = rb.baseUrl + '/app/' + entity + '/view/' + id let viewUrl = rb.baseUrl + '/app/' + entity + '/view/' + id
if (viewModal) viewModal.show(viewUrl) if (viewModal) viewModal.show(viewUrl, { entity: entity, title: title, icon: icon })
else viewModal = renderRbcomp(<RbView url={viewUrl} entity={entity} />) else viewModal = renderRbcomp(<RbView url={viewUrl} entity={entity} title={title} icon={icon} />)
} }

View file

@ -77,7 +77,7 @@ const __detectElement = function(item){
return <RbFormImage {...item} /> return <RbFormImage {...item} />
} else if (item.type == 'FILE'){ } else if (item.type == 'FILE'){
return <RbFormFile {...item} /> return <RbFormFile {...item} />
} else if (item.type == 'DATETIME'){ } else if (item.type == 'DATETIME' || item.type == 'DATE'){
return <RbFormDateTime {...item} /> return <RbFormDateTime {...item} />
} else if (item.type == 'PICKLIST'){ } else if (item.type == 'PICKLIST'){
return <RbFormPickList {...item} /> return <RbFormPickList {...item} />
@ -123,7 +123,7 @@ class RbForm extends React.Component {
__renderFormError(message) { __renderFormError(message) {
let fdUrl = rb.baseUrl + '/admin/entity/' + this.props.entity + '/form-design' let fdUrl = rb.baseUrl + '/admin/entity/' + this.props.entity + '/form-design'
message = message || `表单尚未配置,请 <a href="${fdUrl}">配置</a> 后使用` message = message || `表单尚未配置,请 <a href="${fdUrl}">配置</a> 后使用`
message = { __html: '<strong>Opps! </strong> ' + message } message = { __html: '<strong>错误! </strong> ' + message }
return <div class="alert alert-contrast alert-warning"> return <div class="alert alert-contrast alert-warning">
<div class="icon"><span class="zmdi zmdi-alert-triangle"></span></div> <div class="icon"><span class="zmdi zmdi-alert-triangle"></span></div>
<div class="message" dangerouslySetInnerHTML={message}></div> <div class="message" dangerouslySetInnerHTML={message}></div>
@ -331,7 +331,7 @@ class RbFormDateTime extends RbFormElement {
} }
componentDidMount() { componentDidMount() {
super.componentDidMount() super.componentDidMount()
let format = (this.props.dateFormat || 'yyyy-MM-dd HH:mm:ss').replace('mm', 'ii').toLowerCase() let format = (this.props.datetimeFormat || this.props.dateFormat).replace('mm', 'ii').toLowerCase()
let minView = 0 let minView = 0
switch (format.length) { switch (format.length) {
case 7: case 7:

View file

@ -11,7 +11,7 @@ class RbList extends React.Component {
this.setPageSize = this.setPageSize.bind(this) this.setPageSize = this.setPageSize.bind(this)
this.__defaultColumnWidth = $('#react-list').width() / 10 this.__defaultColumnWidth = $('#react-list').width() / 10
this.__defaultColumnWidth = 130; if (this.__defaultColumnWidth < 130) this.__defaultColumnWidth = 130
} }
render() { render() {
let that = this; let that = this;
@ -39,12 +39,12 @@ class RbList extends React.Component {
<tbody> <tbody>
{this.state.rowData.map((item, index) => { {this.state.rowData.map((item, index) => {
let lastGhost = item[lastIndex]; let lastGhost = item[lastIndex];
return (<tr className={lastGhost[1] && 'table-active'} data-id={lastGhost[0]} onClick={this.clickRow.bind(this, index, false)}> return (<tr className={lastGhost[3] && 'table-active'} data-id={lastGhost[0]} onClick={this.clickRow.bind(this, index, false)}>
<td className="column-checkbox"> <td className="column-checkbox">
<div><label className="custom-control custom-control-sm custom-checkbox"><input className="custom-control-input" type="checkbox" checked={lastGhost[1]} onClick={this.clickRow.bind(this, index, true)} /><span className="custom-control-label"></span></label></div> <div><label className="custom-control custom-control-sm custom-checkbox"><input className="custom-control-input" type="checkbox" checked={lastGhost[3]} onClick={this.clickRow.bind(this, index, true)} /><span className="custom-control-label"></span></label></div>
</td> </td>
{item.map((cell, index) => { {item.map((cell, index) => {
return that.__renderCell(cell, index) return that.__renderCell(cell, index, lastGhost)
})} })}
<td className="column-empty"></td> <td className="column-empty"></td>
</tr>) </tr>)
@ -78,15 +78,16 @@ class RbList extends React.Component {
} }
componentDidUpdate() { componentDidUpdate() {
let that = this let that = this
let selectedRows = [] this.__selectedRows = []
this.state.rowData.forEach((item) => { this.state.rowData.forEach((item) => {
let lastGhost = item[that.state.fields.length]; let lastGhost = item[that.state.fields.length];
if (lastGhost[1] == true) selectedRows.push(lastGhost[0]) if (lastGhost[3] == true) that.__selectedRows.push(lastGhost)
}) })
$('.J_delete, .J_view').attr('disabled', true) $('.J_delete, .J_view').attr('disabled', true)
if (selectedRows.length > 0) $('.J_delete').attr('disabled', false) let sLen = this.__selectedRows.length
if (selectedRows.length == 1) $('.J_view').attr('disabled', false) if (sLen > 0) $('.J_delete').attr('disabled', false)
this.__selectedRows = selectedRows if (sLen == 1) $('.J_view').attr('disabled', false)
} }
fetchList(filter) { fetchList(filter) {
@ -114,13 +115,13 @@ class RbList extends React.Component {
if (_rowData.length == 0) { if (_rowData.length == 0) {
that.setState({ noData: true }); that.setState({ noData: true });
} else { } else {
let lastIndex = _rowData[0].length - 1; let lastIndex = _rowData[0].length - 1
_rowData = _rowData.map((item) => { _rowData = _rowData.map((item) => {
item[lastIndex] = [item[lastIndex], false] // [ID, Checked?] item[lastIndex][3] = false // Checked?
return item; return item;
}) })
} }
that.setState({ rowData: _rowData, rowTotal: res.data.total }); that.setState({ rowData: _rowData, rowTotal: res.data.total })
}else{ }else{
rb.notice(res.error_msg || '数据加载失败,请稍后重试', 'error') rb.notice(res.error_msg || '数据加载失败,请稍后重试', 'error')
} }
@ -130,63 +131,71 @@ class RbList extends React.Component {
// //
__renderCell(cellVal, index) { __renderCell(cellVal, index, lastGhost) {
if (this.state.fields.length == index) return null; if (this.state.fields.length == index) return null
if (!!!cellVal) return <td><div></div></td>; if (!!!cellVal) return <td><div></div></td>
let ft = this.state.fields[index].type; const field = this.state.fields[index]
let styles = { width: (this.state.fields[index].width || this.__defaultColumnWidth) + 'px' } let styles = { width: (this.state.fields[index].width || this.__defaultColumnWidth) + 'px' }
if (ft == 'IMAGE') { if (field.type == 'IMAGE') {
cellVal = JSON.parse(cellVal) cellVal = JSON.parse(cellVal || '[]')
return <td><div style={styles}>{cellVal.map((item)=>{ return <td><div style={styles}>{cellVal.map((item)=>{
return <a href={'#!/Preview/' + item} className="img-thumbnail img-zoom"><img src={rb.storageUrl + item} /></a> return <a href={'#!/Preview/' + item} className="img-thumbnail img-zoom"><img src={rb.storageUrl + item} /></a>
})}<div className="clearfix" /></div></td>; })}<div className="clearfix" /></div></td>
} else if (ft == 'FILE') { } else if (field.type == 'FILE') {
cellVal = JSON.parse(cellVal); cellVal = JSON.parse(cellVal || '[]')
return <td><div style={styles}>{cellVal.map((item)=>{ return <td><div style={styles}>{cellVal.map((item)=>{
let fileName = item.split('/'); let fileName = item.split('/')
if (fileName.length > 1) fileName = fileName[fileName.length - 1]; if (fileName.length > 1) fileName = fileName[fileName.length - 1];
fileName = fileName.substr(15); fileName = fileName.substr(15);
return <a href={'#!/Preview/' + item}>{fileName}</a> return <a href={'#!/Preview/' + item}>{fileName}</a>
})}</div></td>; })}</div></td>;
} else if ($.type(cellVal) == 'array'){ } else if (field.type == 'REFERENCE'){
return <td><div style={styles}><a href={'#!/View/' + cellVal[2] + '/' + cellVal[0]} onClick={() => this.clickView(cellVal)}>{cellVal[1]}</a></div></td>; return <td><div style={styles}><a href={'#!/View/' + cellVal[2][0] + '/' + cellVal[0]} onClick={() => this.clickView(cellVal)}>{cellVal[1]}</a></div></td>
} else if (field.field == this.props.config.nameField){
cellVal = lastGhost
return <td><div style={styles}><a href={'#!/View/' + cellVal[2][0] + '/' + cellVal[0]} onClick={() => this.clickView(cellVal)} className="column-main">{cellVal[1]}</a></div></td>
} else if (field.type == 'URL') {
return <td><div style={styles}><a href={rb.baseUrl + '/common/url-safe?url=' + encodeURIComponent(cellVal)} className="column-url" target="_blank">{cellVal}</a></div></td>
} else if (field.type == 'EMAIL') {
return <td><div style={styles}><a href={'mailto:' + cellVal} className="column-url">{cellVal}</a></div></td>
} else { } else {
return <td><div style={styles}>{cellVal || ''}</div></td>; return <td><div style={styles}>{cellVal}</div></td>
} }
} }
toggleAllRow(e) { toggleAllRow(e) {
let checked = this.state.checkedAll == false; let checked = this.state.checkedAll == false
let _rowData = this.state.rowData; let _rowData = this.state.rowData
_rowData = _rowData.map((item) => { _rowData = _rowData.map((item) => {
item[item.length - 1][1] = checked; // Checked? item[item.length - 1][3] = checked // Checked?
return item; return item;
}); });
this.setState({ checkedAll: checked, rowData: _rowData }); this.setState({ checkedAll: checked, rowData: _rowData })
return false; return false;
} }
clickRow(rowIndex, holdOthers, e) { clickRow(rowIndex, holdOthers, e) {
if (e.target.tagName == 'SPAN') return false; if (e.target.tagName == 'SPAN') return false
e.stopPropagation() e.stopPropagation()
e.nativeEvent.stopImmediatePropagation() e.nativeEvent.stopImmediatePropagation()
let _rowData = this.state.rowData; let _rowData = this.state.rowData
let lastIndex = _rowData[0].length - 1; let lastIndex = _rowData[0].length - 1
if (holdOthers == true){ if (holdOthers == true){
let item = _rowData[rowIndex]; let item = _rowData[rowIndex];
item[lastIndex][1] = item[lastIndex][1] == false; // Checked? item[lastIndex][3] = item[lastIndex][3] == false // Checked?
_rowData[rowIndex] = item; _rowData[rowIndex] = item
} else { } else {
_rowData = _rowData.map((item, index) => { _rowData = _rowData.map((item, index) => {
item[lastIndex][1] = index == rowIndex; item[lastIndex][3] = index == rowIndex
return item; return item
}) })
} }
this.setState({ rowData: _rowData }); this.setState({ rowData: _rowData })
return false; return false
} }
clickView(cellVal) { clickView(cellVal) {
console.log(cellVal) console.log(cellVal)
rb.recordView(cellVal[0], cellVal[1], cellVal[2][0], cellVal[2][1])
return false; return false;
} }
@ -209,7 +218,7 @@ class RbList extends React.Component {
// //
getSelectedIds() { getSelectedRows() {
return this.__selectedRows return this.__selectedRows
} }

View file

@ -75,15 +75,18 @@ $(document).ready(function(){
else rbFormModal = renderRbcomp(<RbFormModal title="新建${entityLabel}" entity="${entityName}" />, 'react-forms') else rbFormModal = renderRbcomp(<RbFormModal title="新建${entityLabel}" entity="${entityName}" />, 'react-forms')
}); });
$('.J_delete').click(function(){ $('.J_delete').click(function(){
let ids = rbList.getSelectedIds() let s = rbList.getSelectedRows()
if (ids.length < 1) return if (s.length < 1) return
rb.alter('确认删除选中的 ' + ids.length + ' 条记录吗?', '删除确认', { type: 'danger', confirm: function(){ rb.alter('确认删除选中的 ' + s.length + ' 条记录吗?', '删除确认', { type: 'danger', confirm: function(){
console.log('TODO delete ... ') console.log('TODO delete ... ' + JSON.stringify(s))
} }) } })
}); });
$('.J_view').click(function(){ $('.J_view').click(function(){
let ids = rbList.getSelectedIds() let s = rbList.getSelectedRows()
if (ids.length == 1) rb.recordView(ids[0], '${entityName}') if (s.length == 1) {
s = s[0]
rb.recordView(s[0], s[1], s[2][0], s[2][1])
}
}); });
$('.J_columnset').click(function(){ $('.J_columnset').click(function(){

View file

@ -24,10 +24,10 @@
<input class="form-control" id="passwd" type="password" placeholder="密码"> <input class="form-control" id="passwd" type="password" placeholder="密码">
</div> </div>
<div class="form-group row login-tools"> <div class="form-group row login-tools">
<div class="col-6 login-remember"> <div class="col-6 login-remember">
<label class="custom-control custom-checkbox"> <label class="custom-control custom-checkbox custom-control-inline" style="margin-bottom:0">
<input class="custom-control-input" type="checkbox"> <input class="custom-control-input" type="checkbox"><span class="custom-control-label"> 记住登录</span>
<span class="custom-control-label">记住登录</span>
</label> </label>
</div> </div>
<div class="col-6 login-forgot-password"> <div class="col-6 login-forgot-password">