Ver Fonte

添加训练报告

lex há 2 anos atrás
pai
commit
2e1278085f
38 ficheiros alterados com 1547 adições e 15 exclusões
  1. 24 1
      src/router/routes-school.ts
  2. 175 0
      src/school/train-report/components/list.tsx
  3. BIN
      src/school/train-report/images/icon-arrow-point.png
  4. BIN
      src/school/train-report/images/icon-class.png
  5. BIN
      src/school/train-report/images/icon-photo.png
  6. BIN
      src/school/train-report/images/icon-share.png
  7. BIN
      src/school/train-report/images/month/banner-month.png
  8. BIN
      src/school/train-report/images/month/icon-train-month.png
  9. BIN
      src/school/train-report/images/month/popup-week-banner.png
  10. BIN
      src/school/train-report/images/month/teacher-icon-arrow-line.png
  11. BIN
      src/school/train-report/images/month/teacher-icon-point.png
  12. BIN
      src/school/train-report/images/month/teacher-section-title-bg.png
  13. BIN
      src/school/train-report/images/month/teacher-section-title-bg1.png
  14. BIN
      src/school/train-report/images/month/teacher-section-title-bg2.png
  15. BIN
      src/school/train-report/images/month/teacher-train-bg.png
  16. BIN
      src/school/train-report/images/month/teacher-train-bg1.png
  17. BIN
      src/school/train-report/images/popup-qrcode-bg.png
  18. BIN
      src/school/train-report/images/week/banner-week.png
  19. BIN
      src/school/train-report/images/week/icon-arrow-line.png
  20. BIN
      src/school/train-report/images/week/icon-point.png
  21. BIN
      src/school/train-report/images/week/icon-train-week.png
  22. BIN
      src/school/train-report/images/week/popup-week-banner.png
  23. BIN
      src/school/train-report/images/week/section-title-bg.png
  24. BIN
      src/school/train-report/images/week/section-title-bg1.png
  25. BIN
      src/school/train-report/images/week/section-title-bg2.png
  26. BIN
      src/school/train-report/images/week/train-bg.png
  27. 61 0
      src/school/train-report/index.module.less
  28. 22 0
      src/school/train-report/index.tsx
  29. 193 0
      src/school/train-report/modal/index.module.less
  30. 48 0
      src/school/train-report/modal/orchestra-num.tsx
  31. 139 0
      src/school/train-report/modal/student-attendance.tsx
  32. 150 0
      src/school/train-report/modal/teacher-attendance.tsx
  33. 147 0
      src/school/train-report/modal/train-class.tsx
  34. 65 0
      src/school/train-report/modal/train-progress.tsx
  35. 129 0
      src/school/train-report/month-report.tsx
  36. 259 0
      src/school/train-report/report.module.less
  37. 123 0
      src/school/train-report/week-report.tsx
  38. 12 14
      src/views/subject-echarts/index.tsx

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

@@ -406,7 +406,30 @@ export default [
           title: '考勤规则设置'
         }
       },
-
+      {
+        path: '/train-report',
+        name: 'train-report',
+        component: () => import('@/school/train-report'),
+        meta: {
+          title: '训练报告'
+        }
+      },
+      {
+        path: '/train-week-report',
+        name: 'train-week-report',
+        component: () => import('@/school/train-report/week-report'),
+        meta: {
+          title: '训练周报'
+        }
+      },
+      {
+        path: '/train-month-report',
+        name: 'train-month-report',
+        component: () => import('@/school/train-report/month-report'),
+        meta: {
+          title: '训练月报'
+        }
+      },
       //
     ]
   },

+ 175 - 0
src/school/train-report/components/list.tsx

@@ -0,0 +1,175 @@
+import request from '@/helpers/request'
+import { Button, Cell, CellGroup, List, Picker, Popup } from 'vant'
+import { defineComponent, reactive } from 'vue'
+import styles from '../index.module.less'
+import { state as baseState } from '@/state'
+import iconOrchestra from '@/views/mine-orchestra/images/icon-or.png'
+import OEmpty from '@/components/o-empty'
+import { useRouter } from 'vue-router'
+
+export default defineComponent({
+  name: 'train-list',
+  props: {
+    type: {
+      type: String,
+      default: 'week'
+    }
+  },
+  setup(props) {
+    const router = useRouter()
+    const state = reactive({
+      orchestraStatus: false,
+      orchestraList: [] as any,
+      selectOrchestra: {} as any,
+      isClick: false,
+      list: [] as any,
+      listState: {
+        dataShow: true, // 判断是否有数据
+        loading: false,
+        finished: false,
+        refreshing: false,
+        height: 0 // 页面头部高度,为了处理下拉刷新用的
+      },
+      params: {
+        page: 1,
+        rows: 20
+      }
+    })
+    // 获取乐团列表
+    const getOrchestras = async () => {
+      try {
+        const { data } = await request.post('/api-school/orchestra/page', {
+          data: {
+            page: 1,
+            rows: 100,
+            schoolId: baseState.user.data.school.id,
+            status: 'DONE'
+          }
+        })
+        const temps = data.rows || []
+        const s = [] as any
+        temps.forEach((item: any) => {
+          s.push({
+            text: item.name,
+            value: item.id
+          })
+        })
+        state.orchestraList = [...s]
+
+        // 判断是否有乐团
+        if (s.length > 0) {
+          const orchestraId = sessionStorage.getItem('orchestraStoryId')
+          if (orchestraId) {
+            const item = s.find((child: any) => child.value === orchestraId)
+            state.selectOrchestra = item || s[0]
+          } else {
+            state.selectOrchestra = s[0]
+          }
+        }
+
+        await getList()
+      } catch {
+        //
+      }
+    }
+
+    getOrchestras()
+
+    const getList = async () => {
+      try {
+        await request.post('/api-school/orchestraReport/page', {
+          data: {
+            reportType: props.type,
+            page: state.params.page,
+            rows: state.params.rows
+          }
+        })
+      } catch {
+        //
+      }
+    }
+    return () => (
+      <div
+        style={{
+          minHeight: 'calc(100vh  - var(--van-tabs-line-height))',
+          overflow: 'hidden'
+        }}
+      >
+        {state.orchestraList.length > 0 && (
+          <div style={{ width: '100%' }}>
+            <CellGroup inset class={styles.cellGroup}>
+              <Cell
+                isLink
+                center
+                onClick={() => (state.orchestraStatus = true)}
+                class={styles.select}
+              >
+                {{
+                  icon: () => <img class={styles.icon} src={iconOrchestra} />,
+                  title: () => <div class="van-ellipsis">{state.selectOrchestra.text || ' '}</div>
+                }}
+              </Cell>
+            </CellGroup>
+          </div>
+        )}
+
+        {state.listState.dataShow ? (
+          // <OFullRefresh
+          //   v-model:modelValue={state.listState.refreshing}
+          //   onRefresh={onRefresh}
+          //   style={{
+          //     minHeight: `calc(100vh - ${state.listState.height}px)`
+          //   }}
+          // >
+          <List
+            // v-model:loading={state.listState.loading}
+            finished={state.listState.finished}
+            finishedText=" "
+            class={[styles.liveList]}
+            onLoad={getList}
+            immediateCheck={false}
+          >
+            <Cell center class={styles.reportList}>
+              {{
+                title: () => <div>武汉小学第一届乐团</div>,
+                value: () => (
+                  <Button
+                    type="primary"
+                    round
+                    size="small"
+                    onClick={() => {
+                      router.push('/train-week-report')
+                    }}
+                  >
+                    查看报告
+                  </Button>
+                ),
+                label: () => <div class={styles.time}>2023年3月</div>
+              }}
+            </Cell>
+          </List>
+        ) : (
+          <OEmpty btnStatus={false} tips="暂无训练报告" />
+        )}
+
+        <Popup
+          v-model:show={state.orchestraStatus}
+          position="bottom"
+          round
+          class={'popupBottomSearch'}
+          teleport="body"
+        >
+          <Picker
+            columns={state.orchestraList}
+            onCancel={() => (state.orchestraStatus = false)}
+            onConfirm={(val: any) => {
+              state.selectOrchestra = val.selectedOptions[0]
+              state.orchestraStatus = false
+              sessionStorage.setItem('orchestraStoryId', state.selectOrchestra.value)
+            }}
+          />
+        </Popup>
+      </div>
+    )
+  }
+})

