Browse Source

Merge pull request #2 in TC/finekit from ~ZACK/finekit:master to master

* commit '7f682b45fb4cd0b8db9d559de2e0db9a91392824':
  去除moduleshell
  代码质量
  无JIRA任务  sdk合并finekit
pull/1/head
superman 5 years ago
parent
commit
0ef4748a38
  1. 88
      src/main/java/com/fanruan/api/cal/CalculatorKit.java
  2. 42
      src/main/java/com/fanruan/api/cal/FormulaKit.java
  3. 67
      src/main/java/com/fanruan/api/cal/namespace/SheetInterval4CheckNameSpace.java
  4. 59
      src/main/java/com/fanruan/api/function/FunctionKit.java
  5. 24
      src/main/java/com/fanruan/api/function/shell/FineFunc.java
  6. 24
      src/main/java/com/fanruan/api/report/TemplateKit.java
  7. 111
      src/main/java/com/fanruan/api/report/analy/AnalyKit.java
  8. 52
      src/main/java/com/fanruan/api/report/analy/data/TreeNode.java
  9. 58
      src/main/java/com/fanruan/api/util/TransmissionKit.java
  10. 27
      src/main/java/com/fanruan/api/util/trans/BaseSmsBody.java
  11. 94
      src/main/java/com/fanruan/api/util/trans/BatchSmsBody.java
  12. 219
      src/main/java/com/fanruan/api/util/trans/EmailBody.java
  13. 162
      src/main/java/com/fanruan/api/util/trans/SingleSmsBody.java
  14. 52
      src/test/java/com/fanruan/api/ModulePrepare.java
  15. 49
      src/test/java/com/fanruan/api/cal/CalculatorKitEnvTest.java
  16. 40
      src/test/java/com/fanruan/api/cal/CalculatorKitTest.java
  17. 18
      src/test/java/com/fanruan/api/cal/FormulaKitTest.java
  18. 46
      src/test/java/com/fanruan/api/function/FunctionKitTest.java
  19. 10
      src/test/java/com/fanruan/api/function/TestFunc.java
  20. 31
      src/test/java/com/fanruan/api/report/analy/AnalyKitTest.java
  21. 27
      src/test/java/com/fanruan/api/util/TransmissionKitTest.java
  22. 72
      src/test/resources/com/fanruan/api/report/sheets.cpt
  23. 247
      src/test/resources/com/fanruan/api/report/tree.cpt

88
src/main/java/com/fanruan/api/cal/CalculatorKit.java

@ -0,0 +1,88 @@
package com.fanruan.api.cal;
import com.fanruan.api.cal.namespace.SheetInterval4CheckNameSpace;
import com.fanruan.api.session.SessionKit;
import com.fr.base.ParameterMapNameSpace;
import com.fr.base.TableDataNameSpace;
import com.fr.data.TableDataSource;
import com.fr.report.report.Report;
import com.fr.script.Calculator;
import com.fr.stable.StringUtils;
import com.fr.stable.script.CalculatorProvider;
import com.fr.stable.script.NameSpace;
import com.fr.stable.web.SessionProvider;
import com.fr.third.javax.annotation.Nullable;
import com.fr.web.core.ReportSessionIDInfor;
import com.fr.web.core.TemplateSessionIDInfo;
import com.fr.web.session.SessionIDInfo;
import java.util.Map;
/**
* @ClassName CalculatorKit
* @Author zack
* @Date 2019/8/23
* @Version 10.0
* 帆软算子工具类主要用于公式计算
*/
public class CalculatorKit {
/**
* 创建一个基础算子基础算子仅支持函数计算.比如SUM()函数
*
* @return 算子对象
*/
public static CalculatorProvider createCalculator() {
return Calculator.createCalculator();
}
/**
* 创建一个带参数计算的算子
* 可以支持计算入参paraMap里面相关的带参函数
* 比如paraMap带有参数a->1,b->2,CalculatorKit.createCalculator(paraMap).evalValue("SUM(a,b)")输出3
*
* @return 算子
*/
public static CalculatorProvider createCalculator(Map paraMap) {
ParameterMapNameSpace nameSpace = ParameterMapNameSpace.create(paraMap);
CalculatorProvider calculator = createCalculator();
calculator.pushNameSpace(nameSpace);
return calculator;
}
/**
* 创建一个支持单元格以及模板数据集计算的算子
*
* @param sessionID 模板的sessionID
* @param paraMap 其他参数
* @return 算子对象
*/
public static CalculatorProvider createCalculator(@Nullable String sessionID, @Nullable Map paraMap) {
ParameterMapNameSpace nameSpace = ParameterMapNameSpace.create(paraMap);
CalculatorProvider calculator = createCalculator();
calculator.pushNameSpace(nameSpace);
if (StringUtils.isNotEmpty(sessionID)) {
SessionProvider rsii = SessionKit.getSession(sessionID);
if (rsii != null) {
if (rsii instanceof TemplateSessionIDInfo) {
//支持模板单元格值计算
calculator.setAttribute(TableDataSource.KEY, ((TemplateSessionIDInfo) rsii).getTableDataSource());
calculator.pushNameSpace(SessionIDInfo.asNameSpace(sessionID));
if (rsii instanceof ReportSessionIDInfor) {
//支持跨sheet计算
calculator.pushNameSpace(SheetInterval4CheckNameSpace.getInstance());
calculator.setAttribute(Report.KEY, ((ReportSessionIDInfor) rsii).getReport2Show(0));
}
}
}
}
return calculator;
}
/**
* 返回服务器数据集的算子空间可以通过调用calculator.pushNameSpace()将算子空间塞进算子实例从而支持服务器数据集相关的函数计算
* @return 算子空间对象
*/
public static NameSpace getServerTableDataNameSpace(){
return TableDataNameSpace.getInstance();
}
}

42
src/main/java/com/fanruan/api/cal/FormulaKit.java

