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

avatar
作者
猴君
阅读量: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.js Page({   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.js var 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() {     } })

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

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!