小程序积分排行

小程序云开发积分管理,奖励自动排名定等级.

企业微信里写了个小程序,对学生的积分进行管理,前段时间无聊想着弄个排名吧,因为平时也有扣分,那些平时表现好的犯错跟其他成员扣分一样扣,总觉得亏了点,于是就抄王者荣耀搞了奖分等级,等级高点的扣分的时候就打个折。懒得改小程序,就每个月导出数据库统计一次,扣分打折根据统计出来的排名折扣口算输入。新学期,想着长痛不如短痛,还是直接做在小程序里好了。

云数据库新建rank集合

字段一开始只有name,reward,graduate三个个字段,后来发现坑了,哪怕数据权限改成“所有用户可读,仅创建者可读写”也无法修改数据,只好再加了个_openid字段,值全部是我自己的openid,然后才正常了,也就是加了openid我才有权限修改,这里折腾了很久,一直以为是自己逻辑弄错了。

pages/admin/admin.js //奖惩处理

数据库初始化

1
2
3
// score集合保存所有学生的奖惩记录
const score = db.collection('score');
const rankCollection = db.collection('rank');

输入姓名从rank集合读取排名计算扣分时的折扣rate

这里我傻了点,我是用for循环找有序数组里对应用户的排名的,其实直接在取好的数组里添加一个顺序字段index,后面直接读取index就可以了。

1
2
3
4
// 从rank集合按降序提取前10名未毕业的同学
const rank10 = db.collection('rank').where({
  graduate: 0
}).limit(10).orderBy('reward', 'desc');
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 奖惩时输入姓名查找前十名次,计算折扣 
  inputName(event) {
    nowname = event.detail
      rank10.get({
        success: res => {
          this.setData({
            rate: 1
          })
          for (let i = 0; i < 10; i++) {  //查找排名
            if( res.data[i].name == event.detail){
              if (i < 1){var rate = 0.5;}
                  else if (i < 3){var rate = 0.7;}
                    else if(i < 6){var rate = 0.8;}
                      else {var rate = 0.9;}
              console.log(rate)
              this.setData({
                rate: rate
              })
              break
            }
          }
        }
      })
  },

奖惩操作:负分打折,正分累加

参考小程序调用另一个函数方法中的值调用rate,保存数据时判断分数小于0,则乘以rate。累加那段折腾了很久,一开始用的get.where判断用success箭头函数,但就是要么不生效要么新增数据两倍累加,也不懂,就不停试,直到后来看到JavaScript 错误 - Throw 和 Try to Catch (w3school.com.cn),试了下,好像可以,想着里面应该是个函数,确实可行,就先这样了。中间还出了个拼写错误,现在就不知道试的过程中还有没有别的方法是可以用的了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
  // 添加奖惩信息
  saveuserinfo() {
    if (score1 < 0){ //负分处理
      var rate = this.data.rate
      score.add({  //添加折后数据
            data: {
              name: nowname,
              score: score1*rate, //扣分打折
              detail: detail,
              content: content,
              time: time
            }
          }).then(res => {
            console.log('奖惩成功!')
            wx.showToast({
              title: '奖惩成功!',
              icon: 'success',
              duration: 3000
            })
          })
        }
    else{	//正分处理
      score.add({  //添加奖分数据
        data: {
          name: nowname,
          score: score1, //奖分不打折
          detail: detail,
          content: content,
          time: time
        }
      }).then(res => {
        console.log('奖惩成功!')
        wx.showToast({
          title: '奖惩成功!',
          icon: 'success',
          duration: 3000
        })
      }) 
      //加分写入rank集合,if的几种情况不累加,不知道怎么or。。。
      if(content == "申请通过"){} 
      else if(content == "申请成功"){}
      else if(content == "战队排行"){}
      else if(content == "提交检讨"){}
      else{ //把加分累加到总奖分里
        console.log(nowname,score1)
        //先添加数据,数据库name唯一索引,已有name会出错,错误时更新reward
        rankCollection.add({  
        data: {
          graduate: 0,	//既然有加分那肯定没毕业
          name: nowname,
          reward: score1
        }
        }).catch(function() {
          console.log('已有用户数据,更新总奖分');
          rankCollection.where({
            name: nowname
          }).update({
            data: {
              reward: _.inc(score1)
            }
          }) 
        })
      }
    }
  }   
