【微信小程序】发布投票与用户投票完整讲解

news2024/11/18 7:27:39

目录

前言

       组件功能示例

一、数据库

二、后端接口定义

三、前端准备

3.1 定义连接接口

3.2 Vant Weapp UI 组件库

3.3 授权登录与相关工具

四、小程序编写

4.1 投票组件

WXML

WXSS

JSON

WXJS

效果展示讲解:

4.2  发布投票组件

WXML

WXSS

JSON

WXJS

效果展示讲解:


前言

        本次主要讲解的是在会议系统中完整投票功能,首先建立思维流程:

  1. 先必须要有会议数据,而会议要由发布、审核、待开等,到开启会议后才能进行发布投票功能。
  2. 发布的投票必须要用户进行登录才可投票
  3. 而用户能够查询所有投票以及已投票或结束的投票

总结非常简单,如果要我们去实现,这时候就有许多问题:

  • 需要编写复杂的sql和查询
  • 需要多样化的组件并实现数据交互
  • 需要分析流程与执行顺序

        如果这些都需要自己独立完成,很多东西还要自己去研究测试,不仅要走许多弯路还得花很多时间和心思。嗯...我就是这样过来的,这篇也是爆肝凌晨几点完成的。话不多说,现在就开始进入正题。

组件功能示例

一、数据库

投票功能是建立在会议和用户之上的,所以先介绍一下这两个表:

t_oa_meeting_info:

wx.user: 

主要关注会议状态(state字段)

 

1、存储发布的投票表:

2. 用户投票信息表:

sql预览:

#查询进行中的投票
select * from t_oa_meeting_option where meetingId = (select id from t_oa_meeting_info where state = 5)

#查询结束会议的投票
select * from t_oa_meeting_option where meetingId = (select id from t_oa_meeting_info where state = 6)

#查询票数
select count(*) from t_oa_meeting_vote where optionId = 2

#查询已投的的票
select * from t_oa_meeting_option where id = (select optionId from t_oa_meeting_vote where personId = 5)

 

二、后端接口定义

方法功能:注释 

WxInfoController :会议数据

package com.ycxw.ssm.wxcontroller;

import com.ycxw.ssm.mapper.InfoMapper;
import com.ycxw.ssm.model.Info;
import com.ycxw.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;

/**
 * @author 云村小威
 * @create 2023-10-26 22:28
 */
@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("/listState")
    public Object listState (Info info){
        info.setState(4);
        List<Info> list = infoMapper.list(info);
        Map<Object, Object> data = new HashMap<Object, Object>();
        data.put("listState",list);
        return ResponseUtil.ok(data);
    }

    //修改会议状态
    @RequestMapping("/state")
    public Object updateState (Info info){
        infoMapper.updateByPrimaryKeySelective(info);
        return ResponseUtil.ok();
    }
}

 

WXOptionController:投票数据

package com.ycxw.ssm.wxcontroller;

import com.ycxw.ssm.mapper.OptionMapper;
import com.ycxw.ssm.model.Option;
import com.ycxw.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;

/**
 * @author 云村小威
 * @create 2023-10-26 22:28
 */
@RestController
@RequestMapping("/wx/option")
public class WXOptionController {
    @Autowired
    private OptionMapper optionMapper; //正在投票信息

    //查询所有投票
    @RequestMapping("/list")
    public Object list() {
        List<Option> list = optionMapper.list();
        Map<Object, Object> data = new HashMap<Object, Object>();
        data.put("voteList", list);
        return ResponseUtil.ok(data);
    }

    /*发布投票*/
    @RequestMapping("/add")
    public Object save(Option option) {
        //发起投票
        optionMapper.insertSelective(option);
        return ResponseUtil.ok();
    }

    //查询所有结束的投票
    @RequestMapping("/over")
    public Object selectOverVote() {
        List<Option> list = optionMapper.selectOverVote();
        Map<Object, Object> data = new HashMap<Object, Object>();
        data.put("overList", list);
        return ResponseUtil.ok(data);
    }

