• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

免费开放源码审批类小程序项目预约审批端

武飞扬头像
hiddenSharp429
帮助1

第一节:什么构成了微信小程序、创建一个自己的小程序

第二节:微信开发者工具使用教程

第三节:深入了解并掌握小程序核心组件

第四节:初始化云函数和数据库

第五节:云数据库的增删改查

第六节:项目大纲以及制作登录、注册页面

第七节:制作活动申请页面

第八节:活动申请页面的补充

第九节:我的页面制作

第十节:活动详情页面制作

第十一节:活动历史页面制作

第十二节:预约老师页面制作

第十三节:预约历史页面制作

第十四节:活动审批端制作

第十五节:预约审批端制作

目录

目录

前言

成品图

核心思想

实现步骤 

appointmentApproval.wxml

appointmentApproval.wxss

appointmentApproval.js

appointmentApproval3.wxml

appointmentApproval3.wxss

appointmentApproval3.js

getAll2.js

excel.js

getExcel.js

appointmentApproval2.wxml

appointmentApproval2.wxss

appointmentApproval2.js

appointmentDetail.wxml

appointmentDetail.wxss

appointmentDetail.js

题外话


前言

        上一节我们完成了活动审批端的搭建,这一节我们将要完成预约审批端的搭建,也就是本项目最后一个部分的搭建!我们先来看思维大纲~

学新通

        跟活动审批端同理,我们同样要在app.json文件中创建相关的页面。

  1.  
    "pages/appointmentApproval/appointmentApproval",
  2.  
    "pages/appointmentApproval2/appointmentApproval2",
  3.  
    "pages/appointmentApproval3/appointmentApproval3",
  4.  
    "pages/appointmentDetail/appointmentDetail"

         完成了上诉准备工作那么开始搭建吧~


成品图

学新通学新通学新通学新通


核心思想

1.基本样式参照“我的”页面

2.导航栏参照活动审批端

3.需要老师版的预约详情页面

4.通过云开发来实现预约的审批(updata)

5.点击工具箱可实现一键导出预约信息的excel表格


实现步骤 

        该部分的难点在于如何一键导出预约信息的excel表格,其实node.js也支持这个功能,我们只需要稍加点改动就可以了。这里我直接将代码送上了~如果你对代码有疑问可以在底下留言。

        我们将按照思维大纲中 待审批——>已通过——>已驳回 的顺序来依次制作~


appointmentApproval.wxml

  1.  
    <view class="container">
  2.  
    <view class="container_content">
  3.  
    <view class="box">
  4.  
    <view class="mine_application">
  5.  
    <!-- 活动标题 -->
  6.  
    <view class="mine_application_title">
  7.  
    <view>待审批的预约</view><image src="../../icon/rank.png" style="width: 50px;height: 35px;position: absolute; right: 20px; top: 0px;" bindtap="up"></image>
  8.  
    </view>
  9.  
    <block wx:for="{{list}}"></block>
  10.  
    <!-- 活动内容 点击可跳转至详情页面 -->
  11.  
    <view class="mine_application_content" wx:for="{{list}}" >
  12.  
    <view class="event" bindtap="goDetail" data-id="{{item._id}}">
  13.  
    <view class="appointmentTime">{{item.appointment}}</view>
  14.  
    <view class="appointmentInstitute">预约组织:{{item.g1_orderInstitute}}</view>
  15.  
    <view class='appointmentTeacher'>预约老师:{{item.g1_orderTeacher}}</view>
  16.  
    <view class="time">{{item.time}}</view>
  17.  
    <view class="subscriber">申请人:{{item.subscriber}}</view>
  18.  
     
  19.  
    </view>
  20.  
    <!-- 右上角的状态栏 -->
  21.  
    <!-- 用条件渲染来展示多种样式的活动内容 -->
  22.  
    <!-- 状态为3代表已结束,2为已驳回,1为已通过,0为审核中 -->
  23.  
    <block wx:if="{{item.state==0}}">
  24.  
    <!-- 审核中 -->
  25.  
    <view class="state_0">
  26.  
    <view class="state_content">审核中</view>
  27.  
    </view>
  28.  
    <!-- 活动下方的小点 -->
  29.  
    <image src="../../icon/yellow.png" style="width: 11px;height: 11px;position: absolute;left: 15px;bottom: 15px;"></image>
  30.  
    </block>
  31.  
     
  32.  
     
  33.  
     
  34.  
     
  35.  
     
  36.  
    <block wx:if="{{item.state==1}}">
  37.  
    <!-- 已通过 -->
  38.  
    <view class="state_1">
  39.  
    <view class="state_content">已通过</view>
  40.  
    </view>
  41.  
    <!-- 活动下方的小点 -->
  42.  
    <image src="../../icon/green.png" style="width: 11px;height: 11px;position: absolute;left: 15px;bottom: 15px;"></image>
  43.  
    <view class="next_location" >
  44.  
    <button class="button_detail" size="mini" bindtap="goNext" data-id="{{item._id}}">下一步 >
  45.  
    </button>
  46.  
    </view>
  47.  
    </block>
  48.  
     
  49.  
    <block wx:if="{{item.state==2}}">
  50.  
    <!-- 已驳回 -->
  51.  
    <view class="state_2">
  52.  
    <view class="state_content">已驳回</view>
  53.  
    </view>
  54.  
    <!-- 活动下方的小点 -->
  55.  
    <image src="../../icon/red.png" style="width: 11px;height: 11px;position: absolute;left: 15px;bottom: 15px;"></image>
  56.  
    <view class="reject_location">
  57.  
    <button class="button_detail" size="mini">驳回详情 >
  58.  
    </button>
  59.  
    </view>
  60.  
    </block>
  61.  
     
  62.  
     
  63.  
     
  64.  
     
  65.  
    </view>
  66.  
     
  67.  
    </view>
  68.  
    </view>
  69.  
    <view class="tabar">
  70.  
    <view class='goApprovalButton' bindtap="goApprovalPage">
  71.  
    <image src="../../icon/approval.png" style="width: 40px; height: 40px; margin-top: 5px;"></image>
  72.  
    <view class="button_content">待审批</view>
  73.  
    </view>
  74.  
    <view class="goPassButton" bindtap="goPassPage">
  75.  
    <image src="../../icon/pass(1).png" style="width: 40px; height: 40px; margin-top: 5px;"></image>
  76.  
    <view class="button_content">已通过</view>
  77.  
    </view>
  78.  
    <view class="goRejectButton" bindtap="goRejectPage">
  79.  
    <image src="../../icon/reject(1).png" style="width: 40px; height: 40px; margin-top: 5px;"></image>
  80.  
    <view class="button_content">已驳回</view>
  81.  
    </view>
  82.  
    </view>
  83.  
    </view>
  84.  
    </view>
