Quellcode durchsuchen

Merge branch '02/24resetMain' into 03/08IndexAtten

mo vor 4 Jahren
Ursprung
Commit
c010c83dc9

+ 5 - 1
src/App.vue

@@ -19,7 +19,11 @@ export default {
       isRouterAlive: true,
     };
   },
-  created() {},
+  created() {
+
+
+
+  },
   methods: {
     reloads() {
       this.isRouterAlive = false;

+ 1 - 0
src/views/main/api.js

@@ -4,6 +4,7 @@ import request2 from '@/utils/request2'
 export const getIndex = data => request2({
   url: '/api-web/newIndex',
   params: data,
+  loading: false,
   method: 'get',
 })
 export const getInspectionItem = data => request2({

+ 101 - 13
src/views/main/baseinfo/business.vue

@@ -1,5 +1,16 @@
-<template>
-  <el-card header="业务数据">
+<template
+>
+  <el-card header="">
+      <div slot="header" class="clearfix">
+    <searchHeader
+    v-if="mdate.length>0"
+        :dates="mdate"
+        :title="'业务数据'"
+        :isShowQuert='false'
+        @changeValue="changeValue"
+      />
+    </div>
+
     <statistic class="statistic" :cols="0">
       <statistic-item v-for="(item, key) in items" :key="key" :class="{active: active === key}" @click="active = key">
         <span>
@@ -13,31 +24,47 @@
         </span>
       </statistic-item>
     </statistic>
-    <ve-histogram
+    <!--   :data-zoom="dataZoom" -->
+    <ve-line
       style="width: 100%;"
       height="350px"
       :data="chartData"
       :data-empty="dataEmpty"
-      :data-zoom="dataZoom"
+
       :extend="chartExtend"
-    ></ve-histogram>
+      :legend='legend'
+    ></ve-line>
   </el-card>
 </template>
 <script>
 import 'v-charts/lib/style.css'
 import 'echarts/lib/component/dataZoom'
 import countTo from 'vue-count-to'
-import veHistogram from 'v-charts/lib/histogram.common'
+import veLine from "v-charts/lib/line.common";
+import searchHeader from "./modals/searchHeader";
+import { getTimes } from "@/utils";
+import { getIndex } from "../api";
+import { descs,chioseNum } from "../constant";
+import {
+  getNowDateAndSunday,
+  getNowDateAndMonday,
+} from "@/utils/date";
 export default {
-  props: ['data'],
+  props: ['data',"search"],
   components: {
-    've-histogram': veHistogram,
-    'count-to': countTo
+
+    'count-to': countTo,
+     "ve-line": veLine,
+    searchHeader
   },
   computed: {
+     legend() {
+      return {
+        left: "10px",
+      };
+    },
     items() {
       return {
-        ACTIVATION_RATE: this.data['ACTIVATION_RATE'] || {},
         HOMEWORK_CREATE_RATE: this.data['HOMEWORK_CREATE_RATE'] || {},
         HOMEWORK_SUBMIT_RATE: this.data['HOMEWORK_SUBMIT_RATE'] || {},
         HOMEWORK_COMMENT_RATE: this.data['HOMEWORK_COMMENT_RATE'] || {},
@@ -61,8 +88,11 @@ export default {
     dataZoom() {
       return [
         {
+         grid:{
+           left:'0%'
+         },
           type: 'slider',
-          start: 60,
+          start: 40,
           end: 100
         }
       ]
@@ -75,14 +105,17 @@ export default {
           const key = this.$helpers.dayjs(row.month).format('YYYY-MM-DD')
           if (!months[key]) {
             months[key] = {
-              '日期': key,
+              '日期': key+'/'+getNowDateAndSunday(key),
             }
           }
           months[key][item.title] = row.percent
         }
       }
+
       return {
-        columns: ['日期', ...values.map(item => item.title)],
+        columns: ['日期', ...values.map(item => {
+          return item.title
+        })],
         rows: Object.values(months)
       }
     },
@@ -93,8 +126,55 @@ export default {
   data () {
     return {
       active: 'ACTIVATION_RATE',
+       mdate: [],
+       loading:false
     }
   },
+  mounted(){
+    let nowTiem = this.$helpers.dayjs(new Date()).format('YYYY-MM-DD')
+    let startTime =  this.$helpers.dayjs(getNowDateAndMonday(nowTiem)).subtract(56,'day').format('YYYY-MM-DD')
+    let endTime = getNowDateAndSunday(nowTiem)
+    this.mdate = [startTime,endTime];
+    this.FetchDetail();
+
+  },
+  methods:{
+   changeValue(date) {
+      // 请求更改数据
+      this.mdate = date;
+      //  this.isDayOrMoth(date)
+      this.FetchDetail();
+    },
+    async FetchDetail() {
+      this.loading = true;
+      const data = this.data;
+      try {
+        const { dates, ...rest } = this.search;
+        const res = await getIndex({
+          ...rest,
+          ...getTimes(this.mdate, ["startDate", "endDate"]),
+        });
+        for (const item of res.data) {
+          // 再循环一遍
+          for (const key in this.items) {
+
+            if (item.dataType == key) {
+              data[item.dataType] = {
+                ...item,
+                desc: descs[item.dataType],
+              };
+            }
+          }
+        }
+
+      } catch (error) {
+        console.log(error);
+      }
+      this.loading = false
+      this.dataInfo = data;
+      this.$emit("resetDate", data);
+    },
+  }
 }
 </script>
 <style lang="less" scoped>
@@ -106,4 +186,12 @@ export default {
   //     }
   //   }
   // }
+  .chioseBox {
+  position: absolute;
+  right: 20px;
+  z-index: 1000;
+}
+.wrap {
+  position: relative;
+}
 </style>

+ 183 - 51
src/views/main/baseinfo/curriculum.vue

@@ -1,92 +1,224 @@
-<template>
-  <el-card header="课程数据">
+<template v-loading="loading"
+    element-loading-spinner="el-icon-loading"
+    element-loading-background="rgba(0, 0, 0, 0.8)">
+  <el-card>
+    <div slot="header" class="clearfix">
+      <searchHeader
+        :dates="mdate"
+        :title="'课程数据'"
+        @changeValue="changeValue"
+        :isShowQuert="true"
+      />
+    </div>
     <statistic class="statistic" :cols="0">
-      <statistic-item v-for="(item, key) in items" :key="key" :class="{active: active === key}" @click="active = key">
+      <statistic-item
+        v-for="(item, key) in items"
+        :key="key"
+        :class="{ active: active === key }"
+        @click="active = key"
+      >
         <span>
-          {{item.title}}
-          <el-tooltip v-if="item.desc" :content="item.desc" :open-delay=".3" placement="top">
-            <i style="margin-left: 5px;cursor: pointer;" class="el-icon-warning-outline"/>
+          {{ item.title }}
+          <el-tooltip
+            v-if="item.desc"
+            :content="item.desc"
+            :open-delay="0.3"
+            placement="top"
+          >
+            <i
+              style="margin-left: 5px; cursor: pointer"
+              class="el-icon-warning-outline"
+            />
           </el-tooltip>
         </span>
         <span>
-          <count-to :endVal="item.percent"/>
+          <count-to :endVal="item.percent" />
         </span>
       </statistic-item>
     </statistic>
-    <ve-line :settings="{
-        area: true,
-      }"
-      :data="chartData"
-      height="350px"
-      :data-empty="dataEmpty"
-      :data-zoom="dataZoom"
-    />
+    <div class="wrap">
+        <div class="chioseBox">
+        <el-radio-group v-model="timer" size="mini">
+          <el-radio-button label="day">按天</el-radio-button>
+          <el-radio-button label="month">按月</el-radio-button>
+        </el-radio-group>
+      </div>
+      <!-- :data-zoom="dataZoom" -->
+      <ve-line
+        :settings="{
+          area: true,
+        }"
+       :data="timer == 'day'?chartData:chartDataForMoth"
+        height="350px"
+        :data-empty="dataEmpty"
+
+        :legend="legend"
+      />
+    </div>
   </el-card>
 </template>
 <script>
-import 'echarts/lib/component/dataZoom'
-import countTo from 'vue-count-to'
-import veLine from 'v-charts/lib/line.common'
+import "echarts/lib/component/dataZoom";
+import countTo from "vue-count-to";
+import veLine from "v-charts/lib/line.common";
+import searchHeader from "./modals/searchHeader";
+import { getIndex } from "../api";
+import { getTimes } from "@/utils";
+import { descs, chioseNum } from "../constant";
 export default {
-  props: ['data'],
+  props: ["data","search"],
   components: {
-    've-line': veLine,
-    'count-to': countTo
+    "ve-line": veLine,
+    "count-to": countTo,
+    searchHeader,
   },
   computed: {
+    legend() {
+      return {
+        left: "10px",
+      };
+    },
     items() {
       return {
-        MUSIC_GROUP_COURSE: this.data['MUSIC_GROUP_COURSE'] || {},
-        VIP_GROUP_COURSE: this.data['VIP_GROUP_COURSE'] || {},
-        PRACTICE_GROUP_COURSE: this.data['PRACTICE_GROUP_COURSE'] || {},
-      }
+        MUSIC_GROUP_COURSE: this.data["MUSIC_GROUP_COURSE"] || {},
+        VIP_GROUP_COURSE: this.data["VIP_GROUP_COURSE"] || {},
+        PRACTICE_GROUP_COURSE: this.data["PRACTICE_GROUP_COURSE"] || {},
+      };
     },
     dataZoom() {
       return [
         {
-          type: 'slider',
+          type: "slider",
           start: 50,
-          end: 100
-        }
-      ]
+          end: 100,
+        },
+      ];
     },
     chartData() {
-      const values = Object.values(this.items)
-      const months = {}
+      const values = Object.values(this.items);
+      const months = {};
       for (const item of values) {
-        for (const row of (item.indexMonthData || [])) {
-          const key = this.$helpers.dayjs(row.month).format('YYYY-MM-DD')
+        for (const row of item.indexMonthData || []) {
+          const key = this.$helpers.dayjs(row.month).format("YYYY-MM-DD");
           if (!months[key]) {
             months[key] = {
-              '日期': key,
-            }
+              日期: key,
+            };
           }
-          months[key][item.title] = row.percent
+          months[key][item.title] = row.percent;
         }
       }
       return {
-        columns: ['日期', ...values.map(item => item.title)],
-        rows: Object.values(months)
+        columns: ["日期", ...values.map((item) => item.title)],
+        rows: Object.values(months),
+      };
+    },
+    chartDataForMoth(){
+
+      const values = Object.values(this.items);
+      console.log(values)
+      const months = {};
+      for (const item of values) {
+        for (const row of item.indexMonthData || []) {
+          const key = this.$helpers.dayjs(row.month).format("YYYY-MM");
+
+          if (!months[key]) {
+            months[key] = {
+              '月份': key,
+            };
+              months[key][item.title] = row.percent;
+          }else{
+            if( months[key][item.title]){
+               months[key][item.title] +=parseFloat(row.percent);
+            }else{
+               months[key][item.title]=row.percent
+            }
+
+          }
+
+        }
       }
+
+      return {
+        columns: ["月份", ...values.map((item) => item.title)],
+        rows: Object.values(months),
+      };
     },
     dataEmpty() {
-      return !this.chartData.rows.length
+      return !this.chartData.rows.length;
     },
   },
-  data () {
+  data() {
     return {
-      active: 'MUSIC_GROUP_COURSE',
-    }
+      active: "MUSIC_GROUP_COURSE",
+      timer: "day",
+        mdate: this.search?.dates,
+        loading:false
+    };
   },
-}
+  methods:{
+        changeValue(date) {
+      // 请求更改数据
+      this.mdate = date;
+       this.isDayOrMoth(date)
+      this.FetchDetail();
+    },
+    async FetchDetail() {
+      this.loading = true
+      const data = this.data;
+      try {
+        const { dates, ...rest } = this.search;
+        const res = await getIndex({
+          ...rest,
+          ...getTimes(this.mdate, ["startDate", "endDate"]),
+        });
+        for (const item of res.data) {
+          // 再循环一遍
+          for (const key in this.items) {
+            // console.log(key);
+            if (item.dataType == key) {
+              data[item.dataType] = {
+                ...item,
+                desc: descs[item.dataType],
+              };
+            }
+          }
+        }
+      } catch (error) {
+        console.log(error);
+      }
+      console.log(data)
+      this.loading = false
+      this.dataInfo = data;
+      this.$emit("resetDate", data);
+    },
+     isDayOrMoth(arr){
+      console.log(arr)
+      if(!arr || arr.length<1){
+        this.timer = 'day'
+      }else {
+        const count = this.$helpers.dayjs(arr[0]).diff(this.$helpers.dayjs(arr[1]),'day')
+        Math.abs(count)>chioseNum?this.timer = 'month':this.timer = 'day'
+      }
+    }
+  }
+};
 </script>
 <style lang="less" scoped>
-  // .statistic{
-  //   /deep/ .statistic-content{
-  //     cursor: pointer;
-  //     &.active > span{
-  //       color: #14928a !important;
-  //     }
-  //   }
-  // }
+// .statistic{
+//   /deep/ .statistic-content{
+//     cursor: pointer;
+//     &.active > span{
+//       color: #14928a !important;
+//     }
+//   }
+// }
+.chioseBox {
+  position: absolute;
+  right: 20px;
+  z-index: 1000;
+}
+.wrap {
+  position: relative;
+}
 </style>

+ 13 - 5
src/views/main/baseinfo/hr.vue

@@ -1,5 +1,12 @@
 <template>
-  <el-card header="人事数据">
+  <el-card >
+      <div slot="header" class="clearfix">
+        <div class="box">
+          <span class='shape'></span>
+          <span>人事数据</span>
+        </div>
+
+      </div>
     <statistic class="statistic" :cols="0">
       <statistic-item v-for="(item, key) in items" :key="key" :class="{active: active === key}" @click="active = key">
         <span>
@@ -9,18 +16,18 @@
           </el-tooltip>
         </span>
         <span>
-          <count-to :endVal="item.percent"/>
+          <count-to :endVal="item.percent"/>
         </span>
       </statistic-item>
     </statistic>
-    <ve-histogram
+    <!-- <ve-histogram
       style="width: 100%;"
       height="350px"
       :data="chartData"
       :data-empty="dataEmpty"
       :data-zoom="dataZoom"
       :extend="chartExtend"
-    ></ve-histogram>
+    ></ve-histogram> -->
   </el-card>
 </template>
 <script>
@@ -33,13 +40,14 @@ export default {
     've-histogram': veHistogram,
     'count-to': countTo
   },
+  //     DIMISSION_NUM: this.data['DIMISSION_NUM'] || {},
   computed: {
     items() {
       return {
         TEACHER_NUM: this.data['TEACHER_NUM'] || {},
         FULL_TIME_NUM: this.data['FULL_TIME_NUM'] || {},
         PART_TIME_NUM: this.data['PART_TIME_NUM'] || {},
-        DIMISSION_NUM: this.data['DIMISSION_NUM'] || {},
+
       }
     },
     chartExtend() {

+ 169 - 104
src/views/main/baseinfo/index.vue

@@ -1,7 +1,15 @@
 <template>
-  <div class="container">
-    <save-form inline :model="search" @submit="FetchDetail" @reset="reset" saveKey="/main/main/baseInfo">
-      <el-form-item prop="year">
+  <div
+    class="container"
+  >
+    <save-form
+      inline
+      :model="search"
+      @submit="FetchDetail"
+      @reset="reset"
+      saveKey="/main/main/baseInfo"
+    >
+      <!-- <el-form-item prop="year">
         <el-date-picker
           v-model="search.dates"
           type="daterange"
@@ -12,7 +20,7 @@
           end-placeholder="结束日期"
           :picker-options="pickerOptions">
         </el-date-picker>
-      </el-form-item>
+      </el-form-item> -->
       <el-form-item prop="organId">
         <el-select
           clearable
@@ -20,59 +28,75 @@
           placeholder="请选择分部"
           v-model="search.organId"
         >
-          <el-option v-for="(item,index) in selects.branchs"
+          <el-option
+            v-for="(item, index) in selects.branchs"
             :key="index"
             :label="item.name"
-            :value="item.id"></el-option>
+            :value="item.id"
+          ></el-option>
         </el-select>
       </el-form-item>
       <el-button native-type="submit" type="primary">搜索</el-button>
       <el-button native-type="reset" type="danger">重置</el-button>
     </save-form>
-    <el-alert type="info" :closable="false" style="margin-bottom: 20px;">
+    <!-- <el-alert type="info" :closable="false" style="margin-bottom: 20px;">
       每日0点更新前一日数据
-    </el-alert>
-    <empty desc="暂无统计数据" v-if="isEmpty"/>
+    </el-alert> -->
+    <!-- 这里显示选项卡 -->
+    <empty desc="暂无统计数据" v-if="isEmpty" />
     <el-row v-else class="rows" :gutter="20">
-      <el-col :xs="24" :sm="24" :md="12">
-        <student :data="dataInfo"/>
+      <el-col :xs="24" :sm="24" :md="24" :lg="9" :xl="9">
+        <studentbaseinfo :data="dataInfo" />
       </el-col>
-      <el-col :xs="24" :sm="24" :md="12" :xl="12">
-        <management :data="dataInfo"/>
+      <el-col :xs="24" :sm="24" :md="24" :lg="6" :xl="6">
+        <operate :data="dataInfo" />
       </el-col>
-      <el-col :xs="24" :sm="24" :md="12">
-        <business :data="dataInfo"/>
+      <el-col :xs="24" :sm="24" :md="24" :lg="9" :xl="9">
+        <hrdata :data="dataInfo" />
       </el-col>
-      <el-col :xs="24" :sm="24" :md="12">
-        <curriculum :data="dataInfo"/>
+      <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
+        <surplusCourse :data="dataInfo" />
       </el-col>
-      <el-col :xs="24" :sm="24" :md="12">
-        <operate :data="dataInfo"/>
+      <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
+        <useCourse :data="dataInfo" />
       </el-col>
-      <el-col :xs="24" :sm="24" :md="12">
-        <hrdata :data="dataInfo"/>
+      <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12">
+        <management :data="dataInfo" :search="search" @resetDate="resetDate" />
+      </el-col>
+      <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12">
+        <business :data="dataInfo" :search="search" @resetDate="resetDate" />
       </el-col>
+        <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+        <curriculum :data="dataInfo" :search="search" @resetDate="resetDate" />
+      </el-col>
+      <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+        <student :data="dataInfo" :search="search" @resetDate="resetDate" />
+      </el-col>
+
+
+      <!-- <el-col :xs="24" :sm="24" :md="12">
+        <operate :data="dataInfo"/>
+      </el-col> -->
+      <!-- <el-col :xs="24" :sm="24" :md="12">
+        <hrdata :data="dataInfo"/>
+      </el-col> -->
     </el-row>
   </div>
 </template>
 <script>
-import { getIndex } from '../api'
-import operate from './operate'
-import business from './business'
-import management from './management'
-import hrdata from './hr'
-import student from './student'
-import curriculum from './curriculum'
-import { getTimes } from '@/utils'
-import { descs } from '../constant'
+import { getIndex } from "../api";
+import operate from "./operate";
+import business from "./business";
+import management from "./management";
+import hrdata from "./hr";
+import student from "./student";
+import curriculum from "./curriculum";
+import studentbaseinfo from "./studentBaseinfo";
+import surplusCourse from "./surplusCourse";
+import useCourse from "./useCourse";
+import { getTimes } from "@/utils";
+import { descs } from "../constant";
 
-const getInitDate = () => {
-  const end = new Date();
-  const start = new Date();
-  end.setTime(end.getTime() - 3600 * 1000 * 24 * 1);
-  start.setTime(start.getTime() - 3600 * 1000 * 24 * 8);
-  return [start, end]
-}
 export default {
   components: {
     operate,
@@ -81,104 +105,145 @@ export default {
     hrdata,
     student,
     curriculum,
+    studentbaseinfo,
+    surplusCourse,
+    useCourse,
   },
-  data () {
+  data() {
     return {
       pickerOptions: {
-          firstDayOfWeek: 1,
-        disabledDate: a => {
-          const { dayjs } = this.$helpers
-          return dayjs(a).isAfter(dayjs().subtract(1, 'day'))
+        disabledDate: (a) => {
+          const { dayjs } = this.$helpers;
+          return dayjs(a).isAfter(dayjs().subtract(1, "day"));
         },
-        shortcuts: [{
-          text: '最近一周',
-          onClick(picker) {
-            const end = new Date();
-            const start = new Date();
-            end.setTime(end.getTime() - 3600 * 1000 * 24 * 1);
-            start.setTime(start.getTime() - 3600 * 1000 * 24 * 8);
-            picker.$emit('pick', [start, end]);
-          }
-        }, {
-          text: '最近一个月',
-          onClick(picker) {
-            const end = new Date();
-            const start = new Date();
-            end.setTime(end.getTime() - 3600 * 1000 * 24 * 1);
-            start.setTime(start.getTime() - 3600 * 1000 * 24 * 31);
-            picker.$emit('pick', [start, end]);
-          }
-        }, {
-          text: '最近三个月',
-          onClick(picker) {
-            const end = new Date();
-            const start = new Date();
-            end.setTime(end.getTime() - 3600 * 1000 * 24 * 1);
-            start.setTime(start.getTime() - 3600 * 1000 * 24 * 91);
-            picker.$emit('pick', [start, end]);
-          }
-        }]
+        shortcuts: [
+          {
+            text: "最近一周",
+            onClick(picker) {
+              const end = new Date();
+              const start = new Date();
+              end.setTime(end.getTime() - 3600 * 1000 * 24 * 1);
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 8);
+              picker.$emit("pick", [start, end]);
+            },
+          },
+          {
+            text: "最近一个月",
+            onClick(picker) {
+              const end = new Date();
+              const start = new Date();
+              end.setTime(end.getTime() - 3600 * 1000 * 24 * 1);
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 31);
+              picker.$emit("pick", [start, end]);
+            },
+          },
+          {
+            text: "最近三个月",
+            onClick(picker) {
+              const end = new Date();
+              const start = new Date();
+              end.setTime(end.getTime() - 3600 * 1000 * 24 * 1);
+              start.setTime(start.getTime() - 3600 * 1000 * 24 * 91);
+              picker.$emit("pick", [start, end]);
+            },
+          },
+        ],
       },
       search: {
-        dates: [],
-        organId: null
+        dates:[],
+        organId: null,
       },
       dataInfo: {},
       business: {},
-    }
+      loading: false,
+    };
   },
   computed: {
     isEmpty() {
-      return !Object.keys(this.dataInfo).length
-    }
+      return !Object.keys(this.dataInfo).length;
+    },
   },
-  created(){
-    this.$set(this.search, 'dates', getInitDate())
+  created() {
+
+
   },
-  mounted () {
-    this.FetchDetail()
-    //  this.reset() 和卧龙大佬商量过
-    this.$store.dispatch('setBranchs')
+  mounted() {
+     this.$set(this.search, "dates", this.getInitDate());
+    this.FetchDetail();
+    this.$store.dispatch("setBranchs");
   },
   methods: {
+    getInitDate() {
+      const end = this.$helpers
+        .dayjs(new Date())
+        .subtract(1, "day")
+        .format("YYYY-MM-DD");
+      const start = this.$helpers
+        .dayjs(new Date())
+        .subtract(1, "day")
+        .set("date", 1)
+        .format("YYYY-MM-DD");
+      return [start, end];
+    },
     reset() {
-      this.$set(this.search, 'dates', getInitDate())
-      this.$set(this.search, 'organId', null)
-      this.FetchDetail()
+      this.$set(this.search, "dates", this.getInitDate());
+      this.$set(this.search, "organId", null);
+      this.FetchDetail();
     },
     async FetchDetail() {
-      const data = {}
+      const data = {};
       try {
-        const {dates, ...rest} = this.search
+        const { dates, ...rest } = this.search;
         const res = await getIndex({
           ...rest,
-          ...getTimes(dates, ['startDate', 'endDate'])
-        })
+          ...getTimes(dates, ["startDate", "endDate"]),
+        });
         for (const item of res.data) {
           data[item.dataType] = {
             ...item,
-            desc: descs[item.dataType]
-          }
+            desc: descs[item.dataType],
+          };
         }
       } catch (error) {
-        console.log(error)
+        console.log(error);
       }
-      this.dataInfo = data
+      this.dataInfo = data;
     },
-  }
-}
+    resetDate(data) {
+      this.dataInfo = data;
+    },
+  },
+};
 </script>
 <style lang="less" scoped>
-  .container{
-    overflow: hidden;
-    .rows{
-      >div{
-        margin-bottom: 20px;
-      }
-    }
-    /deep/ .el-card__body .statistic {
-      margin-bottom: 15px;
-      padding: 0;
+.container {
+  overflow: hidden;
+  .rows {
+    > div {
+      margin-bottom: 20px;
     }
   }
+  /deep/ .el-card__body .statistic {
+    margin-bottom: 15px;
+    padding: 0;
+  }
+}
+/deep/.el-card__header {
+  padding: 0 20px !important;
+}
+</style>
+<style lang="scss">
+.box {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  height: 55px;
+  line-height: 55px;
+  .shape {
+    margin-right: 10px;
+    height: 18px;
+    width: 4px;
+    background-color: #14928a;
+  }
+}
 </style>

+ 218 - 59
src/views/main/baseinfo/management.vue

@@ -1,104 +1,263 @@
-<template>
-  <el-card header="经营数据">
+<template >
+  <el-card >
+    <div slot="header" class="clearfix">
+      <searchHeader
+        :dates="mdate"
+        :title="'经营数据'"
+        @changeValue="changeValue"
+        :isShowQuert='true'
+      />
+    </div>
     <statistic :col="5" class="statistic" :cols="0">
-      <statistic-item v-for="(item, key) in items" :key="key" :class="{active: active === key}" @click="active = key">
+      <statistic-item
+        v-for="(item, key) in items"
+        :key="key"
+        :class="{ active: active === key }"
+        @click="active = key"
+      >
         <span>
-          {{item.title}}
-          <el-tooltip v-if="item.desc" :content="item.desc" :open-delay=".3" placement="top">
-            <i style="margin-left: 5px;cursor: pointer;" class="el-icon-warning-outline"/>
+          {{ item.title }}
+          <el-tooltip
+            v-if="item.desc"
+            :content="item.desc"
+            :open-delay="0.3"
+            placement="top"
+          >
+            <i
+              style="margin-left: 5px; cursor: pointer"
+              class="el-icon-warning-outline"
+            />
           </el-tooltip>
         </span>
         <span>
-          <count-to :endVal="item.percent" :decimals="2"/>
+          <count-to :endVal="item.percent" :decimals="2" />
         </span>
       </statistic-item>
     </statistic>
-    <ve-line :settings="{
-        area: true,
-      }"
-      :data="chartData"
-      height="350px"
-      :data-empty="dataEmpty"
-      :data-zoom="dataZoom"
-      :extend="chartExtend"
-    />
+    <!-- 按月/按天 -->
+
+    <div class="wrap">
+      <div class="chioseBox">
+        <el-radio-group v-model="timer" size="mini">
+          <el-radio-button label="day">按天</el-radio-button>
+          <el-radio-button label="month">按月</el-radio-button>
+        </el-radio-group>
+      </div>
+      <!--   v-if="timer == 'day'"    DD-->
+      <ve-line
+
+        :settings="{
+            area: true,
+        }"
+        :data="timer == 'day'?chartData:chartDataForMoth"
+        height="350px"
+        :data-empty="dataEmpty"
+        :extend="chartExtend"
+        :legend="legend"
+      />
+          <!-- <ve-line
+      v-else
+        :data-zoom="dataZoom"
+        :settings="{
+          area: true,
+        }"
+        :data="chartDataForMoth"
+        height="350px"
+        :data-empty="dataEmpty"
+        :data-zoom="dataZoom"
+        :extend="chartExtend"
+        :legend="legend"
+      /> -->
+    </div>
   </el-card>
 </template>
 <script>
