【微信小程序开发】小程序微信用户授权登录(用户信息&手机号)

小程序 0

🥳🥳Welcome Huihui's Code World ! !🥳🥳

接下来看看由辉辉所写的关于小程序的相关操作吧

目录

🥳🥳Welcome Huihui's Code World ! !🥳🥳

授权流程讲解

一.用户信息授权登录

1.wx.login

2.wx.getUserProfile

3.代码

WXML

JS

二.用户信息授权登录之后台交互

前期准备

①准备数据接口

②密钥以及appid

后端代码

WXML

JS

utils/user.js【封装的代码块】

三.手机号授权登录之后台交互

后端代码

WXML

JS

四.投票界面与后台交互

1.效果预览

2.代码演示

vote/list.wxml

 vote/list.wxss

vote/list.js

vote/addvote.wxml

 vote/addvote.wxss

vote/addvote.js

vote/many.wxml

 vote/many.wxss

vote/many.js


授权流程讲解

我们在使用微信中的小程序时,都会要我们进行授权,例如下面这样

那么这样的用户授权时怎么实现的呢,这一篇主要就是讲解用户授权登录的流程!!!

图片说明:

1.客户端调用 wx.login() 获取 临时登录凭证code,通过 wx.request() 发起网络请求,将 code 传给服务端
2、服务端使用 code + appid + appsecret 向微信换取 (调用 auth.code2Session 接口)用户唯一标识openid 会话密钥session_key
3、服务端自定义 登录状态token(与openid、session_key关联)返回客户端
4、客户端将 登录状态token 存入 缓存storage(推荐使用 wx.setStorageSync(‘key’, ‘value’) 同步存储)
5、客户端wx.request() 发起请求时,携带登录状态token (推荐使用 wx.getStorageSync(‘key’) 同步获取)
6、服务端通过 登录状态token 查询到对应 openid 和 session_key
7、验证成功后返回业务数据给客户端

一.用户信息授权登录

其中有两种方法,第一种方法是点击登录之后便直接获取了用户的个人信息,而第二种会询问用户是否同意授权,这样的话,会更具安全性

1.wx.login

这个方法主要用于获取用户的登录凭证(code)。在用户进入小程序时,前端会调用wx.login来获取这个code,然后将这个code发送给后台服务器。后台服务器再向微信发送请求,通过这个code来获取用户的唯一标识(openid)以及本次登录的会话密钥(session_key)。之后,后台服务器将这两个信息传回前台,用于自定义登录状态和用户唯一标识

2.wx.getUserProfile

这个方法主要用于获取用户的更多详细信息,如昵称、头像等。在使用这个方法之前,需要先调用wx.authorize接口来发起授权请求,请求用户授权提供这些信息。如果用户同意授权,就可以通过调用wx.getUserProfile方法来获取这些详细信息

3.代码

WXML

<!--pages/index/index.wxml--><view>  <button wx:if="{{canIUseGetUserProfile}}" type="primary" class="wx-login-btn" bindtap="getUserProfile">微信直接登录1</button>  <button wx:else open-type="getUserInfo" type="primary" class="wx-login-btn" bindgetuserinfo="wxLogin">微信直接登录2</button>  <image mode="scaleToFill" src="{{userInfo.avatarUrl}}" />  <text>昵称:{{userInfo.nickName}}</text></view>

JS

// pages/index/index.jsPage({  data: {    userInfo: {},    canIUseGetUserProfile: false,  },  onLoad() {    // if (wx.getUserProfile) {    //   this.setData({    //     canIUseGetUserProfile: true    //   })    // }  },  getUserProfile(e) {    console.log('getUserProfile')    // 推荐使用 wx.getUserProfile 获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认    // 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗    wx.getUserProfile({      desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写      success: (res) => {        console.log(res);        this.setData({          userInfo: res.userInfo,          hasUserInfo: true        })      }    })  },  wxLogin: function(e) {    debugger    console.log('wxLogin')    console.log(e.detail.userInfo);    this.setData({      userInfo: e.detail.userInfo    })    if (e.detail.userInfo == undefined) {      app.globalData.hasLogin = false;      util.showErrorToast('微信登录失败');      return;    }      },  /**   * 生命周期函数--监听页面初次渲染完成   */  onReady() {  },  /**   * 生命周期函数--监听页面显示   */  onShow() {  },  /**   * 生命周期函数--监听页面隐藏   */  onHide() {  },  /**   * 生命周期函数--监听页面卸载   */  onUnload() {  },  /**   * 页面相关事件处理函数--监听用户下拉动作   */  onPullDownRefresh() {  },  /**   * 页面上拉触底事件的处理函数   */  onReachBottom() {  },  /**   * 用户点击右上角分享   */  onShareAppMessage() {  }})

