目录
小程序UI(User Interface)是指小程序的用户界面,包括小程序的整体布局、样式、交互等方面的设计。小程序UI的设计目的是为了提供用户友好的界面,使用户能够方便地使用小程序的功能。
小程序UI的设计原则通常包括以下几点:
1. 简洁明了:小程序的界面设计应该简洁明了,避免过多的视觉干扰和复杂的布局。用户可以通过一目了然的界面结构快速找到所需的功能。
2. 一致性:小程序的不同页面之间应该保持一致的界面设计,包括颜色、字体、按钮等方面的统一。这样可以提高用户的学习和使用效率,减少用户的困惑。
3. 易用性:小程序的界面设计应该考虑用户的使用习惯和心理需求,尽量减少用户的操作步骤和思考负担。例如,常用的功能应该放在显眼的位置,操作按钮应该易于点击等。
4. 可访问性:小程序的界面设计应该考虑到不同用户的特殊需求,例如视力障碍者、听力障碍者等。设计师应该通过合适的颜色对比度、字体大小等方式来提高小程序的可访问性。
5. 反馈机制:小程序的界面设计应该提供即时的反馈机制,告知用户他们的操作是否成功或失败。例如,可以通过动画、弹窗等方式来提示用户操作的结果。
小程序UI的设计通常由UI设计师负责,他们需要根据小程序的功能和定位进行界面设计,包括页面的布局、颜色的选择、图标的设计等。同时,他们还需要与开发人员密切合作,确保设计的界面能够被准确地实现。
vantWeapp是一个基于微信小程序的组件库,是Vant组件库的小程序版本。它包括了常用的UI组件、业务组件和功能组件,可以帮助开发者快速构建出优秀的小程序页面。
vantWeapp的主要作用包括:
1. 提供常用UI组件:vantWeapp提供了丰富的UI组件,包括按钮、表单、列表、卡片、标签、导航、弹窗等,可以帮助开发者快速构建出美观、易用的小程序页面。
2. 提高开发效率:vantWeapp的组件具有可复用性,可以减少开发者的重复工作,提高开发效率。
3. 提供业务组件:vantWeapp还提供了一些常用的业务组件,例如地址选择器、城市选择器、日期选择器等,可以帮助开发者快速实现一些常用的业务需求。
4. 提供功能组件:vantWeapp还提供了一些功能组件,例如图片预览、下拉刷新、上拉加载等,可以帮助开发者实现一些常用的功能需求。
总之,vantWeapp是一个非常实用的小程序组件库,可以帮助开发者快速构建出美观、易用、功能丰富的小程序页面,提高开发效率,降低开发成本。
我们进入 vantWeapp 的官网进行快速上手 : https://vant-contrib.gitee.io/vant-weapp/0.x/#/quickstarthttps://vant-contrib.gitee.io/vant-weapp/0.x/#/quickstart
在前端项目的跟路径中,打开CMD窗口,输入以下命令安装npm。
npm i vant-weapp -S --production
如图 :
打开微信开发者工具,点击 工具 -> 构建 npm,并勾选 使用 npm 模块 选项,构建完成后,即可引入组件
如图 :
注 : 有些版本的开发工具是不需要勾选使用 npm 模块 选项的
在前端项目的跟路径中,打开CMD窗口,输入以下命令安装项目依赖。
npm install
如图 :
以 Button 组件为例,只需要在
app.json
或index.json
中配置 Button 对应的路径即可。如果你是通过下载源代码的方式使用 vant-weapp,请将路径修改为项目中 vant-weapp 所在的目录。
例如 :
- {
- "navigationBarTitleText": "投票管理",
- "usingComponents": {
- "tabs":"/components/tabs/tabs",
- "van-button": "vant-weapp/button",
- }
- }
引入组件后,可以在 wxml 中直接使用组件,如以下代码 :
- <van-button type="default">默认按钮van-button>
- <van-button type="primary">主要按钮van-button>
- <van-button type="info">信息按钮van-button>
- <van-button type="warning">警告按钮van-button>
- <van-button type="danger">危险按钮van-button>
效果图 :
以下后端代码都是使用SpringMVC及mybatis的技术学习,还有前后端分离的技术应用,在我博客中也信息的学习及技术,通过这些来完成后端的代码及功能的实现。如有不懂可以在我博客中自行学习,你肯定是技术大牛。
Vote : 投票
- package com.CloudJun.ssm.model;
-
- import lombok.Data;
-
- @Data
- public class Vote {
- private Integer id;
-
- private Integer meetingId;
-
- private String name;
-
- private String remark;
-
- private Integer state;
-
- private String images;
-
- public Vote(Integer id, Integer meetingId, String name, String remark, Integer state, String images) {
- this.id = id;
- this.meetingId = meetingId;
- this.name = name;
- this.remark = remark;
- this.state = state;
- this.images = images;
- }
-
- @Override
- public String toString() {
- return "Vote{" +
- "id=" + id +
- ", meetingId=" + meetingId +
- ", name='" + name + '\'' +
- ", remark='" + remark + '\'' +
- ", state=" + state +
- ", images='" + images + '\'' +
- '}';
- }
- }
VoteMapper : 自动生成的对象接口
- package com.CloudJun.ssm.mapper;
-
- import com.CloudJun.ssm.model.Vote;
-
- import java.util.List;
-
- public interface VoteMapper {
- int deleteByPrimaryKey(Integer id);
-
- int insert(Vote record);
-
- int insertSelective(Vote record);
-
- Vote selectByPrimaryKey(Integer id);
-
- int updateByPrimaryKeySelective(Vote record);
-
- int updateByPrimaryKey(Vote record);
-
- List
selectByList(Integer state); - }
VoteService : 自己为了实现方法创建的接口
- package com.CloudJun.ssm.service;
-
- import com.CloudJun.ssm.model.Vote;
-
- import java.util.List;
-
- /**
- * @author CloudJun
- * @create 2023-10-24 14:41
- */
- public interface VoteService {
-
- int deleteByPrimaryKey(Integer id);
-
- int insert(Vote record);
-
- int insertSelective(Vote record);
-
- Vote selectByPrimaryKey(Integer id);
-
- int updateByPrimaryKeySelective(Vote record);
-
- int updateByPrimaryKey(Vote record);
-
- List
selectByList(Integer state); -
- }
VoteServiceimpl : 实现调用方法功能而创建的实现类
- package com.CloudJun.ssm.service.impl;
-
- import com.CloudJun.ssm.mapper.VoteMapper;
- import com.CloudJun.ssm.model.Vote;
- import com.CloudJun.ssm.service.VoteService;
- import org.springframework.beans.factory.annotation.Autowired;
-
- import java.util.List;
-
- /**
- * @author CloudJun
- * @create 2023-10-24 14:42
- */
- public class VoteServiceimpl implements VoteService {
-
- @Autowired
- private VoteMapper voteMapper;
-
- @Override
- public int deleteByPrimaryKey(Integer id) {
- return voteMapper.deleteByPrimaryKey(id);
- }
-
- @Override
- public int insert(Vote record) {
- return voteMapper.insert(record);
- }
-
- @Override
- public int insertSelective(Vote record) {
- return voteMapper.insertSelective(record);
- }
-
- @Override
- public Vote selectByPrimaryKey(Integer id) {
- return voteMapper.selectByPrimaryKey(id);
- }
-
- @Override
- public int updateByPrimaryKeySelective(Vote record) {
- return 0;
- }
-
- @Override
- public int updateByPrimaryKey(Vote record) {
- return 0;
- }
-
- @Override
- public List
selectByList(Integer state) { - return voteMapper.selectByList(state);
- }
- }
VoteController : 处理前端发送的请求及处理数据,并且给予回馈数据到前端
- package com.CloudJun.ssm.wxcontroller;
-
- import com.CloudJun.ssm.mapper.VoteMapper;
- import com.CloudJun.ssm.model.Info;
- import com.CloudJun.ssm.model.Vote;
- import com.CloudJun.ssm.util.ResponseUtil;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
-
- /**
- * @author CloudJun
- * @create 2023-10-24 14:24
- */
- @RestController
- @RequestMapping("/wx/vote")
- public class VoteController {
-
- @Autowired
- private VoteMapper voteMapper;
-
- @RequestMapping("/add")
- public Object Add (Vote vote){
- int i = voteMapper.insertSelective(vote);
- return ResponseUtil.ok();
- }
-
- @RequestMapping("/list")
- public Object list (Integer state){
- List
votes = voteMapper.selectByList(state); - return ResponseUtil.ok(votes);
- }
-
- @RequestMapping("/update")
- public Object update (Vote vote){
- int i = voteMapper.updateByPrimaryKey(vote);
- return ResponseUtil.ok();
- }
-
-
-
-
- }
以下的前端代码基于我博客中的进行扩写 : 微信小程序之微信授权登入及授权的流程讲解https://blog.csdn.net/SAME_LOVE/article/details/133963879?spm=1001.2014.3001.5501
在项目中的 api.js 文件里,配置后端请求数据的请求地址。
- // 以下是业务服务器API地址
- // 本机开发API地址
- var WxApiRoot = 'http://localhost:8080/oapro/wx/';
- // 测试环境部署api地址
- // var WxApiRoot = 'http://192.168.191.1:8080/oapro/wx/';
- // 线上平台api地址
- //var WxApiRoot = 'https://www.oa-mini.com/demo/wx/';
-
- module.exports = {
- IndexUrl: WxApiRoot + 'home/index', //首页数据接口
- SwiperImgs: WxApiRoot+'swiperImgs',
- MettingInfos: WxApiRoot+'meeting/list',
- MettingVote : WxApiRoot+'info/list',
- MettingVoteAdd : WxApiRoot+'vote/add',//增加投票
- MettingVoteList : WxApiRoot+'vote/list',//获取投票信息
- MettingVoteupdate : WxApiRoot+'vote/update',//确认投票
- AuthLoginByWeixin: WxApiRoot + 'auth/login_by_weixin', //微信登录
- UserIndex: WxApiRoot + 'user/index', //个人页面用户相关信息
- AuthLogout: WxApiRoot + 'auth/logout', //账号登出
- AuthBindPhone: WxApiRoot + 'auth/bindPhone' //绑定微信手机号
- };
在项目的投票管理页面中配置引用的组件及自定义组件,在.JSON文件中编写 :
list.json
- {
- "navigationBarTitleText": "投票管理",
- "usingComponents": {
- "tabs":"/components/tabs/tabs",
- "van-button": "vant-weapp/button",
- "van-notice-bar": "vant-weapp/notice-bar/index",
- "van-toast": "vant-weapp/toast/index"
- }
- }
在项目的投票管理页面中,进行编写页面标签,对数据进行显示,在.wxml文件中
list.wxml
- <tabs tabList="{{tabs}}" bindtabsItemChange="tabsItemChange">
- tabs>
- <view style="height: 100rpx;">view>
-
- <view class="{{componentStatus[0] ? '' : 'hidden'}}">
- <view class="publish">
-
- <form bindsubmit='votesubmit'>
- <view class="img">
- <view class="img_left" >
- <image class="imgs" src="{{imageUrl=='' ? '/static/persons/15.gif':imageUrl }}" mode="aspectFit" bindtap="handleUploadImage">image>
- <input hidden="true" type="text" name="images" value="{{imageUrl}}" />
- view>
- view>
- <view class="meeting_id">
- <view class="meeting_title">所属会议 : view>
- <picker bindchange="meetingChange" name="meetingId" value="{{array[meeting_id].id}}" range-key="title" range="{{array}}">
- <view class="meeting_text" >{{array[meeting_id].title==null?'请选择会议':array[meeting_id].title}}view>
- picker>
- view>
- <view class="meeting_id" id="meeting_id">
- <view class="meeting_title">投票标题 : view>
- <input class="vote_text" placeholder="请输入标题" type="text" name="name" />
- view>
- <view class="textarea" id="vote_text">
- <view class="meeting_textarea">投票说明 : view>
- <textarea class="vote_textarea" name="remark" type="text" >textarea>
- view>
- <view class="vote_button">
- <button class="vote_button_empty" type="default" formType="reset" plain="true">清空内容button>
- <view style="width: 70rpx;">view>
- <button class="vote_button_submit" type="primary" formType="submit" plain="true">确认发起button>
- view>
- form>
- view>
-
- view>
-
- <view class="{{componentStatus[1] ? '' : 'hidden'}}">
- <van-notice-bar
- left-icon="flower-o"
- mode="closeable"
- color="#6d9d9e"
- delay="100"
- backgroundColor="#e4ecec"
- text="无论我们能活多久,我们能够享受的只有无法分割的此刻,不会回头,离弦的箭、逝去的生活和失去的机会。此外别无其他。"
- />
- <block wx:for-items="{{engage}}" wx:for-item="item" wx:key="item.id">
- <view class="vote_carryout">
- <image class="vote_carryout_img" src="{{item.images}}">image>
- <view class="vote_carryout_text">
- <view style="width: 450rpx;display: flex;flex-direction:column;">
- <text class="vote_carryout_text_f" >{{item.name}}text>
- <text class="vote_carryout_text_t">{{item.remark}}text>
- view>
- <button class="vote_carryout_text_btn" bindtap="voteparticipate" data-item="{{item.id}}" size="mini">参与button>
- view>
- view>
- block>
-
-
- view>
- <view class="{{componentStatus[2] ? '' : 'hidden'}}">
-
- <van-notice-bar
- left-icon="flower-o"
- mode="closeable"
- color="#6d9d9e"
- delay="100"
- backgroundColor="#e4ecec"
- text="无论我们能活多久,我们能够享受的只有无法分割的此刻,不会回头,离弦的箭、逝去的生活和失去的机会。此外别无其他。"
- />
- <block wx:for-items="{{not}}" wx:for-item="item" wx:key="item.id">
- <view class="vote_carryout">
- <image class="vote_carryout_img" src="{{item.images==null?'/static/persons/15.gif':item.images}}">image>
- <view class="vote_carryout_text">
- <view style="width: 450rpx;display: flex;flex-direction:column;">
- <text class="vote_carryout_text_f" >{{item.name}}text>
- <text class="vote_carryout_text_t">{{item.remark}}text>
- view>
- <button class="vote_carryout_text_btn" bindtap="Votenotbtn" size="mini">已参与button>
- view>
- view>
- block>
-
- view>
- <view class="{{componentStatus[3] ? '' : 'hidden'}}">
-
- <van-notice-bar
- left-icon="flower-o"
- mode="closeable"
- color="#6d9d9e"
- delay="100"
- backgroundColor="#e4ecec"
- text="无论我们能活多久,我们能够享受的只有无法分割的此刻,不会回头,离弦的箭、逝去的生活和失去的机会。此外别无其他。"
- />
- <block wx:for-items="{{lists}}" wx:for-item="item" wx:key="item.id">
- <view class="vote_carryout">
- <image class="vote_carryout_img" src="{{item.images==null?'/static/persons/15.gif':item.images}}">image>
- <view class="vote_carryout_text">
- <view style="width: 450rpx;display: flex;flex-direction:column;">
- <text class="vote_carryout_text_f" >{{item.name}}text>
- <text class="vote_carryout_text_t">{{item.remark}}text>
- view>
- <button class="vote_carryout_text_btn" size="mini">{{item.state==0?'未参与':'已参与'}}button>
- view>
- view>
- block>
-
-
- view>
-
在项目的投票管理页面中,编写标签样式,对页面的美化,在.wxss文件中编写
list.wxss
- /* pages/vote/list/list.wxss */
- .hidden {
- display: none;
- }
-
- .img {
- height: 450rpx;
- /* display: flex; */
- /* border-radius: 6px; */
- /* align-items: center; */
- }
-
- .imgs {
- height: 420rpx;
- width: 419rpx;
- margin-left: 105rpx;
- box-shadow: 0 0 20px rgb(117, 241, 241);
- border-radius: 10rpx;
- }
-
- .img_left {
- margin-top: 28rpx;
- height: 450rpx;
- width: 600rpx;
- margin-left: 57rpx;
- /* border-radius: 23rpx; */
- /* background-color: deeppink; */
- }
-
- .publish {
- width: 100%;
- }
-
- .meeting_id {
- height: 100rpx;
- background-color: rgb(230, 243, 243);
- display: flex;
- /* border-radius: 6px; */
- align-items: center;
- }
-
- .meeting_title {
- margin-left: 20rpx;
- }
-
- .meeting_text {
- /* background-color: aqua; */
- margin-left: 20rpx;
- margin-top: 10rpx;
- padding-left: 20rpx;
- font-size: 14px;
- height: 50rpx;
- width: 520rpx;
- }
-
- #meeting_id {
- border-top: 2px solid #fafafa;
- }
-
- #vote_text {
- display: flex;
- align-items: center;
- }
-
- .vote_text {
- margin-left: 35rpx;
- }
-
- .meeting_textarea {
- margin-left: 20rpx;
- width: 440rpx;
- }
-
- .vote_textarea {
- height: 160rpx;
- width: 490px;
- padding-right: 10rpx;
- padding-top: 10rpx;
- padding-left: 10rpx;
- border: 2px solid #c0f0f1;
- border-radius: 20rpx;
- }
-
- .textarea {
- border-top: 2px solid #fafafa;
- background-color: rgb(238, 247, 247);
- }
-
- .vote_button {
- border-top: 4px solid #fafafa;
- display: flex;
- width: 80%;
- align-items: center;
- margin-left: 73rpx;
- }
- .vote_carryout{
- background-color: rgba(150, 250, 250, 0.315);
- box-shadow: 0 0 20px rgb(117, 241, 241);
- margin: 20rpx 30rpx 0rpx 70rpx;
- border-radius: 20rpx;
- height: 460rpx;
- width: 620rpx;
- }
- .vote_carryout_img{
- height: 350rpx;
- width: 620rpx;
- border-radius: 20rpx;
- }
- .vote_carryout_text{
- display: flex;
- height: 100rpx;
- border-radius: 20rpx;
- }
- .vote_carryout_text_f{
- margin-left: 50rpx;
- height: 40rpx;
- font-size: 12px;
- }
- .vote_carryout_text_t{
- margin-left: 50rpx;
- height: 40rpx;
- color: rgba(116, 114, 114, 0.89);
- font-size: 12px;
- }
- .vote_carryout_text_btn{
- margin-top: 10rpx;
- height: 80rpx;
- font-size: 12px;
- size: 12px;
- background-color: rgb(174, 249, 252);
- }
在项目的投票管理页面中,编写后台请求的数据进行回应到前端,在.js文件中
list.js
- // pages/vote/list/list.js
- var app = getApp();
- const api = require('../../../config/api');
- const util = require('../../../utils/util.js');
- Page({
- /**
- * 页面的初始数据
- */
- data: {
- tabs: ['发起投票', '未参与', '已参与', '全部投票'],//顶部导航栏
- componentStatus: [true, false, false, false],//用于处理内容显示
- array: ['美国', '中国', '巴西', '日本'],
- engage:[],//未参与的投票
- not:[],//已参与的投票
- lists:[],//全部投票信息
- meeting_id: '请选择会议',
- imageUrl: '',//图片路径
- votename: '123'
- },
- //选择所属会议的事件
- meetingChange(e) {
- // console.log(e.detail.value)
- this.setData({
- meeting_id: e.detail.value
- })
- },
- //初始会议信息
- meetingini() {
- util.request(api.MettingVote).then(res => {
- this.setData({
- array: res.data.infoList
- })
- }).catch(res => {
- console.log('服器没有开启,使用模拟数据!')
- })
- },
- //初始化未参与的投票
- Voteiniengage() {
- util.request(api.MettingVoteList,{state:0}).then(res => {
- // console.log(res);
- this.setData({
- engage: res.data
- })
- }).catch(res => {
- console.log('服器没有开启,使用模拟数据!')
- })
- },
- //初始化已参与的投票
- Voteininot() {
- util.request(api.MettingVoteList,{state:1}).then(res => {
- // console.log(res);
- this.setData({
- not: res.data
- })
- }).catch(res => {
- console.log('服器没有开启,使用模拟数据!')
- })
- },
- //初始化全部投票信息
- VoteiniList() {
- util.request(api.MettingVoteList).then(res => {
- // console.log(res);
- this.setData({
- lists: res.data
- })
- }).catch(res => {
- console.log('服器没有开启,使用模拟数据!')
- })
- },
- //参与投票的点击事件
- voteparticipate(id){
- // console.log(id.target.dataset.item)
- wx.showModal({
- title: '提示',
- content: '你是否要贡献出你宝贵的一票?',
- success: function (res) {
- if (res.confirm) {
- //这里是点击了确定以后
- util.request(api.MettingVoteupdate, {id:id.target.dataset.item}).then(res => {
- // console.log(res)
- if (res.errno == 0) {
- wx.showToast({
- title: '成功投票!!',
- icon: 'none',
- duration: 1000//持续的时间
- })
- }
- }).catch(res => {
- console.log('服器没有开启,发布失败')
- })
- } else {//这里是点击了取消以后
- console.log('用户点击取消')
- }
- }
- })
- },
- //发起投票的事件
- votesubmit(data) {
- console.log(data.detail.value)
- wx.showModal({
- title: '提示',
- content: '确定发起该投票吗?',
- success: function (res) {
- if (res.confirm) {
- //这里是点击了确定以后
- util.request(api.MettingVoteAdd, data.detail.value).then(res => {
- // console.log(res)
- if (res.errno == 0) {
- wx.showToast({
- title: '发布投票成功',
- icon: 'none',
- duration: 1500//持续的时间
- })
- }
- }).catch(res => {
- console.log('服器没有开启,发布失败')
- })
- } else {//这里是点击了取消以后
- console.log('用户点击取消')
- }
- }
- })
- },
- //已参与按钮的点击事件
- Votenotbtn() {
- wx.showToast({
- title: '已进行投票,不可再投',
- icon: 'none',
- duration: 1000//持续的时间
- })
- },
- //图片选择器
- handleUploadImage() {
- wx.chooseImage({
- count: 1,
- success: (res) => {
- const imagePath = res.tempFilePaths[0];
- // 处理选择的图片路径
- // console.log('选择的图片路径:', imagePath);
- this.setData({
- imageUrl: imagePath // 更新图片路径,触发重新渲染
- });
- }
- });
- },
- /**
- * 生命周期函数--监听页面加载
- */
- onLoad(options) {
- this.meetingini();
- this.Voteiniengage();
- this.Voteininot();
- this.VoteiniList();
- },
-
- /**
- * 生命周期函数--监听页面初次渲染完成
- */
- onReady() {
-
- },
-
- /**
- * 生命周期函数--监听页面显示
- */
- onShow() {
-
- },
-
- /**
- * 生命周期函数--监听页面隐藏
- */
- onHide() {
-
- },
-
- /**
- * 生命周期函数--监听页面卸载
- */
- onUnload() {
-
- },
-
- /**
- * 页面相关事件处理函数--监听用户下拉动作
- */
- onPullDownRefresh() {
-
- },
-
- /**
- * 页面上拉触底事件的处理函数
- */
- onReachBottom() {
-
- },
-
- /**
- * 用户点击右上角分享
- */
- onShareAppMessage() {
-
- },
- //点击导航栏进行切换下方内容
- tabsItemChange(e) {
- let index = e.detail.index;
- //全部的组件赋值为false
- const lists = [false, false, false, false];
- //将所点击的组件赋值为true
- lists[index] = true;
- this.setData({
- componentStatus: lists // 更新 data 中的 componentStatus 属性值
- });
- },
- // tabsItemChange(e){
- // let index = e.detail.index;
- // console.log('vote.index='+index)
- // if(index==1 || index==2){
- // if (app.globalData.hasLogin) {
-
- // }else{
- // wx.navigateTo({
- // url: '/pages/auth/login/login',
- // })
- // }
- // }
- // }
- })
发起投票
参与投票
查看所有投票