BIN
src/school/train-report/images/icon-arrow-point.png


BIN
src/school/train-report/images/icon-class.png


BIN
src/school/train-report/images/icon-photo.png


BIN
src/school/train-report/images/icon-share.png


BIN
src/school/train-report/images/month/banner-month.png


BIN
src/school/train-report/images/month/icon-train-month.png


BIN
src/school/train-report/images/month/popup-week-banner.png


BIN
src/school/train-report/images/month/teacher-icon-arrow-line.png


BIN
src/school/train-report/images/month/teacher-icon-point.png


BIN
src/school/train-report/images/month/teacher-section-title-bg.png


BIN
src/school/train-report/images/month/teacher-section-title-bg1.png


BIN
src/school/train-report/images/month/teacher-section-title-bg2.png


BIN
src/school/train-report/images/month/teacher-train-bg.png


BIN
src/school/train-report/images/month/teacher-train-bg1.png


BIN
src/school/train-report/images/popup-qrcode-bg.png


BIN
src/school/train-report/images/week/banner-week.png


BIN
src/school/train-report/images/week/icon-arrow-line.png


BIN
src/school/train-report/images/week/icon-point.png


BIN
src/school/train-report/images/week/icon-train-week.png


BIN
src/school/train-report/images/week/popup-week-banner.png


BIN
src/school/train-report/images/week/section-title-bg.png


BIN
src/school/train-report/images/week/section-title-bg1.png


BIN
src/school/train-report/images/week/section-title-bg2.png


BIN
src/school/train-report/images/week/train-bg.png


+ 61 - 0
src/school/train-report/index.module.less

@@ -0,0 +1,61 @@
+.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;
+    }
+  }
+
+  .cellGroup {
+    margin: 12px 13px 0;
+    overflow: hidden;
+    border-radius: 10px;
+    .select {
+      height: 45px;
+
+      .icon {
+        width: 17px;
+        height: 17px;
+        margin-right: 4px;
+        flex-shrink: 0;
+      }
+
+      :global {
+        .van-cell__title {
+          overflow: hidden;
+          white-space: nowrap;
+          text-overflow: ellipsis;
+        }
+
+        .van-cell__right-icon {
+          color: #333;
+          transform: rotate(90deg);
+          margin: 0 0 0 4px;
+        }
+      }
+    }
+  }
+}
+
+.reportList {
+  width: auto;
+  margin: 12px 13px 0;
+  padding: 15px 12px;
+  border-radius: 10px;
+
+  :global {
+    .van-cell__title {
+      font-size: 16px;
+      color: #333333;
+    }
+    .van-cell_label {
+      font-size: 14px;
+      color: #777;
+    }
+  }
+}

+ 22 - 0
src/school/train-report/index.tsx

@@ -0,0 +1,22 @@
+import { Tab, Tabs } from 'vant'
+import { defineComponent } from 'vue'
+import List from './components/list'
+import styles from './index.module.less'
+
+export default defineComponent({
+  name: 'train-report',
+  setup() {
+    return () => (
+      <div class={styles.train}>
+        <Tabs sticky lineWidth={20} lineHeight={4} swipeable animated>
+          <Tab title="周报" name="WEEKLY">
+            <List type="WEEKLY" />
+          </Tab>
+          <Tab title="月报" name="MONTHLY">
+            <List type="MONTHLY" />
+          </Tab>
+        </Tabs>
+      </div>
+    )
+  }
+})

+ 193 - 0
src/school/train-report/modal/index.module.less