-import 'echarts/lib/component/dataZoom'
-import countTo from 'vue-count-to'
-import veLine from 'v-charts/lib/line.common'
+import "echarts/lib/component/dataZoom";
+import countTo from "vue-count-to";
+import veLine from "v-charts/lib/line.common";
+import searchHeader from "./modals/searchHeader";
+import { getIndex } from "../api";
+import { getTimes } from "@/utils";
+import { descs,chioseNum } from "../constant";
+
 export default {
-  props: ['data'],
+  props: ["data", "search"],
   components: {
-    've-line': veLine,
-    'count-to': countTo
+    "ve-line": veLine,
+    "count-to": countTo,
+    searchHeader,
   },
   computed: {
+    legend() {
+      return {
+        left: "10px",
+      };
+    },
     items() {
       return {
-        FINANCE_AMOUNT: this.data['FINANCE_AMOUNT'] || {},
-        FINANCE_BALANCE_AMOUNT: this.data['FINANCE_BALANCE_AMOUNT'] || {},
-        FINANCE_PAY: this.data['FINANCE_PAY'] || {},
-      }
+        FINANCE_AMOUNT: this.data["FINANCE_AMOUNT"] || {},
+        FINANCE_BALANCE_AMOUNT: this.data["FINANCE_BALANCE_AMOUNT"] || {},
+        FINANCE_PAY: this.data["FINANCE_PAY"] || {},
+      };
     },
     chartExtend() {
       return {
         tooltip: {
-          formatter: item => {
-            return [item[0].axisValueLabel, ...item.map(d => {
-              return `<br/>${d.marker}${d.seriesName}: ${this.$helpers.numeral(d.value[1]).format('0,0.00')}`
-            })].join('')
-          }
-        }
-      }
+          formatter: (item) => {
+            return [
+              item[0].axisValueLabel,
+              ...item.map((d) => {
+                return `<br/>${d.marker}${
+                  d.seriesName
+                }: ${this.$helpers.numeral(d.value[1]).format("0,0.00")}`;
+              }),
+            ].join("");
+          },
+        },
+      };
     },
     dataZoom() {
       return [
         {
-          type: 'slider',
+          type: "slider",
           start: 50,
-          end: 100
-        }
-      ]
+          end: 100,
+          filterMode: 'empty'
+        },
+      ];
     },
     chartData() {
-      const values = Object.values(this.items)
-      const months = {}
+      const values = Object.values(this.items);
+      const months = {};
       for (const item of values) {
-        for (const row of (item.indexMonthData || [])) {
-          const key = this.$helpers.dayjs(row.month).format('YYYY-MM-DD')
+        for (const row of item.indexMonthData || []) {
+          const key = this.$helpers.dayjs(row.month).format("YYYY-MM-DD");
           if (!months[key]) {
             months[key] = {
-              '日期': key,
-            }
+              日期: key,
+            };
           }
-          months[key][item.title] = row.percent
+          months[key][item.title] = row.percent;
         }
       }
       return {
-        columns: ['日期', ...values.map(item => item.title)],
-        rows: Object.values(months)
+        columns: ["日期", ...values.map((item) => item.title)],
+        rows: Object.values(months),
+           loading: true
+      };
+    },
+    chartDataForMoth(){
+
+      const values = Object.values(this.items);
+      console.log(values)
+      const months = {};
+      for (const item of values) {
+        for (const row of item.indexMonthData || []) {
+          const key = this.$helpers.dayjs(row.month).format("YYYY-MM");
+
+          if (!months[key]) {
+            months[key] = {
+              '月份': key,
+            };
+              months[key][item.title] = row.percent;
+          }else{
+            if( months[key][item.title]){
+               months[key][item.title] +=parseFloat(row.percent);
+            }else{
+               months[key][item.title]=row.percent
+            }
+
+          }
+
+        }
       }
+
+      return {
+        columns: ["月份", ...values.map((item) => item.title)],
+        rows: Object.values(months),
+         loading: true
+      };
     },
