[WeChat Mini Program] Implement voting function (source code attached)

1. Introduction to Vant Weapp

  1.         Vant Weapp is a component library based on WeChat mini programs. It provides rich UI components and interactive functions, which can help developers quickly build modern mini program applications. The design concept of Vant Weapp focuses on simplicity, ease of use and efficiency, while providing flexible customization options to meet the different needs of developers.
  2.         Vant Weapp contains a number of commonly used components, such as buttons, navigation bars, labels, lists, cards, forms, etc. These components are carefully designed and optimized to help developers quickly build small apps with good interactive effects and user experience. program page. In addition, Vant Weapp also provides commonly used functional components, such as loading prompts, pop-up boxes, pull-down refresh, pull-up loading, etc., to facilitate developers to implement various commonly used interactive functions.
  3.         Vant Weapp adopts a modular design idea. Each component is independent and will not affect other parts of the page. This allows for more flexible use and maintenance of the component library. At the same time, Vant Weapp also provides detailed documentation and sample code to facilitate developers to learn and use.
  4.         Vant Weapp is a powerful and easy-to-use WeChat mini program component library that can help developers quickly build modern mini program applications with good user experience. Vant Weapp - lightweight, reliable small program UI component library (youzan.github.io) icon-default.png?t=N7T8https://youzan.github.io/vant-weapp/#/dialog

2. Backend

1. Entity

Write meeting entities and voting entities

conference entity

package com.zking.ssm.model;

import java.util.Date;

public class Info {
    private Long id;

    private String title;

    private String content;

    private String canyuze;

    private String liexize;

    private String zhuchiren;

    private String location;

    private Date starttime;

    private Date endtime;

    private String fujian;

    private Integer state;

    private String auditperson;

    private Date audittime;

    private String seatpic;

    private String remark;

    public Info(Long id, String title, String content, String canyuze, String liexize, String zhuchiren, String location, Date starttime, Date endtime, String fujian, Integer state, String auditperson, Date audittime, String seatpic, String remark) {
        this.id = id;
        this.title = title;
        this.content = content;
        this.canyuze = canyuze;
        this.liexize = liexize;
        this.zhuchiren = zhuchiren;
        this.location = location;
        this.starttime = starttime;
        this.endtime = endtime;
        this.fujian = fujian;
        this.state = state;
        this.auditperson = auditperson;
        this.audittime = audittime;
        this.seatpic = seatpic;
        this.remark = remark;
    }

    public Info() {
        super();
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getCanyuze() {
        return canyuze;
    }

    public void setCanyuze(String canyuze) {
        this.canyuze = canyuze;
    }

    public String getLiexize() {
        return liexize;
    }

    public void setLiexize(String liexize) {
        this.liexize = liexize;
    }

    public String getZhuchiren() {
        return zhuchiren;
    }

    public void setZhuchiren(String zhuchiren) {
        this.zhuchiren = zhuchiren;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public Date getStarttime() {
        return starttime;
    }

    public void setStarttime(Date starttime) {
        this.starttime = starttime;
    }

    public Date getEndtime() {
        return endtime;
    }

    public void setEndtime(Date endtime) {
        this.endtime = endtime;
    }

    public String getFujian() {
        return fujian;
    }

    public void setFujian(String fujian) {
        this.fujian = fujian;
    }

    public Integer getState() {
        return state;
    }

    public void setState(Integer state) {
        this.state = state;
    }

    public String getAuditperson() {
        return auditperson;
    }

    public void setAuditperson(String auditperson) {
        this.auditperson = auditperson;
    }

    public Date getAudittime() {
        return audittime;
    }

    public void setAudittime(Date audittime) {
        this.audittime = audittime;
    }

    public String getSeatpic() {
        return seatpic;
    }

    public void setSeatpic(String seatpic) {
        this.seatpic = seatpic;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }
}

voting entity

package com.zking.ssm.model;

public class Option {
    private Long id;

    private Long meetingId;

    private String optionValue;

    private String optionText;

    public Option(Long id, Long meetingId, String optionValue, String optionText) {
        this.id = id;
        this.meetingId = meetingId;
        this.optionValue = optionValue;
        this.optionText = optionText;
    }

    public Option() {
        super();
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getmeetingId() {
        return meetingId;
    }

    public void setmeetingId(Long meetingId) {
        this.meetingId = meetingId;
    }

    public String getoptionValue() {
        return optionValue;
    }

    public void setoptionValue(String optionValue) {
        this.optionValue = optionValue;
    }

    public String getoptionText() {
        return optionText;
    }

    public void setoptionText(String optionText) {
        this.optionText = optionText;
    }
}

2、xmlsql

Used to access database data for data access, one for accessing meeting data and one for accessing voting data.

<select id="voteList" resultMap="BaseResultMap" >
    select
    <include refid="Base_Column_List" />
    from t_oa_meeting_info
    where 1=1
    <if test="state!=null">
      and state=#{state}
    </if>
    <if test="title!=null">
      and title like concat('%',#{title},'%')
    </if>
  </select>

<insert id="insertSelective" parameterType="com.zking.ssm.model.Option" >
    insert into t_oa_meeting_option
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        id,
      </if>
      <if test="meetingId != null" >
        meetingId,
      </if>
      <if test="optionValue != null" >
        optionValue,
      </if>
      <if test="optionText != null" >
        optionText
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        #{id,jdbcType=BIGINT},
      </if>
      <if test="meetingId != null" >
        #{meetingId,jdbcType=BIGINT},
      </if>
      <if test="optionValue != null" >
        #{optionValue,jdbcType=VARCHAR},
      </if>
      <if test="optionText != null" >
        #{optionText,jdbcType=VARCHAR}
      </if>
    </trim>
  </insert>

3. Implement the interface

Write methods to call sql commands in xml to better operate data in the database

Write interface methods

Meeting

package com.zking.ssm.mapper;

import com.zking.ssm.model.Info;

import java.util.List;

public interface InfoMapper {
    int deleteByPrimaryKey(Long id);

    int insert(Info record);

    int insertSelective(Info record);

    Info selectByPrimaryKey(Long id);

    int updateByPrimaryKeySelective(Info record);

    int updateByPrimaryKey(Info record);

    List<Info> list(Info info);

    List<Info> voteList(Info info);
}

vote

package com.zking.ssm.mapper;

import com.zking.ssm.model.Option;

public interface OptionMapper {
    int deleteByPrimaryKey(String id);

    int insert(Option record);

    int insertSelective(Option record);

    Option selectByPrimaryKey(String id);

    int updateByPrimaryKeySelective(Option record);

    int updateByPrimaryKey(Option record);
}

implement interface

Implementing the meeting interface and voting interface requires data interaction.

Meeting

package com.zking.ssm.service.impl;

import com.zking.ssm.mapper.InfoMapper;
import com.zking.ssm.mapper.WxUserMapper;
import com.zking.ssm.model.Info;
import com.zking.ssm.service.InfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @软件包名 com.zking.ssm.service.impl
 * @用户 tgq
 * @create 2023-10-24 上午11:24
 * @注释说明:
 */
@Service
public class InfoServiceImpl implements InfoService {
    @Autowired
    private InfoMapper infoMapper;

    @Override
    public int updateByPrimaryKeySelective(Info record) {
        return infoMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public List<Info> voteList(Info info) {
        return infoMapper.voteList(info);
    }
}

vote

package com.zking.ssm.service.impl;

import com.zking.ssm.mapper.OptionMapper;
import com.zking.ssm.model.Option;
import com.zking.ssm.service.OptionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @软件包名 com.zking.ssm.service.impl
 * @用户 tgq
 * @create 2023-10-24 下午9:57
 * @注释说明:
 */
@Service
public class OptionServiceImpl implements OptionService {
    @Autowired
    private OptionMapper om;

    @Override
    public int insertSelective(Option record) {
        return om.insertSelective(record);
    }
}

4. Write Controller

The Controller class interacts with data between a front-end and a back-end.

Meeting

package com.zking.ssm.wxcontroller;

import com.zking.ssm.mapper.InfoMapper;
import com.zking.ssm.model.Info;
import com.zking.ssm.util.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 */
@SuppressWarnings("all")
@RestController
@RequestMapping("/wx/info")
public class WxInfoController {
    @Autowired
    private InfoMapper infoMapper;
    @RequestMapping("/list")
    public Object list (Info info){
        List<Info> list = infoMapper.list(info);
        Map<Object, Object> data = new HashMap<Object, Object>();
        data.put("infoList",list);
        return ResponseUtil.ok(data);
    }

    @RequestMapping("/votelist")
    public Object voteList (Info info){
        List<Info> list = infoMapper.voteList(info);
        Map<Object, Object> data = new HashMap<Object, Object>();
        data.put("voteList",list);
        return ResponseUtil.ok(data);
    }

    @RequestMapping("/update")
    public Object update (Info info){
        int i = infoMapper.updateByPrimaryKeySelective(info);
        return ResponseUtil.ok(i);
    }
}

vote

package com.zking.ssm.wxcontroller;

import com.zking.ssm.mapper.InfoMapper;
import com.zking.ssm.mapper.OptionMapper;
import com.zking.ssm.model.Info;
import com.zking.ssm.model.Option;
import com.zking.ssm.util.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Autho donkee
 * @Since 2022/7/29
 */
@SuppressWarnings("all")
@RestController
@RequestMapping("/wx/option")
public class WxOptionController {
    @Autowired
    private OptionMapper optionMapper;

    @RequestMapping("/insert")
    public Object insertSelective(Option option) {
        int i = optionMapper.insertSelective(option);
        return ResponseUtil.ok(i);
    }

}

3. Front-end

There are some technologies in it that I won’t explain in detail here. You can check out my column WeChat Mini Program_Blog of People Who Can’t Discipline-CSDN Blog .

A small program plug- in Dialog pop-up box - Vant Weapp (youzan.github.io) is used here . There are many plug-ins used in Vant Weapp, which can be used more conveniently. For main references, you need to check the official documents yourself.

1. Page layout

Write the page layout of the main page, which uses a pop-up component of an external plug-in.

It utilizes the use of wxs .

wxml

<tabs tabList="{
   
   {tabs}}" bindtabsItemChange="tabsItemChange">
    <view class="search-container">
        <input class="search-input" bindblur="ontitle" bindblur="onBlur" placeholder="会议标题" />
        <!-- <input class="search-input" bindinput="searchInputTwo" placeholder="投票标题" /> -->
        <button type="primary" plain="true" size="mini" bindtap="likelist">搜索</button>
    </view>
</tabs>
<view>
    <view class="list" data-id="">
        <view class="list-img al-center">
            <image class="video-img" mode="scaleToFill" src=""></image>
        </view>
        <view class="list-detail">
            <view class="list-title"><text><text style="margin-right: 13rpx;"></text></text></view>
            <view class="list-title"><text></text></view>
            <view class="list-tag">
                <view class="state al-center"></view>
                <view class="join al-center"><text class="list-count"></text></view>
            </view>
            <view class="list-info"><text style="font-weight: bold;"></text><text></text> <text style="float: right;"></text> </view>
            <view>
                <button class="btn"></button>
            </view>
        </view>
    </view>
    <wxs src="/utils/capture.wxs" module="tools" />
    <block wx:for-items="{
   
   {lists}}" wx:for-item="item" wx:key="item.id">
        <view class="list" data-id="{
   
   {item.id}}">
            <view class="list-img al-center">
                <image class="video-img" mode="scaleToFill" src="/static/persons/7.jpg"></image>
            </view>
            <view class="list-detail">
                <view class="list-title"><text><text style="margin-right: 13rpx;"> 发 起 人</text> : {
   
   {item.zhuchiren}}</text></view>
                <view class="list-title"><text>会议名称 : {
   
   {item.title}}</text></view>
                <!-- <view class="list-title"><text>投票标题 : [ {
   
   {item.vote}} ]</text></view> -->
                <view class="list-tag">
                    <view class="state al-center">{
   
   {tools.getState(item.state)}}</view>
                    <view class="join al-center"><text class="list-count">{
   
   {tools.getNumber(item.canyuze,item.liexize,item.zhuzhiren)}}</text>人参与会议</view>
                </view>
                <view class="list-info"><text style="font-weight: bold;">地址:</text><text>{
   
   {item.location}}</text> <text style="float: right;">开始时间:{
   
   {tools.formatDate(item.starttime,'YY-MM-DD hh-mm-ss')}}结束时间:{
   
   {tools.formatDate(item.endTime,'YY-MM-DD hh-mm-ss')}}</text> </view>
                <view data-id="{
   
   {item.id}}" bindtap="{
   
   {data.state == 5 ? 'show1' : 'showPopup'}}">
                    <button class="btn">{
   
   {data.state == 5? '开启投票' : '参与投票'}}</button>
                    <!-- <button wx:if="{
   
