소스 검색

Merge branch 'iteration-school-info'

lex 1 년 전
부모
커밋
9e96749f66

+ 8 - 0
src/router/router-root.ts

@@ -192,6 +192,14 @@ export default [
     }
   },
   {
+    path: '/tenantDataShool',
+    name: 'tenantDataShool',
+    component: () => import('@/views/tenantAllData/tenantDataSchool'),
+    meta: {
+      title: '学练工具报名统计'
+    }
+  },
+  {
     path: '/tenantAllData',
     name: 'tenantAllData',
     component: () => import('@/views/tenantAllData/index'),

BIN
src/views/tenantAllData/images/icon-close.png


BIN
src/views/tenantAllData/images/icon-qrcode.png


BIN
src/views/tenantAllData/images/memberIcon.png


BIN
src/views/tenantAllData/images/qr-bg.png


BIN
src/views/tenantAllData/images/qrcode-bg.png


+ 182 - 11
src/views/tenantAllData/index.module.less

@@ -2,12 +2,14 @@
   padding: 0 12px;
   min-height: 100vh;
   box-sizing: border-box;
+
   .topWrap {
     padding-top: 16px;
     display: flex;
     flex-direction: row;
     align-items: center;
     justify-content: space-between;
+
     .topHead {
       display: flex;
       flex-direction: row;
@@ -16,15 +18,18 @@
       font-weight: 600;
       color: #333333;
       line-height: 24px;
+
       .topDot {
         width: 4px;
         height: 14px;
         margin-right: 6px;
       }
+
       .sanIcon {
         margin-left: 6px;
       }
     }
+
     .timerWrap {
       display: flex;
       flex-direction: row;
@@ -32,6 +37,7 @@
       font-size: 14px;
       font-weight: 400;
       color: #333333;
+
       .sanIcon {
         width: 12px;
         height: 12px;
@@ -39,20 +45,23 @@
       }
     }
   }
+
   .cardWrap {
     display: flex;
     flex-direction: row;
     align-items: center;
     justify-content: space-between;
     margin-top: 18px;
+
     .cardItem {
       padding: 8px 16px;
-      width: 170px;
+      width: 110px;
       height: 70px;
       background: #ffffff;
       border-radius: 10px;
       overflow: hidden;
       position: relative;
+
       .cardLine {
         width: 6px;
         height: 70px;
@@ -63,6 +72,7 @@
         top: 0;
       }
     }
+
     .cardNum {
       font-size: 24px;
       font-family: DINAlternate-Bold, DINAlternate;
@@ -70,15 +80,30 @@
       color: #fe6f25;
       line-height: 28px;
     }
+
     .studentCard {
       .cardLine {
         background: #259cfe;
         color: #fe6f25;
       }
+
       .cardNum {
         color: #259cfe;
       }
     }
+
+    .memberCard {
+      .cardLine {
+        background: rgba(254, 37, 37, 1);
+        color: rgba(254, 37, 37, 1);
+      }
+
+      .cardNum {
+        color: rgba(254, 37, 37, 1);
+      }
+
+    }
+
     .cardInfo {
       margin-top: 5px;
       display: flex;
@@ -88,41 +113,49 @@
       font-weight: 400;
       color: #777777;
       line-height: 21px;
+
       img {
         width: 16px;
         height: 16px;
       }
     }
   }
+
   .searchWrap {
     display: flex;
     flex-direction: row;
     align-items: center;
+
     .allDataWrap {
       padding-left: 0px !important;
     }
+
     .searechInfo {
       width: 273px;
     }
   }
+
   .sanIcon {
     width: 12px;
     height: 12px;
   }
+
   .routeSan {
     transform: rotate(180deg);
     transition: 0.2;
   }
+
   .schoolItem {
-    display: flex;
-    flex-direction: row;
-    align-items: center;
-    justify-content: space-between;
+    // display: flex;
+    // flex-direction: row;
+    // align-items: center;
+    // justify-content: space-between;
     background-color: #fff;
     margin-bottom: 12px;
     padding: 12px;
     border-radius: 10px;
     min-height: 73px;
+
     .title {
       font-weight: 400;
       color: #777777;
@@ -130,8 +163,9 @@
       font-size: 12px;
       margin-bottom: 6px;
     }
+
     .schoolName {
-      max-width: 235px;
+      max-width: 305px;
       white-space: nowrap;
       overflow: hidden;
       text-overflow: ellipsis;
@@ -140,6 +174,7 @@
       color: #333333;
       line-height: 20px;
     }
+
     .personNum {
       font-size: 20px;
       font-family: DINAlternate-Bold, DINAlternate;
@@ -148,15 +183,42 @@
       line-height: 24px;
       text-align: center;
     }
+
     .schoolCountWrap {
       display: flex;
       flex-direction: row;
       align-items: center;
-      .arrow {
-        width: 6px;
-        height: 12px;
-        margin-left: 17px;
+
+      &>div {
+        flex: 1;
+        padding-top: 14px;
       }
+
+      .title {
+        padding-top: 6px;
+        text-align: center;
+
+      }
+
+      .personNum {
+        font-weight: bold;
+        font-size: 24px;
+        color: #FF5A56;
+        line-height: 28px;
+        font-family: DINAlternate, DINAlternate;
+
+        img {
+          width: 30px;
+          height: 30px;
+          vertical-align: middle;
+        }
+      }
+
+      // .arrow {
+      //   width: 6px;
+      //   height: 12px;
+      //   margin-left: 17px;
+      // }
     }
   }
 }
@@ -166,6 +228,7 @@
   display: flex;
   flex-direction: row;
   align-items: center;
+
   .sanIcon {
     margin-left: 5px;
   }
@@ -184,6 +247,7 @@
   margin-bottom: 12px;
   padding: 12px;
   border-radius: 10px;
+
   .studentNameWrap {
     .title {
       font-size: 16px;
@@ -196,6 +260,7 @@
       text-overflow: ellipsis;
       overflow: hidden;
     }
+
     .studentPhone {
       font-size: 14px;
       font-weight: 400;
@@ -203,6 +268,7 @@
       line-height: 20px;
     }
   }
+
   .studentCountWrap {
     font-size: 14px;
     font-weight: 400;
@@ -210,28 +276,133 @@
     line-height: 20px;
   }
 }