,

pages/index/index.js //首页等级逻辑

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 读取当前用户在前十名中的名次,未匹配则为青铜
console.log('[获取]user集合用户姓名: ', nowname)
rankCollection.where({ //毕业学生全部都是传奇王者
  name: nowname
  })
  .get({
    success: res => {
      if (res.data[0].graduate == 1)
      {this.setData({
        grade: "☆☆☆☆☆传奇王者☆☆☆☆☆"
      })
      console.log('等级: ', grade)
      }
      else {
        rank10.get({
          success: res => {
            this.setData({
              grade: "★倔强青铜★"	//在校生默认青铜
            })
            for (let i = 0; i < 10; i++) {  //查找前十名次
              if( res.data[i].name == nowname){
                if (i < 1){this.setData({
                        grade: "★★★★★荣耀王者★★★★★"
                      })}
                else if (i < 3){this.setData({
                      grade: "★★★★至尊星耀★★★★"
                    })}
                  else if(i < 6){this.setData({
                        grade: "★★★永恒钻石★★★"
                      })}
                else {this.setData({
                  grade: "★★尊贵铂金★★"
                  })}
                console.log(grade)
                break
              }
            }
          }
        })
      }
    },
    fail:	//从来没加过分的同学都是青铜
    this.setData({
      grade: "★倔强青铜★"
    })
  })

pages/index/index.wxml //首页渲染

用了个Vant Weapp的UI组件vantvan-button展示等级,CSS我不知道怎么修改,就只好挑自己喜欢的组件用了。

1
<van-button type="warning" size="large">{{grade}}</van-button>

前十名次计算的另一种思路

用for循环增加index名次字段,然后读取名次就好了,做前二十的排行榜的时候网上找的办法。

按前面的方法,rank20只有名字和总奖分,渲染的页面就是一个ranklist循环:

1
2
3
4
5
6
7
8
9
<!--pages/rank/rank.wxml-->
<block wx:for="{{ranklist}}" wx:key="_id">
<van-cell value="{{item.reward}}" center>
 <view slot="title">
   <view class="van-cell-text">{{item.index}}.  {{item.name }}</view>
   <van-tag type="danger">{{item.grade}}</van-tag>
 </view>
</van-cell>
</block>

不知道怎么在wxml加其他要展示的信息,那就只能在rank.js里想办法了。 pages/rank/rank.js:for循环添加名次index和等级grade字段到ranklist。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
const rank20 = db.collection('rank').where({
  graduate: 0
}).limit(20).orderBy('reward', 'desc');

rank20.get()
.then(async res => {
  var ranklist = res.data
  // console.log(ranklist)
    for (const i in ranklist) {
      ranklist[i].index = Number(i)+1
      if (Number(i) < 1){ranklist[i].grade = "★★★★★荣耀王者★★★★★"}
      else if (Number(i) < 3){ranklist[i].grade =  "★★★★至尊星耀★★★★"}
      else if(Number(i) < 6){ranklist[i].grade = "★★★永恒钻石★★★"}
      else  if(Number(i) < 10){ranklist[i].grade = "★★尊贵铂金★★"}
      else{ranklist[i].grade = "★倔强青铜★"}
    }
      // console.log(ranklist)  
      this.setData({
        ranklist: ranklist
      }) 
})

结语

开学一个礼拜就干了这个,换成懂的人,估计几分钟就解决了吧,那几天脑子里都在想为什么写的跟实现的不一样,怎么才能解决,然后就是各种搜索。官方文档确实很有用,有些问题就是直接抄的官方文档里的代码稍微改改就可以了。

挺好的,实现了自己想要的功能,很有成就感。

Built with Hugo
主题 StackJimmy 设计