mo 2 år sedan
förälder
incheckning
15a9ef7a9b

+ 2 - 2
src/router/index.ts

@@ -5,7 +5,7 @@ import { postMessage } from '@/helpers/native-message'
 import routesTeacher from './routes-teacher'
 import routesStudent from './routes-student'
 import routesSchool from './routes-school'
-
+;(window as any).paymentType = 'SCHOOL'
 const paymentType = (window as any).paymentType
 let routes: any = []
 let baseUrl = null as any
@@ -45,7 +45,7 @@ router.beforeEach((to, from, next) => {
 })
 
 let isOpen = false
-router.onError(error => {
+router.onError((error) => {
   if (error instanceof Error) {
     const isChunkLoadFailed = error.name.indexOf('chunk')
     const targetPath = router.currentRoute.value.fullPath

+ 11 - 4
src/router/routes-school.ts

@@ -6,9 +6,7 @@ type metaType = {
 }
 
 // 不需要登录的路由
-const noLoginRouter = [
-
-]
+const noLoginRouter = []
 
 export default [
   {
@@ -60,13 +58,22 @@ export default [
         meta: {
           title: '群发记录'
         }
-      }, {
+      },
+      {
         path: '/create-message',
         name: 'create-message',
         component: () => import('@/school/mass-message/create-message'),
         meta: {
           title: '群发消息'
         }
+      },
+      {
+        path: '/exercise-record',
+        name: 'exercise-record',
+        component: () => import('@/school/exercise-record'),
+        meta: {
+          title: '练习记录'
+        }
       }
     ]
   },

+ 7 - 0
src/school/exercise-record/index.module.less

@@ -0,0 +1,7 @@
+.chioseWrap {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: space-around;
+  background-color: #f8f8f8;
+}

+ 213 - 0
src/school/exercise-record/index.tsx

@@ -0,0 +1,213 @@
+import OHeader from '@/components/o-header'
+import OSearch from '@/components/o-search'
+import OSticky from '@/components/o-sticky'
+import dayjs from 'dayjs'
+import {
+  Cell,
+  Icon,
+  Popover,
+  Tag,
+  DatePicker,
+  DatePickerColumnType,
+  Popup,
+  List,
+  PullRefresh,
+  ActionSheet
+} from 'vant'
+import StudentItem from './modals/student-item'
+import { defineComponent, reactive, ref } from 'vue'
+import { useRouter } from 'vue-router'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'exercise-record',
+  setup() {
+    const router = useRouter()
+    const state = reactive({
+      showPopoverTime: false,
+      showPopoverOrchestra: false,
+      showPopoverSubject: false,
+      showPopoverSort: false,
+      actions: [
+        { text: '全部乐团', color: 'var(--van-primary-color)' },
+        { text: '交付团' },
+        { text: '晋升团' }
+      ],
+      actionSorts: [
+        { text: '按天数', value: 'PRACTICE_DAY' },
+        { text: '按时长', value: 'PRACTICE_TIMES' }
+      ],
+      currentDate: [dayjs().format('YYYY'), dayjs().format('MM')]
+    })
+    const forms = reactive({
+      practiceMonth: state.currentDate[0] + '' + state.currentDate[1],
+      practiceMonthName: state.currentDate[0] + '年' + state.currentDate[1] + '月',
+      orchestraId: '',
+      orchestraName: '',
+      subjectId: '',
+      subjectName: '',
+      sortType: '',
+      sortTypeName: ''
+    })
+    const minDate = ref(new Date(dayjs().subtract(5, 'year').format('YYYY-MM-DD')))
+    const maxDate = ref(new Date(dayjs().add(5, 'year').format('YYYY-MM-DD')))
+    const columnsType = ref<DatePickerColumnType[]>(['year', 'month'])
+    const refreshing = ref(false)
+    const loading = ref(false)
+    const finished = ref(false)
+    const showContact = ref(false)
+    const list = ref([])
+    const onDetail = (item: any) => {
+      console.log(item)
+      router.push({
+        path: '/orchestra-detail',
+        query: {
+          id: item
+        }
+      })
+    }
+    const getList = () => {
+      console.log('getList')
+      if (refreshing.value) {
+        list.value = []
+        refreshing.value = false
+      }
+
+      for (let i = 0; i < 10; i++) {
+        // list.value.push(list.value.length + 1)
+      }
+      loading.value = false
+
+      if (list.value.length >= 40) {
+        finished.value = true
+      }
+    }
+    const onBack = () => {
+      console.log('返回')
+    }
+
+    const checkTimer = (val: any) => {
+      forms.practiceMonth = val.selectedValues[0] + val.selectedValues[1]
+      forms.practiceMonthName = val.selectedValues[0] + '年' + val.selectedValues[1] + '月'
+      state.showPopoverTime = false
+      getList()
+    }
+    const checkSort = (val: any) => {
+      forms.sortType = val.value
+      forms.sortTypeName = val.text
+      getList()
+    }
+
+    const onRefresh = () => {
+      finished.value = false
+      // 重新加载数据
+      // 将 loading 设置为 true,表示处于加载状态
+      loading.value = true
+      getList()
+    }
+    return () => (
+      <>
+        <OSticky position="top" background="#F8F8F8">
+          <OHeader isBack={true} onHeaderBack={onBack}></OHeader>
+          <OSearch placeholder="学生编号" onSearch={getList}></OSearch>
+          <div class={styles.chioseWrap}>
+            <div style={{ padding: '12px 13px', background: '#F8F8F8' }}>
+              <div
+                class={styles.searchBand}
+                onClick={() => {
+                  state.showPopoverTime = true
+                }}
+              >
+                {forms.practiceMonthName}
+                <Icon name={state.showPopoverTime ? 'arrow-up' : 'arrow-down'} />
+              </div>
+            </div>
+
+            <div style={{ padding: '12px 13px', background: '#F8F8F8' }}>
+              <Popover
+                v-model:show={state.showPopoverSubject}
+                actions={state.actions}
+                showArrow={false}
+                placement="bottom-start"
+                offset={[0, 12]}
+              >
+                {{
+                  reference: () => (
+                    <div class={styles.searchBand}>
+                      全部乐团
+                      <Icon name={state.showPopoverSubject ? 'arrow-up' : 'arrow-down'} />
+                    </div>
+                  )
+                }}
+              </Popover>
+            </div>
+            <div style={{ padding: '12px 13px', background: '#F8F8F8' }}>
+              <Popover
+                v-model:show={state.showPopoverSubject}
+                actions={state.actions}
+                showArrow={false}
+                placement="bottom-start"
+                offset={[0, 12]}
+              >
+                {{
+                  reference: () => (
+                    <div class={styles.searchBand}>
+                      全部声部
+                      <Icon name={state.showPopoverSubject ? 'arrow-up' : 'arrow-down'} />
+                    </div>
+                  )
+                }}
+              </Popover>
+            </div>
+
+            <div style={{ padding: '12px 13px', background: '#F8F8F8' }}>
+              <Popover
+                v-model:show={state.showPopoverSort}
+                actions={state.actionSorts}
+                showArrow={false}
+                placement="bottom-end"
+                offset={[0, 12]}
+                onSelect={checkSort}
+              >
+                {{
+                  reference: () => (
+                    <div class={styles.searchBand}>
+                      按天数
+                      <Icon name={state.showPopoverSort ? 'arrow-up' : 'arrow-down'} />
+                    </div>
+                  )
+                }}
+              </Popover>
+            </div>
+          </div>
+        </OSticky>
+        <PullRefresh v-model={refreshing.value} onRefresh={onRefresh}>
+          <List
+            v-model:loading={loading.value}
+            finished={finished.value}
+            finished-text="没有更多了"
+            onLoad={getList}
+          >
+            {[1, 2, 3, 4, 5, 6].map((item: any) => (
+              <StudentItem item={item} />
+            ))}
+          </List>
+        </PullRefresh>
+
+        <Popup v-model:show={state.showPopoverTime} position="bottom" style="{ height: '30%' }">
+          <DatePicker
+            onCancel={() => {
+              state.showPopoverTime = false
+            }}
+            onConfirm={checkTimer}
+            v-model={state.currentDate}
+            title="选择年月"
+            minDate={minDate.value}
+            maxDate={maxDate.value}
+            columnsType={columnsType.value}
+          />
+        </Popup>
+      </>
+    )
+  }
+})

+ 176 - 0
src/school/exercise-record/modals/student-item.module.less

@@ -0,0 +1,176 @@
+.itemWrap {
+  width: calc(100% -30px);
+  height: 121px;
+  background: #ffffff;
+  border-radius: 10px;
+  margin: 0 15px 12px;
+  .itemTop {
+    padding: 8px 15px 8px;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: space-between;
+    border-bottom: 1px solid #f2f2f2;
+    .itemTopLeft {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      .headIcon {
+        width: 30px;
+        height: 30px;
+        border-radius: 50%;
+        overflow: hidden;
+        margin-right: 12px;
+        img {
+          width: 100%;
+          height: 100%;
+        }
+      }
+      .name {
+        font-size: 16px;
+        font-family: PingFangSC-Medium, PingFang SC;
+        font-weight: 500;
+        color: #333333;
+        line-height: 30px;
+        margin-right: 10px;
+      }
+      .tag {
+        padding: 1px 8px;
+        min-width: 40px;
+        height: 19px;
+        background: #ffe7da;
+        border-radius: 4px;
+        font-size: 12px;
+        font-family: PingFangSC-Medium, PingFang SC;
+        font-weight: 500;
+        color: #f67146;
+        text-align: center;
+        line-height: 17px;
+      }
+    }
+    .itemTopRight {
+      width: 24px;
+      height: 24px;
+      padding: 2px;
+      img {
+        width: 100%;
+        height: 100%;
+      }
+    }
+  }
+  .itemBottom {
+    padding: 0 10px 10px;
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    text-align: center;
+    .msgMain {
+      font-size: 26px;
+      font-family: DINAlternate-Bold, DINAlternate;
+      font-weight: bold;
+      color: #f67146;
+      line-height: 30px;
+      span {
+        height: 17px;
+        font-size: 12px;
+        font-family: PingFangSC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #777777;
+        line-height: 17px;
+      }
+    }
+    .msgsub {
+      margin-top: 4px;
+      height: 20px;
+      font-size: 14px;
+      font-family: PingFangSC-Regular, PingFang SC;
+      font-weight: 400;
+      color: #333333;
+      line-height: 20px;
+    }
+    .itemBottomLeft {
+      width: 50%;
+      position: relative;
+      &::after {
+        content: '';
+        width: 1px;
+        height: 20px;
+        background: #f2f2f2;
+        border-radius: 1px;
+        right: 0;
+        top: 50%;
+        margin-top: -10px;
+        position: absolute;
+      }
+    }
+    .itemBottomRight {
+      width: 50%;
+      position: relative;
+      .arrow {
+        position: absolute;
+        bottom: 14px;
+        right: 15px;
+        color: #f2f2f2;
+      }
+    }
+  }
+}
+:global {
+  .bottomSheet {
+    .van-action-sheet__description {
+      padding: 0 !important;
+      &::after {
+        border: none !important;
+      }
+    }
+  }
+}
+.bottomTitle {
+  padding: 15px 15px 20px;
+  text-align: left;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: space-between;
+  height: 22px;
+  font-size: 16px;
+  font-family: PingFangSC-Medium, PingFang SC;
+  font-weight: 500;
+  color: #333333;
+  line-height: 22px;
+  .bottomTitleLeft {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    span {
+      width: 4px;
+      height: 12px;
+      background: #ff8057;
+      border-radius: 2px;
+      display: inline-block;
+      margin-right: 6px;
+    }
+  }
+}
+.bottomConent {
+  padding: 20px 15px 57px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  .bottomImgWrap {
+    width: 47px;
+    height: 47px;
+    margin-bottom: 6px;
+    img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+  .bottomConentLeft,
+  .bottomConentRight {
+    width: 50%;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+  }
+}

+ 89 - 0
src/school/exercise-record/modals/student-item.tsx

@@ -0,0 +1,89 @@
+import { defineComponent, reactive, ref } from 'vue'
+import styles from './student-item.module.less'
+import defaultIcon from '@/school/images/default-icon.jpg'
+import msgIcon from '@/school/images/msg-icon.png'
+import sendmsgIcon from '@/school/images/sendmsg-icon.png'
+import phoneIcon from '@/school/images/phone-icon.png'
+import { Icon, ActionSheet } from 'vant'
+export default defineComponent({
+  props: ['item'],
+  name: 'student-item',
+  setup(props) {
+    const showContact = ref(false)
+    const startContact = () => {
+      showContact.value = true
+    }
+    const closeSheet = () => {
+      showContact.value = false
+    }
+    return () => (
+      <>
+        <div>
+          <div class={styles.itemWrap}>
+            <div class={styles.itemTop}>
+              <div class={styles.itemTopLeft}>
+                <div class={styles.headIcon}>
+                  <img src={defaultIcon} alt="" />
+                </div>
+                <p class={styles.name}>xxx</p>
+                <div class={styles.tag}>长笛</div>
+              </div>
+              <div class={styles.itemTopRight}>
+                <div class={styles.msgIcon} onClick={startContact}>
+                  <img src={msgIcon} alt="" />
+                </div>
+              </div>
+            </div>
+            <div class={styles.itemBottom}>
+              <div class={styles.itemBottomLeft}>
+                <p class={styles.msgMain}>
+                  10 <span>天</span>
+                </p>
+                <p class={styles.msgsub}>练习天数</p>
+              </div>
+              <div class={styles.itemBottomRight}>
+                <p class={styles.msgMain}>
+                  10 <span>分钟</span>
+                </p>
+                <p class={styles.msgsub}>练习时长</p>
+                <Icon class={styles.arrow} name="arrow"></Icon>
+              </div>
+            </div>
+          </div>
+        </div>
+        <ActionSheet
+          class="bottomSheet"
+          v-model:show={showContact.value}
+          vSlots={{
+            description: () => (
+              <div class={styles.bottomTitle}>
+                <div class={styles.bottomTitleLeft}>
+                  <span></span>
+                  <p>联系方式</p>
+                </div>
+                <div class={styles.bottomTitleRight} onClick={closeSheet}>
+                  <Icon class={styles.cross} name="cross"></Icon>
+                </div>
+              </div>
+            )
+          }}
+        >
+          <div class={styles.bottomConent}>
+            <div class={styles.bottomConentLeft}>
+              <div class={styles.bottomImgWrap}>
+                <img src={sendmsgIcon} alt="" />
+              </div>
+              <p>发送消息</p>
+            </div>
+            <div class={styles.bottomConentRight}>
+              <div class={styles.bottomImgWrap}>
+                <img src={phoneIcon} alt="" />
+              </div>
+              <p>拨打电话</p>
+            </div>
+          </div>
+        </ActionSheet>
+      </>
+    )
+  }
+})

BIN
src/school/images/default-icon.jpg


BIN
src/school/images/msg-icon.png


BIN
src/school/images/phone-icon.png


BIN
src/school/images/sendmsg-icon.png


+ 4 - 2
src/school/main.ts

@@ -4,7 +4,7 @@ import router from '../router/index'
 import { postMessage } from '@/helpers/native-message'
 
 import 'normalize.css'
-import 'vant/lib/index.css';
+import 'vant/lib/index.css'
 
 import '../styles/index.less'
 import { state } from '@/state'
@@ -25,6 +25,7 @@ postMessage(
 // import Vconsole from 'vconsole'
 // const vconsole = new Vconsole()
 const paymentType = (window as any).paymentType // 浏览器设置
+
 if (browser().isTeacher || paymentType === 'TEACHER') {
   state.platformType = 'TEACHER'
 } else if (browser().isStudent || paymentType === 'STUDENT') {
@@ -37,7 +38,8 @@ if (browser().isTeacher || paymentType === 'TEACHER') {
 
 if (state.platformType === 'TEACHER') {
   state.platformApi = '/api-teacher'
-} if (state.platformType === 'SCHOOL') {
+}
+if (state.platformType === 'SCHOOL') {
   state.platformApi = '/api-school'
 } else {
   state.platformApi = '/api-student'

+ 1 - 0
src/styles/index.less

@@ -17,6 +17,7 @@
   --van-primary: #ff8057 !important;
   --van-picker-confirm-action-color: #ff8057 !important;
   --van-primary-text: #f67146 !important;
+  // --van-popover-light-text-color: var(--van-primary) !important;
   // --van-orange: #ff976a;
   // --van-orange-dark: #ed6a0c;
   // --van-orange-light: #fffbe8;