@@ -0,0 +1,193 @@
+.trainSection {
+  background: url('../images/week/section-title-bg.png') no-repeat top center;
+  background-size: contain;
+  position: relative;
+  z-index: 1;
+  margin: 0 13px 10px;
+  &.studentSection {
+    background: url('../images/week/section-title-bg1.png') no-repeat top center;
+    background-size: contain;
+  }
+  &.teacherSection {
+    background: url('../images/week/section-title-bg2.png') no-repeat top center;
+    background-size: contain;
+  }
+
+  &.teacherTrainSection {
+    background: url('../images/month/teacher-section-title-bg.png') no-repeat top center;
+    background-size: contain;
+    &.studentSection {
+      background: url('../images/month/teacher-section-title-bg1.png') no-repeat top center;
+      background-size: contain;
+    }
+    &.teacherSection {
+      background: url('../images/month/teacher-section-title-bg2.png') no-repeat top center;
+      background-size: contain;
+    }
+  }
+
+  .trainTitle {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding-top: 4px;
+    height: 36px;
+    .allowLine {
+      width: 13px;
+      height: 13px;
+      margin-right: 6px;
+    }
+    .arrowPoint {
+      height: 5px;
+      margin-right: 15px;
+    }
+    .name {
+      display: flex;
+      align-items: center;
+      padding-left: 12px;
+      font-size: 16px;
+      font-weight: 600;
+      color: #000977;
+      line-height: 22px;
+    }
+  }
+  .countNums {
+    display: flex;
+    align-items: center;
+    margin-right: 20px;
+    font-size: 14px;
+    font-weight: 600;
+    color: #ffffff;
+    line-height: 20px;
+    span {
+      color: #42ffe2;
+      padding: 0 6px;
+    }
+  }
+
+  .trainSectionContent {
+    background: linear-gradient(180deg, #ffffff 0%, #ffffff 16%, rgba(255, 255, 255, 0.6) 100%);
+    box-shadow: 0px -1px 9px 0px rgba(129, 187, 193, 0.49);
+    // border: 1px solid;
+    // border-image: linear-gradient(156deg, rgba(255, 255, 255, 0.11), rgba(96, 155, 198, 0.98)) 1 1;
+    padding: 12px;
+    border-radius: 20px;
+  }
+  .tContent {
+    background: #ffffff;
+    box-shadow: 0px 2px 22px 0px rgba(83, 109, 233, 0.79);
+    border-radius: 10px;
+    padding: 10px 10px 0;
+    display: flex;
+    flex-wrap: wrap;
+
+    .tItem {
+      margin: 0 10px 10px 0;
+      width: 53px;
+      height: 55px;
+      background: linear-gradient(
+        132deg,
+        rgba(199, 239, 243, 0.39) 0%,
+        rgba(229, 206, 251, 0.39) 40%,
+        rgba(147, 194, 254, 0.39) 100%
+      );
+      box-shadow: inset 0px 1px 0px 0px rgba(255, 255, 255, 0.62);
+      border-radius: 4px;
+      display: flex;
+      align-items: center;
+      flex-direction: column;
+      justify-content: center;
+      &:nth-child(5n + 5) {
+        margin-right: 0;
+      }
+      .pople {
+        font-size: 20px;
+        font-family: DINA;
+        font-weight: bold;
+        color: #1c4aff;
+        line-height: 24px;
+        span {
+          font-size: 12px;
+          color: #777777;
+          line-height: 17px;
+        }
+      }
+      .subjectName {
+        font-size: 12px;
+        color: #333333;
+        line-height: 17px;
+      }
+    }
+  }
+
+  .calssEchartTitle {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    width: 100%;
+    padding-bottom: 10px;
+    .unit {
+      font-size: 12px;
+      color: #777777;
+    }
+    .unitType {
+      background: linear-gradient(
+        132deg,
+        rgba(199, 239, 243, 0.25) 0%,
+        rgba(223, 213, 250, 0.25) 32%,
+        rgba(147, 194, 254, 0.25) 100%
+      );
+      box-shadow: inset 0px 1px 0px 0px rgba(255, 255, 255, 0.62);
+      border-radius: 12px;
+      padding: 4px 8px;
+      font-size: 12px;
+      color: #000977;
+    }
+  }
+  .classEcharts {
+    height: 230px;
+    width: 100%;
+  }
+
+  .tProgress {
+    display: block;
+  }
+  .progressItem {
+    padding-bottom: 16px;
+    .className {
+      padding-bottom: 6px;
+      font-size: 14px;
+      font-weight: 600;
+      color: #333333;
+      line-height: 20px;
+      .line {
+        display: inline-block;
+        width: 4px;
+        height: 12px;
+        background: #d1d1d1;
+        border-radius: 3px;
+        margin-right: 6px;
+      }
+    }
+    .classNum {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      font-size: 12px;
+      padding-bottom: 6px;
+      color: #333333;
+      span {
+        font-size: 16px;
+        padding: 0 4px;
+        font-weight: bold;
+        font-family: DINA;
+      }
+      .konowCount {
+        color: #777;
+        span {
+          color: #f44541;
+        }
+      }
+    }
+  }
+}

+ 48 - 0
src/school/train-report/modal/orchestra-num.tsx

@@ -0,0 +1,48 @@
+import { defineComponent } from 'vue'
+import { Image } from 'vant'
+import styles from './index.module.less'
+import arrowLine from '../images/week/icon-arrow-line.png'
+import arrowPoint from '../images/icon-arrow-point.png'
+import teacherArrowLine from '../images/month/teacher-icon-arrow-line.png'
+
+export default defineComponent({
+  name: 'orchestra-num',
+  props: {
+    type: {
+      type: String,
+      default: 'week'
+    }
+  },
+  setup(props) {
+    return () => (
+      <div class={[styles.trainSection, props.type === 'month' ? styles.teacherTrainSection : '']}>
+        <div class={styles.trainTitle}>
+          <div class={styles.name}>
+            <Image
+              src={props.type === 'month' ? teacherArrowLine : arrowLine}
+              class={styles.allowLine}
+            />
+            乐团人数
+          </div>
+          <div class={styles.countNums}>
+            <Image src={arrowPoint} class={styles.arrowPoint} />
+            乐团总人数<span>272</span>人
+          </div>
+        </div>
+
+        <div class={styles.trainSectionContent}>
+          <div class={styles.tContent}>
+            {[1, 2, 3, 4, 5, 6].map((item, index) => (
+              <div class={styles.tItem}>
+                <p class={styles.pople}>
+                  20<span>人</span>
+                </p>
+                <p class={styles.subjectName}>长笛</p>
+              </div>
+            ))}
+          </div>
+        </div>
+      </div>
+    )
+  }
+})

+ 139 - 0
src/school/train-report/modal/student-attendance.tsx

@@ -0,0 +1,139 @@
+import { defineComponent, onMounted } from 'vue'
+import { Image } from 'vant'
+import styles from './index.module.less'
+import arrowLine from '../images/week/icon-arrow-line.png'
+import arrowPoint from '../images/icon-arrow-point.png'
+import teacherArrowLine from '../images/month/teacher-icon-arrow-line.png'
+import * as echarts from 'echarts/core'
+import {
+  TitleComponent,
+  // 组件类型的定义后缀都为 ComponentOption
+  TooltipComponent,
+  GridComponent,
+  // 数据集组件
+  DatasetComponent,
+  // 内置数据转换器组件 (filter, sort)
+  TransformComponent,
+  LegendComponent,
+  ToolboxComponent,
+  DataZoomComponent
+} from 'echarts/components'
+import { BarChart } from 'echarts/charts'
+import { PieChart } from 'echarts/charts'
+import { LabelLayout, UniversalTransition } from 'echarts/features'
+import { CanvasRenderer } from 'echarts/renderers'
+// type EChartsOption = echarts.EChartsOption
+
+// 注册必须的组件
+echarts.use([
+  TitleComponent,
+  TooltipComponent,
+  GridComponent,
+  DatasetComponent,
+  TransformComponent,
+  BarChart,
+  LabelLayout,
+  UniversalTransition,
+  CanvasRenderer,
+  PieChart,
+  ToolboxComponent,
+  LegendComponent,
+  DataZoomComponent
+])
+
+export default defineComponent({
+  name: 'orchestra-num',
+  props: {
+    type: {
+      type: String,
+      default: 'week'
+    }
+  },
+  setup(props) {
+    let myChart: any
+    const handleInit = () => {
+      if (myChart) {
+        myChart.dispose()
+      }
+      const chartDom = document.getElementById('studentEcharts')
+      console.log(chartDom, 'chartDom')
+      myChart = echarts.init(chartDom as HTMLDivElement)
+      const option = {
+        xAxis: {
+          type: 'category',
+          data: ['Mon', 'Tue', 'Wed', '上低音号', 'Fri', 'Sat', 'Sun', 'Fri', 'Sat', 'Sun'],
+          axisLabel: {
+            rotate: 45,
+            fontSize: 10,
+            color: '#333'
+          }
+        },
+        yAxis: {
+          type: 'value'
+        },
+        grid: {
+          left: 0,
+          top: 22,
+          right: 0,
+          bottom: 12,
+          containLabel: true
+        },
+        series: [
+          {
+            type: 'line',
+            showBackground: false,
+            itemStyle: {
+              color: '#FF8057'
+            },
+            label: {
+              show: true,
+              position: 'top',
+              fontSize: 10,
+              color: '#FF8057'
+            },
+            data: [120, 200, 150, 80, 70, 110, 130, 70, 110, 130]
+          }
+        ]
+      }
+
+      option && myChart.setOption(option)
+    }
+
+    onMounted(() => {
+      handleInit()
+    })
+
+    return () => (
+      <div
+        class={[
+          styles.trainSection,
+          props.type === 'month' ? styles.teacherTrainSection : '',
+          styles.studentSection
+        ]}
+      >
+        <div class={styles.trainTitle}>
+          <div class={styles.name}>
+            <Image
+              src={props.type === 'month' ? teacherArrowLine : arrowLine}
+              class={styles.allowLine}
+            />
+            本{props.type === 'month' ? '月' : '周'}学生出勤
+          </div>
+          <div class={styles.countNums}>
+            <Image src={arrowPoint} class={styles.arrowPoint} />
+            总出勤率<span>59</span>%
+          </div>
+        </div>
+
+        <div class={styles.trainSectionContent}>
+          <div class={styles.tContent}>
+            <div class={styles.calssEchartTitle}>
+              <span class={styles.unit}>单位:%</span>
+            </div>
+            <div id="studentEcharts" class={styles.classEcharts}></div>
+          </div>
+        </div>
+      </div>
+    )
+  }
+})

+ 150 - 0
src/school/train-report/modal/teacher-attendance.tsx

@@ -0,0 +1,150 @@
+import { defineComponent, onMounted } from 'vue'
+import { Image } from 'vant'
+import styles from './index.module.less'
+import arrowLine from '../images/week/icon-arrow-line.png'
+import arrowPoint from '../images/icon-arrow-point.png'
+import teacherArrowLine from '../images/month/teacher-icon-arrow-line.png'
+import * as echarts from 'echarts/core'
+import {
+  TitleComponent,
+  // 组件类型的定义后缀都为 ComponentOption
+  TitleComponentOption,
+  TooltipComponent,
+  TooltipComponentOption,
+  GridComponent,
+  GridComponentOption,
+  // 数据集组件
+  DatasetComponent,
+  DatasetComponentOption,
+  // 内置数据转换器组件 (filter, sort)
+  TransformComponent,
+  LegendComponent,
+  ToolboxComponent,
+  DataZoomComponent
+} from 'echarts/components'
+import {
+  BarChart,
+  // 系列类型的定义后缀都为 SeriesOption
+  BarSeriesOption,
+  LineChart,
+  LineSeriesOption
+} from 'echarts/charts'
+import { PieChart } from 'echarts/charts'
+import { LabelLayout, UniversalTransition } from 'echarts/features'
+import { CanvasRenderer } from 'echarts/renderers'
+// type EChartsOption = echarts.EChartsOption
+
+// 注册必须的组件
+echarts.use([
+  TitleComponent,
+  TooltipComponent,
+  GridComponent,
+  DatasetComponent,
+  TransformComponent,
+  BarChart,
+  LabelLayout,
+  UniversalTransition,
+  CanvasRenderer,
+  PieChart,
+  ToolboxComponent,
+  LegendComponent,
+  DataZoomComponent,
+  LineChart
+])
+
+export default defineComponent({
+  name: 'orchestra-num',
+  props: {
+    type: {
+      type: String,
+      default: 'week'
+    }
+  },
+  setup(props) {
+    let myChart: any
+    const handleInit = () => {
+      if (myChart) {
+        myChart.dispose()
+      }
+      const chartDom = document.getElementById('teacherEcharts')
+      console.log(chartDom, 'chartDom')
+      myChart = echarts.init(chartDom as HTMLDivElement)
+      const option = {
+        xAxis: {
+          type: 'category',
+          data: ['Mon', 'Tue', 'Wed', '上低音号', 'Fri', 'Sat', 'Sun', 'Fri', 'Sat', 'Sun'],
+          axisLabel: {
+            rotate: 45,
+            fontSize: 10,
+            color: '#333'
+          }
+        },
+        yAxis: {
+          type: 'value'
+        },
+        grid: {
+          left: 0,
+          top: 22,
+          right: 0,
+          bottom: 12,
+          containLabel: true
+        },
+        series: [
+          {
+            type: 'line',
+            showBackground: false,
+            itemStyle: {
+              color: '#FF8057'
+            },
+            label: {
+              show: true,
+              position: 'top',
+              fontSize: 10,
+              color: '#FF8057'
+            },
+            data: [120, 200, 150, 80, 70, 110, 130, 70, 110, 130]
+          }
+        ]
+      }
+
+      option && myChart.setOption(option)
+    }
+
+    onMounted(() => {
+      handleInit()
+    })
+
+    return () => (
+      <div
+        class={[
+          styles.trainSection,
+          props.type === 'month' ? styles.teacherTrainSection : '',
+          styles.teacherSection
+        ]}
+      >
+        <div class={styles.trainTitle}>
+          <div class={styles.name}>
+            <Image
+              src={props.type === 'month' ? teacherArrowLine : arrowLine}
+              class={styles.allowLine}
+            />
+            本{props.type === 'month' ? '月' : '周'}伴学指导出勤
+          </div>
+          <div class={styles.countNums}>
+            <Image src={arrowPoint} class={styles.arrowPoint} />
+            总出勤率<span>59</span>%
+          </div>
+        </div>
+
+        <div class={styles.trainSectionContent}>
+          <div class={styles.tContent}>
+            <div class={styles.calssEchartTitle}>
+              <span class={styles.unit}>单位:%</span>
+            </div>
+            <div id="teacherEcharts" class={styles.classEcharts}></div>
+          </div>
+        </div>
+      </div>
+    )
+  }
+})

+ 147 - 0
src/school/train-report/modal/train-class.tsx

@@ -0,0 +1,147 @@
+import { defineComponent, onMounted } from 'vue'
+import { Image } from 'vant'
+import styles from './index.module.less'
+import arrowLine from '../images/week/icon-arrow-line.png'
+import arrowPoint from '../images/icon-arrow-point.png'
+import teacherArrowLine from '../images/month/teacher-icon-arrow-line.png'
+import * as echarts from 'echarts/core'
+import {
+  TitleComponent,
+  // 组件类型的定义后缀都为 ComponentOption
+  TooltipComponent,
+  GridComponent,
+  // 数据集组件
+  DatasetComponent,
+  // 内置数据转换器组件 (filter, sort)
+  TransformComponent,
+  LegendComponent,
+  ToolboxComponent,
+  DataZoomComponent
+} from 'echarts/components'
+import { BarChart } from 'echarts/charts'
+import { PieChart } from 'echarts/charts'
+import { LabelLayout, UniversalTransition } from 'echarts/features'
+import { CanvasRenderer } from 'echarts/renderers'
+// type EChartsOption = echarts.EChartsOption
+
+// 注册必须的组件
+echarts.use([
+  TitleComponent,
+  TooltipComponent,
+  GridComponent,
+  DatasetComponent,
+  TransformComponent,
+  BarChart,
+  LabelLayout,
+  UniversalTransition,
+  CanvasRenderer,
+  PieChart,
+  ToolboxComponent,
+  LegendComponent,
+  DataZoomComponent
+])
+
+export default defineComponent({
+  name: 'orchestra-num',
+  props: {
+    type: {
+      type: String,
+      default: 'week'
+    }
+  },
+  setup(props) {
+    let myChart: any
+    const handleInit = () => {
+      if (myChart) {
+        myChart.dispose()
+      }
+      const chartDom = document.getElementById('classEcharts')
+      console.log(chartDom, 'chartDom')
+      myChart = echarts.init(chartDom as HTMLDivElement)
+      const option = {
+        xAxis: {
+          type: 'category',
+          data: ['Mon', 'Tue', 'Wed', '上低音号', 'Fri', 'Sat', 'Sun', 'Fri', 'Sat', 'Sun'],
+          axisLabel: {
+            rotate: 45,
+            fontSize: 10,
+            color: '#333'
+          }
+        },
+        yAxis: {
+          type: 'value'
+        },
+        grid: {
+          left: 0,
+          top: 22,
+          right: 0,
+          bottom: 12,
+          containLabel: true
+        },
+        series: [
+          {
+            type: 'bar',
+            showBackground: false,
+            itemStyle: {
+              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                { offset: 0, color: '#69DCE8' },
+                { offset: 0.5, color: '#E5CEFB' },
+                { offset: 1, color: '#58A2FF' }
+              ])
+            },
+            emphasis: {
+              itemStyle: {
+                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+                  { offset: 0, color: '#69DCE8' },
+                  { offset: 0.5, color: '#E5CEFB' },
+                  { offset: 1, color: '#58A2FF' }
+                ])
+              }
+            },
+            label: {
+              show: true,
+              position: 'top',
+              fontSize: 10,
+              color: '#777'
+            },
+            data: [120, 200, 150, 80, 70, 110, 130, 70, 110, 130]
+          }
+        ]
+      }
+
+      option && myChart.setOption(option)
+    }
+
+    onMounted(() => {
+      handleInit()
+    })
+
+    return () => (
+      <div class={[styles.trainSection, props.type === 'month' ? styles.teacherTrainSection : '']}>
+        <div class={styles.trainTitle}>
+          <div class={styles.name}>
+            <Image
+              src={props.type === 'month' ? teacherArrowLine : arrowLine}
+              class={styles.allowLine}
+            />
+            训练课程
+          </div>
+          <div class={styles.countNums}>
+            <Image src={arrowPoint} class={styles.arrowPoint} />
+            乐团累计总课时<span>272</span>课时
+          </div>
+        </div>
+
+        <div class={styles.trainSectionContent}>
+          <div class={styles.tContent}>
+            <div class={styles.calssEchartTitle}>
+              <span class={styles.unit}>单位:课时</span>
+              <span class={styles.unitType}>本{props.type === 'month' ? '月' : '周'}训练</span>
+            </div>
+            <div id="classEcharts" class={styles.classEcharts}></div>
+          </div>
+        </div>
+      </div>
+    )
+  }
+})

