lex 2 роки тому
батько
коміт
500c14b9c7
41 змінених файлів з 1161 додано та 24 видалено
  1. 0 0
      dist/assets/exercis-detail-legacy.8128183b.js
  2. 0 0
      dist/assets/exercis-detail.f1751904.js
  3. 0 0
      dist/assets/index-legacy.bd959491.js
  4. 0 0
      dist/assets/index.d69d5aad.js
  5. 0 0
      dist/assets/unbind-legacy.ff30fb4d.js
  6. 0 0
      dist/assets/unbind.3c0101ad.js
  7. 1 1
      src/constant/index.ts
  8. 24 0
      src/router/routes-school.ts
  9. 1 1
      src/school/companion-teacher/companion-teacher-register.tsx
  10. 1 1
      src/school/companion-teacher/compontent/teacher.tsx
  11. 5 4
      src/school/companion-teacher/index.tsx
  12. 1 1
      src/school/exercise-record/exercis-detail.tsx
  13. 3 3
      src/school/mass-message/index.tsx
  14. 1 1
      src/school/orchestra/compontent/information.tsx
  15. 1 1
      src/school/orchestra/compontent/photo-detail.tsx
  16. 1 1
      src/school/orchestra/compontent/photo.tsx
  17. 1 1
      src/school/orchestra/compontent/plan.tsx
  18. 26 3
      src/school/orchestra/create-orchestra/index.tsx
  19. 1 1
      src/school/orchestra/create-orchestra/select-teacher.tsx
  20. 13 2
      src/school/orchestra/modal/subject-list.tsx
  21. 1 1
      src/school/orchestra/orchestra-information.tsx
  22. 114 0
      src/school/train-planning/component/course-preview/index.module.less
  23. 104 0
      src/school/train-planning/component/course-preview/index.tsx
  24. 0 0
      src/school/train-planning/component/practice/index.module.less
  25. 8 0
      src/school/train-planning/component/practice/index.tsx
  26. 74 0
      src/school/train-planning/component/standard/index.module.less
  27. 210 0
      src/school/train-planning/component/standard/index.tsx
  28. 43 0
      src/school/train-planning/component/train-content/index.module.less
  29. 53 0
      src/school/train-planning/component/train-content/index.tsx
  30. 39 0
      src/school/train-planning/create.ts
  31. BIN
      src/school/train-planning/images/calendar_bg.png
  32. BIN
      src/school/train-planning/images/icon-timer.png
  33. BIN
      src/school/train-planning/images/icon_arrow.png
  34. BIN
      src/school/train-planning/images/icon_arrow_default.png
  35. 13 0
      src/school/train-planning/index.module.less
  36. 29 0
      src/school/train-planning/index.tsx
  37. 100 0
      src/school/train-planning/modal/calendar/index.module.less
  38. 192 0
      src/school/train-planning/modal/calendar/index.tsx
  39. 44 0
      src/school/train-planning/modal/class-list/index.module.less
  40. 55 0
      src/school/train-planning/modal/class-list/index.tsx
  41. 2 2
      vite.config.ts

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/assets/exercis-detail-legacy.8128183b.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/assets/exercis-detail.f1751904.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/assets/index-legacy.bd959491.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/assets/index.d69d5aad.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/assets/unbind-legacy.ff30fb4d.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
dist/assets/unbind.3c0101ad.js


+ 1 - 1
src/constant/index.ts

@@ -2,7 +2,7 @@
 
 // 管理老师状态
 export const manageTeacherType = {
-  CANCEL: '注销',
+  // CANCEL: '注销',
   LOCKED: '冻结',
   ACTIVATION: '正常'
 }

+ 24 - 0
src/router/routes-school.ts

@@ -211,6 +211,30 @@ export default [
         meta: {
           title: '审批详情'
         }
+      },
+      {
+        path: '/train-planning',
+        name: 'train-planning',
+        component: () => import('@/school/train-planning/index'),
+        meta: {
+          title: '训练规划'
+        }
+      },
+      {
+        path: '/train-content',
+        name: 'train-content',
+        component: () => import('@/school/train-planning/component/train-content'),
+        meta: {
+          title: '训练内容'
+        }
+      },
+      {
+        path: '/course-preview',
+        name: 'course-preview',
+        component: () => import('@/school/train-planning/component/course-preview'),
+        meta: {
+          title: '课程预览'
+        }
       }
       //
     ]

+ 1 - 1
src/school/companion-teacher/companion-teacher-register.tsx