+
     dataEmpty() {
-      return !this.chartData.rows.length
+      return !this.chartData.rows.length;
     },
   },
-  data () {
+  data() {
     return {
-      active: 'SHOULD_INCOME_MONEY',
-    }
+      active: "SHOULD_INCOME_MONEY",
+      timer: "day",
+      mdate: this.search?.dates,
+      loading:false
+    };
   },
-}
+  created(){
+    console.log(this.search?.dates)
+  },
+  methods: {
+    changeValue(date) {
+      // 请求更改数据
+      this.mdate = date;
+       this.isDayOrMoth(date)
+      this.FetchDetail();
+    },
+    async FetchDetail() {
+      this.loading = true
+      const data = this.data;
+      try {
+        const { dates, ...rest } = this.search;
+        const res = await getIndex({
+          ...rest,
+          ...getTimes(this.mdate, ["startDate", "endDate"]),
+        });
+        for (const item of res.data) {
+          // 再循环一遍
+          for (const key in this.items) {
+            // console.log(key);
+            if (item.dataType == key) {
+              data[item.dataType] = {
+                ...item,
+                desc: descs[item.dataType],
+              };
+            }
+          }
+        }
+      } catch (error) {
+        console.log(error);
+      }
+      console.log(data)
+      this.dataInfo = data;
+      this.loading = false
+      this.$emit("resetDate", data);
+    },
+
+    isDayOrMoth(arr){
+      console.log(arr)
+      if(!arr || arr.length<1){
+        this.timer = 'day'
+      }else {
+        const count = this.$helpers.dayjs(arr[0]).diff(this.$helpers.dayjs(arr[1]),'day')
+        Math.abs(count)>chioseNum?this.timer = 'month':this.timer = 'day'
+      }
+    }
+  }
+};
 </script>
 <style lang="less" scoped>