学新通

appointmentApproval.wxss

  1.  
    .mine_application{
  2.  
    margin-left: 15px;
  3.  
    margin-right: 15px;
  4.  
    }
  5.  
    .mine_application_title{
  6.  
    border-bottom: 5rpx solid #A6A6A6;
  7.  
    font-size: 28px;
  8.  
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  9.  
    }
  10.  
     
  11.  
    .mine_application_content{
  12.  
    height: 250px;
  13.  
    width: 100%;
  14.  
    display: flex;
  15.  
    position: relative;
  16.  
    box-shadow: 16rpx 8rpx 24rpx rgba(212,48,48, 0.1);
  17.  
    margin-top: 15px;
  18.  
    border-radius: 15px;
  19.  
     
  20.  
    }
  21.  
    .event{
  22.  
    font-size: 20px;
  23.  
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  24.  
    position: relative;
  25.  
    margin:15px;
  26.  
    width: 90%;
  27.  
    flex: 1;
  28.  
    }
  29.  
    .appointmentTime{
  30.  
    margin-top: 0px;
  31.  
    font-size: 16px;
  32.  
    color: black;
  33.  
    }
  34.  
    .state_0{
  35.  
    float: right;
  36.  
    width: 80px;
  37.  
    height: 40px;
  38.  
    background-color:#FFC300;
  39.  
    border-radius: 0 15px 0 15px;
  40.  
    }
  41.  
    .state_content{
  42.  
    position: relative;
  43.  
    margin-top:10px ;
  44.  
    margin-left: 15px;
  45.  
    font-size: 12;
  46.  
    color: white;
  47.  
    }
  48.  
     
  49.  
    .appointmentInstitute{
  50.  
     
  51.  
    font-size: 20px;
  52.  
    color:#FF5733;
  53.  
    margin-top: 10px;
  54.  
    }
  55.  
    .appointmentTeacher{
  56.  
     
  57.  
    font-size: 20px;
  58.  
    color:#611504;
  59.  
    margin-top: 10px;
  60.  
    }
  61.  
    .time{
  62.  
    margin-top: 10px;
  63.  
    font-size: 18px;
  64.  
    color: #A0A9BD;
  65.  
    }
  66.  
    .goApprovalButton{
  67.  
    position: absolute;
  68.  
    bottom:0px ;
  69.  
    left: 0%;
  70.  
    color:#FFFFFF;
  71.  
    background-color:#FFFFFF;
  72.  
    border-top: 2px solid grey;
  73.  
    width: 33.333%;
  74.  
    height: 70px;
  75.  
    text-align:center;
  76.  
    margin-top: 10px;
  77.  
    }
  78.  
    .goPassButton{
  79.  
    position: absolute;
  80.  
    bottom:0px ;
  81.  
    left: 33.333%;
  82.  
    color:#FFFFFF;
  83.  
    background-color:#FFFFFF;
  84.  
    border-top: 2px solid grey;
  85.  
    width: 33.333%;
  86.  
    height: 70px;
  87.  
    text-align:center;
  88.  
    margin-top: 10px;
  89.  
    }
  90.  
     
  91.  
    .goRejectButton{
  92.  
    position: absolute;
  93.  
    bottom:0px ;
  94.  
    left: 66.666%;
  95.  
    color:#FFFFFF;
  96.  
    background-color:#FFFFFF;
  97.  
    border-top: 2px solid grey;
  98.  
    width: 33.333%;
  99.  
    height: 70px;
  100.  
    text-align:center;
  101.  
    margin-top: 10px;
  102.  
     
  103.  
    }
  104.  
    .button_content{
  105.  
    font-size: 15px;
  106.  
    color: black;
  107.  
    }
  108.  
    .box{
  109.  
    margin-bottom: 50px;
  110.  
    }
  111.  
    .container{
  112.  
    position: relative;
  113.  
    }
  114.  
     
  115.  
    .container_content{
  116.  
    position: relative;
  117.  
    min-height: 100vh;
  118.  
    box-sizing: border-box;
  119.  
    padding-bottom: 60rpx;
  120.  
    padding-top: 0rpx;
  121.  
    }
  122.  
    .subscriber{
  123.  
    font-size: 20px;
  124.  
    font-weight: 100;
  125.  
    color: rgb(23, 6, 175);
  126.  
    }
  127.  
    .tabar{
  128.  
    width: 100%;
  129.  
    text-align: center;
  130.  
    letter-spacing: 4rpx;
  131.  
    position: absolute;
  132.  
    bottom: 0;
  133.  
    }
学新通