+ 65 - 0
src/school/train-report/modal/train-progress.tsx

@@ -0,0 +1,65 @@
+import { defineComponent } from 'vue'
+import { Image, Progress } from 'vant'
+import styles from './index.module.less'
+import arrowLine from '../images/week/icon-arrow-line.png'
+import arrowPoint from '../images/icon-arrow-point.png'
+import teacherArrowLine from '../images/month/teacher-icon-arrow-line.png'
+export default defineComponent({
+  name: 'orchestra-num',
+  props: {
+    type: {
+      type: String,
+      default: 'week'
+    }
+  },
+  setup(props) {
+    return () => (
+      <div class={[styles.trainSection, props.type === 'month' ? styles.teacherTrainSection : '']}>
+        <div class={styles.trainTitle}>
+          <div class={styles.name}>
+            <Image
+              src={props.type === 'month' ? teacherArrowLine : arrowLine}
+              class={styles.allowLine}
+            />
+            训练进度
+          </div>
+          <div class={styles.countNums}>
+            <Image src={arrowPoint} class={styles.arrowPoint} />
+          </div>
+        </div>
+
+        <div class={styles.trainSectionContent}>
+          <div class={[styles.tContent, styles.tProgress]}>
+            {[1, 2, 3, 4, 5, 6].map((item, index) => (
+              <div class={styles.progressItem}>
+                <div class={styles.className}>
+                  <i class={styles.line}></i>
+                  长笛班
+                </div>
+                <div class={styles.classNum}>
+                  <div class={styles.konowCount}>
+                    已学习知识点<span>33</span>个
+                  </div>
+                  <div class={styles.allCount}>
+                    共<span>33</span>个
+                  </div>
+                </div>
+
+                <Progress
+                  color={'linear-gradient(90deg, #FFC3A1 0%, #FF9895 100%);'}
+                  trackColor="#ECECEC"
+                  showPivot={false}
+                  style={{
+                    borderRadius: '10px'
+                  }}
+                  percentage={10}
+                  strokeWidth={8}
+                />
+              </div>
+            ))}
+          </div>
+        </div>
+      </div>
+    )
+  }
+})

