• 微信小程序投票管理系统:打造智能、便捷的投票体验


    前言

    随着社交网络的兴起和移动互联网的普及,人们对于参与和表达意见的需求越来越强烈。在这个背景下,微信小程序投票管理系统应运而生。它为用户提供了一个智能、便捷的投票平台,使用户可以轻松创建和参与各种类型的投票活动。本文将详细介绍微信小程序投票管理系统的设计与功能,并探讨其在实际应用中的优势和耐人寻味之处。

    投票管理的实现

    实现流程

    1.用户进入后显示投票页面

    2.用户可以选择自己想投票的选项并进行投票

    3.投票完成后显示总的投票结果以及投票数量

    4.限制每个用户每天投票只能进行一次

    用例图演示

    用户在系统内可以登陆,选择投票对象、进行投票、查看投票等等。

     数据表

     

     总体设计

     投票管理系统后端

    mapper

    1. package com.ctb.minoa.mapper;
    2. import com.ctb.minoa.model.Voteinfo;
    3. public interface VoteinfoMapper {
    4. int deleteByPrimaryKey(int id);
    5. int insert(Voteinfo record);
    6. int insertSelective(Voteinfo record);
    7. Voteinfo selectByPrimaryKey(int id);
    8. int updateByPrimaryKeySelective(Voteinfo record);
    9. int updateByPrimaryKey(Voteinfo record);
    10. }

    controller

    1. /**
    2. * @Autho biao
    3. *
    4. */
    5. @RestController
    6. @RequestMapping("/wx/vote")
    7. public class VoteinfoController {
    8. @Autowired
    9. private VoteinfoMapper voteinfoMapper;
    10. @RequestMapping("/index")
    11. public Object index(Voteinfo voteinfo) {
    12. Voteinfo voteinfo1 = voteinfoMapper.selectByPrimaryKey(3);
    13. Map<Object, Object> data = new HashMap<Object, Object>();
    14. data.put("voteinfoList",voteinfo1);
    15. return ResponseUtil.ok(data);
    16. }
    17. }

    工具类getopenid---获取用户的openid

    1. package util;
    2. import com.alibaba.fastjson.JSON;
    3. import com.alibaba.fastjson.JSONObject;
    4. import java.io.*;
    5. import java.net.URL;
    6. import java.net.URLConnection;
    7. import java.util.List;
    8. import java.util.Map;
    9. /**
    10. * biao
    11. *拼接用户信息对官方进行用户的openid进行查询
    12. *
    13. */
    14. public class getopenid {
    15. public static String getOpenid(String url) {
    16. String result = "";
    17. BufferedReader in = null;
    18. try {
    19. String urlNameString = url;
    20. URL realUrl = new URL(urlNameString);
    21. // 打开和URL之间的连接
    22. URLConnection connection = realUrl.openConnection();
    23. // 设置通用的请求属性
    24. connection.setRequestProperty("accept", "*/*");
    25. connection.setRequestProperty("connection", "Keep-Alive");
    26. connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
    27. // 建立实际的连接
    28. connection.connect();
    29. // 获取所有响应头字段
    30. Map<String, List<String>> map = connection.getHeaderFields();
    31. // 遍历所有的响应头字段
    32. // 定义 BufferedReader输入流来读取URL的响应
    33. in = new BufferedReader(new InputStreamReader(
    34. connection.getInputStream()));
    35. String line;
    36. while ((line = in.readLine()) != null) {
    37. result += line;
    38. }
    39. } catch (Exception e) {
    40. System.out.println("发送GET请求出现异常!" + e);
    41. e.printStackTrace();
    42. }
    43. // 使用finally块来关闭输入流
    44. finally {
    45. try {
    46. if (in != null) {
    47. in.close();
    48. }
    49. } catch (Exception e2) {
    50. e2.printStackTrace();
    51. }
    52. }
    53. return result;
    54. }
    55. public static String jointStr(String code) {
    56. String result = "https://api.weixin.qq.com/sns/jscode2session?appid=wxf55dc8be7c3885ab&secret=05e3ac3badee5c088ff97b5f3cac3974&js_code=";
    57. String rigth = "&grant_type=authorization_code";
    58. return result + code + rigth;
    59. }
    60. public static String outopenid(String code){
    61. String json = getOpenid(jointStr(code));
    62. JSONObject jsonObj = JSON.parseObject(json);
    63. System.out.println("openid:"+jsonObj.getString("openid"));
    64. return jsonObj.getString("openid");
    65. }
    66. }

    解释:

    1. 该类包含三个静态方法:getOpenid()jointStr()outopenid()
    2. getOpenid(String url)方法:

      • 参数:一个字符串类型的URL。
      • 返回值:一个字符串类型的结果。
      • 功能:通过发送GET请求到指定的URL,并从响应中解析出openid。
        • 首先,创建一个URL对象,表示要连接的URL。
        • 然后,使用openConnection()方法打开与URL之间的连接。
        • 设置通用的请求属性,如"accept"、"connection"和"user-agent"。
        • 建立实际的连接。
        • 获取所有响应头字段。
        • 定义一个BufferedReader输入流来读取URL的响应。
        • 逐行读取响应内容,并将其拼接到结果字符串中。
        • 关闭输入流。
        • 返回结果字符串。
    3. jointStr(String code)方法:

      • 参数:一个字符串类型的code。
      • 返回值:一个字符串类型的拼接后的URL。
      • 功能:根据给定的code和appid和密钥拼接成一个完整的URL,用于向微信服务器发送请求以获取用户的openid。
        • 定义一个字符串变量result,存储拼接后的URL前半部分。
        • 定义一个字符串变量rigth,存储拼接后的URL后半部分。
        • 返回拼接后的完整URL。
    4. outopenid(String code)方法:

      • 参数:一个字符串类型的code。
      • 返回值:一个字符串类型的openid。
      • 功能:调用getOpenid()方法获取响应中的JSON字符串,然后将其解析为JSON对象,并从中提取出openid。
        • 调用getOpenid()方法,传入拼接后的URL,获取响应中的JSON字符串。
        • 使用JSON.parseObject()方法将JSON字符串转换为JSON对象。
        • 从JSON对象中获取名为"openid"的值,并打印出来。
        • 返回提取出的openid。

    获取小程序传递的参数

    1. String openid =request.getParameter("openid");
    2. Writer out = response.getWriter();
    3. String sqlSel = "SELECT * FROM openid WHERE openid = '"+ openid +"'";
    4. String sqlIns = "INSERT INTO openid VALUES ('"+ openid +"')";
    5. System.out.println(sqlIns);
    6. sqlUtils sqlutils = new sqlUtils();
    7. if (!openid.equals("")) {
    8. int count = sqlutils.selectOpenid(sqlSel);
    9. System.out.println(count);
    10. if (count == 0) {
    11. sqlutils.DMLsql(sqlIns);
    12. System.out.println(sqlIns);
    13. out.write("false");
    14. System.out.println("没投票");
    15. } else {
    16. out.write("true");//数据库中已有数据
    17. System.out.println("1投票");
    18. }
    19. }

    获取参数并修改投票数量

    1. int votevalue = Integer.parseInt(request.getParameter("votevalue"));
    2. String s="SELECT * FROM voteinfo where id =" + votevalue;
    3. sqlUtils utils=new sqlUtils();
    4. List<vote1> selectsql = utils.selectsql11(s);
    5. int a = 0;
    6. for(vote1 tl:selectsql)
    7. {
    8. a=tl.getValue();
    9. }
    10. ++a;
    11. System.out.println(a);
    12. String s1="update voteinfo set value =" + a + " where id =" + votevalue;
    13. int a1 = utils.DMLsql(s1);
    14. utils.Exceptionsql();

    投票管理系统前端

    投票页面wxml

    1. <image src="{{indeximage}}" class="indexImage_top"></image>
    2. <view class="text-top">请选择你喜欢的角色</view>
    3. <radio-group bindchange="radioChang" data-id="{{item.id}}">
    4. <view class="index_class" wx:for="{{voteinfo}}" wx:for-item="item" wx:key="index">
    5. <view class="voteInfo_class">
    6. <radio value="{{item.id}}">
    7. <view>{{item.id}}号选手:{{item.name}}</view>
    8. <image src="{{item.imagesrc}}" class="voteImage"></image>
    9. </radio>
    10. </view>
    11. </view>
    12. <button class="btn" type="primary" bindtap="sureVote">确定投票</button>
    13. </radio-group>
    14. <view class="text-bottom">
    15. <view>每人只能投票一次,投票后可以查看每个选项的投票次数</view>
    16. </view>

    wxss

    1. /*首页图*/
    2. .indexImage_top {
    3. width: 100%;
    4. height: 300rpx;
    5. }
    6. .text-top{
    7. display: flex;
    8. align-items: center;
    9. justify-content: center;/*对齐方式*/
    10. height: 100rpx;
    11. font-weight: 600;
    12. font-size: large;
    13. }
    14. .text-bottom{
    15. display: flex;
    16. flex-direction: column;/*以列的方式进行排列*/
    17. align-items: center;
    18. justify-content: center;
    19. height: 40rpx;
    20. font-size:smaller;
    21. margin-top:40px;/*margin外边距 上右下左 padding内边距*/
    22. margin-bottom: 60rpx;
    23. }
    24. /*投票view的边距*/
    25. .voteInfo_class{
    26. padding: 20px 10px 20px 10px;
    27. }
    28. /*投票的图片大小*/
    29. .voteImage {
    30. width: 250rpx;
    31. height: 250rpx;
    32. }
    33. /*首页排版*/
    34. .index_class {
    35. display: flex;
    36. flex-direction: row;
    37. flex-wrap: wrap;
    38. justify-content:space-around;
    39. display:inline-block
    40. }
    41. .btn{
    42. margin-top: 30rpx;
    43. width: 300rpx;
    44. }

    js

    1. Page({
    2. data: {
    3. indeximage:"/pages/images/index.png",
    4. voteinfo:[],
    5. radioValue: '', //当前用户选中的投票值
    6. userinfo: {}, //当前用户的微信信息
    7. openid: '', //当前用户的openid
    8. islogin: false, //判断用户是否已经登陆
    9. isopenid: false, //判断用户是否已经投票
    10. a: 1 ,//判断是否对数据库查询用户是否投票
    11. },
    12. onLoad: function () {
    13. let islogin = wx.getStorageSync('islogin') || false //判断是否登陆
    14. let userinfo = wx.getStorageSync('userinfo') //取登陆后的信息
    15. //console.log(islogin)
    16. if (islogin) {
    17. this.setData({
    18. islogin: true,
    19. userinfo: userinfo,
    20. })
    21. }
    22. //判断本获取投票名字和图片
    23. this.getvoteinfo()
    24. //微信登录获取openid
    25. this.wxlogin()
    26. },
    27. //首页确定投票事件
    28. sureVote: function () {
    29. this.setData({
    30. a: 1
    31. })
    32. //let openid = wx.getStorageSync('openid')
    33. console.log(this.data.openid)
    34. //微信登录获取个人信息
    35. if (!this.data.islogin) {
    36. //登陆及获取用户信息
    37. this.wxgeiuserinfo()
    38. //console.log(this.data.islogin)
    39. //console.log(this.data.userinfo)
    40. } else {
    41. //console.log(this.data.islogin)
    42. //console.log(this.data.userinfo)
    43. if (this.radioValue == undefined) {
    44. wx.showToast({
    45. title: '请选择你的投票对象',
    46. icon: 'none'
    47. })
    48. } else {
    49. this.data.isopenid = wx.getStorageSync('isopenid') //判断用户是否投票
    50. console.log(this.data.isopenid)
    51. if (this.data.isopenid) { //如果投过票 就直接跳转
    52. wx.setStorageSync('votevalue', this.radioValue)
    53. wx.redirectTo({
    54. url: '/pages/result/result'
    55. })
    56. } else {
    57. wx.request({
    58. url: 'http://localhost:8080/vote/voteupdate',
    59. data: {
    60. votevalue: this.radioValue
    61. },
    62. method: 'get',
    63. header: {
    64. 'content-type': 'application/json'
    65. },
    66. })
    67. wx.setStorageSync('votevalue', this.radioValue)
    68. wx.redirectTo({
    69. url: '/pages/result/result'
    70. })
    71. }
    72. }
    73. }
    74. },
    75. //单选框组选中事件
    76. radioChang: function (e) {
    77. console.log("选择的值为" + e.detail.value)
    78. this.radioValue = e.detail.value
    79. console.log(this.radioValue)
    80. if (this.data.a == 1) {
    81. //判断该用户是否投票
    82. this.isopenid()
    83. this.setData({
    84. a: 0
    85. })
    86. }
    87. },
    88. //获取openid
    89. wxlogin: function () {
    90. console.log("我是获取openid")
    91. var that = this
    92. wx.login({
    93. success(res) {
    94. if (res.code) {
    95. //console.log(res.data)
    96. //发起请求
    97. wx.request({
    98. url: 'http://localhost:8080/vote/openid',
    99. data: {
    100. code: res.code
    101. },
    102. header: {
    103. 'content-type': 'application/json'
    104. },
    105. success: function (res) {
    106. console.log(res);
    107. let openid = res.data
    108. that.setData({
    109. openid: openid
    110. })
    111. //console.log(that.data.openid);
    112. wx.setStorageSync('openid', that.data.openid)
    113. },
    114. fail: function (res) {
    115. console.log("失败");
    116. }
    117. })
    118. } else {
    119. console.log('登录失败!' + res.errMsg)
    120. }
    121. }
    122. })
    123. },
    124. //登陆及获取用户信息
    125. wxgeiuserinfo: function () {
    126. console.log("我是登陆及获取用户信息")
    127. let that = this;
    128. wx.getUserProfile({
    129. desc: '获取个人信息以便于您的投票',
    130. success(res) {
    131. let userinfo = res.userInfo
    132. that.setData({
    133. islogin: true,
    134. userinfo: userinfo
    135. })
    136. wx.setStorageSync('islogin', true)
    137. wx.setStorageSync('userinfo', userinfo)
    138. console.log(that.islogin)
    139. },
    140. fail() {
    141. wx.showToast({
    142. title: '请求信息失败',
    143. icon: 'error'
    144. })
    145. }
    146. })
    147. },
    148. //判断该用户是否投票
    149. isopenid: function () {
    150. console.log("我是判断该用户是否投票")
    151. let that = this
    152. wx.request({
    153. url: 'http://localhost:8080/vote/isopenid',
    154. data: {
    155. openid: this.data.openid
    156. },
    157. method: 'get',
    158. header: {
    159. 'content-type': 'application/json'
    160. },
    161. success(res) {
    162. console.log(res.data)
    163. let isopenid = res.data
    164. wx.setStorageSync('isopenid', isopenid)
    165. },
    166. fail() {
    167. wx.showToast({
    168. title: '网络连接失败!',
    169. icon: 'error'
    170. })
    171. console.log("失败");
    172. },
    173. })
    174. },
    175. //获取投票信息
    176. getvoteinfo: function () {
    177. console.log("我是获取投票图片")
    178. var that = this
    179. wx.request({
    180. url: 'http://localhost:8080/vote/voteinfo',
    181. success: function (res) {
    182. console.log(res);
    183. that.setData({
    184. voteinfo: res.data
    185. })
    186. console.log(that.data.voteinfo);
    187. wx.setStorageSync('voteinfo', res.data)
    188. wx.setStorageSync('isinfo', true)
    189. },
    190. fail: function (res) {
    191. wx.showToast({
    192. title: '网络连接失败!',
    193. icon: 'error'
    194. })
    195. console.log("失败");
    196. }
    197. })
    198. },
    199. onRefresh(){
    200. this.getvoteinfo()
    201. },
    202. //分享
    203. onShareAppMessage: function (res) {
    204. var that = this;
    205. //console.log(JSON.stringify(that.data.array))
    206. return {
    207. title: "快来和我一起投票吧",
    208. path: '/pages/index/index',
    209. imageUrl: "/pages/images/index.png"
    210. }
    211. },
    212. //下拉刷新
    213. onPullDownRefresh: function () {
    214. //调用刷新时将执行的方法
    215. this.onRefresh();
    216. }
    217. })

    json

    下拉刷新,当用户在页面顶部向下滑动时,可以触发下拉刷新操作,从而更新页面内容,在上述js中并需定义方法

    1. {
    2. "enablePullDownRefresh": true
    3. }

    投票结果wxml

    1. <view class="center">
    2. <image class="image_user" src="{{userImage}}"></image>
    3. <view class="text_user">{{userName}},你好</view>
    4. <view wx:if="{{isopenid}}"class="text_tip">你今天已经参加过本投票</view>
    5. <view wx:if="{{!isopenid}}" class="view_text">你的投票结果为:{{votevalue}}号选手:{{voteinfo[votevalue-1].name}}</view>
    6. <view class="view_text2">截止到{{date}}的投票结果为:</view>
    7. <view wx:for="{{voteinfo}}" wx:for-item="item" wx:key="index">
    8. <view class="view_text1">{{item.id}}号选手:{{item.name}},票数为:{{item.value}}票</view>
    9. <view class="index_class">
    10. <progress class="progress_box" percent="{{item.value/num*100}}" active stroke-width="20"
    11. border-radius="50"/>
    12. </view>
    13. </view>
    14. </view>

    wxss

    1. .view_text2{
    2. font-weight: 300;
    3. font-size:small;
    4. margin-bottom:30px;
    5. }
    6. .view_text{
    7. height: 100rpx;
    8. font-weight: 600;
    9. font-size: large;
    10. }
    11. /*首页排版*/
    12. .index_class {
    13. display: flex;
    14. }
    15. /*进度条排版*/
    16. .progress_box{
    17. width: 500rpx;
    18. margin-bottom:50px;
    19. }
    20. .center{
    21. display: flex;
    22. flex-direction: column;
    23. align-items: center;
    24. justify-content: center;
    25. }
    26. .image_user{
    27. height: 100px;
    28. width: 100px;
    29. border-radius: 50px;
    30. margin-top:30px;
    31. margin-bottom:10px;
    32. }
    33. .text_user{
    34. font-weight: 600;
    35. font-size: large;
    36. margin-bottom:10px;
    37. }
    38. .text_tip{
    39. font-weight: 600;
    40. font-size: large;
    41. color: red;
    42. margin-bottom:10px;
    43. }

    js

    1. Page({
    2. data: {
    3. date: new Date().toLocaleString(),
    4. votevalue: '',
    5. voteinfo: [],
    6. userName: '',
    7. userImage: '',
    8. isopenid: true,
    9. num:0
    10. },
    11. onLoad: function (options) {
    12. //获取投票信息
    13. this.getvoteinfo()
    14. let userinfo = wx.getStorageSync('userinfo') //取用户的头像 名字
    15. this.setData({
    16. userName: userinfo.nickName,
    17. userImage: userinfo.avatarUrl
    18. })
    19. let isopenid = wx.getStorageSync('isopenid') //判断用户是否已经进行过投票
    20. this.setData({
    21. isopenid: isopenid
    22. })
    23. console.log(this.data.isopenid)
    24. var that = this
    25. var votevalue = wx.getStorageSync('votevalue') //取用户的投票的对象
    26. this.setData({
    27. votevalue: votevalue
    28. })
    29. console.log(votevalue)
    30. },
    31. onShareAppMessage: function (res) {
    32. var that = this;
    33. //console.log(JSON.stringify(that.data.array))
    34. return {
    35. title: "快来和我一起投票吧",
    36. path: '/pages/index/index',
    37. imageUrl: "/pages/images/index.png"
    38. }
    39. },
    40. getvoteinfo: function () {
    41. console.log("我是获取投票图片")
    42. var that = this
    43. wx.request({
    44. url: 'http://localhost:8080/vote/voteinfo',
    45. /*method: 'get',
    46. header: {
    47. 'content-type': 'application/json'
    48. },*/
    49. success: function (res) {
    50. //console.log(res);
    51. that.setData({
    52. voteinfo: res.data
    53. })
    54. var num = 0
    55. var i = 0
    56. console.log(that.data.voteinfo);
    57. for(i = 0;i<that.data.voteinfo.length;i++){
    58. num = num + that.data.voteinfo[i].value
    59. }
    60. that.setData({
    61. num: num
    62. })
    63. console.log(that.data.num);
    64. },
    65. fail: function (res) {
    66. wx.showToast({
    67. title: '网络连接失败!',
    68. icon: 'error'
    69. })
    70. console.log("失败");
    71. }
    72. })
    73. }
    74. })

    效果演示

    当我们登录不同账号时都将有唯一标识,进行判断是否可以参与投票,这里也是注册了两个账号测试

    一开始需要进行登录之后通过openid拿到个人用户信息去判断该用户是否参与投票

    登录之后可以直接投票并每天只能参与一次投票

  • 相关阅读:
    Oracle客户端工具安装(PL/SQL Developer 和 instantclient)小记
    【优化算法】新型多目标热交换MOTEO优化算法(Matlab代码实现)
    ES&elasticsearch-header菜鸟教程06--模糊查询
    OLED透明拼接屏在乌海湖旅游区的应用探究
    vue elementui 组合式 api 对于容器的滑动条的位置的获取与设置。切换页面可以保持原来的容器里的滑动条位置不变
    实验:使用apache + yum实现自制yum仓库
    XSS 安全漏洞介绍及修复方案
    哈希----位图
    JS数组对象去重
    为什么Android 手机这么慢?如何提高 Android 手机的运行速度
  • 原文地址:https://blog.csdn.net/weixin_74268571/article/details/134025732