@@ -276,7 +276,7 @@ export default defineComponent({
             </Field>
             <div class={styles.phoneTips}>
               <Icon name="warning" size="16" />
-              提示:手机号码将成为您管乐团管理端登录账号
+              提示:手机号码将成为您管乐团老师端登录账号
             </div>
 
             <Field

+ 1 - 1
src/school/companion-teacher/compontent/teacher.tsx

@@ -40,7 +40,7 @@ export default defineComponent({
         form.listState.loading = false
         const result = res.data || {}
         // 处理重复请求数据
-        if (form.list.length > 0 && result.pageNo === 1) {
+        if (form.list.length > 0 && result.current === 1) {
           return
         }
         const rows = result.rows || []

+ 5 - 4
src/school/companion-teacher/index.tsx

@@ -30,7 +30,7 @@ export default defineComponent({
       schoolName: null,
       schoolId: null,
       url: null as any,
-      subjectList: [] as any,
+      subjectList: [{ text: '全部声部', value: 'ALL' }] as any,
       list: [] as any,
       listState: {
         dataShow: true, // 判断是否有数据
@@ -99,7 +99,7 @@ export default defineComponent({
         form.listState.loading = false
         const result = res.data || {}
         // 处理重复请求数据
-        if (form.list.length > 0 && result.pageNo === 1) {
+        if (form.list.length > 0 && result.current === 1) {
           return
         }
         const rows = result.rows || []
@@ -138,7 +138,8 @@ export default defineComponent({
     // 选择声部
     const onConfirmSubject = (item: any) => {
       form.subjectText = item.selectedOptions[0].text
-      form.params.subjectId = item.selectedOptions[0].value
+      form.params.subjectId =
+        item.selectedOptions[0].value === 'ALL' ? null : item.selectedOptions[0].value
       form.showPopover = false
       onSearch()
     }
@@ -354,7 +355,7 @@ export default defineComponent({
           actions={
             [
               { name: '全部', id: 'ALL' },
-              { name: '注销', id: 'CANCEL' },
+              // { name: '注销', id: 'CANCEL' },
               { name: '冻结', id: 'LOCKED' },
               { name: '正常', id: 'ACTIVATION' }
             ] as any

+ 1 - 1
src/school/exercise-record/exercis-detail.tsx

@@ -74,7 +74,7 @@ export default defineComponent({
           data: { ...forms }
         })
 
-        if (list.value.length > 0 && res.data.pageNo === 1) {
+        if (list.value.length > 0 && res.data.current === 1) {
           return
         }
 

+ 3 - 3
src/school/mass-message/index.tsx

@@ -33,12 +33,12 @@ export default defineComponent({
         // state.loading = false
         // const result = res.data || {}
         // 处理重复请求数据
-        // if (state.list.length > 0 && result.pageNo === 1) {
+        // if (state.list.length > 0 && result.current === 1) {
         //   return
         // }
         // state.list = state.list.concat(result.rows || [])
-        // state.finished = result.pageNo >= result.totalPage
-        // state.params.page = result.pageNo + 1
+        // state.finished = result.current >= result.totalPage
+        // state.params.page = result.current + 1
         // state.dataShow = state.list.length > 0
       } catch {
         // state.dataShow = false

+ 1 - 1
src/school/orchestra/compontent/information.tsx

@@ -101,7 +101,7 @@ export default defineComponent({
         state.listState.loading = false
         const result = res.data || {}
         // 处理重复请求数据
-        if (state.list.length > 0 && result.pageNo === 1) {
+        if (state.list.length > 0 && result.current === 1) {
           return
         }
         const rows = result.rows || []

+ 1 - 1
src/school/orchestra/compontent/photo-detail.tsx

@@ -64,7 +64,7 @@ export default defineComponent({
         state.listState.loading = false
         const result = res.data || {}
         // 处理重复请求数据
-        if (state.list.length > 0 && result.pageNo === 1) {
+        if (state.list.length > 0 && result.current === 1) {
           return
         }
         const rows = result.rows || []

+ 1 - 1
src/school/orchestra/compontent/photo.tsx

@@ -72,7 +72,7 @@ export default defineComponent({
         state.listState.loading = false
         const result = res.data || {}
         // 处理重复请求数据
-        if (state.list.length > 0 && result.pageNo === 1) {
+        if (state.list.length > 0 && result.current === 1) {
           return
         }
         const rows = result.rows || []

+ 1 - 1
src/school/orchestra/compontent/plan.tsx

@@ -87,7 +87,7 @@ export default defineComponent({
         state.listState.loading = false
         const result = res.data || {}
         // 处理重复请求数据
-        if (state.list.length > 0 && result.pageNo === 1) {
+        if (state.list.length > 0 && result.current === 1) {
           return
         }
         const rows = result.rows || []

+ 26 - 3
src/school/orchestra/create-orchestra/index.tsx

@@ -77,6 +77,7 @@ export default defineComponent({
             temps.push({
               id: item.id,
               name: item.name,
+              code: item.code,
               type: null,
               teacher: {}, // 老师信息
               students: [] as any // 选中的数据数
@@ -112,12 +113,34 @@ export default defineComponent({
       }
 
       // 初始化班级
-      state.selectLastTeacherSubjects = deepClone(state.selectSubjects)
+      const tempSelect: any = []
       // 添加所在学生
       const tempStudents: any = []
+      let largeUpSubject: any = {} // 上低音号和大号合集,目前根据编码处理,待定
       state.selectSubjects.forEach((item: any) => {
-        tempStudents.push(...item.students)
+        console.log(item, 'item.name')
+        if (item.code !== 'BARITONE' && item.code !== 'TUBA') {
+          tempStudents.push(...item.students)
+          tempSelect.push(item)
+        } else {
+          // 获取学生
+          const temps = largeUpSubject.students ? largeUpSubject.students : []
+          largeUpSubject = {
+            id: largeUpSubject.id ? largeUpSubject.id + ',' + item.id : item.id,
+            name: largeUpSubject.name ? largeUpSubject.name + '-' + item.name : item.name,
+            type: null,
+            teacher: {},
+            students: [...temps, ...item.students]
+          }
+        }
       })
+
+      state.selectLastTeacherSubjects = deepClone(tempSelect)
+
+      // 判断是否有大号或者上低音号, 如果有则添加
+      if (largeUpSubject.id) {
+        state.selectLastTeacherSubjects.push(largeUpSubject)
+      }
       // 默认添加两个班级
       state.selectLastTeacherSubjects.push(
         {
@@ -204,7 +227,7 @@ export default defineComponent({
           <SubjectList
             onClose={() => (state.subjectStatus = false)}
             subjectList={state.subjectList}
-            selectSubjects={state.selectSubjects}
+            selectSubjects={state.selectSubjectIds}
             onSelect={onSelectSubject}
           />
         </OPopup>

+ 1 - 1
src/school/orchestra/create-orchestra/select-teacher.tsx

@@ -59,7 +59,7 @@ export default defineComponent({
 
     const onConfirm = () => {
       resestState()
-      router.replace('/my-orchestra')
+      router.replace('/train-planning')
     }
     // 取消
     const onCancel = () => {

+ 13 - 2
src/school/orchestra/modal/subject-list.tsx

@@ -1,6 +1,6 @@
 import OHeader from '@/components/o-header'
 import { Button, Checkbox, CheckboxGroup, Icon, Image } from 'vant'
-import { defineComponent, reactive, ref } from 'vue'
+import { defineComponent, onMounted, reactive, ref, watch } from 'vue'
 import styles from './subject-list.module.less'
 import checkboxCheck from '@/common/images/icon-checkbox-check.png'
 import checkboxDefault from '@/common/images/icon-checkbox-default.png'
@@ -21,7 +21,7 @@ export default defineComponent({
   emits: ['close', 'select'],
   setup(props, { slots, attrs, emit }) {
     const state = reactive({
-      check: [],
+      check: [] as any,
       checkboxRefs: [] as any
     })
 
@@ -34,6 +34,17 @@ export default defineComponent({
       emit('close')
     }
 
+    watch(
+      () => props.selectSubjects,
+      () => {
+        state.check = [...props.selectSubjects]
+      }
+    )
+
+    onMounted(() => {
+      state.check = [...props.selectSubjects]
+    })
+
     return () => (
       <div style={{ minHeight: '100vh' }}>
         <OHeader title="选择声部" />

+ 1 - 1
src/school/orchestra/orchestra-information.tsx

@@ -44,7 +44,7 @@ export default defineComponent({
         state.listState.loading = false
         const result = res.data || {}
         // 处理重复请求数据
-        if (state.list.length > 0 && result.pageNo === 1) {
+        if (state.list.length > 0 && result.current === 1) {
           return
         }
         const rows = result.rows || []

+ 114 - 0
src/school/train-planning/component/course-preview/index.module.less

@@ -0,0 +1,114 @@
+.dialogTitle {
+  i {
+    display: inline-block;
+    width: 4px;
+    height: 14px;
+    background: #ff8057;
+    border-radius: 2px;
+    margin-right: 6px;
+  }
+
+  padding-left: 25px;
+  text-align: left;
+  font-size: 18px;
+  font-weight: 500;
+  color: #333333;
+  line-height: 25px;
+  padding-bottom: 12px;
+}
+
+.coursePreview {
+}
+.orchestraTabs {
+  font-weight: 400;
+  --van-tab-active-text-color: var(--van-primary-color);
+  --van-tab-text-color: #333;
+  --van-tab-font-size: 16px;
+  :global {
+    .van-tabs__wrap {
+      padding-bottom: 3px;
+    }
+  }
+}
+
+.courseTabs {
+  :global {
+    .van-tabs__nav {
+      background: #f6f8f9;
+    }
+
+    .van-tab__text {
+      font-size: 14px;
+      color: #aaaaaa;
+      line-height: 20px;
+      background: #eaeaea;
+      border-radius: 4px;
+      padding: 3px 9px;
+    }
+
+    .van-tab--active {
+      .van-tab__text {
+        color: #fff;
+        background: #ff8057;
+      }
+    }
+  }
+}
+
+.cellGroup {
+  border-radius: 10px;
+  overflow: hidden;
+  margin: 3px 13px 12px;
+  .cellDatetime {
+    padding: 12px 12px 10px;
+  }
+  .cellTeacher {
+    padding: 10px 12px 15px;
+  }
+
+  .cellDate {
+    font-size: 14px;
+    font-weight: 500;
+    color: #777777;
+    line-height: 20px;
+    .iconTimer {
+      font-size: 18px;
+      margin-right: 6px;
+    }
+  }
+
+  .cellTime {
+    font-size: 14px;
+    font-weight: 500;
+    color: #777777;
+    line-height: 20px;
+  }
+
+  .img {
+    width: 42px;
+    height: 42px;
+    overflow: hidden;
+    border-radius: 50%;
+    margin-right: 10px;
+    flex-shrink: 0;
+  }
+
+  .cellTimeRange {
+    padding: 12px 12px 0;
+    font-size: 30px;
+    font-weight: bold;
+    color: #333333;
+    line-height: 35px;
+  }
+  .teacherName {
+    font-size: 16px;
+    font-weight: 600;
+    color: #333333;
+  }
+
+  .btn {
+    padding: 5px 28px;
+    height: 32px;
+    line-height: 30px;
+  }
+}

+ 104 - 0
src/school/train-planning/component/course-preview/index.tsx

@@ -0,0 +1,104 @@
+import OHeader from '@/components/o-header'
+import OSticky from '@/components/o-sticky'
+import { Button, Cell, CellGroup, Dialog, Icon, Image, Tab, Tabs, Tag } from 'vant'
+import { defineComponent, reactive } from 'vue'
+import styles from './index.module.less'
+import iconTimer from '../../images/icon-timer.png'
+import iconTeacher from '@common/images/icon_teacher.png'
+
+export default defineComponent({
+  name: 'course-preview',
+  setup() {
+    const forms = reactive({
+      conflictStatus: false,
+      conflictMessage: '该时间段伴学指导在其他学校有课',
+      tabValue: '1',
+      courseValue: '1'
+    })
+    return () => (
+      <div class={styles.coursePreview}>
+        <OSticky position="top">
+          <OHeader border={false} />
+          <Tabs
+            lineWidth={20}
+            lineHeight={4}
+            v-model:active={forms.tabValue}
+            swipeThreshold={3}
+            class={styles.orchestraTabs}
+          >
+            <Tab title="2022上学期团" name="1"></Tab>
+            <Tab title="2022下学期团" name="2"></Tab>
+            <Tab title="2022下学期团" name="2"></Tab>
+            <Tab title="2022下学期团" name="2"></Tab>
+            <Tab title="2022下学期团" name="2"></Tab>
+          </Tabs>
+
+          <Tabs
+            swipeThreshold={3}
+            class={styles.courseTabs}
+            v-model:active={forms.courseValue}
+            lineHeight={0}
+            shrink
+          >
+            <Tab title="长笛班" name="1"></Tab>
+            <Tab title="乐理班" name="1"></Tab>
+            <Tab title="小号班" name="1"></Tab>
+            <Tab title="长笛" name="1"></Tab>
+          </Tabs>
+        </OSticky>
+
+        <CellGroup inset class={styles.cellGroup}>
+          <Cell center class={styles.cellDatetime}>
+            {{
+              title: () => (
+                <div class={styles.cellDate}>
+                  <Icon name={iconTimer} class={styles.iconTimer} />
+                  2022-10-31
+                </div>
+              ),
+              value: () => <span class={styles.cellTime}>45分钟</span>
+            }}
+          </Cell>
+          <div class={styles.cellTimeRange}>14:00-15:30</div>
+          <Cell center class={styles.cellTeacher}>
+            {{
+              icon: () => <Image src={iconTeacher} class={styles.img} />,
+              title: () => (
+                <div class={styles.teacherInfo}>
+                  <p class={styles.teacherName}>李老师</p>
+                  <Tag type="primary">乐理课</Tag>
+                </div>
+              ),
+              value: () => (
+                <Button round plain type="primary" class={styles.btn}>
+                  调整
+                </Button>
+              )
+            }}
+          </Cell>
+        </CellGroup>
+
+        <Dialog
+          v-model:show={forms.conflictStatus}
+          message={forms.conflictMessage}
+          messageAlign="left"
+          confirmButtonText="知道了"
+          cancelButtonText="暂不设置"
+          showCancelButton
+          onConfirm={() => {
+            // forms.classStatus = true
+          }}
+        >
+          {{
+            title: () => (
+              <div class={styles.dialogTitle}>
+                <i></i>
+                课程冲突
+              </div>
+            )
+          }}
+        </Dialog>
+      </div>
+    )
+  }
+})

+ 0 - 0
src/school/train-planning/component/practice/index.module.less


+ 8 - 0
src/school/train-planning/component/practice/index.tsx

@@ -0,0 +1,8 @@
+import { defineComponent } from 'vue'
+
+export default defineComponent({
+  name: 'standard',
+  setup() {
+    return () => '标准加练'
+  }
+})

+ 74 - 0
src/school/train-planning/component/standard/index.module.less

@@ -0,0 +1,74 @@
+.tips {
+  display: flex;
+  align-items: center;
+  margin: 12px 13px;
+  background: #ffebdd;
+  border-radius: 10px;
+  padding: 7px 19px;
+  font-size: 14px;
+  color: #f67146;
+  line-height: 20px;
+
+  .icon {
+    font-size: 24px;
+    margin-right: 6px;
+  }
+}
+
+.cellGroup {
+  margin: 0 13px;
+  border-radius: 10px;
+  overflow: hidden;
+
+  :global {
+    .van-cell {
+      font-size: 16px;
+      padding: 18px 12px;
+    }
+    .van-cell__value {
+      color: #333;
+    }
+
+    .van-radio-group {
+      justify-content: flex-end;
+    }
+  }
+
+  .radioSection {
+    position: relative;
+    min-width: 32px;
+    justify-content: center;
+  }
+
+  .radioItem {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    opacity: 0;
+  }
+
+  .radioSection + .radioSection {
+    margin-left: 12px;
+  }
+}
+
+.dialogTitle {
+  i {
+    display: inline-block;
+    width: 4px;
+    height: 14px;
+    background: #ff8057;
+    border-radius: 2px;
+    margin-right: 6px;
+  }
+
+  padding-left: 25px;
+  text-align: left;
+  font-size: 18px;
+  font-weight: 500;
+  color: #333333;
+  line-height: 25px;
+  padding-bottom: 12px;
+}

+ 210 - 0
src/school/train-planning/component/standard/index.tsx

@@ -0,0 +1,210 @@
+import OPopup from '@/components/o-popup'
+import OSticky from '@/components/o-sticky'
+import request from '@/helpers/request'
+import { state } from '@/state'
+import dayjs from 'dayjs'
+import {
+  Button,
+  Cell,
+  CellGroup,
+  Dialog,
+  Icon,
+  Picker,
+  Popup,
+  Radio,
+  RadioGroup,
+  Sticky,
+  Tag
+} from 'vant'
+import { defineComponent, onMounted, reactive } from 'vue'
+import { weekdays, weekFormat } from '../../create'
+import Calendar from '../../modal/calendar'
+import ClassList from '../../modal/class-list'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'standard',
+  setup() {
+    const forms = reactive({
+      status: false,
+      weekStatus: false,
+      calendarStatus: false,
+      classStatus: false,
+      holiday: 1,
+      week: null,
+      times: 1,
+      classList: [] as any,
+      calendarList: [] as any,
+      calendarDate: null as any,
+      trainStartDate: null
+    })
+
+    const getList = async (date?: any) => {
+      try {
+        const { data } = await request.post('/api-school/orchestra/trainingPlanTime', {
+          data: {
+            schoolId: state.user.data.school.id,
+            skipHoliday: forms.holiday ? true : false,
+            type: 'STANDARD',
+            calendarDate: dayjs(date).format('YYYY-MM-DD')
+          }
+        })
+        // console.log(data)
+        forms.calendarList = data || []
+      } catch {
+        //
+      }
+    }
+
+    // 查询没有设置指导老师的班级
+    const getClasses = async () => {
+      try {
+        const { data } = await request.post('/api-school/classGroup/page', {
+          data: {
+            page: 1,
+            rows: 20,
+            schoolId: state.user.data.school.id,
+            hasTeacher: false,
+            orchestraType: 'DELIVERY'
+          }
+        })
+        // 班级数据
+        forms.classList = data.rows || []
+        // 判断没有设置伴学指导的班级
+        if (forms.classList.length > 0) {
+          forms.status = true
+        }
+      } catch {
+        //
+      }
+    }
+
+    onMounted(() => {
+      getList()
+
+      getClasses()
+    })
+
+    return () => (
+      <div class={styles.standard}>
+        <div class={styles.tips}>
+          <Icon name="warning" class={styles.icon} />
+          标准训练可对交付团进行整学期标准训练排课
+        </div>
+
+        <CellGroup inset class={styles.cellGroup}>
+          <Cell
+            title="训练开始日期"
+            isLink
+            value={forms.trainStartDate ? dayjs(forms.trainStartDate).format('YYYY年MM月DD日') : ''}
+            onClick={() => (forms.calendarStatus = true)}
+          ></Cell>
+          <Cell title="训练开始时间" isLink value=""></Cell>
+          <Cell title="训练时长" value="120分钟"></Cell>
+          <Cell
+            title="训练周次"
+            isLink
+            value={weekFormat(forms.week)}
+            onClick={() => (forms.weekStatus = true)}
+          ></Cell>
+          <Cell title="训练次数" isLink value={forms.times + '次'}></Cell>
+          <Cell title="跳过节假日">
+            {{
+              value: () => (
+                <RadioGroup checked-color="#FF8057" v-model={forms.holiday} direction="horizontal">
+                  <Tag
+                    size="large"
+                    type="primary"
+                    plain={!(forms.holiday === 1)}
+                    color="#FF8057"
+                    class={styles.radioSection}
+                  >
+                    <Radio class={styles.radioItem} name={1}></Radio>是
+                  </Tag>
+                  <Tag
+                    size="large"
+                    type="primary"
+                    plain={!(forms.holiday === 0)}
+                    color="#FF8057"
+                    class={styles.radioSection}
+                  >
+                    <Radio class={styles.radioItem} name={0}></Radio>否
+                  </Tag>
+                </RadioGroup>
+              )
+            }}
+          </Cell>
+        </CellGroup>
+
+        <Sticky position="bottom">
+          <div class={'btnGroup'} style={{ marginTop: '24px' }}>
+            <Button
+              type="primary"
+              block
+              round
+              size="large"
+              onClick={() => {
+                // forms.status = true
+              }}
+            >
+              下一步
+            </Button>
+          </div>
+        </Sticky>
+
+        <Popup v-model:show={forms.weekStatus} position="bottom" round>
+          <Picker
+            columns={weekdays}
+            onCancel={() => (forms.weekStatus = false)}
+            onConfirm={(val: any) => {
+              forms.week = val.selectedValues[0]
+              forms.weekStatus = false
+            }}
+          />
+        </Popup>
+
+        <OPopup v-model:modelValue={forms.calendarStatus} position="bottom">
+          <Calendar
+            list={forms.calendarList}
+            nextMonth={(date: Date) => getList(date)}
+            prevMonth={(date: Date) => getList(date)}
+            onSelect={(date: any) => {
+              forms.calendarStatus = false
+              forms.trainStartDate = date
+            }}
+            v-model:calendarDate={forms.calendarDate}
+          />
+        </OPopup>
+
+        <Dialog
+          v-model:show={forms.status}
+          message={`您有${forms.classList.length}个班级尚未指定伴学指导,请完成指定后再进行训练规划。`}
+          messageAlign="left"
+          confirmButtonText="去设置"
+          cancelButtonText="暂不设置"
+          showCancelButton
+          onConfirm={() => {
+            forms.classStatus = true
+          }}
+        >
+          {{
+            title: () => (
+              <div class={styles.dialogTitle}>
+                <i></i>
+                指定伴学指导
+              </div>
+            )
+          }}
+        </Dialog>
+
+        <OPopup
+          v-model:modelValue={forms.classStatus}
+          position="bottom"
+          style={{ background: '#F6F6F6' }}
+        >
+          <ClassList onClose={() => (forms.classStatus = false)} />
+        </OPopup>
+      </div>
+    )
+  }
+})

+ 43 - 0
src/school/train-planning/component/train-content/index.module.less

@@ -0,0 +1,43 @@
+.cellGroup {
+  margin: 12px 13px;
+  :global {
+    .van-cell {
+      padding: 12px 15px;
+    }
+  }
+
+  .classType {
+    display: flex;
+    align-items: center;
+    font-size: 16px;
+    font-weight: 600;
+    color: #333333;
+    line-height: 22px;
+    .classNum {
+      margin-left: 6px;
+    }
+  }
+
+  .classTime {
+    font-size: 14px;
+    font-weight: 500;
+    color: #333333;
+    line-height: 20px;
+  }
+
+  .orchestra {
+    font-size: 14px;
+    color: #333333;
+    .name {
+      color: #777777;
+      line-height: 20px;
+      padding-bottom: 3px;
+    }
+
+    span {
+      padding: 0 5px;
+      font-size: 20px;
+      color: #f67146;
+    }
+  }
+}

+ 53 - 0
src/school/train-planning/component/train-content/index.tsx

@@ -0,0 +1,53 @@
+import OHeader from '@/components/o-header'
+import OSticky from '@/components/o-sticky'
+import { Button, Cell, CellGroup, Tag } from 'vant'
+import { defineComponent } from 'vue'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'train-content',
+  setup() {
+    return () => (
+      <>
+        <OHeader />
+        {/* 训练内容 */}
+
+        <CellGroup inset class={styles.cellGroup}>
+          <Cell center>
+            {{
+              title: () => (
+                <div class={styles.classType}>
+                  乐理课
+                  <Tag round type="primary" size="medium" class={styles.classNum}>
+                    16课时
+                  </Tag>
+                </div>
+              ),
+              value: () => <span class={styles.classTime}>每周三 14:00-14:45</span>
+            }}
+          </Cell>
+          <Cell center>
+            {{
+              title: () => (
+                <div class={styles.orchestra}>
+                  <p class={styles.name}>武汉洪山区第二小学2022下学期团</p>
+                  <p class={styles.class}>
+                    共<span>3</span>个班级
+                  </p>
+                </div>
+              )
+            }}
+          </Cell>
+        </CellGroup>
+
+        <OSticky position="bottom">
+          <div class={'btnGroup'}>
+            <Button round type="primary" size="large" block>
+              下一步
+            </Button>
+          </div>
+        </OSticky>
+      </>
+    )
+  }
+})

+ 39 - 0
src/school/train-planning/create.ts

@@ -0,0 +1,39 @@
+// 训练周次
+export const weekdays = [{
+  text: '周一',
+  value: 1
+}, {
+  text: '周二',
+  value: 2
+}, {
+  text: '周三',
+  value: 3
+}, {
+  text: '周四',
+  value: 4
+}, {
+  text: '周五',
+  value: 5
+}, {
+  text: '周六',
+  value: 6
+}, {
+  text: '周日',
+  value: 7
+}]
+// 格式化
+export const weekFormat = (val: any) => {
+  const template = {
+    1: '周一',
+    2: '周二',
+    3: '周三',
+    4: '周四',
+    5: '周五',
+    6: '周六',
+    7: '周日'
+  }
+  if (val) {
+    return template[val]
+  }
+  return val
+}

BIN
src/school/train-planning/images/calendar_bg.png


BIN
src/school/train-planning/images/icon-timer.png


BIN
src/school/train-planning/images/icon_arrow.png


BIN
src/school/train-planning/images/icon_arrow_default.png


+ 13 - 0
src/school/train-planning/index.module.less

@@ -0,0 +1,13 @@
+.train {
+  --van-tab-active-text-color: var(--van-primary-color);
+  --van-tab-text-color: #333;
+  --van-tab-font-size: 16px;
+  :global {
+    .van-tab {
+      font-weight: 400;
+    }
+    .van-tabs__wrap {
+      padding-bottom: 3px;
+    }
+  }
+}

+ 29 - 0
src/school/train-planning/index.tsx

@@ -0,0 +1,29 @@
+import OHeader from '@/components/o-header'
+import OSticky from '@/components/o-sticky'
+import { Sticky, Tab, Tabs } from 'vant'
+import { defineComponent, ref } from 'vue'
+import Practice from './component/practice'
+import Standard from './component/standard'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'train-planning',
+  setup() {
+    const tabValue = ref('standard')
+    return () => (
+      <div class={styles.train}>
+        <OSticky position="top">
+          <OHeader />
+          <Tabs sticky lineWidth={20} lineHeight={4} v-model:active={tabValue.value}>
+            <Tab title="标准训练" name="standard">
+              <Standard />
+            </Tab>
+            <Tab title="乐团加练" name="practice">
+              <Practice />
+            </Tab>
+          </Tabs>
+        </OSticky>
+      </div>
+    )
+  }
+})

+ 100 - 0
src/school/train-planning/modal/calendar/index.module.less

@@ -0,0 +1,100 @@
+.calendarContainer {
+  background: url('../../images/calendar_bg.png') no-repeat top center;
+  background-size: contain;
+}
+.calendar {
+  border-radius: 10px;
+  height: auto;
+  background: transparent;
+  margin: 0 16px;
+
+  .subtitle {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    font-size: 18px;
+    font-weight: 500;
+    color: #333333;
+    line-height: 25px;
+    height: var(--van-calendar-header-title-height);
+    padding: 0 13px;
+
+    .right {
+      transform: rotateZ(180deg);
+      margin-right: 16px;
+    }
+
+    .disabled {
+      opacity: 0.6;
+    }
+  }
+  :global {
+    .van-calendar__header {
+      box-shadow: none;
+    }
+    .van-calendar__selected-day {
+      width: 40px !important;
+      height: 54px !important;
+      border-radius: 5px;
+      overflow: hidden;
+      align-items: flex-start;
+      background: linear-gradient(45deg, #ffa357 0%, #ff6736 100%) !important;
+      .van-calendar__bottom-info {
+        color: #fff !important;
+        background: #ff945c;
+        box-shadow: 1px 2px 4px 0px #ff6221;
+      }
+    }
+    .van-calendar__weekday {
+      color: #777;
+      font-size: 14px;
+    }
+    .van-calendar__day {
+      font-size: 20px;
+      font-weight: bold;
+      color: #333;
+      align-items: flex-start;
+      // padding-top: 6px;
+
+      &::after {
+        position: absolute;
+        top: 50%;
+        right: 0;
+        bottom: 0;
+        left: 50%;
+        width: 40px;
+        height: 54px;
+        background: #fff7ed;
+        content: ' ';
+        transform: translate(-50%, -50%);
+        border-radius: 4px;
+        z-index: -1;
+      }
+    }
+    .van-calendar__day--disabled {
+      &::after {
+        background: #f8f8f8;
+      }
+    }
+    .van-calendar__days {
+      padding: 12px 0;
+    }
+    .van-calendar__bottom-info {
+      bottom: 6px;
+      background: #ffe7c8;
+      border-radius: 4px;
+      font-size: 11px;
+      font-weight: 500;
+      color: #b96c2e;
+      line-height: 16px;
+      width: 64%;
+      margin-left: 18%;
+    }
+
+    .van-calendar__day.full::after,
+    .van-calendar__day--disabled.full::after {
+      display: inline-block !important;
+      background-color: #ffd7a6;
+    }
+  }
+}

+ 192 - 0
src/school/train-planning/modal/calendar/index.tsx

@@ -0,0 +1,192 @@
+import { Button, Calendar, Dialog, Icon, Image, Popup, showToast, Tag, Toast } from 'vant'
+import { defineComponent } from 'vue'
+import dayjs from 'dayjs'
+import styles from './index.module.less'
+import IconArrow from '../../images/icon_arrow.png'
+import IconArrowDefault from '../../images/icon_arrow_default.png'
+import isToday from 'dayjs/plugin/isToday'
+import OHeader from '@/components/o-header'
+dayjs.extend(isToday)
+
+export default defineComponent({
+  name: 'calendar',
+  props: {
+    calendarDate: {
+      type: String,
+      default: ''
+    },
+    // 接口数据
+    list: {
+      type: Array,
+      default: () => []
+    },
+    /**
+     * 点击并选中任意日期时触发
+     */
+    onSelect: {
+      type: Function,
+      default: (date: Date) => {}
+    },
+    /**
+     * 上一月,不能小于当月
+     */
+    prevMonth: {
+      type: Function,
+      default: (date: Date) => {}
+    },
+    /**
+     * 下一月,暂无限制
+     */
+    nextMonth: {
+      type: Function,
+      default: (date: Date) => {}
+    },
+    /**
+     * 日期选择结束时触发
+     */
+    selectDay: {
+      type: Function,
+      default: (obj: any) => {}
+    }
+  },
+  data() {
+    return {
+      minDate: new Date(),
+      maxDate: new Date(),
+      currentDate: dayjs().add(1, 'day').toDate(), // 当前日历日期
+      subtitle: '',
+      dayList: [],
+      selectDays: [] as any
+    }
+  },
+  computed: {
+    arrowStatus() {
+      // 上月箭头状态
+      return !dayjs().add(1, 'day').isBefore(dayjs(this.currentDate), 'month')
+    },
+    selectDayTitle() {
+      // 选中日期标题
+      return dayjs(this.currentDate).format('YYYY-MM-DD')
+    },
+    isPrevDay() {
+      // 是否可以点击上一天
+      return dayjs(this.currentDate).subtract(1, 'day').isBefore(dayjs(this.minDate), 'day')
+    },
+    isNextDay() {
+      // 是否可以点击下一天
+      return dayjs(this.currentDate).add(1, 'day').isAfter(dayjs(this.maxDate), 'day')
+    }
+  },
+  mounted() {
+    // 初始化标题和最大显示日期
+    this.subtitle = dayjs().add(1, 'day').format('YYYY年MM月')
+    this.maxDate = dayjs().add(1, 'day').endOf('month').toDate()
+    this.minDate = dayjs().add(1, 'day').toDate()
+
+    console.log(this.list, 'this.list')
+  },
+  methods: {
+    formatter(date: any) {
+      const dateStr = dayjs(date.date).format('YYYY-MM-DD')
+      let isActive = false // 是否可选
+      this.list.forEach((item: any) => {
+        if (item.calendarDate === dateStr) {
+          isActive = true
+        }
+      })
+
+      // 判断是否有课程 并且 时间在当前时间之后
+      if (isActive && dayjs().isBefore(dayjs(date.date))) {
+        date.bottomInfo = '可选'
+        if (dayjs(dateStr).isSame(this.calendarDate)) {
+          date.type = 'selected'
+        } else {
+          date.type = ''
+        }
+      } else {
+        date.type = 'disabled'
+      }
+      return date
+    },
+    onPrevMonth() {
+      // 上一月
+      if (this.arrowStatus) return
+      const tempDate = dayjs(this.currentDate).subtract(1, 'month')
+      this._monthChange(tempDate)
+      this.prevMonth && this.prevMonth(this.minDate)
+    },
+    onNextMonth() {
+      // 下一月
+      const tempDate = dayjs(this.currentDate).add(1, 'month')
+      this._monthChange(tempDate)
+      this.nextMonth && this.nextMonth(this.minDate)
+    },
+    _monthChange(date: any) {
+      // 月份改变
+      // 需要判断是否是当月,需要单独处理最小时间
+      const currentMinDate = dayjs().add(1, 'day').toDate()
+      const monthMinDate = date.startOf('month').toDate()
+      this.minDate = dayjs(currentMinDate).isAfter(monthMinDate) ? currentMinDate : monthMinDate
+      this.maxDate = date.endOf('month').toDate()
+      this.currentDate = date.toDate()
+      this.$emit('update:calendarDate', date.toDate())
+      this.subtitle = date.format('YYYY年MM月')
+    },
+    onPrevDay() {
+      // 获取上一天的数据
+      const tempDate = dayjs(this.currentDate).subtract(1, 'day')
+      this._dayChange(tempDate.toDate())
+    },
+    onNextDay() {
+      // 获取下一天的数据
+      const tempDate = dayjs(this.currentDate).add(1, 'day')
+      this._dayChange(tempDate.toDate())
+    },
+    onDateSelect(date: any) {
+      // 选择日历上某一个日期
+      this._dayChange(date)
+      this.onSelect && this.onSelect(date)
+    },
+    _dayChange(date: Date) {
+      this.currentDate = date // 更新当前日期
+      this.$emit('update:calendarDate', dayjs(date).format('YYYY-MM-DD'))
+    }
+  },
+  render() {
+    return (
+      <div class={styles.calendarContainer}>
+        <OHeader title="训练日期" border={false} background="transparent" />
+        <Calendar
+          class={styles.calendar}
+          showTitle={false}
+          poppable={false}
+          showConfirm={false}
+          showMark={false}
+          firstDayOfWeek={1}
+          rowHeight={62}
+          minDate={this.minDate}
+          maxDate={this.maxDate}
+          color="var(--van-primary)"
+          formatter={this.formatter}
+          onSelect={this.onDateSelect}
+          v-slots={{
+            subtitle: () => (
+              <div class={styles.subtitle}>
+                <span>{this.subtitle}</span>
+                <div>
+                  <Icon
+                    name={this.arrowStatus ? IconArrowDefault : IconArrow}
+                    size={22}
+                    class={[styles.right]}
+                    onClick={this.onPrevMonth}
+                  />
+                  <Icon name={IconArrow} size={22} onClick={this.onNextMonth} />
+                </div>
+              </div>
+            )
+          }}
+        />
+      </div>
+    )
+  }
+})

+ 44 - 0
src/school/train-planning/modal/class-list/index.module.less

@@ -0,0 +1,44 @@
+.classList {
+  .cell {
+    margin: 13px;
+    border-radius: 10px;
+    width: calc(100% - 26px);
+    padding: 15px;
+  }
+  :global {
+    .van-cell__title {
+      flex: 1 auto;
+    }
+  }
+
+  .content {
+    .title {
+      display: flex;
+      align-items: center;
+      font-size: 16px;
+      font-weight: 500;
+      color: #333333;
+      line-height: 22px;
+      i {
+        margin-right: 6px;
+        width: 4px;
+        height: 12px;
+        background: #ff8057;
+        border-radius: 2px;
+      }
+    }
+    .name {
+      padding-top: 10px;
+      font-size: 14px;
+      color: #777777;
+      line-height: 20px;
+    }
+  }
+
+  .teacherName {
+    font-size: 16px;
+    font-weight: 500;
+    color: #333333;
+    line-height: 22px;
+  }
+}

+ 55 - 0
src/school/train-planning/modal/class-list/index.tsx

@@ -0,0 +1,55 @@
+import OHeader from '@/components/o-header'
+import OSticky from '@/components/o-sticky'
+import { Button, Cell } from 'vant'
+import { defineComponent } from 'vue'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'class-list',
+  emits: ['close'],
+  setup(props, { slots, attrs, emit }) {
+    const onSubmit = async () => {
+      emit('close')
+    }
+    return () => (
+      <div class={styles.classList}>
+        <OHeader title="指定伴学老师" />
+
+        <Cell class={styles.cell} center isLink>
+          {{
+            title: () => (
+              <div class={styles.content}>
+                <div class={styles.title}>
+                  <i></i>长笛班
+                </div>
+                <div class={styles.name}>武汉洪山区第二小学2022标准团</div>
+              </div>
+            ),
+            value: () => <span class={styles.teacherName}>张老师</span>
+          }}
+        </Cell>
+        <Cell class={styles.cell} center isLink>
+          {{
+            title: () => (
+              <div class={styles.content}>
+                <div class={styles.title}>
+                  <i></i>长笛班
+                </div>
+                <div class={styles.name}>武汉洪山区第二小学2022标准团</div>
+              </div>
+            ),
+            value: () => <span class={styles.teacherName}>张老师</span>
+          }}
+        </Cell>
+
+        <OSticky position="buttom">
+          <div class={'btnGroup'}>
+            <Button round block type="primary" size="large" onClick={onSubmit}>
+              完成
+            </Button>
+          </div>
+        </OSticky>
+      </div>
+    )
+  }
+})

+ 2 - 2
vite.config.ts

@@ -12,8 +12,8 @@ function resolve(dir: string) {
 // https://vitejs.dev/config/
 // https://github.com/vitejs/vite/issues/1930 .env
 // const proxyUrl = 'https://mstutest.dayaedu.com/';
-// const proxyUrl = 'http://47.98.131.38:8989/'
-const proxyUrl = 'http://192.168.3.26:8989/'
+const proxyUrl = 'http://47.98.131.38:8989/'
+// const proxyUrl = 'http://192.168.3.26:8989/'
 export default defineConfig({
   base: './',
   plugins: [

Деякі файли не було показано, через те що забагато файлів було змінено