appointmentApproval.js

  1.  
    const db = wx.cloud.database()
  2.  
    Page({
  3.  
    data: {
  4.  
    list:[]
  5.  
     
  6.  
    },
  7.  
    onLoad(options) {
  8.  
    console.log("列表携带的值",options)
  9.  
    db.collection("appointment")
  10.  
    .where({
  11.  
    state:0,
  12.  
    })
  13.  
    .get()
  14.  
    .then(res=>{
  15.  
    console.log('查询数据库成功',res.data)
  16.  
    //将返回的res.data里面的值赋值给list
  17.  
    this.setData({
  18.  
    list :res.data,
  19.  
    })
  20.  
    console.log("这是list",this.data.list)
  21.  
    })
  22.  
     
  23.  
    },
  24.  
    up(){
  25.  
    db.collection("appointment")
  26.  
    .where({
  27.  
    state:0,
  28.  
    })
  29.  
    .orderBy('rank','asc')
  30.  
    .get()
  31.  
    .then(res=>{
  32.  
    console.log('升序成功',res.data)
  33.  
    this.setData({
  34.  
    list:res.data
  35.  
    })
  36.  
    })
  37.  
    .catch(err=>{
  38.  
    console.log('升序失败')
  39.  
    })
  40.  
    },
  41.  
    onPullDownRefresh() {
  42.  
     
  43.  
    },
  44.  
    onReachBottom() {
  45.  
     
  46.  
    },
  47.  
    goDetail(e){
  48.  
    console.log("点击了详情页面,将展示活动的id ",e)
  49.  
    wx.navigateTo({
  50.  
    // 跳转到活动详情页面并携带活动id
  51.  
    url: '/pages/appointmentDetail/appointmentDetail?id=' e.currentTarget.dataset.id
  52.  
    })
  53.  
    },
  54.  
     
  55.  
    // 前往待审批页面
  56.  
    goApprovalPage(){
  57.  
    wx.showToast({
  58.  
    title: '您已经在当前页面',
  59.  
    icon:'none'
  60.  
    })
  61.  
    },
  62.  
     
  63.  
    // 前往已通过页面
  64.  
    goPassPage(){
  65.  
    wx.redirectTo({
  66.  
    url: '../appointmentApproval3/appointmentApproval3',
  67.  
    })
  68.  
    },
  69.  
     
  70.  
    // 前往已驳回页面
  71.  
    goRejectPage(){
  72.  
    wx.redirectTo({
  73.  
    url: '../appointmentApproval2/appointmentApproval2',
  74.  
    })
  75.  
    },
  76.  
    })
学新通

appointmentApproval3.wxml

  1.  
    <view class="container">
  2.  
    <view class="container_content">
  3.  
    <view class="box">
  4.  
    <view class="mine_application">
  5.  
    <!-- 活动标题 -->
  6.  
    <view class="mine_application_title">
  7.  
    <view>已通过的预约历史</view><image src="../../icon/work-box.png" style="width: 40px;height: 40px;position: absolute; right: 20px; top: 0px;" bindtap="download"></image>
  8.  
    <image src="../../icon/guide.png" style="width: 40px;height:40px;position: absolute; right: 70px; top:0px;"bindtap="lookAll"></image>
  9.  
    </view>
  10.  
    <block wx:for="{{list}}"></block>
  11.  
    <!-- 活动内容 点击可跳转至详情页面 -->
  12.  
    <view class="mine_application_content" wx:for="{{list}}" >
  13.  
    <view class="event" bindtap="goDetail" data-id="{{item._id}}">
  14.  
    <view class="appointmentTime">{{item.appointment}}</view>
  15.  
    <view class="appointmentInstitute">预约组织:{{item.g1_orderInstitute}}</view>
  16.  
    <view class='appointmentTeacher'>预约老师:{{item.g1_orderTeacher}}</view>
  17.  
    <view class="time">{{item.time}}</view>
  18.  
     
  19.  
    </view>
  20.  
    <!-- 右上角的状态栏 -->
  21.  
    <!-- 用条件渲染来展示多种样式的活动内容 -->
  22.  
    <!-- 状态为3代表已结束,2为已驳回,1为已通过,0为审核中 -->
  23.  
    <block wx:if="{{item.state==1}}">
  24.  
    <!-- 已通过 -->
  25.  
    <view class="state_1">
  26.  
    <view class="state_content">已通过</view>
  27.  
    </view>
  28.  
    <!-- 活动下方的小点 -->
  29.  
    <image src="../../icon/green.png" style="width: 11px;height: 11px;position: absolute;left: 15px;bottom: 15px;"></image>
  30.  
    </block>
  31.  
     
  32.  
    <block wx:if="{{item.state==2}}">
  33.  
    <!-- 已驳回 -->
  34.  
    <view class="state_2">
  35.  
    <view class="state_content">已驳回</view>
  36.  
    </view>
  37.  
    <!-- 活动下方的小点 -->
  38.  
    <image src="../../icon/red.png" style="width: 11px;height: 11px;position: absolute;left: 15px;bottom: 15px;"></image>
  39.  
    </block>
  40.  
     
  41.  
     
  42.  
     
  43.  
     
  44.  
    </view>
  45.  
     
  46.  
    </view>
  47.  
    </view>
  48.  
    <view class="tabar">
  49.  
    <view class='goApprovalButton' bindtap="goApprovalPage">
  50.  
    <image src="../../icon/approval(1).png" style="width: 40px; height: 40px; margin-top: 5px;"></image>
  51.  
    <view class="button_content">待审批</view>
  52.  
    </view>
  53.  
    <view class="goPassButton" bindtap="goPassPage">
  54.  
    <image src="../../icon/pass.png" style="width: 40px; height: 40px; margin-top: 5px;"></image>
  55.  
    <view class="button_content">已通过</view>
  56.  
    </view>
  57.  
    <view class="goRejectButton" bindtap="goRejectPage">
  58.  
    <image src="../../icon/reject(1).png" style="width: 40px; height: 40px; margin-top: 5px;"></image>
  59.  
    <view class="button_content">已驳回</view>
  60.  
    </view>
  61.  
    </view>
  62.  
    </view>
  63.  
    </view>
学新通

