1.报表上报汇总的运行时 (UploadRunTime, 填数过程) 在移动端的实现;
2.上报的报表 XML 模版,在 pc 端能录入、移动端也能录入,采集到的数据格式基本一致, 所以数据保存到数据库的工作不需要单独再开发;
3.您要做的,只是写一个很简单的 aspx 或 jsp,调用硕正报表服务, 动态地将报表 xml 文件转换成纯 HTML5 的程序即可.
Step 1:报表模版如下,该报表已经部署在服务器上了, 您不需要修改. Step 2:如下二维码指向后端的aspx程序, 请拿出手机扫描, 进入上报填数模式.
Step 3:在手机中任意输入,然后点击 “提交”,数据将上传、服务器将对数据进行验证, 如果地区、省份、城市、数量未输入,手机会给出未通过验证的提示.
一旦输入成功,大约 10 秒钟后,左侧报表会显示您刚才输入的内容!

注:在电脑上即刻显示手机录入内容的场景并不太常见,该例子只是演示了手机输入、三级关联下拉、ajax上传、验证、回显,这整个链路的实现的过程.



1.本页面脚本分析:
<script>
var uid;  //伪 id,本例中用来判别PC端、手机端是否同一个人
var count = 0;
function OnReady(id)
{
 cooper();
}
function cooper()
{
 count++;
 if(count != 3) return;
 
 //生成伪 id
 uid = getpsid();
 //打开报表模版
 AF1.func("build", "report/uploadmobile.xml");
 //打开Freeform
 AF2.func("build", "treelist/qr.xml");
 //Freeform显示二维码,引导您访问后端的关键程序:up.aspx
 AF2.func("SetValue", "QR \r\n http://www.supcan.cn/dotnet/up.aspx?func=0&uid=" + uid);
 //定时(每隔15秒)轮询,取得上报的XML数据
 setInterval("loadXML()", 15000);
}
 
//从服务器取得上报的XML
function loadXML()
{
 var xml = AF1.func("Download", "http://www.supcan.cn/dotnet/up.aspx?func=24&uid=" + uid + "\r\n toString=true; isEcho=false");
 if(xml == "") return;
 //把 XML 数据填入报表
 AF1.func("RebuildTabOrder", "");
 AF1.func("SetUploadXML", xml + "\r\n autoCalc=none");
}
 
//生成伪随机数
function getpsid()
{
 var s = new Date();
 return s.getHours().toString() + s.getMinutes().toString() + s.getSeconds().toString() + s.getMilliseconds().toString();
}
</script>
...
<body onLoad="cooper()" ...
这些就是全部的脚本了,客户端脚本并不复杂。

2.后端开发稍复杂,在开发文档的 “服务器专版” 中,有这方面的详细介绍。本例的后端程序资料可下载:uploadmobile.zip, 包中包括 3 个文件:
up.aspx - C#程序文件,关键代码
template_upload.txt - html 模版
uploadxml.js - html 引用的 js 包,用于下拉处理(比如例子中的三级关联下拉)、遍历 html 生成 XML 数据串、ajax上传

3.在开发文档中有介绍的关键代码,在此就不作介绍,如下是 up.aspx 和本例有关的其它功能讲解:
 ...
 //用于存放提交的 XML 串的map
 static Dictionary mapUidXml = new Dictionary();
 
 public void Page_Load(Object sender, EventArgs e) {
   ..
上报的 XML ,通常是需要后端解析、保存到数据库的,在本例中,只是简单地将其暂存在一全局哈希表 mapUidXml 中, 其 key 就是“伪id”。


 ...
 //分支:功能号24, 直接返回 uid 提交的 xml 串, 并从 map 中移除
 if(pageFunc == "24") {
  string xml = "";
  lock(mapUidXml) {	//并发加锁,必须的
   if(mapUidXml.ContainsKey(uid)) {
    xml = mapUidXml[uid];
    mapUidXml.Remove(uid);
   }
  }
  Response.Write(xml);
  Response.End();
  return;
 }
 ..
上面的代码相信您一看就明白,上面的C#片段,就是例子中 js 每隔10秒轮询的请求,URL中的功能号func=24,对应到后端的实现。