    //查询所有已投票的信息
    @RequestMapping("/already")
    public Object selectByAlready(Long personId) {
        List<Option> list = optionMapper.selectByAlready(personId);
        Map<Object, Object> data = new HashMap<Object, Object>();
        data.put("alreadyList", list);
        return ResponseUtil.ok(data);
    }

    //模糊查询投票信息
    @RequestMapping("/search")
    public Object SearchVote(Option option) {
        List<Option> list = optionMapper.SearchVote(option);
        Map<Object, Object> data = new HashMap<Object, Object>();
        data.put("searchList", list);
        return ResponseUtil.ok(data);
    }
}

WXVoteController:用户投票数据

package com.ycxw.ssm.wxcontroller;

import com.ycxw.ssm.mapper.VoteMapper;
import com.ycxw.ssm.model.Vote;
import com.ycxw.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.Map;

/**
 * @author 云村小威
 * @create 2023-10-26 22:28
 */
@RestController
@RequestMapping("/wx/vote")
public class WXVoteController {
    @Autowired
    private VoteMapper voteMapper;

    //查询选项正在投票的会议的票数
    @RequestMapping("/ticket")
    public Object selectByOptionId(Long optionId) {
        Long i = voteMapper.selectByOptionId(optionId);
        Map<Object, Object> data = new HashMap<Object, Object>();
        data.put("ticket", i);
        return ResponseUtil.ok(data);
    }

    //投票
    @RequestMapping("/add")
    public Object insertSelective(Vote record) {
        int i = voteMapper.insertSelective(record);
        Map<Object, Object> data = new HashMap<Object, Object>();
        data.put("ok", i);
        return ResponseUtil.ok(data);
    }

}

 

三、前端准备

3.1 定义连接接口

这里只列出本次需要实现功能的接口 

// 以下是业务服务器API地址
// 本机开发API地址
var WxApiRoot = 'http://localhost:8080/oapro/wx/';

module.exports = {
  AuthLoginByWeixin: WxApiRoot + 'auth/login_by_weixin', //微信登录
  AuthLogout: WxApiRoot + 'auth/logout', //账号登出
  MettingInfoState: WxApiRoot + 'info/listState', //所有进行中的会议
  VoteInfos: WxApiRoot + 'option/list', //所有发布投票的会议
  SearchVote: WxApiRoot + 'option/search', //搜索投票信息
  UpdateState: WxApiRoot + 'info/state', //修改会议状态
  MeetingAddVote: WxApiRoot + 'option/add', //发布投票
  OverVote: WxApiRoot + 'option/over',//所有结束的会议
  AlreadyVote: WxApiRoot + 'option/already',//所有已投的会议
  SelectTicket: WxApiRoot + 'vote/ticket',//查询票数
  AddTicket: WxApiRoot + 'vote/add',//投票
};

3.2 Vant Weapp UI 组件库

本次主要使用 Vant Weapp UI 组件搭建的,学习这个很简单,根据文档安装操作即可:进入 Vant Weapp UI 文档

3.3 授权登录与相关工具

进入 【微信小程序】授权登录流程解析

主要为了了解微信授权登录的流程和原理,方便更好理解后面的知识。

四、小程序编写

4.1 投票组件

WXML

        这里是利用 vant weapp 组件布局的,里面包括搜索框、tab列表、弹窗、以及一个定位的图片按钮,用于进入发布投票页面。 