   {data.state == 5}}"  class="btn" bindtap="show1">开启投票</button>
          <button wx:else="{
   
   {data.state == 6}}" class="btn" bindtap="showPopup">参与投票</button> -->
                </view>
            </view>
        </view>

    </block>
    <view class="section bottom-line">
        <text>到底啦</text>
    </view>
</view>


<!-- 开启投票 弹窗-->
<van-dialog use-slot title="请添加投票选项" show="{
   
   { show1 }}" show-cancel-button bind:close="onClose1" bind:confirm="getVoteState">
    <view class="container">
        <view class="input-box">
            <input placeholder="请输入投票选项" bindblur="onOptionValue" bindinput="bindInput"></input>
        </view>
        <view class="checkbox-group">
            <view class="checkbox-item" data-id="1" bindtap="toggleCheckbox">同意</view>
            <view class="checkbox-item" data-id="2" bindtap="toggleCheckbox">不同意</view>
            <view class="checkbox-item" data-id="3" bindtap="toggleCheckbox">保留意见</view>
            <view class="checkbox-item" data-id="4" bindtap="toggleCheckbox">弃票</view>
        </view>
    </view>
</van-dialog>
<!-- 选择投票选项 弹窗 -->
<van-dialog use-slot title="选择投票" show="{
   
   { show }}" show-cancel-button bind:close="onClose" bind:confirm="getVoteOption">
    <view class="container">
        <view class="input-box">
            <!-- <input placeholder="请输入投票选项" bindinput="bindInput"></input> -->
        </view>
        <view class="checkbox-group">
            <view class="checkbox-item {
   
   { checkbox1 ? 'active' : '' }}" data-id="1" bindtap="toggleCheckbox">同意</view>
            <view class="checkbox-item {
   
   { checkbox2 ? 'active' : '' }}" data-id="2" bindtap="toggleCheckbox">不同意</view>
            <view class="checkbox-item {
   
   { checkbox3 ? 'active' : '' }}" data-id="3" bindtap="toggleCheckbox">保留意见</view>
            <view class="checkbox-item {
   
   { checkbox4 ? 'active' : '' }}" data-id="4" bindtap="toggleCheckbox">弃票</view>
        </view>
    </view>