-  // .statistic{
-  //   /deep/ .statistic-content{
-  //     cursor: pointer;
-  //     &.active > span{
-  //       color: #14928a !important;
-  //     }
-  //   }
-  // }
+// .statistic{
+//   /deep/ .statistic-content{
+//     cursor: pointer;
+//     &.active > span{
+//       color: #14928a !important;
+//     }
+//   }
+// }
+.chioseBox {
+  position: absolute;
+  right: 20px;
+  z-index: 1000;
+}
+.wrap {
+  position: relative;
+}
 </style>

+ 130 - 0
src/views/main/baseinfo/modals/searchHeader.vue

@@ -0,0 +1,130 @@
+<template>
+  <div class="titleWrap">
+    <div class="box">
+      <span class="shape"></span>
+      <span>{{title}}</span>
+    </div>
+    <div class="right">
+      <el-radio-group v-model="timer" size="mini" @change="changeQuick" v-if="isShowQuert">
+        <el-radio-button label="month">本月</el-radio-button>
+        <el-radio-button label="year">本年度</el-radio-button>
+        <el-radio-button label="lastYear">去年</el-radio-button>
+      </el-radio-group>
+      <el-date-picker
+      v-if="isShowQuert"
+        v-model="date"
+        type="daterange"
+        style="width: 300px;padding: 0 10px"
+        range-separator="-"
+        start-placeholder="开始日期"
+        end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          format="yyyy-MM-dd"
+        size="mini"
+        @change="changeValue"
+        :picker-options="{
+        firstDayOfWeek: 1
+    }"
+      >
+      </el-date-picker>
+            <el-date-picker
+      v-else
+        v-model="date"
+        type="daterange"
+        style="width: 300px;padding: 0 10px"
+        range-separator="-"
+        start-placeholder="开始日期"
+        end-placeholder="结束日期"
+          value-format="yyyy-MM-dd"
+          format="yyyy-MM-dd"
+        size="mini"
+      @change="changeWeek"
+        :picker-options="{
+        firstDayOfWeek: 1
+    }"
+      >
+      </el-date-picker>
+
+
+    </div>
+  </div>
+</template>
+<script>
+import {
+
+  getNowDateAndSunday,
+  getNowDateAndMonday,
+
+} from "@/utils/date";
+export default {
+  props:['title','dates','isShowQuert'],
+  data() {
+    return {
+      timer: "",
+      date:this.dates,
+    };
+  },
+  methods: {
+    changeWeek(val){
+      this.date = [getNowDateAndMonday(val[0]),getNowDateAndSunday(val[1])]
+      console.log( this.date)
+       this.submitDate( this.date)
+    },
+    changeValue(val) {
+       this.timer = ''
+       this.date = val;
+        this.submitDate( this.date)
+    },
+    changeQuick(val) {
+      let startDate;
+      let endDate;
+      if (val == "month") {
+        // 获取本月的第一天 获取本月的今天
+        startDate = this.$helpers
+          .dayjs(new Date())
+          .set("date", 1)
+          .format("YYYY-MM-DD");
+        endDate = this.$helpers.dayjs(new Date()).format("YYYY-MM-DD");
+        this.date = [startDate, endDate];
+        this.submitDate( this.date)
+      } else if (val == "year") {
+        startDate = this.$helpers
+          .dayjs(new Date())
+          .set("month", 0)
+          .set("date", 1)
+          .format("YYYY-MM-DD");
+        endDate = this.$helpers.dayjs(new Date()).format("YYYY-MM-DD");
+        this.date = [startDate, endDate];
+        this.submitDate( this.date)
+      } else if (val == "lastYear") {
+        startDate = this.$helpers
+          .dayjs(new Date())
+          .subtract(1, "year")
+          .set("month", 0)
+          .set("date", 1)
+          .format("YYYY-MM-DD");
+        endDate = this.$helpers
+          .dayjs()
+          .subtract(1, "year")
+          .endOf("year")
+          .format("YYYY-MM-DD");
+        this.date = [startDate, endDate];
+          this.submitDate( this.date)
+      }
+    },
+    submitDate(date){
+      this.$emit('changeValue',date)
+    }
+  },
+};
+</script>
+<style lang="scss" scoped>
+.titleWrap {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  .right {
+    margin-top: 15px;
+  }
+}
+</style>