appointmentApproval3.wxss

  1.  
    .mine_application{
  2.  
    margin-left: 15px;
  3.  
    margin-right: 15px;
  4.  
    }
  5.  
    .mine_application_title{
  6.  
    border-bottom: 5rpx solid #A6A6A6;
  7.  
    font-size: 28px;
  8.  
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  9.  
    }
  10.  
     
  11.  
    .mine_application_content{
  12.  
    height: 250px;
  13.  
    width: 100%;
  14.  
    display: flex;
  15.  
    position: relative;
  16.  
    box-shadow: 16rpx 8rpx 24rpx rgba(212,48,48, 0.1);
  17.  
    margin-top: 15px;
  18.  
    border-radius: 15px;
  19.  
     
  20.  
    }
  21.  
    .event{
  22.  
    font-size: 20px;
  23.  
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  24.  
    position: relative;
  25.  
    margin:15px;
  26.  
    width: 90%;
  27.  
    flex: 1;
  28.  
    }
  29.  
    .appointmentTime{
  30.  
    margin-top: 0px;
  31.  
    font-size: 16px;
  32.  
    color: black;
  33.  
    }
  34.  
    .state_1{
  35.  
    width: 80px;
  36.  
    height: 40px;
  37.  
    background-color:#43CF7C;
  38.  
    border-radius: 0 15px 0 15px;
  39.  
    z-index: 2;
  40.  
    flex-direction: row;
  41.  
    position: relative;
  42.  
    margin-left: 20px;
  43.  
    }
  44.  
    .state_content{
  45.  
    position: relative;
  46.  
    margin-top:10px ;
  47.  
    margin-left: 15px;
  48.  
    font-size: 12;
  49.  
    color: white;
  50.  
    }
  51.  
    .appointmentInstitute{
  52.  
     
  53.  
    font-size: 20px;
  54.  
    color:#FF5733;
  55.  
    margin-top: 10px;
  56.  
    }
  57.  
    .appointmentTeacher{
  58.  
     
  59.  
    font-size: 20px;
  60.  
    color:#611504;
  61.  
    margin-top: 10px;
  62.  
    }
  63.  
    .time{
  64.  
    margin-top: 10px;
  65.  
    font-size: 18px;
  66.  
    color: #A0A9BD;
  67.  
    }
  68.  
    .goApprovalButton{
  69.  
    position: absolute;
  70.  
    bottom:0px ;
  71.  
    left: 0%;
  72.  
    color:#FFFFFF;
  73.  
    background-color:#FFFFFF;
  74.  
    border-top: 2px solid grey;
  75.  
    width: 33.333%;
  76.  
    height: 70px;
  77.  
    text-align:center;
  78.  
    margin-top: 10px;
  79.  
    }
  80.  
    .goPassButton{
  81.  
    position: absolute;
  82.  
    bottom:0px ;
  83.  
    left: 33.333%;
  84.  
    color:#FFFFFF;
  85.  
    background-color:#FFFFFF;
  86.  
    border-top: 2px solid grey;
  87.  
    width: 33.333%;
  88.  
    height: 70px;
  89.  
    text-align:center;
  90.  
    margin-top: 10px;
  91.  
    }
  92.  
     
  93.  
    .goRejectButton{
  94.  
    position: absolute;
  95.  
    bottom:0px ;
  96.  
    left: 66.666%;
  97.  
    color:#FFFFFF;
  98.  
    background-color:#FFFFFF;
  99.  
    border-top: 2px solid grey;
  100.  
    width: 33.333%;
  101.  
    height: 70px;
  102.  
    text-align:center;
  103.  
    margin-top: 10px;
  104.  
     
  105.  
    }
  106.  
    .button_content{
  107.  
    font-size: 15px;
  108.  
    color: black;
  109.  
    }
  110.  
    .box{
  111.  
    margin-bottom: 50px;
  112.  
    }
  113.  
    .container{
  114.  
    position: relative;
  115.  
    }
  116.  
     
  117.  
    .container_content{
  118.  
    position: relative;
  119.  
    min-height: 100vh;
  120.  
    box-sizing: border-box;
  121.  
    padding-bottom: 60rpx;
  122.  
    padding-top: 0rpx;
  123.  
    }
  124.  
     
  125.  
    /* 有无这个属性都行,之后可能会用到 */
  126.  
    .tabar{
  127.  
    width: 100%;
  128.  
    text-align: center;
  129.  
    letter-spacing: 4rpx;
  130.  
    position: absolute;
  131.  
    bottom: 0;
  132.  
    }
学新通