</van-dialog>

2. Function realization

The functions and methods of the above pages are called, and the interaction of background data is called.

js

// pages/vote/list/list.js ../../config/api.js
const api = require('../../../config/api.js');
const util = require('../../../utils/util.js');
const app = getApp();
Page({
  /**
   * 页面的初始数据
   */
  data: {
    show: false,
    show1: false,
    tabs: ['未开启投票', '已开启投票'],
    lists: [],
    inputValue: '',//输入框内容
    data: {
      id: 0,
      state: 5,
      title: ''
    },
    option: {
      meetingId: 0,
      optionValue: ''
    },
    checkbox1: false,
    checkbox2: false,
    checkbox3: false,
    checkbox4: false
  },
  onBlur: function (e) {//输入框获取事件
    this.setData({
      inputValue: e.detail.value
    });
  },
  onOptionValue: function (e) {//弹窗1输入框获取
    this.setData({
      option: { optionValue: e.detail.value }
    });
  },
  likelist() {//搜索事件
    // console.log(this.data.inputValue);
    this.data.data.title = this.data.inputValue
    this.InfoVote();
  },
  tabsItemChange(e) {//是否投票

    var tolists;
    if (e.detail.index == 0) {
      tolists = 5;
      this.data.data.state = 5
      // tolists = this.data.lists;
    } else if (e.detail.index == 1) {
      // tolists = this.data.lists;
      tolists = 6;
      this.data.data.state = 6
    }
    this.setData({
      data: {
        state: tolists
      }
    })
    console.log(e.detail, this.data.Profile, this.data.data, tolists);
    this.InfoVote();
  },
  InfoVote() {//初始化数据
    util.request(api.MettingInfoVote, this.data.data).then(res => {
      // console.log(res)
      this.setData({
        lists: res.data.voteList
      })
    }).catch(res => {
      console.log('服器没有开启,使用模拟数据!')
    })
  },
  toggleCheckbox: function (e) {
    var checkboxId = e.currentTarget.dataset.id;

    var data = {}; // 更新的状态数据

    // 遍历每个复选框的状态变量,根据点击的复选框的id确定是否选中
    Object.keys(this.data).forEach(key => {
      if (key.includes('checkbox') && key !== `checkbox${checkboxId}` && this.data[key]) {
        data[key] = false; // 将其他复选框的状态设为false
      }
    });

    // 切换当前复选框的选中状态
    data[`checkbox${checkboxId}`] = !this.data[`checkbox${checkboxId}`];

    this.setData(data);
  },
  // 1弹窗
  show1(e) {
    // console.log(e, e.currentTarget.dataset.id)
    this.setData({
      data: {
        id: e.currentTarget.dataset.id
      },
    })
    this.setData({
      show1: true
    })
    // console.log(e.currentTarget.dataset.id, this.data.data)
  },
  getVoteState(e) {//开启投票确认事件
    console.log(e, this.data.data, this.data.option.meetingId);

    var optiondata = {
      meetingId: this.data.data.id,
      optionValue: this.data.option.optionValue
    }
    // console.log(optiondata)
    util.request(api.MettingOptionInsert, optiondata).then(res => {//添加投票选项
      // console.log(api.MettingOptionInsert);
      if (res.errno == 0) {
        wx.showToast({
          title: '开启投票成功',
          icon: 'none',
          duration: 1500//持续的时间
        })
        util.request(api.MettingInfoupdate, { id: optiondata.meetingId, state: 6 }).then(r => {//更改会议状态
          // console.log(api.MettingInfoupdate);
          // this.InfoVote('');
          if (res.errno == 0) {
            this.data.data.state = 5
            this.InfoVote('');
          }
        }).catch(res => {
          console.log('服器没有开启,使用模拟数据!')
        })
      }

    }).catch(res => {
      console.log('服器没有开启,使用模拟数据!')
    })
    // console.log(123,i)


  },
  onClose1() {
    this.setData({ show1: false });
  },
  // 2弹窗
  showPopup(e) {
    this.setData({
      show: true,
      data: {
        id: e.currentTarget.dataset.id
      }
    })
  },
  getVoteOption(e) {//参与投票确认事件
    console.log(2, e.detail);
  },

  onClose() {
    this.setData({ show: false });
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    // this.data.Profile=true
    this.InfoVote('');
  }
})

