瀏覽代碼

Merge branch 'master' of http://git.dayaedu.com/lex/orchestra-app

mo 2 年之前
父節點
當前提交
df4f9b8368

+ 2 - 1
src/components/o-sticky/index.tsx

@@ -24,7 +24,8 @@ export default defineComponent({
       divStyle: {} as any,
       sectionStyle: {
         width: '100%',
-        height: 'auto'
+        height: 'auto',
+        left: '0'
       }
     }
   },

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

@@ -335,14 +335,6 @@ export default [
         }
       },
       {
-        path: '/subsidy-details',
-        name: 'subsidy-details',
-        component: () => import('@/school/approval-manage/subsidy/details'),
-        meta: {
-          title: '补助明细'
-        }
-      },
-      {
         path: '/unitDetail',
         name: 'unitDetail',
         component: () => import('@/views/unit-test/unit-list/unitDetail'),

+ 144 - 82
src/school/approval-manage/agency/index.tsx

@@ -1,106 +1,168 @@
 import { Cell, Grid, GridItem } from 'vant'
-import { defineComponent, onMounted, reactive } from 'vue'
+import { defineComponent, onMounted, reactive, ref } from 'vue'
 import styles from '../index.module.less'
 import iconSubsidy from '../images/icon-subsidy.png'
 import iconNews from '../images/icon-news.png'
 import iconPhoto from '../images/icon-photo.png'
 import request from '@/helpers/request'
 import { state } from '@/state'
+import OFullRefresh from '@/components/o-full-refresh'
+
+interface ISalaryRecord {
+  /**学校补助确认记录ID */
+  id: string
+  /**练习补助 */
+  trainingSalary: number | string
+  /**课程训练补助 */
+  courseSalary: number | string
+  /**一周开始日期 */
+  startDate: string
+  /**一周结束日期 */
+  endDate: string
+  /**已发练习补助 */
+  issueTrainingSalary: number | string
+  /**结算状态 */
+  withdrawalStatus: 'WAIT' | 'SETTLED' | 'PART_SETTLED' | 'SETTLE_FAIL'
+  /**管理补助 */
+  manageSalary: number | string
+  /**已发课程训练补助 */
+  issueCourseSalary: number | string
+  /**已发管理补助 */
+  issueManageSalary: number | string
+}
 
 export default defineComponent({
   name: 'approval-manage-agency',
   setup() {
     const data = reactive({
-
+      salaryRecordList: [{}] as ISalaryRecord[],
+      /**训练照片 */
+      schoolWeekPhoto: {
+        /**预计的训练照片数 */
+        expectPhotoNum: 0,
+        /**结束日期 */
+        endDate: '',
+        /**开始日期 */
+        startDate: '',
+        /**训练照片数 */
+        photoNum: 0
+      },
+      /**乐团资讯 */
+      schoolWeekNews: {
+        //
+        /**乐团资讯数 */
+        newsNum: 0,
+        /**结束日期 */
+        endDate: '',
+        /**开始日期 */
+        startDate: '',
+        /**预计的乐团资讯数 */
+        expectNewsNum: 0
+      }
     })
+    const refreshing = ref(false)
     const getData = async () => {
-        try {
-            const res: any = await request.post(`${state.platformApi}/schoolWeekSalaryRecord/manage`)
-        } catch (error) {
-            
-        }
+      try {
+        const res: any = await request.post(`${state.platformApi}/schoolWeekSalaryRecord/manage`)
+      } catch (error) {}
+      refreshing.value = false
     }
     onMounted(() => {
-        getData()
+      getData()
     })
     return () => (
-      <div>
-        <div class={styles.item}>
-          <Cell center label="2023-1-16 至 2023-1-2" isLink to={'/approval-manage-subsidy'}>
-            {{
-              title: () => (
-                <div class={styles.itemTitle}>
-                  <img class={styles.titleIcon} src={iconSubsidy} />
-                  <span>补助确认</span>
-                </div>
-              )
-            }}
-          </Cell>
-          <Grid class={styles.grid} columnNum={3} border={false}>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元
-                </div>
-                <div>管理补助</div>
-              </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元
-                </div>
-                <div>管理补助</div>
+      <OFullRefresh
+        v-model:modelValue={refreshing.value}
+        onRefresh={getData}
+        style="min-height: calc(100vh - var(--van-nav-bar-height) - var(--header-height))"
+      >
+        <div class={styles.wrap}>
+          {data.salaryRecordList.map((item: ISalaryRecord) => {
+            return (
+              <div class={styles.item} style={{ marginTop: 0 }}>
+                <Cell
+                  center
+                  label={`${item.startDate} 至 ${item.endDate}`}
+                  isLink
+                  to={'/approval-manage-subsidy?salaryId=' + (item.id || '')}
+                >
+                  {{
+                    title: () => (
+                      <div class={styles.itemTitle}>
+                        <img class={styles.titleIcon} src={iconSubsidy} />
+                        <span>补助确认</span>
+                      </div>
+                    )
+                  }}
+                </Cell>
+                <Grid class={styles.grid} columnNum={3} border={false}>
+                  <GridItem>
+                    <div class={styles.gridItem}>
+                      <div class={styles.gridItemTop}>
+                        <span class={styles.topNum}>{item.manageSalary}</span>元
+                      </div>
+                      <div>管理补助</div>
+                    </div>
+                  </GridItem>
+                  <GridItem>
+                    <div class={styles.gridItem}>
+                      <div class={styles.gridItemTop}>
+                        <span class={styles.topNum}>{item.courseSalary}</span>元
+                      </div>
+                      <div>训练补助</div>
+                    </div>
+                  </GridItem>
+                  <GridItem>
+                    <div class={styles.gridItem}>
+                      <div class={styles.gridItemTop}>
+                        <span class={styles.topNum}>{item.trainingSalary}</span>元
+                      </div>
+                      <div>练习奖励</div>
+                    </div>
+                  </GridItem>
+                </Grid>
               </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元
-                </div>
-                <div>管理补助</div>
-              </div>
-            </GridItem>
-          </Grid>
-        </div>
+            )
+          })}
 
-        <div class={styles.item}>
-          <Cell
-            style={{ '--van-cell-value-color': '#333' }}
-            center
-            label="2023-1-16 至 2023-1-2"
-            value="1/6"
-            isLink
-          >
-            {{
-              title: () => (
-                <div class={styles.itemTitle}>
-                  <img class={styles.titleIcon} src={iconNews} />
-                  <span>训练照片</span>
-                </div>
-              )
-            }}
-          </Cell>
-        </div>
-        <div class={styles.item}>
-          <Cell
-            style={{ '--van-cell-value-color': '#333' }}
-            center
-            label="2023-1-16 至 2023-1-2"
-            value="1/6"
-            isLink
-          >
-            {{
-              title: () => (
-                <div class={styles.itemTitle}>
-                  <img class={styles.titleIcon} src={iconPhoto} />
-                  <span>乐团资讯</span>
-                </div>
-              )
-            }}
-          </Cell>
+          <div class={styles.item}>
+            <Cell
+              style={{ '--van-cell-value-color': '#333' }}
+              center
+              label={`${data.schoolWeekPhoto.startDate} 至 ${data.schoolWeekPhoto.endDate}`}
+              value={data.schoolWeekPhoto.photoNum + '/' + data.schoolWeekPhoto.expectPhotoNum}
+              isLink
+            >
+              {{
+                title: () => (
+                  <div class={styles.itemTitle}>
+                    <img class={styles.titleIcon} src={iconNews} />
+                    <span>训练照片</span>
+                  </div>
+                )
+              }}
+            </Cell>
+          </div>
+          <div class={styles.item}>
+            <Cell
+              style={{ '--van-cell-value-color': '#333' }}
+              center
+              label={`${data.schoolWeekNews.startDate} 至 ${data.schoolWeekNews.endDate}`}
+              value={data.schoolWeekNews.newsNum + '/' + data.schoolWeekNews.expectNewsNum}
+              isLink
+            >
+              {{
+                title: () => (
+                  <div class={styles.itemTitle}>
+                    <img class={styles.titleIcon} src={iconPhoto} />
+                    <span>乐团资讯</span>
+                  </div>
+                )
+              }}
+            </Cell>
+          </div>
         </div>
-      </div>
+      </OFullRefresh>
     )
   }
 })

+ 1 - 1
src/school/approval-manage/components/end-approval.tsx

@@ -74,7 +74,7 @@ export default defineComponent({
             <OFullRefresh
               v-model:modelValue={refreshing.value}
               onRefresh={onRefresh}
-              style="min-height: calc(100vh - 2.50666rem);"
+              style="min-height: calc(100vh - var(--van-tabs-line-height) - var(--header-height) - 1.33333rem);"
             >
               <List
                 loading-text=" "

+ 1 - 1
src/school/approval-manage/components/wait-approval.tsx

@@ -74,7 +74,7 @@ export default defineComponent({
           <OFullRefresh
             v-model:modelValue={refreshing.value}
             onRefresh={onRefresh}
-            style="min-height: calc(100vh - 2.50666rem);"
+            style="min-height: calc(100vh - var(--van-tabs-line-height) - var(--header-height) - 1.33333rem);"
           >
             {showContact.value ? (
               <List

+ 38 - 4
src/school/approval-manage/index.module.less

@@ -20,10 +20,28 @@
     }
   }
 }
-
+.rightTip {
+  :global {
+    .van-nav-bar__right {
+      background: rgba(239, 135, 97, 1);
+      color: #fff;
+      border-radius: 50%;
+      width: 22px;
+      height: 22px;
+      padding: 0;
+      justify-content: center;
+      top: 50%;
+      right: 13px;
+      transform: translateY(-50%);
+    }
+  }
+}
+.wrap{
+  padding: 12px 0;
+}
 .item {
   border-radius: 10px;
-  margin: 12px 13px;
+  margin: 0 13px 12px 13px;
   overflow: hidden;
   background: #fff;
   :global {
@@ -85,6 +103,22 @@
     }
   }
 }
+.tipItem {
+  margin: 0;
+  :global{
+    .van-cell{
+      padding: 25px 25px 20px 25px;
+    }
+  }
+}
+.tipContent {
+  font-size: 15px;
+  font-family: PingFangSC-Regular, PingFang SC;
+  font-weight: 400;
+  color: #333;
+  line-height: 22px;
+  padding: 0 25px 25px 25px;
+}
 .listItem {
   padding-top: 4px;
   padding-bottom: 4px;
@@ -185,10 +219,10 @@
       font-weight: bold;
     }
   }
-  .startTime{
+  .startTime {
     margin-right: 5px;
   }
-  .endTime{
+  .endTime {
     margin-left: 5px;
   }
 }

+ 20 - 4
src/school/approval-manage/index.tsx

@@ -4,16 +4,32 @@ import styles from './index.module.less'
 import { useRouter } from 'vue-router'
 import MyApproval from './MyApproval'
 import Agency from './agency'
+import OSticky from '@/components/o-sticky'
+import OHeader from '@/components/o-header'
 const activeName = ref('wait')
 export default defineComponent({
   name: 'approval-manage',
   setup() {
     const router = useRouter()
     const state = reactive({})
-
+    const headerHeight = ref(0)
     return () => (
-      <>
-        <Tabs v-model:active={activeName.value} class={styles.approvalTab} animated sticky>
+      <div>
+        <OSticky
+          onGetHeight={(height: number) => {
+            headerHeight.value = height
+            document.documentElement.style.setProperty('--header-height', height + 'px')
+          }}
+        >
+          <OHeader />
+        </OSticky>
+        <Tabs
+          v-model:active={activeName.value}
+          class={styles.approvalTab}
+          animated
+          sticky
+          offsetTop={headerHeight.value}
+        >
           <Tab name="wait" title="处理事项">
             <Agency />
           </Tab>
@@ -21,7 +37,7 @@ export default defineComponent({
             <MyApproval />
           </Tab>
         </Tabs>
-      </>
+      </div>
     )
   }
 })

+ 25 - 16
src/school/approval-manage/subsidy/details.tsx

@@ -1,57 +1,66 @@
 import { Cell, Grid, GridItem } from 'vant'
-import { defineComponent } from 'vue'
+import { defineComponent, PropType } from 'vue'
 import styles from '../index.module.less'
 import iconA from '../images/icon-photo.png'
 import iconTime from '../images/icon-time.png'
 import iconPrimary from '../images/icon-primary.png'
 import iconError from '../images/icon-error.png'
+import {courseEmnu} from '@/constant'
 
 export default defineComponent({
   name: 'subsidy-detail',
-  setup() {
+  props: {
+    item: {
+      type: Object,
+      default: () => {}
+    }
+  },
+  setup(props) {
+    console.log("🚀 ~ props", props)
+    const item = (props?.item || {}) as ICourseSalaryRecordDetailItem
     return () => (
-      <div>
+      <div class={styles.wrap}>
         <div class={[styles.item, styles.listItem]}>
-          <Cell border={false} center class={styles.listItem} title="补助标准" value={'240元/天'} />
+          <Cell border={false} center class={styles.listItem} title="补助标准" value={`${item.standardSalary}元/天`} />
           <Cell
             border={false}
             center
             class={styles.listItem}
             title="补助课程"
-            value={'长笛单技课'}
+            value={courseEmnu[item.courseType]}
           />
           <Cell
             border={false}
             center
             class={styles.listItem}
             title="课件使用未达标"
-            value={'-240.00元'}
+            value={`-${item.reduceSalary}元`}
           />
-          <Cell border={false} center class={styles.listItem} title="早退" value={'-50.00元'} />
+          <Cell border={false} center class={styles.listItem} title="早退" value={`-0.00元`} />
           <Cell
             border={false}
             center
             class={styles.listItem}
             title="实际补助金额"
-            value={'190.00元'}
+            value={`${item.actualSalary}元`}
           />
         </div>
 
-        {[1, 2, 3].map((item: any) => (
+        {item?.courseScheduleTeacherAttendanceList.map((item: ICourseScheduleTeacherAttendance) => (
           <div class={styles.item}>
             <Cell center>
               {{
                 title: () => (
                   <div class={styles.itemTitle}>
                     <img class={styles.titleIcon} src={iconTime} />
-                    <span>2023-1-17 14:00~15:3</span>
+                    <span>{item.startTime} - {item.endTime}</span>
                   </div>
                 )
               }}
             </Cell>
             <div class={styles.itemContent}>
               <div class={styles.itemContentTitle}>
-                <span>长笛单技课-张老师</span>
+                <span>{item.classGroupName}-{item.teacherName}</span>
                 <span
                   class={styles.itemContentTitleDetail}
                   style={{ color: 1 ? '#358AF5' : '#F44541' }}
@@ -59,21 +68,21 @@ export default defineComponent({
                   课件使用:15/20分钟
                 </span>
               </div>
-              <div class={styles.itemContentLabel}>武汉市洪山区第二小学2022标准团</div>
+              <div class={styles.itemContentLabel}>{item.orchestraName}</div>
               <div class={styles.times}>
                 <div class={[styles.timesItem, styles.startTime]}>
                   <div class={styles.startTimeTop}>
                     <span>签到时间</span>
-                    <img src={iconPrimary} />
+                    <img src={item.signInStatus === 'NORMAL' ? iconPrimary : iconError} />
                   </div>
-                  <div class={styles.startTimeBottom}>14:08:25</div>
+                  <div class={styles.startTimeBottom}>{item.signInTime}</div>
                 </div>
                 <div class={[styles.timesItem, styles.endTime]}>
                   <div class={styles.startTimeTop}>
                     <span>签退时间</span>
-                    <img src={iconError} />
+                    <img src={item.signOutStatus === 'NORMAL' ?iconPrimary : iconError} />
                   </div>
-                  <div class={styles.startTimeBottom}>15:35:25</div>
+                  <div class={styles.startTimeBottom}>{item.signOutTime}</div>
                 </div>
               </div>
             </div>

+ 147 - 61
src/school/approval-manage/subsidy/exercise-detail.tsx

@@ -1,74 +1,160 @@
-import { Cell, Grid, GridItem } from 'vant'
-import { defineComponent } from 'vue'
+import { Cell, Grid, GridItem, NavBar, Popup, Sticky } from 'vant'
+import { defineComponent, onMounted, reactive, ref } from 'vue'
 import styles from '../index.module.less'
 import iconA from '../images/icon-photo.png'
+import { useRoute } from 'vue-router'
+import request from '@/helpers/request'
+import { state } from '@/state'
+import OFullRefresh from '@/components/o-full-refresh'
+import Details from './details'
+import OHeader from '@/components/o-header'
+import OSticky from '@/components/o-sticky'
 
 export default defineComponent({
   name: 'subsidy-exercise-detail',
   setup() {
+    const route = useRoute()
+    const refreshing = ref(false)
+    const modelData = reactive({
+      show: false,
+      row: null as any
+    })
+    const data = reactive({
+      /**补助明细 */
+      record: {
+        courseSalaryRecordDetailList: [
+          { courseScheduleTeacherAttendanceList: [{}] }
+        ] as ICourseSalaryRecordDetailItem[]
+      } as ICourseSalaryRecordDetail
+    })
+    const getData = () => {
+      request
+        .post(`${state.platformApi}/schoolWeekSalaryRecord/detailInfo/course`, {
+          data: {
+            id: route.query.id,
+            userId: state.user.data.id
+          }
+        })
+        .then((res: any) => {
+          data.record = res?.data || {}
+        })
+        .finally(() => {
+          refreshing.value = false
+        })
+    }
+    onMounted(() => {
+      getData()
+    })
     return () => (
       <div>
-        <div class={styles.item}>
-          <Cell center class={styles.rewardItem}>
-            {{
-              icon: <img class={styles.itemPicture} src={iconA} />,
-              title: () => (
-                <div class={styles.itemTitle}>
-                  <span>邓同学</span>
-                </div>
-              ),
-              value: () => (
-                <div class={styles.gridItem}>
-                  <div class={styles.gridItemTop}>
-                    <span class={styles.topNum}>40</span>元
-                  </div>
-                  <div class={styles.valeLabel}>实际补助</div>
-                </div>
-              )
-            }}
-          </Cell>
-        </div>
+        <OSticky
+          onGetHeight={(height: number) => {
+            document.documentElement.style.setProperty('--header-height', height + 'px')
+          }}
+        >
+          <OHeader></OHeader>
+        </OSticky>
+        <OFullRefresh
+          v-model:modelValue={refreshing.value}
+          onRefresh={getData}
+          style="min-height: calc(100vh - var(--header-height))"
+        >
+          <div class={styles.wrap}>
+            <div class={styles.item}>
+              <Cell center class={styles.rewardItem}>
+                {{
+                  icon: () => <img class={styles.itemPicture} src={iconA} />,
+                  title: () => (
+                    <div class={styles.itemTitle}>
+                      <span>邓同学</span>
+                    </div>
+                  ),
+                  value: () => (
+                    <div class={styles.gridItem}>
+                      <div class={styles.gridItemTop}>
+                        <span class={styles.topNum}>{data.record.actualSalary}</span>元
+                      </div>
+                      <div class={styles.valeLabel}>实际补助</div>
+                    </div>
+                  )
+                }}
+              </Cell>
+            </div>
 
-        {[1, 2, 3].map((item: any) => (
-          <div class={styles.item}>
-            <Cell center value="1天" isLink to={'/subsidy-details'}>
-              {{
-                title: () => (
-                  <div class={styles.itemTitle}>
-                    <div class={styles.titleLine}></div>
-                    <span>长笛单技训练</span>
-                  </div>
-                )
-              }}
-            </Cell>
-            <Grid class={styles.grid} columnNum={3} border={false}>
-              <GridItem>
-                <div class={styles.gridItem}>
-                  <div class={styles.gridItemTop}>
-                    <span class={styles.topNum}>240</span>元
-                  </div>
-                  <div>预计补助</div>
-                </div>
-              </GridItem>
-              <GridItem>
-                <div class={styles.gridItem}>
-                  <div class={styles.gridItemTop}>
-                    <span class={styles.topNum}>0.00</span>元
-                  </div>
-                  <div>考勤扣款</div>
-                </div>
-              </GridItem>
-              <GridItem>
-                <div class={styles.gridItem}>
-                  <div class={styles.gridItemTop}>
-                    <span class={styles.topNum}>240</span>课元
-                  </div>
-                  <div>实际补助</div>
-                </div>
-              </GridItem>
-            </Grid>
+            {data.record.courseSalaryRecordDetailList.map((item: ICourseSalaryRecordDetailItem) => (
+              <div class={styles.item}>
+                <Cell
+                  center
+                  value={`${item.days}天`}
+                  isLink
+                  onClick={() => {
+                    modelData.show = true
+                    modelData.row = item
+                  }}
+                >
+                  {{
+                    title: () => (
+                      <div class={styles.itemTitle}>
+                        <div class={styles.titleLine}></div>
+                        <span>长笛单技训练</span>
+                      </div>
+                    )
+                  }}
+                </Cell>
+                <Grid class={styles.grid} columnNum={3} border={false}>
+                  <GridItem>
+                    <div class={styles.gridItem}>
+                      <div class={styles.gridItemTop}>
+                        <span class={styles.topNum}>{item.expectSalary || 0}</span>元
+                      </div>
+                      <div>预计补助</div>
+                    </div>
+                  </GridItem>
+                  <GridItem>
+                    <div class={styles.gridItem}>
+                      <div class={styles.gridItemTop}>
+                        <span class={styles.topNum}>{item.reduceSalary || 0}</span>元
+                      </div>
+                      <div>考勤扣款</div>
+                    </div>
+                  </GridItem>
+                  <GridItem>
+                    <div class={styles.gridItem}>
+                      <div class={styles.gridItemTop}>
+                        <span class={styles.topNum}>{item.actualSalary || 0}</span>课元
+                      </div>
+                      <div>实际补助</div>
+                    </div>
+                  </GridItem>
+                </Grid>
+              </div>
+            ))}
+          </div>
+        </OFullRefresh>
+        <Popup
+          v-model:show={modelData.show}
+          position="bottom"
+          closeable
+          style={{
+            width: '100vw',
+            height: '80vh',
+            '--van-popup-background': 'rgba(246,246,246,1)',
+            '--van-nav-bar-icon-color': '#333',
+            '--van-popup-close-icon-margin':
+              'calc(var(--van-nav-bar-height) / 2 - var(--van-popup-close-icon-size) / 2)'
+          }}
+        >
+          <NavBar title="补助明细" />
+          <div
+            style={{
+              height: 'calc(80vh - var(--van-nav-bar-height))',
+              overflow: 'hidden',
+              'overflow-y': 'auto'
+            }}
+          >
+            <Details item={modelData.row || {}} />
           </div>
-        ))}
+        </Popup>
       </div>
     )
   }

+ 148 - 54
src/school/approval-manage/subsidy/grant-detail.tsx

@@ -1,69 +1,163 @@
-import { Cell, Grid, GridItem } from 'vant'
-import { defineComponent } from 'vue'
+import { Cell, Dialog, Grid, GridItem, Sticky } from 'vant'
+import { defineComponent, onMounted, reactive, ref } from 'vue'
 import styles from '../index.module.less'
 import iconTime from '../images/icon-time.png'
+import { useRoute } from 'vue-router'
+import request from '@/helpers/request'
+import { state } from '@/state'
+import OFullRefresh from '@/components/o-full-refresh'
+import OHeader from '@/components/o-header'
+import OSticky from '@/components/o-sticky'
 
 export default defineComponent({
   name: 'subsidy-grant-detail',
   setup() {
+    const route = useRoute()
+    const refreshing = ref(false)
+    const dialog = ref(false)
+    const data = reactive({
+      /**管理补助 */
+      manageSalary: {} as ISchoolStaffManageSalary,
+      rows: [] as ICourseSchedule[]
+    })
+    const getData = () => {
+      request
+        .post(`${state.platformApi}/schoolWeekSalaryRecord/detailInfo/manageTitle`, {
+          data: {
+            id: route.query.id,
+            userId: state.user.data.id
+          }
+        })
+        .then((res: any) => {
+          data.manageSalary = res?.data || {}
+        })
+      request
+        .post(`${state.platformApi}/schoolWeekSalaryRecord/detailInfo/managePage`, {
+          data: {
+            id: route.query.id,
+            userId: state.user.data.id
+          }
+        })
+        .then((res: any) => {
+          data.rows = res?.data?.rows || []
+        })
+        .finally(() => {
+          refreshing.value = false
+        })
+    }
+    onMounted(() => {
+      getData()
+    })
     return () => (
       <div>
+        <OSticky
+          onGetHeight={(height: number) => {
+            document.documentElement.style.setProperty('--header-height', height + 'px')
+          }}
+        >
+          <OHeader
+            class={styles.rightTip}
+            rightText="?"
+            onClickRight={() => (dialog.value = true)}
+          ></OHeader>
+        </OSticky>
+        <OFullRefresh
+          v-model:modelValue={refreshing.value}
+          onRefresh={getData}
+          style="min-height: calc(100vh - var(--header-height))"
+        >
+          <div class={styles.wrap}>
+            <div class={styles.item}>
+              <Cell
+                center
+                value={`${data.manageSalary.photoNum}/${data.manageSalary.expectPhotoNum}`}
+              >
+                {{
+                  title: () => (
+                    <div class={styles.itemTitle}>
+                      <div class={styles.titleLine}></div>
+                      <span>管理补助</span>
+                    </div>
+                  )
+                }}
+              </Cell>
+              <Grid class={styles.grid} columnNum={3} border={false}>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum} style={{ color: '#333' }}>
+                        {data.manageSalary.standardSalary || 0}
+                      </span>
+                      元/周
+                    </div>
+                    <div>补助标准</div>
+                  </div>
+                </GridItem>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum} style={{ color: '#333' }}>
+                        {data.manageSalary.coursewareNum || 0}
+                      </span>
+                      课时
+                    </div>
+                    <div>本周课时数</div>
+                  </div>
+                </GridItem>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>{data.manageSalary.actualSalary || 0}</span>元
+                    </div>
+                    <div>实际补助</div>
+                  </div>
+                </GridItem>
+              </Grid>
+            </div>
 
-        <div class={styles.item}>
-          <Cell center value="训练照片2/6">
-            {{
-              title: () => (
-                <div class={styles.itemTitle}>
-                  <div class={styles.titleLine}></div>
-                  <span>管理补助</span>
+            {data.rows.map((item: ICourseSchedule) => {
+              return () => (
+                <div class={styles.item}>
+                  <Cell center>
+                    {{
+                      title: () => (
+                        <div class={styles.itemTitle}>
+                          <img class={styles.titleIcon} src={iconTime} />
+                          <span>{item.startTime}</span>
+                        </div>
+                      )
+                    }}
+                  </Cell>
+                  <div class={styles.itemContent}>
+                    <div class={styles.itemContentTitle}>
+                      {item.className}-{item.teacherName}
+                    </div>
+                    <div class={styles.itemContentLabel}>{item.orchestraName}</div>
+                  </div>
                 </div>
               )
-            }}
-          </Cell>
-          <Grid class={styles.grid} columnNum={3} border={false}>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元/周
-                </div>
-                <div>补助标准</div>
-              </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元/周
-                </div>
-                <div>补助标准</div>
-              </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>课时
-                </div>
-                <div>本周课时数</div>
-              </div>
-            </GridItem>
-          </Grid>
-        </div>
-
-        <div class={styles.item}>
-          <Cell center>
-            {{
-              title: () => (
-                <div class={styles.itemTitle}>
-                  <img class={styles.titleIcon} src={iconTime} />
-                  <span>2023-1-17 14:00~15:3</span>
-                </div>
-              )
-            }}
-          </Cell>
-          <div class={styles.itemContent}>
-            <div class={styles.itemContentTitle}>长笛单技课-张老师</div>
-            <div class={styles.itemContentLabel}>武汉市洪山区第二小学2022标准团</div>
+            })}
+          </div>
+        </OFullRefresh>
+        <Dialog v-model:show={dialog.value} confirmButtonText="我知道了">
+          <div class={[styles.item, styles.tipItem]}>
+            <Cell center border={false}>
+              {{
+                title: () => (
+                  <div class={styles.itemTitle}>
+                    <div class={styles.titleLine}></div>
+                    <span>补助标准</span>
+                  </div>
+                )
+              }}
+            </Cell>
+            <div class={styles.tipContent}>
+              1、若未在学期时间内发布不少于2篇乐团资讯,则下一学期管理补助按标准金额的80%发放
+              <br />
+              2、如该学期管理补助是按标准金额的80%发放,只要该学期完成不少于2篇乐团资讯推送,则下学期恢复正常管理补助标准
+            </div>
           </div>
-        </div>
+        </Dialog>
       </div>
     )
   }

+ 274 - 172
src/school/approval-manage/subsidy/index.tsx

@@ -1,191 +1,293 @@
-import { Cell, Grid, GridItem } from 'vant'
-import { defineComponent } from 'vue'
+import { Cell, Dialog, Grid, GridItem, Sticky } from 'vant'
+import { defineComponent, onMounted, reactive, ref } from 'vue'
 import styles from '../index.module.less'
 import iconA from '../images/icon-photo.png'
+import request from '@/helpers/request'
+import { state } from '@/state'
+import { useRoute } from 'vue-router'
+import OFullRefresh from '@/components/o-full-refresh'
+import OHeader from '@/components/o-header'
+import OSticky from '@/components/o-sticky'
 
 export default defineComponent({
   name: 'approval-manage-subsidy',
   setup() {
+    const route = useRoute()
+    const dialog = ref(false)
+    const refreshing = ref(false)
+    const data = reactive({
+      startDate: '',
+      endDate: '',
+      manageSalary: '',
+      courseSalary: '',
+      practiceSalary: '',
+      /**管理补助 */
+      manageSalaryInfo: {} as any,
+      /**训练补助 */
+      courseSalaryInfo: {} as any,
+      /**练习奖励 */
+      practiceSalaryInfo: {} as any
+    })
+    const getData = async () => {
+      try {
+        const res: any = await request.post(
+          `${state.platformApi}/schoolWeekSalaryRecord/manageConfirm/${route.query.salaryId}`
+        )
+      } catch (error) {}
+      refreshing.value = false
+    }
+    onMounted(() => {
+      getData()
+    })
     return () => (
       <div>
-        <div class={styles.item}>
-          <Cell center isLink>
-            {{
-              title: () => (
-                <div class={styles.itemTitle}>
-                  <span>2023-1-16 至 2023-1-2</span>
-                  <span class={styles.itemTag}>补助周期</span>
-                </div>
-              )
-            }}
-          </Cell>
-          <Grid class={styles.grid} columnNum={3} border={false}>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元
-                </div>
-                <div>管理补助</div>
-              </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元
-                </div>
-                <div>训练补助</div>
-              </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元
-                </div>
-                <div>练习奖励</div>
-              </div>
-            </GridItem>
-          </Grid>
-        </div>
+        <OSticky
+          onGetHeight={(height: number) => {
+            document.documentElement.style.setProperty('--header-height', height + 'px')
+          }}
+        >
+          <OHeader
+            class={styles.rightTip}
+            rightText="?"
+            onClickRight={() => (dialog.value = true)}
+          ></OHeader>
+        </OSticky>
+        <OFullRefresh
+          v-model:modelValue={refreshing.value}
+          onRefresh={getData}
+          style="min-height: calc(100vh - var(--header-height))"
+        >
+          <div class={styles.wrap}>
+            <div class={styles.item}>
+              <Cell center>
+                {{
+                  title: () => (
+                    <div class={styles.itemTitle}>
+                      <span>
+                        {data.startDate} 至 {data.endDate}
+                      </span>
+                      <span class={styles.itemTag}>补助周期</span>
+                    </div>
+                  )
+                }}
+              </Cell>
+              <Grid class={styles.grid} columnNum={3} border={false}>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>{data.manageSalary || 0}</span>元
+                    </div>
+                    <div>管理补助</div>
+                  </div>
+                </GridItem>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>{data.courseSalary || 0}</span>元
+                    </div>
+                    <div>训练补助</div>
+                  </div>
+                </GridItem>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>{data.practiceSalary || 0}</span>元
+                    </div>
+                    <div>练习奖励</div>
+                  </div>
+                </GridItem>
+              </Grid>
+            </div>
 
-        <div class={styles.item}>
-          <Cell
-            style={{ '--van-cell-value-color': '#F44541' }}
-            center
-            value="训练照片2/6"
-            isLink
-            to={'/subsidy-grant-detail'}
-          >
-            {{
-              title: () => (
-                <div class={styles.itemTitle}>
-                  <div class={styles.titleLine}></div>
-                  <span>管理补助</span>
-                </div>
-              )
-            }}
-          </Cell>
-          <Grid class={styles.grid} columnNum={3} border={false}>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元/周
-                </div>
-                <div>补助标准</div>
-              </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元/周
-                </div>
-                <div>补助标准</div>
-              </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>课时
-                </div>
-                <div>本周课时数</div>
-              </div>
-            </GridItem>
-          </Grid>
-        </div>
+            <div class={styles.item}>
+              <Cell
+                style={{ '--van-cell-value-color': '#F44541' }}
+                center
+                value={`${data.manageSalaryInfo.expectPhotoNum}/${data.manageSalaryInfo.photoNum}`}
+                isLink
+                to={'/subsidy-grant-detail?id=' + (data.manageSalaryInfo.id || '')}
+              >
+                {{
+                  title: () => (
+                    <div class={styles.itemTitle}>
+                      <div class={styles.titleLine}></div>
+                      <span>管理补助</span>
+                    </div>
+                  )
+                }}
+              </Cell>
+              <Grid class={styles.grid} columnNum={3} border={false}>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum} style={{ color: '#333' }}>
+                        {data.manageSalaryInfo.standardSalary || 0}
+                      </span>
+                      元/周
+                    </div>
+                    <div>补助标准</div>
+                  </div>
+                </GridItem>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum} style={{ color: '#333' }}>
+                        {data.manageSalaryInfo.standardSalary || 0}
+                      </span>
+                      课时
+                    </div>
+                    <div>本周课时数</div>
+                  </div>
+                </GridItem>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>{data.manageSalaryInfo.actualSalary || 0}</span>元
+                    </div>
+                    <div>实际补助</div>
+                  </div>
+                </GridItem>
+              </Grid>
+            </div>
 
-        <div class={styles.item}>
-          <Cell center isLink to={'/subsidy-reward-detail'}>
-            {{
-              title: () => (
-                <div class={styles.itemTitle}>
-                  <div class={styles.titleLine}></div>
-                  <span>练习奖励</span>
-                </div>
-              )
-            }}
-          </Cell>
-          <Grid class={styles.grid} columnNum={3} border={false}>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>5</span>元/人
-                </div>
-                <div>补助标准</div>
-              </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>78</span>人
-                </div>
-                <div>练习达标人数</div>
-              </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元
-                </div>
-                <div>实际奖励</div>
-              </div>
-            </GridItem>
-          </Grid>
-        </div>
+            <div class={styles.item}>
+              <Cell center isLink to={'/subsidy-reward-detail'}>
+                {{
+                  title: () => (
+                    <div class={styles.itemTitle}>
+                      <div class={styles.titleLine}></div>
+                      <span>练习奖励</span>
+                    </div>
+                  )
+                }}
+              </Cell>
+              <Grid class={styles.grid} columnNum={3} border={false}>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>
+                        {data.practiceSalaryInfo.standardSalary || 0}
+                      </span>
+                      元/人
+                    </div>
+                    <div>补助标准</div>
+                  </div>
+                </GridItem>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>{data.practiceSalaryInfo.targetNum || 0}</span>人
+                    </div>
+                    <div>练习达标人数</div>
+                  </div>
+                </GridItem>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>{data.practiceSalaryInfo.actualSalary || 0}</span>
+                      元
+                    </div>
+                    <div>实际奖励</div>
+                  </div>
+                </GridItem>
+              </Grid>
+            </div>
 
-        <div class={styles.item}>
-          <Cell center isLink to={'/subsidy-exercise-detail'}>
-            {{
-              title: () => (
-                <div class={styles.itemTitle}>
-                  <div class={styles.titleLine}></div>
-                  <span>训练补助</span>
-                </div>
-              )
-            }}
-          </Cell>
-          <Grid class={styles.grid} columnNum={3} border={false}>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元/人
-                </div>
-                <div>单技补助标准</div>
-              </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元/天
-                </div>
-                <div>乐理补助标准</div>
-              </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元
-                </div>
-                <div>合奏补助标准</div>
-              </div>
-            </GridItem>
-          </Grid>
-          {[1, 2, 3].map((teacher: any) => {
-            return (
-              <Cell center title="邓老师" isLink>
+            <div class={styles.item}>
+              <Cell center to={'/subsidy-exercise-detail'}>
                 {{
-                  icon: () => <img class={styles.itemPicture} src={iconA} />,
-                  value: () => (
-                    <div class={styles.gridItem}>
-                      <div class={styles.gridItemTop}>
-                        <span class={styles.topNum}>240</span>元
-                      </div>
-                      <div class={styles.valeLabel}>实际奖励</div>
+                  title: () => (
+                    <div class={styles.itemTitle}>
+                      <div class={styles.titleLine}></div>
+                      <span>训练补助</span>
                     </div>
                   )
                 }}
               </Cell>
-            )
-          })}
-        </div>
+              <Grid class={styles.grid} columnNum={3} border={false}>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>
+                        {data.courseSalaryInfo.singleSubsidyStandard || 0}
+                      </span>
+                      元/人
+                    </div>
+                    <div>单技补助标准</div>
+                  </div>
+                </GridItem>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>
+                        {data.courseSalaryInfo.musicSubsidyStandard || 0}
+                      </span>
+                      元/天
+                    </div>
+                    <div>乐理补助标准</div>
+                  </div>
+                </GridItem>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>
+                        {data.courseSalaryInfo.ensembleSubsidyStandard || 0}
+                      </span>
+                      元
+                    </div>
+                    <div>合奏补助标准</div>
+                  </div>
+                </GridItem>
+              </Grid>
+              {Array.isArray(data.courseSalaryInfo.salaryRecordDetailItemList) &&
+                data.courseSalaryInfo.salaryRecordDetailItemList.map((teacher: any) => {
+                  return (
+                    <Cell
+                      center
+                      title={teacher.userName}
+                      isLink
+                      to={'/subsidy-exercise-detail?id='}
+                    >
+                      {{
+                        icon: () => <img class={styles.itemPicture} src={teacher.avatar} />,
+                        value: () => (
+                          <div class={styles.gridItem}>
+                            <div class={styles.gridItemTop}>
+                              <span class={styles.topNum}>{teacher.salary || 0}</span>元
+                            </div>
+                            <div class={styles.valeLabel}>实际奖励</div>
+                          </div>
+                        )
+                      }}
+                    </Cell>
+                  )
+                })}
+            </div>
+          </div>
+        </OFullRefresh>
+        <Dialog v-model:show={dialog.value} confirmButtonText="我知道了">
+          <div class={[styles.item, styles.tipItem]}>
+            <Cell center border={false}>
+              {{
+                title: () => (
+                  <div class={styles.itemTitle}>
+                    <div class={styles.titleLine}></div>
+                    <span>补助发放规则</span>
+                  </div>
+                )
+              }}
+            </Cell>
+            <div class={styles.tipContent}>
+              1、每周一上午10点生成上一周实际补助数据
+              <br />
+              2、每周一24点前完成补助确认,则该补助将会在当周周五发放
+              <br />
+              3、超过周一24点确认,则延后到下周周五发放 4、如遇法定节假日,则统一延后到下一周五发放
+              <br />
+              5、未绑定银行卡造成无法发放时,在绑定银行卡后的下一周五一次性将已确认且未发放的金额一次性发放
+            </div>
+          </div>
+        </Dialog>
       </div>
     )
   }

+ 155 - 69
src/school/approval-manage/subsidy/reward-detail.tsx

@@ -1,105 +1,191 @@
 import { ActionSheet, ActionSheetAction, Cell, Grid, GridItem } from 'vant'
-import { computed, defineComponent, ref } from 'vue'
+import { computed, defineComponent, onMounted, reactive, ref } from 'vue'
 import styles from '../index.module.less'
 import iconA from '../images/icon-photo.png'
 import iconArrow from '../images/icon-arrow.png'
+import OFullRefresh from '@/components/o-full-refresh'
+import { useRoute } from 'vue-router'
+import request from '@/helpers/request'
+import { state } from '@/state'
+import OEmpty from '@/components/o-empty'
+import OSticky from '@/components/o-sticky'
+import OHeader from '@/components/o-header'
 
 export default defineComponent({
   name: 'subsidy-reward-detail',
   setup() {
+    const route = useRoute()
+    const refreshing = ref(false)
+    const dialog = ref(false)
+    const data = reactive({
+      /**声部ID */
+      subjectId: '',
+      /**声部列表 */
+      subjects: [] as any[],
+      /**管理补助 */
+      manageSalary: {} as ISchoolStaffTrainingSalary,
+      rows: [] as IStudent[]
+    })
+    const getData = () => {
+      request
+        .post(`${state.platformApi}/schoolWeekSalaryRecord/detailInfo/trainingTitle`, {
+          data: {
+            id: route.query.id,
+            userId: state.user.data.id,
+            subjectId: data.subjectId
+          }
+        })
+        .then((res: any) => {
+          data.manageSalary = res?.data || {}
+        })
+      request
+        .post(`${state.platformApi}/schoolWeekSalaryRecord/detailInfo/trainingPage`, {
+          data: {
+            id: route.query.id,
+            userId: state.user.data.id,
+            subjectId: data.subjectId
+          }
+        })
+        .then((res: any) => {
+          data.rows = res?.data?.rows || []
+        })
+        .finally(() => {
+          refreshing.value = false
+        })
+    }
+    onMounted(() => {
+      request
+        .post(`${state.platformApi}/subjectBasicConfig/page`, {
+          data: { page: 1, rows: 9999 }
+        })
+        .then((res: any) => {
+          if (Array.isArray(res?.data?.rows)) {
+            data.subjects = res.data.rows
+          }
+        })
+      getData()
+    })
     const actions = computed(() => {
+      const subList = data.subjects.map((n: any) => {
+        return {
+          name: n.subjectName,
+          value: n.subjectId,
+          color: activeName.value == n.subjectName ? 'var(--van-primary-color)' : ''
+        }
+      })
       return [
         {
           name: '全部声部',
           color: activeName.value == '全部声部' ? 'var(--van-primary-color)' : ''
         },
-        { name: '待审批', color: activeName.value == '待审批' ? 'var(--van-primary-color)' : '' },
-        { name: '已完成', color: activeName.value == '已完成' ? 'var(--van-primary-color)' : '' }
+        ...subList
       ]
     })
     const activeName = ref('全部声部')
     const show = ref(false)
     return () => (
       <div>
-        <div class={styles.item}>
-          <Cell center>
-            {{
-              title: () => (
-                <div class={styles.itemTitle}>
-                  <div class={styles.titleLine}></div>
-                  <span>练习奖励</span>
-                </div>
-              )
-            }}
-          </Cell>
-          <Grid class={styles.grid} columnNum={3} border={false}>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>5</span>元/人
-                </div>
-                <div>补助标准</div>
-              </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>78</span>人
-                </div>
-                <div>练习达标人数</div>
-              </div>
-            </GridItem>
-            <GridItem>
-              <div class={styles.gridItem}>
-                <div class={styles.gridItemTop}>
-                  <span class={styles.topNum}>240</span>元
-                </div>
-                <div>实际奖励</div>
-              </div>
-            </GridItem>
-          </Grid>
-        </div>
-
-        <div class={styles.itemSelect}>
-          <div class={styles.select} onClick={() => (show.value = true)}>
-            <span>{activeName.value}</span>
-            <img src={iconArrow} />
-          </div>
-        </div>
-
-        <div class={styles.item}>
-          {[1, 2, 3].map((item: any) => {
-            return (
-              <Cell center class={styles.rewardItem}>
+        <OSticky
+          onGetHeight={(height: number) => {
+            document.documentElement.style.setProperty('--header-height', height + 'px')
+          }}
+        >
+          <OHeader></OHeader>
+        </OSticky>
+        <OFullRefresh
+          v-model:modelValue={refreshing.value}
+          onRefresh={getData}
+          style="min-height: calc(100vh - var(--header-height))"
+        >
+          <div class={styles.wrap}>
+            <div class={styles.item}>
+              <Cell center>
                 {{
-                  icon: <img class={styles.itemPicture} src={iconA} />,
                   title: () => (
                     <div class={styles.itemTitle}>
-                      <span>邓同学</span>
-                    </div>
-                  ),
-                  label: () => <span class={styles.itemTag}>长笛</span>,
-                  value: () => (
-                    <div class={styles.gridItem}>
-                      <div class={styles.gridItemTop}>
-                        <span class={styles.topNum}>40</span>分钟
-                      </div>
-                      <div class={styles.valeLabel}>练习时长</div>
+                      <div class={styles.titleLine}></div>
+                      <span>练习奖励</span>
                     </div>
                   )
                 }}
               </Cell>
-            )
-          })}
-        </div>
+              <Grid class={styles.grid} columnNum={3} border={false}>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>{data.manageSalary.standardSalary || 0}</span>
+                      元/人
+                    </div>
+                    <div>补助标准</div>
+                  </div>
+                </GridItem>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>{data.manageSalary.targetNum || 0}</span>人
+                    </div>
+                    <div>练习达标人数</div>
+                  </div>
+                </GridItem>
+                <GridItem>
+                  <div class={styles.gridItem}>
+                    <div class={styles.gridItemTop}>
+                      <span class={styles.topNum}>{data.manageSalary.actualSalary || 0}</span>元
+                    </div>
+                    <div>实际奖励</div>
+                  </div>
+                </GridItem>
+              </Grid>
+            </div>
+
+            <div class={styles.itemSelect}>
+              <div class={styles.select} onClick={() => (show.value = true)}>
+                <span>{activeName.value}</span>
+                <img src={iconArrow} />
+              </div>
+            </div>
+
+            {data.rows.length ? (
+              <div class={styles.item}>
+                {data.rows.map((item: IStudent) => {
+                  return (
+                    <Cell center>
+                      {{
+                        icon: () => <img class={styles.itemPicture} src={item.avatar} />,
+                        title: () => (
+                          <div class={styles.itemTitle}>
+                            <span>{item.nickname}</span>
+                          </div>
+                        ),
+                        label: () => <span class={styles.itemTag}>{item.subjectNames}</span>,
+                        value: () => (
+                          <div class={styles.gridItem}>
+                            <div class={styles.gridItemTop}>
+                              <span class={styles.topNum}>{item.practiceTimes}</span>分钟
+                            </div>
+                            <div class={styles.valeLabel}>练习时长</div>
+                          </div>
+                        )
+                      }}
+                    </Cell>
+                  )
+                })}
+              </div>
+            ) : (
+              <OEmpty tips="暂无学生练习" />
+            )}
+          </div>
+        </OFullRefresh>
         <ActionSheet
           teleport="body"
           cancelText="取消"
           v-model:show={show.value}
           actions={actions.value}
-          onSelect={(action: ActionSheetAction, index: number) => {
-            activeName.value = action.name || '待审批'
+          onSelect={(action: any, index: number) => {
+            activeName.value = action.name || '全部声部'
+            data.subjectId = action.value || ''
             show.value = false
+            getData()
           }}
         ></ActionSheet>
       </div>

+ 252 - 0
src/school/approval-manage/subsidy/subsidyTypes.ts

@@ -0,0 +1,252 @@
+/**管理老师管理补助表 */
+interface ISchoolStaffManageSalary {
+  /**预计的训练照片数 */
+  expectPhotoNum: number | string
+  /**扣减奖励 */
+  reduceSalary: number | string
+  /**补助标准 */
+  standardSalary: number | string
+  /**实际奖励 */
+  actualSalary: number | string
+  /**课件数 */
+  coursewareNum: number | string
+  /**预计奖励 */
+  expectSalary: number | string
+  /**训练照片数 */
+  photoNum: number | string
+}
+
+/**老师课程表 */
+interface ICourseSchedule {
+  /**课程计划编号 */
+  lessonCoursewareId: string
+  /**训练规划类型: STANDARD:标准 PRACTISE:加练 ADJUST:调整 */
+  arrangeType: 'STANDARD' | 'PRACTISE' | 'ADJUST'
+  /**班级名 */
+  className: string
+  /**课程类型 */
+  type:
+    | 'PERCUSSION_SINGLE'
+    | 'FLUTE_SINGLE'
+    | 'SAX_SINGLE'
+    | 'CLARINET_SINGLE'
+    | 'TRUMPET_SINGLE'
+    | 'TROMBONE_SINGLE'
+    | 'HORN_SINGLE'
+    | 'BARITONE_TUBA_SINGLE'
+    | 'EUPHONIUM_SINGLE'
+    | 'TUBA_SINGLE'
+    | 'MUSIC_THEORY'
+    | 'INSTRUMENTAL_ENSEMBLE'
+  /**训练时长 */
+  singleCourseTime: string | number
+  /**班组IM群 */
+  imGroupId: string
+  /**乐团id */
+  orchestraId: string
+  /**学校编号 */
+  schoolId: number | string
+  /**是否必须配置课件 */
+  coursewareFlag: boolean
+  /**上课时间 */
+  startTime: string
+  /**课程id */
+  id: string
+  /**签退时间 */
+  signOutTime: string
+  /**课程老师签到信息 */
+  attendanceStatus:
+    | 'NORMAL'
+    | 'EXCEPTION'
+    | 'LATE'
+    | 'EARLY'
+    | 'TRUANCY'
+    | 'NO_SIGN'
+    | 'NO_SIGN_OUT'
+    | 'LOCATION_EXCEPTION'
+  /**伴学老师名 */
+  teacherAvatar: string
+  /**课程计划内容编号 */
+  lessonCoursewareDetailId: string
+  /**上课日期 */
+  classDate: string
+  /**伴学老师名 */
+  teacherName: string
+  /**学生考勤 */
+  studentAttendance: 'LATE' | 'NORMAL' | 'LEAVE' | 'TRUANCY' | 'UNCALLED'
+  /**时间冲突 */
+  timeConflict: boolean
+  /**乐团名 */
+  orchestraName: string
+  /**是否签退 */
+  signOut: boolean
+  /**签到时间 */
+  signInTime: string
+  /**伴学老师Id */
+  teacherId: string
+  /**是否签到 */
+  signIn: boolean
+  /**作业是否完成:NO_HOMEWORK:未布置作业 UNSUBMITTED:未提交 SUBMITTED:已提交 TARGET:已达标 */
+  homeworkComplete: 'NO_HOMEWORK' | 'UNSUBMITTED' | 'SUBMITTED' | 'TARGET'
+  /**冲突类型 */
+  conflictType: Array<any> | string
+  /**下课时间 */
+  endTime: string
+  /**班级id */
+  classGroupId: string
+  /**预计上课人数 */
+  preStudentNum: string
+  /**课程状态 NOT_START未开始 ING进行中 COMPLETE已完成 */
+  status: 'NOT_START' | 'ING' | 'COMPLETE'
+}
+
+/**管理老师训练奖励表 */
+interface ISchoolStaffTrainingSalary {
+  /**一周结束日期 */
+  endDate: string
+  /**扣减明细 */
+  deductionDetail: string
+  /**老师编号 */
+  userId: string
+  /**奖励变动原因 */
+  deductionReason: string
+  /**扣减奖励 */
+  reduceSalary: number
+  /**奖励标准 */
+  standardSalary: number
+  /**实际奖励 */
+  actualSalary: number
+  /**结算时间 */
+  settlementTime: string
+  /**达标人数 */
+  targetNum: number
+  /**学校id */
+  schoolId: string
+  /**预计奖励 */
+  expectSalary: number
+  /**一周开始日期 */
+  startDate: string
+  /**结算状态 */
+  status: 'WAIT' | 'SETTLED' | 'PART_SETTLED' | 'SETTLE_FAIL'
+}
+
+/**学生列表 */
+interface IStudent {
+  /**练习分钟 */
+  practiceTimes: number
+  /**昵称 */
+  nickname: string
+  /**头像 */
+  avatar: string
+  /**声部名, 多个逗号隔开 */
+  subjectNames: string
+  /**主键ID */
+  userId: string
+  /**声部ID */
+  subjectId: string
+}
+
+/**补助详情数据明细-课程补助明细 */
+interface ICourseSalaryRecordDetail {
+  /**扣款金额 */
+  reduceSalary: number
+  /**补助详情列表数据 */
+  courseSalaryRecordDetailList: ICourseSalaryRecordDetailItem[]
+  /**实际补助金额 */
+  actualSalary: number
+  /**预计补助金额 */
+  expectSalary: number
+}
+/**课程补助详情数据集合 */
+interface ICourseSalaryRecordDetailItem {
+  /**课程类型 */
+  courseType:
+    | 'PERCUSSION_SINGLE'
+    | 'FLUTE_SINGLE'
+    | 'SAX_SINGLE'
+    | 'CLARINET_SINGLE'
+    | 'TRUMPET_SINGLE'
+    | 'TROMBONE_SINGLE'
+    | 'HORN_SINGLE'
+    | 'BARITONE_TUBA_SINGLE'
+    | 'EUPHONIUM_SINGLE'
+    | 'TUBA_SINGLE'
+    | 'TEST_CLARINET'
+    | 'MUSIC_THEORY'
+    | 'INSTRUMENTAL_ENSEMBLE'
+  /**扣款金额 */
+  reduceSalary: number
+  /**补助标准 */
+  standardSalary: number
+  /**实际补助金额 */
+  actualSalary: number
+  /**天数 */
+  days: number
+  /**预计补助金额 */
+  expectSalary: number
+  /**课程考勤信息 */
+  courseScheduleTeacherAttendanceList: ICourseScheduleTeacherAttendance[]
+}
+/**伴学老师签到 */
+interface ICourseScheduleTeacherAttendance {
+  /**老师名称 */
+  teacherName: string
+  /**乐团名称 */
+  orchestraName: string
+  /**课程编号 */
+  courseScheduleId: string
+  /**训练时长 */
+  singleCourseTime: string
+  /**签到状态(正常、异常、迟到、早退、旷课、未签到) */
+  signInStatus:
+    | 'NORMAL'
+    | 'EXCEPTION'
+    | 'LATE'
+    | 'EARLY'
+    | 'TRUANCY'
+    | 'NO_SIGN'
+    | 'NO_SIGN_OUT'
+    | 'LOCATION_EXCEPTION'
+  /**乐团编号 */
+  orchestraId: string
+  /**班级名称 */
+  classGroupName: string
+  /**签到时间 */
+  signInTime: string
+  /**是否为补助考勤 */
+  subsidyFlag: boolean
+  /**老师编号 */
+  teacherId: string
+  /**学校编号 */
+  schoolId: string
+  /**用户聊天ID */
+  imUserId: string
+  /**老师电话 */
+  teacherPhone: string
+  /**上课时间 */
+  startTime: string
+  /**班级im聊天 */
+  classGroupImToken: string
+  /**下课时间 */
+  endTime: string
+  /**考勤id */
+  id: string
+  /**签退状态(正常、异常、迟到、早退、旷课、未签到) */
+  signOutStatus:
+    | 'NORMAL'
+    | 'EXCEPTION'
+    | 'LATE'
+    | 'EARLY'
+    | 'TRUANCY'
+    | 'NO_SIGN'
+    | 'NO_SIGN_OUT'
+    | 'LOCATION_EXCEPTION'
+  /**签退时间 */
+  signOutTime: string
+  /**课程类型 */
+  classType: 'SINGLE' | 'MUSIC_THEORY' | 'INSTRUMENTAL_ENSEMBLE'
+  /**老师头像 */
+  teacherAvatar: string
+  /**班级编号 */
+  classGroupId: string
+}

+ 42 - 41
src/school/companion-teacher/companion-teacher-register.tsx

@@ -44,7 +44,7 @@ export default defineComponent({
       id: route.query.id,
       name: route.query.name,
       t: route.query.t as any, // 过期时间
-      qrCodeStatus: false, // 二维码是否失效
+      // qrCodeStatus: false, // 二维码是否失效
       pattern: /^1(3|4|5|6|7|8|9)\d{9}$/,
       columns: [] as any,
       pickerType: null, // 下拉类型
@@ -77,15 +77,15 @@ export default defineComponent({
     })
 
     const onSubmit = async () => {
-      if (state.qrCodeStatus) {
-        showDialog({
-          title: '提示',
-          message: '二维码已失效',
-          theme: 'round-button',
-          confirmButtonColor: '#ff8057'
-        })
-        return
-      }
+      // if (state.qrCodeStatus) {
+      //   showDialog({
+      //     title: '提示',
+      //     message: '二维码已失效',
+      //     theme: 'round-button',
+      //     confirmButtonColor: '#ff8057'
+      //   })
+      //   return
+      // }
       if (!state.checked) {
         showToast('请阅读并同意协议')
         return
@@ -198,37 +198,6 @@ export default defineComponent({
       //   return
       // }
 
-      // t: route.query.t, // 过期时间
-      try {
-        // await request.post('/api-school/open/schoolTeacherStudent/queryQrCodeStatus', {
-        //   data: {
-        //     schoolId: state.id,
-        //     qrCodeEffectiveStartTime: state.t ? dayjs(state.t).format('YYYY-MM-DD HH:mm:ss') : null
-        //   }
-        // })
-        if (state.t) {
-          const { data } = await request.get('/api-school/open/paramConfig/queryByParamName', {
-            requestType: 'form',
-            params: {
-              paramName: 'qr_code_expire_hours'
-            }
-          })
-          if (dayjs(Number(state.t)).add(data.paramValue, 'hour').isBefore(dayjs())) {
-            showDialog({
-              title: '提示',
-              message: '二维码已失效',
-              theme: 'round-button',
-              confirmButtonColor: '#ff8057'
-            })
-            state.qrCodeStatus = true
-          } else {
-            state.qrCodeStatus = false
-          }
-        }
-      } catch {
-        //
-      }
-
       try {
         const tempareas: any = []
         areas.forEach((item) => {
@@ -272,6 +241,38 @@ export default defineComponent({
           confirmButtonColor: '#ff8057'
         })
       }
+
+      // t: route.query.t, // 过期时间
+      try {
+        await request.post('/api-school/open/schoolTeacherStudent/queryQrCodeStatus', {
+          data: {
+            schoolId: state.id
+            // qrCodeEffectiveStartTime: state.t ? dayjs(state.t).format('YYYY-MM-DD HH:mm:ss') : null
+          }
+        })
+        // if (state.t) {
+        //   const { data } = await request.get('/api-school/open/paramConfig/queryByParamName', {
+        //     requestType: 'form',
+        //     params: {
+        //       paramName: 'qr_code_expire_hours'
+        //     }
+        //   })
+        //   if (dayjs(Number(state.t)).add(data.paramValue, 'hour').isBefore(dayjs())) {
+        // showDialog({
+        //   title: '提示',
+        //   message: '二维码已失效',
+        //   theme: 'round-button',
+        //   confirmButtonColor: '#ff8057'
+        // })
+        //     state.qrCodeStatus = true
+        //   } else {
+        //     state.qrCodeStatus = false
+        //   }
+        // }
+      } catch (e: any) {
+        //
+        console.log(e)
+      }
     })
 
     const onPreview = () => {

+ 7 - 3
src/school/manage-teacher/manage-detail.tsx

@@ -8,6 +8,7 @@ import styles from './manage-detail.module.less'
 import MenuFunction from './menu-function'
 import iconTeacher from '@common/images/icon_teacher.png'
 import OSticky from '@/components/o-sticky'
+import { state as baseState } from '@/state'
 
 export default defineComponent({
   name: 'manage-detail',
@@ -120,9 +121,12 @@ export default defineComponent({
             class={['btnGroup', 'btnMore']}
             style={{ paddingLeft: '13px', paddingRight: '13px' }}
           >
-            <Button type="primary" round onClick={() => (state.menuStatus = true)}>
-              修改权限
-            </Button>
+            {baseState.user.data.manageAdmin && (
+              <Button type="primary" round onClick={() => (state.menuStatus = true)}>
+                修改权限
+              </Button>
+            )}
+
             <Button
               type="primary"
               round

+ 66 - 44
src/views/unit-test/examination-mode/index.tsx

@@ -123,9 +123,7 @@ export default defineComponent({
       try {
         const questionList = state.questionList || []
         const userAnswerList: any = [] // 所有题目的答案
-
-        let currentResult = false // 当前题目是否已经答题
-
+        // let currentResult = false // 当前题目是否已经答题
         questionList.forEach((question: any, index: number) => {
           // 格式化所有题目的答案
           if (question.userAnswer && question.userAnswer.length > 0) {
@@ -135,61 +133,84 @@ export default defineComponent({
             })
           }
 
-          if (index === state.currentIndex) {
-            currentResult = question.userAnswer && question.userAnswer.length > 0 ? true : false
-          }
+          // if (index === state.currentIndex) {
+          //   currentResult = question.userAnswer && question.userAnswer.length > 0 ? true : false
+          // }
         })
 
-        // 判断是否答题了
-        if (!currentResult) {
-          swipeRef.value?.next()
+        // 判断是否是最后一题
+        console.log(state.questionList.length, state.currentIndex)
+        if (state.questionList.length === state.currentIndex + 1) {
+          state.visiableSure = true
           return
         }
 
+        // 判断是否答题了 - 由于连线题
+        // if (!currentResult) {
+        //   swipeRef.value?.next()
+        //   return
+        // }
+
         state.nextStatus = true
-        // 判断是否是最后一题
-        if (state.questionList.length === state.currentIndex + 1) {
-          // api-student/studentUnitExamination/completionExamination
-          const { data } = await request.post(
-            '/api-student/studentUnitExamination/completionExamination',
-            {
-              data: {
-                answers: userAnswerList,
-                studentUnitExaminationId: state.id
-              }
-            }
-          )
-          if (data.score >= state.examDetail.passScore) {
-            state.resultStatusType = 'SUCCESS'
-            state.resultInfo = {
-              tips: '恭喜你,测验通过!',
-              score: data.score,
-              examName: data.unitExaminationName
-            }
-          } else {
-            state.resultStatusType = 'FAIL'
-            state.resultInfo = {
-              tips: '本次测验不合格!',
-              score: data.score,
-              examName: data.unitExaminationName
-            }
+        await request.post('/api-student/studentUnitExamination/submitAnswer', {
+          hideLoading: true,
+          data: {
+            answers: userAnswerList,
+            studentUnitExaminationId: state.id
           }
-          state.visiableResult = true
-        } else {
-          await request.post('/api-student/studentUnitExamination/submitAnswer', {
-            hideLoading: true,
+        })
+        swipeRef.value?.next()
+
+        state.nextStatus = false
+      } catch {
+        //
+        state.nextStatus = false
+      }
+    }
+
+    /**
+     * @description 提交最终答案
+     */
+    const onConfirmExam = async () => {
+      try {
+        const questionList = state.questionList || []
+        const userAnswerList: any = [] // 所有题目的答案
+        questionList.forEach((question: any) => {
+          // 格式化所有题目的答案
+          if (question.userAnswer && question.userAnswer.length > 0) {
+            userAnswerList.push({
+              questionId: question.id,
+              details: question.userAnswer
+            })
+          }
+        })
+        const { data } = await request.post(
+          '/api-student/studentUnitExamination/completionExamination',
+          {
             data: {
               answers: userAnswerList,
               studentUnitExaminationId: state.id
             }
-          })
-          swipeRef.value?.next()
+          }
+        )
+        if (data.status === 'A_PASS') {
+          state.resultStatusType = 'SUCCESS'
+          state.resultInfo = {
+            tips: '恭喜你,测验通过!',
+            score: data.score,
+            examName: state.examDetail.unitExaminationName
+          }
+        } else {
+          state.resultStatusType = 'FAIL'
+          state.resultInfo = {
+            tips: '本次测验不合格!',
+            score: data.score,
+            examName: state.examDetail.unitExaminationName
+          }
         }
-
-        state.nextStatus = false
+        state.visiableResult = true
       } catch {
         //
-        state.nextStatus = false
       }
     }
 
@@ -348,6 +369,7 @@ export default defineComponent({
           showCancelButton
           cancelButtonText="再等等"
           confirmButtonText="确认完成"
+          onConfirm={onConfirmExam}
         />
 
         <ODialog

+ 23 - 0
src/views/unit-test/index.module.less

@@ -58,6 +58,29 @@
       font-size: 13px;
       color: #777777;
     }
+
+    .unitInformation {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+
+      & > span {
+        flex: 0 auto;
+        flex-shrink: 0;
+        font-family: 'DINA';
+        font-size: 26px;
+        font-weight: bold;
+        color: #f44541;
+        line-height: 30px;
+        i {
+          padding-left: 2px;
+          font-style: normal;
+          font-size: 14px;
+          color: #333333;
+          line-height: 20px;
+        }
+      }
+    }
   }
 
   .unitBtnGroup {

+ 39 - 17
src/views/unit-test/index.tsx

@@ -102,6 +102,11 @@ export default defineComponent({
       }
     }
 
+    // 查看测验
+    const onUnitTestLook = (item: any) => {
+      //
+    }
+
     const onExamStart = async () => {
       try {
         await request.post('/api-student/studentUnitExamination/startExamination', {
@@ -210,34 +215,51 @@ export default defineComponent({
                     {{
                       title: () => (
                         <div class={styles.unitInformation}>
-                          <div class={styles.name}>{item.orchestraName}</div>
-                          <div class={styles.endTime}>
-                            截止时间:
-                            {dayjs(item.expiryDate || new Date()).format('YYYY-MM-DD HH:mm')}
+                          <div>
+                            <div class={styles.name}>{item.orchestraName}</div>
+                            <div class={styles.endTime}>
+                              截止时间:
+                              {dayjs(item.expiryDate || new Date()).format('YYYY-MM-DD HH:mm')}
+                            </div>
                           </div>
+                          {item.status === 'A_PASS' || item.status === 'B_NO_PASS' ? (
+                            <span>
+                              {item.score || 0}
+                              <i>分</i>
+                            </span>
+                          ) : (
+                            ''
+                          )}
+                        </div>
+                      ),
 
-                          <div class={styles.unitBtnGroup}>
-                            <Button
-                              color="#FFF0E6"
-                              round
-                              block
-                              style={{ color: '#F67146' }}
-                              onClick={() => {
-                                router.push('/test-exercise')
-                              }}
-                            >
-                              练习模式
+                      label: () => (
+                        <div class={styles.unitBtnGroup}>
+                          <Button
+                            color="#FFF0E6"
+                            round
+                            block
+                            style={{ color: '#F67146' }}
+                            onClick={() => {
+                              router.push('/test-exercise')
+                            }}
+                          >
+                            练习模式
+                          </Button>
+                          {item.status === 'A_PASS' || item.status === 'B_NO_PASS' ? (
+                            <Button type="primary" round block onClick={() => onUnitTestLook(item)}>
+                              查看测验
                             </Button>
+                          ) : (
                             <Button
                               type="primary"
                               round
                               block
-                              disabled={item.status === 'A_PASS' || item.status === 'B_NO_PASS'}
                               onClick={() => onUnitTestStart(item)}
                             >
                               {item.status === 'C_ING' ? '继续测验' : '开始测验'}
                             </Button>
-                          </div>
+                          )}
                         </div>
                       )
                     }}

+ 57 - 8
src/views/unit-test/model/keep-look-question/index.tsx

@@ -282,15 +282,16 @@ export default defineComponent({
 
     const initOptions = () => {
       const answers = props.data.answers || []
+      const userAnswer = props.data.userAnswer || [] // 用户填写的答案
       answers.forEach((answer: any) => {
         const tmp = {
-          index: answer.examinationQuestionAnswerId,
-          leftValue: answer.questionAnswer,
-          rightValue: answer.questionExtra,
-          leftType: answer.questionAnswerTypeCode || 'TXT',
-          rightType: answer.questionExtraTypeCode || 'TXT',
-          left: false,
-          right: false,
+          index: answer.examinationQuestionAnswerId, // 左边的值
+          leftValue: answer.questionAnswer, // 左边的值
+          rightValue: answer.questionExtra, // 右边的值
+          leftType: answer.questionAnswerTypeCode || 'TXT', // 左边类型
+          rightType: answer.questionExtraTypeCode || 'TXT', // 右边类型
+          left: false, // 左边是否选中
+          right: false, // 右边是否选中
           leftLocked: false, // 是否已经连线
           rightLocked: false // 是否已经连线
         }
@@ -298,7 +299,53 @@ export default defineComponent({
         state.options.push(tmp)
       })
 
-      console.log(state.options)
+      // 反显答案-初始化数据
+      userAnswer.forEach((user: any) => {
+        console.log(user)
+        const temps: any = {
+          startPoint: { x: 0, y: 0 },
+          endPoint: { x: 0, y: 0 },
+          leftIndex: 0,
+          rightIndex: 0
+        }
+        state.options.forEach((option: any) => {
+          // 左边状态
+          if (option.index === user.answerId) {
+            option.left = true
+            option.leftLocked = true
+            temps.leftIndex = option.index
+          }
+          // 右边状态
+          if (option.rightValue === user.extra) {
+            option.right = true
+            option.leftLocked = true
+            temps.rightIndex = option.index
+          }
+        })
+        state.drawLineList.push(temps)
+      })
+
+      console.log(state.drawLineList, state.options)
+      // 反显答案-连线
+      nextTick(() => {
+        state.drawLineList.forEach((draw: any) => {
+          state.selectItem = []
+          const leftObj: any = useRect(document.getElementById(draw.leftIndex + '-left') as any)
+          leftObj.index = draw.leftIndex
+          state.selectItem[0] = leftObj
+          const rightObj: any = useRect(document.getElementById(draw.leftIndex + '-right') as any)
+          rightObj.index = draw.rightIndex
+          state.selectItem[1] = rightObj
+
+          const postion = calcPoint()
+          draw.endPoint = postion.endPoint
+          draw.startPoint = postion.startPoint
+          state.selectItem = []
+        })
+        setTimeout(() => {
+          renderDrawLine(canvasRef.value)
+        }, 60)
+      })
     }
 
     onMounted(() => {
@@ -335,6 +382,7 @@ export default defineComponent({
             <div class={styles.answerItem}>
               <div
                 class={[styles.unitItem, item.left && styles.active]}
+                id={item.index + '-left'}
                 onClick={(e: any) => onLeftClick(e, item)}
               >
                 {item.leftType === 'TXT' && item.leftValue}
@@ -342,6 +390,7 @@ export default defineComponent({
               </div>
               <div
                 class={[styles.unitItem, item.right && styles.active]}
+                id={item.index + '-right'}
                 onClick={(e: any) => onRightClick(e, item)}
               >
                 {item.rightType === 'TXT' && item.rightValue}

+ 9 - 9
src/views/unit-test/unit-list/models/unit-student-list.tsx

@@ -52,15 +52,15 @@ export default defineComponent({
       },
       oldValue: ''
     })
-    const gotoMsg = () => {
-      postMessage({
-        api: 'joinChatGroup',
-        content: {
-          type: 'multi', // single 单人 multi 多人
-          id: props.item?.imGroupId
-        }
-      })
-    }
+    // const gotoMsg = () => {
+    //   postMessage({
+    //     api: 'joinChatGroup',
+    //     content: {
+    //       type: 'multi', // single 单人 multi 多人
+    //       id: props.item?.imGroupId
+    //     }
+    //   })
+    // }
     onMounted(() => {
       getList()
     })

+ 22 - 1
src/views/unit-test/unit-list/unitDetail.tsx

@@ -2,7 +2,7 @@ import OEmpty from '@/components/o-empty'
 import OHeader from '@/components/o-header'
 import OSearch from '@/components/o-search'
 import OSticky from '@/components/o-sticky'
-import { Dialog, Icon, Tab, Tabs } from 'vant'
+import { Button, Dialog, Icon, Tab, Tabs } from 'vant'
 import { defineComponent, onMounted, reactive, ref } from 'vue'
 import questIcon from '@/school/images/quest-icon.png'
 import styles from './index.module.less'
@@ -72,6 +72,27 @@ export default defineComponent({
             </Tab>
           </Tabs>
         </div>
+
+        <OSticky position="bottom">
+          <div class={['btnGroup']}>
+            <Button
+              block
+              round
+              type="primary"
+              onClick={() => {
+                router.push({
+                  path: '/unit-detail',
+                  query: {
+                    id: route.query.id
+                  }
+                })
+              }}
+            >
+              测试报告
+            </Button>
+          </div>
+        </OSticky>
+
         <Dialog
           class="exercisDetailDialog"
           v-model:show={showTip.value}