<template>
  <div class="container">
    <el-form ref="queryForm" :inline="true" :model="queryParams" :rules="rules" label-width="100px">
      <el-form-item label="预约日期" prop="date">
        <el-date-picker v-model="queryParams.date" clearable
                        placeholder="选择预约时间"
                        size="small"
                        type="date"
                        value-format="yyyy-MM-dd">
        </el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-button :loading="loading" icon="el-icon-search" size="mini" type="cyan" @click="queryList">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="reset">重置</el-button>
      </el-form-item>
    </el-form>
    <el-table v-loading="loading" :border="true" :cell-class-name="cellClassName" :data="list" :span-method="mergeRows" row-key="sourceId"
              size="mini" stripe
              tooltip-effect="light" @row-click="rowClick"
    >
      <el-table-column align="center" header-align="center" label="预约统计查询">
        <el-table-column align="center" class-name="examTypeName" fixed="left" header-align="center"
                         label="队列名称" prop="queueName" show-overflow-tooltip
                         width="150"
        />
        <el-table-column align="center" header-align="center" label="时间">
          <el-table-column align="center" fixed="left" header-align="center" label="午段" prop="timeFrame" show-overflow-tooltip
                           width="80"
          />
          <el-table-column align="center" fixed="left" header-align="center" label="时段" prop="timeSlot"
                           show-overflow-tooltip width="100"
          />
        </el-table-column>
        <el-table-column align="center" header-align="center" label="号源总数">
          <el-table-column align="center" header-align="center" label="门诊号源数" prop="outSourceCount"/>
          <el-table-column align="center" header-align="center" label="住院号源数" prop="inSourceCount"/>
          <el-table-column align="center" header-align="center" label="体检号源数" prop="phySourceCount"/>
          <el-table-column align="center" header-align="center" label="单时段号源小计" prop="sourceCount"/>
        </el-table-column>
        <el-table-column align="center" header-align="center" label="号源预约数">
          <el-table-column align="center" header-align="center" label="门诊预约数" prop="outUseSourceCount"/>
          <el-table-column align="center" header-align="center" label="住院预约数" prop="inUseSourceCount"/>
          <el-table-column align="center" header-align="center" label="体检预约数" prop="phyUseSourceCount"/>
          <el-table-column align="center" header-align="center" label="单时段预约小计" prop="useSourceCount"/>
        </el-table-column>
      </el-table-column>
    </el-table>
    <!--抽屉查询-->
    <el-drawer ref="drawer" :destroy-on-close="true" :visible.sync="show" size="50%" title="预约查询">
      <el-form ref="drawerForm" :inline="true" :model="params" label-width="70px">
        <el-form-item label="检查类型" prop="visitTypeId">
          <el-select v-model="params.visitTypeId" clearable placeholder="请选择类型">
            <el-option :key="0" :label="'全部'" :value="''"/>
            <el-option v-for="item in visitTypeList" :key="item.id" :label="item.name" :value="item.id"/>
          </el-select>
        </el-form-item>
        <el-form-item label="检查科室" prop="inspectionDeptId">
          <el-select v-model="params.inspectionDeptId" clearable placeholder="请选择">
            <el-option :key="0" :label="'全部'" :value="''"/>
            <el-option v-for="item in inspectionDeptList" :key="item.deptId" :label="item.deptName"
                       :value="item.deptId"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="开单科室" prop="billingDeptName">
          <el-input v-model="params.billingDeptName" />
        </el-form-item>
        <el-form-item label="队列名称" prop="queueId">
          <el-select v-model="params.queueId" clearable placeholder="请选择队列">
            <el-option :key="0" :label="'全部'" :value="''"/>
            <el-option v-for="item in queueList" :key="item.id" :label="item.queueName" :value="item.id"/>
          </el-select>
        </el-form-item>
        <el-form-item label="时段" prop="startTime">
          <el-time-select v-model="params.startTime" :picker-options="{start: '06:00',step: '00:30',end: '23:30',}" placeholder="开始"
                          style="width: 100px"
          >
          </el-time-select>
          <el-time-select v-model="params.endTime" :picker-options="{start: '06:00',step: '00:30',end: '23:30',minTime: params.startTime}" placeholder="结束"
                          style="width: 100px"
          >
          </el-time-select>
        </el-form-item>
        <el-form-item>
          <el-button :loading="detailLoading" type="primary" @click="getDetailList">查询</el-button>
        </el-form-item>
      </el-form>
      <el-table ref="multipleTable"
                v-loading="detailLoading" :data="detailList" border stripe tooltip-effect="light"
                @row-click="handleRowClick"
      >
        <el-table-column align="left" fixed="left" label="门诊/住院号" min-width="160" prop="visitNum"
                         show-overflow-tooltip
        />
        <el-table-column :formatter="visitTypeFormatter" align="center" label="类别" prop="visitTypeId" width="60"/>
        <el-table-column align="left" fixed="left" label="姓名" min-width="80" prop="patientName" show-overflow-tooltip/>
        <el-table-column align="center" label="时段" prop="reservationTimeSlot" width="110"/>
        <el-table-column align="left" label="序号" min-width="120" prop="reservationNum" show-overflow-tooltip/>
        <el-table-column align="left" label="项目" min-width="200" prop="inExamItemName" show-overflow-tooltip/>
        <el-table-column align="left" label="开单科室" min-width="150" prop="applyDeptName" show-overflow-tooltip/>
      </el-table>
      <pagination
        v-show="total > 0"
        :limit.sync="params.pageSize"
        :page.sync="params.pageNum"
        :total="total"
        @pagination="getDetailList"
      />
    </el-drawer>
  </div>
