整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

如何用JavaScript和HTML 实现一整套的考试答题卡和成绩表

信在学校的你都有这样的体验,临近考试,必然要疯狂的“背诵”、“速记”,否则成绩单就要挂零,因为答题卡全部涂抹并不能得高分。

那么毕业多年的你,没有了考试,有没有一丝怀念涂答题卡的时候,有没有好奇这个答题卡到底如何制作,成绩表到底如何为每位同学定制动态生成的。

其实,这些都要归功于“报表”工具。

学校每年都会打印很多的学生成绩单,往往因为新增的课程和不同的教学体系,导致想要的结果复杂且多变。那么如何使用一个工具就可以灵活的制作各种各样报表,面对多变的场景,十分重要。

(答题卡)

上图就是我们制作出来的一个答题卡报表,而且它可以根据学生数量批量加载学生的信息数据,然后直接生成并且供我们打印。那它的优势也就显而易见了,自己设计的答题卡,题型和题量都可以自己来选择,灵活多变,且可以根据不同题型自己随意更新,也可以增加很多默认数据,毕竟自己设计打印的肯定也比购买的便宜。

自己制作报表困难吗?

有些人可能就想说,自己做是不是很麻烦,而且也不会用,学起来是不是还很吃力。小编就可以自信地说了,作为手残党的我也可以很快制作的,但是上限却很高,随着越发深入的使用,带来的经验肯定也是越多。当你熟练制作了后,还可以关注更多的功能,不仅仅是制作显示出来,更美观、更多的功能才是我们的追求。

就比如下面这个报表,只需要简单的几步就可以实现。而且效果还不错。

(最终效果展示)

实战开始

首先我们要设计对应的报表,下面是报表设计的整体界面:

在左侧是我们需要使用的组件,也就是设计报表需要的元素,中间就是显示,最右侧可以控制一些属性设置和指定数据。这么一看就很清晰了,我们其实简单的拖拽就可以实现所需要的报表设计,简单方便,设计好之后可以导出下载都可以。光说这些肯定还是不够的,那么接下来就直接上实例:

毕业信息表

当我们统计学校不同学院的毕业信息时,可能需要根据从系统中查到数据然后拿出来,之后在自己计算所需要的数据,然后在在Excel表中一点一点的去写,特别时数据多点,我们的工作人员可能就会因为一张表而制作一整天。毕竟制作Excel表的痛苦大家应该都知道吧,那用wyn产品怎么实现的,手残党福利来了:

只需要简单的绑定需要的数据,然后把要显示的直接拖到页面上,然后写几个表达式。完成,可能本来一天的工作量,现在几个小时就OK了,是不是很诱惑啊。可以看下面两个图,第一个是设计界面,第二个是预览成果。

(设计界面)

(表格展示)

没错,就是简单的绑定这么几列数据,然后他就会根据我们数据源有的数据进行自动计算,自动扩展行展示。是不是很简单。

答题卡

那么答题卡的样子上面大家已经看到了,那有人问了,我们学生人很多啊,我不可能真的一个一个设计吧,就算只是一直复制粘贴,也很费时间。那在怎么解决呢,很简单这里只要绑定好数据的话,设置按人的分组,那他就会自动加载所有学生的了,而且对应的信息也对对应过来,这个时候我们打印就可以批量打印,并且不同学生显示不同信息。这种场景其实也可以应用在很多场景下,比如打印学生的准考证,学生的成绩单等等,其实都是需要批量打印的,那用这个产品就可以实现相同模板的批量打印。

学生成绩单

除了教师使用的,当然也有学生使用的啦,就比如我们最常见的成绩单。

那么针对不同学生我们需要的是不同的成绩单,那这里就有个需求就是不同学生看不同的信息,自己查询自己的成绩单,自己打印自己的成绩单,那其实就像当于一个筛选。针对多变且不同的课程,往往很复杂,不同学生信息不同怎么办,那么使用wyn产品的就可以设计统一的样式,然后我们通过参数筛选,就可以筛选出来自己的信息。比如我们通过学号查询自己的成绩单,就可以实现如下图:

(学号筛选)

考生成绩表报表设计

接下来给大家来点干货分享,如何使用前端报表控件ARJS通过拖拉拽实现大学成绩绩效表的设计。

1、 首先我们来解析下这张报表

该表主要分为三个部分:

表头:也是就是学生基础信息,包括学习:姓名、学院、专业、学号、班级、学历、毕业证号

(学生信息)

明细部分:显示大学四年的考试绩效成绩,包含学期、课程名称、学分、成绩

明细部分你自己看发现其实是三个相同的模块

(模块细分)

表尾部分:表尾部分主要是学分的统计、平均成绩、平均绩点

(表尾部分)

2、 拆分完这张表之后,那么就可以根据实际需求进行报表的设计

首先给报表添加页眉和页脚,页眉中通过文本框来设置表头需要显示的信息表头和页脚通过文本框来进行表尾的显示设计。

中间内容区域,首先使用表格控件,然后利用表格控件的分组,分组条件根据绑定数据的中的数据字段学年和学期进行分组。

(表设计)

明细内容是三个相同的模块,也就是在一个内容区域显三个相同区域,那么这可以使用报表字段的分栏属性来设置。

(分栏属性设置)

3、 最终设计好的报表设计样式

(最终效果展示)

4、 最终预览结果:

(预览展示)

5、 报表模板

相信能看到这里的小伙伴肯定也已经跃跃欲试了,这里我们为大家提供了多模板可以尝试,欢迎搜索并访问葡萄城官网,了解更多。

个页面内显示多个iframe,一个变宽,另一个就变窄,一个变高,另一个就变矮的这种可自由伸缩的效果。它们之间有一个可多拽的分隔条。效果图:

修改文件位址:coreframe/app/content/admin/template/content_manage.tpl.php

用下面代码替代原来的;

<?php defined('IN_WZ') or exit('No direct script access allowed');?>

<?php

include $this->template('header','core');

?>

<body class="body">

<section id="iframecontent">

<section class="treelistframe pull-left">

<iframe width="190px" name="treemain" id="treemain" frameborder="false" scrolling="auto" height="auto" style="" allowtransparency="true" frameborder="0" src="?m=content&f=content&v=left&modelid=<?php echo $modelid.'&type='.$type.$this->su();?>"></iframe>

</section>

<section class="treelistframe pull-left">

<div id="s" style="height:100%;position:absolute;z-index:3;cursor:move;">

<img style="height:100%;position:absolute;z-index:1;" src="res/images/arrow1.png" />

<div style="height:100%;width:100%;position:absolute;z-index:2;margin-left:0px;margin-top:0px;padding:0px;filter:alpha(opacity=0);opacity:0;background-color:#fee;" id="drag"></div>

</div>

</section>

<section id="iframecontent">

<iframe width="100%" name="iframeid" id="iframeid" frameborder="false" scrolling="auto" height="auto" allowtransparency="true" frameborder="0" src="?m=content&f=content&v=listing&<?php echo $modelid.$this->su();?>"></iframe>

</section>

</section>

<script type="text/javascript">

/***

*

* iframe横向分隔条拖拽伸缩实例

*

***/

