小程序项目中封装通用echarts、时间选择器

315 阅读10分钟

如图:

1641974501(1).png

图1:是时间选择器组件,包括昨日、今日、上月、今年可选

1641974672(1).png

1641974710(1).png

图2和图3:是封装好的通用echarts,此项目是饼状图和柱状图

可参考这篇博客:blog.csdn.net/sinat_33255…

先来讲讲这个通用echarts组件的封装

1、下载echarts

官网下载

此项目的下载文件都放在miniprogram_npm文件夹下:

1641976879(1).png

2、在components文件下建立bar文件夹

1641975593(1).png

3、index.json 中引入echarts 组件

  "component": true,
  "usingComponents": {
    "ec-canvas": "../../miniprogram_npm/ec-canvas/ec-canvas"
  }
}

 4、index.js 中引入echarts 组件及方法

import * as echarts from '../../miniprogram_npm/ec-canvas/echarts';
const computedBehavior = require('miniprogram-computed').behavior
const app = getApp() //获取应用实例
var chart = null;
Component({
  behaviors: [computedBehavior],
  // 接收父组件传来的参数
  properties: {
    // id
    chartLineId: { type: String },
    // canvas的Id
    canvasId: { type: String },
    // 高度
    height: { type: String },
    // 属性
    options: { type: Object }
  },
  /**
   * 组件的初始数据
   */
  data: {
    ec: {
      lazyLoad: true, // 延迟加载
    },
    option: {}
  },
  // 监听 这一步需要注意,博客上是ready()去执行的,但是项目中必须需要observers监听并,原因后面截图讲
  observers: {
    // 监听父组件传来的值,并赋值给option
    'options': function (option) {
      this.setData({
        option: option
      })
      this.getEchartData()
    }
  },
  lifetimes: {
    // ready() {
    //   // this[this.data.chartLineId] = this.selectComponent('#' + this.data.chartLineId);
    //   this.getEchartData();
    // },
    detached(e) {
      this[this.data.chartLineId] = null
      this[this.data.canvasId] = null
    },
  },
  /**
   * 组件的方法列表
   */

  methods: {
    async getEchartData() {
      await this.initChart();
    },
    // 初始化
    initChart() {
      this.selectComponent('.ec-chart').init((canvas, width, height, dpr) => {
         let chart = echarts.init(canvas, null, {
          width: width,
          height: height,
          devicePixelRatio: dpr // new
        })
        chart.setOption(this.getOption())
        return chart
      })
    },
    // 获取配置
    getOption() {
      let option = this.data.option;
      // let option = this.data.options;
      return option;
    },
  }
});

博客上都是没有这一步的,但是项目中这一步是这样写的,为什么这一步需要监听

ecf397217788639730becc9a1afcc1b.png

这个难道就是vue中的watch???

82f4ac9868948885d20e5eeaf04ff3d.png

1641981863(1).png

这里注意:父组件传来的值如果是改变了,需要在子组件监听并重新setData赋值

c4b8f4189b44a7a1f4b3e4260729832.png

没准是视图不刷新,再重新刷新下视图???

反正如果不重新设置 父组件通过ajax获取的值 传递不过来 子组件只能渲染父组件传递的默认值

1641980813(1).png

小程序子组件数据数据不更新blog.csdn.net/qq_40190624…

反正这一步挺坑的。。。记住两点需要监听就行了。。。。

1、官网上说的

一些数据字段被 setData 设置时需要监听

1641981279(1).png 2、小程序子组件数据不更新时,需要监听

3、父组件传来的值如果是改变了,需要在子组件监听并重新setData赋值

5、index.wxml

<!--通用echarts页面-->
<view style="height: {{ height }};width:100%">
  <ec-canvas id="{{ chartLineId }}" canvas-id="{{ canvasId }}" ec="{{ ec }}" options="{{ option }}" class="ec-chart"></ec-canvas>
</view>

6、index.wxss

ec-canvas {
  width: 100%;
  height: 100%;
}

7、父组件目录如下

1641978575(1).png

8、父组件index.json中引入子组件

  "navigationBarTitleText": "手术量",
  "usingComponents": {
    "e-bar": "../../../components/bar/index"
  }
}

9、父组件index.wxml

<!-- 饼图 -->
<e-bar options="{{ options }}" canvasId="{{ canvasId }}" chartLineId="{{ chartLineId }}" height="200px"></e-bar>
<!-- 柱状图 -->
<e-bar options="{{ weekTrendOptions }}" canvasId="{{ canvasBottomId }}" chartLineId="{{ chartLineBottomId }}" height="400px"></e-bar>

原项目代码

1641979787(1).png

9、父组件index.js

这里js太多内容了,怕复制丢失,所以将整个项目的js全部粘贴过来了, 但是只涉及到echarts的option配置部分的,我会截图标出来