+
 .emptyC {
   padding-bottom: 0;
   min-height: calc(100vh - 190px);
 }
+
 .refreshC {
   min-height: calc(100vh - 190px);
 }
+
 .refreshD {
   min-height: calc(100vh - 185px);
 }
+
 .emptyD {
   padding-bottom: 0;
   min-height: calc(100vh - 175px);
 }
+
 .top {
   background-color: #f6f8f9;
   padding: 0 12px;
 }
+
 .timerWrap {
   font-size: 14px;
-  width: 85px;
+  width: 120px;
 }
+
 .schoolList {
   display: block;
 }
+
+
+
+
+.popupQrcode {
+  background: transparent;
+  overflow: visible;
+  // position: relative;
+
+  .iconClose {
+    position: absolute;
+    display: inline-block;
+    width: 32px;
+    height: 32px;
+    background: url('./images/icon-close.png') no-repeat center;
+    background-size: contain;
+    top: -32px;
+    right: -9px;
+  }
+
+  .qrcodeBg {
+    // position: absolute;
+    // left: 0;
+    // right: 0;
+    // top: -40px;
+    width: 310px;
+    // margin-top: -40px;
+  }
+
+  .shareContaienr {
+    width: 310px;
+    position: relative;
+    text-align: center;
+    border-radius: 16px;
+    text-align: center;
+    line-height: 0;
+    font-size: 0;
+    // margin-top: 40px;
+    overflow: hidden;
+
+    .qrcodeSection {
+      width: 155px;
+      height: 155px;
+      margin: 0 auto;
+      position: relative;
+      overflow: hidden;
+
+      .qrbg {
+        position: absolute;
+        left: 0;
+        top: 0;
+        width: 100%;
+        height: 100%;
+      }
+
+      .mqrcode {
+        width: 136px !important;
+        height: 136px !important;
+        margin: 12px;
+      }
+    }
+
+    .sectionGroup {
+      padding: 0 28px 40px;
+      background: linear-gradient(90deg, #C5ECF8 0%, #D9F9DC 100%);
+      margin-top: -45px;
+      position: relative;
+      z-index: 9;
+    }
+
+    .section {
+      border-radius: 12px;
+      background-color: #fff;
+      padding-bottom: 30px;
+
+    }
+  }
+
+  .memo {
+    padding: 20px 15px;
+    font-size: 14px;
+    margin: 0 auto;
+    font-weight: 500;
+    font-size: 15px;
+    color: #000000;
+    line-height: 21px;
+    word-break: break-all;
+  }
+
+  .downloadBtn {
+    margin-top: 29px;
+    background: linear-gradient(90deg, #4CFFDD 0%, #2AA4FF 100%);
+    border-radius: 10px;
+    height: 47px;
+    max-width: 264px;
+    margin: 29px auto 0;
+  }
+}

+ 158 - 42
src/views/tenantAllData/index.tsx

@@ -10,33 +10,33 @@ import {
   Row,
   Tab,
   Tabs,
-  DatePicker
+  DatePicker,
+  Button
 } from 'vant';
 import MSticky from '@/components/m-sticky';
-// import icon1 from './images/icon1.png';
-// import icon2 from './images/icon2.png';
-// import icon3 from './images/icon3.png';
-// import icon4 from './images/icon4.png';
-// import iconTimer from './images/icon-timer.png';
 import personIcon from './images/personIcon.png';
 import homeIcon from './images/homeIcon.png';
+import memberIcon from './images/memberIcon.png';
 import sanIcon from './images/san.png';
+import iconQrcode from './images/icon-qrcode.png';
+import qrcodeBg from './images/qrcode-bg.png';
+import qrbg from './images/qr-bg.png';
 import request from '@/helpers/request';
 import topDot from './images/topDot.png';
 import { useRoute, useRouter } from 'vue-router';
-import { moneyFormat, numberFormat } from '@/helpers/utils';
+// import { moneyFormat, numberFormat } from '@/helpers/utils';
 import OFullRefresh from '@/components/m-full-refresh';
 import OEmpty from '@/components/m-empty';
-import arrowIcon from './images/arrowIcon.png';
-import OHeader from '@/components/m-header';
+// import arrowIcon from './images/arrowIcon.png';
+// import OHeader from '@/components/m-header';
 import OSearch from '@/components/m-search';
 import numeral from 'numeral';
+import MQrcode from '@/components/m-qrcode';
+import html2canvas from 'html2canvas';
 export default defineComponent({
   name: 'tenant-apply-data',
   setup() {
     const route = useRoute();
-    const router = useRouter();
-    const tabName = ref('all');
     const forms = reactive({
       keyword: '',
       id: route.query.id,
@@ -48,18 +48,25 @@ export default defineComponent({
       classList: [] as any,
       statObj: {
         registerNum: 0,
-        schoolNum: 0
+        schoolNum: 0,
+        registerMemberShipNum: 0
       } as any,
       perponStatus: false,
+      sortKey: 'CLASS' as 'CLASS' | 'MEMBER',
       sortId: 'desc',
-      sortName: '人数降序',
+      sortName: '班级人数降序',
       sortList: [
-        { value: 'desc', text: '人数降序' },
-        { value: 'asc', text: '人数升序' }
+        { value: 'desc', text: '班级人数降序' },
+        { value: 'asc', text: '班级人数升序' },
+        { value: 'asc', text: '会员人数升序' },
+        { value: 'asc', text: '会员人数升序' }
       ] as any,
       page: 1,
       rows: 20,
-      isClick: false
+      isClick: false,
+      qrcodeStatus: false,
+      url: '', // 二维码
+      urlItem: {} as any
     });
 
     const refreshing = ref(false);
@@ -145,22 +152,62 @@ export default defineComponent({
       getList();
     };
 
+    const imgs = reactive({
+      saveLoading: false,
+      image: null as any,
+      shareLoading: false
+    });
+    const downImg = () => {
+      if (imgs.saveLoading) {
+        return;
+      }
+      imgs.saveLoading = true;
+      // 判断是否已经生成图片
+      if (imgs.image) {
+        saveImg();
+      } else {
+        const container: any = document.getElementById(`preview-container`);
+
+        html2canvas(container, {
+          allowTaint: true,
+          useCORS: true,
+          backgroundColor: null
+        })
+          .then(async canvas => {
+            const url = canvas.toDataURL('image/png');
+            imgs.image = url;
+            saveImg();
+          })
+          .catch(() => {
+            imgs.saveLoading = false;
+          });
+      }
+    };
+
+    const saveImg = async () => {
+      // showLoadingToast({ message: '图片生成中...', forbidClick: true });
+      setTimeout(() => {
+        imgs.saveLoading = false;
+      }, 100);
+      const link = document.createElement('a');
+      link.setAttribute('download', forms.urlItem.schoolName + '统计' + '.png');
+      // 添加时间戳,防止浏览器缓存图
+
+      link.href = imgs.image;
+      link.click();
+    };
+
     onMounted(async () => {
-      document.title = '学生报名统计';
+      if (route.query.name) {
+        document.title = route.query.name + '报名统计';
+      } else {
+        document.title = '学生报名统计';
+      }
+
       // await getSchoolList();
       await getStat();
       await getList();
     });
-    const gotoDetail = (item: any) => {
-      router.push({
-        path: '/tenamtDataDetail',
-        query: {
-          id: route.query.id,
-          schoolId: item.schoolId,
-          schoolName: item.schoolName
-        }
-      });
-    };
     const getStat = async () => {
       try {
         const { data } = await request.post(
@@ -180,7 +227,7 @@ export default defineComponent({
     return () => (
       <div class={styles.tenantAllData}>
         {/* <OHeader isBack={false} /> */}
-        <MSticky position='top'>
+        <MSticky position="top">
           <div class={styles.top}>
             <div class={styles.topWrap}>
               <div class={styles.topHead}>
@@ -206,7 +253,6 @@ export default defineComponent({
             <div class={styles.cardWrap}>
               <div class={[styles.schoolCard, styles.cardItem]}>
                 <div class={styles.cardNum}>
-                  {' '}
                   {numeral(forms.statObj.schoolNum).format('0,0')}
                 </div>
                 <div class={styles.cardInfo}>
@@ -217,12 +263,21 @@ export default defineComponent({
               </div>
               <div class={[styles.studentCard, styles.cardItem]}>
                 <div class={styles.cardNum}>
-                  {' '}
                   {numeral(forms.statObj.registerNum).format('0,0')}
                 </div>
                 <div class={styles.cardInfo}>
                   <img src={personIcon} class={styles.cardInfoImg} alt="" />
-                  报名总人数
+                  报名人数
+                </div>
+                <div class={styles.cardLine}></div>
+              </div>
+              <div class={[styles.memberCard, styles.cardItem]}>
+                <div class={styles.cardNum}>
+                  {numeral(forms.statObj.registerMemberShipNum).format('0,0')}
+                </div>
+                <div class={styles.cardInfo}>
+                  <img src={memberIcon} class={styles.cardInfoImg} alt="" />
+                  会员人数
                 </div>
                 <div class={styles.cardLine}></div>
               </div>
@@ -234,7 +289,7 @@ export default defineComponent({
                   shape="round"
                   background="#F6F8F9"
                   inputBackground="white"
-                  placeholder='请输入学校名称'
+                  placeholder="请输入学校名称"
                   onSearch={val => {
                     forms.keyword = val;
                     forms.page = 1;
@@ -257,8 +312,8 @@ export default defineComponent({
                 />
               </div>
             </div>
-            </div>
-          </MSticky>
+          </div>
+        </MSticky>
 
         <div class={styles.schoolList}>
           {showContact.value ? (
@@ -272,19 +327,34 @@ export default defineComponent({
                 finished-text=" "
                 onLoad={getList}>
                 {list.value.map((item: any) => (
-                  <div
-                    class={styles.schoolItem}
-                    onClick={() => gotoDetail(item)}>
+                  <div class={styles.schoolItem}>
                     <div class={styles.schoolNameWrap}>
-                      <p class={styles.title}>学校名称</p>
+                      {/* <p class={styles.title}>学校名称</p> */}
                       <p class={styles.schoolName}>{item.schoolName}</p>
                     </div>
                     <div class={styles.schoolCountWrap}>
                       <div>
+                        <p class={styles.personNum}>{item.registerNum || 0}</p>
                         <p class={styles.title}>报名人数</p>
-                        <p class={styles.personNum}>{item.registerNum}</p>
                       </div>
-                      <img class={[styles.arrow]} src={arrowIcon} alt="" />
+                      <div>
+                        <p class={styles.personNum}>
+                          {item.registerMemberShipNum || 0}
+                        </p>
+                        <p class={styles.title}>会员人数</p>
+                      </div>
+                      <div
+                        onClick={() => {
+                          forms.qrcodeStatus = true;
+                          forms.urlItem = item;
+                          forms.url = `${location.origin}/classroom-app/#/tenantDataShool?id=${item.schoolId}&name=${item.schoolName}`;
+                        }}>
+                        <p class={styles.personNum}>
+                          <img src={iconQrcode} />
+                        </p>
+                        <p class={styles.title}>学校统计二维码</p>
+                      </div>
+                      {/* <img class={[styles.arrow]} src={arrowIcon} alt="" /> */}
                     </div>
                   </div>
                 ))}
@@ -333,9 +403,23 @@ export default defineComponent({
             columns={forms.sortList}
             onCancel={() => (forms.perponStatus = false)}
             onConfirm={(val: any) => {
-              console.log(val);
               const selectedOption = val.selectedOptions[0];
-              forms.sortId = selectedOption.value;
+              if (
+                selectedOption.value === 'desc' ||
+                selectedOption.value === 'asc'
+              ) {
+                forms.sortId = selectedOption.value;
+                forms.sortKey = 'CLASS';
+              }
+              if (selectedOption.value === 'mdesc') {
+                forms.sortId = 'desc';
+                forms.sortKey = 'MEMBER';
+              }
+              if (selectedOption.value === 'masc') {
+                forms.sortId = 'asc';
+                forms.sortKey = 'MEMBER';
+              }
+
               forms.sortName = selectedOption.text;
               refreshing.value = true;
               getList();
@@ -343,6 +427,38 @@ export default defineComponent({
             }}
           />
         </Popup>
+
+        <Popup v-model:show={forms.qrcodeStatus} class={styles.popupQrcode}>
+          <i
+            class={styles.iconClose}
+            onClick={() => (forms.qrcodeStatus = false)}></i>
+          <div class={[styles.shareContaienr]} id="preview-container">
+            <img src={qrcodeBg} class={styles.qrcodeBg} />
+            <div class={styles.sectionGroup}>
+              <div class={styles.section}>
+                <div class={styles.memo}>{forms.urlItem.schoolName}</div>
+                <div class={styles.qrcodeSection}>
+                  <img src={qrbg} class={styles.qrbg} />
+                  <MQrcode
+                    class={styles.mqrcode}
+                    text={forms.url}
+                    logoSize={'small'}
+                    size={'100%'}
+                  />
+                </div>
+              </div>
+            </div>
+          </div>
+
+          <Button
+            type="primary"
+            round
+            block
+            class={styles.downloadBtn}
+            onClick={downImg}>
+            下载二维码
+          </Button>
+        </Popup>
       </div>
     );
   }

+ 377 - 0
src/views/tenantAllData/tenantDataSchool.tsx

@@ -0,0 +1,377 @@
+import { defineComponent, onMounted, reactive, ref } from 'vue';
+import styles from './index.module.less';
+import {
+  Cell,
+  CellGroup,
+  Col,
+  List,
+  Picker,
+  Popup,
+  Row,
+  Tab,
+  Tabs,
+  DatePicker,
+  Button
+} from 'vant';
+import MSticky from '@/components/m-sticky';
+import personIcon from './images/personIcon.png';
+import homeIcon from './images/homeIcon.png';
+import sanIcon from './images/san.png';
+import request from '@/helpers/request';
+import topDot from './images/topDot.png';
+import { useRoute, useRouter } from 'vue-router';
+import { moneyFormat, numberFormat } from '@/helpers/utils';
+import OFullRefresh from '@/components/m-full-refresh';
+import OEmpty from '@/components/m-empty';
+import arrowIcon from './images/arrowIcon.png';
+import OHeader from '@/components/m-header';
+import OSearch from '@/components/m-search';
+import numeral from 'numeral';
+import MQrcode from '@/components/m-qrcode';
+import html2canvas from 'html2canvas';
+export default defineComponent({
+  name: 'tenant-apply-data',
+  setup() {
+    const route = useRoute();
+    const router = useRouter();
+    const tabName = ref('all');
+    const forms = reactive({
+      keyword: '',
+      id: route.query.id,
+      // id: '1687275949971763202',
+      yearStatus: false,
+      schoolId: null,
+      year: [new Date().getFullYear()] as any,
+      yearName: new Date().getFullYear(),
+      classList: [] as any,
+      statObj: {
+        registerNum: 0,
+        classNum: 0,
+        registerMemberShipNum: 0
+      } as any,
+      perponStatus: false,
+      sortKey: 'CLASS' as 'CLASS' | 'MEMBER',
+      sortId: 'desc',
+      sortName: '人数降序',
+      sortList: [
+        { value: 'desc', text: '班级人数降序' },
+        { value: 'asc', text: '班级人数升序' },
+        { value: 'mdesc', text: '会员人数升序' },
+        { value: 'masc', text: '会员人数升序' }
+      ] as any,
+      page: 1,
+      rows: 20,
+      isClick: false
+    });
+
+    const refreshing = ref(false);
+    const loading = ref(true);
+    const finished = ref(false);
+    const showContact = ref(false);
+    const list = ref([]);
+
+    // const getSchoolList = async () => {
+    //   try {
+    //     const { data } = await request.get('/edu-app/open/school/list', {
+    //       params: {
+    //         tenantId: forms.id
+    //       }
+    //     });
+    //     const temp = [
+    //       {
+    //         value: '',
+    //         text: '全部学校'
+    //       }
+    //     ];
+    //     if (Array.isArray(data)) {
+    //       data.forEach((item: any) => {
+    //         temp.push({
+    //           value: item.id,
+    //           text: item.name
+    //         });
+    //       });
+    //       forms.classList = temp;
+    //     }
+    //   } catch {
+    //     //
+    //   }
+    // };
+
+    const getList = async () => {
+      if (forms.isClick) {
+        return;
+      }
+      forms.isClick = true;
+      if (refreshing.value) {
+        list.value = [];
+        forms.page = 1;
+        refreshing.value = false;
+      }
+      try {
+        const res = await request.post(
+          '/edu-app/open/school/schoolRegisterClassPage',
+          {
+            data: {
+              schoolId: forms.id,
+              page: forms.page,
+              rows: forms.rows,
+              // year: forms.yearName,
+              keyword: forms.keyword,
+              sort: forms.sortId
+            }
+          }
+        );
+
+        if (list.value.length > 0 && res.data.current === 1) {
+          return;
+        }
+
+        list.value = list.value.concat(res.data.rows || []);
+        forms.page = res.data.current + 1;
+        showContact.value = list.value.length > 0;
+        loading.value = false;
+        finished.value = res.data.current >= res.data.pages;
+      } catch {
+        showContact.value = false;
+        finished.value = true;
+      } finally {
+        loading.value = false;
+      }
+      forms.isClick = false;
+    };
+    const onRefresh = () => {
+      finished.value = false;
+      // 重新加载数据
+      // 将 loading 设置为 true,表示处于加载状态
+      loading.value = true;
+      getList();
+    };
+
+    const imgs = reactive({
+      saveLoading: false,
+      image: null as any,
+      shareLoading: false
+    });
+
+    onMounted(async () => {
+      if (route.query.name) {
+        document.title = route.query.name + '报名统计';
+      } else {
+        document.title = '学生报名统计';
+      }
+      await getStat();
+      await getList();
+    });
+    const getStat = async () => {
+      try {
+        const { data } = await request.post(
+          '/edu-app/open/school/schoolRegisterStat',
+          {
+            data: {
+              schoolId: forms.id
+              // year: forms.yearName
+            }
+          }
+        );
+        forms.statObj = data;
+      } catch {
+        //
+      }
+    };
+    return () => (
+      <div class={styles.tenantAllData}>
+        {/* <OHeader isBack={false} /> */}
+        <MSticky position="top">
+          <div class={styles.top}>
+            <div class={styles.topWrap}>
+              <div class={styles.topHead}>
+                <img src={topDot} class={styles.topDot} alt="" />
+                汇总数据
+              </div>
+              {/* <div
+                class={styles.timerWrap}
+                onClick={() => {
+                  forms.yearStatus = true;
+                }}>
+                {forms.yearName}年{' '}
+                <img
+                  src={sanIcon}
+                  class={[
+                    styles.sanIcon,
+                    forms.yearStatus ? styles.routeSan : ''
+                  ]}
+                  alt=""
+                />
+              </div> */}
+            </div>
+            <div class={styles.cardWrap}>
+              <div class={[styles.studentCard, styles.cardItem]}>
+                <div class={styles.cardNum}>
+                  {numeral(forms.statObj.registerNum).format('0,0')}
+                </div>
+                <div class={styles.cardInfo}>
+                  <img src={personIcon} class={styles.cardInfoImg} alt="" />
+                  报名人数
+                </div>
+                <div class={styles.cardLine}></div>
+              </div>
+              <div class={[styles.memberCard, styles.cardItem]}>
+                <div class={styles.cardNum}>
+                  {numeral(forms.statObj.registerNum).format('0,0')}
+                </div>
+                <div class={styles.cardInfo}>
+                  <img src={personIcon} class={styles.cardInfoImg} alt="" />
+                  会员人数
+                </div>
+                <div class={styles.cardLine}></div>
+              </div>
+              <div class={[styles.schoolCard, styles.cardItem]}>
+                <div class={styles.cardNum}>
+                  {numeral(forms.statObj.classNum).format('0,0')}
+                </div>
+                <div class={styles.cardInfo}>
+                  <img src={homeIcon} class={styles.cardInfoImg} alt="" />
+                  班级数量
+                </div>
+                <div class={styles.cardLine}></div>
+              </div>
+            </div>
+            <div class={styles.searchWrap}>
+              <div class={styles.searechInfo}>
+                <OSearch
+                  class={styles.allDataWrap}
+                  shape="round"
+                  background="#F6F8F9"
+                  inputBackground="white"
+                  placeholder="请输入学校名称"
+                  onSearch={val => {
+                    forms.keyword = val;
+                    forms.page = 1;
+                    refreshing.value = true;
+                    getList();
+                  }}></OSearch>
+              </div>
+
+              <div
+                class={styles.timerWrap}
+                onClick={() => (forms.perponStatus = true)}>
+                {forms.sortName}{' '}
+                <img
+                  src={sanIcon}
+                  class={[
+                    styles.sanIcon,
+                    forms.perponStatus ? styles.routeSan : ''
+                  ]}
+                  alt=""
+                />
+              </div>
+            </div>
+          </div>
+        </MSticky>
+
+        <div class={styles.schoolList}>
+          {showContact.value ? (
+            <OFullRefresh
+              v-model:modelValue={refreshing.value}
+              onRefresh={onRefresh}
+              class={styles.refreshC}>
+              <List
+                loading-text=" "
+                finished={finished.value}
+                finished-text=" "
+                onLoad={getList}>
+                {list.value.map((item: any) => (
+                  <div class={styles.schoolItem}>
+                    <div class={styles.schoolNameWrap}>
+                      {/* <p class={styles.title}>学校名称</p> */}
+                      <p class={styles.schoolName}>{item.classGroupName}</p>
+                    </div>
+                    <div class={styles.schoolCountWrap}>
+                      <div>
+                        <p class={styles.personNum}>{item.registerNum || 0}</p>
+                        <p class={styles.title}>报名人数</p>
+                      </div>
+                      <div>
+                        <p class={styles.personNum}>
+                          {item.registerMemberShipNum || 0}
+                        </p>
+                        <p class={styles.title}>会员人数</p>
+                      </div>
+                      <div></div>
+                      {/* <img class={[styles.arrow]} src={arrowIcon} alt="" /> */}
+                    </div>
+                  </div>
+                ))}
+              </List>
+            </OFullRefresh>
+          ) : null}
+
+          {!showContact.value && !loading.value && (
+            <OEmpty description="暂无学校信息" class={styles.emptyC} />
+          )}
+        </div>
+        <Popup
+          v-model:show={forms.yearStatus}
+          position="bottom"
+          round
+          class={'popupBottomSearch'}>
+          <DatePicker
+            showToolbar
+            v-model={forms.year}
+            columns-type={['year']}
+            onCancel={() => (forms.yearStatus = false)}
+            onConfirm={(val: any) => {
+              console.log(val);
+              // const selectedOption = val.selectedOptions[0];
+              // console.log(selectedOption, 'selectedOption');
+              // forms.schoolId = selectedOption.value;
+              // // forms.schoolName = selectedOption.text;
+              forms.year = [val.selectedValues[0]];
+              forms.yearName = val.selectedValues[0];
+              forms.page = 1;
+              refreshing.value = true;
+              getStat();
+              getList();
+              forms.yearStatus = false;
+            }}
+          />
+        </Popup>
+
+        <Popup
+          v-model:show={forms.perponStatus}
+          position="bottom"
+          round
+          class={'popupBottomSearch'}>
+          <Picker
+            showToolbar
+            columns={forms.sortList}
+            onCancel={() => (forms.perponStatus = false)}
+            onConfirm={(val: any) => {
+              const selectedOption = val.selectedOptions[0];
+              if (
+                selectedOption.value === 'desc' ||
+                selectedOption.value === 'asc'
+              ) {
+                forms.sortId = selectedOption.value;
+                forms.sortKey = 'CLASS';
+              }
+              if (selectedOption.value === 'mdesc') {
+                forms.sortId = 'desc';
+                forms.sortKey = 'MEMBER';
+              }
+              if (selectedOption.value === 'masc') {
+                forms.sortId = 'asc';
+                forms.sortKey = 'MEMBER';
+              }
+
+              forms.sortName = selectedOption.text;
+              refreshing.value = true;
+              getList();
+              forms.perponStatus = false;
+            }}
+          />
+        </Popup>
+      </div>
+    );
+  }
+});