lex 2 年之前
父节点
当前提交
3627948535

+ 1 - 1
public/project/initiation.html

@@ -241,7 +241,7 @@
           </template>
         </van-field>
         <van-field label="所学乐器" :disabled='checkPhone' v-if="stu.hasLearningExperience==1" name="learningSubjectName"
-          v-model="stu.learningSubjectName" placeholder="请所学乐器"></van-field>
+          v-model="stu.learningSubjectName" placeholder="请选择所学乐器"></van-field>
         <van-field required label="是否报名参加管乐团家长会了解相关情况" :disabled='checkPhone' name="joinParentMeeting"
           :rules="[{ required: true, message: '请选择是否报名参加管乐团家长会了解相关情况' }]">
           <template #input>

+ 0 - 1
src/components/o-upload/index.tsx

@@ -163,7 +163,6 @@ export default defineComponent({
     }
   },
   render() {
-    console.log(state.platformApi, state.platformType)
     useCustomFieldValue(() => this.modelValue)
     return (
       <div class={styles['uploader-section']}>

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

@@ -8,6 +8,14 @@ export const router = [
 // 不需要登录的路由
 export const rootRouter = [
   {
+    path: '/information-detail',
+    name: 'information-detail',
+    component: () => import('@/views/information/information-detail'),
+    meta: {
+      title: '资讯详情'
+    }
+  },
+  {
     path: '/:pathMatch(.*)*',
     component: () => import('@/views/404'),
     meta: {

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

@@ -56,10 +56,17 @@ export default [
       {
         path: '/create-orchestra',
         name: 'create-orchestra',
-        component: () => import('@/school/orchestra/create-orchestra'),
+        component: () => import('@/school/orchestra/create-orchestra/index'),
         meta: {
           title: '新建乐团'
         }
+      }, {
+        path: '/create-orchestra-teacher',
+        name: 'create-orchestra-teacher',
+        component: () => import('@/school/orchestra/create-orchestra/select-teacher'),
+        meta: {
+          title: '选择老师'
+        }
       },
       {
         path: '/orchestra-detail',

+ 2 - 0
src/school/manage-teacher/menu-function.tsx

@@ -28,6 +28,8 @@ export default defineComponent({
       try {
         const { data } = await request.post('/api-school/sysMenuButton/page', {
           data: {
+            auditFlag: false,
+            status: true,
             clientType: 'SCHOOL',
             page: 1,
             rows: 100

+ 25 - 0
src/school/orchestra/create-orchestra/create.ts

@@ -0,0 +1,25 @@
+import { reactive } from "vue";
+
+
+const original = () => {
+  return {
+    subjectStatus: false,
+    subjectList: [] as any, // 声部列表
+    selectSubjectIds: [] as any,
+    selectSubjects: [] as any, // 选中的声部
+    selectLastTeacherSubjects: [] as any, // 选择老师最终信息
+    studentStatus: false,
+    teacherStatus: false,
+    orchestraList: [] as any, // 乐团列表
+    selectSubjectStudents: {} as any,
+    orchestraName: null, //乐团名称
+    selectTeacher: {} as any // 选中老师信息
+  }
+}
+
+export const createState = reactive(original())
+
+// 重置对象
+export const resestState = () => {
+  Object.assign(orderStatus, original())
+}

+ 170 - 20
src/school/orchestra/create-orchestra/index.tsx

@@ -1,32 +1,163 @@
 import OHeader from '@/components/o-header'
 import OPopup from '@/components/o-popup'
 import OSticky from '@/components/o-sticky'
-import { Button, Cell, CellGroup, Field } from 'vant'
-import { defineComponent, reactive } from 'vue'
+import request from '@/helpers/request'
+import { Button, Cell, CellGroup, Field, showToast } from 'vant'
+import { defineComponent, onMounted } from 'vue'
 import styles from '../index.module.less'
+import { state as baseState } from '@/state'
 import StudentList from '../modal/student-list'
 import SubjectList from '../modal/subject-list'
-import TeacherList from '../modal/teacher-list'
+import { createState as state } from './create'
+import { useRouter } from 'vue-router'
+import deepClone from '@/helpers/deep-clone'
 
 export default defineComponent({
   name: 'create-orchestra',
   setup() {
-    const state = reactive({
-      subjectStatus: false,
-      studentStatus: false,
-      teacherStatus: false
-    })
+    const router = useRouter()
+    // const state = reactive({
+    //   subjectStatus: false,
+    //   subjectList: [] as any, // 声部列表
+    //   selectSubjectIds: [] as any,
+    //   selectSubjects: [] as any, // 选中的声部
+    //   studentStatus: false,
+    //   teacherStatus: false,
+    //   orchestraList: [] as any, // 乐团列表
+    //   selectSubjectStudents: {} as any
+    // })
+    // 获取声部
+    const getSubjects = async () => {
+      try {
+        const { data } = await request.post('/api-school/subject/page', {
+          data: {
+            page: 1,
+            rows: 50
+          }
+        })
+        state.subjectList = data.rows || []
+      } catch {
+        //
+      }
+    }
+
+    // 获取乐团列表
+    const getOrchestras = async () => {
+      try {
+        const { data } = await request.post('/api-school/orchestra/page', {
+          data: {
+            page: 1,
+            rows: 100,
+            schoolId: baseState.user.data.school.id
+          }
+        })
+        const temps = data.rows || []
+        const s = [] as any
+        temps.forEach((item: any) => {
+          s.push({
+            text: item.name,
+            value: item.id
+          })
+        })
+        state.orchestraList = [...s]
+      } catch {
+        //
+      }
+    }
+
+    // 初始化选择声部
+    const onSelectSubject = (ids: any) => {
+      state.selectSubjectIds = [...ids]
+      const temps: any = []
+      state.subjectList.forEach((item: any) => {
+        const index = state.selectSubjects.findIndex((select: any) => select.id === item.id)
+        if (ids.includes(item.id)) {
+          // 判断是否在数据里,如果在则直接添加,不能重置数据
+          if (index < 0) {
+            temps.push({
+              id: item.id,
+              name: item.name,
+              type: null,
+              teacher: {}, // 老师信息
+              students: [] as any // 选中的数据数
+            })
+          } else {
+            temps.push(state.selectSubjects.find((select: any) => select.id === item.id))
+          }
+        }
+      })
+      state.selectSubjects = [...temps]
+    }
 
     const onSubmit = () => {
-      state.teacherStatus = true
+      if (!state.orchestraName) {
+        showToast('请输入乐团名称')
+        return
+      }
+      if (state.selectSubjects && state.selectSubjects.length <= 0) {
+        showToast('请选择声部')
+        return
+      }
+
+      const selectSubjects = state.selectSubjects || []
+      let isSelect = false
+      selectSubjects.forEach((item: any) => {
+        if (!item.students || (item.students && item.students.length <= 0)) {
+          isSelect = true
+        }
+      })
+      if (isSelect) {
+        showToast('请选择学生')
+        return
+      }
+
+      // 初始化班级
+      state.selectLastTeacherSubjects = deepClone(state.selectSubjects)
+      // 添加所在学生
+      const tempStudents: any = []
+      state.selectSubjects.forEach((item: any) => {
+        tempStudents.push(...item.students)
+      })
+      // 默认添加两个班级
+      state.selectLastTeacherSubjects.push(
+        {
+          id: null,
+          name: '乐理班',
+          type: 'MUSIC_THEORY',
+          teacher: {}, // 老师信息
+          students: [...tempStudents] as any // 选中的数据数
+        },
+        {
+          id: null,
+          name: '合奏班',
+          type: 'INSTRUMENTAL_ENSEMBLE',
+          teacher: {}, // 老师信息
+          students: [...tempStudents] as any // 选中的数据数
+        }
+      )
+
+      // 选择老师
+      router.push({
+        path: '/create-orchestra-teacher'
+      })
     }
 
+    onMounted(() => {
+      getSubjects()
+      getOrchestras()
+    })
     return () => (
       <div class={styles['create-orchestra']}>
         <OHeader />
 
         <CellGroup inset>
-          <Field label="乐团名称" placeholder="请输入乐团名称" inputAlign="right" maxlength={30} />
+          <Field
+            label="乐团名称"
+            v-model={state.orchestraName}
+            placeholder="请输入乐团名称"
+            inputAlign="right"
+            maxlength={30}
+          />
           <Field
             label="乐团声部"
             readonly
@@ -36,12 +167,22 @@ export default defineComponent({
             onClick={() => (state.subjectStatus = true)}
           />
 
-          {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 7, 8, 9, 10].map((item: any) => (
-            <Cell title="长笛" isLink onClick={() => (state.studentStatus = true)}>
+          {state.selectSubjects.map((item: any) => (
+            <Cell
+              title={item.name}
+              isLink
+              onClick={() => {
+                state.studentStatus = true
+                state.selectSubjectStudents = item
+              }}
+            >
               {{
                 value: () => (
                   <>
-                    已选 <span style={{ color: 'var(--van-primary-color)' }}>{item + 1}</span>
+                    已选
+                    <span style={{ color: 'var(--van-primary-color)' }}>
+                      {item.students?.length || 0}
+                    </span>
                     名学生
                   </>
                 )
@@ -60,17 +201,26 @@ export default defineComponent({
 
         {/* 选择声部 */}
         <OPopup v-model:modelValue={state.subjectStatus} style="background: #F8F8F8;">
-          <SubjectList onClose={() => (state.subjectStatus = false)} />
+          <SubjectList
+            onClose={() => (state.subjectStatus = false)}
+            subjectList={state.subjectList}
+            selectSubjects={state.selectSubjects}
+            onSelect={onSelectSubject}
+          />
         </OPopup>
 
         {/* 选择学生 */}
         <OPopup v-model:modelValue={state.studentStatus} style="background: #f8f8f8;">
-          <StudentList onClose={() => (state.studentStatus = false)} />
-        </OPopup>
-
-        {/* 选择老师 */}
-        <OPopup v-model:modelValue={state.teacherStatus} style="background: #f8f8f8;">
-          <TeacherList onClose={() => (state.teacherStatus = false)} />
+          <StudentList
+            orchestraList={state.orchestraList}
+            subjectId={state.selectSubjectStudents.id}
+            selectStudentIds={state.selectSubjectStudents.students}
+            onClose={() => (state.studentStatus = false)}
+            onSelect={(item: any) => {
+              console.log(item, 'select student')
+              state.selectSubjectStudents.students = [...item]
+            }}
+          />
         </OPopup>
       </div>
     )

+ 18 - 0
src/school/orchestra/create-orchestra/select-teacher.module.less

@@ -0,0 +1,18 @@
+.cellGroup {
+  margin: 12px 13px;
+  :global {
+    .van-cell {
+      padding: 18px 12px;
+      color: #333;
+      font-size: 16px;
+    }
+  }
+
+  .tips {
+    color: #999;
+  }
+
+  .name {
+    color: #333;
+  }
+}

+ 142 - 0
src/school/orchestra/create-orchestra/select-teacher.tsx

@@ -0,0 +1,142 @@
+import OHeader from '@/components/o-header'
+import OPopup from '@/components/o-popup'
+import OSticky from '@/components/o-sticky'
+import { Button, Cell, CellGroup, Dialog, Field, showDialog, showToast } from 'vant'
+import { defineComponent, reactive } from 'vue'
+import TeacherList from '../modal/teacher-list'
+import styles from './select-teacher.module.less'
+import { state as baseState } from '@/state'
+import { createState as state, resestState } from './create'
+import { useRouter } from 'vue-router'
+import request from '@/helpers/request'
+
+export default defineComponent({
+  name: 'teacher-list',
+  emits: ['close'],
+  setup() {
+    const router = useRouter()
+    const forms = reactive({
+      teacherStatus: false,
+      status: false
+    })
+
+    const onSubmit = async () => {
+      // forms.status = true
+      showDialog({
+        title: '提示',
+        message: '是否创建乐团?',
+        showCancelButton: true
+      }).then(async () => {
+        try {
+          const selectSubjects = state.selectLastTeacherSubjects || []
+          const tempSelects: any = []
+          selectSubjects.forEach((item: any) => {
+            tempSelects.push({
+              teacherId: item.teacher.id,
+              type: item.type,
+              subjectId: item.id,
+              studentIdList: [...item.students]
+            })
+          })
+
+          console.log(tempSelects, 'tempselects')
+          // return
+          await request.post('/api-school/orchestra/addOrchestra', {
+            data: {
+              schoolId: baseState.user.data.school.id,
+              name: state.orchestraName,
+              classGroupList: [...tempSelects]
+            }
+          })
+
+          showToast('创建成功')
+          forms.status = true
+        } catch {
+          //
+        }
+      })
+    }
+
+    const onConfirm = () => {
+      resestState()
+      router.replace('/my-orchestra')
+    }
+    // 取消
+    const onCancel = () => {
+      resestState()
+      router.replace('/my-orchestra')
+    }
+    return () => (
+      <div>
+        <OHeader title="选择老师" />
+
+        <CellGroup inset class={styles.cellGroup}>
+          {state.selectLastTeacherSubjects.map((subject: any) => (
+            <Cell
+              center
+              onClick={() => {
+                forms.teacherStatus = true
+                state.selectTeacher = subject
+              }}
+              isLink
+            >
+              {{
+                title: () => <span class={styles.title}>{subject.name}</span>,
+                value: () => (
+                  <>
+                    {subject.teacher?.nickname ? (
+                      <p class={styles.name}>{subject.teacher?.nickname || ''}</p>
+                    ) : (
+                      <p class={styles.tips}>请选择老师</p>
+                    )}
+                  </>
+                )
+              }}
+            </Cell>
+          ))}
+        </CellGroup>
+
+        <OSticky position="bottom">
+          <div class={['btnGroup']}>
+            <Button type="primary" round block onClick={onSubmit}>
+              创建成功
+            </Button>
+          </div>
+        </OSticky>
+
+        <OPopup v-model:modelValue={forms.teacherStatus} position="bottom">
+          <TeacherList
+            onClose={() => (forms.teacherStatus = false)}
+            onSelect={(item: any) => {
+              state.selectTeacher.teacher = item
+              forms.teacherStatus = false
+
+              console.log(state.selectTeacher, 'select')
+              console.log(state.selectSubjects, 'state.selectSubjects')
+            }}
+          />
+        </OPopup>
+
+        <Dialog
+          v-model:show={forms.status}
+          message="乐团创建完成,是否需要排课?"
+          messageAlign="left"
+          confirmButtonText="去排课"
+          cancelButtonText="暂不排课"
+          showCancelButton
+          onConfirm={onConfirm}
+          onCancel={onCancel}
+        >
+          {{
+            title: () => (
+              <div class={styles.dialogTitle}>
+                <i></i>
+                创建成功
+              </div>
+            )
+          }}
+        </Dialog>
+      </div>
+    )
+  }
+})

+ 29 - 6
src/school/orchestra/modal/add-information.tsx

@@ -1,26 +1,49 @@
 import OUpload from '@/components/o-upload'
 import request from '@/helpers/request'
-import { Button, Field } from 'vant'
+import { verifyUrl } from '@/helpers/toolsValidate'
+import { Button, Field, showNotify, showToast } from 'vant'
 import { defineComponent, reactive } from 'vue'
 import styles from './add-information.module.less'
 
 export default defineComponent({
   name: 'add-information',
-  emits: ['close'],
+  emits: ['close', 'getList'],
   setup(props, { slots, attrs, emit }) {
     const forms = reactive({
       type: 'HOT_CONSULTATION',
       clientType: 'SCHOOL',
       coverImage: null,
       title: null,
-      linkUrl: null,
+      linkUrl: '',
       memo: null
     })
     const onSubmit = async () => {
+      if (!forms.coverImage) {
+        showToast('请上传封面图片')
+        return
+      } else if (!forms.title) {
+        showToast('请输入资讯标题')
+        return
+      } else if (!forms.memo) {
+        showToast('请输入内容简介')
+        return
+      } else if (!forms.linkUrl) {
+        showToast('请输入链接')
+        return
+      } else if (!verifyUrl(forms.linkUrl)) {
+        showToast('链接输入有误')
+        return
+      }
       try {
         await request.post('/api-school/sysNewsInformation/save', {
-          data: {}
+          data: {
+            ...forms
+          }
         })
+        showNotify({ type: 'primary', message: '添加成功' })
+
+        emit('close')
+        emit('getList')
       } catch {
         //
       }
@@ -54,8 +77,8 @@ export default defineComponent({
         </div>
         <Field placeholder="请输入链接" class={styles.field} v-model={forms.linkUrl} />
 
-        <div class={'btnGroup'}>
-          <Button type="primary" size="large" block round>
+        <div class={'btnGroup'} style={{ marginTop: '24px' }}>
+          <Button type="primary" size="large" block round onClick={onSubmit}>
             发布资讯
           </Button>
         </div>

+ 1 - 0
src/school/orchestra/modal/student-list.module.less

@@ -1,4 +1,5 @@
 .searchBand {
+  display: inline-block;
   // margin: 12px 13px;
   font-size: 14px;
   font-weight: 600;

+ 264 - 83
src/school/orchestra/modal/student-list.tsx

@@ -1,121 +1,270 @@
 import OHeader from '@/components/o-header'
 import OSearch from '@/components/o-search'
-import { Cell, Icon, Popover, Image, Checkbox, CheckboxGroup, Button } from 'vant'
-import { defineComponent, reactive } from 'vue'
+import {
+  Cell,
+  Icon,
+  Popover,
+  Image,
+  Checkbox,
+  CheckboxGroup,
+  Button,
+  Popup,
+  Picker,
+  List
+} from 'vant'
+import { defineComponent, onMounted, reactive, watch } from 'vue'
 import styles from './student-list.module.less'
 import checkboxCheck from '@/common/images/icon-checkbox-check.png'
 import checkboxDefault from '@/common/images/icon-checkbox-default.png'
+import iconStudent from '@/common/images/icon_student.png'
 import OSticky from '@/components/o-sticky'
+import { state as baseState } from '@/state'
+import request from '@/helpers/request'
+import OEmpty from '@/components/o-empty'
+
+export const classStr = {
+  1: '一年级',
+  2: '二年级',
+  3: '三年级',
+  4: '四年级',
+  5: '五年级',
+  6: '六年级'
+}
 
 export default defineComponent({
   name: 'student-list',
-  emits: ['close'],
+  props: {
+    orchestraList: {
+      // 乐团列表
+      type: Array,
+      default: () => []
+    },
+    subjectId: {
+      // 声部编号
+      type: [String, Number],
+      default: ''
+    },
+    selectStudentIds: {
+      // 选中的学生列表
+      type: Array,
+      default: () => []
+    }
+  },
+  emits: ['close', 'select'],
   setup(props, { slots, attrs, emit }) {
     const state = reactive({
       showPopover: false,
-      actions: [
-        { text: '全部乐团', color: 'var(--van-primary-color)' },
-        { text: '交付团' },
-        { text: '晋升团' }
-      ],
       oPopover: false,
-      check: [],
-      checkboxRefs: [] as any
+      isLoad: false,
+      classList: [
+        { text: '一年级', value: 1 },
+        { text: '二年级', value: 2 },
+        { text: '三年级', value: 3 },
+        { text: '四年级', value: 4 },
+        { text: '五年级', value: 5 }
+      ] as any, // 年级列表
+      check: [] as any,
+      checkboxRefs: [] as any,
+      orchestra: {
+        id: null,
+        name: '全部乐团'
+      } as any,
+      class: {
+        id: null,
+        name: '年级'
+      } as any,
+      list: [] as any,
+      listState: {
+        dataShow: true, // 判断是否有数据
+        loading: false,
+        finished: false
+      },
+      params: {
+        keyword: null,
+        page: 1,
+        rows: 20
+      }
     })
 
     const onSelect = (type: string) => {
-      console.log(type, 'tye')
-      console.log(state.checkboxRefs[type])
+      // console.log(state.checkboxRefs[type])
       state.checkboxRefs[type].toggle()
     }
 
+    const getList = async () => {
+      try {
+        if (state.isLoad) return
+        state.isLoad = true
+        const res = await request.post('/api-school/student/page', {
+          data: {
+            ...state.params,
+            subjectId: props.subjectId,
+            orchestraId: state.orchestra.id,
+            classId: state.class.id
+          }
+        })
+        state.listState.loading = false
+        const result = res.data || {}
+        // 处理重复请求数据
+        if (state.list.length > 0 && result.current === 1) {
+          return
+        }
+        state.list = state.list.concat(result.rows || [])
+        state.listState.finished = result.current >= result.pages
+        state.params.page = result.current + 1
+        state.listState.dataShow = state.list.length > 0
+
+        state.isLoad = false
+      } catch {
+        state.listState.dataShow = false
+        state.listState.finished = true
+        state.isLoad = false
+      }
+    }
+
+    // 搜索
+    const onSearch = () => {
+      state.params.page = 1
+      state.list = []
+      state.listState.dataShow = true // 判断是否有数据
+      state.listState.loading = false
+      state.listState.finished = false
+      getList()
+    }
+
     const onSubmit = () => {
       emit('close')
+      emit('select', state.check)
+      setTimeout(() => {
+        state.check = []
+      }, 100)
     }
 
+    // 监听声部是否变化
+    watch(
+      () => props.subjectId,
+      () => {
+        onSearch()
+      }
+    )
+
+    // 监听选择学生变化
+    watch(
+      () => props.selectStudentIds,
+      () => {
+        state.check = [...props.selectStudentIds]
+      }
+    )
+
+    onMounted(() => {
+      // 判断年级
+      if (baseState.user.data.school.schoolSystem === 'sixYearSystem') {
+        state.classList.push({ text: '六年级', value: 6 })
+      }
+
+      if (props.orchestraList.length > 0) {
+        const o: any = props.orchestraList[0]
+        state.orchestra.id = o.value
+        state.orchestra.name = o.text
+      }
+
+      // 获取学生列表
+      getList()
+
+      state.check = [...props.selectStudentIds]
+    })
+
     return () => (
       <div class={styles.studentList}>
         <OSticky position="top">
           <OHeader title="选择学生" />
-          <OSearch inputBackground="white" background="#F8F8F8" />
+          <OSearch
+            inputBackground="white"
+            background="#F8F8F8"
+            placeholder="学生名称/手机号"
+            onSearch={(val: any) => {
+              state.params.keyword = val
+              onSearch()
+            }}
+          />
           <div style={{ padding: '8px 13px 16px', background: '#F8F8F8' }}>
-            <Popover
-              v-model:show={state.showPopover}
-              actions={state.actions}
-              showArrow={false}
-              placement="bottom-start"
-              offset={[0, 12]}
-              style={{ zIndex: '9999' }}
+            <div class={styles.searchBand} onClick={() => (state.showPopover = true)}>
+              {state.class.name} <Icon name={state.showPopover ? 'arrow-up' : 'arrow-down'} />
+            </div>
+            <div
+              class={styles.searchBand}
+              style="margin-left: 16px"
+              onClick={() => (state.oPopover = true)}
             >
-              {{
-                reference: () => (
-                  <div class={styles.searchBand}>
-                    全部乐团 <Icon name={state.showPopover ? 'arrow-up' : 'arrow-down'} />
-                  </div>
-                )
-              }}
-            </Popover>
-            <Popover
-              v-model:show={state.oPopover}
-              actions={state.actions}
-              showArrow={false}
-              placement="bottom"
-              offset={[0, 12]}
-              style={{ zIndex: '9999' }}
-            >
-              {{
-                reference: () => (
-                  <div class={styles.searchBand} style="margin-left: 16px">
-                    武汉小学2022预备团 <Icon name={state.oPopover ? 'arrow-up' : 'arrow-down'} />
-                  </div>
-                )
-              }}
-            </Popover>
+              {state.orchestra.name} <Icon name={state.oPopover ? 'arrow-up' : 'arrow-down'} />
+            </div>
           </div>
         </OSticky>
 
-        <CheckboxGroup v-model={state.check}>
-          {[1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6].map((value: any) => (
-            <Cell v-model={state.check} center onClick={() => onSelect(value)}>
-              {{
-                icon: () => (
-                  <Image
-                    class={styles.img}
-                    src="https://daya.ks3-cn-beijing.ksyuncs.com/12/1670231208704.png"
-                  />
-                ),
-                title: () => (
-                  <div class={styles.content}>
-                    <p class={styles.name}>长毛</p>
-                    <p class={styles.class}>三年级</p>
-                  </div>
-                ),
-                'right-icon': () => (
-                  <Checkbox
-                    name={value}
-                    ref={(el: any) => (state.checkboxRefs[value] = el)}
-                    onClick={(e: any) => {
-                      e.stopPropagation()
-                      e.preventDefault()
-                    }}
-                    v-slots={{
-                      icon: (props: any) => (
-                        <Icon
-                          class={styles.iconChecked}
-                          name={props.checked ? checkboxCheck : checkboxDefault}
-                        />
-                      )
-                    }}
-                  />
-                )
-              }}
-            </Cell>
-          ))}
-        </CheckboxGroup>
+        {state.listState.dataShow ? (
+          <List
+            v-model:loading={state.listState.loading}
+            finished={state.listState.finished}
+            finishedText=" "
+            class={[styles.liveList]}
+            onLoad={getList}
+            immediateCheck={false}
+          >
+            <CheckboxGroup v-model={state.check}>
+              {state.list.map((item: any) => (
+                <Cell v-model={state.check} center onClick={() => onSelect(item.id)}>
+                  {{
+                    icon: () => <Image class={styles.img} src={item.avatar || iconStudent} />,
+                    title: () => (
+                      <div class={styles.content}>
+                        <p class={styles.name}>{item.nickname}</p>
+                        <p class={styles.class}>
+                          {item.currentGradeNum > 0 ? classStr[item.currentGradeNum] : ''}
+                        </p>
+                      </div>
+                    ),
+                    'right-icon': () => (
+                      <Checkbox
+                        name={item.id}
+                        ref={(el: any) => (state.checkboxRefs[item.id] = el)}
+                        onClick={(e: any) => {
+                          e.stopPropagation()
+                          e.preventDefault()
+                        }}
+                        v-slots={{
+                          icon: (props: any) => (
+                            <Icon
+                              class={styles.iconChecked}
+                              name={props.checked ? checkboxCheck : checkboxDefault}
+                            />
+                          )
+                        }}
+                      />
+                    )
+                  }}
+                </Cell>
+              ))}
+            </CheckboxGroup>
+          </List>
+        ) : (
+          <OEmpty btnStatus={false} classImgSize="SMALL" tips="暂无学生" />
+        )}
 
         <OSticky position="bottom">
           <div class={['btnGroup', styles.btnMore]}>
-            <Button type="primary" plain round>
+            <Button
+              type="primary"
+              plain
+              round
+              onClick={() => {
+                state.list.forEach((item: any) => {
+                  if (!state.check.includes(item.id)) {
+                    state.check.push(item.id)
+                  }
+                })
+                state.check
+              }}
+            >
               全选
             </Button>
             <Button type="primary" round block onClick={onSubmit}>
@@ -123,6 +272,38 @@ export default defineComponent({
             </Button>
           </div>
         </OSticky>
+
+        {/* 乐团 */}
+        <Popup v-model:show={state.oPopover} position="bottom" round>
+          <Picker
+            columns={props.orchestraList as any}
+            onCancel={() => (state.oPopover = false)}
+            onConfirm={(item: any) => {
+              const selectedOptions = item.selectedOptions[0]
+              state.orchestra.id = selectedOptions.value
+              state.orchestra.name = selectedOptions.text
+
+              state.oPopover = false
+              onSearch()
+            }}
+          />
+        </Popup>
+
+        {/* 年级 */}
+        <Popup v-model:show={state.showPopover} position="bottom" round>
+          <Picker
+            columns={state.classList as any}
+            onCancel={() => (state.showPopover = false)}
+            onConfirm={(item: any) => {
+              const selectedOptions = item.selectedOptions[0]
+              state.class.id = selectedOptions.value
+              state.class.name = selectedOptions.text
+
+              state.showPopover = false
+              onSearch()
+            }}
+          />
+        </Popup>
       </div>
     )
   }

+ 23 - 12
src/school/orchestra/modal/subject-list.tsx

@@ -8,7 +8,17 @@ import OSticky from '@/components/o-sticky'
 
 export default defineComponent({
   name: 'subject-list',
-  emits: ['close'],
+  props: {
+    subjectList: {
+      type: Array,
+      default: () => []
+    },
+    selectSubjects: {
+      type: Array,
+      default: () => []
+    }
+  },
+  emits: ['close', 'select'],
   setup(props, { slots, attrs, emit }) {
     const state = reactive({
       check: [],
@@ -20,7 +30,7 @@ export default defineComponent({
     }
 
     const onSubmit = () => {
-      console.log(state.check)
+      emit('select', state.check)
       emit('close')
     }
 
@@ -28,13 +38,17 @@ export default defineComponent({
       <div style={{ minHeight: '100vh' }}>
         <OHeader title="选择声部" />
 
-        <CheckboxGroup class={styles.subjectList} v-model={state.check}>
-          {[1, 2, 3, 4, 5].map((value: any) => (
-            <div class={styles.subject} onClick={() => onSelect(value)}>
+        <CheckboxGroup
+          class={styles.subjectList}
+          v-model={state.check}
+          style={{ paddingBottom: '24px' }}
+        >
+          {props.subjectList.map((item: any) => (
+            <div class={styles.subject} onClick={() => onSelect(item.id)}>
               <Checkbox
-                name={value}
+                name={item.id}
                 class={styles.checkbox}
-                ref={(el: any) => (state.checkboxRefs[value] = el)}
+                ref={(el: any) => (state.checkboxRefs[item.id] = el)}
                 v-slots={{
                   icon: (props: any) => (
                     <Icon
@@ -44,11 +58,8 @@ export default defineComponent({
                   )
                 }}
               />
-              <Image
-                class={styles.img}
-                src="https://daya.ks3-cn-beijing.ksyuncs.com/12/1670231208704.png"
-              />
-              <p class={styles.name}>长笛长笛长笛长笛长笛长笛s</p>
+              <Image class={styles.img} src={item.img} />
+              <p class={styles.name}>{item.name}</p>
             </div>
           ))}
         </CheckboxGroup>

+ 30 - 0
src/school/orchestra/modal/teacher-list.module.less

@@ -0,0 +1,30 @@
+.cellTeacher {
+  .img {
+    width: 48px;
+    height: 48px;
+    overflow: hidden;
+    border-radius: 50%;
+    margin-right: 12px;
+    flex-shrink: 0;
+  }
+
+  .name {
+    font-size: 16px;
+    font-weight: 500;
+    color: #333333;
+    line-height: 22px;
+  }
+
+  .class {
+    padding-top: 3px;
+    font-size: 12px;
+    color: #777777;
+    line-height: 17px;
+  }
+
+  :global {
+    .van-tag + .van-tag {
+      margin-left: 8px;
+    }
+  }
+}

+ 122 - 29
src/school/orchestra/modal/teacher-list.tsx

@@ -1,40 +1,133 @@
 import OHeader from '@/components/o-header'
+import OPopup from '@/components/o-popup'
 import OSticky from '@/components/o-sticky'
-import { Button, CellGroup, Field } from 'vant'
-import { defineComponent } from 'vue'
+import { state } from '@/state'
+import { Button, Cell, CellGroup, Field, List, Image, Tag } from 'vant'
+import { defineComponent, onMounted, reactive } from 'vue'
+import TeacherList from '../modal/teacher-list'
+import styles from './teacher-list.module.less'
+import iconTeacher from '@common/images/icon_teacher.png'
+import OEmpty from '@/components/o-empty'
+import request from '@/helpers/request'
+import OSearch from '@/components/o-search'
 
 export default defineComponent({
   name: 'teacher-list',
-  emits: ['close'],
-  setup() {
+  emits: ['close', 'select'],
+  setup(props, { slots, attrs, emit }) {
+    const forms = reactive({
+      teacherStatus: false,
+      isLoad: false,
+      list: [] as any,
+      listState: {
+        dataShow: true, // 判断是否有数据
+        loading: false,
+        finished: false
+      },
+      params: {
+        keyword: null,
+        page: 1,
+        rows: 20
+      }
+    })
+
+    const getList = async () => {
+      try {
+        if (forms.isLoad) return
+        forms.isLoad = true
+        const res = await request.post('/api-school/teacher/page', {
+          data: {
+            ...forms.params,
+            schoolId: state.user.data.school.id
+          }
+        })
+        forms.listState.loading = false
+        const result = res.data || {}
+        // 处理重复请求数据
+        if (forms.list.length > 0 && result.current === 1) {
+          return
+        }
+        const rows = result.rows || []
+        rows.forEach((item: any) => {
+          item.subjectNames = item.subjectName ? item.subjectName.split(',') : []
+        })
+        forms.list = forms.list.concat(rows)
+        forms.listState.finished = result.current >= result.pages
+        forms.params.page = result.current + 1
+        forms.listState.dataShow = forms.list.length > 0
+
+        forms.isLoad = false
+      } catch {
+        forms.listState.dataShow = false
+        forms.listState.finished = true
+        forms.isLoad = false
+      }
+    }
+
+    // 搜索
+    const onSearch = () => {
+      forms.params.page = 1
+      forms.list = []
+      forms.listState.dataShow = true // 判断是否有数据
+      forms.listState.loading = false
+      forms.listState.finished = false
+      getList()
+    }
+
+    const onSelect = (item: any) => {
+      emit('close')
+      emit('select', item)
+    }
+
+    onMounted(() => {
+      getList()
+    })
+
     return () => (
       <div>
-        <OHeader title="选择老师" />
-
-        <CellGroup inset>
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-          <Field label="长笛" inputAlign="right" placeholder="请选择老师" readonly isLink />
-        </CellGroup>
-
-        <OSticky position="bottom">
-          <div class={['btnGroup']}>
-            <Button type="primary" round block>
-              创建成功
-            </Button>
-          </div>
+        <OSticky position="top">
+          <OHeader title="选择老师" />
+          <OSearch
+            inputBackground="white"
+            background="#F8F8F8"
+            placeholder="老师名称/手机号"
+            onSearch={(val: any) => {
+              forms.params.keyword = val
+              onSearch()
+            }}
+          />
         </OSticky>
+
+        {forms.listState.dataShow ? (
+          <List
+            v-model:loading={forms.listState.loading}
+            finished={forms.listState.finished}
+            finishedText=" "
+            onLoad={getList}
+            immediateCheck={false}
+          >
+            {forms.list.map((item: any) => (
+              <Cell center class={styles.cellTeacher} onClick={() => onSelect(item)}>
+                {{
+                  icon: () => <Image class={styles.img} src={item.avatar || iconTeacher} />,
+                  title: () => (
+                    <div class={styles.content}>
+                      <p class={styles.name}>{item.nickname}</p>
+                      <p class={styles.class}>
+                        {item.subjectNames &&
+                          item.subjectNames.map((subject: any) => (
+                            <Tag type="primary">{subject}</Tag>
+                          ))}
+                      </p>
+                    </div>
+                  )
+                }}
+              </Cell>
+            ))}
+          </List>
+        ) : (
+          <OEmpty btnStatus={false} classImgSize="SMALL" tips="暂无老师" />
+        )}
       </div>
     )
   }

+ 32 - 3
src/school/orchestra/orchestra-information.tsx

@@ -1,10 +1,11 @@
 import OEmpty from '@/components/o-empty'
 import OPopup from '@/components/o-popup'
 import request from '@/helpers/request'
+import { router } from '@/router/routes-common'
 import dayjs from 'dayjs'
 import { Button, Cell, Image, List } from 'vant'
 import { defineComponent, onMounted, reactive } from 'vue'
-import { useRoute } from 'vue-router'
+import { useRoute, useRouter } from 'vue-router'
 import AddInformation from './modal/add-information'
 import styles from './orchestra-information.module.less'
 
@@ -12,6 +13,7 @@ export default defineComponent({
   name: 'orchestra-information',
   setup() {
     const route = useRoute()
+    const router = useRouter()
     const state = reactive({
       addStatus: false,
       isLoading: false,
@@ -58,6 +60,33 @@ export default defineComponent({
       }
     }
 
+    const onSearch = () => {
+      state.params.page = 1
+      state.list = []
+      state.listState.dataShow = true // 判断是否有数据
+      state.listState.loading = false
+      state.listState.finished = false
+      getList()
+    }
+
+    const onDetail = (item: any) => {
+      try {
+        console.log(item, 'item')
+        if (item.linkUrl) {
+          window.location.href = item.linkUrl
+        } else {
+          router.push({
+            path: '/information-detail',
+            query: {
+              id: item.id
+            }
+          })
+        }
+      } catch {
+        //
+      }
+    }
+
     onMounted(() => {
       getList()
     })
@@ -76,7 +105,7 @@ export default defineComponent({
             immediateCheck={false}
           >
             {state.list.map((item: any, index: number) => (
-              <Cell center class={styles.cell}>
+              <Cell center class={styles.cell} onClick={() => onDetail(item)}>
                 {{
                   icon: () => <Image src={item.coverImage} class={styles.img} />,
                   title: () => (
@@ -95,7 +124,7 @@ export default defineComponent({
         )}
 
         <OPopup v-model:modelValue={state.addStatus} style={{ background: '#f8f8f8' }}>
-          <AddInformation onClose={() => (state.addStatus = false)} />
+          <AddInformation onClose={() => (state.addStatus = false)} onGetList={onSearch} />
         </OPopup>
       </div>
     )

+ 37 - 0
src/views/information/information-detail.module.less

@@ -0,0 +1,37 @@
+.detail {
+  padding: 18px;
+
+  font-size: 15px;
+  color: #333333;
+  line-height: 25px;
+
+  .title {
+    font-size: 20px;
+    font-weight: 600;
+    color: #333333;
+    line-height: 28px;
+  }
+
+  .who {
+    padding-top: 15px;
+    font-size: 14px;
+    color: #aaaaaa;
+    line-height: 20px;
+    span {
+      font-weight: 500;
+      color: #f67146;
+      padding-right: 10px;
+    }
+  }
+
+  .content {
+    padding-top: 24px;
+
+    img {
+      width: 100%;
+      padding: 6px 0;
+      border-radius: 6px;
+      overflow: hidden;
+    }
+  }
+}

+ 37 - 0
src/views/information/information-detail.tsx

@@ -0,0 +1,37 @@
+import request from '@/helpers/request'
+import { defineComponent, onMounted, ref } from 'vue'
+import { useRoute } from 'vue-router'
+import styles from './information-detail.module.less'
+
+export default defineComponent({
+  name: 'orchestra-information-detail',
+  setup() {
+    const route = useRoute()
+    const detail = ref<any>({})
+
+    const getDetails = async () => {
+      try {
+        const { data } = await request.get(
+          '/api-school/sysNewsInformation/detail/' + route.query.id
+        )
+        detail.value = data
+      } catch {
+        //
+      }
+    }
+
+    onMounted(() => {
+      getDetails()
+    })
+    return () => (
+      <div class={styles.detail}>
+        <div class={styles.title}>常见的乐器可以分为三大类,你真的了解过吗</div>
+        <div class={styles.who}>
+          <span>管乐团</span>2022-12-05 11:47
+        </div>
+
+        <div class={styles.content} v-html={detail.value.content}></div>
+      </div>
+    )
+  }
+})

+ 2 - 2
vite.config.ts

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