3. Page beautification

The layout and beautification of the page, as well as the beautification of pop-up windows, and the layout of pop-up windows have been beautified for better operation.

wxss

/* pages/vote/list/list.wxss */

.search-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px;
    background-color: #ffffff;
    border: cornsilk;
}

.search-input {
    width: 45%;
    padding: 8px;
    border-radius: 20px;
    border: 1px solid rgb(255, 255, 255);
    font-size: 14px;
    transition: border-color 0.3s;
    border: cornsilk;
}

.search-input:focus {
    outline: none;
    border-color: #51a7f9;
}

.search-input::placeholder {
    color: #999;
}

.search-input::-webkit-input-placeholder {
    color: #999;
}

.search-input::-moz-placeholder {
    color: #999;
}

.search-input:-ms-input-placeholder {
    color: #999;
}
.list {
    display: flex;
    flex-direction: row;
    width: 100%;
    padding: 0 20rpx 0 0;
    background-color: seashell;
    border-bottom: 1px solid #cecece;
    margin-bottom: 5rpx;
    height: 350rpx;
}

.list-img {
    display: flex;
    margin: 10rpx 10rpx;
    width: 160rpx;
    height: 250rpx;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}

.list-img .video-img {
    width: 140rpx;
    height: 160rpx;
    border-radius: 6px;
}