function init(){

//alert($("#treemain").contents().find("#tree").width());

var li = $("#treemain");//left iframe

var ri = $("#iframeid");//right iframe

var s = $("#s");//中间分割条

var img = s.children("img").eq(0);

var drag = $("#drag");//分隔条中的拖拽层.

var clientWidth = $(window).width();

var li_init_width=200;//上边iframe要显示的宽度,若需要调整默认宽度,请改此值即可.

var s_init_width=5;//分隔条宽度默认值

var ri_width=clientWidth-li_init_width-s_init_width;//底部iframe要显示的宽度

//初始化

li.css("width",li_init_width+"px");

ri.css("width",ri_width+"px");

s.css("left",li_init_width+"px").css("width",s_init_width+"px");

img.css("width",s_init_width+"px").css("box-shadow","0 0 2px #666");

var is_drag = false;//是否点住并进行了拖拽

/***

* 分隔条事件处理,如果用户执行了mousedown,mousemove,mouseup说明是拖拽,

* 如果只执行了mousedown,mouseup说明是点击.

*/

drag.unbind("mousedown").mousedown(function () {

//获得分隔条内拖拽层离顶边的距离

var li_width = parseInt(li.css("width"));

var ri_width = parseInt(ri.css("width"));

//分隔条div宽度设为100%,撑满屏,只有这样才能在拖拽分隔条时,有效的控制mouseup事件.

s.css("width","100%").css("left","0px");

img.css("left",li_width);

var start_x = event.clientX;

drag.unbind("mousemove").mousemove(function (event) {

is_drag = true;

var current_x = event.clientX;

var cha = current_x - start_x;//算偏移差量

li.css("width",(li_width+cha)+"px");

ri.css("width",(ri_width-cha)+"px");

img.css("left",(li_width+cha)+"px");

});

drag.unbind("mouseup").mouseup(function (event) {

var left = parseInt(img.css("left"));

s.css("width",s_init_width+"px").css("left",left+"px");

img.css("left","0px");

//处理非拖拽的click情况

if(!is_drag){

//直接设定固定值

var src=img.attr("src");

if(src.indexOf("toleft")!=-1){

li.css("width","0px");

s.css("left","0px");

clientWidth = $(window).width();

ri.css("width",(clientWidth-s_init_width)+"px");

img.attr("src",src.replace("toleft","toright"));

}else{

li.css("width",li_init_width+"px");

s.css("left",li_init_width+"px");

clientWidth = $(window).width();

ri.css("width",(clientWidth-li_init_width-s_init_width)+"px");

img.attr("src",src.replace("toright","toleft"));

}

}

drag.unbind("mousemove");

is_drag = false;

});

});

//当窗口大小发生改变时,重新渲染页面,以使各组件自适应高宽度.

$(window).resize(function() {

//顶部iframe保持高度不变,改变底部iframe高度

var clientWidth = $(window).width();

var li_width = parseInt(li.css("width"));

var new_ri_width = clientWidth - li_width - s_init_width;

ri.css("width",new_ri_width+"px");

});

}

/***

* 加载左边页面方法

* 当右边页面先加载完后再加载左边页面,因为左边页面需要控制右边页面里的iframe

* 如果右边页面还没加载完,则会出错,左边页面也会加载失败.

*/

function loadLeft(){

$("#li").attr("src","exam/left.html");

}

$(document).ready(function(){

init();

});

</script>

<script src="<?php echo R;?>js/bootstrap.min.js"></script>

<script src="<?php echo R;?>js/contentiframe.js"></script>

</body>

</html>

辑导语:虽然国内软件的iPad用户占比不大,但依然存在着横屏适配的需求。本文作者讲述了自己做iPad横屏适配的背景,并对竞品的适配方式进行了分析研究,用自己的亲身经历提供了参考,推荐对ipad横屏适配感兴趣的童鞋阅读。

一、背景

在我参与的一款资料查询 App 中,对 iPad 只支持竖屏以手机 UI 尺寸拉伸,每个季度都有用户反馈希望适配 iPad 横屏。经过询问用户发现,因为 iPad mini 尺寸刚好可以放在工作服口袋中,随时拿出来使用,而 iPad 屏幕远比手机大,浏览资料视野更大更舒服。

但另外一方面,后台数据显示当前 iPad 用户占比只有 1%,用户呼声够不上星星之火,不足以燎原。先别谈说服团队做 iPad 横屏适配,连说服自己都难。本来以为这事就像水中投石,水波消散就没有下文了。直到有一天,同样是资深用户的高管自己拿着 iPad 装上我们的 App 用了几天,终于忍不了,开始推动 iPad 横屏适配。

二、参考

我们肯定不是第一个做 iPad 横屏适配的,但在网上搜了一圈,别说横屏适配,连 iPad 界面设计的文章都很少,下面 3 篇算不错的。这也是我决定写下本文的原因,为后来者提供经验,少踩坑。

  1. 《利用好 iPad 的大屏幕 —— 如何为 iPadOS 14 设计 app?》,https://steppark.net/15942969497015.html
  2. 《iPad 交互设计探索系列:iPad 适用产品篇》,https://www.jianshu.com/p/65211fddefb9
  3. 《iPad 交互设计探索系列:iPad 导航设计篇》,https://www.jianshu.com/p/0c8e315d39d4

三、研究

没得经验参考就只能先从竞品分析开始了。经过对 iOS 系统应用、微信、QQ、微信阅读、得到、豆瓣、淘宝和有道词典的分析,我和同事总结成 5 种横屏适配模式。

1. 内容响应式

典型 App:iOS 应用商店

特征:标题栏和 Tabbar 通栏拉伸,内容区根据宽度向右响应式布局。

适用场景:全部场景。

评价:灵活性和用户体验都很好,但设计和开发成本很大。

2. 左右分栏

