微信小程序之开发会议OA项目

小程序 0

目录

前言

本篇目标 

首页

会议

投票 

个人中心 

会议OA项目-首页

配置

tabbar

mock工具

page

swiper

会议信息

会议OA项目-会议 

自定义tabs组件

会议管理

会议OA项目-投票

会议OA项目-个人中心


前言

文章含源码资源,投票及个人中心详细自行查看源码即可

  1. 小程序没有DOM对象,一切基于组件化
  2. 储备知识

    1. 理解事件机制

    2. 理解组件化

    3. 理解数据绑定

    4. Flex布局

    5. 移动端适配方案

  3. 建议:学习vue后开发小程序更简单

本篇目标 

首页

会议

 

投票 

个人中心 

 

会议OA项目-首页

配置

  • config/api.js
    // 以下是业务服务器API地址 // 本机开发API地址var WxApiRoot = 'http://localhost:8080/demo/wx/';// 测试环境部署api地址// var WxApiRoot = 'http://192.168.0.101:8070/demo/wx/';// 线上平台api地址//var WxApiRoot = 'https://www.oa-mini.com/demo/wx/';module.exports = {  IndexUrl: WxApiRoot + 'home/index', //首页数据接口  SwiperImgs: WxApiRoot+'swiperImgs', //轮播图  MettingInfos: WxApiRoot+'meeting/list', //会议信息};

tabbar

  • app.json
    "list": [{      "pagePath": "pages/index/index",      "text": "首页",      "iconPath": "/static/tabBar/coding.png",      "selectedIconPath": "/static/tabBar/coding-active.png"    },      {        "pagePath": "pages/meeting/list/list",        "iconPath": "/static/tabBar/sdk.png",        "selectedIconPath": "/static/tabBar/sdk-active.png",        "text": "会议"      },      {        "pagePath": "pages/vote/list/list",        "iconPath": "/static/tabBar/template.png",        "selectedIconPath": "/static/tabBar/template-active.png",        "text": "投票"      },      {        "pagePath": "pages/ucenter/index/index",        "iconPath": "/static/tabBar/component.png",        "selectedIconPath": "/static/tabBar/component-active.png",        "text": "个人中心"      }]

mock工具

  • imageSrcs
    {  "data": {    "images":[        {          "img": "https://tse2-mm.cn.bing.net/th/id/OIP-C.ja-L_FC01Xbzhqo4Rm3B8gHaEo?rs=1&pid=ImgDetMain",          "text": "1"        },        {          "img": "https://tse2-mm.cn.bing.net/th/id/OIP-C.A3UXYP_OyP3S5UfO6HXuAgHaEK?rs=1&pid=ImgDetMain",          "text": "2"        },        {          "img": "https://pic3.zhimg.com/v2-9873f715d01819718cdc59dc004052b5_1440w.jpg?source=172ae18b",          "text": "3"        },        {          "img": "https://ts1.cn.mm.bing.net/th/id/R-C.8bb9ed00b8b77b8de03ca88c2c5b9c70?rik=KsLZ%2fjYfY5ELCg&riu=http%3a%2f%2fwww.kutoo8.com%2fupload%2fimage%2f10539408%2f14.jpg&ehk=HMGT1e0hcjxVw1XAbC7yJpq3qSDWlnwsj%2fRN%2f0Etimk%3d&risl=&pid=ImgRaw&r=0",          "text": "4"        },        {          "img": "https://img1.pconline.com.cn/piclib/200906/09/batch/1/34797/1244512002916phjm5dpgjl.jpg",          "text": "5"        },        {          "img": "https://ts1.cn.mm.bing.net/th/id/R-C.d951726778523659c8f2d7fd6ad838fd?rik=kR8VYs9ELLWFKQ&riu=http%3a%2f%2fwww.kutoo8.com%2fupload%2fimage%2f85280274%2f2017032108.jpg&ehk=%2fJInO%2fEPMaYF1q%2fu6vzk2j6hPSkAEyCyc3%2fH1Ib1tM0%3d&risl=&pid=ImgRaw&r=0",          "text": "6"        }    ]  },  "statusCode": "200",  "header": {    "content-type":"applicaiton/json;charset=utf-8"  }}