appointmentApproval3.js

  1.  
    const db = wx.cloud.database()
  2.  
    const _ = db.command
  3.  
    const t = new Date().getTime().toString().slice(0, -3);
  4.  
    Page({
  5.  
    data: {
  6.  
    list:[],
  7.  
    // fileUrl:'',
  8.  
     
  9.  
    },
  10.  
    onLoad(options) {
  11.  
    //调用云函数来突破返回数据库的条数只有20条的限制
  12.  
    wx.cloud.callFunction({
  13.  
    name:'getAll2'
  14.  
    })
  15.  
    .then(res=>{
  16.  
    console.log('成功',res)
  17.  
    this.setData({
  18.  
    list :res.result.data,
  19.  
    })
  20.  
    })
  21.  
    .catch(res=>{
  22.  
    console.log("失败",res);
  23.  
    })
  24.  
     
  25.  
    },
  26.  
    onPullDownRefresh() {
  27.  
     
  28.  
    },
  29.  
    onReachBottom() {
  30.  
     
  31.  
    },
  32.  
    goDetail(e){
  33.  
    console.log("点击了详情页面,将展示活动的id ",e)
  34.  
    wx.navigateTo({
  35.  
    // 跳转到活动详情页面并携带活动id
  36.  
    url: '/pages/appointmentDetail/appointmentDetail?id=' e.currentTarget.dataset.id
  37.  
    })
  38.  
    },
  39.  
    // 前往待审批页面
  40.  
    goApprovalPage(){
  41.  
    wx.redirectTo({
  42.  
    url: '../appointmentApproval/appointmentApproval',
  43.  
    })
  44.  
    },
  45.  
    // 前往已通过页面
  46.  
    goPassPage(){
  47.  
    wx.showToast({
  48.  
    title: '您已经在当前页面',
  49.  
    icon:'none'
  50.  
    })
  51.  
    },
  52.  
    // 前往已驳回页面
  53.  
    goRejectPage(){
  54.  
    wx.redirectTo({
  55.  
    url: '../appointmentApproval2/appointmentApproval2',
  56.  
    })
  57.  
    },
  58.  
    //一键导出excel表格
  59.  
    download(){
  60.  
    let that = this
  61.  
    wx.showModal({
  62.  
    title: '您是否需要导出已通过的预约',
  63.  
    content: '',
  64.  
    success (res) {
  65.  
    if (res.confirm){
  66.  
    console.log('点击了一键导出excel')
  67.  
    //引用了excel的云函数,调取了appointment里面的数据
  68.  
    wx.cloud.callFunction({
  69.  
    name:'excel',
  70.  
    success(res) {
  71.  
    console.log("读取成功", res.result.data)
  72.  
    //将调取的数据存入函数里
  73.  
    that.savaExcel(res.result.data)
  74.  
    },
  75.  
    })
  76.  
    }
  77.  
    else if (res.cancel) {
  78.  
    //取消绑定的操作
  79.  
    }
  80.  
    }
  81.  
    })
  82.  
     
  83.  
    },
  84.  
    //把数据保存到excel里,并把excel保存到云存储
  85.  
    savaExcel(userdata) {
  86.  
    let that = this
  87.  
    //调取getExcel云函数(核心)
  88.  
    wx.cloud.callFunction({
  89.  
    name: "getExcel",
  90.  
    data: {
  91.  
    userdata: userdata
  92.  
    },
  93.  
    success(res) {
  94.  
    console.log("保存成功", res)
  95.  
    //调取获取地址的函数
  96.  
    that.getFileUrl(res.result.fileID)
  97.  
    },
  98.  
    fail(res) {
  99.  
    console.log("保存失败", res)
  100.  
    }
  101.  
    })
  102.  
    },
  103.  
    //获取云存储文件下载地址,这个地址有效期一天
  104.  
    getFileUrl(fileID) {
  105.  
     
  106.  
    let that = this;
  107.  
    wx.cloud.getTempFileURL({
  108.  
    fileList: [fileID],
  109.  
    success: res => {
  110.  
    // 这里的文件下载链接延迟很高,不能实时更新excel里面的数据,故采用文件下载链接拼接时间字符串的形式来达到可下载实时文件的目的
  111.  
    console.log("文件下载链接", res.fileList[0].tempFileURL)
  112.  
    // 这里就是拼接,方法来自 https://blog.csdn.net/sjn0503/article/details/74936613
  113.  
    const finalUrl = `${res.fileList[0].tempFileURL}?${t}`
  114.  
    console.log("实时文件下载链接",finalUrl)
  115.  
    that.setData({
  116.  
    fileUrl: finalUrl
  117.  
    })
  118.  
    //获取到文件下载链接后,使用showModal和setClipboardData来达到给用户复制地址的目的
  119.  
    wx.showModal({
  120.  
    title:'一键导出excel成功',
  121.  
    content:finalUrl,
  122.  
    showCancel:true,
  123.  
    confirmText:'复制地址',
  124.  
    success(res){
  125.  
    if (res.confirm) {
  126.  
    wx.setClipboardData({
  127.  
    data: that.data.fileUrl,
  128.  
    success(res) {
  129.  
    wx.getClipboardData({
  130.  
    success(res) {
  131.  
    console.log(res.data) // data
  132.  
    }
  133.  
    })
  134.  
    }
  135.  
    })
  136.  
    }
  137.  
    }
  138.  
     
  139.  
    })
  140.  
     
  141.  
    },
  142.  
    })
  143.  
    },
  144.  
    })
学新通

其中在js中还用到了getAll2、excel、getExcel 三个云函数

getAll2.js

  1.  
    // 云函数入口文件
  2.  
    //获取所有已结束的活动
  3.  
    const cloud = require('wx-server-sdk')
  4.  
    let id=0;
  5.  
    // 云开发环境初始化
  6.  
    cloud.init({env: 'cloud1-0glmim4o153108f5'})
  7.  
    const db = cloud.database()
  8.  
    const _ = db.command
  9.  
    exports.main = async (event, context) => {
  10.  
    try{
  11.  
    return await db.collection('appointment')
  12.  
    .where(
  13.  
    {
  14.  
    state:1
  15.  
    }
  16.  
    )
  17.  
    //给申请到的预约数据排序
  18.  
    .orderBy('rank','asc')
  19.  
    .get({
  20.  
    success: function (res) {
  21.  
    this.setData({
  22.  
    id:res._id
  23.  
    })
  24.  
    return res
  25.  
    }
  26.  
    })
  27.  
    }
  28.  
    catch(e){
  29.  
    console.error(e)
  30.  
    }
  31.  
    }
学新通

excel.js

  1.  
    //这个函数是用来获取预约集合里面的数据的,并没有存储到excel里
  2.  
    // 云函数入口文件
  3.  
    const cloud = require('wx-server-sdk')
  4.  
     
  5.  
    cloud.init({
  6.  
    env:'cloud1-0glmim4o153108f5'
  7.  
    })
  8.  
     
  9.  
    // 云函数入口函数
  10.  
    exports.main = async (event, context) => {
  11.  
    return await cloud.database().collection('appointment')
  12.  
    .where({
  13.  
    state:1,
  14.  
    })
  15.  
    .orderBy('rank','asc')
  16.  
    .get()
  17.  
    }
学新通

getExcel.js

  1.  
    const cloud = require('wx-server-sdk')
  2.  
    cloud.init({
  3.  
    env: "cloud1-0glmim4o153108f5"
  4.  
    })
  5.  
    //操作excel用的类库
  6.  
    const xlsx = require('node-xlsx');
  7.  
     
  8.  
    // 云函数入口函数
  9.  
    exports.main = async(event, context) => {
  10.  
    try {
  11.  
    let {userdata} = event
  12.  
     
  13.  
    //1,定义excel表格名
  14.  
    let dataCVS = '预约.xlsx'
  15.  
    //2,定义存储数据的
  16.  
    let alldata = [];
  17.  
    let row = ['日期','时间段', '组织', '预约老师','预约事项','预约人','手机号']; //表属性
  18.  
    alldata.push(row);
  19.  
     
  20.  
    for (let key in userdata) {
  21.  
    let arr = [];
  22.  
    arr.push(userdata[key].day);
  23.  
    arr.push(userdata[key].hour);
  24.  
    arr.push(userdata[key].g1_orderInstitute);
  25.  
    arr.push(userdata[key].g1_orderTeacher);
  26.  
    arr.push(userdata[key].content);
  27.  
    arr.push(userdata[key].subscriber);
  28.  
    arr.push(userdata[key].subscriberPhone);
  29.  
    alldata.push(arr)
  30.  
    }
  31.  
    //3,把数据保存到excel里
  32.  
    var buffer = await xlsx.build([{
  33.  
    name: "mySheetName",
  34.  
    data: alldata
  35.  
    }]);
  36.  
    //4,把excel文件保存到云存储里
  37.  
    return await cloud.uploadFile({
  38.  
    cloudPath: dataCVS,
  39.  
    fileContent: buffer, //excel二进制文件
  40.  
    })
  41.  
     
  42.  
    } catch (e) {
  43.  
    console.error(e)
  44.  
    return e
  45.  
    }
  46.  
    }