+ 129 - 0
src/school/train-report/month-report.tsx

@@ -0,0 +1,129 @@
+import OHeader from '@/components/o-header'
+import { defineComponent, reactive } from 'vue'
+import styles from './report.module.less'
+import iconOrchestra from '@/views/mine-orchestra/images/icon-or.png'
+import { Grid, GridItem, Icon, Image, Popup } from 'vant'
+import trainWeek from './images/month/icon-train-month.png'
+import OrchestraNum from './modal/orchestra-num'
+import TrainClass from './modal/train-class'
+import StudentAttendance from './modal/student-attendance'
+import TeacherAttendance from './modal/teacher-attendance'
+import TrainProgress from './modal/train-progress'
+import iconPhoto from './images/icon-photo.png'
+import iconClass from './images/icon-class.png'
+import iconSaveImage from '@/school/orchestra/images/icon-save-image.png'
+import iconWechat from '@/school/orchestra/images/icon-wechat.png'
+import OQrcode from '@/components/o-qrcode'
+
+export default defineComponent({
+  name: 'train-report',
+  setup() {
+    const forms = reactive({
+      showQrcode: false,
+      url: 'http://'
+    })
+    return () => (
+      <div class={[styles.trainWeek, styles.trainMonth]}>
+        <div class={styles.trainContainer}></div>
+        <OHeader background="transparent" border={false} title=" ">
+          {{
+            right: () => <i class={styles.iconShare} onClick={() => (forms.showQrcode = true)}></i>
+          }}
+        </OHeader>
+        <div class={[styles.headerContant, styles.teacherHeaderContant]}>
+          <div class={styles.orchestra}>
+            <Image src={iconOrchestra} class={styles.iconOrchestra} />
+            <span>武汉市洪山区实验小学第一届乐团</span>
+          </div>
+          <Image src={trainWeek} class={styles.iconTrainWeek} />
+          <div class={styles.trainTimer}>2023/1/16-2023/1/22</div>
+        </div>
+
+        <OrchestraNum type="month" />
+        <TrainClass type="month" />
+
+        <div class={[styles.trainPhoto, styles.teacherTrainPhoto]}>
+          <Image src={iconPhoto} class={styles.iconPhoto} />
+          <p>
+            本月上传<span>17</span>张训练照片
+          </p>
+        </div>
+
+        <StudentAttendance type="month" />
+        <TeacherAttendance type="month" />
+
+        <div class={[styles.trainPhoto, styles.teacherTrainClass, styles.trainClass]}>
+          <Image src={iconClass} class={styles.iconPhoto} />
+          <div>
+            <p>课件使用未达标班级</p>
+            <p class={styles.subjectNames}>长笛班 单簧管班 萨克斯班 小号班 大号</p>
+          </div>
+        </div>
+        <TrainProgress type="month" />
+
+        <Popup
+          v-model:show={forms.showQrcode}
+          position="bottom"
+          style={{ background: 'transparent' }}
+        >
+          <div class={styles.codeContainer}>
+            <div class={[styles.codeImg, styles.teacherCodeImg]} id="preview-container">
+              <div class={styles.codeContent}>
+                <div
+                  class={[
+                    styles.headerContant,
+                    styles.teacherHeaderContant,
+                    styles.headerContantPopup
+                  ]}
+                >
+                  <div class={styles.orchestra}>
+                    <Image src={iconOrchestra} class={styles.iconOrchestra} />
+                    <span>武汉市洪山区实验小学第一届乐团</span>
+                  </div>
+                  <Image src={trainWeek} class={styles.iconTrainWeek} />
+                  <div class={styles.trainTimer}>2023/1/16-2023/1/22</div>
+                </div>
+
+                <div class={styles.codeQr}>
+                  <OQrcode text={forms.url} size={'100%'} logoSize="small" />
+                </div>
+                <div style={{ textAlign: 'center' }}>
+                  <span class={styles.codeBtnText}>
+                    扫描上方二维码<span>查看训练月报</span>
+                  </span>
+                </div>
+              </div>
+            </div>
+            <div class={styles.codeBottom}>
+              <Icon
+                name="cross"
+                size={22}
+                class={styles.close}
+                color="#666"
+                onClick={() => (forms.showQrcode = false)}
+              />
+
+              <h3 class={styles.title}>
+                <i></i>分享方式
+              </h3>
+              <Grid columnNum={2} border={false}>
+                <GridItem>
+                  {{
+                    icon: () => <Image class={styles.shareImg} src={iconSaveImage} />,
+                    text: () => <div class={styles.shareText}>保存图片</div>
+                  }}
+                </GridItem>
+                <GridItem>
+                  {{
+                    icon: () => <Image class={styles.shareImg} src={iconWechat} />,
+                    text: () => <div class={styles.shareText}>微信</div>
+                  }}
+                </GridItem>
+              </Grid>
+            </div>
+          </div>
+        </Popup>
+      </div>
+    )
+  }
+})