// pages/TodayViews/outpIncome/index.js
const computedBehavior = require('miniprogram-computed').behavior
import { surgeryTarget, surgeryDeptDetail, surgeryTrendMonth } from '../../../api/MonthlyReport/surgeryAmount.js'
import dayjs from "dayjs"
import {frmDateWithDateType} from '../../../utils/util'
  Page({
  behaviors: [computedBehavior],
  /**
   * 页面的初始数据
   */
  data: {
    currentDate: '', // 记录时间
    dateType:3, // 时间类型,如果是1,日期格式startDate和endDate就是yyyy(只传年),3格式是yyyy-MM,4格式是yyyy-MM-dd,如果是空,就是 YYYY-MM-DD HH:mm:ss
    searchObj1:{}, // 查询参数
    searchObj2:{}, // 查询参数
    canvasId: 'surgeryCanvasId',
    chartLineId: 'surgeryChartLineId',
    depList:[], // 科室的数组
    pieList:[], // 饼状图的数据
    activeTab: '周趋势分析', // tab页选中值
    surgeryNum:{},//手术例数对象
    // 顶部的
    options: { backgroundColor:'#ecf3fb',
      // 颜色
      color: ['#F8C32B', '#3F8EEB', '#959AAF', '#DDDEE4'],
      // 直角坐标系内绘图网格,单个 grid 内最多可以放置上下两个 X 轴,左右两个 Y 轴
      grid: {
        right: '2%'
      },
      title: {
        text:"手术例数",
        textStyle:{
          color:'#565B6E',
          fontSize: 12
        },
        subtext: "",
        subtextStyle:{
          color:'#3F8EEB',
          fontSize: 14
        },
        left: 'center',
        top: '42%'
      },
      // 提示框
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          type: 'cross'
        }
      },
      // 图例组件
      legend: {
        orient: "vertical",
        left: "left",
        data: ["tongbi", "huanbi"]
      },
      // 图形,例如柱状,线状图
      series: [
        {
          name: 'target',
          type: 'pie',
          radius:['50%', '70%'],
          data: ['1', '2', '3']
        }
      ] },
    //周趋势里面的
    canvasBottomId: 'weekTrendCanvasId',
    chartLineBottomId: 'weekTrendChartLineId',
    weekTrendOptions: {
      color: ['#7ed3f4', '#86c56a', '#f9c14e'],
      // backgroundColor: '#5CA3F5',
      grid:{
        left: '14%', // 调整这个属性
        right: '12%'
      },
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          type: 'cross',
          crossStyle: {
            color: '#999'
          }
        },
        formatter: function (params) {
          var result = params[0].name + "\n";
          params.forEach(function (item) {
            if (item.value) {
              if (item.seriesName == "同比") {
                result +=
                  item.marker +
                  " " +
                  item.seriesName +
                  " : " +
                  item.value +
                  "%\n";
              } else {
                result +=
                  item.marker +
                  " " +
                  item.seriesName +
                  " : " +
                  item.value +
                  "\n";
              }
            } else {
              result +=
                item.marker + " " + item.seriesName + " :  - \n";
            }
          });
          return result;
        },
      },
      legend: {
        data: ['手术例数', '同比']
      },
      xAxis: [
        {
          type: 'category',
          data: [],
          axisPointer: {
            type: 'shadow'
          }
        }
      ],
      yAxis: [
        {
          type: 'value',
          name: '手术例数',
          min: 0,
          max: '',
          axisLabel: {
            interval:0,
            formatter: '{value}'
          }
        },
        {
          type: 'value',
          name: '增长率',
          min: 0,
          max: 25,
          axisLabel: {
            interval:0,
            formatter: '{value}%'
          }
        }
      ],
      series: [
        {
          name: '手术例数',
          type: 'bar',
          data: [],
          // itemStyle:{
          //   color: '#BBDBFF'
          // }
        },
        {
          name: '同比',
          type: 'line',
          data: [],
          // itemStyle: {
          //   color: '#F8C32B'
          // }
        }
        // {
        //   name: '环比',
        //   type: 'line',
        //   // yAxisIndex: 1,
        //   data: [],
        //   itemStyle: {
        //     color: '#49FFE8'
        //   }
        // }
      ],
      timer:'' //定时器
    }
  },
  computed:{
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    // 获取当前时间
    let nowTimer = new Date()
    let day = dayjs(nowTimer).format('YYYY-MM')
    if(this.$store.time.queryDate.length>4){ // 年月格式
      this.setData({
        dateType:3
      })
    }else{
      this.setData({
        dateType:1
      })
    }
    // 参数是当前月
    this.setData({
      searchObj1:{
        "dateType": this.data.dateType,
        "endDate": this.$store.time.queryDate.substr(0,7),
        "startDate": this.$store.time.queryDate.substr(0,7)
      },
      searchObj2:{
        "year": this.$store.time.queryDate.substr(0,4)
      },
      currentDate: this.$store.time.queryDate.substr(0,4)
    })
    //手术指标
    this.surgeryTarget()
    // 科室明细
    this.surgeryDeptDetail()
    // 渲染柱状图
    this.surgeryTrendMonth()  // 1个参数year

  },

  // 子组件绑定的方法
  prevDay(e){
    
    // 判断 子组件时间控件里面,是不是有值
    if (e && e.detail) {
     const {start, end} =  frmDateWithDateType(e.detail.currentDate, 3)
      this.setData({
        searchObj1:{
          "dateType": 3,
          "endDate": end,
          "startDate": start
        },
        searchObj2:{
          "year": end.substr(0,4),
        },
        // searchObj3:{
        //   "leftMonth": day.substr(5,7)
        // },
        currentDate: end.substr(0,4),  // 当年
        activeTab: '趋势分析'
      })
    }
    //手术指标
    this.surgeryTarget()
    // 科室明细
    this.surgeryDeptDetail()
    // 渲染柱状图
    this.surgeryTrendMonth()

  },
  // 日期直接选择时间
  onConfim(e){
    console.log('e.detail.startDate----------', e.detail.startDate, this)
    const {start, end} =  frmDateWithDateType(e.detail.currentDate, 3)
    // 调用
    this.setData({
      searchObj1:{
        "dateType": 3,
        "endDate": end,
        "startDate": start
      },
      searchObj2:{
        "year": end.substr(0,4),
      },
      // searchObj3:{
      //   "leftMonth": day.substr(5,7)
      // },
      currentDate: end.substr(0,4),  // 当年
      activeTab: '趋势分析'
    })
    this.surgeryTarget()
    this.surgeryDeptDetail()
    this.surgeryTrendMonth()  
  },
  // 今年按钮点击事件
  yearHandle(e){
    this.setData({
      dateType: 1
    })
    // 调用手术指标方法
    this.setData({
      searchObj1:{
        "dateType": this.data.dateType,
        "endDate": e.detail.startDate,
        "startDate": e.detail.endDate
      },
      searchObj2:{
        "year": e.detail.startDate
      },
      // searchObj3:{
      //   "leftMonth": day.substr(5,7)
      // },
      currentDate: e.detail.startDate,  // 当年
      activeTab: '趋势分析'
    })
    //手术指标
    this.surgeryTarget()
    // 科室明细
    this.surgeryDeptDetail()
    // 渲染柱状图
    this.surgeryTrendMonth()  
  },
  // // tab切换   可以不要
  // onChange(event) {
  //   this.setData({
  //     activeTab: event.detail.title
  //   })
  //   if (event.detail.name === 'a') {
  //     console.log('this.searchObj.startDate----------', this.data.currentDate)
  //     // 调用手术指标方法
  //     this.setData({
  //       searchObj2:{
  //         "year": this.data.currentDate
  //       }
  //     })
  //     // 渲染柱状图
  //     this.surgeryTrendMonth()
  //   }
  //   console.log(event.detail.title, '==========event')
  // },
  /**
   * 手术指标
   * @returns {Promise<void>}
   */
  async surgeryTarget() {
    let res = await surgeryTarget(this.data.searchObj1)
    if (res && res.data.code === 200) {
      const { data } = res.data
      // 封装echars数据
      let arr = [
        { value: data.fourSurgeryNum, name: '四级手术' },
        { value: data.threeSurgeryNum, name: '三级手术' },
        { value: data.twoSurgeryNum, name: '二级手术' },
        { value: data.oneSurgeryNum, name: '一级手术' }
      ]
      this.data.options.series[0].data = arr
      this.data.options.title.subtext = data.surgeryNum + '例'
      this.setData({
        options: this.data.options,
        surgeryNum: data
      })
    }
  },
  /**
   * 手术科室明细
   * @returns {Promise<void>}
   */
  async surgeryDeptDetail(){
    let res = await surgeryDeptDetail(this.data.searchObj1)
    if (res && res.data.code === 200) {
      const { data } = res.data
      this.setData({
        depList: data
      })
    }
  },
  /**
   * 月报-手术趋势分析
   * @returns {Promise<void>}
   */
  async surgeryTrendMonth() {
    let res = await surgeryTrendMonth(this.data.searchObj2)
    if (res && res.data.code === 200) {
      const { data } = res.data
      let monthArr = [] // 月份
      let surgeryNumArr = [] // 手术例数
      // let surgeryNumRatioLinkArr = [] // 环比
      let surgeryNumRatioYearArr = [] // 同比
      data.forEach(item => {
        monthArr.push(item.date)
        surgeryNumArr.push(item.surgeryNum)
        // surgeryNumRatioLinkArr.push(item.surgeryNumRatioLink)
        surgeryNumRatioYearArr.push(item.surgeryNumRatioYear)
      })
      console.log('获取到的趋势----------', data)
      // 封装echars数据
      /**
       *   this.data.weekTrendOptions.xAxis[0].data = monthsAry
       this.data.weekTrendOptions.series[0].data = outPAccountAry
       this.data.weekTrendOptions.series[1].data = compareAry
       this.data.weekTrendOptions.series[2].data = linkAry
       * @type {[]}
       */

      let maxSurgeryNumArr = Math.max.apply(Math, surgeryNumArr) + 50
      // 同比环比中的最大值
      // 同比最大值
      let maxYear = Math.max.apply(Math, surgeryNumRatioYearArr)
      // 同比最小值
      let minYear = Math.min.apply(Math, surgeryNumRatioYearArr);
      // // 环比最大值
      // let maxMonth = Math.max.apply(Math, surgeryNumRatioLinkArr)
      // // 环比最小值
      // let minMonth = Math.min.apply(Math, surgeryNumRatioLinkArr);
      // // 两个中的最大值
      // let maxYearMonth = Math.max.apply(Math, [maxYear, maxMonth]) + 5
      // // 两个中最小值
      // let minYearMonth = Math.max.apply(Math, [minYear, minMonth]) - 5

      // x轴的月份数据
      this.data.weekTrendOptions.xAxis[0].data = monthArr
      // 这个是柱状图数据
      this.data.weekTrendOptions.series[0].data = surgeryNumArr
      // 同比
      this.data.weekTrendOptions.series[1].data = surgeryNumRatioYearArr
      // 环比
      // this.data.weekTrendOptions.series[2].data = surgeryNumRatioLinkArr
      this.data.weekTrendOptions.yAxis[0].max = maxSurgeryNumArr  //
      // this.data.weekTrendOptions.yAxis[1].max = maxYearMonth  // 增长率最大
      this.data.weekTrendOptions.yAxis[1].max = maxYear  // 增长率最大
      this.setData({
        weekTrendOptions: this.data.weekTrendOptions
      })
    }
  }
})

1642061234.png

1642061398(1).png

1642061524(1).png

时间选择器组件的封装

首先先看几篇文章:

微信小程序全局状态管理 实现响应式的 juejin.cn/post/684490…

微信小程序:全局状态管理mobx-miniprogram blog.csdn.net/mouday/arti…

日期时间工具(dayjs)的使用blog.csdn.net/u014225733/…

微信小程序扩展能力(201912) www.bookstack.cn/read/minipr…

Object.defineProperty在小程序中的简单使用 blog.csdn.net/weixin_4548…

组件目录如下:

1642065463(1).png

timepicker.wxml

<view class="grid items-center mb-20 bg-white grid-template-columns">
  <view class="ml-40">
    <van-button
      wx:if="{{ layout === 'day' }}"
      type="default"
      size="small"
      round
      bind:tap="onTap"
      custom-class="float-left"
    >昨日</van-button>
    <van-button
      wx:if="{{ layout === 'month' }}"
      type="default"
      size="small"
      round
      bind:tap="onTap"
    >上月</van-button>
  </view>

  <view class="pick-container">
    <van-cell
      custom-class="h-80 m-w-max"
      title="{{ displayDate }}"
      is-link
      arrow-direction="down"
      bind:click="showPopup"
    ></van-cell>
  </view>

  <view class="flex justify-end mr-40">
    <van-button
      wx:if="{{ layout === 'day' }}"
      type="default"
      size="small"
      round
      bind:tap="switchCurrentDay"
      custom-class="float-left"
    >今日</van-button>
    <van-button
      wx:if="{{ showYear === 'true' }}"
      type="default"
      size="small"
      round
      bind:click="onTapYear"
    >今年</van-button>
  </view>
</view>

<van-popup
  show="{{ datePickerShow }}"
  position="bottom"
  custom-style="height: 40%;"
  close-on-click-overlay="{true}"
  bind:close="onClosePopup"
>
  <van-datetime-picker
    wx:if="{{ layout === 'day' }}"
    type="date"
    size="small"
    value="{{ currentDate }}"
    maxDate="{{ maxDate }}"
    bind:confirm="onConfirm"
    bind:cancel="onCancel"
  ></van-datetime-picker>
  <van-datetime-picker
    wx:if="{{ layout === 'month' }}"
    type="year-month"
    value="{{ currentDate }}"
    maxDate="{{ maxDate }}"
    bind:confirm="onConfirm"
    bind:cancel="onCancel"
  ></van-datetime-picker>
</van-popup>

timepicker.js

// components/timepicker/timepicker.js
const computedBehavior = require('miniprogram-computed').behavior
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
import { store } from '../../store/index'
import dayjs from 'dayjs'
Component({
  behaviors: [storeBindingsBehavior, computedBehavior],
  options: {
    styleIsolation: 'apply-shared'
  },
  /**
   * 组件的属性列表
   */
  properties: {
    layout: String,
    showYear: String,
    idNeedTime: Boolean, // 是否需要日期格式化后面的时分秒
    dateType: Number // 时间类型,用来确定日期格式的比如是yyyy,还是YYYY-MM
  },
  /**
   * 组件的初始数据
   */
  data: {
    datePickerShow: false,
    currentDate: new Date().getTime(),
    maxDate: new Date().getTime(),
    startDate: '', //开始日期
    endDate: '' // 结束日期
  },
  storeBindings: {
    store,
    fields: {
      queryDateReal: () => store.realTime.queryDate,
      queryDate: () => store.time.queryDate
    },
    actions: {
      update: () => store.time.update
    }
  },
  computed: {
    isDay(data) {
      return data.layout === 'day'
    },
    /**
     * timepicker展示时间
     */    
    displayDate(data) {
      return data.isDay ? data.queryDateReal : data.queryDate
    }
  },
  observers: {
    dateType: function (oldVal, newVal) {
      console.log('oldVal-------', oldVal, 'newVal--------', newVal)
    }
  },
  lifetimes: {
    attached() {
      // console.log('layout', this.properties.layout)
    }
  },
  /**
   * 组件的方法列表
   */
  methods: {
    showPopup() {
      this.setData({
        datePickerShow: true
      })
    },
    onClosePopup() {
      this.setData({
        datePickerShow: false
      })
    },
    /**
     * 修改时间
     * @param {Date} detail 时间戳
     */
    onConfirm({ detail }) {
      // console.log('detail1111: ', detail);
      let unit = this.properties.layout
      let format = this.data.isDay ? 'YYYY-MM-DD' : 'YYYY-MM'
      let date = dayjs(detail).format(format)
      store.time.update(date)
      this.setData({
        datePickerShow: false
      })
      this.triggerEvent('confirm', { currentDate: detail })
    },
    onCancel() {
      this.setData({
        datePickerShow: false
      })
    },
    /**
     * @description: 点击昨日/前一月触发
     */    
    onTap() {
      let unit = this.properties.layout
      let format = this.data.isDay ? 'YYYY-MM-DD' : 'YYYY-MM'
      console.log('store.time.queryDate.length: ', store.time.queryDate.length);
      let time = this.data.isDay ? store.realTime.queryDate : store.time.queryDate
      let date = dayjs(time).subtract(1, unit).format(format)
      // 更新store内容 实时/月报
      this.data.isDay ? store.realTime.update(date) : store.time.update(date)
      this.triggerEvent('prev-date', { currentDate: date }, {})
    },
    // 点击年份
    onTapYear() {
      // 获取今年 1的格式是 YYYY
      console.log('年份的格式时间-------', this.data.dateType)
      let date = new Date()
      // 年份不适合
      let start = dayjs(date).startOf('month').format('YYYY')
      let end = dayjs(date).endOf('month').format('YYYY')
      console.log('111', end)
      // 更新store内容
      store.time.update(dayjs().format('YYYY'))
      this.triggerEvent('year-handle', { startDate: start, endDate: end })
    },
    /**
     * @description: 将时间切换为当天
     */
    switchCurrentDay() {
      store.realTime.update(dayjs().format('YYYY-MM-DD'))
      this.triggerEvent('curr-date')
    }
  }
})

timepicker.json

  "component": true,
  "usingComponents": {
    "van-cell": "@vant/weapp/cell/index",
    "van-button": "@vant/weapp/button/index",
    "van-datetime-picker": "@vant/weapp/datetime-picker/index",
    "van-popup": "@vant/weapp/popup/index"
  }
}

timepicker.wxss

/* components/timepicker/timepicker.wxss */
.year {
  position: absolute;
  right: 10rpx;
  top: 26rpx;
  z-index: 33;
}
.grid-template-columns {
  grid-template-columns: 1fr 1.1fr 1fr;
}
.ml-40 {
  margin-left: 40rpx;
}
.pick-container{
  min-width: 200rpx;
}
.m-w-max {
  min-width: max-content;
}

建立一个store文件夹,如下 1644400525(1).png store/index.js

import { observable, action } from 'mobx-miniprogram'
import dayjs from 'dayjs'
export const store = observable({
  /**
   * @description: 月报时间
   */  
  time: {
    _queryDate: dayjs().format('YYYY-MM'),
    get queryDate() {
      console.log('月报全局时间', this._queryDate)
      return this._queryDate
    },
    update: action(function (val) {
      this._queryDate = val
    })
  },
  /**
   * @description: 实时概览时间
   */  
  realTime: {
    _queryDate: dayjs().format('YYYY-MM-DD'),
    get queryDate() {
      console.log('实时全局时间', this._queryDate)
      return this._queryDate
    },
    update: action(function (val) {
      this._queryDate = val
    })
  }
})

app.js这里使用Object.defineProperty返回store,把store挂载到原型链上去,为了通过this.$store访问store

 * WeChat API 模块
 * @type {Object}
 * 用于将微信官方`API`封装为`Promise`方式
 */
const wechat = require('./utils/wechat.js')
/**
 *  API 模块
 * @type {Object}
 */

const utils = require('./utils/util.js')
import { store } from './store/index.js'

App({
  // 注册小程序
  onLaunch() {
    this.setStatusBarHeight()
    this.setNavBar()
    console.log('启动')
    if (!wx.getStorageSync('token')) {
      wx.redirectTo({
        url: 'pages/guidePage/index'
      })
    }
    Object.defineProperty(Object.prototype, '$store', {
      get() {
        return store
      }
    })
  },
  //设置系统状态栏高度
  setStatusBarHeight() {
    try {
      const res = wx.getSystemInfoSync()
      this.data.globalData.statusBarHeight = res.statusBarHeight
    } catch (error) {
      console.log(error)
    }
  },
  //设置导航栏height
  setNavBar() {
    let res = wx.getMenuButtonBoundingClientRect()
    let navBarPadding = (res.top - this.data.setStatusBarHeight) * 2
    this.data.globalData.navBarHeight = res.height + navBarPadding
  },
  data: {
    globalData: {
      statusBarHeight: 20,
      navBarHeight: 44
    }
  },

  /**
   * WeChat API
   */
  wechat,

  /**
   *  API 接口
   */
  utils
})

在其它页面中使用这个日期组件

1644400777(1).png

json中引入组件

{
  "backgroundTextStyle": "dark",
  "enablePullDownRefresh": true,
  "navigationBarTitleText": "院长月报",
  "usingComponents": {
    "time-picker": "../../../components/timepicker/timepicker",
    "van-icon": "@vant/weapp/icon/index"
  }
}

wxml中使用

<!--院长月报  首页-->
<view>
    <!-- 时间控件 -->
    <view class="topTime bgWhite">
        <time-picker layout="month" showYear="true" idNeedTime="{{false}}" dateType="{{dateType}}" bind:prev-date="prevDay" bind:year-handle="yearHandle" bind:confirm="onConfim"></time-picker>
    </view>
    <view class="item" bindtap="open" data-chart="">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">总收入</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{ pageInfo.totalAccount || 0 }}(万元)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.totalAccountCompare>0?'add':'pre'}}">{{pageInfo.totalAccountCompare}}<text>{{pageInfo.totalAccountCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.totalAccountLink>0?'add':'pre'}}">{{pageInfo.totalAccountLink}}<text>{{pageInfo.totalAccountLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
    </view>
    <view class="item" bindtap="open" data-chart="outpIncome" data-time="{{searchObj1.endDate}}">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">门急诊</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{ pageInfo.outPAccount || 0 }}(万元)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.outPAccountCompare>0?'add':'pre'}}">{{pageInfo.outPAccountCompare}}<text>{{pageInfo.outPAccountCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.outPAccountLink>0?'add':'pre'}}">{{pageInfo.outPAccountLink}}<text>{{pageInfo.outPAccountLink>0?'↑':'↓'}}</text></text></text>
            </view>
            
            <!-- <icon slot="icon" class="icon_ring" /> -->
        </view>
        <van-icon name="arrow" class="arrow"/>
    </view>
    <view class="item" bindtap="open" data-chart="inpIncome">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">住院</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{ pageInfo.inPAccount || 0 }}(万元)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.inPAccountCompare>0?'add':'pre'}}">{{pageInfo.inPAccountCompare}}<text>{{pageInfo.inPAccountCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.inPAccountLink>0?'add':'pre'}}">{{pageInfo.inPAccountLink}}<text>{{pageInfo.inPAccountLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
        <van-icon name="arrow" class="arrow"/>
    </view>
    <view class="item" bindtap="open" data-chart="stuffProportion">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">住院手术材料占比</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{ pageInfo.surgicalMaterialsRatio || 0 }} (%)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.surgicalMaterialsCompare>0?'add':'pre'}}">{{pageInfo.surgicalMaterialsCompare}}<text>{{pageInfo.surgicalMaterialsCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.surgicalMaterialsLink>0?'add':'pre'}}">{{pageInfo.surgicalMaterialsLink}}<text>{{pageInfo.surgicalMaterialsLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
        <van-icon name="arrow" class="arrow"/>
    </view>
    <view class="item">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">全院药占比</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{ pageInfo.totalDrugIncomeRatio || 0 }} (%)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.totalDrugIncomeCompare>0?'add':'pre'}}">{{pageInfo.totalDrugIncomeCompare}}<text>{{pageInfo.totalDrugIncomeCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.totalDrugIncomeLink>0?'add':'pre'}}">{{pageInfo.totalDrugIncomeLink}}<text>{{pageInfo.totalDrugIncomeLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
    </view>
    <view class="item" bindtap="open" data-chart="outpatientServiceDrugProportion">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">门诊药占比</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{ pageInfo.outpatientDrugIncomeRatio || 0 }} (%)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.outpatientDrugIncomeCompare>0?'add':'pre'}}">{{pageInfo.outpatientDrugIncomeCompare}}<text>{{pageInfo.outpatientDrugIncomeCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.outpatientDrugIncomeLink>0?'add':'pre'}}">{{pageInfo.outpatientDrugIncomeLink}}<text>{{pageInfo.outpatientDrugIncomeLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
        <van-icon name="arrow" class="arrow"/>
    </view>
    <view class="item" bindtap="open" data-chart="inpIncomeDrug">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">住院药占比</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{ pageInfo.inpatientDrugIncomeRatio || 0 }} (%)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.inpatientDrugIncomeCompare>0?'add':'pre'}}">{{pageInfo.inpatientDrugIncomeCompare}}<text>{{pageInfo.inpatientDrugIncomeCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.inpatientDrugIncomeLink>0?'add':'pre'}}">{{pageInfo.inpatientDrugIncomeLink}}<text>{{pageInfo.inpatientDrugIncomeLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
        <van-icon name="arrow" class="arrow"/>
    </view>
    <view class="item" bindtap="open" data-chart="regNum">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">门急诊挂号人次</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{ pageInfo.outPCount || 0 }}(人次)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.outPCountCompare>0?'add':'pre'}}">{{pageInfo.outPCountCompare}}<text>{{pageInfo.outPCountCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.outPCountLink>0?'add':'pre'}}">{{pageInfo.outPCountLink}}<text>{{pageInfo.outPCountLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
        <van-icon name="arrow" class="arrow"/>
    </view>
    <view class="item" bindtap="open" data-chart="inpNum">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">入院人数</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{ pageInfo.admissionCount || 0 }}(人数)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.admissionCountCompare>0?'add':'pre'}}">{{pageInfo.admissionCountCompare}}<text>{{pageInfo.admissionCountCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.admissionCountLink>0?'add':'pre'}}">{{pageInfo.admissionCountLink}}<text>{{pageInfo.admissionCountLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
        <van-icon name="arrow" class="arrow"/>
    </view>
    <view class="item" bindtap="open" data-chart="outpNum">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">出院人数</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{pageInfo.leaveCount || 0}}(人数)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.leaveCountCompare>0?'add':'pre'}}">{{pageInfo.leaveCountCompare}}<text>{{pageInfo.leaveCountCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.leaveCountLink>0?'add':'pre'}}">{{pageInfo.leaveCountLink}}<text>{{pageInfo.leaveCountLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
        <van-icon name="arrow" class="arrow"/>
    </view>
    <view class="item" bindtap="open" data-chart="outpIncomeCost">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">门急诊次均费用</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{ pageInfo.outPCountFee || 0 }}(元)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.outPCountFeeCompare>0?'add':'pre'}}">{{pageInfo.outPCountFeeCompare}}<text>{{pageInfo.outPCountFeeCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.outPCountFeeLink>0?'add':'pre'}}">{{pageInfo.outPCountFeeLink}}<text>{{pageInfo.outPCountFeeLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
        <van-icon name="arrow" class="arrow"/>
    </view>
    <view class="item" bindtap="open" data-chart="inpIncomeCost">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">住院次均费用</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{ pageInfo.inPCountFee || 0 }}(元)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.inPCountFeeCompare>0?'add':'pre'}}">{{pageInfo.inPCountFeeCompare}}<text>{{pageInfo.inPCountFeeCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.inPCountFeeLink>0?'add':'pre'}}">{{pageInfo.inPCountFeeLink}}<text>{{pageInfo.inPCountFeeLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
        <van-icon name="arrow" class="arrow"/>
    </view>
    <view class="item" bindtap="open" data-chart="surgeryAmount">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">手术例数</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{pageInfo.surgeryNum || 0}}(例数)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.surgeryNumCompare>0?'add':'pre'}}">{{pageInfo.surgeryNumCompare}}<text>{{pageInfo.surgeryNumCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.surgeryNumLink>0?'add':'pre'}}">{{pageInfo.surgeryNumLink}}<text>{{pageInfo.surgeryNumLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
        <van-icon name="arrow" class="arrow"/>
    </view>
    <view class="item" bindtap="open" data-chart="test">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">检验量</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{pageInfo.medicalTestNum || 0}}(例数)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.medicalTestNumCompare>0?'add':'pre'}}">{{pageInfo.medicalTestNumCompare}}<text>{{pageInfo.medicalTestNumCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.medicalTestNumLink>0?'add':'pre'}}">{{pageInfo.medicalTestNumLink}}<text>{{pageInfo.medicalTestNumLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
        <van-icon name="arrow" class="arrow"/>
    </view>
    <view class="item" bindtap="open" data-chart="check">
        <view class="l">
            <view class="box">
                <text class="icon_ring"></text>
                <text class="name">检查量</text>
            </view>
        </view>
        <view class="r">
            <view class="sum">{{pageInfo.inspectNum || 0}}(例数)</view>
            <view class="num">
                <text>同比 <text class="{{pageInfo.inspectNumCompare>0?'add':'pre'}}">{{pageInfo.inspectNumCompare}}<text>{{pageInfo.inspectNumCompare>0?'↑':'↓'}}</text></text></text>
                <text wx:if="{{ isShow }}" class="ml">环比 <text class="{{pageInfo.inspectNumLink>0?'add':'pre'}}">{{pageInfo.inspectNumLink}}<text>{{pageInfo.inspectNumLink>0?'↑':'↓'}}</text></text></text>
            </view>
        </view>
        <van-icon name="arrow" class="arrow"/>
    </view>
</view>

主要是这部分代码

<time-picker layout="month" showYear="true" idNeedTime="{{false}}" dateType="{{dateType}}" bind:prev-date="prevDay" bind:year-handle="yearHandle" bind:confirm="onConfim"></time-picker>

js

// pages/MonthlyReport/index/index.js
//获取应用实例
import dayjs from 'dayjs'
const computedBehavior = require('miniprogram-computed').behavior
import {frmDateWithDateType} from '../../../utils/util'
import { getTotalInfoByDate } from '../../../api/MonthlyReport/index'
const app = getApp()
Page({
   behaviors: [computedBehavior],
    /**
     * 页面的初始数据
     */
    data: {
        pageInfo: {}, // 页面显示数据
        // queryDate: dayjs().format('YYYY-MM-DD'),
        currentDate: '', // 记录时间
        dateType:3, // 时间类型,如果是1,日期格式startDate和date就是yyyy(只传年),3/2格式是yyyy-MM,4格式是yyyy-MM-dd,如果是空,就是 YYYY-MM-DD HH:mm:ss
        searchObj1:{}, // 查询参数
        isShow:true
    },

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad: function (options) {
      
    },
    // onTabItemTap(item){
    //   item.index === 1 && this.$store.time.update(dayjs().format('YYYY-MM'))
    // },

    /**
     * 生命周期函数--监听页面初次渲染完成
     */
    async onReady () {
        // 获取当前时间
        let nowTimer = new Date()
        let day = dayjs(nowTimer).format('YYYY-MM')
        // 参数是当前月
        this.setData({
          searchObj1:{
            "dateType": this.data.dateType,
            "endDate": day,
            "startDate": day
          },
          currentDate: day.substr(0,4),  // 当年
          // currentMon: day.substr(5,7)   // 月份
        })
        // await this.getData() // 基本信息 3个参数 dateType/endDate/startDate
    },

    /**
     * 生命周期函数--监听页面显示
     */
    onShow: function () {
      this.getData()
    },

    /**
     * 生命周期函数--监听页面隐藏
     */
    onHide: function () {

    },

    /**
     * 生命周期函数--监听页面卸载
     */
    onUnload: function () {

    },

    /**
     * 页面相关事件处理函数--监听用户下拉动作
     */
    onPullDownRefresh: function () {
      this.onLoad()
    },

    /**
     * 页面上拉触底事件的处理函数
     */
    onReachBottom: function () {

    },

    /**
     * 用户点击右上角分享
     */
    onShareAppMessage: function () {

    },

    open: function(e) {
        let chart = e.currentTarget.dataset.chart
        let time = e.currentTarget.dataset.time
        wx.navigateTo({
            url: '../'+chart+'/index?time=' + time
        //   url: '../deanMonthReport/' + e.target.dataset.chart + '/' + "index"
        })
    },

    /**
   * 首页获取数据
   * @param {*} param0
   */
  async getData() {
    console.log('this.$store.time.queryDate: ', this.$store.time.queryDate);
    console.log('this.data.dateType: ', this.data.dateType);
    let res = await getTotalInfoByDate({
      dateType: this.data.dateType,
      endDate: this.$store.time.queryDate,
      startDate: this.$store.time.queryDate
    })
    if (res.data.code === 200) {
      this.setData({
        pageInfo: res.data.data
      })
      // console.log(123)
      // console.log(this.data.pageInfo)
    }
  },
      /**
   * 前一日
   * @param {object} detail {currentDate}
   */
  async prevDay(e) {
    this.setData({
      dateType: 3,
    })
    
    // 判断 子组件时间控件里面,是不是有值
    if (e && e.detail) {
      const {start, end} =  frmDateWithDateType(e.detail.currentDate, 3)
      this.setData({
        searchObj1:{
          "dateType": 3,
          "endDate": end,
          "startDate": start
        },
        isShow:true,
        currentDate: end.substr(0,4),  // 当年
        activeTab: 'b'
      })
    }
    this.getData()
  },
    /**
   * 确认具体时间
   * @param {object} detail {currentDate}
   */
  onConfim(e) {
    // console.log("执行没有哟??")
    console.log('e.detail.startDate----------', e.detail.startDate, this)
    const {start, end} =  frmDateWithDateType(e.detail.currentDate, 3)
    // 调用
    this.setData({
      searchObj1:{
        "dateType": 3,
        "endDate": end,
        "startDate": start
      },
      isShow:true,
      currentDate: end.substr(0,4),  // 当年
      activeTab: 'b'
    })
    // console.log("执行没有啊??")
    // console.log(this.data.searchObj1.endDate)
    this.getData()
  },

  // 今年按钮点击事件
  yearHandle(e){
    this.setData({
      dateType: 1,
      isShow:false
    })
    // 调用手术指标方法
    this.setData({
      searchObj1:{
        "dateType": this.data.dateType,
        "endDate": e.detail.endDate,
        "startDate": e.detail.startDate
      },
      // currentDate: end.substr(0,4),  // 当年
      activeTab: 'b'
    })
    this.getData()
  },
})

