lex %!s(int64=2) %!d(string=hai) anos
pai
achega
a71ae06ccb

+ 1 - 1
src/helpers/toolsValidate.ts

@@ -421,7 +421,7 @@ export const checkFile = (fileValue: string, type: string) => {
     }
   }
   if (type == 'image') {
-    if (!/(.*)\.(gif|jpg|jpeg|png|GIF|JPG|PNG)$/.test(fileValueSuffix)) {
+    if (!/(.*)\.(gif|jpg|jpeg|png|GIF|JPG|PNG|svg)$/.test(fileValueSuffix)) {
       //根据后缀,判断是否符合图片格式
       return false;
     }

+ 19 - 0
src/views/lesson-list/components/component.module.less

@@ -155,6 +155,25 @@
       color: #999999;
     }
   }
+
+  .skeletonGroup {
+    padding: 12px;
+    width: 100%;
+    background: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    flex-wrap: wrap;
+  }
+
+  .skeletonItem {
+    margin-top: 0;
+    margin-bottom: 9px;
+    width: 158px !important;
+    background: #F6F6F6;
+    border-radius: 6px;
+    height: 76px;
+  }
 }
 
 .practice-list {

+ 67 - 58
src/views/lesson-list/components/evaluating.tsx

@@ -6,6 +6,7 @@ import iconMember from '../images/icon-member.png';
 import DetailModal from '../detail-modal';
 import request from '@/helpers/request';
 import MEmpty from '@/components/m-empty';
+import SkeletonComponentModal from './skeleton-component-modal';
 
 export default defineComponent({
   name: 'evaluating-list',
@@ -20,7 +21,8 @@ export default defineComponent({
       showPopup: false,
       list: [] as any[],
       dataShow: true,
-      detail: {} as any
+      detail: {} as any,
+      loading: false
     });
 
     const getList = async () => {
@@ -34,32 +36,37 @@ export default defineComponent({
           }
         );
         forms.list = data.rows || [];
-        forms.dataShow = forms.list.length ? true : false;
       } catch {
         //
+      } finally {
+        forms.dataShow = forms.list.length ? true : false;
+        forms.loading = false;
       }
     };
 
     const onDetail = async (item: any) => {
       try {
-        const { data } = await request.post(
-          '/api-web/schoolStudentHomework/queryStudentLessonDetail',
-          {
-            hideLoading: false,
-            data: {
-              lessonExaminationId: props.lessonExaminationId,
-              userId: item.userId
+        if (forms.detail.userId != item.userId) {
+          const { data } = await request.post(
+            '/api-web/schoolStudentHomework/queryStudentLessonDetail',
+            {
+              hideLoading: false,
+              data: {
+                lessonExaminationId: props.lessonExaminationId,
+                userId: item.userId
+              }
             }
-          }
-        );
-        forms.detail = {
-          avatar: item.avatar,
-          memberFlag: item.memberFlag,
-          username: item.username,
-          subjectName: item.subjectName,
-          trainingScore: item.trainingScore,
-          list: data || []
-        };
+          );
+          forms.detail = {
+            userId: item.userId,
+            avatar: item.avatar,
+            memberFlag: item.memberFlag,
+            username: item.username,
+            subjectName: item.subjectName,
+            trainingScore: item.trainingScore,
+            list: data || []
+          };
+        }
         forms.showPopup = true;
       } catch {
         //
@@ -71,45 +78,47 @@ export default defineComponent({
     });
     return () => (
       <div class={styles['practice-list']}>
-        {forms.dataShow ? (
-          forms.list.map((item: any) => (
-            <Cell center isLink onClick={() => onDetail(item)}>
-              {{
-                icon: () => (
-                  <div class={styles.iconGroup}>
-                    <Image
-                      src={item.avatar || iconStudent}
-                      class={styles.iconStudent}
-                      fit="contain"
-                    />
-                    {item.memberFlag && (
-                      <Icon name={iconMember} class={styles.iconMember} />
-                    )}
-                  </div>
-                ),
-                title: () => (
-                  <div class={styles.userInfo}>
-                    <p class={styles.name}>{item.username}</p>
-                    <span>{item.subjectName}</span>
-                  </div>
-                ),
-                value: () => (
-                  <div
-                    class={[
-                      styles.after,
-                      item.trainingScore >= 60 ? styles.success : styles.error
-                    ]}>
-                    {item.trainingScore}分
-                  </div>
-                )
-              }}
-            </Cell>
-          ))
-        ) : (
-          <div class={styles.emptyContainer}>
-            <MEmpty description="暂无数据" />
-          </div>
-        )}
+        <SkeletonComponentModal v-model:show={forms.loading}>
+          {forms.dataShow ? (
+            forms.list.map((item: any) => (
+              <Cell center isLink onClick={() => onDetail(item)}>
+                {{
+                  icon: () => (
+                    <div class={styles.iconGroup}>
+                      <Image
+                        src={item.avatar || iconStudent}
+                        class={styles.iconStudent}
+                        fit="contain"
+                      />
+                      {item.memberFlag && (
+                        <Icon name={iconMember} class={styles.iconMember} />
+                      )}
+                    </div>
+                  ),
+                  title: () => (
+                    <div class={styles.userInfo}>
+                      <p class={styles.name}>{item.username}</p>
+                      <span>{item.subjectName}</span>
+                    </div>
+                  ),
+                  value: () => (
+                    <div
+                      class={[
+                        styles.after,
+                        item.trainingScore >= 60 ? styles.success : styles.error
+                      ]}>
+                      {item.trainingScore}分
+                    </div>
+                  )
+                }}
+              </Cell>
+            ))
+          ) : (
+            <div class={styles.emptyContainer}>
+              <MEmpty description="暂无数据" />
+            </div>
+          )}
+        </SkeletonComponentModal>
 
         <Popup
           v-model:show={forms.showPopup}

+ 39 - 33
src/views/lesson-list/components/practice.tsx

@@ -5,6 +5,7 @@ import iconStudent from '@/common/images/icon-student-default.png';
 import iconMember from '../images/icon-member.png';
 import DetailModal from '../detail-modal';
 import request from '@/helpers/request';
+import SkeletonComponentModal from './skeleton-component-modal';
 
 export default defineComponent({
   name: 'practice-list',
@@ -21,7 +22,8 @@ export default defineComponent({
       showPopup: false,
       list: [] as any[],
       dataShow: true,
-      detail: {} as any
+      detail: {} as any,
+      loading: true
     });
 
     const getList = async () => {
@@ -36,9 +38,11 @@ export default defineComponent({
           }
         );
         forms.list = data || [];
-        forms.dataShow = forms.list.length ? true : false;
       } catch {
         //
+      } finally {
+        forms.dataShow = forms.list.length ? true : false;
+        forms.loading = false;
       }
     };
 
@@ -63,37 +67,39 @@ export default defineComponent({
     });
     return () => (
       <div class={styles['practice-list']}>
-        {forms.list.map((item: any) => (
-          <Cell center isLink onClick={() => onDetail(item)}>
-            {{
-              icon: () => (
-                <div class={styles.iconGroup}>
-                  <Image
-                    src={item.avatar || iconStudent}
-                    class={styles.iconStudent}
-                    fit="contain"
-                  />
-                  <Icon name={iconMember} class={styles.iconMember} />
-                </div>
-              ),
-              title: () => (
-                <div class={styles.userInfo}>
-                  <p class={styles.name}>{item.userName}</p>
-                  <span>{item.subjectName}</span>
-                </div>
-              ),
-              value: () => (
-                <div
-                  class={[
-                    styles.after,
-                    item.finishFlag ? styles.success : styles.error
-                  ]}>
-                  {item.finishFlag ? '完成' : '未完成'}
-                </div>
-              )
-            }}
-          </Cell>
-        ))}
+        <SkeletonComponentModal v-model:loading={forms.loading}>
+          {forms.list.map((item: any) => (
+            <Cell center isLink onClick={() => onDetail(item)}>
+              {{
+                icon: () => (
+                  <div class={styles.iconGroup}>
+                    <Image
+                      src={item.avatar || iconStudent}
+                      class={styles.iconStudent}
+                      fit="contain"
+                    />
+                    <Icon name={iconMember} class={styles.iconMember} />
+                  </div>
+                ),
+                title: () => (
+                  <div class={styles.userInfo}>
+                    <p class={styles.name}>{item.userName}</p>
+                    <span>{item.subjectName}</span>
+                  </div>
+                ),
+                value: () => (
+                  <div
+                    class={[
+                      styles.after,
+                      item.finishFlag ? styles.success : styles.error
+                    ]}>
+                    {item.finishFlag ? '完成' : '未完成'}
+                  </div>
+                )
+              }}
+            </Cell>
+          ))}
+        </SkeletonComponentModal>
 
         <Popup
           v-model:show={forms.showPopup}

+ 80 - 0
src/views/lesson-list/components/skeleton-component-modal.tsx

@@ -0,0 +1,80 @@
+import {
+  Cell,
+  CellGroup,
+  Skeleton,
+  SkeletonImage,
+  SkeletonParagraph
+} from 'vant';
+import { defineComponent, onMounted, reactive, watch } from 'vue';
+import styles from './component.module.less';
+
+export default defineComponent({
+  name: 'skeleton-modal',
+  props: {
+    show: {
+      type: Boolean,
+      default: false
+    },
+    showCount: {
+      type: Array,
+      default: () => [1, 2, 3, 4, 5]
+    }
+  },
+  setup(props, { slots }) {
+    const forms = reactive({
+      loading: false
+    });
+
+    onMounted(() => {
+      forms.loading = props.show;
+    });
+
+    watch(
+      () => props.show,
+      () => {
+        forms.loading = props.show;
+      }
+    );
+    return () => (
+      <Skeleton loading={forms.loading} style="flex-wrap: wrap">
+        {{
+          template: () => (
+            <div
+              style={{
+                height: `calc(100vh - var(--header-height))`,
+                overflow: 'hidden',
+                width: '100%'
+              }}>
+              {props.showCount.map(() => (
+                <Cell center>
+                  {{
+                    icon: () => (
+                      <div class={styles.iconGroup}>
+                        <SkeletonImage class={styles.iconStudent} />
+                      </div>
+                    ),
+                    title: () => (
+                      <div class={styles.userInfo}>
+                        <SkeletonParagraph
+                          class={styles.name}
+                          rowWidth={'60%'}
+                        />
+                        <SkeletonParagraph rowWidth={'40%'} />
+                      </div>
+                    ),
+                    value: () => (
+                      <div class={styles.after} style={{ width: '80px' }}>
+                        <SkeletonParagraph rowWidth={'100%'} />
+                      </div>
+                    )
+                  }}
+                </Cell>
+              ))}
+            </div>
+          ),
+          default: () => slots.default && slots.default()
+        }}
+      </Skeleton>
+    );
+  }
+});

+ 49 - 43
src/views/lesson-list/components/student.tsx

@@ -10,6 +10,7 @@ import request from '@/helpers/request';
 import { useRoute } from 'vue-router';
 import { clockingIn } from '@/helpers/constant';
 import MEmpty from '@/components/m-empty';
+import SkeletonComponentModal from './skeleton-component-modal';
 
 export default defineComponent({
   name: 'student-list',
@@ -18,6 +19,7 @@ export default defineComponent({
     const forms = reactive({
       courseId: route.query.courseId,
       dataShow: true,
+      loading: true,
       list: [] as any[]
     });
 
@@ -32,9 +34,11 @@ export default defineComponent({
           }
         );
         forms.list = data || [];
-        forms.dataShow = forms.list.length ? true : false;
       } catch {
         //
+      } finally {
+        forms.dataShow = forms.list.length ? true : false;
+        forms.loading = false;
       }
     };
 
@@ -44,48 +48,50 @@ export default defineComponent({
 
     return () => (
       <div class={styles['student-list']}>
-        {forms.dataShow ? (
-          forms.list.map((item: any) => (
-            <Cell center>
-              {{
-                icon: () => (
-                  <div class={styles.iconGroup}>
-                    <Image
-                      src={item.studentAvatar || iconStudent}
-                      class={styles.iconStudent}
-                      fit="contain"
-                    />
-                    {item.memberFlag && (
-                      <Icon name={iconMember} class={styles.iconMember} />
-                    )}
-                  </div>
-                ),
-                title: () => (
-                  <div class={styles.userInfo}>
-                    <p class={styles.name}>{item.studentName}</p>
-                    <span class={styles[item.attendanceStatus]}>
-                      {clockingIn[item.attendanceStatus]}
-                    </span>
-                  </div>
-                ),
-                value: () => (
-                  <div class={styles.after}>
-                    {item.qualifiedFlag ? (
-                      <img src={iconStandard} class={styles.standard} />
-                    ) : (
-                      <img src={iconNotStandard} class={styles.notStandard} />
-                    )}
-                    <p class={styles.txt}>课后评价</p>
-                  </div>
-                )
-              }}
-            </Cell>
-          ))
-        ) : (
-          <div class={styles.emptyContainer}>
-            <MEmpty description="暂无数据" />
-          </div>
-        )}
+        <SkeletonComponentModal v-model:show={forms.loading}>
+          {forms.dataShow ? (
+            forms.list.map((item: any) => (
+              <Cell center>
+                {{
+                  icon: () => (
+                    <div class={styles.iconGroup}>
+                      <Image
+                        src={item.studentAvatar || iconStudent}
+                        class={styles.iconStudent}
+                        fit="contain"
+                      />
+                      {item.memberFlag && (
+                        <Icon name={iconMember} class={styles.iconMember} />
+                      )}
+                    </div>
+                  ),
+                  title: () => (
+                    <div class={styles.userInfo}>
+                      <p class={styles.name}>{item.studentName}</p>
+                      <span class={styles[item.attendanceStatus]}>
+                        {clockingIn[item.attendanceStatus]}
+                      </span>
+                    </div>
+                  ),
+                  value: () => (
+                    <div class={styles.after}>
+                      {item.qualifiedFlag ? (
+                        <img src={iconStandard} class={styles.standard} />
+                      ) : (
+                        <img src={iconNotStandard} class={styles.notStandard} />
+                      )}
+                      <p class={styles.txt}>课后评价</p>
+                    </div>
+                  )
+                }}
+              </Cell>
+            ))
+          ) : (
+            <div class={styles.emptyContainer}>
+              <MEmpty description="暂无数据" />
+            </div>
+          )}
+        </SkeletonComponentModal>
       </div>
     );
   }

+ 146 - 109
src/views/lesson-list/components/teacher.tsx

@@ -1,4 +1,4 @@
-import { Cell, Icon, Image } from 'vant';
+import { Cell, Icon, Image, Skeleton, SkeletonParagraph } from 'vant';
 import { defineComponent, onMounted, reactive } from 'vue';
 import styles from './component.module.less';
 import iconTeacher from '@/common/images/icon-teacher-default.png';
@@ -16,7 +16,8 @@ export default defineComponent({
     const forms = reactive({
       courseId: route.query.courseId,
       teacherId: route.query.teacherId,
-      detail: {} as any
+      detail: {} as any,
+      loading: true
     });
 
     // schoolTeacherAttendance/getCourseTeacherAttendance
@@ -47,6 +48,8 @@ export default defineComponent({
         forms.detail = data || {};
       } catch {
         //
+      } finally {
+        forms.loading = false;
       }
     };
 
@@ -56,117 +59,151 @@ export default defineComponent({
 
     return () => (
       <div class={styles['teacher-list']}>
-        <Cell center>
-          <div class={styles.detailGroup}>
-            <div class={styles.detailItem}>
-              <div class={styles.detailStatus}>
-                <span
-                  class={[
-                    styles.statusName,
-                    forms.detail.signInStatus ? '' : styles.error
-                  ]}>
-                  {forms.detail.signInStatus ? '正常' : '异常'}
-                </span>
-                <img
-                  src={forms.detail.signInStatus ? iconSuccess : iconWarn}
-                  class={styles.img}
+        <Skeleton loading={forms.loading}>
+          {{
+            template: () => (
+              <div class={styles.skeletonGroup}>
+                <SkeletonParagraph
+                  class={styles.skeletonItem}
+                  rowWidth={'50%'}
                 />
-              </div>
-              <div class={styles.sign}>
-                <span class={styles.signTime}>
-                  签到时间{' '}
-                  {forms.detail.signInTime
-                    ? dayjs(forms.detail.signInTime).format('HH:mm:ss')
-                    : '--'}
-                </span>
-              </div>
-            </div>
-            {forms.detail.teachMode === 'OFFLINE' ? (
-              <div class={styles.detailItem}>
-                <div class={styles.detailStatus}>
-                  <span
-                    class={[
-                      styles.statusName,
-                      forms.detail.signInAddressStatus ? '' : styles.error
-                    ]}>
-                    {forms.detail.signInAddressStatus ? '正常' : '异常'}
-                  </span>
-                  <img
-                    src={
-                      forms.detail.signInAddressStatus ? iconSuccess : iconWarn
-                    }
-                    class={styles.img}
-                  />
-                </div>
-                <div class={styles.sign}>
-                  <span class={styles.signTime}>签到地点</span>
-                  <span
-                    class={styles.locate}
-                    onClick={() => onAddressGps(forms.detail)}>
-                    查看定位
-                    <Icon name="arrow" class={styles.iconArrow} />
-                  </span>
-                </div>
-              </div>
-            ) : (
-              ''
-            )}
-
-            <div class={styles.detailItem}>
-              <div class={styles.detailStatus}>
-                <span
-                  class={[
-                    styles.statusName,
-                    forms.detail.signOutStatus ? '' : styles.error
-                  ]}>
-                  {forms.detail.signOutStatus ? '正常' : '异常'}
-                </span>
-                <img
-                  src={forms.detail.signOutStatus ? iconSuccess : iconWarn}
-                  class={styles.img}
+                <SkeletonParagraph
+                  class={styles.skeletonItem}
+                  rowWidth={'50%'}
+                />
+                <SkeletonParagraph
+                  class={styles.skeletonItem}
+                  rowWidth={'50%'}
+                />
+                <SkeletonParagraph
+                  class={styles.skeletonItem}
+                  rowWidth={'50%'}
                 />
               </div>
-              <div class={styles.sign}>
-                <span class={styles.signTime}>
-                  签退时间{' '}
-                  {forms.detail.signOutTime
-                    ? dayjs(forms.detail.signOutTime).format('HH:mm:ss')
-                    : '--'}
-                </span>
-              </div>
-            </div>
-            {forms.detail.teachMode === 'OFFLINE' ? (
-              <div class={styles.detailItem}>
-                <div class={styles.detailStatus}>
-                  <span
-                    class={[
-                      styles.statusName,
-                      forms.detail.signOutAddressStatus ? '' : styles.error
-                    ]}>
-                    {forms.detail.signOutAddressStatus ? '正常' : '异常'}
-                  </span>
-                  <img
-                    src={
-                      forms.detail.signOutAddressStatus ? iconSuccess : iconWarn
-                    }
-                    class={styles.img}
-                  />
-                </div>
-                <div class={styles.sign}>
-                  <span class={styles.signTime}>签到地点</span>
-                  <span
-                    class={styles.locate}
-                    onClick={() => onAddressGps(forms.detail)}>
-                    查看定位
-                    <Icon name="arrow" class={styles.iconArrow} />
-                  </span>
+            ),
+            default: () => (
+              <Cell center>
+                <div class={styles.detailGroup}>
+                  <div class={styles.detailItem}>
+                    <div class={styles.detailStatus}>
+                      <span
+                        class={[
+                          styles.statusName,
+                          forms.detail.signInStatus ? '' : styles.error
+                        ]}>
+                        {forms.detail.signInStatus ? '正常' : '异常'}
+                      </span>
+                      <img
+                        src={forms.detail.signInStatus ? iconSuccess : iconWarn}
+                        class={styles.img}
+                      />
+                    </div>
+                    <div class={styles.sign}>
+                      <span class={styles.signTime}>
+                        签到时间{' '}
+                        {forms.detail.signInTime
+                          ? dayjs(forms.detail.signInTime).format('HH:mm:ss')
+                          : '--'}
+                      </span>
+                    </div>
+                  </div>
+                  {forms.detail.teachMode === 'OFFLINE' ? (
+                    <div class={styles.detailItem}>
+                      <div class={styles.detailStatus}>
+                        <span
+                          class={[
+                            styles.statusName,
+                            forms.detail.signInAddressStatus ? '' : styles.error
+                          ]}>
+                          {forms.detail.signInAddressStatus ? '正常' : '异常'}
+                        </span>
+                        <img
+                          src={
+                            forms.detail.signInAddressStatus
+                              ? iconSuccess
+                              : iconWarn
+                          }
+                          class={styles.img}
+                        />
+                      </div>
+                      <div class={styles.sign}>
+                        <span class={styles.signTime}>签到地点</span>
+                        <span
+                          class={styles.locate}
+                          onClick={() => onAddressGps(forms.detail)}>
+                          查看定位
+                          <Icon name="arrow" class={styles.iconArrow} />
+                        </span>
+                      </div>
+                    </div>
+                  ) : (
+                    ''
+                  )}
+
+                  <div class={styles.detailItem}>
+                    <div class={styles.detailStatus}>
+                      <span
+                        class={[
+                          styles.statusName,
+                          forms.detail.signOutStatus ? '' : styles.error
+                        ]}>
+                        {forms.detail.signOutStatus ? '正常' : '异常'}
+                      </span>
+                      <img
+                        src={
+                          forms.detail.signOutStatus ? iconSuccess : iconWarn
+                        }
+                        class={styles.img}
+                      />
+                    </div>
+                    <div class={styles.sign}>
+                      <span class={styles.signTime}>
+                        签退时间{' '}
+                        {forms.detail.signOutTime
+                          ? dayjs(forms.detail.signOutTime).format('HH:mm:ss')
+                          : '--'}
+                      </span>
+                    </div>
+                  </div>
+                  {forms.detail.teachMode === 'OFFLINE' ? (
+                    <div class={styles.detailItem}>
+                      <div class={styles.detailStatus}>
+                        <span
+                          class={[
+                            styles.statusName,
+                            forms.detail.signOutAddressStatus
+                              ? ''
+                              : styles.error
+                          ]}>
+                          {forms.detail.signOutAddressStatus ? '正常' : '异常'}
+                        </span>
+                        <img
+                          src={
+                            forms.detail.signOutAddressStatus
+                              ? iconSuccess
+                              : iconWarn
+                          }
+                          class={styles.img}
+                        />
+                      </div>
+                      <div class={styles.sign}>
+                        <span class={styles.signTime}>签到地点</span>
+                        <span
+                          class={styles.locate}
+                          onClick={() => onAddressGps(forms.detail)}>
+                          查看定位
+                          <Icon name="arrow" class={styles.iconArrow} />
+                        </span>
+                      </div>
+                    </div>
+                  ) : (
+                    ''
+                  )}
                 </div>
-              </div>
-            ) : (
-              ''
-            )}
-          </div>
-        </Cell>
+              </Cell>
+            )
+          }}
+        </Skeleton>
       </div>
     );
   }

BIN=BIN
src/views/lesson-list/detail-modal/images/bottom.png


+ 23 - 21
src/views/lesson-list/detail.tsx

@@ -127,29 +127,31 @@ export default defineComponent({
           </CellGroup>
         </SkeletonIndexModal>
 
-        <div class={styles.tabs}>
-          <Tabs v-model:active={forms.tabs} lazyRender>
-            <Tab title="学员考勤" name="student">
-              <Student />
-            </Tab>
-            <Tab title="老师考勤" name="teacher">
-              <Teacher />
-            </Tab>
-            {forms.headerDetail.homeworkType === 'HOMEWORK' && (
-              <Tab title="练习内容" name="practice">
-                <Practice courseId={forms.courseId} />
+        {forms.headerDetail.courseId && (
+          <div class={styles.tabs}>
+            <Tabs v-model:active={forms.tabs} lazyRender>
+              <Tab title="学员考勤" name="student">
+                <Student />
               </Tab>
-            )}
-
-            {forms.headerDetail.homeworkType === 'LESSON' && (
-              <Tab title="评测内容" name="evaluating">
-                <Evaluating
-                  lessonExaminationId={forms.headerDetail.homeworkId}
-                />
+              <Tab title="老师考勤" name="teacher">
+                <Teacher />
               </Tab>
-            )}
-          </Tabs>
-        </div>
+              {forms.headerDetail.homeworkType === 'HOMEWORK' && (
+                <Tab title="练习内容" name="practice">
+                  <Practice courseId={forms.courseId} />
+                </Tab>
+              )}
+
+              {forms.headerDetail.homeworkType === 'LESSON' && (
+                <Tab title="评测内容" name="evaluating">
+                  <Evaluating
+                    lessonExaminationId={forms.headerDetail.homeworkId}
+                  />
+                </Tab>
+              )}
+            </Tabs>
+          </div>
+        )}
       </>
     );
   }

+ 57 - 13
src/views/mass-message/components/contacts.tsx

@@ -1,11 +1,13 @@
 import { Cell, Checkbox, CheckboxGroup, Icon, Image, Sticky } from 'vant';
-import { defineComponent, reactive, ref, watch } from 'vue';
+import { defineComponent, onMounted, reactive, ref, watch } from 'vue';
 import styles from '../index.module.less';
-import badge1 from '../images/badge-1.png';
-import class1 from '../images/1.png';
+// import badge1 from '../images/badge-1.png';
 import MSearch from '@/components/m-search';
 import activeButtonIcon from '@/common/images/icon-check-active.png';
 import inactiveButtonIcon from '@/common/images/icon-check.png';
+import iconStudent from '@/common/images/icon-student-default.png';
+import iconTeacher from '@/common/images/icon-teacher-default.png';
+import request from '@/helpers/request';
 export default defineComponent({
   name: 'contacts-modal',
   props: {
@@ -44,8 +46,12 @@ export default defineComponent({
         if (forms.check.includes(item.id)) {
           list.push({
             id: item.id,
-            value: item.nickname,
-            avatar: item.avatar
+            value: item.friendNickname,
+            text: item.memo,
+            avatar:
+              item.friend.avatar || item.friend.userType === 'TEACHER'
+                ? iconTeacher
+                : iconStudent
           });
         }
       });
@@ -56,9 +62,40 @@ export default defineComponent({
       () => props.height,
       () => {
         forms.height = props.height;
-        console.log(forms.height);
       }
     );
+
+    watch(
+      () => props.selectItem,
+      () => {
+        initSelectItem();
+      },
+      { deep: true }
+    );
+
+    const initSelectItem = () => {
+      const selectItem = props.selectItem || [];
+      const temp: any = [];
+      selectItem.forEach((item: any) => {
+        temp.push(item.id);
+      });
+      forms.check = temp;
+    };
+
+    const getList = async () => {
+      try {
+        const { data } = await request.post(
+          '/api-web/imGroup/schoolQueryFriendList'
+        );
+        forms.list = data || [];
+      } catch {
+        //
+      }
+    };
+
+    onMounted(() => {
+      getList();
+    });
     return () => (
       <div
         style={{
@@ -71,28 +108,35 @@ export default defineComponent({
           <MSearch placeholder="请输入群聊名称" />
         </Sticky>
         <CheckboxGroup v-model={forms.check}>
-          {[1, 2, 3, 4, 5, 6, 7, 8].map((item: any, index: number) => (
+          {forms.list.map((item: any, index: number) => (
             <Cell
               center
               onClick={() => onToggle(index)}
               class={styles.popupCell}>
               {{
                 icon: () => (
-                  <Image src={class1} class={styles.imgLogo} fit="contain" />
+                  <Image
+                    src={
+                      item.friend.avatar || item.friend.userType === 'TEACHER'
+                        ? iconTeacher
+                        : iconStudent
+                    }
+                    class={styles.imgLogo}
+                    fit="contain"
+                  />
                 ),
                 title: () => (
                   <div class={styles.infos}>
                     <div class={styles.infoTitle}>
-                      长笛班 <img src={badge1} class={styles.iconBadge} />
-                    </div>
-                    <div class={styles.infoContent}>
-                      武汉洪山区第二小学第一乐团
+                      {item.friendNickname}
+                      {/* <img src={badge1} class={styles.iconBadge} /> */}
                     </div>
+                    <div class={styles.infoContent}>{item.memo}</div>
                   </div>
                 ),
                 'right-icon': () => (
                   <Checkbox
-                    name={item}
+                    name={item.id}
                     ref={e => (checkboxRefs.value[index] = e)}
                     onClick={(e: MouseEvent) => {
                       e.stopPropagation();

+ 42 - 9
src/views/mass-message/components/group-chat.tsx

@@ -1,10 +1,11 @@
 import { Cell, Checkbox, CheckboxGroup, Icon, Image, Sticky } from 'vant';
-import { defineComponent, reactive, ref, watch } from 'vue';
+import { defineComponent, onMounted, reactive, ref, watch } from 'vue';
 import styles from '../index.module.less';
 import class1 from '../images/1.png';
 import MSearch from '@/components/m-search';
 import activeButtonIcon from '@/common/images/icon-check-active.png';
 import inactiveButtonIcon from '@/common/images/icon-check.png';
+import request from '@/helpers/request';
 export default defineComponent({
   name: 'group-chat',
   props: {
@@ -43,8 +44,9 @@ export default defineComponent({
         if (forms.check.includes(item.id)) {
           list.push({
             id: item.id,
-            value: item.nickname,
-            avatar: item.avatar
+            value: item.name,
+            text: item.tags,
+            avatar: class1
           });
         }
       });
@@ -58,6 +60,39 @@ export default defineComponent({
         console.log(forms.height);
       }
     );
+
+    watch(
+      () => props.selectItem,
+      () => {
+        initSelectItem();
+      },
+      { deep: true }
+    );
+
+    const initSelectItem = () => {
+      const selectItem = props.selectItem || [];
+      const temp: any = [];
+      selectItem.forEach((item: any) => {
+        temp.push(item.id);
+      });
+      forms.check = temp;
+    };
+
+    const getList = async () => {
+      try {
+        const { data } = await request.post(
+          '/api-web/imGroup/schoolQueryGroupList'
+        );
+        console.log(data);
+        forms.list = data || [];
+      } catch {
+        //
+      }
+    };
+
+    onMounted(() => {
+      getList();
+    });
     return () => (
       <div
         style={{
@@ -70,7 +105,7 @@ export default defineComponent({
           <MSearch placeholder="请输入群聊名称" />
         </Sticky>
         <CheckboxGroup v-model={forms.check}>
-          {[1, 2, 3, 4, 5, 6, 7, 8].map((item: any, index: number) => (
+          {forms.list.map((item: any, index: number) => (
             <Cell
               center
               onClick={() => onToggle(index)}
@@ -81,15 +116,13 @@ export default defineComponent({
                 ),
                 title: () => (
                   <div class={styles.infos}>
-                    <div class={styles.infoTitle}>长笛班</div>
-                    <div class={styles.infoContent}>
-                      武汉洪山区第二小学第一乐团
-                    </div>
+                    <div class={styles.infoTitle}>{item.name}</div>
+                    <div class={styles.infoContent}>{item.tags}</div>
                   </div>
                 ),
                 'right-icon': () => (
                   <Checkbox
-                    name={item}
+                    name={item.id}
                     ref={e => (checkboxRefs.value[index] = e)}
                     onClick={(e: MouseEvent) => {
                       e.stopPropagation();

+ 118 - 37
src/views/mass-message/index.tsx

@@ -8,8 +8,10 @@ import {
   Field,
   Icon,
   Image,
-  showConfirmDialog
+  showConfirmDialog,
+  showToast
 } from 'vant';
+import { postMessage } from '@/helpers/native-message';
 import MUploader from '@/components/m-uploader';
 import MPopup from '@/components/m-popup';
 import SelectSend from './select-send';
@@ -19,31 +21,100 @@ import iconContent from './images/icon-content.png';
 import iconFile from './images/icon-file.png';
 import iconUsers from './images/icon-users.png';
 
-import badge1 from './images/badge-1.png';
-import class1 from './images/1.png';
+// import badge1 from './images/badge-1.png';
+// import class1 from './images/1.png';
 import MSticky from '@/components/m-sticky';
+import request from '@/helpers/request';
+import { useRouter } from 'vue-router';
 
 export default defineComponent({
   name: 'mass-message',
   setup() {
+    const router = useRouter();
     const forms = reactive({
-      textMessage: '',
-      attachments: [],
+      messageContent: '',
+      fileUrl: [] as any,
       selectStatus: false,
-      selectObject: []
+      receives: [] as any[],
+      selectObject: {} as any
     });
 
-    const onClose = () => {
+    const onClose = (item: any) => {
       showConfirmDialog({
         title: '提示',
         message: '您是否删除该数据'
       }).then(() => {
         //
+        const selectList = forms.selectObject;
+        if (item.receiveType === 'GROUPCHAT') {
+          const tempClass = selectList.groupChat || [];
+          const sIndex = tempClass.findIndex(
+            (child: any) => child.id === item.receiveId
+          );
+          tempClass.splice(sIndex, 1);
+        } else if (item.receiveType === 'CONTACTS') {
+          const tempSchool = selectList.contcats || [];
+          const sIndex = tempSchool.findIndex(
+            (child: any) => child.id === item.receiveId
+          );
+          tempSchool.splice(sIndex, 1);
+        }
+        forms.selectObject = selectList;
+
+        const index = forms.receives.findIndex(
+          (child: any) => child.receiveId === item.receiveId
+        );
+        forms.receives.splice(index, 1);
       });
     };
 
-    const onSubmit = () => {
+    const checkForms = () => {
+      if (!forms.messageContent) {
+        showToast('请输入消息内容');
+        return false;
+      }
+
+      if (
+        forms.messageContent.length < 3 &&
+        forms.messageContent.length > 150
+      ) {
+        showToast('消息内容长度为3~150个字');
+        return false;
+      }
+
+      if (forms.receives.length <= 0) {
+        showToast('请选择发送对象');
+        return;
+      }
+      return true;
+    };
+    const onSubmit = async () => {
       console.log('onSubmit');
+      const targetIds = forms.selectObject.groupChat.map(
+        (item: any) => item.id
+      );
+      const userTargetIds = forms.selectObject.contacts.map(
+        (item: any) => item.id
+      );
+      console.log(targetIds, userTargetIds);
+      try {
+        if (!checkForms()) return;
+        await request.post('/api-web/imSendGroupMessage/schoolSend', {
+          hideLoading: false,
+          data: {
+            messageContent: forms.messageContent,
+            messageType: 'IMG',
+            sendType: 'NOW',
+            fileUrl: forms.fileUrl.join(','),
+            targetIds: targetIds.join(','),
+            userTargetIds: userTargetIds.join(',')
+          }
+        });
+
+        postMessage({ api: 'back' });
+      } catch {
+        //
+      }
     };
 
     return () => (
@@ -63,7 +134,7 @@ export default defineComponent({
                 <Field
                   style={{ padding: '0', marginTop: '12px' }}
                   placeholder="请输入您的消息内容"
-                  v-model={forms.textMessage}
+                  v-model={forms.messageContent}
                   type="textarea"
                   rows={3}
                   showWordLimit
@@ -85,7 +156,7 @@ export default defineComponent({
               ),
               label: () => (
                 <MUploader
-                  v-model:modelValue={forms.attachments}
+                  v-model:modelValue={forms.fileUrl}
                   maxCount={5}
                   uploadIcon={iconUploader}
                 />
@@ -115,47 +186,30 @@ export default defineComponent({
             }}
           </Field>
 
-          <Cell center border={false}>
-            {{
-              icon: () => <Image src={class1} class={styles.imgLogo} />,
-              title: () => (
-                <div class={styles.infos}>
-                  <div class={styles.infoTitle}>长笛班</div>
-                  <div class={styles.infoContent}>
-                    武汉洪山区第二小学第一乐团
-                  </div>
-                </div>
-              ),
-              'right-icon': () => (
-                <Icon
-                  name={iconClose}
-                  class={styles.infoClose}
-                  onClick={onClose}
-                />
-              )
-            }}
-          </Cell>
-          {[1, 2, 3, 4, 5, 6].map(() => (
+          {forms.receives.map((item: any) => (
             <Cell center border={false}>
               {{
                 icon: () => (
-                  <Image src={class1} class={styles.imgLogo} fit="contain" />
+                  <Image
+                    src={item.avatar}
+                    class={styles.imgLogo}
+                    fit="contain"
+                  />
                 ),
                 title: () => (
                   <div class={styles.infos}>
                     <div class={styles.infoTitle}>
-                      长笛班 <img src={badge1} class={styles.iconBadge} />
-                    </div>
-                    <div class={styles.infoContent}>
-                      武汉洪山区第二小学第一乐团
+                      {item.receiveName}
+                      {/* <img src={badge1} class={styles.iconBadge} /> */}
                     </div>
+                    <div class={styles.infoContent}>{item.receiveText}</div>
                   </div>
                 ),
                 'right-icon': () => (
                   <Icon
                     name={iconClose}
                     class={styles.infoClose}
-                    onClick={onClose}
+                    onClick={() => onClose(item)}
                   />
                 )
               }}
@@ -175,6 +229,33 @@ export default defineComponent({
           <SelectSend
             v-model:selectObject={forms.selectObject}
             onClose={() => (forms.selectStatus = false)}
+            onConfirm={(val: any) => {
+              const groupChat = val.groupChat;
+              const contacts = val.contacts;
+              const tempList: any = [];
+              console.log(groupChat, contacts, tempList);
+              groupChat.forEach((item: any) => {
+                tempList.push({
+                  receiveType: 'GROUPCHAT',
+                  receiveId: item.id,
+                  receiveName: item.value,
+                  receiveText: item.text,
+                  avatar: item.avatar
+                });
+              });
+
+              contacts.forEach((item: any) => {
+                tempList.push({
+                  receiveType: 'CONTACTS',
+                  receiveId: item.id,
+                  receiveName: item.value,
+                  receiveText: item.text,
+                  avatar: item.avatar
+                });
+              });
+
+              forms.receives = tempList;
+            }}
           />
         </MPopup>
       </div>

+ 10 - 14
src/views/mass-message/select-send.tsx

@@ -31,15 +31,13 @@ export default defineComponent({
     });
 
     const onSubmit = async () => {
-      // const params = {
-      //   class: state.selectClass,
-      //   student: state.selectStudent,
-      //   teacher: state.selectTeacher,
-      //   school: state.selectManage
-      // };
-      // emit('close');
-      // emit('update:selectObject', params);
-      // emit('confirm', params);
+      const params = {
+        groupChat: state.selectGroupChat,
+        contacts: state.selectContacts
+      };
+      emit('close');
+      emit('update:selectObject', params);
+      emit('confirm', params);
     };
 
     watch(
@@ -52,11 +50,9 @@ export default defineComponent({
     );
 
     const resetSelectItems = () => {
-      // const list = props.selectObject || {};
-      // state.selectClass = list.class || [];
-      // state.selectTeacher = list.teacher || [];
-      // state.selectManage = list.school || [];
-      // state.selectStudent = list.student || [];
+      const list = props.selectObject || {};
+      state.selectGroupChat = list.groupChat || [];
+      state.selectContacts = list.contacts || [];
     };
 
     onMounted(() => {