用户授权登录后,后台便会保存用户的信息

二.用户信息授权登录之后台交互

前期准备

①准备数据接口

②密钥以及appid

后端代码

package com.zking.ssm.wxcontroller;/** * @Autho donkee * @Since 2022/6/27 */import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;import com.alibaba.fastjson.JSONObject;import com.zking.ssm.annotation.LoginUser;import com.zking.ssm.model.UserInfo;import com.zking.ssm.model.WxLoginInfo;import com.zking.ssm.model.WxUser;import com.zking.ssm.service.UserToken;import com.zking.ssm.service.UserTokenManager;import com.zking.ssm.service.WxUserService;import com.zking.ssm.util.JacksonUtil;import com.zking.ssm.util.ResponseUtil;import com.zking.ssm.util.UserTypeEnum;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.util.StringUtils;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import cn.binarywang.wx.miniapp.api.WxMaService;import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;import javax.servlet.http.HttpServletRequest;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;/** * 鉴权服务 */@Slf4j@RestController@RequestMapping("/wx/auth")public class WxAuthController {    @Autowired    private WxMaService wxService;    @Autowired    private WxUserService userService;    /**     * 微信登录     *     * @param wxLoginInfo     *            请求内容,{ code: xxx, userInfo: xxx }     * @param request     *            请求对象     * @return 登录结果     */    @PostMapping("login_by_weixin")    public Object loginByWeixin(@RequestBody WxLoginInfo wxLoginInfo, HttpServletRequest request) {        //客户端需携带code与userInfo信息        String code = wxLoginInfo.getCode();        UserInfo userInfo = wxLoginInfo.getUserInfo();        if (code == null || userInfo == null) {            return ResponseUtil.badArgument();        }        //调用微信sdk获取openId及sessionKey        String sessionKey = null;        String openId = null;        try {            long beginTime = System.currentTimeMillis();            //            WxMaJscode2SessionResult result = this.wxService.getUserService().getSessionInfo(code);//            Thread.sleep(6000);            long endTime = System.currentTimeMillis();            log.info("响应时间:{}",(endTime-beginTime));            sessionKey = result.getSessionKey();//session id            openId = result.getOpenid();//用户唯一标识 OpenID        } catch (Exception e) {            e.printStackTrace();        }        if (sessionKey == null || openId == null) {            log.error("微信登录,调用官方接口失败:{}", code);            return ResponseUtil.fail();        }else{            log.info("openId={},sessionKey={}",openId,sessionKey);        }        //根据openId查询wx_user表        //如果不存在,初始化wx_user,并保存到数据库中        //如果存在,更新最后登录时间        WxUser user = userService.queryByOid(openId);        if (user == null) {            user = new WxUser();            user.setUsername(openId);            user.setPassword(openId);            user.setWeixinOpenid(openId);            user.setAvatar(userInfo.getAvatarUrl());            user.setNickname(userInfo.getNickName());            user.setGender(userInfo.getGender());            user.setUserLevel((byte) 0);            user.setStatus((byte) 0);            user.setLastLoginTime(new Date());            user.setLastLoginIp(IpUtil.client(request));            user.setShareUserId(1);            userService.add(user);        } else {            user.setLastLoginTime(new Date());            user.setLastLoginIp(IpUtil.client(request));            if (userService.updateById(user) == 0) {                log.error("修改失败:{}", user);                return ResponseUtil.updatedDataFailed();            }        }        // token        UserToken userToken = null;        try {            userToken = UserTokenManager.generateToken(user.getId());        } catch (Exception e) {            log.error("微信登录失败,生成token失败:{}", user.getId());            e.printStackTrace();            return ResponseUtil.fail();        }        userToken.setSessionKey(sessionKey);        log.info("SessionKey={}",UserTokenManager.getSessionKey(user.getId()));        Map<Object, Object> result = new HashMap<Object, Object>();        result.put("token", userToken.getToken());        result.put("tokenExpire", userToken.getExpireTime().toString());        userInfo.setUserId(user.getId());        if (!StringUtils.isEmpty(user.getMobile())) {// 手机号存在则设置            userInfo.setPhone(user.getMobile());        }        try {            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");            String registerDate = df.format(user.getAddTime() != null ? user.getAddTime() : new Date());            userInfo.setRegisterDate(registerDate);            userInfo.setStatus(user.getStatus());            userInfo.setUserLevel(user.getUserLevel());// 用户层级            userInfo.setUserLevelDesc(UserTypeEnum.getInstance(user.getUserLevel()).getDesc());// 用户层级描述        } catch (Exception e) {            log.error("微信登录:设置用户指定信息出错:"+e.getMessage());            e.printStackTrace();        }        result.put("userInfo", userInfo);        log.info("【请求结束】微信登录,响应结果:{}", JSONObject.toJSONString(result));        return ResponseUtil.ok(result);    }   }}

WXML

<!--pages/auth/login/login.wxml--><view class="container">  <view class="login-box">    <button wx:if="{{canIUseGetUserProfile}}" type="primary" class="wx-login-btn" bindtap="getUserProfile">微信直接登录</button>    <button wx:else open-type="getUserInfo" type="primary" class="wx-login-btn" bindgetuserinfo="wxLogin">微信直接登录</button>    <button type="primary" class="account-login-btn" bindtap="accountLogin">账号登录</button>  </view></view>

JS

// pages/auth/login/login.jsvar util = require('../../../utils/util.js');var user = require('../../../utils/user.js');const app = getApp();Page({    /**     * 页面的初始数据     */    data: {        canIUseGetUserProfile: false, // 用于向前兼容        lock:false    },    onLoad: function(options) {        // 页面初始化 options为页面跳转所带来的参数        // 页面渲染完成        if (wx.getUserProfile) {          this.setData({            canIUseGetUserProfile: true          })        }        //console.log('login.onLoad.canIUseGetUserProfile='+this.data.canIUseGetUserProfile)    },    /**     * 生命周期函数--监听页面初次渲染完成     */    onReady() {    },    /**     * 生命周期函数--监听页面显示     */    onShow() {    },    getUserProfile(e) {        console.log('getUserProfile');        // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认        // 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗        wx.getUserProfile({            desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写            success: (res) => {                //console.log(res);                user.checkLogin().catch(() => {                    user.loginByWeixin(res.userInfo).then(res => {                      app.globalData.hasLogin = true;                      wx.navigateBack({                        delta: 1                      })                    }).catch((err) => {                      app.globalData.hasLogin = false;                      if(err.errMsg=="request:fail timeout"){                        util.showErrorToast('微信登录超时');                      }else{                        util.showErrorToast('微信登录失败');                      }                      this.setData({                        lock:false                      })                    });                  });            },            fail: (res) => {                app.globalData.hasLogin = false;                console.log(res);                util.showErrorToast('微信登录失败');            }        });    },    wxLogin: function(e) {        console.log('wxLogin');        if (e.detail.userInfo == undefined) {          app.globalData.hasLogin = false;          util.showErrorToast('微信登录失败');          return;        }        user.checkLogin().catch(() => {            user.loginByWeixin(e.detail.userInfo).then(res => {              app.globalData.hasLogin = true;              wx.navigateBack({                delta: 1              })            }).catch((err) => {              app.globalData.hasLogin = false;              if(err.errMsg=="request:fail timeout"){                util.showErrorToast('微信登录超时');              }else{                util.showErrorToast('微信登录失败');              }            });                });    },    accountLogin() {        console.log('开发中....')    }})

utils/user.js【封装的代码块】

/** * 用户相关服务 */const util = require('../utils/util.js');const api = require('../config/api.js');/** * Promise封装wx.checkSession */function checkSession() {  return new Promise(function(resolve, reject) {    wx.checkSession({      success: function() {        resolve(true);      },      fail: function() {        reject(false);      }    })  });}/** * Promise封装wx.login */function login() {  return new Promise(function(resolve, reject) {    wx.login({      success: function(res) {        if (res.code) {          resolve(res);        } else {          reject(res);        }      },      fail: function(err) {        reject(err);      }    });  });}/** * 调用微信登录 */function loginByWeixin(userInfo) {  return new Promise(function(resolve, reject) {    return login().then((res) => {      //登录远程服务器      util.request(api.AuthLoginByWeixin, {        code: res.code,        userInfo: userInfo      }, 'POST').then(res => {        if (res.errno === 0) {          //存储用户信息          wx.setStorageSync('userInfo', res.data.userInfo);          wx.setStorageSync('token', res.data.token);          resolve(res);        } else {          reject(res);        }      }).catch((err) => {        reject(err);      });    }).catch((err) => {      reject(err);    })  });}/** * 判断用户是否登录 */function checkLogin() {  return new Promise(function(resolve, reject) {    if (wx.getStorageSync('userInfo') && wx.getStorageSync('token')) {      checkSession().then(() => {        resolve(true);      }).catch(() => {        reject(false);      });    } else {      reject(false);    }  });}module.exports = {  loginByWeixin,  checkLogin,};

三.手机号授权登录之后台交互

手机号授权登录的流程与用户信息授权登录流程是一样的,只不过向微信调用的接口有所不同

后端代码

package com.zking.ssm.wxcontroller;/** * @Autho donkee * @Since 2022/6/27 */import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;import com.alibaba.fastjson.JSONObject;import com.zking.ssm.annotation.LoginUser;import com.zking.ssm.model.UserInfo;import com.zking.ssm.model.WxLoginInfo;import com.zking.ssm.model.WxUser;import com.zking.ssm.service.UserToken;import com.zking.ssm.service.UserTokenManager;import com.zking.ssm.service.WxUserService;import com.zking.ssm.util.JacksonUtil;import com.zking.ssm.util.ResponseUtil;import com.zking.ssm.util.UserTypeEnum;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.util.StringUtils;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import cn.binarywang.wx.miniapp.api.WxMaService;import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;import javax.servlet.http.HttpServletRequest;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;/** * 鉴权服务 */@Slf4j@RestController@RequestMapping("/wx/auth")public class WxAuthController {      /**     * 绑定手机号码     *     * @param userId     * @param body     * @return     */    @PostMapping("bindPhone")    public Object bindPhone(@LoginUser Integer userId, @RequestBody String body) {        log.info("【请求开始】绑定手机号码,请求参数,body:{}", body);        String sessionKey = UserTokenManager.getSessionKey(userId);        String encryptedData = JacksonUtil.parseString(body, "encryptedData");        String iv = JacksonUtil.parseString(body, "iv");        WxMaPhoneNumberInfo phoneNumberInfo = null;        try {            phoneNumberInfo = this.wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);        } catch (Exception e) {            log.error("绑定手机号码失败,获取微信绑定的手机号码出错:{}", body);            e.printStackTrace();            return ResponseUtil.fail();        }        String phone = phoneNumberInfo.getPhoneNumber();        WxUser user = userService.selectByPrimaryKey(userId);        user.setMobile(phone);        if (userService.updateById(user) == 0) {            log.error("绑定手机号码,更新用户信息出错,id:{}", user.getId());            return ResponseUtil.updatedDataFailed();        }        Map<Object, Object> data = new HashMap<Object, Object>();        data.put("phone", phone);        log.info("【请求结束】绑定手机号码,响应结果:{}", JSONObject.toJSONString(data));        return ResponseUtil.ok(data);    }      }}

WXML

<!--pages/ucenter/user/user.wxml--><form bindsubmit="formSubmit">    <view class='personal-data'>        <view class='list'>            <view class='item acea-row row-between-wrapper'>                <view>头像</view>                <view class='pictrue'>                    <image src='{{userInfo.avatarUrl}}'></image>                </view>            </view>            <view class='item acea-row row-between-wrapper'>                <view>名字</view>                <view class='input'><input type='text' disabled='true' name='nickname' value='{{userInfo.nickName}}'></input></view>            </view>            <view class='item acea-row row-between-wrapper'>                <view>手机号码</view>                <button name='phone' class='phoneW' value='{{userInfo.phone}}' wx:if="{{!userInfo.phone}}" bindgetphonenumber="getPhoneNumber" hover-class='none' open-type='getPhoneNumber'>                    点击获取                </button>                <view class='input acea-row row-between-wrapper' wx:else>                    <input type='text' disabled='true' name='phone' value='{{userInfo.phone}}' class='id'></input>                    <text class='iconfont icon-suozi'></text>                </view>            </view>            <view class='item acea-row row-between-wrapper'>                <view>ID号</view>                <view class='input acea-row row-between-wrapper'>                    <input type='text' value='1000{{userInfo.userId}}' disabled='true' class='id'></input>                    <text class='iconfont icon-suozi'></text>                </view>            </view>        </view>        <button class='modifyBnt' bindtap="exitLogin">退 出</button>    </view></form>

JS

var util = require('../../../utils/util.js');var api = require('../../../config/api.js');var user = require('../../../utils/user.js');var app = getApp();Page({  /**   * 页面的初始数据   */  data: {    userInfo: {},    hasLogin: false,    userSharedUrl: ''  },  /**      * 生命周期函数--监听页面加载   */  onLoad: function (options) {  },  onShow: function () {    let that = this;    //获取用户的登录信息    let userInfo = wx.getStorageSync('userInfo');    this.setData({      userInfo: userInfo,      hasLogin: true    });  },  getPhoneNumber: function (e) {      console.log(e);    let that = this;    if (e.detail.errMsg !== "getPhoneNumber:ok") {      // 拒绝授权      return;    }    if (!this.data.hasLogin) {      wx.showToast({        title: '绑定失败:请先登录',        icon: 'none',        duration: 2000      });      return;    }    util.request(api.AuthBindPhone, {      iv: e.detail.iv,      encryptedData: e.detail.encryptedData    }, 'POST').then(function (res) {      if (res.errno === 0) {        let userInfo = wx.getStorageSync('userInfo');        userInfo.phone = res.data.phone;//设置手机号码        wx.setStorageSync('userInfo', userInfo);        that.setData({          userInfo: userInfo,          hasLogin: true        });        wx.showToast({          title: '绑定手机号码成功',          icon: 'success',          duration: 2000        });      }    });  },  exitLogin: function () {    wx.showModal({      title: '',      confirmColor: '#b4282d',      content: '退出登录?',      success: function (res) {        if (!res.confirm) {          return;        }        util.request(api.AuthLogout, {}, 'POST');        app.globalData.hasLogin = false;        wx.removeStorageSync('token');        wx.removeStorageSync('userInfo');        wx.reLaunch({          url: '/pages/index/index'        });      }    })  }})

四.投票界面与后台交互

1.效果预览

2.代码演示

数据库

后端代码

package com.zking.minoa.wxcontroller;import com.zking.minoa.mapper.InfoMapper;import com.zking.minoa.mapper.OptionMapper;import com.zking.minoa.model.Info;import com.zking.minoa.model.Option;import com.zking.minoa.util.ResponseUtil;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestBody;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/6/29 */@RestController@RequestMapping("/wx/home")public class WxHomeController {    @Autowired    private InfoMapper infoMapper;    @Autowired    private OptionMapper optionMapper;    @RequestMapping("/add")    public String add(@RequestBody Map<String, Object> obj) {        System.out.println(obj);        //获取选项数组的长度来控制新增的次数        int optionsLength = ((List)obj.get("optionText")).size();        //循环添加投票数据        for (int i = 0; i < optionsLength; i++) {            //初始化option            Option option = new Option();            List<String> options = (List<String>) obj.get("optionText");            option.setMeetingId((Integer) obj.get("meetingId"));//会议id            String firstOption = options.get(i);            option.setOptionValue((String)obj.get("optionValue"));//投票标题            option.setOptionText(firstOption);//选项内容            //调取添加的方法            int insert = optionMapper.insertSelective(option);        }            return "投票发布成功";            } }

vote/list.wxml

<!--pages/vote/list/list.wxml--><wxs src="../../../utils/comm.wxs" module="tools" /><view class="info-title">  <image class="img-title"  src="../../../static/vote/sousuo.png"></image>  <input  type="text" placeholder="选择所属会议" bindtap="showModal" /></view><view class="modal-container {{modalVisible ? '' : 'hidden'}}">  <view class="modal-content">    <view>      <view class="table-header">    <text class="grid-title">标题</text>    <text class="grid-location">地点</text>    <text class="grid-time">开始时间</text>  </view>  <block wx:for="{{lists}}" wx:key="item.id" >    <view class="table-row {{item.id == selectedId ? 'selected' : ''}}" data-id="{{item.id}}" data-value="{{item.title}}" bindtap="handleClick" style="margin-top: 10px;">        <text>{{item.title}}</text>        <text>{{item.location}}</text>        <text>{{tools.formatDate(item.starttime)}}</text>    </view></block>    </view>     <button bindtap="hideModal" class="modal-btn">确认</button>  </view></view><view class="vote-button" bindtap="jumpToFoodPage">  <block wx:for="{{myvotelist}}" wx:key="index">    <view class="myvotes">      <view class="myimg">        <image class="vote-icon" src="{{item.img}}"></image>      </view>      <view class="myview">        <text class="vote-label">{{item.name}}</text>      </view>    </view>  </block>  <image class="vote-add" src="../../../static/vote/addvote.png" bindtap="addvote"></image></view>

 vote/list.wxss

/* pages/vote/list/list.wxss */.vote-button {  display: flex;  flex-direction: row;  flex-wrap: wrap;  /* 使元素在一行中超出容器宽度时自动换行 */}.myvotes {  padding-top: 50px;  padding-left: 5px;  height: 430rpx;  width: 360rpx;  display: flex;  flex-direction: column;}.myimg{  display: flex;  justify-content: center;}.myview{}.vote-icon {  margin: 5px;  width: 320rpx;  height: 300rpx;  border-radius:25px;  border: 10px solid rgb(247, 198, 66);}.img-title{  width: 32px;  height: 32px;}.vote-label { font-weight: 800; font-family: YouYuan;  width: 350rpx;  padding-left: 65px;    /* 将文字放在图标的正下方 */}.info-title{  display: flex;  align-items: center;  margin-left:65px ;  width: 300px;  border-radius:25px;  border: 2px solid rgb(247, 198, 66);}.vote-add {  margin-left: 340px;  margin-top: 35px;  width: 120rpx;  height: 120rpx;}/* --------------------- *//* pages/vote/list/list.wxss */.hidden {  display: none;}.title-view {  background-color: beige;  font-weight: 700;  padding-left: 7px;}.info-title {  padding: 5px 5px 10px 5px;  border-top: 1px solid rgb(129, 129, 127);}.info-text {  height: 100px;  padding: 5px 5px 10px 5px;  border-top: 1px solid rgb(129, 129, 127);}.image {  padding-left: 55px;  display: flex;  align-items: center;}.time {  border-top: 1px solid rgb(129, 129, 127);  padding: 5px 0px 5px 0px;  display: flex;  align-items: center;}.image-container {  padding-left: 60px;}.info-sousuo {  margin-left: 85px;  padding-left: 20px;  border-radius: 25px;  border: 4px solid rgb(214, 214, 98);  width: 250px;}/* pages/meeting/list/list.wxss */.section{  color: #aaa;  display: flex;  justify-content: center;}.list-info {  margin-top: 10px;  color: #aaa;}.list-num {  color: #e40909;  font-weight: 700;}.join {  padding: 0px 0px 0px 10px;  color: #aaa;}.state {  margin: 0px 6px 0px 6px;  border: 1px solid #93b9ff;  color: #93b9ff;}.list-tag {  padding: 3px 0px 10px 0px;  display: flex;  align-items: center;}.list-title {  display: flex;  justify-content: space-between;  color: #333;  font-weight: 900;}.yyy{  display: flex;  align-items: center;}.list-img{  height: 300rpx;  width: 90%;  border-radius: 50rpx;  margin: 5px 5px 5px 20px;}.centered {  display: flex;  /* 设置为弹性容器 */  justify-content: center;  /* 子元素水平方向居中对齐 */}.video-img {  width: 100px;  height: 100px;}.list {  border-bottom: 1px solid #6b6e74;  padding: 10px;}.mobi-text {  font-weight: 700;  padding: 15px;}.mobi-icon {  border-left: 5px solid #e40909;}.mobi-title {  background-color: rgba(158, 158, 142, 0.678);  margin: 10px 0px 10px 0px;}.swiper-item {  height: 300rpx;  width: 100%;  border-radius: 10rpx;}.userinfo {  display: flex;  flex-direction: column;  align-items: center;  color: #aaa;}.userinfo-avatar {  overflow: hidden;  width: 128rpx;  height: 128rpx;  margin: 20rpx;  border-radius: 50%;}.usermotto {  margin-top: 200px;}.filx{  display: flex;  align-items: center;}.container {  padding: 20px;}.modal-container {  position: fixed;  top: 50%;  left: 50%;  transform: translate(-50%, -50%);  background-color: #fff;  width: 80%;  max-height: 80%;  overflow-y: auto;  padding: 20px;}.mask {  position: fixed;  top: 0;  left: 0;  width: 100%;  height: 100%;  background-color: rgba(0, 0, 0, 0.5);}button {  display: block;  margin-top: 10px;}.content {  margin-top: 10px;  border: 1px solid #ccc;  padding: 10px;}

vote/list.js

// pages/vote/list/list.js// 获取应用实例const app = getApp()const api = require("../../../config/api")const utils = require("../../../utils/util")Page({  /**   * 页面的初始数据   */  data: {    myvotelist: [{        index: 1,        name: '投票统计',        img: '../../../static/vote/totaldata-active.png'      },      {        index: 3,        name: '历史投票',        img: '../../../static/vote/voterecords-active.png'      },      {        index: 2,        name: '赞成人数',        img: '../../../static/vote/yes-active.png'      },      {        index: 3,        name: '反对人数',        img: '../../../static/vote/no-active.png'      },    ],    modalVisible: false, // 模态框是否可见    lists: [],    selectedId: '', // 存储选中数据的id    state:false  },  addvote: function () {    if (!this.data.state) {      wx.showModal({          title: '提示',          content: '请先选择会议',          showCancel: false,  // 取消按钮不显示          success (res) {              if (res.confirm) {                  console.log('用户点击确定')              }          }      })  } else {      // 如果state为true      wx.navigateTo({        //id:selectedId,        //url: '/pages/vote/addvote/addvote?id='+id // 跳转到目标页面的路径        url: '/pages/vote/addvote/addvote' // 跳转到目标页面的路径      })  }    },  loadMeetingInfos() {    let that = this;    utils.request(api.IndexUrl).then(res => {      this.setData({        lists: res.data.infoList      })    });  },  // 点击数据行触发的事件  handleClick(event) {    // console.log(event)    const id = event.currentTarget.dataset.id;    const title = event.currentTarget.dataset.value;    // console.log('传递的值:', title);    // console.log('现在已经拿到id了', id)    var obj = {      id: id,      title:title    };    wx.setStorageSync('key', JSON.stringify(obj));    this.setData({      selectedId: id,      state:true    });  },  // 点击事件,显示模态框  showModal() {    this.setData({      modalVisible: true,    });    this.loadMeetingInfos();  },  // 点击事件,隐藏模态框  hideModal() {    this.setData({      modalVisible: false    });  },  /**   * 生命周期函数--监听页面加载   */  onLoad(options) {  },  /**   * 生命周期函数--监听页面初次渲染完成   */  onReady() {  },  /**   * 生命周期函数--监听页面显示   */  onShow() {  },  /**   * 生命周期函数--监听页面隐藏   */  onHide() {  },  /**   * 生命周期函数--监听页面卸载   */  onUnload() {  },  /**   * 页面相关事件处理函数--监听用户下拉动作   */  onPullDownRefresh() {  },  /**   * 页面上拉触底事件的处理函数   */  onReachBottom() {  },  /**   * 用户点击右上角分享   */  onShareAppMessage() {  }})

vote/addvote.wxml

<view class="container">    <button class="title" bindtap="single">单选投票</button>      <button class="title" bindtap="many">多选投票</button>      </view>

 vote/addvote.wxss

.container {  padding: 20rpx;}button {  margin-top: 60px;  background-color: rgb(247, 198, 66);  color: #fff;  padding: 10rpx 20rpx;  border-radius: 4rpx;  text-align: center;}  .title {  font-size: 30rpx;  font-weight: bold;  margin-bottom: 10rpx;}

vote/addvote.js

Page({  many: function () {    console.log(111)    wx.navigateTo ({          url: '/pages/vote/many/many' // 跳转到目标页面的路径    })  },  data: {    radioOptions: ['选项1', '选项2', '选项3'],    checkboxOptions: ['选项A', '选项B', '选项C'],    voteTitle: '',    voteDescription: '',    selectedRadioIndex: -1,    selectedCheckboxIndexes: []  },  onTitleInput(e) {    this.setData({      voteTitle: e.detail.value    });  },  onDescriptionInput(e) {    this.setData({      voteDescription: e.detail.value    });  },  onRadioChange(e) {    this.setData({      selectedRadioIndex: e.detail.value    });  },  onCheckboxChange(e) {    this.setData({      selectedCheckboxIndexes: e.detail.value    });  },  submitVote() {    // 获取投票的标题、描述以及选择的选项    const { voteTitle, voteDescription, selectedRadioIndex, selectedCheckboxIndexes } = this.data;    // TODO: 处理提交投票逻辑,可以发送请求给服务器等    // 打印投票结果    console.log('投票标题:', voteTitle);    console.log('投票描述:', voteDescription);    console.log('单选投票选项:', selectedRadioIndex);    console.log('多选投票选项:', selectedCheckboxIndexes);  },  /**   * 页面的初始数据   */  data: {  },  /**   * 生命周期函数--监听页面加载   */  onLoad(options) {  },  /**   * 生命周期函数--监听页面初次渲染完成   */  onReady() {  },  /**   * 生命周期函数--监听页面显示   */  onShow() {  },  /**   * 生命周期函数--监听页面隐藏   */  onHide() {  },  /**   * 生命周期函数--监听页面卸载   */  onUnload() {  },  /**   * 页面相关事件处理函数--监听用户下拉动作   */  onPullDownRefresh() {  },  /**   * 页面上拉触底事件的处理函数   */  onReachBottom() {  },  /**   * 用户点击右上角分享   */  onShareAppMessage() {  }})

vote/many.wxml

<!--pages/vote/many/many.wxml--><view class="container" >    <input class="title" placeholder="会议标题" value="{{title}}" disabled/> <!-- <input class="title" value="{{title}}" disabled /> --> <view class="line"></view> <input class="info" placeholder="投票标题" bindinput="titleChange"/> <view class="line"></view>  <view id="scrollContainer">  <view wx:for="{{inputList}}" wx:key="index" class="select">    <image class="select-add" src="../../../static/vote/减.png" bindtap="hideInput"      data-index="{{index}}"></image>    <input class="vote-content" placeholder="请输入内容" data-index="{{index}}"      value="{{item.value}}" bindinput="inputChange"></input>  </view>  <view class="select" style="margin-left: 4px;">  <image class="select-add" src="../../../static/vote/添加_填充.png" bindtap="showInput"></image> <view class="select-content" bindtap="showInput"> 添加选项</view> </view>  <button class="submit-button" style="top: {{buttonTop}}rpx;" bindtap="submitVote">提交</button></view>   </view>

 vote/many.wxss

/* pages/vote/many/many.wxss */.container {  display: flex;  flex-direction: column;  align-items: center;} .title{  height: 200px;  font-weight: bolder;  font-size: 70rpx; margin-left: 20px; margin-top: -160px; margin-bottom: -50px;}.line {  width: 100%;  height: 1px;  background-color: #ccc;}.info{height: 70px;width:380px;}.select{  display: flex;flex-direction: row;align-self: start;}.select-add {margin-left: 15px;  margin-top: 15px;  width: 50rpx;  height: 50rpx;}.select-content{  margin-top: 10px;  margin-left: 7px;  display: flex;  align-items: center;}.vote-content {  width: 200rpx;  height: 30rpx;  margin-top: 17px;  margin-left: 7px;  display: flex;  align-items: center;}.scroll-container {  height: 500rpx; /* 设置合适的高度,使其可以滚动 */}.submit-button {margin-top: 20px;  width: 200rpx;  height: 60rpx;  background-color: rgb(241, 189, 46);}

vote/many.js

const app = getApp()const api = require("../../../config/api.js")const util = require("../../../utils/util") Page({  data: {    inputList: [],    title:'',    voteTitle: '',    id:''    },   // 显示输入框  showInput: function () {    const length = this.data.inputList.length;    const newInputList = [...this.data.inputList];    newInputList.push({      value: ''    });    this.setData({      inputList: newInputList    });  },   // 输入框内容改变  inputChange: function (event) {    const index = event.currentTarget.dataset.index;    const value = event.detail.value;    const newInputList = [...this.data.inputList];    newInputList[index].value = value;    this.setData({      inputList: newInputList    });  },   // 删除输入框  hideInput: function (event) {    const index = event.currentTarget.dataset.index;    const newInputList = [...this.data.inputList];    newInputList.splice(index, 1);    this.setData({      inputList: newInputList    });  },   // 投票标题改变  titleChange: function (event) {    const value = event.detail.value;    this.setData({      voteTitle: value    });  },   // 提交投票  submitVote: function () {    // 获取投票标题和选项内容    const meetingId = this.data.id;    const optionValue = this.data.voteTitle;    const optionText = this.data.inputList.map(item => item.value);       // 打印标题和选项    let data = {      meetingId: meetingId,      optionValue: optionValue,      optionText:optionText    };    console.log(data)     util.request(api.VoteADD, data, 'POST').then(res => {      console.log(res)      // 清空投票标题和选项内容      this.setData({        voteTitle: '',        inputList: []      });    })    },    /**   * 生命周期函数--监听页面加载   */  onLoad(options) {var objStr = wx.getStorageSync('key');var obj = JSON.parse(objStr);console.log("这个是父页面的值",obj.id,obj.title)this.setData({  id: obj.id,  title:obj.title});  },   /**   * 生命周期函数--监听页面初次渲染完成   */  onReady() {   },   /**   * 生命周期函数--监听页面显示   */  onShow() {   },   /**   * 生命周期函数--监听页面隐藏   */  onHide() {   },   /**   * 生命周期函数--监听页面卸载   */  onUnload() {   },   /**   * 页面相关事件处理函数--监听用户下拉动作   */  onPullDownRefresh() {   },   /**   * 页面上拉触底事件的处理函数   */  onReachBottom() {   },   /**   * 用户点击右上角分享   */  onShareAppMessage() {   }})

好啦,今天的分享就到这了,希望能够帮到你呢!😊😊  

也许您对下面的内容还感兴趣: