Pārlūkot izejas kodu

Merge branch 'dev'

liushengqiang 2 gadi atpakaļ
vecāks
revīzija
148bceab4e

BIN
src/components/m-empty/images/icon_empty.png


+ 4 - 3
src/components/m-empty/index.tsx

@@ -4,6 +4,7 @@ import { Button, Empty } from 'vant';
 import iconEmpty from './images/empty.png';
 import iconNetwork from './images/network.png';
 import icon404 from './images/404.png';
+import icon_empty from './images/icon_empty.png';
 
 export default defineComponent({
   name: 'm-empty',
@@ -13,8 +14,8 @@ export default defineComponent({
       default: ''
     },
     image: {
-      type: String as PropType<'empty' | 'network' | '404'>,
-      default: 'empty'
+      type: String as PropType<'empty' | 'network' | '404' | 'icon_empty'>,
+      default: 'icon_empty'
     },
     showButton: {
       type: Boolean,
@@ -28,7 +29,7 @@ export default defineComponent({
   emits: ['click'],
   setup(props, { emit }) {
     const forms = reactive({
-      image: iconEmpty
+      image: icon_empty
     });
 
     onMounted(() => {

+ 9 - 7
src/router/router-root.ts

@@ -37,13 +37,7 @@ export default [
       title: '课件播放'
     }
   },
-  {
-    path: '/co-ai',
-    component: () => import('@/views/co-ai/index'),
-    meta: {
-      title: '小酷AI'
-    }
-  },
+
   {
     path: '/payment-result',
     name: 'payment-result',
@@ -109,6 +103,14 @@ export default [
     }
   },
   {
+    path: '/school-register',
+    name: 'school-register',
+    component: () => import('@/views/school-register/index'),
+    meta: {
+      title: '学校登记'
+    }
+  },
+  {
     path: '/:pathMatch(.*)*',
     component: () => import('@/views/404'),
     meta: {

+ 8 - 1
src/router/routes-common.ts

@@ -98,7 +98,14 @@ export default [
         meta: {
           title: '领取详情'
         }
-      }
+      },
+      {
+        path: '/co-ai',
+        component: () => import('@/views/co-ai/index'),
+        meta: {
+          title: '小酷AI'
+        }
+      },
     ]
   },
   ...rootRouter

+ 17 - 0
src/views/co-ai/api.ts

@@ -0,0 +1,17 @@
+import request from '@/helpers/request';
+
+/** 获取教材列表 */
+export const api_musicSheetCategoriesPage = (params: any) => {
+  return request.post('/edu-app/musicSheetCategories/page', {
+    data: params
+  });
+};
+
+/**
+ * 曲谱列表分页
+ */
+export const api_musicSheetPage = (params: any) => {
+  return request.post('/edu-app/musicSheet/page', {
+    data: params
+  });
+};

+ 27 - 0
src/views/co-ai/index.module.less

@@ -87,6 +87,7 @@
 
         &.typeActive {
             .typeImg {
+                padding: 6px;
                 border-color: #99FFD0;
                 animation: scaleBtn 1s ease-in-out;
             }
@@ -109,6 +110,11 @@
         width: 100%;
         height: 100%;
         object-fit: cover;
+        opacity: 0;
+        transition: opacity .3s;
+    }
+    .typeIcon[loaded="true"] {
+        opacity: 1;
     }
 }
 
@@ -182,6 +188,11 @@
         object-fit: cover;
         flex-shrink: 0;
         margin-right: 1vw;
+        opacity: 0;
+        transition: opacity .3s;
+    }
+    .musicAvtor[loaded="true"] {
+        opacity: 1;
     }
 
     .musicInfo {
@@ -300,4 +311,20 @@
     to {
         opacity: 1;
     }
+}
+.loadingWrap {
+    display: flex;
+    justify-content: center;
+    min-height: 80Px;
+}
+.empty{
+    :global{
+        .van-empty__image{
+            width: 50%;
+            height: initial;
+        }
+        .van-empty__description{
+            color: #fff;
+        }
+    }
 }

+ 144 - 23
src/views/co-ai/index.tsx

@@ -1,8 +1,22 @@
-import { TransitionGroup, defineComponent, reactive, ref } from 'vue';
+import {
+  TransitionGroup,
+  defineComponent,
+  nextTick,
+  onMounted,
+  reactive,
+  ref
+} from 'vue';
 import styles from './index.module.less';
 import MSearch from '@/components/m-search';
 import icon_play from '@/common/images/icon_play.svg';
-import { NoticeBar, showLoadingToast, showToast } from 'vant';
+import {
+  Empty,
+  List,
+  Loading,
+  NoticeBar,
+  showLoadingToast,
+  showToast
+} from 'vant';
 import icon_back from './image/icon_back.svg';
 import icon_down from '@/common/images/icon_down.svg';
 import icon_jianpu from '@/common/images/icon_jianpu.svg';
@@ -11,16 +25,24 @@ import icons from '@/common/images/index.json';
 import { postMessage, promisefiyPostMessage } from '@/helpers/native-message';
 import { rows } from './data.json';
 import html2canvas from 'html2canvas';
+import { api_musicSheetCategoriesPage, api_musicSheetPage } from './api';
+import { state } from '@/state';
+import MEmpty from '@/components/m-empty';
 export default defineComponent({
   name: 'co-ai',
   setup() {
-    const types = [
-      { src: 'https://daya.ks3-cn-beijing.ksyuncs.com/16880147803671.png' },
-      { src: 'https://daya.ks3-cn-beijing.ksyuncs.com/16880147833062.png' },
-      { src: 'https://daya.ks3-cn-beijing.ksyuncs.com/16880147854153.png' },
-      { src: 'https://daya.ks3-cn-beijing.ksyuncs.com/16880147881254.png' },
-      { src: 'https://daya.ks3-cn-beijing.ksyuncs.com/16880147939485.png' }
-    ];
+    const categorForms = reactive({
+      page: 1,
+      rows: 999,
+      subjectId: state.user.data?.subjectId || ''
+    });
+    const musicForms = reactive({
+      page: 1,
+      rows: 20,
+      status: true,
+      keyword: '', // 关键词
+      musicSheetCategoriesId: ''
+    });
     const titles = rows;
     const data = reactive({
       /** 教材Index */
@@ -28,7 +50,13 @@ export default defineComponent({
       /** 音乐Index */
       musicIndex: 0,
       /** 显示简谱 */
-      isShowJianpu: false
+      isShowJianpu: false,
+      /** 教材列表 */
+      types: [] as any[],
+      /** 音乐列表 */
+      musics: [] as any[],
+      loading: true,
+      finshed: false
     });
     const downRef = ref();
     // 返回
@@ -38,8 +66,9 @@ export default defineComponent({
     /** 去云教练 */
     const handleGoto = () => {
       let src = `${location.origin}/instrument?id=${
-        titles[data.musicIndex]?.id
+        data.musics[data.musicIndex]?.id
       }`;
+      console.log(src)
       postMessage({
         api: 'openAccompanyWebView',
         content: {
@@ -83,6 +112,66 @@ export default defineComponent({
         }, 500);
       }
     };
+
+    /** 获取音乐教材列表 */
+    const getMusicSheetCategories = async () => {
+      try {
+        const res = await api_musicSheetCategoriesPage({
+          ...categorForms
+        });
+        if (res.code === 200 && Array.isArray(res?.data?.rows)) {
+          data.types = res.data.rows;
+          if (!musicForms.musicSheetCategoriesId && data.types.length > 0) {
+            musicForms.musicSheetCategoriesId = data.types[0].id;
+          }
+        }
+      } catch (error) {
+        console.log('🚀 ~ error:', error);
+      }
+    };
+
+    /** 获取曲谱列表 */
+    const getMusicList = async () => {
+      data.loading = true;
+      try {
+        const res = await api_musicSheetPage({
+          ...musicForms
+        });
+        if (res.code === 200 && Array.isArray(res?.data?.rows)) {
+          data.musics = [...data.musics, ...res.data.rows];
+          data.finshed = !res.data.next;
+        }
+      } catch (error) {
+        console.log('🚀 ~ error:', error);
+      }
+      data.loading = false;
+    };
+    const handleReset = () => {
+      musicForms.page = 1;
+      data.musics = [];
+      getMusicList();
+    };
+
+    const spinRef = ref();
+    const handleResh = () => {
+      if (data.loading || data.finshed) return;
+      musicForms.page = musicForms.page + 1;
+      getMusicList();
+    };
+
+    onMounted(async () => {
+      await getMusicSheetCategories();
+      getMusicList();
+
+      const obv = new IntersectionObserver(entries => {
+        if (entries[0].intersectionRatio > 0) {
+          handleResh();
+        }
+      });
+      nextTick(() => {
+        obv.observe(spinRef.value);
+      });
+    });
     return () => (
       <div class={styles.container}>
         <div class={styles.back} onClick={goback}>
@@ -93,16 +182,27 @@ export default defineComponent({
             <div class={styles.leftBg2}></div>
             <div class={styles.leftBg}></div>
             <div class={styles.types}>
-              {types.map((item, index) => {
+              {data.types.map((item, index) => {
                 return (
                   <div
                     class={[
                       styles.type,
-                      data.typeIndex === index && styles.typeActive
+                      musicForms.musicSheetCategoriesId === item.id &&
+                        styles.typeActive
                     ]}
-                    onClick={() => (data.typeIndex = index)}>
+                    onClick={() => {
+                      musicForms.musicSheetCategoriesId = item.id;
+                      handleReset();
+                    }}>
                     <div class={styles.typeImg}>
-                      <img class={styles.typeIcon} src={item.src} />
+                      <img
+                        class={styles.typeIcon}
+                        src={item.coverImg}
+                        onLoad={(e: Event) => {
+                          const el = e.target as HTMLImageElement;
+                          el.setAttribute('loaded', 'true');
+                        }}
+                      />
                     </div>
                   </div>
                 );
@@ -113,9 +213,13 @@ export default defineComponent({
                 shape="round"
                 background="transparent"
                 placeholder="请输入曲目名称"
+                onSearch={val => {
+                  musicForms.keyword = val;
+                  handleReset();
+                }}
               />
               <div class={styles.musicContent}>
-                {titles.map((item, index) => {
+                {data.musics.map((item: any, index: number) => {
                   return (
                     <div
                       class={[
@@ -125,7 +229,14 @@ export default defineComponent({
                           : styles.disableNotic
                       ]}
                       onClick={() => (data.musicIndex = index)}>
-                      <img class={styles.musicAvtor} src={item.titleImg} />
+                      <img
+                        class={styles.musicAvtor}
+                        src={item.titleImg}
+                        onLoad={(e: Event) => {
+                          const el = e.target as HTMLImageElement;
+                          el.setAttribute('loaded', 'true');
+                        }}
+                      />
                       <div class={styles.musicInfo}>
                         <div class={styles.musicName}>
                           <NoticeBar
@@ -136,7 +247,7 @@ export default defineComponent({
                           />
                         </div>
                         <div class={styles.musicDes}>
-                          <div class={styles.musicFavitor}>{item.updateBy}</div>
+                          <div class={styles.musicFavitor}>{item.usedNum}</div>
                           <div class={[styles.musicAuthor, 'van-ellipsis']}>
                             {item.composer}
                           </div>
@@ -146,20 +257,30 @@ export default defineComponent({
                     </div>
                   );
                 })}
+                {!data.finshed && (
+                  <div ref={spinRef} class={styles.loadingWrap}>
+                    <Loading color="#259CFE" />
+                  </div>
+                )}
+                {!data.loading && data.musics.length === 0 && (
+                  <div class={styles.empty}>
+                    <MEmpty description="暂无曲谱" />
+                  </div>
+                )}
               </div>
             </div>
           </div>
           <div class={[styles.opacityBg, styles.right]}>
             <div ref={downRef}>
               <div class={styles['right-musicName']}>
-                {titles[data.musicIndex].musicSheetName}
+                {data.musics[data.musicIndex]?.musicSheetName}
               </div>
               {data.isShowJianpu ? (
                 <>
                   <TransitionGroup name="van-fade">
-                    {titles[data.musicIndex]?.firstTone
+                    {data.musics[data.musicIndex]?.firstTone
                       ?.split(',')
-                      .map((item, index) => {
+                      .map((item: any, index: number) => {
                         return (
                           <img
                             class={styles.staff}
@@ -173,9 +294,9 @@ export default defineComponent({
               ) : (
                 <>
                   <TransitionGroup name="van-fade">
-                    {titles[data.musicIndex]?.musicImg
+                    {data.musics[data.musicIndex]?.musicImg
                       ?.split(',')
-                      .map((item, index) => {
+                      .map((item: any, index: number) => {
                         return (
                           <img
                             class={styles.staff}

+ 19 - 0
src/views/school-register/api.ts

@@ -0,0 +1,19 @@
+import request from '@/helpers/request';
+
+/** 获取省市区 */
+export const api_sysAreaQueryAllProvince = (): Promise<any> => {
+  return request.get('/edu-app/sysArea/queryAllProvince');
+};
+/** 新增学校 */
+export const api_schoolAdd = (params: any): Promise<any> => {
+  return request.post('/edu-app/school/add', {
+    data: params
+  });
+};
+/** 发送验证码 */
+export const api_openSendSms = (params: any): Promise<any> => {
+  return request.post('/edu-app/open/sendSms', {
+    data: params,
+    requestType: 'form',
+  });
+};

BIN
src/views/school-register/images/icon_bg.png


BIN
src/views/school-register/images/icon_close.png


BIN
src/views/school-register/images/icon_p1.png


BIN
src/views/school-register/images/icon_p2.png


BIN
src/views/school-register/images/icon_person.png


BIN
src/views/school-register/images/icon_school.png


BIN
src/views/school-register/images/icon_submit.png


BIN
src/views/school-register/images/logo.png


+ 193 - 0
src/views/school-register/index.module.less

@@ -0,0 +1,193 @@
+.container {
+    min-height: 100vh;
+    background-color: #005CBA;
+    background-image: url('./images/icon_bg.png');
+    background-repeat: no-repeat;
+    background-size: 100%;
+    padding-top: 50Px;
+    .titleIcon{
+        display: block;
+        max-width: 100%;
+        height: 26Px;
+        margin: 8px auto;
+    }
+}
+
+.title {
+    font-size: 30px;
+    font-family: AlimamaShuHeiTi-Bold, AlimamaShuHeiTi;
+    font-weight: bold;
+    color: #021F67;
+    line-height: 36px;
+    padding: 12px 16px;
+    text-align: center;
+}
+
+.tagWrap {
+    display: flex;
+    justify-content: center;
+
+    .tag {
+        font-size: 16px;
+        font-family: Alibaba-PuHuiTi-M, Alibaba-PuHuiTi;
+        font-weight: normal;
+        color: #FFFFFF;
+        line-height: 22px;
+        background: linear-gradient(90deg, #02BAFF 0%, #007AFE 100%);
+        border-radius: 8px;
+        margin: 0 auto;
+        display: flex;
+        align-items: center;
+        padding: 4px 6px;
+
+        span {
+            font-size: 28Px;
+            color: #C5EEFD;
+        }
+    }
+}
+
+.contentWrap {
+    padding-top: 208px;
+    .content {
+        background: rgba(255, 255, 255, 0.5);
+        border-radius: 20Px 20Px 0 0;
+        border: 2px solid #FFFFFF;
+        border-bottom: none;
+        padding: 12px;
+        padding-bottom: 50Px;
+    }
+
+    .icon {
+        display: block;
+        max-width: 100%;
+        height: 26Px;
+        margin: 8px auto;
+    }
+
+    .group {
+        border-radius: 18Px;
+        overflow: hidden;
+        margin-bottom: 12Px;
+
+        :global {
+            .van-field__control {
+                justify-content: flex-end;
+            }
+
+            .van-field__label {
+                font-size: 16Px;
+                color: #666666;
+            }
+
+            .van-field__error-message {
+                text-align: right;
+            }
+        }
+    }
+
+    .radio {
+        padding: 4px 10px;
+        background: #F5F6FA;
+        border: none;
+        font-size: 14Px;
+        line-height: 22px;
+        color: #626264;
+        font-weight: 400;
+        border-radius: 6px;
+        margin: 0 6px;
+    }
+}
+
+.tips {
+    font-size: 13px;
+    font-family: PingFangSC-Regular, PingFang SC;
+    font-weight: 400;
+    color: #F64650;
+    line-height: 18px;
+    background: #FFEBEB;
+    border-radius: 8Px;
+    padding: 8Px;
+}
+
+.submit {
+    margin-top: 18Px;
+    background-color: transparent;
+    height: 50Px;
+    padding: 0;
+    border: none;
+
+    &::before {
+        display: none;
+    }
+}
+
+.submitIcon {
+    display: block;
+    max-width: 100%;
+    max-height: 50Px;
+}
+
+.successWrap {
+    position: relative;
+    max-width: 76vw;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+
+    .p1 {
+        position: absolute;
+        max-width: 94vw;
+        transform: translate(12Px, -84Px);
+    }
+
+    .p2 {
+        max-width: 100%;
+        position: relative;
+        z-index: 1;
+    }
+
+    .btnWrap {
+        position: relative;
+        top: -2Px;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        background-color: #fff;
+        width: 100%;
+        border-radius: 0 0 16Px 16Px;
+        padding: 0 0 20Px 0;
+
+        .btnTitle {
+            font-size: 17Px;
+            font-family: PingFangSC-Semibold, PingFang SC;
+            font-weight: 600;
+            color: #021F67;
+            line-height: 24Px;
+            padding: 15Px 0;
+            text-align: center;
+        }
+
+        .btnDes {
+            font-size: 15Px;
+            font-family: PingFangSC-Regular, PingFang SC;
+            font-weight: 400;
+            color: #777777;
+            line-height: 21Px;
+            text-align: center;
+            padding-bottom: 20Px;
+        }
+
+        .btn {
+            width: 172Px;
+            height: 40Px;
+            font-size: 16Px;
+            font-family: PingFangSC-Semibold, PingFang SC;
+            font-weight: 600;
+            color: #EEF8FE;
+            line-height: 22Px;
+            background: linear-gradient(135deg, #00B9FF 0%, #007AFF 100%);
+            margin: 0 auto;
+        }
+    }
+}

+ 388 - 0
src/views/school-register/index.tsx

@@ -0,0 +1,388 @@
+import { defineComponent, onMounted, reactive } from 'vue';
+import styles from './index.module.less';
+import MHeader from '@/components/m-header';
+import { Area, Button, CellGroup, Field, Form, Popup, showToast } from 'vant';
+import icon_school from './images/icon_school.png';
+import icon_person from './images/icon_person.png';
+import icon_submit from './images/icon_submit.png';
+import icon_logo from './images/logo.png';
+import icon_p1 from './images/icon_p1.png';
+import icon_p2 from './images/icon_p2.png';
+import {
+  api_openSendSms,
+  api_schoolAdd,
+  api_sysAreaQueryAllProvince
+} from './api';
+import { useRoute } from 'vue-router';
+
+export default defineComponent({
+  name: 'SchoolRegister',
+  setup() {
+    const route = useRoute();
+    const formOptions = {
+      /** 性质 */
+      nature: [
+        { label: '公立', value: 'PUBLIC' },
+        { label: '私立', value: 'PRIVATE' }
+      ],
+      types: [
+        { label: '小学', value: 'PRIMARY' },
+        { label: '初中', value: 'JUNIOR' },
+        { label: '小初一体', value: 'PRIMARY_JUNIOR' }
+      ],
+      grades: [
+        { label: '六年制', value: 'SIX_YEAR_SYSTEM' },
+        { label: '五年制', value: 'FIVE_YEAR_SYSTEM' }
+      ],
+      genaral: [
+        { label: '男', value: '1' },
+        { label: '女', value: '0' }
+      ]
+    };
+    const forms = reactive({
+      name: '', // 学校名称
+      regionCode: '', // 所属区域
+      cityCode: '', // 所属城市
+      provinceCode: '', // 所属省份
+      schoolNature: 'PUBLIC' as 'PUBLIC' | 'PRIVATE' | string, // 学校性质
+      schoolType: 'PRIMARY' as 'PRIMARY' | 'JUNIOR' | 'PRIMARY_JUNIOR' | string, // 学校类型
+      gradeYear: 'SIX_YEAR_SYSTEM' as
+        | 'FIVE_YEAR_SYSTEM'
+        | 'SIX_YEAR_SYSTEM'
+        | string, // 学年制
+      emergencyContact: '', // 校长姓名
+      emergencyContactPhone: '', // 校长联系方式
+      educationalAdministrationUsername: '', // 负责人姓名
+      educationalAdministrationPhone: '', // 负责人联系方式
+      genaral: '1', // 性别
+      smsCode: '', // 验证码
+      buyGoods: true, // 是否购买商品
+      tenantId: route.query.id || '' // 机构
+    });
+    const data = reactive({
+      cityName: '', // 所属城市
+      showArea: false,
+      success: false,
+      areaList: {} as any,
+      sendMsg: '发送验证码'
+    });
+    const formateArea = (area: any[]) => {
+      const province_list: { [_: string]: string } = {};
+      const city_list: { [_: string]: string } = {};
+      const county_list: { [_: string]: string } = {};
+      area.forEach((item: any) => {
+        province_list[item.code] = item.name;
+      });
+      area.forEach((item: any) => {
+        item.areas?.forEach((city: any) => {
+          city_list[city.code] = city.name;
+        });
+      });
+      area.forEach((item: any) => {
+        item.areas?.forEach((city: any) => {
+          city.areas?.forEach((county: any) => {
+            county_list[county.code] = county.name;
+          });
+        });
+      });
+      return {
+        province_list,
+        city_list,
+        county_list
+      };
+    };
+    const getAreaList = () => {
+      api_sysAreaQueryAllProvince().then(res => {
+        if (res?.code === 200) {
+          data.areaList = formateArea(res.data);
+          console.log('🚀 ~ data.areaList:', data.areaList);
+        }
+      });
+    };
+    onMounted(() => {
+      getAreaList();
+    });
+    /** 发送验证码 */
+    const onSendSms = async () => {
+      try {
+        await api_openSendSms({
+          clientId: 'cooleshow-student',
+          type: 'REGISTER',
+          mobile: forms.educationalAdministrationPhone
+        });
+        onCountDown();
+        showToast('验证码已发送');
+      } catch {
+        data.sendMsg = '重新发送';
+      }
+    };
+    const onCountDown = () => {
+      data.sendMsg = '30s';
+      let count = 30;
+      setInterval(() => {
+        count--;
+        data.sendMsg = `${count}s后重新发送`;
+        if (count <= 0) {
+          data.sendMsg = '重新发送';
+        }
+      }, 1000);
+    };
+    const handleSubmit = async () => {
+      const res = await api_schoolAdd({ ...forms });
+      if (res?.code === 200) {
+        showToast('提交成功');
+        data.success = true;
+      }
+    };
+    return () => (
+      <div class={styles.container}>
+        <img class={styles.titleIcon} src={icon_logo} />
+        <div class={styles.title}>{route.query.name}</div>
+        <div class={styles.tagWrap}>
+          <div class={styles.tag}>
+            <span>·</span> 课堂乐器学校登记 <span>·</span>
+          </div>
+        </div>
+
+        <div class={styles.contentWrap}>
+          <div class={styles.content}>
+            <Form onSubmit={() => handleSubmit()}>
+              <CellGroup class={styles.group}>
+                <img src={icon_school} class={styles.icon} />
+                <Field
+                  border
+                  name="name"
+                  label="学校全称"
+                  rows="1"
+                  autosize
+                  type="textarea"
+                  placeholder="请输入学校全称"
+                  inputAlign="right"
+                  v-model={forms.name}
+                  rules={[{ required: true, message: '请输入学校全称' }]}
+                />
+                <Field
+                  isLink
+                  border
+                  label="所属城市"
+                  placeholder="请选择"
+                  readonly
+                  inputAlign="right"
+                  v-model={data.cityName}
+                  onClick={() => (data.showArea = true)}
+                  rules={[{ required: true, message: '请选择' }]}></Field>
+                <Field center border name="schoolNature" label="办学性质">
+                  {{
+                    input: () => (
+                      <>
+                        {formOptions.nature.map(item => {
+                          return (
+                            <Button
+                              class={styles.radio}
+                              size="small"
+                              color={
+                                item.value === forms.schoolNature
+                                  ? '#198CFE'
+                                  : ''
+                              }
+                              onClick={() => (forms.schoolNature = item.value)}>
+                              {item.label}
+                            </Button>
+                          );
+                        })}
+                      </>
+                    )
+                  }}
+                </Field>
+
+                <Field center border label="学校类型" labelWidth="70px">
+                  {{
+                    input: () => (
+                      <>
+                        {formOptions.types.map(item => {
+                          return (
+                            <Button
+                              class={styles.radio}
+                              size="small"
+                              color={
+                                item.value === forms.schoolType ? '#198CFE' : ''
+                              }
+                              onClick={() => (forms.schoolType = item.value)}>
+                              {item.label}
+                            </Button>
+                          );
+                        })}
+                      </>
+                    )
+                  }}
+                </Field>
+                <Field center border label="学年制">
+                  {{
+                    input: () => (
+                      <>
+                        {formOptions.grades.map(item => {
+                          return (
+                            <Button
+                              class={styles.radio}
+                              size="small"
+                              color={
+                                item.value === forms.gradeYear ? '#198CFE' : ''
+                              }
+                              onClick={() => (forms.gradeYear = item.value)}>
+                              {item.label}
+                            </Button>
+                          );
+                        })}
+                      </>
+                    )
+                  }}
+                </Field>
+              </CellGroup>
+
+              <CellGroup class={styles.group}>
+                <img src={icon_person} class={styles.icon} />
+                <Field
+                  border
+                  name="emergencyContact"
+                  label="校长姓名"
+                  placeholder="请输入校长姓名"
+                  inputAlign="right"
+                  maxlength={6}
+                  v-model={forms.emergencyContact}
+                  rules={[{ required: true, message: '请输入校长姓名' }]}
+                />
+                <Field
+                  border
+                  name="emergencyContactPhone"
+                  label="校长联系方式"
+                  maxlength={11}
+                  placeholder="请输入校长手机号码"
+                  inputAlign="right"
+                  v-model={forms.emergencyContactPhone}
+                  rules={[
+                    { required: true, message: '请输入校长手机号码' },
+                    {
+                      pattern: /^1[3456789]\d{9}$/,
+                      message: '请输入正确的手机号码'
+                    }
+                  ]}
+                />
+                <Field
+                  border
+                  name="educationalAdministrationUsername"
+                  label="负责人姓名"
+                  placeholder="请输入负责人姓名"
+                  inputAlign="right"
+                  maxlength={6}
+                  v-model={forms.educationalAdministrationUsername}
+                  rules={[{ required: true, message: '请输入负责人姓名' }]}
+                />
+                <Field
+                  border
+                  name="educationalAdministrationPhone"
+                  label="负责人联系方式"
+                  labelWidth="40%"
+                  inputAlign="right"
+                  placeholder="请输入负责人手机号码"
+                  maxlength={11}
+                  v-model={forms.educationalAdministrationPhone}
+                  rules={[
+                    { required: true, message: '请输入负责人手机号码' },
+                    {
+                      pattern: /^1[3456789]\d{9}$/,
+                      message: '请输入正确的手机号码'
+                    }
+                  ]}
+                />
+                <Field center border label="性别">
+                  {{
+                    input: () => (
+                      <>
+                        {formOptions.genaral.map(item => {
+                          return (
+                            <Button
+                              class={styles.radio}
+                              size="small"
+                              color={
+                                item.value === forms.genaral ? '#198CFE' : ''
+                              }
+                              onClick={() => (forms.genaral = item.value)}>
+                              {item.label}
+                            </Button>
+                          );
+                        })}
+                      </>
+                    )
+                  }}
+                </Field>
+                <Field
+                  border
+                  center
+                  name="smsCode"
+                  label="验证码"
+                  placeholder="请输入验证码"
+                  v-model={forms.smsCode}
+                  maxlength={6}
+                  rules={[{ required: true, message: '请输入验证码' }]}>
+                  {{
+                    button: () => (
+                      <Button
+                        size="small"
+                        type="primary"
+                        color="#198CFE"
+                        onClick={() => onSendSms()}>
+                        {data.sendMsg}
+                      </Button>
+                    )
+                  }}
+                </Field>
+                <div style={{ padding: '10px 16px' }}>
+                  <div class={styles.tips}>
+                    负责人即为该学校酷乐秀课堂乐器老师端管理员,手机号即为酷乐秀课堂乐器老师端账号,默认密码为:ktyq+手机号后四位
+                  </div>
+                </div>
+              </CellGroup>
+
+              <Button class={styles.submit} round block native-type="submit">
+                <img class={styles.submitIcon} src={icon_submit} />
+              </Button>
+            </Form>
+            <Popup v-model:show={data.showArea} position="bottom">
+              <Area
+                areaList={data.areaList}
+                onCancel={() => (data.showArea = false)}
+                onConfirm={({ selectedOptions }) => {
+                  forms.provinceCode = selectedOptions[0].code;
+                  forms.cityCode = selectedOptions[1].code;
+                  forms.regionCode = selectedOptions[2].code;
+                  data.cityName = selectedOptions
+                    .map((item: any) => item.text)
+                    .join('-');
+                  data.showArea = false;
+                }}
+              />
+            </Popup>
+
+            <Popup
+              class="popup-custom van-scale"
+              transition="van-scale"
+              closeOnClickOverlay={false}
+              v-model:show={data.success}>
+              <div class={styles.successWrap}>
+                <img class={styles.p1} src={icon_p1} />
+                <img class={styles.p2} src={icon_p2} />
+                <div class={styles.btnWrap}>
+                  <div class={styles.btnTitle}>您已成功登记</div>
+                  <div class={styles.btnDes}>欢迎您使用酷乐秀课堂乐器~</div>
+                  <Button class={styles.btn} type="primary" round>
+                    我知道了
+                  </Button>
+                </div>
+              </div>
+            </Popup>
+          </div>
+        </div>
+      </div>
+    );
+  }
+});