<template>
  <section class="AppIntegralStatistics">
    <ai-detail list>
      <ai-title slot="title" title="总体统计">
        <template #rightBtn>
          <el-row type="flex" align="middle">
            <span class="shortcut" v-for="(item,i) in timeCheck" :key="i" :class="{active:type==i}"
                  @click="timeChange(i)" v-text="item"/>
            <el-cascader ref="cascader1" v-model="girdArr" :options="girdOptions" placeholder="所属网格" size="small"
                         :props="defaultProps" :show-all-levels="false" @change="gridChange" clearable/>
          </el-row>
        </template>
      </ai-title>
      <template #content>
        <div class="card_list">
          <div class="card">
            <h2>积分余额汇总
              <el-tooltip
                  placement="right"
                  style="width: 16px;"
                  content="截止目前所有居民剩余可用积分余额的总和">
                <i class="el-icon-warning-outline"></i>
              </el-tooltip>
            </h2>
            <p class="color1">{{ data.nowIntegral || 0 }}</p>
          </div>
          <div class="card">
            <h2>发放积分</h2>
            <p class="color1">{{ data.addIntegral || 0 }}</p>
          </div>
          <div class="card">
            <h2>消耗积分</h2>
            <p class="color1">{{ Math.abs(data.reduceIntegral) || 0 }}</p>
          </div>
        </div>
        <el-row type="flex" class="mar-t20 gap-20">
          <div class="chartBox fill">
            <b>个人积分排行</b>
            <div>
              <div id="chart1" style="height: 300px; width: 100%;"
                   v-show="userSortListX.length && userSortListY.length"></div>
              <ai-empty v-if="!userSortListX.length && !userSortListY.length" style="height: 200px; width: 100%;"
                        id="empty"/>
            </div>
          </div>
          <div class="chartBox fill">
            <b>网格积分排行</b>
            <div>
              <div id="chart2" style="height: 300px; width: 100%;" v-show="girdSortListX.length && girdSortListY.length"/>
              <ai-empty v-show="!girdSortListX.length && !girdSortListY.length" style="height: 200px; width: 100%;"
                        id="empty"/>
            </div>
          </div>
        </el-row>
        <el-row type="flex" class="mar-t20 gap-20">
          <div class="chartBox fill" v-for="item in sta" :key="item.id">
            <div flex>
              <b class="fill" v-text="item.label"/>
              <div class="color-primary" v-text="`总次数：${item.total}`"/>
            </div>
            <div class="chart" :id="item.id" v-show="item.sta.length>0"/>
            <ai-empty v-if="item.sta.length==0" style="height: 200px; width: 100%;"/>
          </div>
        </el-row>
        <ai-card class="mar-t20" title="积分明细">
          <template #content>
            <ai-search-bar>
              <template #left>
                <el-cascader ref="cascader2" v-model="girdIdArr" :options="girdOptions" placeholder="所属网格"
                             size="small"
                             :props="defaultProps" :show-all-levels="false" clearable
                             @change="gridChangeOpt"></el-cascader>
                <ai-select v-model="search.integralType" placeholder="请选择类型" @change="current=1, getTableData()"
                           :selectList="dict.getDict('integralType')"/>
                <el-date-picker v-model="time" size="small" type="daterange" value-format="yyyy-MM-dd"
                                range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"
                                @change="onChange">
                </el-date-picker>
              </template>
              <template #right>
                <el-input size="small" placeholder="请输入姓名" v-model="search.userName" clearable
                          @clear="current = 1, search.userName = '', getTableData()" suffix-icon="iconfont iconSearch"
                          v-throttle="() => {(current = 1), getTableData();}"/>
              </template>
            </ai-search-bar>
            <ai-table :tableData="tableData" :total="total" :current.sync="current" :size.sync="size"
                      @getList="getTableData" :col-configs="colConfigs" :dict="dict">
              <el-table-column slot="eventDesc" label='事件' align="center" width="400px" show-overflow-tooltip>
                <template slot-scope="{ row }">
                  <span>{{ row.integralRuleName || row.eventDesc }}</span>
                </template>
              </el-table-column>
              <el-table-column slot="changeIntegral" label="变动积分" align="center">
                <template slot-scope="{ row }">
                  <span>{{ row.integralCalcType == 0 ? '-' : '+' }}{{ row.changeIntegral }}</span>
                </template>
              </el-table-column>
              <el-table-column slot="options" label="操作" align="center">
                <template slot-scope="{ row }">
                  <el-button type="text" @click="open(row.id)">详情</el-button>
                </template>
              </el-table-column>
            </ai-table>
          </template>
        </ai-card>
      </template>
    </ai-detail>
    <el-dialog title="详情" :visible.sync="dialog" customFooter width="700">
      <ai-detail>
        <template #content>
          <ai-wrapper>
            <ai-info-item label="姓名" :value="details.integralUserName"/>
            <ai-info-item label="所属网格" :value="details.girdName"/>
            <ai-info-item label="事件" isLine :value="details.eventDesc">
              <span v-if="details.integralRuleId">{{ details.integralRuleName }}</span>
              <span v-else>{{ details.eventDesc }}</span>
            </ai-info-item>
            <ai-info-item label="时间" isLine :value="details.createTime"/>
            <ai-info-item label="积分变动">
              {{ details.integralCalcType == 0 ? '-' : '+' }}{{ details.changeIntegral }}
            </ai-info-item>
            <ai-info-item label="积分余额" :value="details.nowIntegral"/>
            <ai-info-item label="凭证" isLine v-if="fileDownLoad.length">
              <ai-file-list :fileList="fileDownLoad" style="width: 200px;" :fileOps="{name: 'name'}"></ai-file-list>
            </ai-info-item>
          </ai-wrapper>
        </template>
      </ai-detail>
      <span slot="footer" class="dialog-footer" center>
        <el-button @click="dialog = false" style="width: 92px">关闭</el-button>
      </span>
    </el-dialog>
    <ai-dialog :visible.sync="dialogDate" title="选择时间" width="500px" customFooter>
      <el-date-picker v-model="timeList" size="small" type="daterange" value-format="yyyy-MM-dd"
                      range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期">
      </el-date-picker>
      <el-button slot="footer" @click="selectDete" type="primary">确认</el-button>
    </ai-dialog>
  </section>