page

  • index.css
    page{	height: 100%;	background-color: #efeff4;}

swiper

  • index.wxml
    <swiper indicator-dots="true" autoplay="true" circular="true" indicator-color="#fff" indicator-active-color="blue">   <block wx:for="{{images}}" wx:key="text">       <swiper-item>           <view class="swiper-item">              <image src="{{item.img}}" mode="scaleToFill"></image>           </view>       </swiper-item>   </block></swiper>

  • index.css
    swiper {  width: 100%;  height: calc(100vw*9/16);}.swiper-item>image {   width:100%;}

  • index.js
    loadSwiperImgs(){     //请注意this的指向问题     let that=this;     wx.request({       url: api.SwiperImgs,       success(rs){         console.log(rs);         that.setData({            images:rs.data.images         });       }    })}

会议信息

  • mock数据
    {  "data": {    "lists": [        {           "id": "1",          "image": "/static/persons/Snipaste_2024-02-18_20-39-17.png",          "title": "微信小程序会议OA_空空",          "num":"1314",          "state":"进行中",          "starttime": "2024-02-18 21:00:00",          "location": "湖南省——长沙市"        },        {          "id": "1",          "image": "/static/persons/Snipaste_2024-02-18_20-40-00.png",          "title": "微信小程序会议OA_空空",          "num":"520",          "state":"已结束",          "starttime": "2024-02-18 12:00:00",          "location": "湖南省——长沙市"        },        {          "id": "1",          "image": "/static/persons/Snipaste_2024-02-18_20-40-45.png",          "title": "微信小程序会议OA_空空",          "num":"888",          "state":"进行中",          "starttime": "2024-02-18 08:00:00",          "location": "湖南省——长沙市"        },        {          "id": "1",          "image": "/static/persons/Snipaste_2024-02-18_20-40-45.png",          "title": "微信小程序会议OA_空空",          "num":"666",          "state":"已结束",          "starttime": "2024-02-18 08:00:00",          "location": "湖南省——长沙市"        },        {          "id": "1",          "image": "/static/persons/Snipaste_2024-02-18_20-40-00.png",          "title": "微信小程序会议OA_空空",          "num":"999",          "state":"进行中",          "starttime": "2024-02-18 08:00:00",          "location": "湖南省——长沙市"        }      ]  },  "statusCode": "200",  "header": {    "content-type":"applicaiton/json;charset=utf-8"  }}

  • index.wxml
    <view class="mobi-title">    <text class="mobi-icon"></text>    <text>会议信息</text></view><block wx:for-items="{{lists}}" wx:for-item="item" wx:key="item.id">    <view class="list" data-id="{{item.id}}">        <view class="list-img">            <image class="video-img" mode="scaleToFill" src="{{item.image}}"></image>        </view>        <view class="list-detail">            <view class="list-title"><text>{{item.title}}</text></view>            <view class="list-tag">                <view class="state">{{item.state}}</view>                <view class="join"><text class="list-num">{{item.num}}</text>人报名</view>            </view>            <view class="list-info"><text>{{item.address}}</text>|<text>{{item.time}}</text></view>        </view>    </view></block><view class="section bottom-line">		<text>到底啦</text></view>

  • index.js
    loadMeetingInfos(){    let that=this;    wx.request({        url: api.MettingInfos,        dataType: 'json',        success(res) {          console.log(res)          that.setData({              lists:res.data.lists          })        }      })  }

  • index.wxss
    .mobi-title {    font-size: 12pt;    color: #777;    line-height: 110%;    font-weight: bold;    width: 100%;    padding: 15rpx;    background-color: #f3f3f3;}.mobi-icon {    padding: 0rpx 3rpx;    border-radius: 3rpx;    background-color: #ff7777;    position: relative;    margin-right: 10rpx;}/*list*/.list {    display: flex;    flex-direction: row;    width: 100%;    padding: 0 20rpx 0 0;    border-top: 1px solid #eeeeee;    background-color: #fff;    margin-bottom: 5rpx;    /* border-radius: 20rpx;    box-shadow: 0px 0px 10px 6px rgba(0,0,0,0.1); */}.list-img {    display: flex;    margin: 10rpx 10rpx;    width: 150rpx;    height: 220rpx;    justify-content: center;    align-items: center;}.list-img .video-img {    width: 120rpx;    height: 120rpx;    }.list-detail {    margin: 10rpx 10rpx;    display: flex;    flex-direction: column;    width: 600rpx;    height: 220rpx;}.list-title text {    font-size: 11pt;    color: #333;    font-weight: bold;}.list-detail .list-tag {    display: flex;    height: 70rpx;}.list-tag .state {    font-size: 9pt;    color: #81aaf7;    width: 120rpx;    border: 1px solid #93b9ff;    border-radius: 2px;    margin: 10rpx 0rpx;    display: flex;    justify-content: center;    align-items: center;}.list-tag .join {    font-size: 11pt;    color: #bbb;    margin-left: 20rpx;    display: flex;    justify-content: center;    align-items: center;}.list-tag .list-num {    font-size: 11pt;    color: #ff6666;}.list-info {    font-size: 9pt;    color: #bbb;    margin-top: 20rpx;}.bottom-line{    display: flex;    height: 60rpx;    justify-content: center;    align-items: center;    background-color: #f3f3f3;}.bottom-line text{    font-size: 9pt;    color: #666;}

会议OA项目-会议 

自定义tabs组件

 文档参考地址:自定义组件 | 微信开放文档

tabs.json

{  "component": true,  "usingComponents": {}}

 tabs.wxml

<view class="tabs">    <view class="tabs_title">        <view wx:for="{{tabList}}" wx:key="id" class="title_item  {{index==tabIndex?'item_active':''}}" bindtap="handleItemTap" data-index="{{index}}">            <view style="margin-bottom:5rpx">{{item}}</view>            <view style="width:30px" class="{{index==tabIndex?'item_active1':''}}"></view>        </view>    </view>    <view class="tabs_content">        <slot></slot>    </view></view>

 tabs.wxss

.tabs {    position: fixed;    top: 0;    width: 100%;    background-color: #fff;    z-index: 99;    border-bottom: 1px solid #efefef;    padding-bottom: 20rpx;}.tabs_title {    /* width: 400rpx; */    width: 90%;    display: flex;    font-size: 9pt;    padding: 0 20rpx;}.title_item {    color: #999;    padding: 15rpx 0;    display: flex;    flex: 1;    flex-flow: column nowrap;    justify-content: center;    align-items: center;}.item_active {    /* color:#ED8137; */    color: #000000;    font-size: 11pt;    font-weight: 800;}.item_active1 {    /* color:#ED8137; */    color: #000000;    font-size: 11pt;    font-weight: 800;    border-bottom: 6rpx solid #333;    border-radius: 2px;}

 tabs.js

var App = getApp();Component({  /**   * 组件的属性列表   */  properties: {    tabList:Object  },  /**   * 组件的初始数据   */  data: {    tabIndex:0  },  /**   * 组件的方法列表   */  methods: {    handleItemTap(e){      // 获取索引      const {index} = e.currentTarget.dataset;      // 触发 父组件的事件      this.triggerEvent("tabsItemChange",{index})      this.setData({          tabIndex:index      })    }  }})

会议管理

list.json

{    "usingComponents": {      "tabs":"/components/tabs/tabs"    }}

list.wxml

<tabs tabList="{{tabs}}"  bindtabsItemChange="tabsItemChange"></tabs><view style="height: 100rpx;"></view><block wx:for-items="{{lists}}" wx:for-item="item" wx:key="item.id">    <view class="list" data-id="{{item.id}}">        <view class="list-img al-center">            <image class="video-img" mode="scaleToFill" src="{{item.image}}"></image>        </view>        <view class="list-detail">            <view class="list-title"><text>{{item.title}}</text></view>            <view class="list-tag">                <view class="state al-center">{{item.state}}</view>                <view class="join al-center"><text class="list-num">{{item.num}}</text>人报名</view>            </view>            <view class="list-info"><text>{{item.address}}</text>|<text>{{item.time}}</text></view>        </view>    </view></block> 

list.wxss

.mobi-title {    font-size: 12pt;    color: #777;    line-height: 110%;    font-weight: bold;    width: 100%;    padding: 15rpx;    background-color: #f3f3f3;}.mobi-icon {    padding: 0rpx 3rpx;    border-radius: 3rpx;    background-color: #ff7777;    position: relative;    margin-right: 10rpx;}/*list*/.list {    display: flex;    flex-direction: row;    width: 100%;    padding: 0 20rpx 0 0;    border-top: 1px solid #eeeeee;    background-color: #fff;    margin-bottom: 5rpx;    /* border-radius: 20rpx;    box-shadow: 0px 0px 10px 6px rgba(0,0,0,0.1); */}.list-img {    display: flex;    margin: 10rpx 10rpx;    width: 150rpx;    height: 220rpx;    justify-content: center;    align-items: center;}.list-img .video-img {    width: 120rpx;    height: 120rpx;    }.list-detail {    margin: 10rpx 10rpx;    display: flex;    flex-direction: column;    width: 600rpx;    height: 220rpx;}.list-title text {    font-size: 11pt;    color: #333;    font-weight: bold;}.list-detail .list-tag {    display: flex;    height: 70rpx;}.list-tag .state {    font-size: 9pt;    color: #81aaf7;    width: 120rpx;    border: 1px solid #93b9ff;    border-radius: 2px;    margin: 10rpx 0rpx;    display: flex;    justify-content: center;    align-items: center;}.list-tag .join {    font-size: 11pt;    color: #bbb;    margin-left: 20rpx;    display: flex;    justify-content: center;    align-items: center;}.list-tag .list-num {    font-size: 11pt;    color: #ff6666;}.list-info {    font-size: 9pt;    color: #bbb;    margin-top: 20rpx;}.bottom-line{    display: flex;    height: 60rpx;    justify-content: center;    align-items: center;    background-color: #f3f3f3;}.bottom-line text{    font-size: 9pt;    color: #666;}

list.js

// pages/meeting/list/list.jsPage({    /**     * 页面的初始数据     */    data: {      tabs:['会议中','已完成','已取消','全部会议'],      lists: [        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-39-17.png',          'title': '微信小程序会议OA_空空',          'num':'1314',          'state':'进行中',          'time': '02月18日 21:00',          'address': '湖南省——长沙市'        },        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-40-00.png',          'title': '微信小程序会议OA_空空',          'num':'520',          'state':'已结束',          'time': '02月18日 21:00',          'address': '湖南省——长沙市'        },        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-40-45.png',          'title': '微信小程序会议OA_空空',          'num':'666',          'state':'进行中',          'time': '02月18日 21:00',          'address': '湖南省——长沙市'        },        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-40-45.png',          'title': '微信小程序会议OA_空空',          'num':'888',          'state':'已结束',          'time': '02月18日 21:00',          'address': '湖南省——长沙市'        },        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-39-17.png',          'title': '微信小程序会议OA_空空',          'num':'217',          'state':'进行中',          'time': '10月09日 16:59',          'address': '北京市·朝阳区'        }      ],      lists1: [        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-39-17.png',          'title': '微信小程序会议OA_空空',          'num':'304',          'state':'进行中',          'time': '10月09日 17:59',          'address': '深圳市·南山区'        },        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-39-17.png',          'title': '微信小程序会议OA_空空',          'num':'380',          'state':'已结束',          'time': '10月09日 17:39',          'address': '北京市·朝阳区'        },        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-39-17.png',          'title': '微信小程序会议OA_空空',          'num':'500',          'state':'进行中',          'time': '10月09日 17:31',          'address': '大连市'        }      ],      lists2: [        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-39-17.png',          'title': '微信小程序会议OA_空空',          'num':'304',          'state':'进行中',          'time': '10月09日 17:59',          'address': '深圳市·南山区'        },        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-39-17.png',          'title': '微信小程序会议OA_空空',          'num':'380',          'state':'已结束',          'time': '10月09日 17:39',          'address': '北京市·朝阳区'        }      ],      lists3: [        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-39-17.png',          'title': '微信小程序会议OA_空空',          'num':'304',          'state':'进行中',          'time': '10月09日 17:59',          'address': '深圳市·南山区'        },        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-39-17.png',          'title': '微信小程序会议OA_空空',          'num':'380',          'state':'已结束',          'time': '10月09日 17:39',          'address': '北京市·朝阳区'        },        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-39-17.png',          'title': '微信小程序会议OA_空空',          'num':'500',          'state':'进行中',          'time': '10月09日 17:31',          'address': '大连市'        },        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-39-17.png',          'title': '微信小程序会议OA_空空',          'num':'150',          'state':'已结束',          'time': '10月09日 17:21',          'address': '北京市·朝阳区'        },        {          'id': '1',          'image': '/static/persons/Snipaste_2024-02-18_20-39-17.png',          'title': '微信小程序会议OA_空空',          'num':'217',          'state':'进行中',          'time': '10月09日 16:59',          'address': '北京市·朝阳区'        }      ]    },    /**     * 生命周期函数--监听页面加载     */    onLoad(options) {    },    /**     * 生命周期函数--监听页面显示     */    onShow() {    },    tabsItemChange(e){        let tolists;        if(e.detail.index==1){            tolists = this.data.lists1;        }else if(e.detail.index==2){            tolists = this.data.lists2;        }else{            tolists = this.data.lists3;        }        this.setData({            lists: tolists        })    }})

会议OA项目-投票

list.js

// pages/vote/list/list.jsvar app = getApp();Page({    /**     * 页面的初始数据     */    data: {        tabs:['全部','发起的','参与的'],        voteList:[            {                id:1,                title:'微信小程序会议OA_空空',                votes:[                    {                        id:1,                        img:'/static/persons/Snipaste_2024-02-18_20-40-00.png',                        title:'A',                        mem:'A'                    },                    {                        id:2,                        img:'/static/persons/Snipaste_2024-02-18_20-40-45.png',                        title:'B',                        mem:'B'                    }                ]            },            {                id:1,                title:'微信小程序会议OA_空空',                votes:[                    {                        id:1,                        img:'/static/persons/Snipaste_2024-02-18_20-40-00.png',                        title:'B',                        mem:'B'                    },                    {                        id:2,                        img:'/static/persons/Snipaste_2024-02-18_20-40-45.png',                        title:'C',                        mem:'C'                    },                    {                        id:3,                        img:'/static/persons/Snipaste_2024-02-18_20-40-45.png',                        title:'D',                        mem:'X'                    },                    {                        id:4,                        img:'/static/persons/Snipaste_2024-02-18_20-39-17.png',                        title:'F',                        mem:'T'                    }                ]            }        ]    },    /**     * 生命周期函数--监听页面加载     */    onLoad(options) {    },    /**     * 生命周期函数--监听页面初次渲染完成     */    onReady() {    },    /**     * 生命周期函数--监听页面显示     */    onShow() {    },    /**     * 生命周期函数--监听页面隐藏     */    onHide() {    },    /**     * 生命周期函数--监听页面卸载     */    onUnload() {    },    /**     * 页面相关事件处理函数--监听用户下拉动作     */    onPullDownRefresh() {    },    /**     * 页面上拉触底事件的处理函数     */    onReachBottom() {    },    /**     * 用户点击右上角分享     */    onShareAppMessage() {    },    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',                })            }        }    }})

会议OA项目-个人中心

index.wxml

<view class="page-container">    <view class="user-info-container">        <view class="user-info"  bindtap="goLogin">            <image class="user-img" mode="scaleToFill" src="{{userInfo.avatarUrl}}" />            <text class="user-info-name">{{userInfo.nickName}}</text>        </view>        <image class="user-update" src="/static/tabBar/component.png" bindtap='goPages' data-url='/pages/ucenter/user/user'/>    </view>    <view class="boundary" />    <view class="cells-container">        <view class="cell-wrap">            <image class="cell-icon" src="/static/tabBar/sdk.png" />            <text class="cell-text">我主持的会议</text>            <view class="cell-right">                <view class="cell-list-num">{{metting_pubs}}</view>                <view class="cell-arrow"></view>            </view>        </view>        <view class="cell-wrap">            <image class="cell-icon" src="/static/tabBar/sdk.png" />            <text class="cell-text">我参与的会议</text>            <view class="cell-right">                <view class="cell-list-num">{{metting_joins}}</view>                <view class="cell-arrow"></view>            </view>        </view>    </view>    <view class="boundary" />    <view class="cells-container">        <view class="cell-wrap">            <image class="cell-icon" src="/static/tabBar/sdk.png" />            <text class="cell-text">我发布的投票</text>            <view class="cell-right">                <view class="cell-list-num">1</view>                <view class="cell-arrow"></view>            </view>        </view>        <view class="cell-wrap">            <image class="cell-icon" src="/static/tabBar/sdk.png" />            <text class="cell-text">我参与的投票</text>            <view class="cell-right">                <view class="cell-list-num">10</view>                <view class="cell-arrow"></view>            </view>        </view>    </view>    <view class="boundary" />    <view class="cells-container">        <view class="cell-wrap">            <image class="cell-icon" src="/static/tabBar/template.png" />            <text class="cell-text">消息</text>            <view class="cell-right">                <view class="cell-list-num"></view>                <view class="cell-arrow"></view>            </view>        </view>        <view class="cell-wrap">            <image class="cell-icon" src="/static/tabBar/component.png" />            <text class="cell-text">设置</text>            <view class="cell-right">                <view class="cell-list-num"></view>                <view class="cell-arrow"></view>            </view>        </view>    </view></view>

箭头样式:

.cell-arrow {  width: 7px;  height: 7px;  border-width: 1px;  border-color: rgb(136, 136, 136);  border-style: none solid solid none;  transform: rotate(315deg);}

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