<!--pages/vote/list/list.wxml-->
<view style="height: 15rpx;"></view>
<!-- 搜索框 -->
<van-search value="{{ search }}" placeholder="请输入搜索关键词" show-action bind:change="Search" bind:search="onSearch" bind:cancel="onCancel" />
<view style="height: 20rpx;"></view>
<!-- tabs列表 -->
<van-tabs type="card" color="#1989fa">
  <!-- VoteALL -->
  <van-tab title="进行中">
    <van-divider dashed contentPosition="center" customStyle="color: #1989fa; border-color: #1989fa;">
      投一票
    </van-divider>
    <view class="oaFlex">
      <block wx:for-items="{{VoteAll}}" wx:for-item="item" wx:key="item.id">
        <view class="list" data-id="{{item.id}}" bindtap="open_vote" data-text="{{item.title}}">
          <view class="list-detail">
            <view class="list-title"><text>{{item.title}}</text></view>
            <!-- <view class="list-tag">
              <view class="join al-center"><text class="list-num">0</text> 人已投</view>
            </view> -->
          </view>
          <view class="list-img al-center">
            <image class="video-img" mode="scaleToFill" src="{{item.picture}}"></image>
          </view>
        </view>
      </block>
    </view>
  </van-tab>
  <!-- publishVote  -->
  <van-tab title="已结束">
    <view style="height: 50rpx;"></view>
    <view class="oaFlex">
      <block wx:for-items="{{OverVote}}" wx:for-item="item" wx:key="item.id">
        <view class="list" data-id="{{item.id}}" bindtap="open_vote" data-text="{{item.title}}">
          <view class="list-detail">
            <view class="list-title"><text>{{item.title}}</text></view>
            <!-- <view class="list-tag">
              <view class="join al-center"><text class="list-num">0</text> 人已投</view>
            </view> -->
          </view>
          <view class="list-img al-center">
            <image class="video-img" mode="scaleToFill" src="{{item.picture}}"></image>
          </view>
        </view>
      </block>
    </view>
  </van-tab>
  <!-- AlreadyVote  -->
  <van-tab title="已投票">
    <view style="height: 50rpx;"></view>
    <view class="oaFlex">
      <block wx:for-items="{{AlreadyVote}}" wx:for-item="item" wx:key="item.id">
        <view class="list" data-id="{{item.id}}" bindtap="open_vote" data-text="{{item.title}}">
          <view class="list-detail">
            <view class="list-title"><text>{{item.title}}</text></view>
            <!-- <view class="list-tag">
              <view class="join al-center"><text class="list-num">0</text> 人已投</view>
            </view> -->
          </view>
          <view class="list-img al-center">
            <image class="video-img" mode="scaleToFill" src="{{item.picture}}"></image>
          </view>
        </view>
      </block>
    </view>
  </van-tab>
</van-tabs>
<!-- 投票弹出框 -->
<van-dialog use-slot title="投一票" show="{{ showVote }}" show-cancel-button confirm-button-open-type="getUserInfo" bind:close="onClose" bind:getuserinfo="getUserInfo">
  <view style="height: 25rpx;"></view>
  <van-notice-bar scrollable="{{true}}" color="#1989fa" background="#ecf9ff" left-icon="volume-o" text="{{text}}" />
  <view style="height: 15rpx;"></view>
  <van-cell-group inset>
    <van-cell title="当前票数">
      <van-stepper disable-input="{{true}}" value="{{ ticket }}" bind:change="onChange" max="{{ticket+1}}" min="{{ticket}}" />
    </van-cell>
  </van-cell-group>
</van-dialog>
<!-- 发布投票图片按钮 -->
<view style="position:fixed; bottom:10px;width: 150rpx;right: 10px;">
  <van-image bindtap="open_publishVote" round width="5rem" height="5rem" src="/static/images/add.png" />
</view>

WXSS