+ 12 - 5
src/views/main/baseinfo/operate.vue

@@ -1,5 +1,12 @@
 <template>
-  <el-card header="运营数据">
+  <el-card >
+          <div slot="header" class="clearfix">
+        <div class="box">
+          <span class='shape'></span>
+          <span>运营数据</span>
+        </div>
+
+      </div>
     <statistic class="statistic" :cols="0">
       <statistic-item v-for="(item, key) in items" :key="key" :class="{active: active === key}" @click="active = key">
         <span>
@@ -9,18 +16,18 @@
           </el-tooltip>
         </span>
         <span>
-          <count-to :endVal="item.percent"/>
+          <count-to :endVal="item.percent"/>
         </span>
       </statistic-item>
     </statistic>
-    <ve-histogram
+    <!-- <ve-histogram
       style="width: 100%;"
       height="350px"
       :data="chartData"
       :data-empty="dataEmpty"
       :data-zoom="dataZoom"
       :extend="chartExtend"
-    ></ve-histogram>
+    ></ve-histogram> -->
   </el-card>
 </template>
 <script>
@@ -37,7 +44,7 @@ export default {
     items() {
       return {
         SCHOOL: this.data['SCHOOL'] || {},
-        MUSIC_GROUP_NUM: this.data['MUSIC_GROUP_NUM'] || {},
+        PROGRESS_MUSIC_GROUP_NUM: this.data['PROGRESS_MUSIC_GROUP_NUM'] || {},
       }
     },
     chartExtend() {

+ 204 - 87
src/views/main/baseinfo/student.vue

@@ -1,138 +1,255 @@
-<template>
+<template
+v-loading="loading"
+    element-loading-spinner="el-icon-loading"
+    element-loading-background="rgba(0, 0, 0, 0.8)">
   <el-card>
     <div slot="header" class="clearfix">
-      <span>学员变动</span>
-      <el-button
-        @click="isHistogram = !isHistogram"
-        style="float: right; padding: 0px 0"
-        type="text"
-      >{{isHistogram ? '学员转化漏斗图' : '学员柱状图'}}</el-button>
+      <searchHeader
+        :dates="mdate"
+        :title="'学员变动'"
+        @changeValue="changeValue"
+        :isShowQuert="true"
+      />
     </div>
-    <statistic :col="5" class="statistic" :cols="0">
-      <statistic-item v-for="(item, key) in items" :key="key" :class="{active: active === key}" @click="active = key">
+    <statistic :col="6" class="statistic" :cols="0">
+      <statistic-item
+        v-for="(item, key) in items"
+        :key="key"
+        :class="{ active: active === key }"
+        @click="active = key"
+      >
         <span>
-          {{item.title}}
-          <el-tooltip v-if="item.desc" :content="item.desc" :open-delay=".3" placement="top">
-            <i style="margin-left: 5px;cursor: pointer;" class="el-icon-warning-outline"/>
+          {{ item.title }}
+          <el-tooltip
+            v-if="item.desc"
+            :content="item.desc"
+            :open-delay="0.3"
+            placement="top"
+          >
+            <i
+              style="margin-left: 5px; cursor: pointer"
+              class="el-icon-warning-outline"
+            />
           </el-tooltip>
         </span>
-        <span>
-          <count-to :endVal="item.percent"/>
-        </span>
-      </statistic-item>
-      <statistic-item>
-        <span>
-          {{data['STUDENT_CONVERSION'].title}}
-          <el-tooltip v-if="data['STUDENT_CONVERSION'].desc" :content="data['STUDENT_CONVERSION'].desc" :open-delay=".3" placement="top">
-            <i style="margin-left: 5px;cursor: pointer;" class="el-icon-warning-outline"/>
-          </el-tooltip>
-        </span>
-        <span>
-          <count-to :endVal="data['STUDENT_CONVERSION'].percent"/>%
-        </span>
+        <span> <count-to :endVal="item.percent" />人 </span>
       </statistic-item>
     </statistic>
-    <ve-histogram
-      style="width: 100%;"
-      height="350px"
-      :data="chartData"
-      :data-empty="dataEmpty"
-      :data-zoom="dataZoom"
-      :extend="chartExtend"
-       v-if="isHistogram"
-    ></ve-histogram>
-    <ve-funnel v-else style="width: 100%;" height="350px" :data="funnelData" :data-empty="dataEmpty"></ve-funnel>
+    <div class="wrap">
+      <div class="chioseBox">
+        <el-radio-group v-model="timer" size="mini">
+          <el-radio-button label="day">按天</el-radio-button>
+          <el-radio-button label="month">按月</el-radio-button>
+        </el-radio-group>
+      </div>
+      <!--  :data-zoom="dataZoom" -->
+      <ve-line
+        style="width: 100%"
+        height="350px"
+        :data="timer == 'day' ? chartData : chartDataForMoth"
+        :data-empty="dataEmpty"
+
+        :extend="chartExtend"
+        :legend="legend"
+      ></ve-line>
+    </div>
+    <!-- <ve-funnel v-else style="width: 100%;" height="350px" :data="funnelData" :data-empty="dataEmpty"></ve-funnel> -->
   </el-card>
 </template>
 <script>
-import countTo from 'vue-count-to'
-import veHistogram from 'v-charts/lib/histogram.common'
-import veFunnel from 'v-charts/lib/funnel.common'
+import countTo from "vue-count-to";
+import veLine from "v-charts/lib/line.common";
+import veFunnel from "v-charts/lib/funnel.common";
+import searchHeader from "./modals/searchHeader";
+import { getIndex } from "../api";
+import { getTimes } from "@/utils";
+import { descs, chioseNum } from "../constant";
 export default {
-  props: ['data'],
+  props: ["data", "search"],
   components: {
-    've-funnel': veFunnel,
-    've-histogram': veHistogram,
-    'count-to': countTo
+    "ve-funnel": veFunnel,
+      "ve-line": veLine,
+    "count-to": countTo,
+    searchHeader,
   },
   computed: {
+    legend() {
+      return {
+        left: "10px",
+      };
+    },
     items() {
       return {
-        MUSIC_GROUP_STUDENT: this.data['MUSIC_GROUP_STUDENT'] || {},
-        OTHER_STUDENT: this.data['OTHER_STUDENT'] || {},
-        NEWLY_STUDENT_NUM: this.data['NEWLY_STUDENT_NUM'] || {},
-        QUIT_MUSIC_GROUP_STUDENT_NUM: this.data['QUIT_MUSIC_GROUP_STUDENT_NUM'] || {},
-      }
+        ADD_STUDENT_REGISTRATION_NUM:
+          this.data["ADD_STUDENT_REGISTRATION_NUM"] || {},
+        MUSIC_GROUP_STUDENT: this.data["MUSIC_GROUP_STUDENT"] || {},
+        NEWLY_STUDENT_NUM: this.data["NEWLY_STUDENT_NUM"] || {},
+        QUIT_MUSIC_GROUP_STUDENT_NUM:
+          this.data["QUIT_MUSIC_GROUP_STUDENT_NUM"] || {},
+        VIP_PRACTICE_STUDENT_NUM: this.data["VIP_PRACTICE_STUDENT_NUM"] || {},
+        VIP_PRACTICE_ADD_STUDENT_NUM:
+          this.data["VIP_PRACTICE_ADD_STUDENT_NUM"] || {},
+      };
     },
     chartExtend() {
       return {
         tooltip: {
           axisPointer: {
-            type: 'shadow',
+            type: "shadow",
             shadowStyle: {
-              color: 'rgba(150,150,150,0.2)'
-            }
-          }
-        }
-      }
+              color: "rgba(150,150,150,0.2)",
+            },
+          },
+        },
+      };
     },
     dataZoom() {
       return [
         {
-          type: 'slider',
+          type: "slider",
           start: 60,
-          end: 100
-        }
-      ]
+          end: 100,
+        },
+      ];
     },
     chartData() {
-      const values = Object.values(this.items)
-      const months = {}
+      const values = Object.values(this.items);
+      const months = {};
       for (const item of values) {
-        for (const row of (item.indexMonthData || [])) {
-          const key = this.$helpers.dayjs(row.month).format('YYYY-MM-DD')
+        for (const row of item.indexMonthData || []) {
+          const key = this.$helpers.dayjs(row.month).format("YYYY-MM-DD");
           if (!months[key]) {
             months[key] = {
-              '日期': key,
-            }
+              日期: key,
+            };
           }
-          months[key][item.title] = row.percent
+          months[key][item.title] = row.percent;
         }
       }
       return {
-        columns: ['日期', ...values.map(item => item.title)],
-        rows: Object.values(months)
+        columns: ["日期", ...values.map((item) => item.title)],
+        rows: Object.values(months),
+      };
+    },
+    chartDataForMoth() {
+      const values = Object.values(this.items);
+      console.log(values);
+      const months = {};
+      for (const item of values) {
+        for (const row of item.indexMonthData || []) {
+          const key = this.$helpers.dayjs(row.month).format("YYYY-MM");
+
+          if (!months[key]) {
+            months[key] = {
+              月份: key,
+            };
+            months[key][item.title] = row.percent;
+          } else {
+            if (months[key][item.title]) {
+              months[key][item.title] += parseFloat(row.percent);
+            } else {
+              months[key][item.title] = row.percent;
+            }
+          }
+        }
       }
+
+      return {
+        columns: ["月份", ...values.map((item) => item.title)],
+        rows: Object.values(months),
+      };
     },
     funnelData() {
-      const { indexMonthData = [] } = this.data['STUDENT_CONVERSION'] || {}
+      const { indexMonthData = [] } = this.data["STUDENT_CONVERSION"] || {};
       return {
-        columns: ['类型', '数值'],
-        rows: indexMonthData.map(item => ({
-          '类型': item.title,
-          '数值': item.percent
-        }))
-      }
+        columns: ["类型", "数值"],
+        rows: indexMonthData.map((item) => ({
+          类型: item.title,
+          数值: item.percent,
+        })),
+      };
     },
     dataEmpty() {
-      return !this.chartData.rows.length
+      return !this.chartData.rows.length;
     },
   },