@ -2,10 +2,14 @@ package com.fanruan.api.cal;
import com.fanruan.api.err.KitError;
import com.fr.base.BaseFormula;
import com.fr.log.FineLoggerFactory;
import com.fr.script.Calculator;
import com.fr.stable.FormulaProvider;
import com.fr.stable.StringUtils;
import com.fr.stable.UtilEvalError;
import com.fr.stable.script.CalculatorProvider;
import com.fr.stable.script.Expression;
import com.fr.third.antlr.ANTLRException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -19,6 +23,7 @@ public class FormulaKit {
/**
* 计算公式的值会新建一个算子对象来计算该公式
*
* @param formula 公式内容
* @return 公式计算后的结果值
* @throws KitError 如果计算过程中出现错误则抛出此异常
@ -29,6 +34,7 @@ public class FormulaKit {
/**
* 计算公式的值
*
* @param calculator 自定义算子
* @param formula 公式内容
* @return 公式计算后的结果值
@ -44,10 +50,46 @@ public class FormulaKit {
/**
* 生成公式对象
*
* @param content 公式的内容
* @return 公式对象
*/
public static @NotNull FormulaProvider newFormula(Object content) {
return BaseFormula.createFormulaBuilder().build(content);
}
/**
* 检查公式内容合法性
*
* @param content 公式文本
* @return 如果非空且不合法返回false, 反之返回true
*/
public static boolean checkFormulaContent(String content) {
String formulaText = content.trim();
if (StringUtils.isNotEmpty(formulaText)) {
FormulaProvider formula = newFormula(formulaText);
Expression expression = null;
try {
expression = formula.parse(Calculator.createCalculator());
} catch (ANTLRException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return null != expression;
}
return true;
}
/**
* 公式合法性校验
*
* @param formula 公式对象
* @return 当前公式是否合法
*/
public static boolean checkFormulaContent(FormulaProvider formula) {
if (formula == null) {
return true;
}
return checkFormulaContent(formula.getPureContent());
}
}

67
src/main/java/com/fanruan/api/cal/namespace/SheetInterval4CheckNameSpace.java

@ -0,0 +1,67 @@
package com.fanruan.api.cal.namespace;
import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.main.FineBook;
import com.fr.parser.SheetIntervalLiteral;
import com.fr.report.report.Report;
import com.fr.report.report.WriteECReport;
import com.fr.stable.StringUtils;
import com.fr.stable.script.AbstractNameSpace;
import com.fr.stable.script.CalculatorProvider;
import com.fr.stable.script.ColumnRowRange;
/**
* @deprecated 当sdk因为其他需求有主体jar要求的时候这边可以删掉
* 主体代码里面的这个类被混淆了sdk抄一份一样的
* @author Carl
* 填报的时候处理跨域的值
*/
public class SheetInterval4CheckNameSpace extends AbstractNameSpace {
public static final SheetInterval4CheckNameSpace SC = new SheetInterval4CheckNameSpace();
private SheetInterval4CheckNameSpace(){}
public static SheetInterval4CheckNameSpace getInstance() {
return SC;
}
@Override
public Object getVariable(Object var, CalculatorProvider calculator) {
// TODO carl:真是乱
if (!(var instanceof SheetIntervalLiteral)) {
return null;
}
Report report = calculator.getAttribute(Report.KEY);
if (report == null) {
return null;
}
FineBook wb = report.getBook();
SheetIntervalLiteral sil = (SheetIntervalLiteral)var;
if (wb == null || StringUtils.isBlank(sil.getSheetName())) {
return null;
}
for (int i = 0; i < wb.getReportCount(); i++) {
if (ComparatorUtils.equals(wb.getReportName(i), sil.getSheetName())) {
Report rp = wb.getReport(i);
if (rp instanceof WriteECReport) {
if (sil.getSheetAtom() instanceof ColumnRowRange) {
return ((WriteECReport)rp).resolveColumnRowRange((ColumnRowRange)sil.getSheetAtom(), null);
} else {
// TODO 暂时只有 ColumnRowRange和Ambiguity两种,考虑到以后会加就弄到外面来处理
// Ambiguity的情况不处理
FineLoggerFactory.getLogger().error("UnResolvedVariable " + sil.toString());
}
}
break;
}
}
return null;
}
}

59
src/main/java/com/fanruan/api/function/FunctionKit.java

@ -0,0 +1,59 @@
package com.fanruan.api.function;
import com.fanruan.api.function.shell.FineFunc;
import com.fr.file.FunctionManager;
import com.fr.script.Calculator;
import com.fr.stable.StringUtils;
import com.fr.stable.script.FunctionDef;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName FunctionKit
* @Author zack
* @Date 2019/8/23
* @Version 10.0
* 函数相关工具类
*/
public class FunctionKit {
/**
* 新增一个自定义函数
*
* @param fineFunc 自定义函数对象
*/
public static void addFunc(FineFunc fineFunc) {
if (fineFunc == null) {
return;
}
if (Calculator.createCalculator().resolveMethod(fineFunc.getName()) == null) {
FunctionManager.getInstance().addFunctionDef(new FunctionDef(fineFunc.getName(), fineFunc.getDescription(), fineFunc.getClassName()));
}
}
/**
* 根据自定义函数类路径移除一个自定义函数
*
* @param className 自定义函数类路径
*/
public static void removeFunc(String className) {
if (StringUtils.isEmpty(className)) {
return;
}
int count = FunctionManager.getInstance().getFunctionDefCount();
List<FunctionDef> functionDefList = new ArrayList<FunctionDef>(count);
for (int i = 0; i < count; i++) {
FunctionDef functionDef = FunctionManager.getInstance().getFunctionDef(i);
if (!className.equalsIgnoreCase(functionDef.getClassName())) {
functionDefList.add(functionDef);
}
}
if (functionDefList.size() == count) {
return;
}
FunctionManager.getInstance().clearAllFunctionDef();
for (FunctionDef fun : functionDefList) {
FunctionManager.getInstance().addFunctionDef(fun);
}
}
}

24
src/main/java/com/fanruan/api/function/shell/FineFunc.java

@ -0,0 +1,24 @@
package com.fanruan.api.function.shell;
import com.fr.stable.script.FunctionDef;
/**
* ClassName FineFunc
*
* @Author zack
* @Date 2019/8/23
* @Version 10.0
* 自定义函数实体
*/
public class FineFunc extends FunctionDef {
public FineFunc() {
}
public FineFunc(String name, String descrption) {
super(name, descrption);
}
public FineFunc(String name, String description, String className) {
super(name, description, className);
}
}

24
src/main/java/com/fanruan/api/report/TemplateKit.java

@ -0,0 +1,24 @@
package com.fanruan.api.report;
import com.fr.io.TemplateWorkBookIO;
import com.fr.main.TemplateWorkBook;
/**
* @ClassName TemplateKit
* @Author zack
* @Date 2019/8/23
* @Version 10.0
* 模板操作相关工具类
*/
public class TemplateKit {
/**
* 通过相对路径读取模板
*
* @param relativePath 相对路径相对reportlets目录
* @return 模板对象
* @throws Exception 模板读取异常
*/
public static TemplateWorkBook readTemplateByPath(String relativePath) throws Exception {
return TemplateWorkBookIO.readTemplateWorkBook(
relativePath);
}
}

111
src/main/java/com/fanruan/api/report/analy/AnalyKit.java

@ -0,0 +1,111 @@
package com.fanruan.api.report.analy;
import com.fanruan.api.report.analy.data.TreeNode;
import com.fr.cache.list.IntList;
import com.fr.form.ui.Widget;
import com.fr.main.workbook.ResultWorkBook;
import com.fr.report.cell.ResultCellElement;
import com.fr.report.cell.WidgetAttrElem;
import com.fr.report.report.Report;
import com.fr.report.report.ResultReport;
import com.fr.report.web.button.form.TreeNodeToggleButton;
import com.fr.report.worksheet.AnalysisRWorkSheet;
import com.fr.script.Calculator;
import com.fr.web.core.TreeHTMLWriter;
import com.fr.web.core.reportcase.WebElementReportCase;
import com.fr.web.output.html.chwriter.ViewCellWriter;
import com.fr.web.request.EmptyRepository;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* @ClassName AnalyKit
* @Author zack
* @Date 2019/8/23
* @Version 10.0
* 数据分析相关工具类
*/
public class AnalyKit {
/**
* 折叠树模板将结果报表行转成一个树形数据结构
*
* @param book 结果报表
* @param index sheet索引
* @return 树节点集合
*/
public static Map<Integer, TreeNode> generateResultBookTree(ResultWorkBook book, int index) {
ResultReport resultWS = book.getResultReport(index);
if (!(resultWS instanceof AnalysisRWorkSheet)) {
//只有分析预览支持折叠树
throw new UnsupportedOperationException();
}
AnalysisRWorkSheet analysisRWorkSheet = (AnalysisRWorkSheet) resultWS;
Calculator c = Calculator.createCalculator();
c.setAttribute(Report.KEY, analysisRWorkSheet);
TreeHTMLWriter htmlWriter = new TreeHTMLWriter();
ViewCellWriter cellHtmlWriter = new ViewCellWriter(new EmptyRepository(), 1, resultWS.getReportSettings(), true);
htmlWriter.writeReportToHtml(new WebElementReportCase(analysisRWorkSheet, new EmptyRepository()), 1, cellHtmlWriter, new EmptyRepository(), "");
cellHtmlWriter.dealWithAllTreeNodeRelation(c);
return generateNodeTree(analysisRWorkSheet);
}
private static Map<Integer, TreeNode> generateNodeTree(AnalysisRWorkSheet resultWS) {
int rowSize = resultWS.getRowCount();
Map<Integer, TreeNode> nodeMap = new HashMap<Integer, TreeNode>();
for (int rowIndex = 0; rowIndex < rowSize; rowIndex++) {//遍历行
ResultCellElement treeNodeCell = findToggleCell(resultWS, rowIndex);
if (treeNodeCell != null) {
Widget widget = ((WidgetAttrElem) treeNodeCell).getWidget();
IntList sonList = ((TreeNodeToggleButton) widget).getRelativeIndexList();
if (sonList != null && sonList.size() > 1) {
if (sonList.get(0) == -1) {
//折叠行
if (nodeMap.containsKey(treeNodeCell.getRow())) {
continue;
}
buildNodeMap(resultWS, treeNodeCell, nodeMap, -1);
} else {
//折叠列 暂不处理
}
}
}
}
return nodeMap;
}
private static ResultCellElement findToggleCell(AnalysisRWorkSheet reportCase, int rowIndex) {
Iterator cellIterator = reportCase.getRow(rowIndex);
while (cellIterator.hasNext()) {
ResultCellElement tmpCell = (ResultCellElement) cellIterator.next();
if (tmpCell instanceof WidgetAttrElem) {
if (((WidgetAttrElem) tmpCell).getWidget() instanceof TreeNodeToggleButton) {
return tmpCell;
}
}
}
return null;
}
private static void buildNodeMap(AnalysisRWorkSheet reportCase, ResultCellElement cellElment, Map<Integer, TreeNode> nodeMap, int parent) {
if (cellElment == null) {
return;
}
TreeNodeToggleButton toggleButton = (TreeNodeToggleButton) ((WidgetAttrElem) cellElment).getWidget();
int self = cellElment.getRow();
IntList sonList = toggleButton.getRelativeIndexList();
if (sonList != null && sonList.size() > 1) {
if (sonList.get(0) == -1) {//折叠行
nodeMap.put(self, new TreeNode(self, parent, sonList));
int size = sonList.size();
for (int i = 0; i < size; i++) {
buildNodeMap(reportCase, findToggleCell(reportCase, sonList.get(i)), nodeMap, self);
}
}
}
}
}

52
src/main/java/com/fanruan/api/report/analy/data/TreeNode.java

@ -0,0 +1,52 @@
package com.fanruan.api.report.analy.data;
import com.fr.cache.list.IntList;
/**
* 折叠行树节点对象
*/
public class TreeNode {
private int self;//自身所在行
private int parent;//父节点所在行
private IntList sons;//子节点
public TreeNode(int self, int parent, IntList sons) {
this.self = self;
this.parent = parent;
this.sons = sons;
}
public void setParent(int parent) {
this.parent = parent;
}
public void setSons(IntList sons) {
this.sons = sons;
}
public void setSelf(int self) {
this.self = self;
}
public int getParent() {
return parent;
}
public int getSelf() {
return self;
}
public IntList getSons() {
return sons;
}
@Override
public String toString() {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(self).append("#").append(parent);
if (sons != null) {
stringBuffer.append("#").append(sons.toString());
}
return stringBuffer.toString();
}
}

58
src/main/java/com/fanruan/api/util/TransmissionKit.java

@ -0,0 +1,58 @@
package com.fanruan.api.util;
import com.fanruan.api.util.trans.BaseSmsBody;
import com.fanruan.api.util.trans.EmailBody;
import com.fr.base.EmailManager;
import com.fr.base.sms.SMSManager;
/**
* @ClassName TransmissionKit
* @Author zack
* @Date 2019/8/23
* @Version 10.0
* fine kit for data transmission.(eg. email or sms...)
*/
public class TransmissionKit {
/**
* 服务端是否支持短信服务
*
* @return 支持返回true 否则false
*/
public static boolean isSmsFuncSupport() {
return SMSManager.getInstance().isSMSFuncSupport();
}
/**
* 发送短信
*
* @param baseSmsBody 短信实体
* @return 发送成功返回true 否则false
* @throws Exception
*/
public static boolean sendSms(BaseSmsBody baseSmsBody) throws Exception {
return baseSmsBody.send();
}
/**
* 发送邮件
*
* @param emailBody 邮件实体
* @return 发送成功返回true否则false
* @throws Exception
*/
public static boolean sendEmail(EmailBody emailBody) throws Exception {
EmailManager.getInstance().send(
emailBody.getToAddress(),
emailBody.getCcAddress(),
emailBody.getBccAddress(),
emailBody.getFromAddress(),
emailBody.getSubject(),
emailBody.getBodyContent(),
emailBody.getAttaches(),
emailBody.getFormat(),
emailBody.getContentAttaches(),
emailBody.getSessionId()
);
return true;
}
}

27
src/main/java/com/fanruan/api/util/trans/BaseSmsBody.java

@ -0,0 +1,27 @@
package com.fanruan.api.util.trans;
/**
* 抽象短信体
*
* @author vito
* @date 2019-07-24
*/
public abstract class BaseSmsBody {
private String templateCode;
public String getTemplateCode() {
return templateCode;
}
void setTemplateCode(String templateCode) {
this.templateCode = templateCode;
}
/**
* 发送
*
* @return 发送结果
* @throws Exception 发送异常
*/
public abstract boolean send() throws Exception;
}

94
src/main/java/com/fanruan/api/util/trans/BatchSmsBody.java

@ -0,0 +1,94 @@
package com.fanruan.api.util.trans;
import com.fr.base.sms.SMSManager;
import com.fr.json.JSONArray;
import java.util.List;
/**
* 批量短信体
*
* @author vito
* @date 2019-07-24
*/
public class BatchSmsBody extends BaseSmsBody {
private List<String> mobiles;
private List<String> receivers;
private JSONArray para;
private BatchSmsBody() {
}
public List<String> getMobiles() {
return mobiles;
}
public List<String> getReceivers() {
return receivers;
}
public JSONArray getPara() {
return para;
}
public static Builder newBuilder() {
return new Builder();
}
@Override
public boolean send() throws Exception {
return SMSManager.getInstance().batchSendSMS(
getTemplateCode(),
getMobiles(),
getPara(),
getReceivers());
}
public static final class Builder {
private String templateCode;
private List<String> mobiles;
private List<String> receivers;
private JSONArray para;
private Builder() {
}
public Builder templateCode(String templateCode) {
this.templateCode = templateCode;
return this;
}
public Builder mobiles(List<String> mobiles) {
this.mobiles = mobiles;
return this;
}
public Builder receivers(List<String> receivers) {
this.receivers = receivers;
return this;
}
public Builder para(JSONArray para) {
this.para = para;
return this;
}
public BatchSmsBody build() {
if (templateCode == null) {
throw new IllegalArgumentException("templateCode should not be null");
}
if (mobiles == null) {
throw new IllegalArgumentException("mobiles should not be null");
}
if (para == null) {
throw new IllegalArgumentException("para should not be null");
}
BatchSmsBody batchSmsBody = new BatchSmsBody();
batchSmsBody.setTemplateCode(templateCode);
batchSmsBody.receivers = this.receivers;
batchSmsBody.mobiles = this.mobiles;
batchSmsBody.para = this.para;
return batchSmsBody;
}
}
}

219
src/main/java/com/fanruan/api/util/trans/EmailBody.java

@ -0,0 +1,219 @@
package com.fanruan.api.util.trans;
import com.fr.base.EmailAttachment;
import org.jetbrains.annotations.Nullable;
/**
* 邮件体
*
* @author vito
* @date 2019-07-24
*/
public class EmailBody {
private String toAddress;
private String ccAddress;
private String bccAddress;
private String fromAddress;
private String subject;
private String bodyContent;
private EmailAttachment[] attaches;
private String format;
private EmailAttachment[] contentAttaches;
private String sessionId;
private EmailBody(Builder builder) {
this.toAddress = builder.toAddress;
this.ccAddress = builder.ccAddress;
this.bccAddress = builder.bccAddress;
this.fromAddress = builder.fromAddress;
this.subject = builder.subject;
this.bodyContent = builder.bodyContent;
this.attaches = builder.attaches;
this.format = builder.format;
this.contentAttaches = builder.contentAttaches;
this.sessionId = builder.sessionId;
}
public static Builder newBuilder() {
return new Builder();
}
public String getToAddress() {
return toAddress;
}
public String getCcAddress() {
return ccAddress;
}
public String getBccAddress() {
return bccAddress;
}
public String getFromAddress() {
return fromAddress;
}
public String getSubject() {
return subject;
}
public String getBodyContent() {
return bodyContent;
}
public EmailAttachment[] getAttaches() {
return attaches;
}
public String getFormat() {
return format;
}
public EmailAttachment[] getContentAttaches() {
return contentAttaches;
}
public String getSessionId() {
return sessionId;
}
public static final class Builder {
private String toAddress;
private String ccAddress;
private String bccAddress;
private String fromAddress;
private String subject;
private String bodyContent;
private EmailAttachment[] attaches;
private String format;
private EmailAttachment[] contentAttaches;
private String sessionId;
private Builder() {
}
public EmailBody build() {
if (toAddress == null) {
throw new IllegalArgumentException("toAddress should not be null");
}
if (subject == null) {
throw new IllegalArgumentException("subject should not be null");
}
if (bodyContent == null) {
throw new IllegalArgumentException("bodyContent should not be null");
}
return new EmailBody(this);
}
/**
* 设置收件人地址
*
* @param toAddress 收件人地址
* @return 建造者
*/
public Builder toAddress(String toAddress) {
this.toAddress = toAddress;
return this;
}
/**
* 设置抄送地址
*
* @param ccAddress 抄送地址
* @return 建造者
*/
public Builder ccAddress(@Nullable String ccAddress) {
this.ccAddress = ccAddress;
return this;
}
/**
* 设置密送地址
*
* @param bccAddress 密送地址
* @return 建造者
*/
public Builder bccAddress(@Nullable String bccAddress) {
this.bccAddress = bccAddress;
return this;
}
/**
* 设置发件人地址
*
* @param fromAddress 发件人地址
* @return 建造者
*/
public Builder fromAddress(@Nullable String fromAddress) {
this.fromAddress = fromAddress;
return this;
}
/**
* 设置主题
*
* @param subject 主题
* @return 建造者
*/
public Builder subject(String subject) {
this.subject = subject;
return this;
}
/**
* 设置正文
*
* @param bodyContent 正文
* @return 建造者
*/
public Builder bodyContent(String bodyContent) {
this.bodyContent = bodyContent;
return this;
}
/**
* 设置附件
*
* @param attaches 附件
* @return 建造者
*/
public Builder attaches(@Nullable EmailAttachment[] attaches) {
this.attaches = attaches;
return this;
}
/**
* 设置格式
*
* @param format 格式
* @return 建造者
*/
public Builder format(@Nullable String format) {
this.format = format;
return this;
}
/**
* 设置邮件正文显示的附件
*
* @param contentAttaches 邮件正文显示的附件
* @return 建造者
*/
public Builder contentAttaches(@Nullable EmailAttachment[] contentAttaches) {
this.contentAttaches = contentAttaches;
return this;
}
/**
* 设置报表的session id
*
* @param sessionId 报表的session id
* @return 建造者
*/
public Builder sessionId(@Nullable String sessionId) {
this.sessionId = sessionId;
return this;
}
}
}

162
src/main/java/com/fanruan/api/util/trans/SingleSmsBody.java

@ -0,0 +1,162 @@
package com.fanruan.api.util.trans;
import com.fr.base.sms.SMSManager;
import com.fr.json.JSONObject;
import org.jetbrains.annotations.Nullable;
/**
* 单个短信体
*
* @author vito
* @date 2019-07-24
*/
public class SingleSmsBody extends BaseSmsBody {
private String mobile;
private JSONObject para;
private String receiver;
private boolean needRecord;
private SingleSmsBody() {
}
/**
* 获取收集号码
*
* @return 手机号码
*/
public String getMobile() {
return mobile;
}
/**
* 获取参数
*
* @return 模板参数
*/
public JSONObject getPara() {
return para;
}
/**
* 获取接收者
*
* @return 接收者
*/
@Nullable
public String getReceiver() {
return receiver;
}
/**
* 是否需要记录
*
* @return 是否需要记录
*/
public boolean isNeedRecord() {
return needRecord;
}
public static Builder newBuilder() {
return new Builder();
}
@Override
public boolean send() throws Exception {
return SMSManager.getInstance().sendSMS(
getTemplateCode(),
getMobile(),
getPara(),
getReceiver(),
isNeedRecord());
}
public static final class Builder {
private String templateCode;
private String mobile;
private JSONObject para;
private String receiver;
private boolean needRecord;
private Builder() {
}
/**
* 设置模板代码
*
* @param templateCode 模板代码
* @return builder
*/
public Builder templateCode(String templateCode) {
this.templateCode = templateCode;
return this;
}
/**
* 设置手机号码
*
* @param mobile 手机号码
* @return builder
*/
public Builder mobile(String mobile) {
this.mobile = mobile;
return this;
}
/**
* 设置模板参数
*
* @param para 模板参数
* @return builder
*/
public Builder para(JSONObject para) {
this.para = para;
return this;
}
/**
* 设置接受对象可不传
*
* @param receiver 接受对象
* @return builder
*/
public Builder receiver(@Nullable String receiver) {
this.receiver = receiver;
return this;
}
/**
* 设置是否需要记录
*
* @param needRecord 需要记
* @return builder
*/
public Builder needRecord(boolean needRecord) {
this.needRecord = needRecord;
return this;
}
/**
* 构建
*
* @return 单个短信体
*/
public SingleSmsBody build() {
if (templateCode == null) {
throw new IllegalArgumentException("templateCode should not be null");
}
if (mobile == null) {
throw new IllegalArgumentException("mobile should not be null");
}
if (para == null) {
throw new IllegalArgumentException("para should not be null");
}
SingleSmsBody singleSmsBody = new SingleSmsBody();
singleSmsBody.setTemplateCode(templateCode);
singleSmsBody.para = this.para;
singleSmsBody.receiver = this.receiver;
singleSmsBody.needRecord = this.needRecord;
singleSmsBody.mobile = this.mobile;
return singleSmsBody;
}
}
}

52
src/test/java/com/fanruan/api/ModulePrepare.java

@ -0,0 +1,52 @@
package com.fanruan.api;
import com.fr.base.operator.common.CommonOperator;
import com.fr.cluster.engine.activator.standalone.StandaloneModeActivator;
import com.fr.config.activator.BaseDBActivator;
import com.fr.config.activator.ConfigurationActivator;
import com.fr.env.operator.CommonOperatorImpl;
import com.fr.general.I18nResource;
import com.fr.module.Module;
import com.fr.module.tool.ActivatorToolBox;
import com.fr.report.ReportActivator;
import com.fr.report.RestrictionActivator;
import com.fr.report.module.ReportBaseActivator;
import com.fr.scheduler.SchedulerActivator;
import com.fr.store.StateServerActivator;
import com.fr.workspace.simple.SimpleWork;
import org.junit.After;
import org.junit.Before;
/**
* @ClassName ModulePrepare
* @Author zack
* @Date 2019/8/26
* @Version 10.0
*/
public class ModulePrepare {
Module module = null;
@Before
public void start() {
module = ActivatorToolBox.simpleLink(
new BaseDBActivator(),
new ConfigurationActivator(),
new StandaloneModeActivator(),
new StateServerActivator(),
new SchedulerActivator(),
new ReportBaseActivator(),
new RestrictionActivator(),
new ReportActivator()
);
SimpleWork.supply(CommonOperator.class, new CommonOperatorImpl());
I18nResource.getInstance();
module.start();
}
@After
public void stop() {
if (module != null) {
module.stop();
}
}
}

49
src/test/java/com/fanruan/api/cal/CalculatorKitEnvTest.java

@ -0,0 +1,49 @@
package com.fanruan.api.cal;
import com.fanruan.api.Prepare;
import com.fr.invoke.Reflect;
import com.fr.log.FineLoggerFactory;
import com.fr.main.impl.WorkBook;
import com.fr.main.workbook.ResultWorkBook;
import com.fr.report.cell.CellElementValueConverterRegistry;
import com.fr.stable.ActorConstants;
import com.fr.stable.ActorFactory;
import com.fr.web.core.ReportSessionIDInfor;
import com.fr.web.core.SessionPoolManager;
import org.junit.Assert;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* 需要启动模块的算子单元测试
*
* @ClassName CalculatorKitEnvTest
* @Author zack
* @Date 2019/8/23
* @Version 10.0
*/
public class CalculatorKitEnvTest extends Prepare {
@Test
public void testSheetInterval() {
WorkBook tpl = new WorkBook();
Map paraMap = new HashMap(0);
String path = "/com/fanruan/api/report/sheets.cpt";
try {
tpl.readStream(CalculatorKitEnvTest.class.getResourceAsStream(path));
ResultWorkBook resultWorkBook = tpl.execute(paraMap, ActorFactory.getActor(ActorConstants.TYPE_WRITE));
ReportSessionIDInfor sessionIDInfor = new ReportSessionIDInfor(paraMap, path, ActorFactory.getActor(ActorConstants.TYPE_WRITE)).buildResultWorkBook(resultWorkBook);
String sessionId = Reflect.on(SessionPoolManager.class).call("addSessionIDInfor", sessionIDInfor).get();
CellElementValueConverterRegistry.complete();
Assert.assertEquals(111, CalculatorKit.createCalculator(sessionId, null).evalValue("sheet1!A1"));
Assert.assertEquals(222, CalculatorKit.createCalculator(sessionId, null).evalValue("sheet2!A1"));
Assert.assertEquals(333, CalculatorKit.createCalculator(sessionId, null).evalValue("SUM(sheet1!A1,sheet2!A1)"));
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} finally {
CellElementValueConverterRegistry.reset();
}
Assert.assertNotNull(tpl.getReport(0));
}
}

40
src/test/java/com/fanruan/api/cal/CalculatorKitTest.java

@ -0,0 +1,40 @@
package com.fanruan.api.cal;
import com.fr.general.FRLogger;
import com.fr.stable.script.CalculatorProvider;
import org.junit.Assert;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName CalculatorKitTest
* @Author zack
* @Date 2019/8/23
* @Version 10.0
*/
public class CalculatorKitTest {
@Test
public void testCalculatorCreate() {
CalculatorProvider calculator = CalculatorKit.createCalculator();
try {
Assert.assertEquals(3, calculator.evalValue("sum(1,2)"));
} catch (Exception e) {
FRLogger.getLogger().error(e.getMessage(), e);
}
}
@Test
public void testCalculatorCreateWithPara() {
Map paraMap = new HashMap();
paraMap.put("a", 1);
paraMap.put("b", 2);
CalculatorProvider calculator = CalculatorKit.createCalculator(paraMap);
try {
Assert.assertEquals(3, calculator.evalValue("sum(a,b)"));
} catch (Exception e) {
FRLogger.getLogger().error(e.getMessage(), e);
}
}
}

18
src/test/java/com/fanruan/api/cal/FormulaKitTest.java

@ -2,17 +2,17 @@ package com.fanruan.api.cal;
import com.fanruan.api.Prepare;
import com.fanruan.api.err.KitError;
import com.fr.base.Formula;
import com.fr.base.ParameterMapNameSpace;
import com.fr.script.Calculator;
import com.fr.stable.script.CalculatorProvider;
import com.fr.stable.script.NameSpace;
import org.junit.Assert;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
/**
* @author richie
@ -43,4 +43,18 @@ public class FormulaKitTest extends Prepare {
Assert.fail();
}
}
@Test
public void testCheckFormulaContent() {
assertEquals(true, FormulaKit.checkFormulaContent(new Formula("")));
assertEquals(true, FormulaKit.checkFormulaContent(new Formula("SUM(1,1)")));
assertEquals(true, FormulaKit.checkFormulaContent(""));
assertEquals(true, FormulaKit.checkFormulaContent(("=SUM(1,1)")));
assertEquals(true, FormulaKit.checkFormulaContent(("SUM(1,1)")));
assertEquals(true, FormulaKit.checkFormulaContent(new Formula("=")));
assertEquals(false, FormulaKit.checkFormulaContent("="));
}
}

46
src/test/java/com/fanruan/api/function/FunctionKitTest.java

@ -0,0 +1,46 @@
package com.fanruan.api.function;
import com.fanruan.api.Prepare;
import com.fanruan.api.function.shell.FineFunc;
import com.fr.script.Calculator;
import com.fr.stable.UtilEvalError;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
/**
* @ClassName FunctionKitTest
* @Author zack
* @Date 2019/8/23
* @Version 10.0
*/
public class FunctionKitTest extends Prepare {
@Test
public void testFuncAdd() {
FunctionKit.removeFunc("com.fanruan.api.function.TestFunc");
FunctionKit.addFunc(new FineFunc("TestFunc", "com.fanruan.api.function.TestFunc"));
try {
assertEquals("OK", Calculator.createCalculator().evalValue("TESTFUNC()"));
} catch (UtilEvalError utilEvalError) {
}
}
@Test
public void testFuncRemove() {
FunctionKit.removeFunc("com.fanruan.api.function.TestFunc");
FunctionKit.addFunc(new FineFunc("TestFunc", "com.fanruan.api.function.TestFunc"));
FunctionKit.removeFunc("com.fanruan.api.function.TestFunc");
String result = "ERROR";
try {
result = Calculator.createCalculator().evalValue("TESTFUNC()").toString();
} catch (Throwable e) {
}
assertNotEquals("OK", result);
}
}

10
src/test/java/com/fanruan/api/function/TestFunc.java

@ -0,0 +1,10 @@
package com.fanruan.api.function;
import com.fr.script.AbstractFunction;
public class TestFunc extends AbstractFunction {
@Override
public Object run(Object[] objects) {
return "OK";
}
}

31
src/test/java/com/fanruan/api/report/analy/AnalyKitTest.java

@ -0,0 +1,31 @@
package com.fanruan.api.report.analy;
import com.fanruan.api.ModulePrepare;
import com.fanruan.api.report.analy.data.TreeNode;
import com.fr.log.FineLoggerFactory;
import com.fr.main.impl.WorkBook;
import com.fr.main.workbook.ResultWorkBook;
import com.fr.stable.ActorConstants;
import com.fr.stable.ActorFactory;
import org.junit.Assert;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
public class AnalyKitTest extends ModulePrepare {
@Test
public void testTree() {
WorkBook tpl = new WorkBook();
Map<Integer, TreeNode> nodeMap = new HashMap<Integer, TreeNode>(0);
try {
tpl.readStream(AnalyKitTest.class.getResourceAsStream("/com/fanruan/api/report/tree.cpt"));
ResultWorkBook resultWorkBook = tpl.execute(java.util.Collections.EMPTY_MAP, ActorFactory.getActor(ActorConstants.TYPE_ANALYSIS));
nodeMap = AnalyKit.generateResultBookTree(resultWorkBook, 0);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
Assert.assertEquals(nodeMap.toString(), "{0=0#-1#[-1,1,3,8,14,19,25,31], 1=1#0#[-1,2], 3=3#0#[-1,4,5,6,7], 19=19#0#[-1,20,21,22,23,24], 8=8#0#[-1,9,10,11,12,13], 25=25#0#[-1,26,27,28,29,30], 14=14#0#[-1,15,16,17,18], 31=31#0#[-1,32,33,34,35,36,37,38,39]}");
}
}

27
src/test/java/com/fanruan/api/util/TransmissionKitTest.java

@ -0,0 +1,27 @@
package com.fanruan.api.util;
import com.fanruan.api.util.trans.BatchSmsBody;
import com.fanruan.api.util.trans.SingleSmsBody;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @ClassName TransmissionKitTest
* @Author zack
* @Date 2019/8/23
* @Version 10.0
*/
public class TransmissionKitTest {
@Test
public void testSmsBody() {
try {
SingleSmsBody.newBuilder().mobile("").para(null).build();
BatchSmsBody.newBuilder().mobiles(null).build();
fail();
} catch (Exception e) {
assertTrue(true);
}
}
}

72
src/test/resources/com/fanruan/api/report/sheets.cpt

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<WorkBook xmlVersion="20170720" releaseVersion="10.0.0">
<Report class="com.fr.report.worksheet.WorkSheet" name="sheet1">
<ReportPageAttr>
<HR/>
<FR/>
<HC/>
<FC/>
</ReportPageAttr>
<ColumnPrivilegeControl/>
<RowPrivilegeControl/>
<RowHeight defaultValue="723900">
<![CDATA[723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900]]></RowHeight>
<ColumnWidth defaultValue="2743200">
<![CDATA[2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200]]></ColumnWidth>
<CellElementList>
<C c="0" r="0">
<O t="I">
<![CDATA[111]]></O>
<PrivilegeControl/>
<Expand/>
</C>
</CellElementList>
<ReportAttrSet>
<ReportSettings headerHeight="0" footerHeight="0">
<PaperSetting/>
<Background name="ColorBackground" color="-1"/>
</ReportSettings>
</ReportAttrSet>
<PrivilegeControl/>
</Report>
<Report class="com.fr.report.worksheet.WorkSheet" name="sheet2">
<ReportPageAttr>
<HR/>
<FR/>
<HC/>
<FC/>
</ReportPageAttr>
<ColumnPrivilegeControl/>
<RowPrivilegeControl/>
<RowHeight defaultValue="723900">
<![CDATA[723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900]]></RowHeight>
<ColumnWidth defaultValue="2743200">
<![CDATA[2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200]]></ColumnWidth>
<CellElementList>
<C c="0" r="0">
<O t="I">
<![CDATA[222]]></O>
<PrivilegeControl/>
<Expand/>
</C>
</CellElementList>
<ReportAttrSet>
<ReportSettings headerHeight="0" footerHeight="0">
<PaperSetting/>
<Background name="ColorBackground" color="-1"/>
</ReportSettings>
</ReportAttrSet>
<PrivilegeControl/>
</Report>
<ReportParameterAttr>
<Attributes showWindow="true" delayPlaying="true" windowPosition="1" align="0" useParamsTemplate="true"/>
<PWTitle>
<![CDATA[参数]]></PWTitle>
</ReportParameterAttr>
<StyleList/>
<DesignerVersion DesignerVersion="KAA"/>
<PreviewType PreviewType="0"/>
<TemplateIdAttMark class="com.fr.base.iofile.attr.TemplateIdAttrMark">
<TemplateIdAttMark TemplateId="fbd148d4-72d8-4df8-957f-c99fee3ca9dc"/>
</TemplateIdAttMark>
</WorkBook>

247
src/test/resources/com/fanruan/api/report/tree.cpt

@ -0,0 +1,247 @@
<?xml version="1.0" encoding="UTF-8"?>
<WorkBook xmlVersion="20170720" releaseVersion="10.0.0">
<TableDataMap>
<TableData name="ds1" class="com.fr.data.impl.EmbeddedTableData">
<Parameters/>
<DSName>
<![CDATA[]]></DSName>
<ColumnNames>
<![CDATA[部门ID,,.,,上级ID,,.,,部门名称]]></ColumnNames>
<ColumnTypes>
<![CDATA[java.lang.String,java.lang.String,java.lang.String]]></ColumnTypes>
<RowData ColumnTypes="java.lang.String,java.lang.String,java.lang.String">
<![CDATA[?'/Dg_Cu[YYIf;5:]AK8_h86Z%"/nKu1SQ!.J;HWbkJs3/fC!!jHE*0RfCq;gI?q%#O=%*ar_
l-4Tu:V]AM`ZEuB_48NTTm6sSUEe5+e:6r?0T@s]At/n@s$(>&F.>LRf]A0MJBQQ"KZHgQo8EMn
@7Hs(LfRWKV((C<qe'q-:2S6?6LEq8-phC*cB]AWX`SX$OCbkp2a8k;&iRqnp/&dg8NVY<Q`Y
pc7n\tWRUq2\O&;jh-4l5CL0p>!-'"\IYO1394-67'^A,&J*BPY$tY:*s+7EK'XR4959PkQa
-MJK'B<hp2i^n?mQ0X0!=WRR7Uf$EU86.Y\7r@Y^S+T>.-h@+"Lk%jc3KmJ1K;M[I;_Ze`8`
E#*u'-WX$SVu6f~
]]></RowData>
</TableData>
<TableData name="Tree1" class="com.fr.data.impl.EmbeddedTableData">
<Parameters/>
<DSName>
<![CDATA[]]></DSName>
<ColumnNames>
<![CDATA[部门ID,,.,,上级ID,,.,,部门名称,,.,,FR_GEN_0,,.,,FR_GEN_1,,.,,FR_GEN_2]]></ColumnNames>
<ColumnTypes>
<![CDATA[java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String]]></ColumnTypes>
<RowData ColumnTypes="java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String">
<![CDATA[?'=YO_Cu\C5F8i^gPsf(U+F(b0Rt&e0b=Na!14$a3rck:\ohrM\YYR+ZK0luF7/i]Ah'0k]A1p
>Z[/8@QbMcc[;mbOAMAZ:E-bT]Ar`0YH#$D`bg'@npmN;JkUIYbSDj]ASjZRrk$=B/?jp7jY2+
qcnjdN=Q<?^-9N8A:6cR7WUA$3HiTTOBh+[^7j*Kkd\`"&4l5JLQ0pk_;)[Wgbj6-JEd0,@.
KLS3!PI@?(*?J]ASbk.WJh#6;Wmn'k,6UhDN?8M8El!8t.R>aN'#B`0CHe*XmCkRB7@ni<nPW
KZV6/:rO""DhW(!U&D#>-'(k((1bLt0<A'CkS<-VkK@nuF5ln452+Cd^>IXa+Y'e#`pddA+O
AiC#1J.qQtQC7]AKlE8;tbMa*_<!#1P$1J81A%U`p8-(mdJb&]AO8AkfI8aV@S^+0i\&@(%b>@
tVW13!Oj@[6Uf]Am^>'3aS$(+s1MVqXY)YhY[B~
]]></RowData>
</TableData>
<TableData name="Tree2" class="com.fr.data.impl.EmbeddedTableData">
<Parameters/>
<DSName>
<![CDATA[]]></DSName>
<ColumnNames>
<![CDATA[部门ID,,.,,上级ID,,.,,部门名称,,.,,FR_GEN_0,,.,,FR_GEN_1,,.,,FR_GEN_2]]></ColumnNames>
<ColumnTypes>
<![CDATA[java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String]]></ColumnTypes>
<RowData ColumnTypes="java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String">
<![CDATA[?'=YO_Cu\C5F8i^gPsf(U+F(b0Rt&e0b=Na!14$a3rck:\ohrM\YYR+ZK0luF7/i]Ah'0k]A1p
>Z[/8@QbMcc[;mbOAMAZ:E-bT]Ar`0YH#$D`bg'@npmN;JkUIYbSDj]ASjZRrk$=B/?jp7jY2+
qcnjdN=Q<?^-9N8A:6cR7WUA$3HiTTOBh+[^7j*Kkd\`"&4l5JLQ0pk_;)[Wgbj6-JEd0,@.
KLS3!PI@?(*?J]ASbk.WJh#6;Wmn'k,6UhDN?8M8El!8t.R>aN'#B`0CHe*XmCkRB7@ni<nPW
KZV6/:rO""DhW(!U&D#>-'(k((1bLt0<A'CkS<-VkK@nuF5ln452+Cd^>IXa+Y'e#`pddA+O
AiC#1J.qQtQC7]AKlE8;tbMa*_<!#1P$1J81A%U`p8-(mdJb&]AO8AkfI8aV@S^+0i\&@(%b>@
tVW13!Oj@[6Uf]Am^>'3aS$(+s1MVqXY)YhY[B~
]]></RowData>
</TableData>
</TableDataMap>
<Report class="com.fr.report.worksheet.WorkSheet" name="sheet1">
<ReportPageAttr>
<HR/>
<FR/>
<HC/>
<FC/>
</ReportPageAttr>
<ColumnPrivilegeControl/>
<RowPrivilegeControl/>
<RowHeight defaultValue="723900">
<![CDATA[723900,723900,723900,723900,723900,723900,723900,723900,723900,723900,723900]]></RowHeight>
<ColumnWidth defaultValue="2743200">
<![CDATA[7772400,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200,2743200]]></ColumnWidth>
<CellElementList>
<C c="0" r="0" s="0">
<O t="DSColumn">
<Attributes dsName="Tree1" columnName="FR_GEN_0"/>
<Complex/>
<RG class="com.fr.report.cell.cellattr.core.group.FunctionGrouper"/>
<Parameters/>
</O>
<PrivilegeControl/>
<CellGUIAttr/>
<CellPageAttr/>
<Widget class="com.fr.report.web.button.form.TreeNodeToggleButton">
<WidgetAttr description="">
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[null]]></Text>
</Widget>
<Present class="com.fr.base.present.DictPresent">
<Dictionary class="com.fr.data.impl.TableDataDictionary">
<FormulaDictAttr ki="0" vi="2"/>
<TableDataDictAttr>
<TableData class="com.fr.data.impl.NameTableData">
<Name>
<![CDATA[ds1]]></Name>
</TableData>
</TableDataDictAttr>
</Dictionary>
</Present>
<Expand dir="0"/>
</C>
<C c="0" r="1" s="1">
<O t="DSColumn">
<Attributes dsName="Tree1" columnName="FR_GEN_1"/>
<Complex/>
<RG class="com.fr.report.cell.cellattr.core.group.FunctionGrouper"/>
<Parameters/>
</O>
<PrivilegeControl/>
<CellGUIAttr/>
<CellPageAttr/>
<Widget class="com.fr.report.web.button.form.TreeNodeToggleButton">
<WidgetAttr description="">
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[null]]></Text>
</Widget>
<HighlightList>
<Highlight class="com.fr.report.cell.cellattr.highlight.DefaultHighlight">
<Name>
<![CDATA[条件属性1]]></Name>
<Condition class="com.fr.data.condition.FormulaCondition">
<Formula>
<![CDATA[len($$$) = 0]]></Formula>
</Condition>
<HighlightAction class="com.fr.report.cell.cellattr.highlight.RowHeightHighlightAction"/>
</Highlight>
</HighlightList>
<Present class="com.fr.base.present.DictPresent">
<Dictionary class="com.fr.data.impl.TableDataDictionary">
<FormulaDictAttr ki="0" vi="2"/>
<TableDataDictAttr>
<TableData class="com.fr.data.impl.NameTableData">
<Name>
<![CDATA[ds1]]></Name>
</TableData>
</TableDataDictAttr>
</Dictionary>
</Present>
<Expand dir="0" leftParentDefault="false" left="A1"/>
</C>
<C c="0" r="2" s="2">
<O t="DSColumn">
<Attributes dsName="Tree1" columnName="FR_GEN_2"/>
<Complex/>
<RG class="com.fr.report.cell.cellattr.core.group.FunctionGrouper"/>
<Parameters/>
</O>
<PrivilegeControl/>
<CellGUIAttr/>
<CellPageAttr/>
<Widget class="com.fr.report.web.button.form.TreeNodeToggleButton">
<WidgetAttr description="">
<PrivilegeControl/>
</WidgetAttr>
<Text>
<![CDATA[null]]></Text>
</Widget>
<HighlightList>
<Highlight class="com.fr.report.cell.cellattr.highlight.DefaultHighlight">
<Name>
<![CDATA[条件属性1]]></Name>
<Condition class="com.fr.data.condition.FormulaCondition">
<Formula>
<![CDATA[len($$$) = 0]]></Formula>
</Condition>
<HighlightAction class="com.fr.report.cell.cellattr.highlight.RowHeightHighlightAction"/>
</Highlight>
</HighlightList>
<Present class="com.fr.base.present.DictPresent">
<Dictionary class="com.fr.data.impl.TableDataDictionary">
<FormulaDictAttr ki="0" vi="2"/>
<TableDataDictAttr>
<TableData class="com.fr.data.impl.NameTableData">
<Name>
<![CDATA[ds1]]></Name>
</TableData>
</TableDataDictAttr>
</Dictionary>
</Present>
<Expand dir="0" leftParentDefault="false" left="A2"/>
</C>
</CellElementList>
<ReportAttrSet>
<ReportSettings headerHeight="0" footerHeight="0">
<PaperSetting/>
<Background name="ColorBackground" color="-1"/>
</ReportSettings>
<Header reportPageType="0">
<Background name="NullBackground"/>
<LeftList/>
<CenterList/>
<RightList/>
</Header>
<Footer reportPageType="0">
<Background name="NullBackground"/>
<LeftList/>
<CenterList/>
<RightList/>
</Footer>
</ReportAttrSet>
<PrivilegeControl/>
</Report>
<ReportParameterAttr>
<Attributes showWindow="true" delayPlaying="true" windowPosition="1" align="0" useParamsTemplate="false"/>
<PWTitle>
<![CDATA[参数]]></PWTitle>
</ReportParameterAttr>
<StyleList>
<Style imageLayout="1">
<FRFont name="SimSun" style="0" size="72"/>
<Background name="ColorBackground" color="-6697729"/>
<Border>
<Top style="1" color="-13382452"/>
<Bottom style="1" color="-13382452"/>
<Left style="1" color="-13382452"/>
<Right style="1" color="-13382452"/>
</Border>
</Style>
<Style horizontal_alignment="0" imageLayout="1">
<FRFont name="SimSun" style="0" size="72"/>
<Background name="ColorBackground" color="-3342388"/>
<Border>
<Top style="1" color="-13382452"/>
<Bottom style="1" color="-13382452"/>
<Left style="1" color="-13382452"/>
<Right style="1" color="-13382452"/>
</Border>
</Style>
<Style horizontal_alignment="4" imageLayout="1">
<FRFont name="SimSun" style="0" size="72"/>
<Background name="ColorBackground" color="-52"/>
<Border>
<Top style="1" color="-13382452"/>
<Bottom style="1" color="-13382452"/>
<Left style="1" color="-13382452"/>
<Right style="1" color="-13382452"/>
</Border>
</Style>
</StyleList>
<DesignerVersion DesignerVersion="KAA"/>
<PreviewType PreviewType="2"/>
<TemplateIdAttMark class="com.fr.base.iofile.attr.TemplateIdAttrMark">
<TemplateIdAttMark TemplateId="f5d5a206-30a6-4709-8400-49dd95b5c57d"/>
</TemplateIdAttMark>
</WorkBook>
Loading…
Cancel
Save