css

/* pages/MonthlyReport/index/index.wxss */
.item{
    min-height: 64rpx;
    font-size: 28rpx;
    color: #565B6E;
    overflow: hidden;
    padding: 40rpx 65rpx 40rpx 40rpx;
    background-color: rgba(98,167,248,0.2);
    position: relative;
}
.item:nth-child(even){
    background:#FFFFFF;
}
.item .l{
    float: left;
}
.item .l .box{
    height: 64rpx;
    line-height: 64rpx;
}
.item .l .icon_ring{
    width: 12rpx;
    height: 12rpx;
    background: #fff;
    border: 2px solid #62A7F8;
    border-radius: 100%;
    display: inline-block;
    vertical-align: middle;
}
.item .l .name{
    font-weight: bold;
    margin-left: 5px;
}
.item .r{
    float: right;
}
.item .r .sum{
    color: #3F8EEB;
    font-weight: bold;
    text-align: right;
}
.item .r .num{
    font-size: 10px;
    margin-top: 3px;
    text-align: right;
}
.add{
   color: #F88A2B; 
}
.pre{
    color: #62A7F8; 
 }
 .ml{
     margin-left: 4px;
 }
/* s时间控件的 */
 .topTime {
    width: 100%;
  
  }
  .bgWhite {
    background: #FFFFFF;
    margin-top: 10rpx;
  }
  .arrow{
      position: absolute;right: 2px;
      font-size: 50rpx;
      color: #969799;
      top:40rpx;
  }

/*  */

这个页面是日期组件和通用echarts都有用到

1646125863(1).png

json

{
  "navigationBarTitleText": "门急诊收入",
  "usingComponents": {
    "van-row": "@vant/weapp/row/index",
    "van-col": "@vant/weapp/col/index",
    "van-cell": "@vant/weapp/cell/index",
    "van-cell-group": "@vant/weapp/cell-group/index",
    "van-button": "@vant/weapp/button/index",
    "van-icon": "@vant/weapp/icon/index",
    "van-switch": "@vant/weapp/switch/index",
    "e-pie": "../../../components/pie/index",
    "wxEchart":"../../../components/wxEchart/wxEchart",
    "van-tab": "@vant/weapp/tab/index",
    "van-tabs": "@vant/weapp/tabs/index",
    "van-tag": "@vant/weapp/tag/index",
    "time-picker": "../../../components/timepicker/timepicker",
    "e-bar": "../../../components/bar/index"
  }
}

wxml

<!--门急诊收入-->
    <!-- 时间控件 -->
    <view class="topTime bgWhite">
        <time-picker layout="month" showYear="true" idNeedTime="{{false}}" dateType="{{dateType}}" bind:prev-date="prevDay" bind:year-handle="yearHandle" bind:confirm="onConfim"></time-picker>
    </view>