-  data () {
+  data() {
     return {
-      active: 'NEWLY_STUDENT_NUM',
+      active: "NEWLY_STUDENT_NUM",
       isHistogram: true,
-    }
+      timer: "day",
+      mdate: this.search?.dates,
+      loading: false,
+    };
   },
-}
+  methods: {
+    changeValue(date) {
+      // 请求更改数据
+      this.mdate = date;
+      this.isDayOrMoth(date);
+      this.FetchDetail();
+    },
+    async FetchDetail() {
+      this.loading = true;
+      const data = this.data;
+      try {
+        const { dates, ...rest } = this.search;
+        const res = await getIndex({
+          ...rest,
+          ...getTimes(this.mdate, ["startDate", "endDate"]),
+        });
+        for (const item of res.data) {
+          // 再循环一遍
+          for (const key in this.items) {
+            // console.log(key);
+            if (item.dataType == key) {
+              data[item.dataType] = {
+                ...item,
+                desc: descs[item.dataType],
+              };
+            }
+          }
+        }
+      } catch (error) {
+        console.log(error);
+      }
+      console.log(data);
+      this.loading = false;
+      this.dataInfo = data;
+      this.$emit("resetDate", data);
+    },
+
+    isDayOrMoth(arr) {
+      console.log(arr);
+      if (!arr || arr.length < 1) {
+        this.timer = "day";
+      } else {
+        const count = this.$helpers
+          .dayjs(arr[0])
+          .diff(this.$helpers.dayjs(arr[1]), "day");
+        Math.abs(count) > chioseNum
+          ? (this.timer = "month")
+          : (this.timer = "day");
+      }
+    },
+  },
+};
 </script>
 <style lang="less" scoped>
