mo 2 years ago
parent
commit
a146487c41

+ 6 - 6
src/constant/index.ts

@@ -135,16 +135,16 @@ export const sendType = {
 
 // 发送状态
 export const snedStatus = {
-  WAIT: "待发送",
-  SEND: "已发送",
-  DISABLE: "已停用",
-  EXPIRE: "已失效",
+  WAIT: '待发送',
+  SEND: '已发送',
+  DISABLE: '已停用',
+  EXPIRE: '已失效'
 }
 
 // 测验状态
 export const unitTestStatus = {
-  D_NO_SUBMIT: '未完成',
+  D_NO_SUBMIT: '未提交',
   C_ING: '进行中',
   B_NO_PASS: '不合格',
   A_PASS: '合格'
-}
+}

+ 12 - 8
src/school/attendance/components/teacher-attendDetail.tsx

@@ -200,16 +200,18 @@ export default defineComponent({
                     alt=""
                   />
                 </div>
-                <div class={styles.attRang}>
+                <div
+                  class={styles.attRang}
+                  onClick={() => {
+                    setAddress(teacherAttInfo.value.signInLongitudeLatitude)
+                  }}
+                >
                   <p>
                     {teacherAttInfo.value?.signInLongitudeLatitudeStatus === 'NORMAL'
                       ? '考勤范围内'
                       : '考勤范围外'}
                   </p>
                   <p
-                    onClick={() => {
-                      setAddress(teacherAttInfo.value.signInLongitudeLatitude)
-                    }}
                     class={[
                       styles.locP,
                       teacherAttInfo.value?.signInLongitudeLatitudeStatus === 'NORMAL'
@@ -268,7 +270,12 @@ export default defineComponent({
                     alt=""
                   />
                 </div>
-                <div class={styles.attRang}>
+                <div
+                  class={styles.attRang}
+                  onClick={() => {
+                    setAddress(teacherAttInfo.value.signOutLongitudeLatitude)
+                  }}
+                >
                   <p>
                     {' '}
                     {teacherAttInfo.value?.signOutLongitudeLatitudeStatus === 'NORMAL'
@@ -276,9 +283,6 @@ export default defineComponent({
                       : '考勤范围外'}
                   </p>
                   <p
-                    onClick={() => {
-                      setAddress(teacherAttInfo.value.signOutLongitudeLatitude)
-                    }}
                     class={[
                       styles.locP,
                       teacherAttInfo.value?.signOutLongitudeLatitudeStatus === 'NORMAL'

+ 1 - 1
src/school/manage-teacher/index.tsx

@@ -26,10 +26,10 @@ import { useRouter } from 'vue-router'
 import request from '@/helpers/request'
 import { state } from '@/state'
 import OEmpty from '@/components/o-empty'
+import OFullRefresh from '@/components/o-full-refresh'
 import { manageTeacherType } from '@/constant'
 import html2canvas from 'html2canvas'
 import { promisefiyPostMessage, postMessage } from '@/helpers/native-message'
-import OFullRefresh from '@/components/o-full-refresh'
 
 export default defineComponent({
   name: 'companion-teacher',

+ 7 - 0
src/school/school-detail/eidt-school.tsx

@@ -62,6 +62,13 @@ export default defineComponent({
       //   showToast('请选择省市')
       //   return
       // }
+      if (forms.email) {
+        const r = /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/
+        if (!forms.email.match(r)) {
+          showToast('请输入正确的邮箱')
+          return
+        }
+      }
       if (!forms.address) {
         showToast('请输入详细地址')
         return

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

@@ -112,6 +112,15 @@
     }
   }
   :global {
+    .van-tabs__nav {
+      padding-right: 0;
+      padding-left: 0;
+      .van-tab {
+        &:nth-child(1) {
+          padding-left: 0;
+        }
+      }
+    }
     .van-tab__text {
       font-size: 16px;
     }

+ 4 - 1
src/views/unit-test/unit-list/models/unit-list-item.tsx

@@ -26,8 +26,11 @@ export default defineComponent({
         }
       })
     }
+    const gotoDetail = () => {
+      router.push({ path: '/unitDetail', query: { id: props.item.id } })
+    }
     return () => (
-      <div class={styles.unitItem}>
+      <div class={styles.unitItem} onClick={gotoDetail}>
         <div class={styles.unitItemTop}>
           <div class={styles.unitItemLeft}>
             <p>

+ 64 - 0
src/views/unit-test/unit-list/models/unit-student-item.tsx

@@ -0,0 +1,64 @@
+import { ActionSheet, Button, Cell, CellGroup, Icon, Image, List } from 'vant'
+import { defineComponent, reactive } from 'vue'
+import styles from './unit-student.module'
+import iconEdit from '../../images/icon-edit.png'
+import iconMessage from '@common/images/icon-muit-message.png'
+
+import { postMessage } from '@/helpers/native-message'
+import { useRouter } from 'vue-router'
+import dayjs from 'dayjs'
+export default defineComponent({
+  name: 'unit-student-item',
+  props: {
+    item: {
+      type: Object,
+      default: () => {}
+    }
+  },
+  setup(props) {
+    const router = useRouter()
+    const gotoMsg = () => {
+      postMessage({
+        api: 'joinChatGroup',
+        content: {
+          type: 'multi', // single 单人 multi 多人
+          id: props.item?.imGroupId
+        }
+      })
+    }
+    return () => (
+      <div class={styles.unitItem}>
+        <div class={styles.unitItemTop}>
+          <div class={styles.unitItemLeft}>
+            <p>
+              {' '}
+              <Image src={iconEdit} class={styles.editImg} />
+              {props.item?.classGroupName || '--'}
+            </p>
+            <span>
+              {dayjs(props.item?.createTime).format('YYYY-MM-DD HH:mm')} 至{' '}
+              {dayjs(props.item?.expiryDate).format('YYYY-MM-DD HH:mm')}
+            </span>
+          </div>
+          <div class={styles.unitItemICon} onClick={gotoMsg}>
+            <Image src={iconMessage} class={styles.msgImg}></Image>
+          </div>
+        </div>
+        <div class={[styles.unitItemInfo]}>
+          <div class={[styles.unitItemInfoWrap, styles.unitItemInfoWrapLine]}>
+            <p class={styles.unitItemInfoMain}>{props.item?.commitNum || 0}</p>
+            <p class={styles.unitItemInfosub}>提交人数</p>
+          </div>
+          <div class={[styles.unitItemInfoWrap]}>
+            <p class={[styles.unitItemInfoMain, styles.orange]}>{props.item?.passNum || 0}</p>
+            <p class={styles.unitItemInfosub}>达标人数</p>
+          </div>
+        </div>
+        <div class={styles.unitItemOrchestra}>
+          <p>{props.item?.orchestraName || '--'}</p>
+          <Icon class={styles.arrow} name="arrow"></Icon>
+        </div>
+      </div>
+    )
+  }
+})

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

@@ -0,0 +1,183 @@
+import {
+  ActionSheet,
+  Button,
+  Cell,
+  CellGroup,
+  Radio,
+  CheckboxGroup,
+  Icon,
+  Image,
+  List,
+  RadioGroup,
+  Tag
+} from 'vant'
+import { defineComponent, onMounted, reactive } from 'vue'
+import styles from './unit-student.module.less'
+import iconEdit from '../../images/icon-edit.png'
+import iconMessage from '@common/images/icon-muit-message.png'
+import iconTeacher from '@common/images/icon_teacher.png'
+import { postMessage } from '@/helpers/native-message'
+import { useRoute, useRouter } from 'vue-router'
+import OEmpty from '@/components/o-empty'
+import OFullRefresh from '@/components/o-full-refresh'
+import dayjs from 'dayjs'
+import request from '@/helpers/request'
+import { unitTestStatus } from '@/constant'
+export default defineComponent({
+  name: 'unit-student-list',
+  props: {
+    item: {
+      type: Object,
+      default: () => {}
+    }
+  },
+  setup(props) {
+    const router = useRouter()
+    const route = useRoute()
+    const searchList = reactive({
+      classGroupUnitExaminationId: route.query.id,
+      status: '',
+      page: 1
+    })
+    const form = reactive({
+      list: [],
+      listState: {
+        dataShow: true, // 判断是否有数据
+        loading: false,
+        finished: false,
+        refreshing: false,
+        height: 0 // 页面头部高度,为了处理下拉刷新用的
+      }
+    })
+    const gotoMsg = () => {
+      postMessage({
+        api: 'joinChatGroup',
+        content: {
+          type: 'multi', // single 单人 multi 多人
+          id: props.item?.imGroupId
+        }
+      })
+    }
+    onMounted(() => {
+      getList()
+    })
+    const getList = async () => {
+      try {
+        const res = await request.post('/api-teacher/studentUnitExamination/studentDetail', {
+          data: {
+            ...searchList
+          },
+          requestType: 'form'
+        })
+        form.listState.loading = false
+        form.listState.refreshing = false
+        const result = res.data || {}
+        // 处理重复请求数据
+        if (form.list.length > 0 && result.current === 1) {
+          return
+        }
+        form.list = form.list.concat(result[1] || [])
+        form.listState.finished = result.current >= result.pages
+        searchList.page = result.current + 1
+        form.listState.dataShow = form.list.length > 0
+      } catch {
+        form.listState.dataShow = false
+        form.listState.finished = true
+        form.listState.refreshing = false
+      }
+    }
+
+    const onSearch = () => {
+      searchList.page = 1
+      form.list = []
+      form.listState.dataShow = true // 判断是否有数据
+      form.listState.loading = false
+      form.listState.finished = false
+      getList()
+    }
+    return () => (
+      <div class={styles.unitList}>
+        <RadioGroup checked-color="#FF8057" v-model={searchList.status} direction="horizontal">
+          <Tag
+            size="large"
+            type="primary"
+            color={searchList.status !== 'A_PASS' ? '#EAEAEA' : '#FF8057'}
+            textColor={searchList.status !== 'A_PASS' ? '#AAA' : '#FFF'}
+            class={styles.radioSection}
+          >
+            <Radio class={styles.radioItem} name={'A_PASS'}></Radio>
+            {unitTestStatus['A_PASS']}
+          </Tag>
+          <Tag
+            size="large"
+            type="primary"
+            color={searchList.status !== 'B_NO_PASS' ? '#EAEAEA' : '#FF8057'}
+            textColor={searchList.status !== 'B_NO_PASS' ? '#AAA' : '#FFF'}
+            class={styles.radioSection}
+          >
+            <Radio class={styles.radioItem} name={'B_NO_PASS'}></Radio>{' '}
+            {unitTestStatus['B_NO_PASS']}
+          </Tag>
+          <Tag
+            size="large"
+            type="primary"
+            color={searchList.status !== 'D_NO_SUBMIT' ? '#EAEAEA' : '#FF8057'}
+            textColor={searchList.status !== 'D_NO_SUBMIT' ? '#AAA' : '#FFF'}
+            class={styles.radioSection}
+          >
+            <Radio class={styles.radioItem} name={'D_NO_SUBMIT'}></Radio>
+            {unitTestStatus['D_NO_SUBMIT']}
+          </Tag>
+        </RadioGroup>
+        {form.listState.dataShow ? (
+          <OFullRefresh
+            v-model:modelValue={form.listState.refreshing}
+            onRefresh={onSearch}
+            style={{
+              minHeight: `calc(100vh - ${form.listState.height}px)`
+            }}
+          >
+            <List
+              v-model:loading={form.listState.loading}
+              finished={form.listState.finished}
+              finishedText=" "
+              class={[styles.liveList]}
+              onLoad={getList}
+              immediateCheck={false}
+            >
+              {form.list.map((item: any) => (
+                <Cell center class={styles.manageCell}>
+                  {{
+                    icon: () => (
+                      <Image class={styles.img} src={item.avatar ? item.avatar : iconTeacher} />
+                    ),
+                    title: () => (
+                      <div class={styles.content}>
+                        <div class={styles.TagWrap}>
+                          {' '}
+                          <p class={[styles.name, 'van-ellipsis']}>
+                            {item.studentName ? item.studentName : '--'}
+                          </p>
+                          <div class={[styles.studentTag]}>{unitTestStatus[item.status]}</div>
+                        </div>
+
+                        <p class={styles.phone}>{item.submitTime}</p>
+                      </div>
+                    )
+                    // value: () => (
+                    //   <span class={[styles.status, item.status === 'LOCKED' ? styles.frozen : '']}>
+                    //     {manageTeacherType[item.status]}
+                    //   </span>
+                    // )
+                  }}
+                </Cell>
+              ))}
+            </List>
+          </OFullRefresh>
+        ) : (
+          <OEmpty btnStatus={false} tips="暂无学员" />
+        )}
+      </div>
+    )
+  }
+})

+ 81 - 0
src/views/unit-test/unit-list/models/unit-student.module.less

@@ -0,0 +1,81 @@
+.radioSection {
+  position: relative;
+  min-width: 32px;
+  justify-content: center;
+}
+
+.radioItem {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  opacity: 0;
+}
+
+.radioSection + .radioSection {
+  margin-left: 12px;
+}
+
+.unitList {
+  padding-top: 12px;
+  .liveList {
+    margin-top: 12px;
+    border-radius: 10px;
+    overflow: hidden;
+  }
+  .manageCell {
+    padding: 15px 13px;
+    .TagWrap {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      .studentTag {
+        background-color: #ff8057;
+        border-radius: 4px;
+        line-height: 19px;
+        padding: 0 8px;
+        color: #fff;
+        margin-left: 6px;
+      }
+      .A_PASS {
+        background-color: #ff8057;
+      }
+      .D_NO_SUBMIT {
+        background-color: #8f80ff;
+      }
+      .B_NO_PASS {
+        background-color: #ff5c5f;
+      }
+    }
+    .img {
+      width: 48px;
+      height: 48px;
+      overflow: hidden;
+      border-radius: 50%;
+      margin-right: 10px;
+    }
+
+    .name {
+      font-size: 16px;
+      font-weight: 500;
+      color: #333333;
+      line-height: 22px;
+      max-width: 200px;
+    }
+    .phone {
+      font-size: 14px;
+      color: #777777;
+      line-height: 20px;
+    }
+
+    .status {
+      font-size: 16px;
+      font-weight: 500;
+      color: #333333;
+    }
+    .frozen {
+      color: #f44541;
+    }
+  }
+}

+ 16 - 5
src/views/unit-test/unit-list/unitDetail.tsx

@@ -18,8 +18,9 @@ import {
 import { defineComponent, onMounted, reactive, ref } from 'vue'
 import questIcon from '@/school/images/quest-icon.png'
 import styles from './index.module.less'
-import { useRouter } from 'vue-router'
+import { useRoute, useRouter } from 'vue-router'
 import UnitListItem from './models/unit-list-item'
+import UnitStudentList from './models/unit-student-list'
 import OFullRefresh from '@/components/o-full-refresh'
 //
 import request from '@/helpers/request'
@@ -27,12 +28,22 @@ export default defineComponent({
   name: 'unitDetail',
   setup() {
     const router = useRouter()
+    const route = useRoute()
     const form = reactive({})
     const refreshing = ref(false)
     const loading = ref(false)
     const activeName = ref('one')
     const showTip = ref(false)
-    onMounted(() => {})
+    const getDetail = async () => {
+      try {
+        const res = await request.get('/api-teacher/unitExamination/detail', {
+          params: { unitExaminationId: route.query.id }
+        })
+      } catch (e) {}
+    }
+    onMounted(() => {
+      getDetail()
+    })
 
     return () => (
       <div class={styles.unitDetail}>
@@ -57,13 +68,13 @@ export default defineComponent({
             shrink
           >
             <Tab name="one" title="I类学生">
-              11111
+              <UnitStudentList></UnitStudentList>
             </Tab>
             <Tab name="two" title="II类学生">
-              22222
+              <UnitStudentList></UnitStudentList>
             </Tab>
             <Tab name="three" title="III类学生">
-              3333333
+              <UnitStudentList></UnitStudentList>
             </Tab>
           </Tabs>
         </div>