+ 259 - 0
src/school/train-report/report.module.less

@@ -0,0 +1,259 @@
+.trainWeek {
+  position: relative;
+  min-height: 100vh;
+  background: linear-gradient(180deg, #225fff 0%, #0e2cdf 94%, #0d29dc 100%);
+  overflow: hidden;
+
+  .trainContainer {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    background: url('./images/week/banner-week.png') no-repeat top center;
+    background-size: contain;
+    height: 342px;
+  }
+
+  .iconShare {
+    width: 20px;
+    height: 20px;
+    display: inline-block;
+    background: url('./images/icon-share.png') no-repeat center;
+    background-size: contain;
+  }
+
+  &.trainWeek {
+    background: linear-gradient(180deg, #c7c7ff 0%, #9c9bff 100%);
+
+    .trainContainer {
+      background: url('./images/month/banner-month.png') no-repeat top center;
+      background-size: contain;
+      height: 342px;
+    }
+  }
+}
+
+.headerContant {
+  padding-top: 16px;
+  padding-left: 17px;
+  margin-bottom: 50px;
+  &.teacherHeaderContant {
+    .orchestra {
+      color: #3e0ed7;
+    }
+    .trainTimer {
+      color: #3a17fd;
+      &::before,
+      &::after {
+        background: url('./images/month/teacher-icon-point.png') no-repeat center;
+        background-size: contain;
+      }
+    }
+  }
+  .orchestra {
+    padding: 3px 7px;
+    display: inline-flex;
+    background: rgba(255, 255, 255, 0.32);
+    border-radius: 12px;
+    font-size: 12px;
+    color: #ffffff;
+    span {
+      max-width: 200px;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+  }
+  .iconOrchestra {
+    width: 14px;
+    height: 14px;
+    margin-right: 4px;
+  }
+  .iconTrainWeek {
+    height: 38px;
+    padding: 18px 0 8px;
+  }
+  .trainTimer {
+    display: flex;
+    align-items: center;
+    font-size: 13px;
+    color: #ffffff;
+    line-height: 18px;
+
+    &::before,
+    &::after {
+      display: inline-block;
+      margin-left: 4px;
+      margin-right: 4px;
+      content: ' ';
+      width: 6px;
+      height: 6px;
+      background: url('./images/week/icon-point.png') no-repeat center;
+      background-size: contain;
+    }
+  }
+}
+
+.trainPhoto {
+  height: 58px;
+  font-size: 14px;
+  font-weight: 600;
+  color: #ffffff;
+  background: url('./images/week/train-bg.png') no-repeat center;
+  background-size: contain;
+  padding: 0 15px;
+  margin: 0 13px 10px;
+  display: flex;
+  align-items: center;
+
+  &.teacherTrainPhoto {
+    background: url('./images/month/teacher-train-bg.png') no-repeat center;
+    background-size: contain;
+  }
+
+  &.teacherTrainClass {
+    background: url('./images/month/teacher-train-bg1.png') no-repeat center;
+    background-size: contain;
+    height: 76px;
+  }
+
+  .iconPhoto {
+    width: 38px;
+    height: 42px;
+    margin-right: 10px;
+  }
+  span {
+    padding: 0 4px;
+    color: #41ffe2;
+    font-family: DINA;
+  }
+}
+
+.trainClass {
+  .subjectNames {
+    padding-top: 2px;
+    font-weight: 600;
+    color: #ff7c88;
+    line-height: 20px;
+    font-size: 14px;
+  }
+}
+
+.codeContainer {
+  .codeImg {
+    width: 315px;
+    height: 440px;
+    // padding-left: 8px;
+    background: url('./images/week/popup-week-banner.png') no-repeat top center;
+    background-size: contain;
+    margin: 0 auto;
+    background-color: #ffffff;
+    border-radius: 8px;
+
+    &.teacherCodeImg {
+      background: url('./images/month/popup-week-banner.png') no-repeat top center;
+      background-size: contain;
+      background-color: #ffffff;
+    }
+
+    .headerContantPopup {
+      padding-top: 23px;
+      padding-left: 18px;
+    }
+
+    .codeTitle {
+      text-align: center;
+      padding-top: 13px;
+      font-size: 24px;
+      font-weight: bold;
+      color: #ffffff;
+      text-shadow: 1px 1px 7px #f4672a;
+      max-width: 90%;
+      padding-left: 5%;
+    }
+
+    .codeName {
+      padding: 36px 8px 0;
+      font-size: 18px;
+      font-weight: 600;
+      color: #ffffff;
+    }
+    .codeQr {
+      margin: 108px auto 0;
+      width: 126px;
+      height: 126px;
+      padding: 12px;
+      background: url('./images/popup-qrcode-bg.png') no-repeat center;
+      background-size: contain;
+      border-radius: 11px;
+      overflow: hidden;
+      box-sizing: border-box;
+      img {
+        width: 100%;
+        height: 100%;
+      }
+    }
+
+    .codeBtnText {
+      margin: 20px auto 0;
+      display: inline-block;
+      background: linear-gradient(
+        132deg,
+        rgba(199, 239, 243, 0.25) 0%,
+        rgba(229, 206, 251, 0.25) 40%,
+        rgba(147, 194, 254, 0.25) 100%
+      );
+      box-shadow: inset 0px 1px 0px 0px rgba(255, 255, 255, 0.62);
+      border-radius: 18px;
+      padding: 6px 16px;
+      font-size: 14px;
+      color: #000977;
+    }
+
+    .codeTips {
+      padding-top: 10px;
+      font-size: 13px;
+      font-weight: 600;
+      color: #f16437;
+      line-height: 18px;
+      text-align: center;
+    }
+  }
+  .close {
+    position: absolute;
+    top: 12px;
+    right: 15px;
+  }
+  .codeBottom {
+    position: relative;
+    margin-top: 32px;
+    background: #ffffff;
+    border-radius: 20px 20px 0px 0px;
+    padding-bottom: 10px;
+  }
+  .title {
+    font-size: 16px;
+    font-weight: 600;
+    color: #333333;
+    line-height: 22px;
+    padding: 15px 15px 0;
+    i {
+      display: inline-block;
+      margin-right: 6px;
+      width: 4px;
+      height: 12px;
+      background: #ff8057;
+      border-radius: 2px;
+    }
+  }
+  .shareImg {
+    width: 47px;
+    height: 47px;
+  }
+  .shareText {
+    padding-top: 6px;
+    font-size: 14px;
+    color: #333333;
+    line-height: 20px;
+  }
+}

+ 123 - 0
src/school/train-report/week-report.tsx

@@ -0,0 +1,123 @@
+import OHeader from '@/components/o-header'
+import { defineComponent, reactive } from 'vue'
+import styles from './report.module.less'
+import iconOrchestra from '@/views/mine-orchestra/images/icon-or.png'
+import { Grid, GridItem, Icon, Image, Popup } from 'vant'
+import trainWeek from './images/week/icon-train-week.png'
+import OrchestraNum from './modal/orchestra-num'
+import TrainClass from './modal/train-class'
+import StudentAttendance from './modal/student-attendance'
+import TeacherAttendance from './modal/teacher-attendance'
+import TrainProgress from './modal/train-progress'
+import iconPhoto from './images/icon-photo.png'
+import iconClass from './images/icon-class.png'
+import iconSaveImage from '@/school/orchestra/images/icon-save-image.png'
+import iconWechat from '@/school/orchestra/images/icon-wechat.png'
+import OQrcode from '@/components/o-qrcode'
+
+export default defineComponent({
+  name: 'train-report',
+  setup() {
+    const forms = reactive({
+      showQrcode: false,
+      url: 'http://'
+    })
+    return () => (
+      <div class={styles.trainWeek}>
+        <div class={styles.trainContainer}></div>
+        <OHeader background="transparent" border={false} title=" ">
+          {{
+            right: () => <i class={styles.iconShare} onClick={() => (forms.showQrcode = true)}></i>
+          }}
+        </OHeader>
+        <div class={styles.headerContant}>
+          <div class={styles.orchestra}>
+            <Image src={iconOrchestra} class={styles.iconOrchestra} />
+            <span>武汉市洪山区实验小学第一届乐团</span>
+          </div>
+          <Image src={trainWeek} class={styles.iconTrainWeek} />
+          <div class={styles.trainTimer}>2023/1/16-2023/1/22</div>
+        </div>
+
+        <OrchestraNum />
+        <TrainClass />
+
+        <div class={styles.trainPhoto}>
+          <Image src={iconPhoto} class={styles.iconPhoto} />
+          <p>
+            本周上传<span>17</span>张训练照片
+          </p>
+        </div>
+
+        <StudentAttendance />
+        <TeacherAttendance />
+
+        <div class={[styles.trainPhoto, styles.trainClass]}>
+          <Image src={iconClass} class={styles.iconPhoto} />
+          <div>
+            <p>课件使用未达标班级</p>
+            <p class={styles.subjectNames}>长笛班 单簧管班 萨克斯班 小号班 大号</p>
+          </div>
+        </div>
+        <TrainProgress />
+
+        <Popup
+          v-model:show={forms.showQrcode}
+          position="bottom"
+          style={{ background: 'transparent' }}
+        >
+          <div class={styles.codeContainer}>
+            <div class={styles.codeImg} id="preview-container">
+              <div class={styles.codeContent}>
+                <div class={[styles.headerContant, styles.headerContantPopup]}>
+                  <div class={styles.orchestra}>
+                    <Image src={iconOrchestra} class={styles.iconOrchestra} />
+                    <span>武汉市洪山区实验小学第一届乐团</span>
+                  </div>
+                  <Image src={trainWeek} class={styles.iconTrainWeek} />
+                  <div class={styles.trainTimer}>2023/1/16-2023/1/22</div>
+                </div>
+
+                <div class={styles.codeQr}>
+                  <OQrcode text={forms.url} size={'100%'} logoSize="small" />
+                </div>
+                <div style={{ textAlign: 'center' }}>
+                  <span class={styles.codeBtnText}>
+                    扫描上方二维码<span>查看训练周报</span>
+                  </span>
+                </div>
+              </div>
+            </div>
+            <div class={styles.codeBottom}>
+              <Icon
+                name="cross"
+                size={22}
+                class={styles.close}
+                color="#666"
+                onClick={() => (forms.showQrcode = false)}
+              />
+
+              <h3 class={styles.title}>
+                <i></i>分享方式
+              </h3>
+              <Grid columnNum={2} border={false}>
+                <GridItem>
+                  {{
+                    icon: () => <Image class={styles.shareImg} src={iconSaveImage} />,
+                    text: () => <div class={styles.shareText}>保存图片</div>
+                  }}
+                </GridItem>
+                <GridItem>
+                  {{
+                    icon: () => <Image class={styles.shareImg} src={iconWechat} />,
+                    text: () => <div class={styles.shareText}>微信</div>
+                  }}
+                </GridItem>
+              </Grid>
+            </div>
+          </div>
+        </Popup>
+      </div>
+    )
+  }
+})

+ 12 - 14
src/views/subject-echarts/index.tsx

@@ -96,8 +96,8 @@ export default defineComponent({
             lineStyle: {
               width: 30,
               type: 'solid',
-              opacity: 0.2,
-            },
+              opacity: 0.2
+            }
           }
         },
         grid: {
@@ -236,15 +236,15 @@ export default defineComponent({
         practiceThisWeeks: new Array(Math.ceil(Math.random() * 9)).fill(1).map((n, i) => {
           return {
             /** 声部名称 */
-          subjectName: '声部' + (i + 1),
-          /**达标率 */
-          practiceRate: Math.ceil(Math.random() * 100),
-          /** 达标人数 */
-          passNum: Math.floor(Math.random() * 1000),
-          /** 未达标人数 */
-          noPassNum: Math.floor(Math.random() * 1000),
-          /** 非会员 */
-          noMemberNum: Math.floor(Math.random() * 1000)
+            subjectName: '声部' + (i + 1),
+            /**达标率 */
+            practiceRate: Math.ceil(Math.random() * 100),
+            /** 达标人数 */
+            passNum: Math.floor(Math.random() * 1000),
+            /** 未达标人数 */
+            noPassNum: Math.floor(Math.random() * 1000),
+            /** 非会员 */
+            noMemberNum: Math.floor(Math.random() * 1000)
           }
         })
       }
@@ -276,9 +276,7 @@ export default defineComponent({
       <div class={styles.subjectEcharts}>
         <div class={[styles.container, styles.ensemble]}>
           <div class={styles.head}>
-            <div
-              class={styles.headLeft}
-            >
+            <div class={styles.headLeft}>
               <img class={styles.icon} src={iconEnsemble} />
               <div>总体情况</div>
             </div>