-  // .statistic{
-  //   /deep/ .statistic-content{
-  //     cursor: pointer;
-  //     &.active > span{
-  //       color: #14928a !important;
-  //     }
-  //   }
-  // }
+// .statistic{
+//   /deep/ .statistic-content{
+//     cursor: pointer;
+//     &.active > span{
+//       color: #14928a !important;
+//     }
+//   }
+// }
+.chioseBox {
+  position: absolute;
+  right: 20px;
+  z-index: 1000;
+}
+.wrap {
+  position: relative;
+}
 </style>

+ 106 - 0
src/views/main/baseinfo/studentBaseinfo.vue

@@ -0,0 +1,106 @@
+<template>
+  <div>
+    <el-card>
+      <div slot="header" class="clearfix">
+        <div class="box">
+          <span class='shape'></span>
+          <span>学员数据</span>
+        </div>
+
+      </div>
+      <statistic :col="5" class="statistic" :cols="0">
+        <statistic-item
+          v-for="(item, key) in items"
+          :key="key"
+          :class="{ active: active === key }"
+          @click="active = key"
+        >
+          <span>
+            {{ item.title }}
+            <el-tooltip
+              v-if="item.desc"
+              :content="item.desc"
+              :open-delay="0.3"
+              placement="top"
+            >
+              <i
+                style="margin-left: 5px; cursor: pointer"
+                class="el-icon-warning-outline"
+              />
+            </el-tooltip>
+          </span>
+          <span>
+            <count-to :endVal="item.percent" />人
+          </span>
+        </statistic-item>
+
+        <statistic-item v-if='data["CHARGE_STUDENT_CHANGE_RATE"]'>
+          <span>
+            {{ data["CHARGE_STUDENT_CHANGE_RATE"].title }}
+            <el-tooltip
+              v-if="data['CHARGE_STUDENT_CHANGE_RATE'].desc"
+              :content="data['CHARGE_STUDENT_CHANGE_RATE'].desc"
+              :open-delay="0.3"
+              placement="top"
+            >
+              <i
+                style="margin-left: 5px; cursor: pointer"
+                class="el-icon-warning-outline"
+              />
+            </el-tooltip>
+          </span>
+          <span>
+            <count-to :endVal="data['CHARGE_STUDENT_CHANGE_RATE'].percent" />%
+          </span>
+        </statistic-item>
+           <statistic-item v-if='data["ACTIVATION_RATE"]'>
+          <span>
+            {{ data["ACTIVATION_RATE"].title }}
+            <el-tooltip
+              v-if="data['ACTIVATION_RATE'].desc"
+              :content="data['ACTIVATION_RATE'].desc"
+              :open-delay="0.3"
+              placement="top"
+            >
+              <i
+                style="margin-left: 5px; cursor: pointer"
+                class="el-icon-warning-outline"
+              />
+            </el-tooltip>
+          </span>
+          <span>
+            <count-to :endVal="data['ACTIVATION_RATE'].percent" />%
+          </span>
+        </statistic-item>
+      </statistic>
+    </el-card>
+  </div>
+</template>
+<script>
+import countTo from "vue-count-to";
+export default {
+  props: ["data"],
+  components: {
+    "count-to": countTo,
+  },
+  data() {
+    return {
+      active:''
+    };
+  },
+  computed: {
+    dataEmpty() {
+      return !this.chartData.rows.length;
+    },
+    //         CHARGE_STUDENT_CHANGE_RATE: this.data['CHARGE_STUDENT_CHANGE_RATE'] || {},
+    //    ACTIVATION_RATE: this.data['ACTIVATION_RATE'] || {},
+    items() {
+      return {
+        STUDENT_REGISTRATION_NUM: this.data['STUDENT_REGISTRATION_NUM'] || {},
+
+      }
+    },
+  },
+};
+</script>
+

+ 68 - 0
src/views/main/baseinfo/surplusCourse.vue

@@ -0,0 +1,68 @@
+<template>
+  <div>
+    <el-card>
+      <div slot="header" class="clearfix">
+        <div class="box">
+          <span class='shape'></span>
+          <span>剩余课时</span>
+        </div>
+
+      </div>
+      <statistic :col="5" class="statistic" :cols="0">
+        <statistic-item
+          v-for="(item, key) in items"
+          :key="key"
+          :class="{ active: active === key }"
+          @click="active = key"
+        >
+          <span>
+            {{ item.title }}
+            <el-tooltip
+              v-if="item.desc"
+              :content="item.desc"
+              :open-delay="0.3"
+              placement="top"
+            >
+              <i
+                style="margin-left: 5px; cursor: pointer"
+                class="el-icon-warning-outline"
+              />
+            </el-tooltip>
+          </span>
+          <span>
+            <count-to :endVal="item.percent" />节
+          </span>
+        </statistic-item>
+      </statistic>
+    </el-card>
+  </div>
+</template>
+<script>
+import countTo from "vue-count-to";
+export default {
+  props: ["data"],
+  components: {
+    "count-to": countTo,
+  },
+  data() {
+    return {
+      active:''
+    };
+  },
+  computed: {
+    dataEmpty() {
+      return !this.chartData.rows.length;
+    },
+    //         CHARGE_STUDENT_CHANGE_RATE: this.data['CHARGE_STUDENT_CHANGE_RATE'] || {},
+    //    ACTIVATION_RATE: this.data['ACTIVATION_RATE'] || {},
+    items() {
+      return {
+        SURPLUS_COURSE_NUM: this.data['SURPLUS_COURSE_NUM'] || {},
+        SURPLUS_MUSIC_COURSE_NUM: this.data['SURPLUS_MUSIC_COURSE_NUM'] || {},
+        SURPLUS_VIP_COURSE_NUM: this.data['SURPLUS_VIP_COURSE_NUM'] || {},
+        SURPLUS_PRACTICE_COURSE_NUM: this.data['SURPLUS_PRACTICE_COURSE_NUM'] || {},
+      }
+    },
+  },
+};
+</script>

+ 68 - 0
src/views/main/baseinfo/useCourse.vue

@@ -0,0 +1,68 @@
+<template>
+  <div>
+    <el-card>
+      <div slot="header" class="clearfix">
+        <div class="box">
+          <span class='shape'></span>
+          <span>已消耗课时</span>
+        </div>
+
+      </div>
+      <statistic :col="5" class="statistic" :cols="0">
+        <statistic-item
+          v-for="(item, key) in items"
+          :key="key"
+          :class="{ active: active === key }"
+          @click="active = key"
+        >
+          <span>
+            {{ item.title }}
+            <el-tooltip
+              v-if="item.desc"
+              :content="item.desc"
+              :open-delay="0.3"
+              placement="top"
+            >
+              <i
+                style="margin-left: 5px; cursor: pointer"
+                class="el-icon-warning-outline"
+              />
+            </el-tooltip>
+          </span>
+          <span>
+            <count-to :endVal="item.percent" />节
+          </span>
+        </statistic-item>
+      </statistic>
+    </el-card>
+  </div>
+</template>
+<script>
+import countTo from "vue-count-to";
+export default {
+  props: ["data"],
+  components: {
+    "count-to": countTo,
+  },
+  data() {
+    return {
+      active:''
+    };
+  },
+  computed: {
+    dataEmpty() {
+      return !this.chartData.rows.length;
+    },
+    //         CHARGE_STUDENT_CHANGE_RATE: this.data['CHARGE_STUDENT_CHANGE_RATE'] || {},
+    //    ACTIVATION_RATE: this.data['ACTIVATION_RATE'] || {},
+    items() {
+      return {
+        OVER_COURSE_NUM: this.data['OVER_COURSE_NUM'] || {},
+        OVER_MUSIC_COURSE_NUM: this.data['OVER_MUSIC_COURSE_NUM'] || {},
+        OVER_VIP_COURSE_NUM: this.data['OVER_VIP_COURSE_NUM'] || {},
+        OVER_PRACTICE_COURSE_NUM: this.data['OVER_PRACTICE_COURSE_NUM'] || {},
+      }
+    },
+  },
+};
+</script>

+ 33 - 26
src/views/main/constant.js