<view>

    <view>
        <e-bar options="{{ options }}" canvasId="{{ canvasId }}" chartLineId="{{ chartLineId }}" height="200px"></e-bar>
        <!-- <e-pie data="{{pieData}}"></e-pie> -->
        <!-- <view class="num"><text class="add"><text class="nam">同比</text>+0.3%↑</text></view>
        <view class="num"><text class="pre"><text class="nam">环比</text>-0.26%↓</text></view> -->
    </view>
    <van-row class="row1">
        <van-col span="12">
            <van-cell value="{{ data.medicateAccount }}">
                <view slot="title">
                    <view class="van-cell-text"><text class="circle circle1"></text>药品收入</view>
                </view>
            </van-cell>
        </van-col>
        <van-col span="12">
            <van-cell value="{{ data.pacsAccount }}">
                <view slot="title">
                    <view class="van-cell-text"><text class="circle circle2"></text>检查收入</view>
                </view>
            </van-cell>
        </van-col>
        <van-col span="12">
            <van-cell value="{{ data.lisAccount }}">
                <view slot="title">
                    <view class="van-cell-text"><text class="circle circle3"></text>检验收入</view>
                </view>
            </van-cell>
        </van-col>
        <van-col span="12">
            <van-cell value="{{ data.otherAccount }}">
                <view slot="title">
                    <view class="van-cell-text"><text class="circle circle4"></text>其他收入</view>
                </view>
            </van-cell>
        </van-col>
    </van-row>
    <van-row class="row2">
        <van-cell value="{{ data.medicateRatio }}">
            <view slot="title">
                <view class="van-cell-text">药占比</view>
                <view class="num"><text class="{{data.medicateRatioCompare>0?'add':'pre'}}"><text class="nam">同比</text>{{data.medicateRatioCompare}}{{data.medicateRatioCompare>0?'↑':'↓'}}</text><text class="{{data.medicateRatioLink>0?'add':'pre'}}"><text class="nam">环比</text>{{data.medicateRatioLink}}{{data.medicateRatioLink>0?'↑':'↓'}}</text></view>
            </view>
        </van-cell>
        <van-cell value="{{ data.anbitioticMedicateRatio || 0 }}">
            <view slot="title">
                <view class="van-cell-text">抗菌药占比</view>
                <view class="num"><text class="{{data.outPCountFeeCompare>0?'add':'pre'}}"><text class="nam">同比</text>{{data.outPCountFeeCompare}}{{data.outPCountFeeCompare>0?'↑':'↓'}}</text><text class="{{data.outPCountFeeRatioLink>0?'add':'pre'}}"><text class="nam">环比</text>{{data.outPCountFeeRatioLink}}{{data.outPCountFeeRatioLink>0?'↑':'↓'}}</text></view>
            </view>
        </van-cell>
        <van-cell value="{{ data.outPCountFee || 0 }}">
            <view slot="title">
                <view class="van-cell-text">门急诊次均费用</view>
                <view class="num"><text class="{{data.outPCountFeeCompare>0?'add':'pre'}}"><text class="nam">同比</text>{{data.outPCountFeeCompare}}{{data.outPCountFeeCompare>0?'↑':'↓'}}</text><text class="{{data.outPCountFeeRatioLink>0?'add':'pre'}}"><text class="nam">环比</text>{{data.outPCountFeeRatioLink}}{{data.outPCountFeeRatioLink>0?'↑':'↓'}}</text></view>
            </view>
        </van-cell>
        <van-cell value="{{ data.materialsRatio || 0 }}">
            <view slot="title">
                <view class="van-cell-text">材料费占比</view>
                <view class="num"><text class="{{data.materialsCompare>0?'add':'pre'}}"><text class="nam">同比</text>{{data.materialsCompare}}{{data.materialsCompare>0?'↑':'↓'}}</text><text class="{{data.materialsRatioLink>0?'add':'pre'}}"><text class="nam">环比</text>{{data.materialsRatioLink}}{{data.materialsRatioLink>0?'↑':'↓'}}</text></view>
            </view>
        </van-cell>
    </van-row>
    <van-tabs class="row3" active="a">
        <van-tab title="趋势分析" name="a">
            <view>
                <e-bar options="{{ weekTrendOptions }}" canvasId="{{ canvasBottomId }}" chartLineId="{{ chartLineBottomId }}" height="400px"></e-bar>
            </view>
        </van-tab>
        <van-tab title="科室收入" name="b">
            <view class="table">
                <van-row class="tit">
                    <van-col span="6">科室名称</van-col>
                    <van-col span="6" >收入(万元)/占比</van-col>
                    <van-col span="6">同比</van-col>
                    <van-col span="6">环比</van-col>
                </van-row>
                <van-row class="tr"
                    wx:for="{{ tableData1 }}"
                    wx:for-item="itemObj"
                    wx:key="itemObj"
                    wx:for-index="index"
                    >
                    <van-col span="6">{{ itemObj.deptName }}</van-col>
                    <van-col span="6">{{ itemObj.deptIncomeAndRatio }}</van-col>
                    <van-col span="6" class="{{(itemObj.compare && itemObj.compare < 0) ? 'reduce_row' : 'plus_row'}}">{{ m1.newVal(itemObj.compare,true) }}</van-col>
                    <van-col span="6" class="{{(itemObj.link && itemObj.link < 0) ? 'reduce_row' : 'plus_row'}}">{{ m1.newVal(itemObj.link,true) }}</van-col>
                </van-row>

            </view>
        </van-tab>
        <van-tab title="科室药占比" name="c">
            <view class="table">
                <van-row class="tit">
                    <van-col span="6">科室名称</van-col>
                    <van-col span="6">药占比</van-col>
                    <van-col span="6">同比</van-col>
                    <van-col span="6">环比</van-col>
                </van-row>
                <van-row class="tr"
                    wx:for="{{ tableData2 }}"
                    wx:for-item="itemObj"
                    wx:key="itemObj"
                    wx:for-index="index"
                    >
                        <van-col span="6">{{ itemObj.deptName }}</van-col>
                        <van-col span="6">{{ itemObj.drugRatio}}%</van-col>
                        <van-col span="6" class="{{(itemObj.compare && itemObj.compare < 0) ? 'reduce_row' : 'plus_row'}}">{{ m1.newVal(itemObj.compare,true) }}</van-col>
                        <van-col span="6" class="{{(itemObj.link && itemObj.link < 0) ? 'reduce_row' : 'plus_row'}}">{{ m1.newVal(itemObj.link,true) }}</van-col>
                </van-row>
            </view>
        </van-tab>
        <!-- <view class="btns">
            <view class="btn">近3个月</view>
            <view class="btn active">近6个月</view>
            <view class="btn">近1年</view>
        </view> -->
    </van-tabs>
    <!--计算属性-->
    <wxs src="../../../utils/common.wxs" module="m1"></wxs>
</view>

js

