🥳🥳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() { }})
好啦,今天的分享就到这了,希望能够帮到你呢!😊😊