这是一个可以部署在私有服务器上的钉钉企业微应用,可用于公司年会抽奖等活动。抽奖通过员工摇动手机方式参与,采用参与激励的算法,摇得越多中奖概率越高。同时中奖结果逐步实时产生并实时显示在大屏幕上。
该程序分为手机端,投屏端,管理端三部分组成:
- 手机端:作为一个微应用部署到钉钉中,活动开始后员工可以从微应用中进入参与摇奖。
- 投屏端:通过PC浏览器访问,可以在活动现场投射到大屏幕上,实时显示中奖结果。
- 管理端:通过PC浏览器访问,用于设定摇奖参数。
当部署好程序之后(如何部署后面介绍),假设您的主机地址是127.0.0.1,三个端的地址分别是:
- 手机端:http://127.0.0.1/phone.html
- 投屏端:http://127.0.0.1/pc.html?playId=xxx
- 管理端:http://127.0.0.1/add.html
首先您需要先访问『管理端』创建一个活动。创建活动需要填写三个字段:
- 标题:显示在投屏端的活动标题,比如『三等奖抽奖』
- 奖品数量:即本次活动总共中奖人数
- 总时间(单位:毫秒):从开始摇奖起多久之内活动结束(实测一分到一分半钟体验较佳)
填写完字段后点击创建会产生一个url,如:http://127.0.0.1/pc.html?playId=123456
打开第一步中拿到的url,这既是需要被投屏的页面。在抽奖开始时点击开始按钮,程序会倒计时10秒后开始抽奖。
活动开始后,所有『手机端』即可开始摇。摇奖会有三种结果:
- 活动未开始:如果所在企业当前的摇奖活动还未开始或者已经结束,就会显示这个结果。
- 再接再厉:活动已经正在进行,但是摇一摇未中奖,但可以继续摇看能不能中奖。
- 恭喜中奖:活动正在进行并且已经中奖,此时您的名字应该会显示在投屏上了。
一般年会上,会有多个抽奖活动,比如一等奖,二等奖,三等奖等,所以需要在管理端创建多个活动,不同的活动url不一样。每个活动有三种状态:未开始,正在进行,已结束。如果全局上创建了多个活动,那么在同时只能有一个活动处于『正在进行』状态。如果当前已经有活动在进行,对另外一个未开始活动执行开始命令是无效的。
根据阳光普照原则,已经中过奖的人,会被拉入一个中奖黑名单中,不能再中奖。此黑名单是跨越活动的,全局有效的。当一个人中了三等奖之后,他将无法再中二等奖,一等奖其他任何奖。如果需要清除黑名单,则需要对数据进行重置。
在『管理端』的最下方有个重置按钮,点击之后所有已创建的活动,以及黑名单数据都清除。
登录企业后台,进入『https://oa.dingtalk.com/#/microApp/microAppSet』获取企业CorpID和CorpSecret。
分别将CorpID和CorpSecret填到src/main/java/com/alibaba/dingtalk/openapi/demo/Env.java中的CORP_ID常量和CORP_SECRET中。
切到项目根目录执行如下打包命令:
mvn clean assembly:assembly -Dmaven.test.skip
得到war包之后根据服务器配置正确部署
- 访问 /phone.html 能正确返回一个html页面
- 访问 /reset 能够正确返回一个json字符串
测试完毕之后登陆企业后台,进入『https://oa.dingtalk.com/#/microApp/microAppList』
点击『新建应用』,弹出的对话框中『首页地址』字段填写摇一摇微应用的手机端地址(比如您的服务器ip地址是127.0.0.1,就填http://127.0.0.1/phone.html)
其他字段根据实际需要填写。
至此程序已经部署完毕,企业成员可以通过钉钉微应用入口找到新增的摇一摇应用。如果打开后出现授权失败等提示,说明服务器有部分环节部署没有成功。
一个活动拥有配置参数$COUNT(奖品总数),$DURATION(抽奖持续时间),而算法旨在$DURATION时间内将$COUNT个奖品随机派发出去。
- 当活动开始时在当前时间$CURRENT_TIME和$CURRENT_TIME+$DURATION范围内随机取$COUNT个时间点,从小到大排序后产生一个时间点队列,$TIMES。
- 当有用户摇动手机时发送请求到服务端,服务的那首先判断发起人是否在『黑名单』中,黑名单中的请求直接返回不中奖,不参与抽奖。
- 当请求用户不在黑名单中,则获取请求进入的时间$REQUEST_TIME,当$REQUEST_TIME>=$TIMES[0],则认为此用户中奖,输出中奖信息到屏幕并将此用户加入到黑名单中。而后将$TIMES[0]从$TIMES队首删除。
- 不断有用户请求发送到服务器,反复执行2,3步中的计算,直到$TIMES队列被全部清空,此时即全部奖项发放完毕活动自动结束。