学新通

appointmentApproval2.wxml

  1.  
    <view class="container">
  2.  
    <view class="container_content">
  3.  
    <view class="box">
  4.  
    <view class="mine_application">
  5.  
    <!-- 活动标题 -->
  6.  
    <view class="mine_application_title">
  7.  
    <view>已驳回的预约历史</view>
  8.  
    </view>
  9.  
    <block wx:for="{{list}}"></block>
  10.  
    <!-- 活动内容 点击可跳转至详情页面 -->
  11.  
    <view class="mine_application_content" wx:for="{{list}}" >
  12.  
    <view class="event" bindtap="goDetail" data-id="{{item._id}}">
  13.  
    <view class="appointmentTime">{{item.appointment}}</view>
  14.  
    <view class="appointmentInstitute">预约组织:{{item.g1_orderInstitute}}</view>
  15.  
    <view class='appointmentTeacher'>预约老师:{{item.g1_orderTeacher}}</view>
  16.  
    <view class="time">{{item.time}}</view>
  17.  
    <view class="subscriber">申请人:{{item.subscriber}}</view>
  18.  
     
  19.  
    </view>
  20.  
    <!-- 右上角的状态栏 -->
  21.  
    <!-- 用条件渲染来展示多种样式的活动内容 -->
  22.  
    <!-- 状态为3代表已结束,2为已驳回,1为已通过,0为审核中 -->
  23.  
    <block wx:if="{{item.state==2}}">
  24.  
    <!-- 已驳回 -->
  25.  
    <view class="state_2">
  26.  
    <view class="state_content">已驳回</view>
  27.  
    </view>
  28.  
    <!-- 活动下方的小点 -->
  29.  
    <image src="../../icon/red.png" style="width: 11px;height: 11px;position: absolute;left: 15px;bottom: 15px;"></image>
  30.  
    </block>
  31.  
     
  32.  
     
  33.  
     
  34.  
     
  35.  
    </view>
  36.  
     
  37.  
    </view>
  38.  
    </view>
  39.  
    <view class="tabar">
  40.  
    <view class='goApprovalButton' bindtap="goApprovalPage">
  41.  
    <image src="../../icon/approval(1).png" style="width: 40px; height: 40px; margin-top: 5px;"></image>
  42.  
    <view class="button_content">待审批</view>
  43.  
    </view>
  44.  
    <view class="goPassButton" bindtap="goPassPage">
  45.  
    <image src="../../icon/pass(1).png" style="width: 40px; height: 40px; margin-top: 5px;"></image>
  46.  
    <view class="button_content">已通过</view>
  47.  
    </view>
  48.  
    <view class="goRejectButton" bindtap="goRejectPage">
  49.  
    <image src="../../icon/reject.png" style="width: 40px; height: 40px; margin-top: 5px;"></image>
  50.  
    <view class="button_content">已驳回</view>
  51.  
    </view>
  52.  
    </view>
  53.  
    </view>
  54.  
    </view>
学新通

appointmentApproval2.wxss

  1.  
    .mine_application{
  2.  
    margin-left: 15px;
  3.  
    margin-right: 15px;
  4.  
    }
  5.  
    .mine_application_title{
  6.  
    border-bottom: 5rpx solid #A6A6A6;
  7.  
    font-size: 28px;
  8.  
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  9.  
    }
  10.  
     
  11.  
    .mine_application_content{
  12.  
    height: 250px;
  13.  
    width: 100%;
  14.  
    display: flex;
  15.  
    position: relative;
  16.  
    box-shadow: 16rpx 8rpx 24rpx rgba(212,48,48, 0.1);
  17.  
    margin-top: 15px;
  18.  
    border-radius: 15px;
  19.  
     
  20.  
    }
  21.  
    .event{
  22.  
    font-size: 20px;
  23.  
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  24.  
    position: relative;
  25.  
    margin:15px;
  26.  
    width: 90%;
  27.  
    flex: 1;
  28.  
    }
  29.  
    .appointmentTime{
  30.  
    margin-top: 0px;
  31.  
    font-size: 16px;
  32.  
    color: black;
  33.  
    }
  34.  
    .state_2{
  35.  
    width: 80px;
  36.  
    height: 40px;
  37.  
    background-color:#FF5733;
  38.  
    border-radius: 0 15px 0 15px;
  39.  
    z-index: 2;
  40.  
     
  41.  
    }
  42.  
    .state_content{
  43.  
    position: relative;
  44.  
    margin-top:10px ;
  45.  
    margin-left: 15px;
  46.  
    font-size: 12;
  47.  
    color: white;
  48.  
    }
  49.  
    .appointmentInstitute{
  50.  
     
  51.  
    font-size: 20px;
  52.  
    color:#FF5733;
  53.  
    margin-top: 10px;
  54.  
    }
  55.  
    .appointmentTeacher{
  56.  
     
  57.  
    font-size: 20px;
  58.  
    color:#611504;
  59.  
    margin-top: 10px;
  60.  
    }
  61.  
    .time{
  62.  
    margin-top: 10px;
  63.  
    font-size: 18px;
  64.  
    color: #A0A9BD;
  65.  
    }
  66.  
    .goApprovalButton{
  67.  
    position: absolute;
  68.  
    bottom:0px ;
  69.  
    left: 0%;
  70.  
    color:#FFFFFF;
  71.  
    background-color:#FFFFFF;
  72.  
    border-top: 2px solid grey;
  73.  
    width: 33.333%;
  74.  
    height: 70px;
  75.  
    text-align:center;
  76.  
    margin-top: 10px;
  77.  
    }
  78.  
    .goPassButton{
  79.  
    position: absolute;
  80.  
    bottom:0px ;
  81.  
    left: 33.333%;
  82.  
    color:#FFFFFF;
  83.  
    background-color:#FFFFFF;
  84.  
    border-top: 2px solid grey;
  85.  
    width: 33.333%;
  86.  
    height: 70px;
  87.  
    text-align:center;
  88.  
    margin-top: 10px;
  89.  
    }
  90.  
     
  91.  
    .goRejectButton{
  92.  
    position: absolute;
  93.  
    bottom:0px ;
  94.  
    left: 66.666%;
  95.  
    color:#FFFFFF;
  96.  
    background-color:#FFFFFF;
  97.  
    border-top: 2px solid grey;
  98.  
    width: 33.333%;
  99.  
    height: 70px;
  100.  
    text-align:center;
  101.  
    margin-top: 10px;
  102.  
     
  103.  
    }
  104.  
    .button_content{
  105.  
    font-size: 15px;
  106.  
    color: black;
  107.  
    }
  108.  
    .box{
  109.  
    margin-bottom: 50px;
  110.  
    }
  111.  
    .container{
  112.  
    position: relative;
  113.  
    }
  114.  
     
  115.  
    .container_content{
  116.  
    position: relative;
  117.  
    min-height: 100vh;
  118.  
    box-sizing: border-box;
  119.  
    padding-bottom: 60rpx;
  120.  
    padding-top: 0rpx;
  121.  
    }
  122.  
     
  123.  
    /* 有无这个属性都行,之后可能会用到 */
  124.  
    .tabar{
  125.  
    width: 100%;
  126.  
    text-align: center;
  127.  
    letter-spacing: 4rpx;
  128.  
    position: absolute;
  129.  
    bottom: 0;
  130.  
    }