import dayjs from 'dayjs'
import { getDeptDrugRatio, getOutPDept, getOutPInfo,listOutPWeekByDate} from '../../../api/MonthlyReport/outpIncome'
const computedBehavior = require('miniprogram-computed').behavior
import {frmDateWithDateType} from '../../../utils/util'
Page({
  behaviors: [computedBehavior],
  /**
   * 页面的初始数据
   */
  data: {
    currentDate: '', // 记录时间
    // currentMon:'', // 月份
    dateType:2, // 时间类型,如果是1,日期格式startDate和date就是yyyy(只传年),3/2格式是yyyy-MM,4格式是yyyy-MM-dd,如果是空,就是 YYYY-MM-DD HH:mm:ss
    searchObj1:{}, // 查询参数
    searchObj2:{}, // 查询参数
    tableData1: [], // 科室收入
    tableData2: [], // 科室药占比
    canvasId: 'surgeryCanvasId',
    chartLineId: 'surgeryChartLineId',
    // 顶部的
    options: {
      // 颜色
      color: ['#FEB843', '#3F8EEB', '#959AAF', '#DDDEE4'],
      // 直角坐标系内绘图网格,单个 grid 内最多可以放置上下两个 X 轴,左右两个 Y 轴
      grid: {
        right: '2%'
      },
      title: {
        text:"门急诊收入",
        textStyle:{
          color:'#565B6E',
          fontSize: 12
        },
        subtext: "",
        subtextStyle:{
          color:'#3F8EEB',
          fontSize: 14
        },
        left: 'center',
        top: '42%'
      },
      // 提示框
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          type: 'cross'
        }
      },
      // 图例组件
      legend: {
        data: ['1','2','3']
      },
      // 图形,例如柱状,线状图
      series: [
        {
          name: 'a',
          type: 'pie',
          radius:['50%', '70%'],
          data: ['1','2','3']
        }
      ]
    },
    //趋势里面的
    canvasBottomId: 'weekTrendCanvasId',
    chartLineBottomId: 'weekTrendChartLineId',
    weekTrendOptions: {
      color: ['#7ed3f4', '#86c56a', '#f9c14e'],
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          type: 'cross',
          crossStyle: {
            color: '#999'
          }
        }
      },
      legend: {
        data: ['门急诊收入', '同比']
      },
      xAxis: [
        {
          type: 'category',
          data: [],
          axisPointer: {
            type: 'shadow'
          }
        }
      ],
      yAxis: [
        {
          type: 'value',
          name: '急诊人次',
          min: 0,
          max: '',
          axisLabel: {
            formatter: '{value}'
          }
        },
        {
          type: 'value',
          name: '增长率',
          min: 0,
          max: 25,
          axisLabel: {
            formatter: '{value}%'
          }
        }
      ],
      series: [
        {
          name: '门急诊收入',
          type: 'bar',
          data: []
        },
        {
          name: '同比',
          type: 'line',
          yAxisIndex: 1,
          data: []
        }
      ]
    }
  },

  /**
   * 生命周期函数--监听页面加载
   */
  async onLoad(options) {

  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  async onReady () {
    // 获取当前时间
    let nowTimer = new Date()
    let day = dayjs(nowTimer).format('YYYY-MM')
    if(this.$store.time.queryDate.length>4){ // 年月格式
      this.setData({
        dateType:2
      })
    }else{
      this.setData({
        dateType:1
      })
    }
    // 参数是当前月
    this.setData({
      searchObj1:{
        "dateType": this.data.dateType,
        "date": this.$store.time.queryDate.substr(0,7)
      },
      searchObj2:{
        "dateType": this.data.dateType,
        "date": this.$store.time.queryDate.substr(0,7),
        "compareType": 3
      },
      currentDate: this.$store.time.queryDate.substr(0,4),  // 当年
      // currentMon: day.substr(5,7)   // 月份
    })
    await this.getOutPInfoFn() // 信息 2个参数 dateType/date
    await this.getOutPDeptFn() // 收入 2个参数 dateType/date
    await this.getDeptDrugRatioFn() // 药占比 2个参数 dateType/date
    await this.listOutPWeekByDateFn() // 趋势 3个参数 dateType/date/compareType compareType默认传3
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  },
  // 饼图
  async getOutPInfoFn() {
    let res = await getOutPInfo(this.data.searchObj1)
    if (res.data.code === 200) {
      const { data } = res.data
      // console.log(data)
      let arr = [
        { value: data.medicateAccount, name: '药品收入' },
        { value: data.pacsAccount, name: '检查收入' },
        { value: data.lisAccount, name: '检验收入' },
        { value: data.otherAccount, name: '其他收入' }
      ]
      // console.log(this.data.options.series)
      this.data.options.series[0].data = arr
      this.data.options.title.subtext = data.outPAccount + '万元'
      this.setData({
        options:this.data.options,
        data: data
      })
      console.log(this.data.options)
    }
  },
  // 科室收入
  async getOutPDeptFn() {
    let res = await getOutPDept(this.data.searchObj1)
    if (res.data.code === 200) {
      const { data } = res.data
      this.setData({
        tableData1: data,
      })
      console.log(this.data.tableData1)
    }
  },
  //  科室药占比
  async getDeptDrugRatioFn() {
    let res = await getDeptDrugRatio(this.data.searchObj1)
    // console.log("科室药占比")
    if (res.data.code === 200) {
      const { data } = res.data
      
      this.setData({
        tableData2: data,
      })
      // console.log("科室药占比")
      console.log(this.data.tableData2)
    }
  },
  // 趋势分析
  async listOutPWeekByDateFn() {
    let res = await listOutPWeekByDate(this.data.searchObj2)
    if (res.data.code === 200) {
      // console.log("走进来没有啊")
      const { data } = res.data
      console.log(data)
      let monthsAry = [] // 月份
      let outPAccountAry = [] // 门急诊收入
      let compareAry = [] // 同比
      // let linkAry = [] // 环比
      data.forEach((item,index)=>{
          monthsAry.push(item.months + '月')
          outPAccountAry.push(item.outPAccount)
          compareAry.push(item.compare)
          // linkAry.push(item.link)
      })
      // 门急诊收入 求出最大值
     let maxOutPAccount = Math.max.apply(Math, outPAccountAry) + 50
      // 同比环比中的最大值
      // 同比最大值
      let maxYear = Math.max.apply(Math, compareAry)
      // 同比最小值
      let minYear = Math.min.apply(Math, compareAry);
      // // 环比最大值
      // let maxMonth = Math.max.apply(Math, linkAry)
      // // 环比最小值
      // let minMonth = Math.min.apply(Math, linkAry);
      // // 两个中的最大值
      // let maxYearMonth = Math.max.apply(Math, [maxYear, maxMonth]) + 5
      // // 两个中最小值
      // let minYearMonth = Math.max.apply(Math, [minYear, minMonth]) - 5
      this.data.weekTrendOptions.xAxis[0].data = monthsAry
      this.data.weekTrendOptions.series[0].data = outPAccountAry
      this.data.weekTrendOptions.series[1].data = compareAry
      // this.data.weekTrendOptions.series[2].data = linkAry
      this.data.weekTrendOptions.yAxis[0].max = maxOutPAccount  // 急诊人次最大
      // this.data.weekTrendOptions.yAxis[1].max = maxYearMonth  // 增长率最大
      // this.data.weekTrendOptions.yAxis[1].min = minYearMonth  // 增长率最小
      this.data.weekTrendOptions.yAxis[1].max = maxYear  // 增长率最大
      this.data.weekTrendOptions.yAxis[1].min = minYear  // 增长率最小
      this.setData({
        weekTrendOptions: this.data.weekTrendOptions,
      })
      // console.log(this.data.weekTrendOptions)
    }
  },


  // 子组件绑定的方法
  prevDay(e){
    
    // 判断 子组件时间控件里面,是不是有值
    if (e && e.detail) {
     const {start, end} =  frmDateWithDateType(e.detail.currentDate, 3)
      console.log('frm----------', start)
      this.setData({
        searchObj1:{
          "dateType": 2,
          "date": start
        },
        searchObj2:{
          "dateType": 2,
          "date": start,
          "compareType": 3
        },
        currentDate: start.substr(0,4),  // 当年
        activeTab: '趋势分析'
      })
    }
    this.getOutPInfoFn()
    this.getOutPDeptFn()
    this.getDeptDrugRatioFn()
    this.listOutPWeekByDateFn()

  },
  // 日期直接选择时间
  onConfim(e){
    console.log('e.detail.startDate----------', e.detail.startDate, this)
    const {start, end} =  frmDateWithDateType(e.detail.currentDate, 3)
    // 调用
    this.setData({
      searchObj1:{
        "dateType": 2,
        "date": start
      },
      searchObj2:{
        "dateType": 2,
        "date": start,
        "compareType": 3
      },
      currentDate: start.substr(0,4),  // 当年
      activeTab: '趋势分析'
    })
    this.getOutPInfoFn()
    this.getOutPDeptFn()
    this.getDeptDrugRatioFn()
    this.listOutPWeekByDateFn()
  },
  // 今年按钮点击事件
  yearHandle(e){
    this.setData({
      dateType: 1
    })
    // 调用手术指标方法
    this.setData({
      searchObj1:{
        "dateType": this.data.dateType,
        "date": e.detail.startDate
      },
      searchObj2:{
        "dateType": this.data.dateType,
        "date": e.detail.startDate,
        "compareType": 3
      },
      currentDate: e.detail.startDate,  // 当年
      activeTab: '趋势分析'
    })
    this.getOutPInfoFn()
    this.getOutPDeptFn()
    this.getDeptDrugRatioFn()
    this.listOutPWeekByDateFn()
  },
  // // tab切换
  // onChange(event) {
  //   this.setData({
  //     activeTab: event.detail.title
  //   })
  //   if (event.detail.name === 'a') {
  //     console.log('this.searchObj.startDate----------', this.data.currentDate)
  //     // 调用手术指标方法
  //     this.setData({
  //       searchObj:{
  //         "year": this.data.currentDate
  //       }
  //     })
  //     // 渲染柱状图
  //     this.surgeryTrendMonth(this.data.searchObj)
  //   }
  //   console.log(event.detail.title, '==========event')
  // },
  
})

css

@import '../../../assets/styles/detailPage.wxss';
.row1 .circle2 {
  background-color: #3F8EEB;
}
.row1 .circle3 {
  background-color: #959AAF;
}
.row1 .circle4 {
  background-color:#DDDEE4;
}

.row1 .van-cell-text{
  width: 215rpx;
}


/* .pie-container {
  width: 100%;
  height: 400px;
  border: 2px solid red;
} */

  /* table  组件结束 */















  /*  */