典型 App:iOS 设置、淘宝、微信、QQ

特征:左右分开显示,左边通常固定显示首页或者目录导航。右侧根据左侧选择显示对应的详情内容。

适用场景:频繁需要使用导航切换内容。

评价:用户体验适中,合理的利用横屏更大地展示更多的内容。设计成本小,需额外设计一个右侧默认为空的情况。开发成本要看是否改程序架构,相当于把手机两个手机界面合并成一个屏幕,可能有些程序架构很难这么修改。

3. 按竖屏宽度显示

典型 App:微信阅读

特征:标题栏和 Tabbar 通栏拉伸,内容直接按竖屏的宽度显示。

适用场景:全部场景。

评价:用户体验适中,设计与开发成本小,大多数产品采用此模式,但是没有更好的展现横屏宽屏的优势。

4. 全屏通栏拉伸

典型 App:豆瓣

特征:横屏为全屏通栏拉伸,所有元素与竖屏一致。

适用场景:全部场景。

评价:设计和开发成本最小,但是相当于没有适配。用户体验较差,横屏情况下内容集中,左侧右侧很空,或者被拉得很长,阅读体验较差。

5. 混合模式

当然也不是所有 App 都采用单一的模式。比如微信阅读,在其他页面是按竖屏宽度显示。但到了图书阅读界面,则是左右分栏充分利用 iPad 大屏幕展现内容。

以上竞品分析所有截图我们都保存在 Figma 中,有需要的读者可前往获取。

链接:https://www.figma.com/community/file/1071850659054902697/iPad-横屏适配竞品分析

四、执行

非常遗憾的是虽然高管牵头做适配,但开发资源确实有限。不能为了设计师邀功拿业绩就从头把 iOS App 重构一遍,因此我们决定用最少的资源做最核心的优化。

适配计划分为 2 期。第 1 期将所有页面用按竖屏宽度显示进行横屏适配。第 2 期挑选核心页面用内容响应式或左右分栏进行优化。

1. 先开发再验收

在第 1 期我们就踩坑了,按照原来的工作流程,我们将所有的 iPad 横屏页面做好线框图、再输出所有视觉效果图。虽然都是线上页面不用重新设计,只需要拉伸画面或者调整间距,但所有线上页面也是一个不小的工作量。

就在进行过程中,iOS 工程师就皱着眉头来提议,由于代码架构和资源所限,设计师如果调整的视觉效果图未必能 100% 实现。不如反过来,让他先把所有页面强行横屏,再由设计师走查发现问题进行修改,这样节省时间效果也可控。

可见,不同的项目类型可以采取不同的工作流程。iPad 横屏适配项目流程和常规工作流程刚好相反,以往是先设计再开发,改成先开发再走查,节省设计师产出效果图时间,也保障最终实现效果。

2. 核心场景决定核心页面

在第 2 期挑选核心页面时,我也犯了错误。最开始我觉得核心是脸面,因此挑选 Tabbar 导航的首页、个人中心等用户一打开 App 就看得到的页面进行优化。但实际上用户真正的核心使用场景是在详情页查阅资料,这才是真正的核心页面。

在得到主管纠正后,我们转而开始为资料阅读页面提供左内容右目录的布局,便于用户方便地在长文中精确定位想读的内容。

2 期计划并非适配的终结,随着 App 功能的迭代,此后老界面修改和新界面设计需要考虑到 iPad 横屏的适配问题,就成为了日常工作的内容了。

五、总结

按照以往的项目总结,最后应该汇报项目数据结果。但由于 iPad 用户本身可怜的占比,即使我们官方公众号推文宣布适配 iPad 横屏后,也没有 iPad 用户站出来点赞,而是又引发出使用华为、小米等安卓 Pad 的用户,要求也适配。

考虑到不同的安卓品牌适配方式不一样,而且安卓厂商自己又有平行世界等通用兼容方案,我们就没再继续参与了。

虽然没有外部用户反馈,但公司内部同事和开发团队使用后确实感觉很棒。所以我觉得这次适配项目真正值得思考的是:如果一个需求用户反馈很少,也没有数据支撑,但对体验影响很大,如何推动团队进行优化呢?

作者:龙爪槐守望者,微信公众号:龙爪槐守望者

本文由 @龙爪槐守望者 原创发布于人人都是产品经理。未经许可,禁止转载。

题图来自 Unsplash,基于 CC0 协议