学新通

appointmentApproval2.js

  1.  
    const db = wx.cloud.database()
  2.  
    const _ = db.command
  3.  
    Page({
  4.  
    data: {
  5.  
    list:[],
  6.  
    },
  7.  
    onLoad(options) {
  8.  
    console.log("列表携带的值",options)
  9.  
    db.collection("appointment")
  10.  
    .where({
  11.  
    state:2,
  12.  
    })
  13.  
    .get()
  14.  
    .then(res=>{
  15.  
    console.log('查询数据库成功',res.data)
  16.  
    //将返回的res.data里面的值赋值给list
  17.  
    this.setData({
  18.  
    list :res.data,
  19.  
    })
  20.  
    console.log("这是list",this.data.list)
  21.  
    })
  22.  
     
  23.  
    },
  24.  
    onPullDownRefresh() {
  25.  
     
  26.  
    },
  27.  
    onReachBottom() {
  28.  
     
  29.  
    },
  30.  
    goDetail(e){
  31.  
    console.log("点击了详情页面,将展示活动的id ",e)
  32.  
    wx.navigateTo({
  33.  
    // 跳转到活动详情页面并携带活动id
  34.  
    url: '/pages/appointmentDetail/appointmentDetail?id=' e.currentTarget.dataset.id
  35.  
    })
  36.  
    },
  37.  
    // 前往待审批页面
  38.  
    goApprovalPage(){
  39.  
    wx.redirectTo({
  40.  
    url: '../appointmentApproval/appointmentApproval',
  41.  
    })
  42.  
    },
  43.  
    // 前往已通过页面
  44.  
    goPassPage(){
  45.  
    wx.redirectTo({
  46.  
    url: '../appointmentApproval3/appointmentApproval3',
  47.  
    })
  48.  
    },
  49.  
    // 前往已驳回页面
  50.  
    goRejectPage(){
  51.  
    wx.showToast({
  52.  
    title: '您已经在当前页面',
  53.  
    icon:'none'
  54.  
    })
  55.  
    },
  56.  
    })
学新通

appointmentDetail.wxml

  1.  
    <view class="container">
  2.  
    <view class="">
  3.  
    <!-- 预约信息 -->
  4.  
    <view>
  5.  
    <view class="subtitle_font">预约基本信息</view>
  6.  
    <view class="message">
  7.  
    <view class="font">申请预约的组织:{{list.g1_orderInstitute}}</view>
  8.  
    <view class="font">预约的老师:{{list.g1_orderTeacher}}</view>
  9.  
    <view class="font">预约的时间:{{list.appointment}}</view>
  10.  
    <view class="font">发出预约的时间:{{list.time}}</view>
  11.  
    <view class="font">预约事项:{{list.content}}</view>
  12.  
    <view class="font">预约人:{{list.subscriber}}</view>
  13.  
    <view class="font">手机号:{{list.subscriberPhone}}</view>
  14.  
    <block wx:if="{{list.state==2}}">
  15.  
    <view class="font">驳回理由:{{list.rejectReason}}</view>
  16.  
    </block>
  17.  
    </view>
  18.  
    </view>
  19.  
     
  20.  
    </view>
  21.  
    <!-- 条件渲染,只有待审批的活动才能显示 -->
  22.  
    <view>
  23.  
    <block wx:if="{{list.state==0}}">
  24.  
    <view class="subtitle_font">如果驳回,请备注驳回理由</view>
  25.  
    <input bindinput="rejectReason" class="rejectReason" placeholder="驳回的理由"> </input>
  26.  
    <button bindtap="pass" class="button_location1" style="margin-left:2%; width: 48%;">审批通过</button>
  27.  
    <button bindtap="reject" class="button_location2" style="margin-right:2%;width:48%" >审批驳回</button>
  28.  
    </block>
  29.  
    </view>
  30.  
    </view>
学新通