</template>

<script>
import {mapState} from "vuex"
import * as echarts from 'echarts';
import dayjs from 'dayjs'
import AiDetail from "dui/packages/layout/AiDetail.vue";
import AiTitle from "dui/packages/basic/AiTitle.vue";

export default {
  name: "AppIntegralStatistics",
  components: {AiTitle, AiDetail},
  label: "积分统计",
  props: {
    instance: Function,
    dict: Object,
    permissions: Function,
  },
  data() {
    return {
      myChart1: null,
      myChart2: null,
      tableData: [],
      search: {
        current: 1,
        userName: '',
        girdId: '',
        integralType: '',
        startTime: '',
        endTime: '',
      },
      girdIdArr: [],
      total: 0,
      size: 10,
      current: 1,
      girdList: [],
      time: [],
      timeCheck: ['昨日', '近7天', '近30天', '自定义'],
      dialog: false,
      dialogDate: false,
      timeList: [],
      type: '1',
      startTime: '',
      endTime: '',
      data: {},
      girdId: '',
      girdArr: [],
      girdOptions: [],
      defaultProps: {
        label: 'girdName',
        value: 'id',
        children: 'children',
        checkStrictly: true,
      },
      details: {},
      fileDownLoad: [],
      userSortListX: [],
      userSortListY: [],
      girdSortListX: [],
      girdSortListY: [],
      sta: []
    }
  },
  computed: {
    ...mapState(['user']),
    colConfigs() {
      return [
        {prop: "integralUserName", label: '姓名', align: "left", width: "200px"},
        {prop: "girdName", label: '所属网格', align: "center", width: "180px"},
        {slot: "eventDesc"},
        {prop: "integralType", label: '类型', align: "center", dict: "integralType"},
        {slot: "changeIntegral", label: '积分变动', align: "center",},
        {prop: "nowIntegral", label: '剩余积分', align: "center",},
        {prop: "createTime", label: '时间', align: "center",},
        {slot: "options"}
      ]
    },
  },
  created() {
    this.time = [dayjs().subtract(1, 'week').format('YYYY-MM-DD'), dayjs().format('YYYY-MM-DD')]
    this.$dict.load('epidemicDangerousAreaLevel', 'integralType', 'integralRuleEvent', 'integralRuleEventType').then(() => {
      this.getGridList()
      this.search.startTime = this.time?.[0]
      this.search.endTime = this.time?.[1]
      this.getTableData()
    })
  },
  methods: {
    // 统计接口
    getStatistics() {
      return Promise.all([
        this.instance.post('/app/appintegraluser/allAppletUserIntegral', null, {
          params: {
            type: this.type,
            girdId: this.girdId,
            startTime: this.startTime,
            endTime: this.endTime,
          }
        }).then(res => {
          if (res?.data) {
            return this.data = res.data
          }
        }),
        this.instance.post("/app/appwechatsigninfo/userSignAndIntegralApplyAndIntegralExchangeSort", null, {
          params: {
            type: this.type,
            girdId: this.girdId,
            startTime: this.startTime,
            endTime: this.endTime,
          }
        }).then(res => {
          if (res?.data) {
            const {
              signCountList = [], integralApplyCountList = [], integralExchangeCountList = [],
              signCount = 0, integralExchangeCount = 0, integralApplyCount = 0
            } = res.data
            return this.sta = [
              {label: "签到次数统计", id: 'signCount', sta: signCountList, total: signCount},
              {label: "积分申请次数统计", id: 'integralApplyCount', sta: integralApplyCountList, total: integralApplyCount},
              {label: "积分兑换次数统计", id: 'integralExchangeCount', sta: integralExchangeCountList, total: integralExchangeCount}
            ]
          }
        }).then(() => this.sta.map(this.renderChart))
      ])
    },
    // 人员、网格排行
    getRanking() {
      return this.instance.post('/app/appintegraluser/userAndGirdIntegralSortByApplet', null, {
        params: {
          type: this.type,
          girdId: this.girdId,
          startTime: this.startTime,
          endTime: this.endTime
        }
      }).then((res) => {
        if (res?.data) {
          this.userSortListX = res.data.userSortList.map(e => e.userName).reverse()
          this.userSortListY = res.data.userSortList.map(e => e.changeIntegral).reverse()
          this.girdSortListX = res.data.girdSortList.map(e => e.girdName).reverse()
          this.girdSortListY = res.data.girdSortList.map(e => e.changeIntegral).reverse()
          return 1;
        }
      }).then(() => {
        this.getColEcherts1(this.userSortListX, this.userSortListY)
        this.getColEcherts2(this.girdSortListX, this.girdSortListY)
      })
    },
    // 积分明细
    getTableData() {
      this.instance.post('/app/appintegraluser/girdIntegralDetailByApplet', null, {
        params: {
          ...this.search,
          current: this.current,
          size: this.size,
          total: this.total,
        }
      }).then(res => {
        if (res?.data) {
          this.tableData = res.data.records
          this.total = res.data.total
        }
      })
    },

    gridChangeOpt(val) {
      this.girdIdArr = val
      this.search.girdId = val?.[val.length - 1]
      this.$refs.cascader2.dropDownVisible = false;
      this.getTableData()
    },

    getColEcherts1(xData, yData) {
      let chartDom1 = document.getElementById('chart1');
      chartDom1.style.width = (window.innerWidth - 435) / 2 + "px";
      this.myChart1 = echarts.init(chartDom1);
      this.myChart1.setOption({
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow'
          }
        },
        grid: {
          left: '16px',
          right: '28px',
          bottom: '14px',
          top: '16px',
          containLabel: true
        },
        xAxis: {
          type: 'value',
          boundaryGap: [0, 0.01],
        },
        yAxis: {
          type: 'category',
          data: xData,
          axisTick: {
            show: false,
          },
          axisLine: {
            show: false,
          },
        },
        series: [
          {
            data: yData,
            type: 'bar',
            itemStyle: {
              normal: {
                color: "#5087ec",
                label: {
                  show: true,  //开启显示
                  position: 'right',    //在上方显示
                  textStyle: {
                    fontSize: 13,
                    color: '#666'
                  }
                },
              },
            },
            barWidth: 10,
            barGap: '20%',
          }
        ]
      }, true);
    },
    getColEcherts2(xData, yData) {
      let chartDom2 = document.getElementById('chart2');
      chartDom2.style.width = (window.innerWidth - 435) / 2 + "px";
      this.myChart2 = echarts.init(chartDom2);
      this.myChart2.setOption({
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow'
          }
        },
        grid: {
          left: '16px',
          right: '28px',
          bottom: '14px',
          top: '16px',
          containLabel: true
        },
        xAxis: {
          type: 'value',
          boundaryGap: [0, 0.01],
        },
        yAxis: {
          type: 'category',
          data: xData,
          axisTick: {
            show: false,
          },
          axisLine: {
            show: false,
          },
          triggerEvent: true,
          //设置文本过长超出隐藏...表示
          axisLabel: {
            margin: 8,
            formatter: function (params) {
              var val = ""
              if (params.length > 8) {
                val = params.substr(0, 8) + '...'
                return val
              } else {
                return params;
              }
            }
          },
        },
        series: [
          {
            data: yData,
            type: 'bar',
            itemStyle: {
              normal: {
                color: "#5087ec",
                label: {
                  show: true,  //开启显示
                  position: 'right',    //在右方显示
                  textStyle: {
                    fontSize: 13,
                    color: '#666'
                  }
                },
              },
            },
            barWidth: 10,
            barGap: '20%',
          }
        ]
      }, true);
    },
    onResize() {
      this.myChart1?.resize()
      this.myChart2?.resize()
      this.sta.map(e => e.chart?.resize())
    },
    gridChange(val) {
      this.girdArr = val
      this.girdId = val?.[val.length - 1]
      this.$refs.cascader1.dropDownVisible = false;
      this.getStatistics()
      this.getRanking()
    },
    // 所有网格
    getGridList() {
      this.instance.post(`/app/appgirdinfo/listAll3`).then((res) => {
        if (res?.code == 0) {
          this.girdOptions = this.toTree(res.data)
        }
      })
    },

    // 转树形结构
    toTree(data) {
      let result = [];
      if (!Array.isArray(data)) {
        return result
      }
      let map = {};
      data.forEach(item => {
        map[item.id] = item;
      });
      data.forEach(item => {
        let parent = map[item.parentGirdId];
        if (parent) {
          (parent.children || (parent.children = [])).push(item);
        } else {
          result.push(item);
        }
      });
      return result;
    },

    timeChange(index) {
      this.type = index
      if (index == 3) {
        this.dialogDate = true
      } else {
        this.getStatistics()
        this.getRanking()
      }
    },

    open(id) {
      this.dialog = true
      this.getDetail(id)
    },

    onChange(val) {
      this.search.startTime = val?.[0]
      this.search.endTime = val?.[1]
      this.getTableData()
    },

    getDetail(id) {
      this.instance.post(`/app/appintegraldetail/queryDetailById?id=${id}`).then(res => {
        if (res?.data) {
          this.details = res.data
          if (res.data.enclosure) {
            let str = res.data.enclosure.split('/')
            this.fileDownLoad = [{
              url: res.data.enclosure,
              name: str?.[str.length - 1]
            }]
          }
        }
      })
    },

    selectDete() {
      if (!this.timeList || !this.timeList.length) {
        return this.$message.error('请选择自定义时间');
      }
      this.startTime = this.timeList?.[0]
      this.endTime = this.timeList?.[1]
      this.dialogDate = false
      this.getStatistics()
      this.getRanking()
    },
    renderChart(item = {}) {
      if (!item.chart) {
        const el = document.getElementById(item.id)
        el.style.width = (window.innerWidth - 435) / 3 + "px";
        item.chart = echarts.init(el)
      }
      item.chart.setOption({
        xAxis: {minInterval: 1},
        tooltip: {},
        legend: {},
        yAxis: {type: 'category', axisLabel: {fontSize: 8}},
        dataset: {dimensions: ['username', 'count', 'integral'], source: item.sta},
        series: [
          {name: "次数", barWidth: 10, barGap: '20%', type: 'bar'},
          {name: "积分", barWidth: 10, barGap: '20%', type: 'bar'}
        ]
      }, true)
    }
  },
  filters: {
    formatTime(num) {
      if (num > 0) {
        return '+' + num
      } else {
        return num
      }
    }
  },
  mounted() {
    window.addEventListener('resize', this.onResize)
    this.getRanking()
    this.getStatistics()
  },
  destroyed() {
    window.removeEventListener('resize', this.onResize)
  },
}
</script>