</template>

<script>
import {getAppointmentStatistics, queryByQueue} from "@/api/resource/apply";
import Dept from "@/views/basis/deptHospital";
import {listQueue} from "@/api/resource/queue";
import {listExamtype} from "@/api/basis/examtype";
import {listDept} from "@/api/basis/dept";

export default {
  name: "Statistics",
  components: {Dept},
  data() {
    return {
      // 查询参数
      queryParams: {
        date: null
      },
      // 规则
      rules: {
        date: [{required: true, message: '请选择预约时间', trigger: 'blur'},]
      },
      loading: false,
      list: [],
      // 详情查询参数
      params: {
        sourceId:'',
        queueId: '',
        startTime: '',
        endTime: '',
        visitTypeId: '',
        inspectionDeptId: '', // 检查科室
        billingDeptName: '', // 开单科室
        pageNum: 1,
        pageSize: 20,
      },
      // 详情列表
      detailList: [],
      detailLoading: false,
      total: 0,
      show: false,
      //队列
      queueList: [],
      visitTypeList: [{id: "1", name: "门诊"}, {id: "2", name: "住院"}, {id: "3", name: "体检"}],
      inspectionDeptList:[],
      billingDeptList:[],
    }
  },
  methods: {
    handleRowClick(row, column, event) {
      this.$refs.multipleTable.toggleRowSelection(row)
    },
    // 查询
    query() {
      this.$refs['queryForm'].validate((valid) => {
        if (valid) {
          this.loading = true
          getAppointmentStatistics(this.queryParams).then(res => {
            if (res.code === 200) {
              if (res.data && res.data.length === 0) {
                this.$message.info('当前日期无预约信息')
              } else {
                let tempList = [] // 定义数据合并的数组，将系统类型时段的数据合并
                res.data.forEach(item => {
                  let index = tempList.findIndex(i => (i.examTypeId === item.examTypeId && i.timeSlot === item.timeSlot))
                  if (index !== -1) {
                    let temp = {
                      ...tempList[index],
                      outSourceCount: parseInt(tempList[index].outSourceCount) + parseInt(item.outSourceCount),
                      inSourceCount: parseInt(tempList[index].inSourceCount) + parseInt(item.inSourceCount),
                      phySourceCount: parseInt(tempList[index].phySourceCount) + parseInt(item.phySourceCount),
                      sourceCount: parseInt(tempList[index].sourceCount) + parseInt(item.sourceCount),
                      outUseSourceCount: parseInt(tempList[index].outUseSourceCount) + parseInt(item.outUseSourceCount),
                      inUseSourceCount: parseInt(tempList[index].inUseSourceCount) + parseInt(item.inUseSourceCount),
                      phyUseSourceCount: parseInt(tempList[index].phyUseSourceCount) + parseInt(item.phyUseSourceCount),
                      useSourceCount: parseInt(tempList[index].useSourceCount) + parseInt(item.useSourceCount),
                    }
                    tempList.splice(index, 1, temp)
                  } else {
                    tempList.push(item)
                  }
                })
                // 定义排序数组,将每个类型的数据存在data，然后按照时段进行排序
                let sortList = [] // { id,data }
                // 定义最后的一行总计行
                let total = {
                  total: true, examTypeName: '总计',
                  outSourceCount: 0, inSourceCount: 0, phySourceCount: 0, sourceCount: 0,
                  outUseSourceCount: 0, inUseSourceCount: 0, phyUseSourceCount: 0, useSourceCount: 0
                }
                // 遍历计算总计，并且添加数据到排序数组
                tempList.forEach(item => {
                  total.outSourceCount += item.outSourceCount
                  total.inSourceCount += item.inSourceCount
                  total.phySourceCount += item.phySourceCount
                  total.sourceCount += item.sourceCount
                  total.outUseSourceCount += item.outUseSourceCount
                  total.inUseSourceCount += item.inUseSourceCount
                  total.phyUseSourceCount += item.phyUseSourceCount
                  total.useSourceCount += item.useSourceCount
                  let tempIndex = sortList.findIndex(i => i.examTypeId === item.examTypeId)
                  if (tempIndex === -1) {
                    sortList.push({examTypeId: item.examTypeId, examTypeName: item.examTypeName, data: [item]})
                  } else {
                    sortList[tempIndex].data.push(item)
                  }
                })
                let list = [] // 最终数组
                sortList.forEach(item => {
                  // 先对数组进行排序
                  item.data.sort((x, y) => {
                    return new Date(`2022-01-01 ${x.timeSlot.split('-')[0]}`).getTime() - new Date(`2022-01-01 ${y.timeSlot.split('-')[0]}`).getTime()
                  })
                  // 插入合计行
                  let am = {
                    outSourceCount: 0,
                    inSourceCount: 0,
                    phySourceCount: 0,
                    sourceCount: 0,
                    amTotal: false,
                    timeFrame: '小计',
                    outUseSourceCount: 0,
                    inUseSourceCount: 0,
                    phyUseSourceCount: 0,
                    useSourceCount: 0,
                    examTypeId: item.examTypeId
                  }
                  let pm = {
                    outSourceCount: 0,
                    inSourceCount: 0,
                    phySourceCount: 0,
                    sourceCount: 0,
                    pmTotal: false,
                    timeFrame: '小计',
                    outUseSourceCount: 0,
                    inUseSourceCount: 0,
                    phyUseSourceCount: 0,
                    useSourceCount: 0,
                    examTypeId: item.examTypeId
                  }
                  // 向最终数组按照顺序添加值，并且计算小计
                  item.data.forEach((value, index) => {
                    list.push(value)
                    if (value.timeFrame === '上午') {
                      am.amTotal = true
                      am.outSourceCount += value.outSourceCount
                      am.inSourceCount += value.inSourceCount
                      am.phySourceCount += value.phySourceCount
                      am.sourceCount += value.sourceCount
                      am.outUseSourceCount += value.outUseSourceCount
                      am.inUseSourceCount += value.inUseSourceCount
                      am.phyUseSourceCount += value.phyUseSourceCount
                      am.useSourceCount += value.useSourceCount
                      // 判断当前下个下标的数据是否是下午，如果是，说明这是当前最后一个上午的数据
                      if (index < item.data.length - 1 && item.data[index + 1].timeFrame === '下午') {
                        list.push(am)
                        // 如果当前是最后一个，说明也是最后一个上午的数据
                      } else if (index === item.data.length - 1) {
                        list.push(am)
                      }
                    } else if (value.timeFrame === '下午') {
                      pm.pmTotal = true
                      pm.outSourceCount += value.outSourceCount
                      pm.inSourceCount += value.inSourceCount
                      pm.phySourceCount += value.phySourceCount
                      pm.sourceCount += value.sourceCount
                      pm.outUseSourceCount += value.outUseSourceCount
                      pm.inUseSourceCount += value.inUseSourceCount
                      pm.phyUseSourceCount += value.phyUseSourceCount
                      pm.useSourceCount += value.useSourceCount
                      // 如果当前数据是数组最后一个，说明是最后一个下午的数据
                      if (index === item.data.length - 1) {
                        list.push(pm)
                      }
                    }
                  })
                  // 给每个类型加一个小计
                  list.push({
                    apmTotal: true, timeFrame: '合计',
                    examTypeId: item.examTypeId,
                    outSourceCount: parseInt(am.outSourceCount) + parseInt(pm.outSourceCount),
                    inSourceCount: parseInt(am.inSourceCount) + parseInt(pm.inSourceCount),
                    phySourceCount: parseInt(am.phySourceCount) + parseInt(pm.phySourceCount),
                    sourceCount: parseInt(am.sourceCount) + parseInt(pm.sourceCount),
                    outUseSourceCount: parseInt(am.outUseSourceCount) + parseInt(pm.outUseSourceCount),
                    inUseSourceCount: parseInt(am.inUseSourceCount) + parseInt(pm.inUseSourceCount),
                    phyUseSourceCount: parseInt(am.phyUseSourceCount) + parseInt(pm.phyUseSourceCount),
                    useSourceCount: parseInt(am.useSourceCount) + parseInt(pm.useSourceCount),
                  })
                })
                list.push(total)
                this.list = list
              }
            }
            this.loading = false
          })
          setTimeout(() => {
            this.loading = false
          }, 5000)
        }
      });
    },
    queryList() {
      this.$refs['queryForm'].validate((valid) => {
        if (valid) {
          this.loading = true
          getAppointmentStatistics(this.queryParams).then(res => {
            if (res.code === 200) {
              if (res.data && res.data.length === 0) {
                this.$message.info("当前日期无预约信息")
              } else {
                let tempList = [] // 将数据分为 [] [] [] [] 的形式
                res.data.forEach(item => {
                  let index = tempList.findIndex(arr => arr[0].queueId === item.queueId)
                  if (index === -1) {
                    let arr = [item]
                    tempList.push(arr)
                  } else {
                    tempList[index].push(item)
                  }
                })
                let fnList = []
                // 总计
                let total = {
                  sourceId: null, total: true, queueName: '总计',
                  outSourceCount: 0, inSourceCount: 0, phySourceCount: 0, sourceCount: 0,
                  outUseSourceCount: 0, inUseSourceCount: 0, phyUseSourceCount: 0, useSourceCount: 0
                }
                // 时间排序
                tempList.forEach(item => {
                  item.sort((x, y) => {
                    return new Date(`2022-01-01 ${x.timeSlot.split('-')[0]}`).getTime() - new Date(`2022-01-01 ${y.timeSlot.split('-')[0]}`).getTime()
                  })
                  // 开始计算小计行
                  let am = {
                    ...item[0],
                    sourceId: null, timeFrame: '小计', totalRow: false, // 代表小计行
                    outSourceCount: 0, inSourceCount: 0, phySourceCount: 0, sourceCount: 0,
                    outUseSourceCount: 0, inUseSourceCount: 0, phyUseSourceCount: 0, useSourceCount: 0
                  }
                  let pm = {
                    ...item[0], timeFrame: '小计',
                    sourceId: null, totalRow: false, // 代表小计行
                    outSourceCount: 0, inSourceCount: 0, phySourceCount: 0, sourceCount: 0,
                    outUseSourceCount: 0, inUseSourceCount: 0, phyUseSourceCount: 0, useSourceCount: 0
                  }
                  item.forEach((value, index) => {
                    if (value.timeFrame === '上午') {
                      //am.sourceId = value.sourceId
                      am.totalRow = true
                      am.outSourceCount += value.outSourceCount
                      am.inSourceCount += value.inSourceCount
                      am.phySourceCount += value.phySourceCount
                      am.sourceCount += value.sourceCount
                      am.outUseSourceCount += value.outUseSourceCount
                      am.inUseSourceCount += value.inUseSourceCount
                      am.phyUseSourceCount += value.phyUseSourceCount
                      am.useSourceCount += value.useSourceCount
                    } else if (value.timeFrame === '下午') {
                      //pm.sourceId = value.sourceId
                      pm.totalRow = true
                      pm.outSourceCount += value.outSourceCount
                      pm.inSourceCount += value.inSourceCount
                      pm.phySourceCount += value.phySourceCount
                      pm.sourceCount += value.sourceCount
                      pm.outUseSourceCount += value.outUseSourceCount
                      pm.inUseSourceCount += value.inUseSourceCount
                      pm.phyUseSourceCount += value.phyUseSourceCount
                      pm.useSourceCount += value.useSourceCount
                    }
                  })
                  if (am.totalRow) {
                    let index = this.getLastIndex(item, i => i.timeFrame === '上午')
                    item.splice(index + 1, 0, am)
                  }
                  if (pm.totalRow) {
                    let index = this.getLastIndex(item, i => i.timeFrame === '下午')
                    item.splice(index + 1, 0, pm)
                  }
                  // 结尾小计
                  let queueTotal = {
                    ...item[0], timeFrame: '合计', sourceId: null,
                    totalRow: true, // 代表小计行
                    outSourceCount: parseInt(am.outSourceCount) + parseInt(pm.outSourceCount),
                    inSourceCount: parseInt(am.inSourceCount) + parseInt(pm.inSourceCount),
                    phySourceCount: parseInt(am.phySourceCount) + parseInt(pm.phySourceCount),
                    sourceCount: parseInt(am.sourceCount) + parseInt(pm.sourceCount),
                    outUseSourceCount: parseInt(am.outUseSourceCount) + parseInt(pm.outUseSourceCount),
                    inUseSourceCount: parseInt(am.inUseSourceCount) + parseInt(pm.inUseSourceCount),
                    phyUseSourceCount: parseInt(am.phyUseSourceCount) + parseInt(pm.phyUseSourceCount),
                    useSourceCount: parseInt(am.useSourceCount) + parseInt(pm.useSourceCount),
                  }
                  item.push(queueTotal)
                  total.outSourceCount += queueTotal.outSourceCount
                  total.inSourceCount += queueTotal.inSourceCount
                  total.phySourceCount += queueTotal.phySourceCount
                  total.sourceCount += queueTotal.sourceCount
                  total.outUseSourceCount += queueTotal.outUseSourceCount
                  total.inUseSourceCount += queueTotal.inUseSourceCount
                  total.phyUseSourceCount += queueTotal.phyUseSourceCount
                  total.useSourceCount += queueTotal.useSourceCount
                  fnList.push(...item)
                })
                fnList.push(total)
                this.list = fnList
              }
            }
            this.loading = false
          })
          setTimeout(() => {
            this.loading = false
          }, 5000)
        }
      });
    },
    // 查询指定数组最后一个符合条件的下标
    getLastIndex(arr = [], predicate) {
      for (let i = arr.length - 1; i >= 0; i--) {
        if (predicate(arr[i])) {
          return i;
        }
      }
      return -1;
    },
    reset() {
      this.$refs['queryForm'].resetFields()
      this.list = []
    },
    // 表格行列合并
    mergeRows({row, column, rowIndex, columnIndex}) {
      // 小计合并时段与午段
      if (row.totalRow) {
        if (columnIndex === 1) {
          return {rowspan: 1, colspan: 2}
        } else if (columnIndex === 2) {
          return {rowspan: 0, colspan: 0}
        }
      }
      // 判断总计
      if (row.total) {
        if (columnIndex === 0) {
          return {rowspan: 1, colspan: 3}
        } else if ([1, 2].includes(columnIndex)) {
          return {rowspan: 0, colspan: 0}
        }
      }
      // 合并队列名称
      if (columnIndex === 0) {
        let rowspan = 0
        let colspan = 0
        if (rowIndex === 0 || (row.queueId !== this.list[rowIndex - 1].queueId)) {
          rowspan = this.list.filter(item => item.queueId === row.queueId).length
          colspan = 1
        }
        return {rowspan, colspan}
      }
      // 合并午段
      if (columnIndex === 1) {
        let rowspan = 0
        let colspan = 0
        if (rowIndex === 0 || (row.timeFrame !== this.list[rowIndex - 1].timeFrame)) {
          rowspan = this.list.filter(item => (item.timeFrame === row.timeFrame && item.queueId === row.queueId)).length
          colspan = 1
        }
        return {rowspan, colspan}
      }
    },
    // 给行列加索引
    cellClassName({row, column, rowIndex, columnIndex}) {
      row.index = rowIndex
      column.index = columnIndex
    },
    // 行点击事件
    rowClick(row, column, event) {
      if (!row.totalRow && !row.total) {
        this.show = true
        this.params.queueId = parseInt(row.queueId)
        this.params.sourceId = row.sourceId
        this.params.startTime = row.timeSlot.split("-")[0]
        this.params.endTime = row.timeSlot.split("-")[1]
        this.$nextTick(() => {
          this.getDetailList()
        })
      }
    },
    getDetailList(){
      this.detailLoading = true
      queryByQueue({
        ...this.params
      }).then(res=>{
        this.detailList = res.rows
        this.total = res.total
      }).finally(_=>{
        this.detailLoading = false
      })
    },
    // 格式化日期
    formatDate(date) {
      if (!date) {
        date = new Date()
      }
      const year = date.getFullYear()
      let month = date.getMonth() + 1
      let day = date.getDate()
      if (month < 10) {
        month = `0${month}`
      }
      if (day < 10) {
        day = `0${day}`
      }
      return (`${year}-${month}-${day}`)
    },
    visitTypeFormatter(row, column, cellValue, index){
      return this.visitTypeList.find(item=>item.id == cellValue).name
    }
  },
  created() {
    this.queryParams.date = this.formatDate()
    this.$nextTick(() => {
      this.queryList()
    })
    listQueue().then(response => {
      this.queueList = response.rows;
    });
    listDept({pageNum: 1, pageSize: 9999, deptType: 3}).then((response) => {
      this.inspectionDeptList = response.rows;
    });
  }
}
</script>

<style lang="scss" scoped>

/*主容器*/
.container {
  padding: 20px;

  ::v-deep .el-drawer__body {
    padding: 0 10px;
  }

}

</style>