appointmentDetail.wxss

  1.  
    .rejectReason{
  2.  
    margin-top: 15px;
  3.  
    margin-left: 20px;
  4.  
    margin-right:20px;
  5.  
    margin-bottom: 15px;
  6.  
    padding-top: 3px;
  7.  
    padding-bottom: 3px;
  8.  
    padding-left: 15px;
  9.  
    padding-right:15px;
  10.  
    border-radius: 30px;
  11.  
    border: 1px solid #F2E6E6;
  12.  
    }
  13.  
    .inputborder{
  14.  
    margin-top: 15px;
  15.  
    margin-left: 20px;
  16.  
    margin-right:20px;
  17.  
    margin-bottom: 15px;
  18.  
    padding-top: 3px;
  19.  
    padding-bottom: 3px;
  20.  
    padding-left: 15px;
  21.  
    padding-right:15px;
  22.  
    border-radius: 30px;
  23.  
    border: 1px solid #F2E6E6;
  24.  
    }
  25.  
     
  26.  
    .message{
  27.  
    margin-top: 15px;
  28.  
    margin-left: 20px;
  29.  
    margin-right:20px;
  30.  
    margin-bottom: 15px;
  31.  
    padding-top: 3px;
  32.  
    padding-bottom: 3px;
  33.  
    padding-left: 15px;
  34.  
    padding-right:15px;
  35.  
    border-radius: 30px;
  36.  
    border: 1px solid #F2E6E6;
  37.  
    height: 400px;
  38.  
    }
  39.  
    .font{
  40.  
    margin-top: 5px;
  41.  
    font-size: 20px;
  42.  
    font-weight: 100;
  43.  
    }
  44.  
    /* 小标题内容 */
  45.  
    .subtitle_font{
  46.  
    font-size: large;
  47.  
    font-weight: 400;
  48.  
    color: #D43C33;
  49.  
    margin-left: 20px;
  50.  
    }
  51.  
    /* 审批通过 */
  52.  
    .button_location1{
  53.  
    border-radius: 80rpx;
  54.  
    margin-top: 5%;
  55.  
    color:#FFFFFF;
  56.  
    background-color: #D43030;
  57.  
    box-shadow: 16rpx 8rpx 24rpx rgba(212,48,48, 0.35);
  58.  
    float: left;
  59.  
     
  60.  
    }
  61.  
    /* 审批驳回 */
  62.  
    .button_location2{
  63.  
    border-radius: 80rpx;
  64.  
    margin-top: 5%;
  65.  
    color:#FFFFFF;
  66.  
    background-color: #D43030;
  67.  
    box-shadow: 16rpx 8rpx 24rpx rgba(212,48,48, 0.35);
  68.  
    float: right;
  69.  
     
  70.  
    }
  71.  
     
  72.  
    .container{
  73.  
    display: flex;
  74.  
    width: 100%;
  75.  
    height:700px;
  76.  
    flex-direction: column;
  77.  
    justify-content: space-between;
  78.  
    }
学新通

appointmentDetail.js

  1.  
    let eventid = ''
  2.  
    const DB = wx.cloud.database().collection("appointment")
  3.  
    Page({
  4.  
    data:{
  5.  
    list:[],
  6.  
    id:"",
  7.  
    rejectReason:""
  8.  
    },
  9.  
    onLoad(option){
  10.  
    console.log("列表所携带的值",option)
  11.  
    var id = option.id
  12.  
    this.setData({
  13.  
    id :option.id
  14.  
    })
  15.  
     
  16.  
    DB
  17.  
    .doc(id)
  18.  
    .get()
  19.  
    .then(res=>{
  20.  
    this.setData({
  21.  
    list:res.data
  22.  
    })
  23.  
     
  24.  
    })
  25.  
    .catch(res=>{
  26.  
    console.log("活动详情页请求失败",res)
  27.  
    })
  28.  
    },
  29.  
    pass(){
  30.  
    let that = this;
  31.  
    wx.showLoading({
  32.  
    title: '正在上传中……',
  33.  
    mask:true
  34.  
    })
  35.  
    DB.doc(this.data.id)
  36.  
    .update({ // updata指 插入数据库中的userlist表;
  37.  
    //将我们获取到的新值代入
  38.  
    data: {
  39.  
    state:1
  40.  
    },
  41.  
    }).then(res => {
  42.  
    console.log("上传成功", res)
  43.  
    wx.showToast({
  44.  
    title: '成功',
  45.  
    })
  46.  
    wx.navigateTo({
  47.  
    url: '../appointmentApproval/appointmentApproval',
  48.  
    })
  49.  
    .then(()=>{
  50.  
    wx.startPullDownRefresh()
  51.  
    })
  52.  
    })
  53.  
    .catch(err => {
  54.  
    console.log("上传失败", err)
  55.  
    wx.showToast({
  56.  
    title: '失败',
  57.  
    icon:"none"
  58.  
    })
  59.  
    })
  60.  
     
  61.  
     
  62.  
    },
  63.  
     
  64.  
    reject(){
  65.  
    let that = this;
  66.  
    wx.showLoading({
  67.  
    title: '正在上传中……',
  68.  
    mask:true
  69.  
    })
  70.  
    DB.doc(this.data.id)
  71.  
    .update({ // updata指 插入数据库中的userlist表;
  72.  
    //将我们获取到的新值代入
  73.  
    data: {
  74.  
    state:2,
  75.  
    rejectReason: this.data.rejectReason
  76.  
    },
  77.  
    }).then(res => {
  78.  
    console.log("上传成功", res)
  79.  
    wx.showToast({
  80.  
    title: '成功',
  81.  
    })
  82.  
    wx.navigateTo({
  83.  
    url: '../appointmentApproval/appointmentApproval',
  84.  
    })
  85.  
    .then(()=>{
  86.  
    wx.startPullDownRefresh()
  87.  
    })
  88.  
    })
  89.  
    .catch(err => {
  90.  
    console.log("上传失败", err)
  91.  
    wx.showToast({
  92.  
    title: '失败',
  93.  
    icon:"none"
  94.  
    })
  95.  
    })
  96.  
     
  97.  
     
  98.  
    },
  99.  
    rejectReason(event){
  100.  
    console.log("这是驳回输入框里的信息",event.detail.value)
  101.  
    this.setData({
  102.  
    rejectReason:event.detail.value
  103.  
    })
  104.  
    }
  105.  
    })
学新通

题外话

这一系列文章会持续更新,手把手教你从零创建一个小程序项目!并且免费提供源码。如果有什么疑问欢迎大家在底下留言讨论!你的赞和收藏是我最大的动力!! 

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgbjkge
系列文章
更多 icon
同类精品
更多 icon
继续加载