@@ -1,32 +1,37 @@
 import dayjs from 'dayjs'
 
 export const descs = {
-  SCHOOL: '截止到当日,【进行中】乐团的【合作单位】总数', // 合作单位
-  MUSIC_GROUP_NUM: '截止到当日,【进行中】乐团总数', // 乐团数量
-  MUSIC_GROUP_STUDENT: '截止到当日,【进行中】乐团【在读】学员总数,分部下去重', // 乐团学员
-  OTHER_STUDENT: '截止到当日,学员有剩余VIP/网管未上课时的人数总数,分部下去重', // 其他学员
-  ACTIVATION_RATE: '截止到当日,筹备中/进行中乐团在读学员和VIP/网管有课学员激活率', // 激活率
-  HOMEWORK_CREATE_RATE: '本月截止到当日服务指标的作业布置率', // 作业布置率
-  HOMEWORK_SUBMIT_RATE: '本月截止到当日已布置的作业学员提交率', // 作业提交率
-  HOMEWORK_COMMENT_RATE: '本月截止到当日学员已提交的作业老师点评率', // 作业点评率
-  SHOULD_INCOME_MONEY: '所有缴费项目应收金额总和', // 应收金额
-  ANTICIPATED_INCOME_MONEY: '已缴费但实际还未产生费用金额总和', // 预收金额
-  SHOULD_EXPEND_MONEY: '预计支出费用总和(暂无此数据)', // 预付金额
-  ANTICIPATED_EXPEND_MONEY: '应付金额总和(暂无此数据)', // 应付金额
-  REVENUE_MONEY: '营收金额总和', // 营收金额
-  TEACHER_NUM: '截止到当日,【非冻结】的老师总数', // 老师总数
-  FULL_TIME_NUM: '截止到当日,【非冻结】且工作类型为【全职】的老师总数', // 全职人数
-  PART_TIME_NUM: '截止到当日,【非冻结】且工作类型为【兼职】的老师总数', // 兼职人数
-  DIMISSION_NUM: '截止到当日,已冻结或将【离职时间】到筛选时间段内的老师总数', // 离职人数
-  NEWLY_STUDENT_NUM: '本年度截止到当日,新增的乐团【在读】学员总数(去重)', // 新增学员
-  QUIT_MUSIC_GROUP_STUDENT_NUM: '本年度截止到当日,乐团退团学员总数(去重)', // 退团学员
-  STUDENT_CONVERSION: '乐团预报名学员中正式报名缴费的学员购买VIP/网管课的转化率(不包括退团学员)', // 学员转化
-  MUSIC_GROUP_COURSE: '筛选时间段内,【已结束】乐团课程总数', // 乐团课
-  VIP_GROUP_COURSE: '筛选时间段内,【已结束】VIP课程总数', // VIP课
-  PRACTICE_GROUP_COURSE: '筛选时间段内,【已结束】网管课程总数', // 网管课
-  FINANCE_PAY: '筛选时间段内支出金额总和', // 财务支出
-  FINANCE_BALANCE_AMOUNT: '筛选时间段内余额消耗总和', // 余额收入
-  FINANCE_AMOUNT: '筛选时间段内现金收入总和', // 现金收入
+  STUDENT_REGISTRATION_NUM:'截止到昨日,系统注册学员总数',
+  CHARGE_STUDENT_CHANGE_RATE:'截止到昨日,在册学员付费率(有订单交易成功的都算,导入的也算)',
+  ACTIVATION_RATE:'截止到昨日,筹备中&进行中乐团在读学员和有VIP或网管课学员激活率',
+  SCHOOL:'截止到昨日,存在【进行中】乐团的【合作单位】总数',
+  PROGRESS_MUSIC_GROUP_NUM:'截止到昨日,【进行中】乐团总数',
+  TEACHER_NUM:'截止到昨日,非冻结,且离职时间在昨日之后的老师总数',
+  FULL_TIME_NUM:'截止到昨日,非冻结、离职时间在昨日之后,且工作类型为【全职】的老师总数',
+  PART_TIME_NUM:'截止到昨日,非冻结、离职时间在昨日之后,且工作类型为【兼职】的老师总数',
+  SURPLUS_COURSE_NUM:'截止到昨日,系统中【未开始】课程总数(乐团+VIP+网管)',
+  SURPLUS_MUSIC_COURSE_NUM:'截止到昨日,系统中【未开始】乐团课程总数',
+  SURPLUS_VIP_COURSE_NUM:'截止到昨日,系统中【未开始】VIP课程总数',
+  SURPLUS_PRACTICE_COURSE_NUM:'截止到昨日,系统中【未开始】网管课程总数',
+  OVER_COURSE_NUM:'已消耗课时总数:截止到昨日,系统中【已结束】&【已结算】课程总数(乐团+VIP+网管)',
+  OVER_MUSIC_COURSE_NUM:'已消耗乐团课时:截止到昨日,系统中【已结束】&【已结算】乐团课程总数',
+  OVER_VIP_COURSE_NUM:'已消耗VIP课时:截止到昨日,系统中【已结束】&【已结算】VIP课程总数',
+  OVER_PRACTICE_COURSE_NUM:'已消耗网管课时:截止到昨日,系统中【已结束】&【已结算】网管课程总数',
+  FINANCE_PAY:'筛选时间段内现金收入总和',
+  FINANCE_BALANCE_AMOUNT:'筛选时间段内余额消耗总和',
+  FINANCE_AMOUNT:'筛选时间段内支出金额总和',
+  HOMEWORK_CREATE_RATE:'筛选时间段内,服务指标作业总布置率',
+  HOMEWORK_SUBMIT_RATE:'筛选时间段内,已布置的作业学员总提交率(包括服务指标外的作业)',
+  HOMEWORK_COMMENT_RATE:'筛选时间段内,学员已提交的作业老师总点评率',
+  MUSIC_GROUP_COURSE:'筛选时间段内,乐团课程总数(未开始+已结束+已结算)',
+  VIP_GROUP_COURSE:'筛选时间段内,VIP课程总数(未开始+已结束+已结算)',
+  PRACTICE_GROUP_COURSE:'筛选时间段内,网管课程总数(未开始+已结束+已结算)',
+  ADD_STUDENT_REGISTRATION_NUM:'筛选时间段内,新注册学员总数',
+  MUSIC_GROUP_STUDENT:'筛选时间段中最后一日,【进行中】乐团【在读】学员总数,分部下去重',
+  NEWLY_STUDENT_NUM:'筛选时间段内,新增的【进行中】乐团【在读】学员总数(学员当前无在读乐团则记为新增)',
+  QUIT_MUSIC_GROUP_STUDENT_NUM:'筛选时间段内,乐团退团学员总数(学员无在读乐团,则记为退团)',
+  VIP_PRACTICE_STUDENT_NUM:'筛选时间段中最后一日,学员有剩余VIP或网管未上课时的总人数(分部下去重)',
+  VIP_PRACTICE_ADD_STUDENT_NUM:'筛选时间段内,新增的VIP/网管课付费学员总数'
 }
 
 const dates = {
@@ -176,3 +181,5 @@ export const matterTypes = {
   INSPECT: '下校巡查',
   VISIT: '学员回访',
 }
+
+export const chioseNum = 31

+ 2 - 2
src/views/teamDetail/teamDetailedList.vue

@@ -111,7 +111,7 @@ export default {
       })
     },
     onCancel () {
-       this.$store.dispatch('delVisitedViews', this.$route) 
+       this.$store.dispatch('delVisitedViews', this.$route)
       this.$router.push({ path: '/business/teamDetail'})
     },
     okDetailList () {
@@ -235,4 +235,4 @@ export default {
 </script>
 
 <style lang="scss">
-</style>
+</style>

+ 3 - 3
vue.config.js

@@ -20,9 +20,9 @@ const name = defaultSettings.title || '管乐迷后台管理系统' // page titl
 // let target = 'http://192.168.3.139:8000' // 箭河
 // let target = 'http://192.168.3.38:8000' //邹璇
 // let target = 'http://192.168.3.57:8000' //勇哥
-// let target = 'http://47.114.176.40:8000' // 开发环境
-// let target = 'http://dev.dayaedu.com/' // 测试环境
-let target = 'http://192.168.3.134:8000' //乔
+// let target = 'http://dev.dayaedu.com' // 测试服
+let target = 'http://47.114.176.40:8000'
+// let target = 'http://192.168.3.134' // 
 // All configuration item explanations can be find in https://cli.vuejs.org/config/
 module.exports = {
   /**