.list-detail {
    margin: 10rpx 10rpx;
    display: flex;
    flex-direction: column;
    width: 600rpx;
    height: 300rpx;
}

.list-title text {
    font-size: 9pt;
    color: #333;
    font-weight: bold;
}

.list-detail {
    display: flex;
    height: 100rpx;
}

.list-tag {
    display: flex;
}

.state {
    font-size: 9pt;
    color: blue;
    width: 120rpx;
    height: 40rpx;
    border: 1px solid blue;
    border-radius: 2px;
    margin: 10rpx 0rpx;
    display: flex;
    justify-content: center;
    align-items: center;
}

.join {
    font-size: 11pt;
    color: #bbb;
    margin-left: 20rpx;
    display: flex;
    justify-content: center;
    align-items: center;
}

.list-count {
    margin-right: 10rpx;
    font-size: 11pt;
    color: red;
}

.list-info {
    font-size: 9pt;
    color: #bbb;
}

.btn {

    background-color: #3388ff;
    color: #fff;
    border-radius: 4rpx;
    font-size: 16rpx;
    padding: 10rpx 20rpx;
}

.bottom-line {
    display: flex;
    height: 60rpx;
    justify-content: center;
    align-items: center;
    background-color: #f3f3f3;
}

.bottom-line text {
    font-size: 9pt;
    color: #666;
}

/* 弹窗 */
.container {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

.input-box {
    margin-top: 20px;
}

.checkbox-group {
    display: flex;
    flex-direction: column;
    margin-top: 15px;
}

.checkbox-item {
    width: 100px;
    height: 40px;
    background-color: #eaf0f4;
    margin-bottom: 10px;
    display: flex;
    justify-content: center;
    align-items: center;
}
.container {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }
  
  .input-box {
    margin-top: 20px;
  }
  
  .checkbox-group {
    display: flex;
    flex-direction: column;
    margin-top: 15px;
  }
  
  .checkbox-item {
    width: 100px;
    height: 40px;
    background-color: #eaf0f4;
    margin-bottom: 10px;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1px solid #ccc;
  }
  
  .checkbox-item.active {
    background-color: #4285f4;
    color: white;
    border-color: #4285f4;
  }
  

4. Effect demonstration

The demonstration effect is long, please be patient and wait... .

Guess you like

Origin blog.csdn.net/weixin_74383330/article/details/134024992