<style lang="scss" scoped>
.AppIntegralStatistics {
  height: 100%;
  box-sizing: border-box;

  .shortcut {
    display: inline-block;
    width: 70px;
    height: 32px;
    line-height: 32px;
    border-radius: 2px;
    border: 1px solid #D0D4DC;
    margin-right: 8px;
    text-align: center;
    cursor: pointer;

    &.active {
      color: #2266FF;
      border: 1px solid #2266FF;
    }
  }

  .chartBox {
    background: #F9F9F9;
    box-shadow: 0px 4px 6px -2px rgba(15, 15, 21, 0.1500);
    border-radius: 4px;
    padding: 16px;
    box-sizing: border-box;

    .chart {
      width: 100%;
      height: 300px;
    }
  }

  .card_list {
    display: flex;

    .card {
      flex: 1;
      height: 96px;
      background: #F9F9F9;
      border-radius: 2px;
      margin-right: 20px;
      padding: 16px 24px;
      box-sizing: border-box;

      h2 {
        color: #888888;
        font-weight: 600;
        font-size: 16px;
      }

      p {
        margin-top: 8px;
        font-size: 24px;
        font-weight: 600;
      }

      .color1 {
        color: #2891FF;
      }

      .color2 {
        color: #22AA99;
      }

      .color3 {
        color: #F8B425;
      }
    }

    .card:last-child {
      margin-right: 0;
    }
  }


  :deep( .el-dialog__footer ) {
    text-align: center;
  }

  :deep( .el-dialog__header ) {
    border-bottom: 1px solid #DDD;
  }

  :deep( .ai-detail ) {
    background: #FFF;
  }
}
</style>