/* pages/vote/list/list.wxss */
.oaFlex {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.list {
  width: 360px;
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: rgb(228, 240, 253);
  border-bottom: 2px solid #d9dbe2;
  margin-bottom: 25px;
}

.video-img {
  width: 360px;
  height: 160px;
}

.list-detail {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.list-title {
  margin-top: 10px;
  height: 30px;
  font-size: 13pt;
  color: #333;
  font-weight: bold;
}

.list-info {
  color: #aaa;
}

.list-num {
  color: red;
  /* font-weight: 700; */
}

.join {
  padding: 0px 0px 0px 10px;
  color: #aaa;
}

.state {
  margin: 0px 6px 0px 6px;
  border: 1px solid #4083ff;
  color: #4083ff;
  padding: 3px 5px 3px 5px;
}

.list-tag {
  padding: 10px 0px 10px 0px;
  display: flex;
  align-items: center;
}

JSON

{
  "navigationBarTitleText": "投票",
  "usingComponents": {
    "van-row": "@vant/weapp/row/index",
    "van-col": "@vant/weapp/col/index",
    "van-search": "@vant/weapp/search/index",
    "van-switch": "@vant/weapp/switch/index",
    "van-dialog": "@vant/weapp/dialog/index",
    "van-tab": "@vant/weapp/tab/index",
    "van-tabs": "@vant/weapp/tabs/index",
    "van-divider": "@vant/weapp/divider/index",
    "van-image": "@vant/weapp/image/index",
    "van-stepper": "@vant/weapp/stepper/index",
    "van-cell": "@vant/weapp/cell/index",
    "van-cell-group": "@vant/weapp/cell-group/index",
    "van-notice-bar": "@vant/weapp/notice-bar/index"
  }
}

WXJS

// pages/vote/list.js
var app = getApp();
const api = require('../../../config/api');
const util = require('../../../utils/util.js');

Page({
  /**
   * 页面的初始数据
   */
  data: {
    VoteAll: [], //进行中的投票
    OverVote: [], //已结束
    AlreadyVote: [], //已投票
    checked: false, //禁止投票开关
    showVote: false, //投票弹出框开关
    text: '', //投票标题
    ticket: 0, //票数
    ticket2: 0, //投票后的票数
    search: '', //搜索值
    optionId: 0, //投票id
    personId: 0, //用户id
  },
  /*监听搜索输入框的值*/
  Search(event) {
    this.setData({
      search: event.detail
    })
  },
  /*输入框搜索商品*/
  onSearch() {
    var that = this;
    //调用查询接口
    util.request(api.SearchVote, {
      title: that.data.search
    }).then(res => {
      //如果搜索字段为空,就刷新界面
      if (that.data.search == '') {
        this.onShow();
      } else {
        this.setData({
          VoteAll: res.data.searchList
        });
      }
    }).catch(res => {
      console.log('服器没有开启,使用模拟数据!')
    })
  },

  //获取全部投票信息
  loadVoteInfos() {
    util.request(api.VoteInfos).then(res => {
      this.setData({
        VoteAll: res.data.voteList
      });
    }).catch(res => {
      console.log('服器没有开启,使用模拟数据!')
    })
  },
  //获取全部已结束投票信息
  loadOverVote() {
    util.request(api.OverVote).then(res => {
      this.setData({
        OverVote: res.data.overList
      });
    }).catch(res => {
      console.log('服器没有开启,使用模拟数据!')
    })
  },
  //获取全部已投票的信息
  loadAlreadyVote() {
    util.request(api.AlreadyVote, {
      personId: this.data.personId
    }).then(res => {
      this.setData({
        AlreadyVote: res.data.alreadyList
      });
    }).catch(res => {
      console.log('服器没有开启,使用模拟数据!')
    })
  },

  //发布投票点击事件
  open_publishVote: function () {
    wx.navigateTo({
      url: '/pages/meeting/add/add',
    })
  },

  //投票弹窗点击事件
  open_vote(event) {
    var itemId = event.currentTarget.dataset.id; //投票id
    var itemText = event.currentTarget.dataset.text; //投票主题
    util.request(api.SelectTicket, {
      optionId: itemId
    }).then(res => {
      this.setData({
        text: itemText,
        showVote: true,
        ticket: res.data.ticket,
        optionId: itemId
      });
    }).catch(res => {
      console.log('服器没有开启,使用模拟数据!')
    })

  },
  //投票弹窗关闭事件
  onClose() {
    this.setData({
      showVote: false
    });
  },
  //票数绑定
  onChange(event) {
    // 用户投的票
    this.setData({
      ticket2: event.detail
    });
    console.log(this.data.ticket); //原票数
    console.log(this.data.ticket2); //新票数
  },

  // 投票确认事件
  getUserInfo(event) {
    let ticket = this.data.ticket2;
    let userInfo = wx.getStorageSync('userInfo');;
    // 构造发布投票请求参数
    const putVote = {
      optionId: this.data.optionId,
      personId: userInfo.userId
    };
    //对比如果没增长就代表没投票,并且为登录状态
    if (this.data.ticket == ticket || userInfo.userId == 0) {
      wx.showToast({
        title: '暂未投票哦',
        icon: 'error',
        duration: 2000,
        mask: true //显示透明蒙层,防止触摸穿透
      });
    } else {
      util.request(api.AddTicket, putVote).then(res => {
        console.log(res);
        wx.showToast({
          title: '投票成功',
          icon: 'sucess',
          duration: 2000,
          mask: true //显示透明蒙层,防止触摸穿透
        });
        this.onShow();
      }).catch(res => {
        console.log('服器没有开启,使用模拟数据!')
      })
    }
  },


  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {

  },


  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {
        // 从本地缓冲拿取用户id
        let userInfo = wx.getStorageSync('userInfo');
        this.setData({
          personId: userInfo.userId
        });
    this.loadVoteInfos();
    this.loadOverVote();
    this.loadAlreadyVote();
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

 

效果展示讲解:

1、查询当前登录的用户id,获取已投票和未投票信息,分别存储不同数组进行遍历显示

2、通过数据投票主题关键字进行模糊查询

3、点击投票列表进入弹窗,显示投票主题和该票数,利用进步器选择加减投票

4、必须加一票和登录后才能投票成功,并刷新界面

🌟更多解释请研究js代码

 

4.2  发布投票组件

WXML

这里用到了图片上传和下拉会议列表

<!--pages/meeting/add/add.wxml-->
<view class="img">
  <image class="upload_img" src="{{imageUrl=='' ? '/static/images/uploadimg.png':imageUrl }}" mode="aspectFit" bindtap="handleUploadImage"></image>
  <input hidden="true" type="text" name="images" value="{{imageUrl}}" />
</view>
<view style="height: 10px;"></view>
<van-cell-group>
  <van-field model:value="{{ title }}" placeholder="请输入投票主题" label="主题" border="{{ true }}" />
</van-cell-group>
<view style="height: 10px;"></view>
<!-- 会议列表 -->
<van-dropdown-menu active-color="#1989fa">
  <van-dropdown-item value="{{ value }}" options="{{ option }}" bind:change="onDropdownMenuChange" />
</van-dropdown-menu>
<view style="height: 300px;"></view>
<van-row>
  <van-col offset="8" span="8">
    <van-button plain hairline icon="add-square" type="info" style="margin-top: 25px;" bind:tap="handleVote" size="large">发起投票</van-button>
  </van-col>
</van-row>

 

WXSS

/* pages/meeting/add/add.wxss */
.img {
  margin-top: 25px;
  height: 480rpx;
}

.upload_img {
  height: 450rpx;
  width: 735rpx;
  box-shadow: 5px 8px rgb(218, 221, 221);
  border-radius: 5rpx;
}

JSON

{
  "navigationBarTitleText": "发起投票",
  "usingComponents": {
    "van-field": "@vant/weapp/field/index",
    "van-uploader": "@vant/weapp/uploader/index",
    "van-row": "@vant/weapp/row/index",
    "van-col": "@vant/weapp/col/index",
    "van-calendar": "@vant/weapp/calendar/index",
    "van-cell": "@vant/weapp/cell/index",
    "van-cell-group": "@vant/weapp/cell-group/index",
    "van-button": "@vant/weapp/button/index",
    "van-picker": "@vant/weapp/picker/index",
    "van-dropdown-menu": "@vant/weapp/dropdown-menu/index",
    "van-dropdown-item": "@vant/weapp/dropdown-item/index"
  }
}

WXJS

// pages/meeting/add/add.js
var app = getApp();
const api = require('../../../config/api');
const util = require('../../../utils/util.js');

Page({
  /**
   * 页面的初始数据
   */
  data: {
    imageUrl: '', //发布投票图片
    option: [{
      text: '选择会议',
      value: 0
    }], //会议选项(该是默认值)
    value: 0, //会议选项id
    optiontext: null, //会议选项标题
    title: '', //投票主题
  },

  //图片选择器
  handleUploadImage() {
    wx.chooseImage({
      count: 1,
      success: (res) => {
        const imagePath = res.tempFilePaths[0];
        // 处理选择的图片路径
        console.log('选择的图片路径:', imagePath);
        this.setData({
          imageUrl: imagePath // 更新图片路径,触发重新渲染
        });
      }
    });
  },

  //获取所有正在进行的会议
  loadMeetingInfos() {
    util.request(api.MettingInfoState).then(res => {
      //定义空数组存储数据库传来的json数据值
      let options = [];
      for (var index in res.data.listState) {
        //获取需要的字段值
        let id = res.data.listState[index].id;
        let title = res.data.listState[index].title;
        //给每个值设置对应的字段存储到数组
        options.push({
          text: title,
          value: id
        });
      }
      this.setData({
        //在option数组的内容后添加新的内容
        option: this.data.option.concat(options)
      });
    }).catch(res => {
      console.log('服器没有开启,使用模拟数据!')
    })
  },

  // 监听菜单选择事件
  onDropdownMenuChange(event) {
    //获取选择的选项值
    let value = event.detail;
    //获取option数组的value与选择的value值相同的数据
    const selectedOption = this.data.option.find(option => option.value === value);
    this.setData({
      //将数据赋值到变量中进行存储
      optiontext: selectedOption.text,
      value: selectedOption.value
    });
  },

  //发布投票
  handleVote() {
    // 获取页面中的数据
    const picture = this.data.imageUrl;
    const meetingId = this.data.value;
    const title = this.data.title;

    //判断只要有内容为空就不进行发布
    if (picture == '' || meetingId == 0 || title == '') {
      wx.showToast({
        title: '请完善投票内容',
        icon: 'error',
        duration: 2000,
        mask: true //显示透明蒙层,防止触摸穿透
      });
      //阻止运行后面的代码
      return
    }

    // 构造发布投票请求参数
    const requestData = {
      meetingid: meetingId,
      title: title,
      picture: picture
    };

    // 构造修改会议状态请求参数
    const updateData = {
        id: meetingId,
        state:5
    };

    // 发起网络请求,将数据传递给后端
    util.request(api.MeetingAddVote, requestData).then(res => {
      //修改会议状态为开启投票接口
      util.request(api.UpdateState,updateData).then(res => {console.log(res)});
      //获取页面栈返回上一个界面
      const pages = getCurrentPages() //获取页面列表
      const perpage = pages[pages.length - 1] //当前页   
      //刷新页面
      wx.navigateBack({
        delta: 1,
        //返回成功调用函数
        success: function () {
          wx.showToast({
            title: '发布成功',
            icon: 'success',
            duration: 2000,
            mask: true //显示透明蒙层,防止触摸穿透
          });
        }
      })
      //加载界面(用于刷新)
      perpage.onLoad()

      // 可以在这里进行页面跳转或其他操作
    }).catch(res => {
      // 请求失败的处理逻辑
      console.error('数据保存失败', err);
    })
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    this.loadMeetingInfos();
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

效果展示讲解:

1、首先是一个图片点击事件跳转到发布投票界面

2、进入页面就开始渲染会议列表内容,获取所有会议状态为开启会议的json数据,通过遍历拿取id和标题,按照指定下拉列表组件指定属性进行复制。

3、通过微信提供的图片上传函数,将图片解析成网络路径进行访问和存储

4、最后准备发布投票:

  • 监听下拉列表数据,通过选择的值对原数组的值进行判断从而确定拿取的数据
  • 发布成功后通过获取页面栈返回上级界面,并利用生命周期同时刷新投票界面

🌟更多解释请研究js代码

 

       如你们所见,其实其中许多不足,比如用户投完票后,该选择没有在界面上消除。这里还需要做连表查询投票信息如果存在该发布的投票列表就不会再获取到;还有每当点击投票弹窗确定时,不管是否投了票,是否登录了,它都会调用一次微信登录方法,这个目前还在排查中,不知道是否是某些方法牵引到了登录功能,各位大佬有什么见解欢迎评论区留言🥰

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1142236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线扫相机DALSA--采集卡Base模式设置

采集卡默认加载“1 X Full Camera Link”固件&#xff0c;Base模式首先要将固件更新为“2 X Base Camera Link”。 右键SCI图标&#xff0c;选择“打开文件所在的位置”&#xff0c;找到并打开SciDalsaConfig的Demo&#xff0c;如上图所示&#xff1a; 左键单击“获取相机”&a…

生成的二维码如何解析出原来的地址?

生成的二维码如何解析出原来的地址&#xff1f; 随着移动互联网的发展&#xff0c;二维码作为一种快速获取信息的方式&#xff0c;在我们的生活中越来越常见。而PHP作为Web语言之一&#xff0c;也有着二维码解码的功能。 PHP中有着众多的二维码解码库&#xff0c;例如&#x…

前端将图片储存table表格中,页面回显

<el-table :data"tableData" v-loading"loading" style"width: 100%" height"calc(100vh - 270px)" :size"tableSize"row-dblclick"enterClick"><el-table-column prop"name" label"文档…

代码随想录Day30 贪心05 LeetCode T435无重叠区间 T763划分字母区间 T56 合并区间

LeetCode T435 无重叠区间 题目链接:435. 无重叠区间 - 力扣&#xff08;LeetCode&#xff09; 题目思路: 这题思路和昨天的打气球类似,我们需要按照左区间或者右区间进行排序,然后哦判断第i个区间的左端点和第i-1个区间的右端点的大小关系,,如果大于等于,那么就无需操作,一旦…

一文搞懂 MineCraft 服务器启动操作和常见问题 2023年10月

文章目录 前言1. 新建文件夹2. 创建 bat 文件3. 编辑 bat 文件4. 启动服务器5. 恭喜完成 文章持续更新中&#xff0c;如果你有问题可以通过 qq 1317699264 获取免费协助&#xff0c;解决的问题将会被更新到本文章中 前言 无论你是使用服务端整合包&#xff0c;还是从上一篇我的…

3.线性神经网络

#pic_center R 1 R_1 R1​ R 2 R^2 R2 目录 知识框架No.1 线性回归基础优化算法一、线性回归1、买房案例2、买房模型简化3、线性模型4、神经网络5、损失函数6、训练数据7、参数学习8、显示解9、总结 二、 基础优化算法1、梯度下降2、学习率3、小批量随机梯度下降4、批量大小5、…

Gerrit | 重磅! 2.x 版本升级到 3.x 版本----转

Gerrit | 重磅! 2.x 版本升级到 3.x 版本 为什么要做版本升级&#xff1f; 2.x known bugs 重大问题不一一列举&#xff0c;这里仅仅是举几个例子&#xff1a; 安全或权限问题&#xff1a;普通用户能看到敏感数据&#xff0c;例如看到其他用户的 hashed api 密码&#xff0c…

小程序配置请求代理

在app.json中添加“proxy”字段配置代理 "proxy": {"/api": {"target": "http://192.168.110.249:8221/",//你要请求的目标地址"changeOrigin": true,"pathRewrite": {"^/api": ""//重定向}}…

尚硅谷大数据项目《在线教育之实时数仓》笔记004

视频地址&#xff1a;尚硅谷大数据项目《在线教育之实时数仓》_哔哩哔哩_bilibili 目录 第8章 数仓开发之DIM层 P024 P025 P026 P027 P028 P029 P030 第8章 数仓开发之DIM层 P024 package com.atguigu.edu.realtime.app.func;import com.alibaba.druid.pool.DruidDat…

面向服务的架构设计理论与实践

面向服务的架构设计理论与实践 面向服务的架构概述 SOA的定义 SOA发展现状 面向Web服务的业务流程执行语言(BPEL) BPEL&#xff08;面向Web服务的业务流程执行语言&#xff09;是一种用于描述和执行业务流程的标准化语言。它可以帮助组织在分布式系统中协调和管理各种Web服务…

【C++进阶】set和map的基本使用(灰常详细)

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

QQ云端机器人登录系统php源码开心版

可能很多人不知道这源码有什么用&#xff0c;这款源码主要是针对群机器人爱好者的&#xff0c; 这是一个通过对接挂机宝里面机器人框架的一个网页站点&#xff0c; 用户通过网页登录 QQ 账号至挂机宝里面框架&#xff08;可扫码登录、账密登录、跳转 QQ 快捷登录&#xff09;…

Canal整合SpringBoot详解(一)

文章目录 Canal整合SpringBoot详解&#xff08;一&#xff09;什么是canal搭建Kafka3.2.1集群⭐Kafka集群机器规划创建3台虚拟机&#xff08;centos7系统&#xff09;必要的环境准备&#xff08;3台虚拟机都要执行如下操作&#xff09;⭐分别修改每个服务器的hosts文件&#xf…

【2021集创赛】Robei杯一等奖:基于Robei EDA工具的隔离病房看护机器人设计

本作品参与极术社区组织的有奖征集|秀出你的集创赛作品风采,免费电子产品等你拿~活动。 团队介绍 参赛单位&#xff1a;重庆交通大学 队伍名称&#xff1a;一丘之貉 指导老师&#xff1a;毕波 李艾星 参赛队员&#xff1a;郁航 张坤 秦衡 总决赛奖项&#xff1a;Robei杯一等奖…

iOS开发-CoreNFC实现NFC标签Tag读取功能

iOS开发-CoreNFC实现NFC标签Tag读取功能 一、NFC近场通信 近场通信&#xff08;NFC&#xff09;是一种无线通信技术&#xff0c;它使设备能够在不使用互联网的情况下相互通信。它首先识别附近配备NFC的设备。NFC常用于智能手机和平板电脑。 二、实现NFC标签Tag读取功能 在…

Linux | 进程终止与进程等待

目录 前言 一、进程终止 1、进程终止的几种可能 2、exit 与 _exit 二、进程等待 1、为什么要进程等待 2、如何进行进程等待 &#xff08;1&#xff09;wait函数 &#xff08;2&#xff09;waitpid函数 3、再次深刻理解进程等待 前言 我们前面介绍进程时说子进程退出…

Canal整合SpringBoot详解(二)

文章目录 Canal整合SpringBoot详解&#xff08;二&#xff09;什么是canal案例2&#xff1a;CanalKafka实现mysql和elasticsearch的数据同步⭐Docker搭建elasticsearch7.8.0&#xff08;单机版本&#xff09;⭐Docker安装elasticsearch-head5⭐解决es-head 406错误问题直接修改…

实用篇-Eureka注册中心

一、提供者与消费者 服务提供者&#xff1a;一次业务中&#xff0c;被其他微服务调用的服务。(提供接口给其他微服务) 服务消费者&#xff1a;一次业务中&#xff0c;调用其他微服务的服务。(调用其他微服务提供的接口) 例如前面的案例中&#xff0c;order-service微服务是服…

系列七、动态代理

一、概述 二、Jdk动态代理案例 2.1、Star /*** Author : 一叶浮萍归大海* Date: 2023/10/27 17:16* Description:*/ public interface Star {/*** 唱歌* param name 歌曲名字* return*/String sing(String name);/*** 跳舞*/void dance(); } 2.2、BigStar /*** Author : 一叶…

AcWing 1.2.1 最长上升子序列模型 + 动态规划 + 图解(详细)

&#xff08;1&#xff09;acwing 4557. 最长上升子序列 4557. 最长上升子序列 - AcWing题库 给定一个长度为 N 的整数序列 a1,a2,…,aN。请你计算该序列的最长上升子序列的长度。上升子序列是指数值严格单调递增的子序列 输入格式 第一行包含整数 N第二行包含 N个整数 a1,a…