forked from p81075629/datagear
完善添加数据操作的批量执行功能
This commit is contained in:
parent
b4db6d0364
commit
fe8ecd6fd9
|
@ -8,6 +8,7 @@ import java.sql.Connection;
|
|||
|
||||
import org.datagear.model.Model;
|
||||
import org.datagear.model.support.PropertyPathInfo;
|
||||
import org.datagear.persistence.support.ExpressionEvaluationContext;
|
||||
|
||||
/**
|
||||
* 持久化管理器。
|
||||
|
@ -17,6 +18,21 @@ import org.datagear.model.support.PropertyPathInfo;
|
|||
*/
|
||||
public interface PersistenceManager
|
||||
{
|
||||
/**
|
||||
* 获取指定{@linkplain Model}的表名称。
|
||||
*
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
String getTableName(Model model);
|
||||
|
||||
/**
|
||||
* 获取此{@linkplain PersistenceManager}使用的{@linkplain DialectSource}。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
DialectSource getDialectSource();
|
||||
|
||||
/**
|
||||
* 插入数据。
|
||||
*
|
||||
|
@ -27,6 +43,21 @@ public interface PersistenceManager
|
|||
*/
|
||||
void insert(Connection cn, Model model, Object obj) throws PersistenceException;
|
||||
|
||||
/**
|
||||
* 插入数据
|
||||
*
|
||||
* @param cn
|
||||
* @param dialect
|
||||
* @param table
|
||||
* @param model
|
||||
* @param obj
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
* @throws PersistenceException
|
||||
*/
|
||||
int insert(Connection cn, Dialect dialect, String table, Model model, Object obj,
|
||||
ExpressionEvaluationContext expressionEvaluationContext) throws PersistenceException;
|
||||
|
||||
/**
|
||||
* 更新数据。
|
||||
*
|
||||
|
@ -41,6 +72,22 @@ public interface PersistenceManager
|
|||
int update(Connection cn, Model model, Object originalObj, Object updateObj, boolean updateMultipleProperty)
|
||||
throws PersistenceException;
|
||||
|
||||
/**
|
||||
* 更新数据。
|
||||
*
|
||||
* @param cn
|
||||
* @param dialect
|
||||
* @param table
|
||||
* @param model
|
||||
* @param originalObj
|
||||
* @param updateObj
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
* @throws PersistenceException
|
||||
*/
|
||||
int update(Connection cn, Dialect dialect, String table, Model model, Object originalObj, Object updateObj,
|
||||
ExpressionEvaluationContext expressionEvaluationContext) throws PersistenceException;
|
||||
|
||||
/**
|
||||
* 插入单元属性值。
|
||||
*
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.datagear.model.support.MU;
|
|||
import org.datagear.persistence.UnsupportedModelCharacterException;
|
||||
import org.datagear.persistence.support.ExpressionResolver.Expression;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.expression.ExpressionException;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
|
||||
/**
|
||||
|
@ -280,7 +281,7 @@ public abstract class AbstractExpressionModelPersistenceOperation extends Abstra
|
|||
expressionValues.add(value);
|
||||
expressionEvaluationContext.putCachedValue(expression, value);
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (ExpressionException e)
|
||||
{
|
||||
throw new VariableExpressionErrorException(expression, e);
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ public class DefaultPersistenceManager extends AbstractModelDataAccessObject imp
|
|||
this.selectPersistenceOperation = new SelectPersistenceOperation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DialectSource getDialectSource()
|
||||
{
|
||||
return dialectSource;
|
||||
|
@ -164,6 +165,12 @@ public class DefaultPersistenceManager extends AbstractModelDataAccessObject imp
|
|||
this.selectPersistenceOperation = selectPersistenceOperation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName(Model model)
|
||||
{
|
||||
return super.getTableName(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(Connection cn, Model model, Object obj) throws PersistenceException
|
||||
{
|
||||
|
@ -172,6 +179,13 @@ public class DefaultPersistenceManager extends AbstractModelDataAccessObject imp
|
|||
this.insertPersistenceOperation.insert(cn, dialect, getTableName(model), model, obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insert(Connection cn, Dialect dialect, String table, Model model, Object obj,
|
||||
ExpressionEvaluationContext expressionEvaluationContext) throws PersistenceException
|
||||
{
|
||||
return this.insertPersistenceOperation.insert(cn, dialect, table, model, obj, expressionEvaluationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(Connection cn, Model model, Object originalObj, Object updateObj, boolean updateMultipleProperty)
|
||||
throws PersistenceException
|
||||
|
@ -181,6 +195,14 @@ public class DefaultPersistenceManager extends AbstractModelDataAccessObject imp
|
|||
return this.updatePersistenceOperation.update(cn, dialect, getTableName(model), model, originalObj, updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(Connection cn, Dialect dialect, String table, Model model, Object originalObj, Object updateObj,
|
||||
ExpressionEvaluationContext expressionEvaluationContext) throws PersistenceException
|
||||
{
|
||||
return this.updatePersistenceOperation.update(cn, dialect, table, model, originalObj, updateObj,
|
||||
expressionEvaluationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertSinglePropValue(Connection cn, Model model, Object obj, PropertyPathInfo propertyPathInfo,
|
||||
Object propValue) throws PersistenceException
|
||||
|
|
|
@ -94,6 +94,14 @@ public class ExpressionEvaluationContext
|
|||
this.valueCache.put(cacheKey, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有缓存值。
|
||||
*/
|
||||
public void clearCachedValue()
|
||||
{
|
||||
this.valueCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取{@linkplain #getVariableExpressionBean()}的{@linkplain VariableExpressionBean#getIndex()}的值。
|
||||
*
|
||||
|
|
|
@ -22,4 +22,10 @@ public class SqlExpressionErrorException extends ExpressionErrorException
|
|||
{
|
||||
super(expression, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLException getCause()
|
||||
{
|
||||
return (SQLException) super.getCause();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package org.datagear.persistence.support;
|
||||
|
||||
import org.datagear.persistence.support.ExpressionResolver.Expression;
|
||||
import org.springframework.expression.ExpressionException;
|
||||
|
||||
/**
|
||||
* 变量表达式执行出错。
|
||||
|
@ -16,8 +17,14 @@ public class VariableExpressionErrorException extends ExpressionErrorException
|
|||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public VariableExpressionErrorException(Expression expression, Exception cause)
|
||||
public VariableExpressionErrorException(Expression expression, ExpressionException cause)
|
||||
{
|
||||
super(expression, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionException getCause()
|
||||
{
|
||||
return (ExpressionException) super.getCause();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,12 +24,15 @@ public class OperationMessage
|
|||
/** 消息内容 */
|
||||
private String message;
|
||||
|
||||
/** 消息详细内容 */
|
||||
private String detail;
|
||||
|
||||
/** 是否是Throwable详细内容 */
|
||||
private boolean throwableDetail;
|
||||
|
||||
/** 操作返回数据 */
|
||||
private Object data;
|
||||
|
||||
/** 错误消息时的异常 */
|
||||
private String throwableTrace;
|
||||
|
||||
public OperationMessage()
|
||||
{
|
||||
super();
|
||||
|
@ -63,16 +66,6 @@ public class OperationMessage
|
|||
return MessageType.FAIL.equals(this.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作是否严重失败(产生{@linkplain #getException() 异常})。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isFatalFail()
|
||||
{
|
||||
return isFail() && hasThrowableTrace();
|
||||
}
|
||||
|
||||
public MessageType getType()
|
||||
{
|
||||
return type;
|
||||
|
@ -103,6 +96,31 @@ public class OperationMessage
|
|||
this.message = message;
|
||||
}
|
||||
|
||||
public boolean hasDetail()
|
||||
{
|
||||
return this.detail != null && !this.detail.isEmpty();
|
||||
}
|
||||
|
||||
public String getDetail()
|
||||
{
|
||||
return detail;
|
||||
}
|
||||
|
||||
public void setDetail(String detail)
|
||||
{
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
public boolean isThrowableDetail()
|
||||
{
|
||||
return throwableDetail;
|
||||
}
|
||||
|
||||
public void setThrowableDetail(boolean throwableDetail)
|
||||
{
|
||||
this.throwableDetail = throwableDetail;
|
||||
}
|
||||
|
||||
public boolean hasData()
|
||||
{
|
||||
return (this.data != null);
|
||||
|
@ -118,24 +136,10 @@ public class OperationMessage
|
|||
this.data = data;
|
||||
}
|
||||
|
||||
public boolean hasThrowableTrace()
|
||||
{
|
||||
return (this.throwableTrace != null && !this.throwableTrace.isEmpty());
|
||||
}
|
||||
|
||||
public String getThrowableTrace()
|
||||
{
|
||||
return throwableTrace;
|
||||
}
|
||||
|
||||
public void setThrowableTrace(String throwableTrace)
|
||||
{
|
||||
this.throwableTrace = throwableTrace;
|
||||
}
|
||||
|
||||
public void setThrowable(Throwable throwable)
|
||||
{
|
||||
this.throwableTrace = printThrowableTrace(throwable);
|
||||
this.detail = printThrowableTrace(throwable);
|
||||
this.throwableDetail = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -247,24 +251,24 @@ public class OperationMessage
|
|||
}
|
||||
|
||||
/**
|
||||
* 构建操作严重失败消息。
|
||||
* 构建Throwable操作失败消息。
|
||||
*
|
||||
* @param code
|
||||
* @param message
|
||||
* @param throwable
|
||||
* @return
|
||||
*/
|
||||
public static OperationMessage valueOfFatalFail(String code, String message, Throwable throwable)
|
||||
public static OperationMessage valueOfThrowableFail(String code, String message, Throwable throwable)
|
||||
{
|
||||
OperationMessage om = new OperationMessage(MessageType.FAIL, code, message);
|
||||
|
||||
om.setThrowableTrace(printThrowableTrace(throwable));
|
||||
om.setThrowable(throwable);
|
||||
|
||||
return om;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建操作严重失败消息。
|
||||
* 构建Throwable操作失败消息。
|
||||
*
|
||||
* @param code
|
||||
* @param message
|
||||
|
@ -272,11 +276,11 @@ public class OperationMessage
|
|||
* @param throwable
|
||||
* @return
|
||||
*/
|
||||
public static OperationMessage valueOfFatalFail(String code, String message, Object data, Throwable throwable)
|
||||
public static OperationMessage valueOfThrowableFail(String code, String message, Object data, Throwable throwable)
|
||||
{
|
||||
OperationMessage om = new OperationMessage(MessageType.FAIL, code, message);
|
||||
om.setThrowable(throwable);
|
||||
om.setData(data);
|
||||
om.setThrowableTrace(printThrowableTrace(throwable));
|
||||
|
||||
return om;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.datagear.web.convert.ClassDataConverter;
|
|||
import org.datagear.web.util.WebUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.NoSuchMessageException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
|
@ -400,6 +401,9 @@ public abstract class AbstractController
|
|||
|
||||
/**
|
||||
* 获取I18N消息内容。
|
||||
* <p>
|
||||
* 如果找不到对应消息码的消息,则返回<code>"???[code]???"<code>(例如:{@code "???error???"})。
|
||||
* </p>
|
||||
*
|
||||
* @param request
|
||||
* @param code
|
||||
|
@ -408,7 +412,14 @@ public abstract class AbstractController
|
|||
*/
|
||||
protected String getMessage(HttpServletRequest request, String code, Object... args)
|
||||
{
|
||||
return this.messageSource.getMessage(code, args, WebUtils.getLocale(request));
|
||||
try
|
||||
{
|
||||
return this.messageSource.getMessage(code, args, WebUtils.getLocale(request));
|
||||
}
|
||||
catch (NoSuchMessageException e)
|
||||
{
|
||||
return "???" + code + "???";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -155,6 +155,8 @@ public abstract class AbstractSchemaModelController extends AbstractController
|
|||
|
||||
private boolean readonly;
|
||||
|
||||
private boolean customCommit = false;
|
||||
|
||||
public AbstractSchemaModelExecutor(HttpServletRequest request, HttpServletResponse response,
|
||||
org.springframework.ui.Model springModel, String schemaId, String tableName, boolean readonly)
|
||||
{
|
||||
|
@ -165,6 +167,21 @@ public abstract class AbstractSchemaModelController extends AbstractController
|
|||
this.schemaId = schemaId;
|
||||
this.tableName = tableName;
|
||||
this.readonly = readonly;
|
||||
this.customCommit = false;
|
||||
}
|
||||
|
||||
public AbstractSchemaModelExecutor(HttpServletRequest request, HttpServletResponse response,
|
||||
org.springframework.ui.Model springModel, String schemaId, String tableName, boolean readonly,
|
||||
boolean customCommit)
|
||||
{
|
||||
super();
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
this.springModel = springModel;
|
||||
this.schemaId = schemaId;
|
||||
this.tableName = tableName;
|
||||
this.readonly = readonly;
|
||||
this.customCommit = customCommit;
|
||||
}
|
||||
|
||||
protected void doExecute() throws Throwable
|
||||
|
@ -185,7 +202,8 @@ public abstract class AbstractSchemaModelController extends AbstractController
|
|||
|
||||
doExecute(request, response, springModel, this._schema, model);
|
||||
|
||||
commitConnection();
|
||||
if (!customCommit)
|
||||
commitConnection();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
|
@ -207,7 +225,8 @@ public abstract class AbstractSchemaModelController extends AbstractController
|
|||
{
|
||||
doExecute(request, response, springModel, this._schema, model);
|
||||
|
||||
commitConnection();
|
||||
if (!customCommit)
|
||||
commitConnection();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -285,6 +304,13 @@ public abstract class AbstractSchemaModelController extends AbstractController
|
|||
super(request, response, springModel, schemaId, tableName, readonly);
|
||||
}
|
||||
|
||||
public ReturnExecutor(HttpServletRequest request, HttpServletResponse response,
|
||||
org.springframework.ui.Model springModel, String schemaId, String tableName, boolean readonly,
|
||||
boolean customCommit)
|
||||
{
|
||||
super(request, response, springModel, schemaId, tableName, readonly, customCommit);
|
||||
}
|
||||
|
||||
public T execute() throws Throwable
|
||||
{
|
||||
doExecute();
|
||||
|
@ -330,6 +356,13 @@ public abstract class AbstractSchemaModelController extends AbstractController
|
|||
super(request, response, springModel, schemaId, tableName, readonly);
|
||||
}
|
||||
|
||||
public VoidExecutor(HttpServletRequest request, HttpServletResponse response,
|
||||
org.springframework.ui.Model springModel, String schemaId, String tableName, boolean readonly,
|
||||
boolean customCommit)
|
||||
{
|
||||
super(request, response, springModel, schemaId, tableName, readonly, customCommit);
|
||||
}
|
||||
|
||||
public void execute() throws Throwable
|
||||
{
|
||||
doExecute();
|
||||
|
|
|
@ -11,7 +11,9 @@ import java.io.FileInputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLNonTransientException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -29,16 +31,20 @@ import org.datagear.model.Property;
|
|||
import org.datagear.model.support.PropertyPath;
|
||||
import org.datagear.model.support.PropertyPathInfo;
|
||||
import org.datagear.persistence.ColumnPropertyPath;
|
||||
import org.datagear.persistence.DialectSource;
|
||||
import org.datagear.persistence.Dialect;
|
||||
import org.datagear.persistence.PagingData;
|
||||
import org.datagear.persistence.PagingQuery;
|
||||
import org.datagear.persistence.PersistenceManager;
|
||||
import org.datagear.persistence.QueryResultMetaInfo;
|
||||
import org.datagear.persistence.columnconverter.LOBConversionContext;
|
||||
import org.datagear.persistence.columnconverter.LOBConversionContext.LOBConversionSetting;
|
||||
import org.datagear.persistence.support.ExpressionEvaluationContext;
|
||||
import org.datagear.persistence.support.SelectOptions;
|
||||
import org.datagear.persistence.support.SqlExpressionErrorException;
|
||||
import org.datagear.persistence.support.VariableExpressionErrorException;
|
||||
import org.datagear.web.OperationMessage;
|
||||
import org.datagear.web.convert.ClassDataConverter;
|
||||
import org.datagear.web.convert.ConverterException;
|
||||
import org.datagear.web.convert.ModelDataConverter;
|
||||
import org.datagear.web.format.DateFormatter;
|
||||
import org.datagear.web.format.SqlDateFormatter;
|
||||
|
@ -52,6 +58,8 @@ import org.datagear.web.vo.PropertyPathDisplayName;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
@ -78,9 +86,6 @@ public class DataController extends AbstractSchemaModelController
|
|||
@Autowired
|
||||
private SelectOptions selectOptions;
|
||||
|
||||
@Autowired
|
||||
private DialectSource dialectSource;
|
||||
|
||||
@Autowired
|
||||
private ModelDataConverter modelDataConverter;
|
||||
|
||||
|
@ -148,16 +153,6 @@ public class DataController extends AbstractSchemaModelController
|
|||
this.selectOptions = selectOptions;
|
||||
}
|
||||
|
||||
public DialectSource getDialectSource()
|
||||
{
|
||||
return dialectSource;
|
||||
}
|
||||
|
||||
public void setDialectSource(DialectSource dialectSource)
|
||||
{
|
||||
this.dialectSource = dialectSource;
|
||||
}
|
||||
|
||||
public ModelDataConverter getModelDataConverter()
|
||||
{
|
||||
return modelDataConverter;
|
||||
|
@ -307,7 +302,30 @@ public class DataController extends AbstractSchemaModelController
|
|||
@ResponseBody
|
||||
public ResponseEntity<OperationMessage> saveAdd(HttpServletRequest request, HttpServletResponse response,
|
||||
org.springframework.ui.Model springModel, @PathVariable("schemaId") String schemaId,
|
||||
@PathVariable("tableName") String tableName) throws Throwable
|
||||
@PathVariable("tableName") String tableName,
|
||||
@RequestParam(value = "batchCount", required = false) Integer batchCount,
|
||||
@RequestParam(value = "batchHandleErrorMode", required = false) BatchHandleErrorMode batchHandleErrorMode)
|
||||
throws Throwable
|
||||
{
|
||||
if (batchCount != null && batchCount >= 0)
|
||||
return saveAddBatch(request, response, springModel, schemaId, tableName, batchCount, batchHandleErrorMode);
|
||||
else
|
||||
return saveAddSingle(request, response, springModel, schemaId, tableName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个添加。
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param springModel
|
||||
* @param schemaId
|
||||
* @param tableName
|
||||
* @return
|
||||
* @throws Throwable
|
||||
*/
|
||||
protected ResponseEntity<OperationMessage> saveAddSingle(HttpServletRequest request, HttpServletResponse response,
|
||||
org.springframework.ui.Model springModel, String schemaId, String tableName) throws Throwable
|
||||
{
|
||||
final Object dataParam = getParamMap(request, "data");
|
||||
|
||||
|
@ -332,6 +350,186 @@ public class DataController extends AbstractSchemaModelController
|
|||
return responseEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加。
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param springModel
|
||||
* @param schemaId
|
||||
* @param tableName
|
||||
* @param batchCount
|
||||
* @param batchHandleErrorMode
|
||||
* @return
|
||||
* @throws Throwable
|
||||
*/
|
||||
protected ResponseEntity<OperationMessage> saveAddBatch(HttpServletRequest request, HttpServletResponse response,
|
||||
org.springframework.ui.Model springModel, String schemaId, String tableName, final Integer batchCount,
|
||||
final BatchHandleErrorMode batchHandleErrorMode) throws Throwable
|
||||
{
|
||||
final Object dataParam = getParamMap(request, "data");
|
||||
|
||||
final int batchCountInt = (batchCount == null ? 0 : batchCount.intValue());
|
||||
|
||||
ResponseEntity<OperationMessage> responseEntity = new ReturnExecutor<ResponseEntity<OperationMessage>>(request,
|
||||
response, springModel, schemaId, tableName, false, true)
|
||||
{
|
||||
@Override
|
||||
protected ResponseEntity<OperationMessage> execute(HttpServletRequest request, HttpServletResponse response,
|
||||
org.springframework.ui.Model springModel, Schema schema, Model model) throws Throwable
|
||||
{
|
||||
Connection cn = getConnection();
|
||||
|
||||
List<BatchUnitResult> batchResults = new ArrayList<BatchUnitResult>();
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
|
||||
Dialect dialect = persistenceManager.getDialectSource().getDialect(cn);
|
||||
String table = persistenceManager.getTableName(model);
|
||||
ExpressionEvaluationContext context = new ExpressionEvaluationContext();
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (; index < batchCountInt; index++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Object data = modelDataConverter.convert(dataParam, model);
|
||||
persistenceManager.insert(cn, dialect, table, model, data, context);
|
||||
|
||||
BatchUnitResult batchUnitResult = new BatchUnitResult(index);
|
||||
batchResults.add(batchUnitResult);
|
||||
successCount++;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (isBatchBreakException(e) && index == 0)
|
||||
throw e;
|
||||
else
|
||||
{
|
||||
BatchUnitResult batchUnitResult = new BatchUnitResult(index, e.getMessage());
|
||||
batchResults.add(batchUnitResult);
|
||||
failCount++;
|
||||
|
||||
if (BatchHandleErrorMode.ROLLBACK.equals(batchHandleErrorMode))
|
||||
{
|
||||
rollbackConnection();
|
||||
break;
|
||||
}
|
||||
else if (BatchHandleErrorMode.ABORT.equals(batchHandleErrorMode))
|
||||
{
|
||||
commitConnection();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
context.clearCachedValue();
|
||||
context.incrementVariableIndex();
|
||||
}
|
||||
}
|
||||
|
||||
if (BatchHandleErrorMode.IGNORE.equals(batchHandleErrorMode))
|
||||
commitConnection();
|
||||
|
||||
ResponseEntity<OperationMessage> responseEntity = null;
|
||||
|
||||
if (successCount == batchCountInt)// 全部成功
|
||||
{
|
||||
OperationMessage operationMessage = buildOperationMessageSuccess(request,
|
||||
buildMessageCode("batchOperationSuccess"), batchCountInt, batchCountInt, 0);
|
||||
operationMessage.setDetail(toBatchUnitResultHtml(request, batchResults));
|
||||
|
||||
responseEntity = buildOperationMessageResponseEntity(HttpStatus.OK, operationMessage);
|
||||
}
|
||||
else if (failCount == batchCountInt)// 全部失败
|
||||
{
|
||||
OperationMessage operationMessage = buildOperationMessageFail(request,
|
||||
buildMessageCode("batchOperationFail"), batchCountInt, 0, batchCountInt);
|
||||
operationMessage.setDetail(toBatchUnitResultHtml(request, batchResults));
|
||||
|
||||
responseEntity = buildOperationMessageResponseEntity(HttpStatus.BAD_REQUEST, operationMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
OperationMessage operationMessage = null;
|
||||
|
||||
if (BatchHandleErrorMode.IGNORE.equals(batchHandleErrorMode))
|
||||
{
|
||||
operationMessage = buildOperationMessageFail(request,
|
||||
buildMessageCode("batchOperationFinish.ignore"), batchCountInt, successCount,
|
||||
failCount);
|
||||
}
|
||||
else if (BatchHandleErrorMode.ROLLBACK.equals(batchHandleErrorMode))
|
||||
{
|
||||
operationMessage = buildOperationMessageFail(request,
|
||||
buildMessageCode("batchOperationFinish.rollback"), batchCountInt, successCount);
|
||||
}
|
||||
else if (BatchHandleErrorMode.ABORT.equals(batchHandleErrorMode))
|
||||
{
|
||||
operationMessage = buildOperationMessageFail(request,
|
||||
buildMessageCode("batchOperationFinish.abort"), batchCountInt, successCount,
|
||||
batchCountInt - successCount);
|
||||
}
|
||||
else
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
operationMessage.setDetail(toBatchUnitResultHtml(request, batchResults));
|
||||
|
||||
responseEntity = buildOperationMessageResponseEntity(HttpStatus.BAD_REQUEST, operationMessage);
|
||||
}
|
||||
|
||||
return responseEntity;
|
||||
}
|
||||
}.execute();
|
||||
|
||||
return responseEntity;
|
||||
}
|
||||
|
||||
protected String toBatchUnitResultHtml(HttpServletRequest request, List<BatchUnitResult> batchUnitResults)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
String mcs = buildMessageCode("batchUnitResult.successHtml");
|
||||
String mcf = buildMessageCode("batchUnitResult.failHtml");
|
||||
|
||||
for (BatchUnitResult batchUnitResult : batchUnitResults)
|
||||
{
|
||||
if (batchUnitResult.isSuccess())
|
||||
sb.append(getMessage(request, mcs, batchUnitResult.getIndex()));
|
||||
else
|
||||
sb.append(getMessage(request, mcf, batchUnitResult.getIndex(), batchUnitResult.getErrorMessage()));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断异常是否是批处理断裂异常。
|
||||
* <p>
|
||||
* 如果是,那么批处理没有继续执行的必要。
|
||||
* </p>
|
||||
*
|
||||
* @param e
|
||||
* @return
|
||||
*/
|
||||
protected boolean isBatchBreakException(Exception e)
|
||||
{
|
||||
if (e instanceof ConverterException)
|
||||
return true;
|
||||
|
||||
// 变量表达式语法错误
|
||||
if (e instanceof VariableExpressionErrorException && e.getCause() instanceof ParseException)
|
||||
return true;
|
||||
|
||||
// SQL语法错误
|
||||
if (e instanceof SqlExpressionErrorException && e.getCause() instanceof SQLNonTransientException)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@RequestMapping("/{schemaId}/{tableName}/edit")
|
||||
public String edit(HttpServletRequest request, HttpServletResponse response,
|
||||
org.springframework.ui.Model springModel, @PathVariable("schemaId") String schemaId,
|
||||
|
@ -1222,6 +1420,12 @@ public class DataController extends AbstractSchemaModelController
|
|||
return fileInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String buildMessageCode(String code)
|
||||
{
|
||||
return super.buildMessageCode("data", code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取{@linkplain QueryResultMetaInfo}的{@linkplain PropertyPathDisplayName}列表。
|
||||
*
|
||||
|
@ -1349,4 +1553,107 @@ public class DataController extends AbstractSchemaModelController
|
|||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量操作单元执行结果。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public static class BatchUnitResult implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int index;
|
||||
|
||||
/** 当操作出错时的错误消息 */
|
||||
private String errorMessage;
|
||||
|
||||
public BatchUnitResult(int index)
|
||||
{
|
||||
super();
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public BatchUnitResult(int index, String errorMessage)
|
||||
{
|
||||
super();
|
||||
this.index = index;
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public int getIndex()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
protected void setIndex(int index)
|
||||
{
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作是否成功。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSuccess()
|
||||
{
|
||||
return (this.errorMessage == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作是否失败。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isFail()
|
||||
{
|
||||
return (this.errorMessage != null);
|
||||
}
|
||||
|
||||
public String getErrorMessage()
|
||||
{
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
protected void setErrorMessage(String errorMessage)
|
||||
{
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getClass().getSimpleName() + " [index=" + index + ", errorMessage=" + errorMessage + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量出错处理方式。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public static enum BatchHandleErrorMode
|
||||
{
|
||||
/** 忽略 */
|
||||
IGNORE,
|
||||
|
||||
/** 终止 */
|
||||
ABORT,
|
||||
|
||||
/** 回滚 */
|
||||
ROLLBACK
|
||||
}
|
||||
|
||||
protected static class BatchInsertTask implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,8 +49,8 @@ bracketRight=\uFF09
|
|||
dataTables.noData=\u6CA1\u6709\u6570\u636E
|
||||
dataTables.zeroRecords=\u6CA1\u6709\u7ED3\u679C
|
||||
|
||||
batchSet.batchSetSwitchTitle=\u6279\u91CF\u6DFB\u52A0\u8BBE\u7F6E
|
||||
batchSet.batchCount=\u6279\u91CF\u6DFB\u52A0\u6570\u76EE
|
||||
batchSet.batchSetSwitchTitle=\u6279\u91CF\u6267\u884C\u8BBE\u7F6E
|
||||
batchSet.batchCount=\u6267\u884C\u6B21\u6570
|
||||
batchSet.batchHandleErrorMode=\u51FA\u9519\u65F6
|
||||
batchSet.batchHandleErrorMode.ignore=\u5FFD\u7565
|
||||
batchSet.batchHandleErrorMode.abort=\u7EC8\u6B62
|
||||
|
@ -98,6 +98,13 @@ data.clearWithShortcut=\u6E05\u9664\uFF08CTRL+SHIFT+BACKSPACE\uFF09
|
|||
data.conditionPanelWithShortcut=\u9AD8\u7EA7\u67E5\u8BE2\uFF08CTRL+SHIFT+↓\uFF09
|
||||
data.likeTitle=\u5305\u542B\uFF08CTRL+SHIFT+!\uFF09
|
||||
data.notLikeTitle=\u4E0D\u5305\u542B\uFF08CTRL+SHIFT+!\uFF09
|
||||
data.batchOperationSuccess=\u6279\u91CF\u6267\u884C\u6210\u529F\uFF0C\u603B\u6570\uFF1A[{0}]\uFF0C\u6210\u529F\u6570\uFF1A[{1}]\uFF0C\u5931\u8D25\u6570\uFF1A[{2}]
|
||||
data.batchOperationFinish.ignore=\u6279\u91CF\u6267\u884C\u5B8C\u6210\uFF08\u5FFD\u7565\uFF09\uFF0C\u603B\u6570\uFF1A[{0}]\uFF0C\u6210\u529F\u6570\uFF1A[{1}]\uFF0C\u5931\u8D25\u6570\uFF1A[{2}]
|
||||
data.batchOperationFinish.abort=\u6279\u91CF\u6267\u884C\u5B8C\u6210\uFF08\u7EC8\u6B62\uFF09\uFF0C\u603B\u6570\uFF1A[{0}]\uFF0C\u6210\u529F\u6570\uFF1A[{1}]\uFF0C\u672A\u6267\u884C\uFF1A[{2}]
|
||||
data.batchOperationFinish.rollback=\u6279\u91CF\u6267\u884C\u5B8C\u6210\uFF08\u64A4\u9500\uFF09\uFF0C\u603B\u6570\uFF1A[{0}]\uFF0C\u6210\u529F\u6570\uFF1A[0]\uFF0C\u64A4\u9500\u6570\uFF1A[{1}]
|
||||
data.batchOperationFail=\u6279\u91CF\u6267\u884C\u5931\u8D25\uFF0C\u603B\u6570\uFF1A[{0}]\uFF0C\u6210\u529F\u6570\uFF1A[{1}]\uFF0C\u5931\u8D25\u6570\uFF1A[{2}]
|
||||
data.batchUnitResult.successHtml=<div class=\u0022 message-detail-item \u0022>[\u6210\u529F] \u7F16\u53F7\uFF1A<span class='index'>{0}</span></div>
|
||||
data.batchUnitResult.failHtml=<div class=\u0022 message-detail-item \u0022>[\u5931\u8D25] \u7F16\u53F7\uFF1A<span class='index'>{0}</span>\uFF0C\u9519\u8BEF\u6D88\u606F\uFF1A<span class='fail-message'>{1}</span></div>
|
||||
|
||||
#driverEntity
|
||||
driverEntity.addDriverEntity=\u6DFB\u52A0\u6570\u636E\u5E93\u9A71\u52A8\u7A0B\u5E8F
|
||||
|
|
|
@ -25,6 +25,8 @@ boolean clientOperation = ("true".equalsIgnoreCase(getStringValue(request, "clie
|
|||
boolean readonly = ("true".equalsIgnoreCase(getStringValue(request, "readonly")));
|
||||
//忽略表单渲染和处理的属性名,允许为null
|
||||
String ignorePropertyName = getStringValue(request, "ignorePropertyName", "");
|
||||
//是否开启批量执行功能,允许为null
|
||||
boolean batchSet = ("true".equalsIgnoreCase(getStringValue(request, "batchSet")));
|
||||
%>
|
||||
<html>
|
||||
<head>
|
||||
|
@ -59,6 +61,7 @@ String ignorePropertyName = getStringValue(request, "ignorePropertyName", "");
|
|||
pageObj.originalData = $.unref(<%writeJson(application, out, data);%>);
|
||||
pageObj.data = $.unref($.ref(pageObj.originalData));
|
||||
pageObj.clientOperation = <%=clientOperation%>;
|
||||
pageObj.batchSet = <%=batchSet%>;
|
||||
|
||||
pageObj.superBuildPropertyActionOptions = pageObj.buildPropertyActionOptions;
|
||||
pageObj.buildPropertyActionOptions = function(property, propertyConcreteModel, extraRequestParams, extraPageParams)
|
||||
|
@ -103,23 +106,48 @@ String ignorePropertyName = getStringValue(request, "ignorePropertyName", "");
|
|||
var thisForm = this;
|
||||
var param = $.extend(formParam, {"data" : data, "originalData" : pageObj.originalData});
|
||||
|
||||
$.post(pageObj.url(pageObj.submitAction), param, function(operationMessage)
|
||||
$.ajax(pageObj.url(pageObj.submitAction),
|
||||
{
|
||||
pageObj.data = $.unref(operationMessage.data);
|
||||
//如果有初始数据,则更新为已保存至后台的数据
|
||||
//注意:不能直接赋值pageObj.data,因为是同一个引用,有可能会被修改,而pageObj.originalData不应该被修改
|
||||
if(pageObj.originalData)
|
||||
pageObj.originalData = $.unref($.ref(operationMessage.data));
|
||||
|
||||
if(pageParam && pageParam.afterSave)
|
||||
close = (pageParam.afterSave(operationMessage.data) != false);
|
||||
|
||||
var pageObjParent = pageObj.parent();
|
||||
if(pageObjParent && pageObjParent.refresh)
|
||||
pageObjParent.refresh();
|
||||
|
||||
if(close && !$(thisForm).modelform("isDialogPinned"))
|
||||
pageObj.close();
|
||||
"data" : param,
|
||||
"success" : function(operationMessage)
|
||||
{
|
||||
var $form = $(thisForm);
|
||||
var batchSubmit = $form.modelform("isBatchSubmit");
|
||||
var isDialogPinned = $form.modelform("isDialogPinned");
|
||||
|
||||
if(batchSubmit)
|
||||
;
|
||||
else
|
||||
{
|
||||
pageObj.data = $.unref(operationMessage.data);
|
||||
//如果有初始数据,则更新为已保存至后台的数据
|
||||
//注意:不能直接赋值pageObj.data,因为是同一个引用,有可能会被修改,而pageObj.originalData不应该被修改
|
||||
if(pageObj.originalData)
|
||||
pageObj.originalData = $.unref($.ref(operationMessage.data));
|
||||
|
||||
if(pageParam && pageParam.afterSave)
|
||||
close = (pageParam.afterSave(operationMessage.data) != false);
|
||||
|
||||
var pageObjParent = pageObj.parent();
|
||||
if(pageObjParent && pageObjParent.refresh)
|
||||
pageObjParent.refresh();
|
||||
|
||||
if(close && !isDialogPinned)
|
||||
pageObj.close();
|
||||
}
|
||||
},
|
||||
"complete" : function()
|
||||
{
|
||||
var $form = $(thisForm);
|
||||
var batchSubmit = $form.modelform("isBatchSubmit");
|
||||
|
||||
if(batchSubmit)
|
||||
{
|
||||
var pageObjParent = pageObj.parent();
|
||||
if(pageObjParent && pageObjParent.refresh)
|
||||
pageObjParent.refresh();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -160,7 +188,7 @@ String ignorePropertyName = getStringValue(request, "ignorePropertyName", "");
|
|||
pageObj.downloadSinglePropertyValueFile(property, propertyConcreteModel);
|
||||
},
|
||||
validationRequiredAsAdd : ("saveAdd" == pageObj.submitAction),
|
||||
batchSet : ("saveAdd" == pageObj.submitAction),
|
||||
batchSet : pageObj.batchSet,
|
||||
labels : pageObj.formLabels,
|
||||
dateFormat : "<c:out value='${dateFormat}' />",
|
||||
timestampFormat : "<c:out value='${sqlTimestampFormat}' />",
|
||||
|
|
|
@ -79,7 +79,7 @@ List<PropertyPathDisplayName> conditionSource = (List<PropertyPathDisplayName>)r
|
|||
<%if(!readonly){%>
|
||||
pageObj.element("input[name=addButton]").click(function()
|
||||
{
|
||||
pageObj.open(pageObj.url("add"), { pinTitleButton : true });
|
||||
pageObj.open(pageObj.url("", "add", "batchSet=true"), { pinTitleButton : true });
|
||||
});
|
||||
|
||||
pageObj.element("input[name=editButton]").click(function()
|
||||
|
|
|
@ -25,6 +25,8 @@ String submitAction = getStringValue(request, "submitAction");
|
|||
boolean clientOperation = ("true".equalsIgnoreCase(getStringValue(request, "clientOperation")));
|
||||
//是否只读操作,允许为null
|
||||
boolean readonly = ("true".equalsIgnoreCase(getStringValue(request, "readonly")));
|
||||
//是否开启批量执行功能,允许为null
|
||||
boolean batchSet = ("true".equalsIgnoreCase(getStringValue(request, "batchSet")));
|
||||
|
||||
PropertyPath propertyPathObj = ModelUtils.toPropertyPath(propertyPath);
|
||||
PropertyPathInfo propertyPathInfoObj = ModelUtils.toPropertyPathInfoConcrete(model, propertyPathObj, data);
|
||||
|
@ -63,6 +65,7 @@ boolean isPrivatePropertyModel = ModelUtils.isPrivatePropertyModelTail(propertyP
|
|||
pageObj.data = ($.unref(<%writeJson(application, out, data);%>) || {});
|
||||
pageObj.propertyPath = "<%=WebUtils.escapeJavaScriptStringValue(propertyPath)%>";
|
||||
pageObj.clientOperation = <%=clientOperation%>;
|
||||
pageObj.batchSet = <%=batchSet%>;
|
||||
|
||||
pageObj.superBuildPropertyActionOptions = pageObj.buildPropertyActionOptions;
|
||||
pageObj.buildPropertyActionOptions = function(property, propertyConcreteModel, extraRequestParams, extraPageParams)
|
||||
|
@ -168,7 +171,7 @@ boolean isPrivatePropertyModel = ModelUtils.isPrivatePropertyModelTail(propertyP
|
|||
pageObj.downloadSinglePropertyValueFile(property, propertyConcreteModel);
|
||||
},
|
||||
validationRequiredAsAdd : ("saveAdd" == pageObj.submitAction),
|
||||
batchSet : ("saveAddMultiplePropValueElement" == pageObj.submitAction),
|
||||
batchSet : pageObj.batchSet,
|
||||
labels : pageObj.formLabels,
|
||||
dateFormat : "<c:out value='${dateFormat}' />",
|
||||
timestampFormat : "<c:out value='${sqlTimestampFormat}' />",
|
||||
|
|
|
@ -186,10 +186,13 @@ boolean isPrivatePropertyModel = ModelUtils.isPrivatePropertyModelTail(propertyP
|
|||
<%if(!readonly){%>
|
||||
pageObj.addMultiplePropValueElement = function()
|
||||
{
|
||||
var url = undefined;
|
||||
var options = undefined;
|
||||
|
||||
if(pageObj.clientOperation)
|
||||
{
|
||||
url = pageObj.url("addMultiplePropValueElement");
|
||||
|
||||
var index = pageObj.table.DataTable().rows().data().length;
|
||||
|
||||
options = pageObj.buildActionOptions(property, propertyModel,
|
||||
|
@ -208,6 +211,8 @@ boolean isPrivatePropertyModel = ModelUtils.isPrivatePropertyModelTail(propertyP
|
|||
}
|
||||
else
|
||||
{
|
||||
url = pageObj.url("", "addMultiplePropValueElement", "batchSet=true");
|
||||
|
||||
options = pageObj.buildActionOptions(property, propertyModel,
|
||||
{
|
||||
"propertyPath" : $.propertyPath.concatElementIndex(pageObj.propertyPath, 0)
|
||||
|
@ -217,7 +222,7 @@ boolean isPrivatePropertyModel = ModelUtils.isPrivatePropertyModelTail(propertyP
|
|||
|
||||
options.pinTitleButton = true;
|
||||
|
||||
pageObj.open(pageObj.url("addMultiplePropValueElement"), options);
|
||||
pageObj.open(url, options);
|
||||
};
|
||||
|
||||
<%if(isPrivatePropertyModel){%>
|
||||
|
|
|
@ -21,16 +21,20 @@
|
|||
*
|
||||
* @param tableName 可选,操作对应的表名,默认是当前表名
|
||||
* @param action 操作名称
|
||||
* @param param URL后面加的参数,不需要以'?'开头
|
||||
*/
|
||||
url : function(tableName, action)
|
||||
url : function(tableName, action, param)
|
||||
{
|
||||
if(!action)
|
||||
if(action == undefined)
|
||||
{
|
||||
action = tableName;
|
||||
tableName = this.tableName;
|
||||
}
|
||||
|
||||
return contextPath + $.toPath("data", this.schemaId, tableName, action);
|
||||
if(!tableName)
|
||||
tableName = this.tableName;
|
||||
|
||||
return contextPath + $.toPath("data", this.schemaId, tableName, action) + (param ? "?" + param : "");
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,9 +14,9 @@ if(__operationMessage != null){
|
|||
<div class="message">
|
||||
<%=__operationMessage.getMessage()%>
|
||||
</div>
|
||||
<%if(__operationMessage.hasThrowableTrace()){%>
|
||||
<div class="throwable">
|
||||
<pre><%=__operationMessage.getThrowableTrace()%></pre>
|
||||
<%if(__operationMessage.hasDetail()){%>
|
||||
<div class="message-detail">
|
||||
<pre><%=__operationMessage.getDetail()%></pre>
|
||||
</div>
|
||||
<%}%>
|
||||
</div>
|
||||
|
|
|
@ -253,7 +253,7 @@
|
|||
},
|
||||
|
||||
/**
|
||||
* 获取除数据意外的参数对象,比如options.batchCountParamName、options.batchHandleErrorModeParamName参数。
|
||||
* 获取除数据以外的参数对象,比如options.batchCountParamName、options.batchHandleErrorModeParamName参数。
|
||||
*/
|
||||
param : function()
|
||||
{
|
||||
|
@ -273,6 +273,18 @@
|
|||
return param;
|
||||
},
|
||||
|
||||
/**
|
||||
* 是否是批量提交。
|
||||
*/
|
||||
isBatchSubmit : function()
|
||||
{
|
||||
var options = this.options;
|
||||
|
||||
var batchCount = parseInt($("input[name='"+options.batchCountParamName+"']", this.element).val());
|
||||
|
||||
return (batchCount >= 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* 表单所处的对话框是否设置为钉住。
|
||||
*/
|
||||
|
|
|
@ -368,7 +368,7 @@
|
|||
{
|
||||
content = "<span class='tooltip-icon ui-icon ui-icon-circle-check'></span>"
|
||||
+"<div class='content-value'>" + content +"</div>";
|
||||
return $._tip("ui-state-default", content, (delayMs || 2000));
|
||||
return $._tip("ui-state-default", content, (delayMs || 2500));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -378,7 +378,7 @@
|
|||
{
|
||||
content = "<span class='tooltip-icon ui-icon ui-icon-alert'></span>"
|
||||
+"<div class='content-value'>" + content +"</div>";
|
||||
return $._tip("ui-state-error", content, (delayMs || 3500));
|
||||
return $._tip("ui-state-error", content, (delayMs || 4100));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -388,7 +388,7 @@
|
|||
{
|
||||
content = "<span class='tooltip-icon ui-icon ui-icon-info'></span>"
|
||||
+"<div class='content-value'>" + content +"</div>";
|
||||
return $._tip("ui-state-highlight", content, (delayMs || 3500));
|
||||
return $._tip("ui-state-highlight", content, (delayMs || 4100));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1342,86 +1342,127 @@
|
|||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
$.handleAjaxError = function(jqXHR, errorThrown)
|
||||
|
||||
$.handleAjaxOperationMessage = function(jqXHR, errorThrown)
|
||||
{
|
||||
if(!window._showResponseErrorDetail)
|
||||
if(!window._showAjaxOperationMessageDetail)
|
||||
{
|
||||
window._showResponseErrorDetail = function()
|
||||
window._showAjaxOperationMessageDetail = function()
|
||||
{
|
||||
$.closeTip();
|
||||
|
||||
var $errorDetail = $("#responseError");
|
||||
var $operationMessageParent = $("#__operationMessageParent");
|
||||
|
||||
var $dialog = $("<div id='dialog-"+new Date().getTime()+"' class='error-dialog'></div>").appendTo(document.body);
|
||||
var $errorContent = $("<div class='ui-state-error error-content' />").appendTo($dialog);
|
||||
$errorContent.html($(".throwable", $errorDetail).html());
|
||||
var isSuccessMessage = ("true" == $operationMessageParent.attr("success"));
|
||||
|
||||
var $dialog = $("<div id='dialog-"+new Date().getTime()+"' class='operation-message-dialog'></div>").appendTo(document.body);
|
||||
|
||||
var $messageDetail = $("<div class='message-detail' />");
|
||||
if(!isSuccessMessage)
|
||||
$messageDetail.addClass("ui-state-error");
|
||||
$messageDetail.appendTo($dialog);
|
||||
$messageDetail.html($(".message-detail", $operationMessageParent).html());
|
||||
|
||||
$._dialog($dialog,
|
||||
{
|
||||
title : $(".message", $errorDetail).text(),
|
||||
title : $(".message", $operationMessageParent).text(),
|
||||
modal : true,
|
||||
height: "60%",
|
||||
position: {my: "center top", at: "center top+3"},
|
||||
classes:
|
||||
{
|
||||
"ui-dialog": "ui-corner-all ui-widget-shadow ui-state-error"
|
||||
"ui-dialog": "ui-corner-all ui-widget-shadow" + (isSuccessMessage ? "" : "ui-state-error")
|
||||
}
|
||||
});
|
||||
|
||||
var $dialogWidget = $dialog.dialog("widget");
|
||||
$(".ui-dialog-titlebar", $dialogWidget).addClass("ui-state-error");
|
||||
$(".ui-dialog-title", $dialogWidget).prepend("<span class='ui-icon ui-icon-alert' style='margin-right:0.3em;'></span>");
|
||||
$(".ui-dialog-titlebar-close", $dialogWidget).addClass("ui-state-error");
|
||||
|
||||
$(".ui-dialog-title", $dialogWidget).prepend("<span class='ui-icon "+(isSuccessMessage ? "ui-icon-circle-check" : "ui-icon-alert")+"'></span>");
|
||||
|
||||
if(!isSuccessMessage)
|
||||
{
|
||||
$dialogWidget.addClass("ui-state-error");
|
||||
$(".ui-dialog-titlebar", $dialogWidget).addClass("ui-state-error");
|
||||
$(".ui-dialog-titlebar-close", $dialogWidget).addClass("ui-state-error");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if(jqXHR.status != 200 && jqXHR.responseText)
|
||||
var isSuccessMessage = (jqXHR.status == 200);
|
||||
|
||||
if(jqXHR.responseText)
|
||||
{
|
||||
var $errorDiv = $("#responseError");
|
||||
if($errorDiv.length == 0)
|
||||
$errorDiv = $("<div id='responseError' style='display:none;' />").appendTo(document.body);
|
||||
var $operationMessageParent = $("#__operationMessageParent");
|
||||
if($operationMessageParent.length == 0)
|
||||
$operationMessageParent = $("<div id='__operationMessageParent' style='display:none;' />").appendTo(document.body);
|
||||
|
||||
var operationMessage = $.getResponseJson(jqXHR);
|
||||
|
||||
var hasMessage = false;
|
||||
|
||||
//操作消息的JSON响应
|
||||
if(operationMessage)
|
||||
if(operationMessage && operationMessage.type && operationMessage.code && operationMessage.message)
|
||||
{
|
||||
$errorDiv.empty();
|
||||
$operationMessageParent.empty();
|
||||
|
||||
var $omdiv = $("<div class='operation-message "+operationMessage.type+"' />").appendTo($errorDiv);
|
||||
var $omdiv = $("<div class='operation-message "+operationMessage.type+"' />").appendTo($operationMessageParent);
|
||||
var $mdiv = $("<div class='message' />").appendTo($omdiv).html(operationMessage.message);
|
||||
|
||||
if(operationMessage.throwableTrace)
|
||||
if(operationMessage.detail)
|
||||
{
|
||||
var $ddiv = $("<div class='throwable' />").appendTo($omdiv);
|
||||
var $pre = $("<pre />").appendTo($ddiv).html(operationMessage.throwableTrace);
|
||||
var $ddiv = $("<div class='message-detail' />").appendTo($omdiv);
|
||||
if(operationMessage.throwableDetail)
|
||||
$("<pre />").appendTo($ddiv).html(operationMessage.detail);
|
||||
else
|
||||
$("<div />").appendTo($ddiv).html(operationMessage.detail);
|
||||
}
|
||||
|
||||
hasMessage = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isSuccessMessage)
|
||||
hasMessage = false;
|
||||
else
|
||||
{
|
||||
//操作消息的HTML响应
|
||||
$operationMessageParent.html(jqXHR.responseText);
|
||||
hasMessage = true;
|
||||
}
|
||||
}
|
||||
//操作消息的HTML响应
|
||||
else
|
||||
$errorDiv.html(jqXHR.responseText);
|
||||
|
||||
var message = $(".message", $errorDiv).html();
|
||||
|
||||
if($(".throwable", $errorDiv).length > 0)
|
||||
message += " <span class='ui-icon ui-icon-comment error-detail-icon' onclick='_showResponseErrorDetail();'></span>";
|
||||
|
||||
$.tipError(message);
|
||||
if(hasMessage)
|
||||
{
|
||||
$operationMessageParent.attr("success", isSuccessMessage);
|
||||
var message = $(".message", $operationMessageParent).html();
|
||||
|
||||
if($(".message-detail", $operationMessageParent).length > 0)
|
||||
message += "<span class='ui-icon ui-icon-comment message-detail-icon' onclick='_showAjaxOperationMessageDetail();'></span>";
|
||||
|
||||
if(isSuccessMessage)
|
||||
$.tipSuccess(message);
|
||||
else
|
||||
$.tipError(message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var msg = (jqXHR.statusText || "Error");
|
||||
|
||||
if(errorThrown && errorThrown.message)
|
||||
if(isSuccessMessage)
|
||||
;
|
||||
else
|
||||
{
|
||||
if(msg)
|
||||
msg += " : ";
|
||||
var msg = (jqXHR.statusText || "Error");
|
||||
|
||||
msg += errorThrown.message;
|
||||
if(errorThrown && errorThrown.message)
|
||||
{
|
||||
if(msg)
|
||||
msg += " : ";
|
||||
|
||||
msg += errorThrown.message;
|
||||
}
|
||||
|
||||
$.tipError(msg);
|
||||
}
|
||||
|
||||
$.tipError(msg);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1454,18 +1495,12 @@
|
|||
|
||||
$(document).ajaxError(function(event, jqXHR, ajaxSettings, thrownError)
|
||||
{
|
||||
$.handleAjaxError(jqXHR, thrownError);
|
||||
$.handleAjaxOperationMessage(jqXHR, thrownError);
|
||||
});
|
||||
|
||||
$(document).ajaxSuccess(function(event, jqXHR, ajaxSettings, thrownError)
|
||||
{
|
||||
var responseJson = $.getResponseJson(jqXHR);
|
||||
|
||||
//确定是操作消息JSON
|
||||
if(responseJson && responseJson.type && responseJson.code && responseJson.message)
|
||||
{
|
||||
$.tipSuccess(responseJson.message);
|
||||
}
|
||||
$.handleAjaxOperationMessage(jqXHR, thrownError);
|
||||
});
|
||||
})
|
||||
(jQuery);
|
|
@ -175,6 +175,9 @@ form .form-foot .ui-button{
|
|||
padding: 1px;
|
||||
height: 20px;
|
||||
}
|
||||
.ui-dialog .ui-dialog-title .ui-icon{
|
||||
margin-right: 0.3em;
|
||||
}
|
||||
/*可保持ui-state-active状态组件样式,默认图标是灰色,这了改成白色*/
|
||||
.stated-active.ui-state-active .ui-icon, .stated-active.ui-state-active:focus .ui-icon, .stated-active.ui-state-active:hover .ui-icon{
|
||||
background-image: url(default/jquery-ui-1.12.1/images/ui-icons_ffffff_256x240.png);
|
||||
|
@ -343,8 +346,9 @@ table.dataTable tbody tr.selected .checkbox .ui-icon{
|
|||
.ui-tooltip .ui-tooltip-content .tooltip-icon{
|
||||
margin-right: 0.41em;
|
||||
}
|
||||
.ui-tooltip .ui-tooltip-content .error-detail-icon{
|
||||
.ui-tooltip .ui-tooltip-content .message-detail-icon{
|
||||
cursor: pointer;
|
||||
margin-left: 1em;
|
||||
}
|
||||
.ui-tooltip .ui-tooltip-content .content{
|
||||
padding-left:0.5em;
|
||||
|
@ -361,10 +365,10 @@ table.dataTable tbody tr.selected .checkbox .ui-icon{
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
/*错误消息对话框*/
|
||||
.error-dialog{
|
||||
/*操作消息对话框*/
|
||||
.operation-message-dialog{
|
||||
}
|
||||
.error-dialog .error-content{
|
||||
.operation-message-dialog .message-detail{
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 98%;
|
||||
|
@ -373,9 +377,13 @@ table.dataTable tbody tr.selected .checkbox .ui-icon{
|
|||
border: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
.error-dialog .error-content pre{
|
||||
.operation-message-dialog .message-detail pre{
|
||||
margin: 0;
|
||||
}
|
||||
.operation-message-dialog .message-detail .message-detail-item{
|
||||
padding: 0.2em 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/*确认对话框*/
|
||||
.dialog-confirm{}
|
||||
|
|
Loading…
Reference in New Issue