index.tsx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. import { defineComponent, reactive, onMounted, ref } from 'vue';
  2. import styles from './index.module.less';
  3. import {
  4. NButton,
  5. NDataTable,
  6. NForm,
  7. NFormItem,
  8. NImage,
  9. NModal,
  10. NSpace,
  11. useMessage
  12. } from 'naive-ui';
  13. import SearchInput from '@/components/searchInput';
  14. import CSelect from '@/components/CSelect';
  15. import Pagination from '@/components/pagination';
  16. import { classGroupList, deleteClass, getSubject, addGroup } from './api';
  17. import CreateClass from './modals/createClass';
  18. import RestStudentBox from './modals/restStudentBox';
  19. import { getgradeNumList, classArray } from './contants';
  20. import add from '@/views/studentList/images/add.png';
  21. import ClassGuide from '@/custom-plugins/guide-page/class-guide';
  22. import { useRoute, useRouter } from 'vue-router';
  23. import TheEmpty from '/src/components/TheEmpty';
  24. import TheTooltip from '/src/components/TheTooltip';
  25. import PreviewWindow from '../preview-window';
  26. import ResetSubject from './modals/resetSubject';
  27. import UpdateSubject from './modals/updateSubject';
  28. import { getGradeLevelList, getGradeYearList } from '../home/api';
  29. import { initCache, setCache } from '/src/hooks/use-async';
  30. export default defineComponent({
  31. name: 'class-classList',
  32. setup() {
  33. const state = reactive({
  34. searchForm: {
  35. keyword: null as any,
  36. currentClass: '',
  37. currentGradeNum: '',
  38. subjectId: '',
  39. gradeYear: '',
  40. gradeLevel: ''
  41. },
  42. orchestraType: null,
  43. courseTypeCode: null,
  44. loading: false,
  45. pagination: {
  46. page: 1,
  47. rows: 10,
  48. pageTotal: 6
  49. },
  50. gradeNumList: [] as any,
  51. tableList: [] as any,
  52. studentVisible: false,
  53. activeRow: null as any,
  54. showaddClass: false,
  55. goCourseVisiable: false,
  56. removeVisiable: false,
  57. removeRow: {} as any,
  58. previewModal: false,
  59. previewParams: {} as any,
  60. lastCourse: null as any,
  61. groupBtnLoading: false, // 按钮是否在请求中
  62. subjectList: [] as any,
  63. showResetClass: false,
  64. showSubjectClass: false,
  65. groupVisiable: false,
  66. popSelectYearList: [] as any,
  67. popSelectLevelList: [] as any
  68. });
  69. const formRef = ref();
  70. const message = useMessage();
  71. const router = useRouter();
  72. const route = useRoute();
  73. const search = () => {
  74. state.pagination.page = 1;
  75. getList();
  76. setCache({ current: state.searchForm, saveKey: route.path });
  77. };
  78. const showGuide = ref(false);
  79. state.gradeNumList = getgradeNumList();
  80. const onReset = () => {
  81. state.searchForm = {
  82. keyword: null as any,
  83. currentClass: '' as any,
  84. currentGradeNum: '' as any,
  85. subjectId: '' as any,
  86. gradeYear: '' as any,
  87. gradeLevel: ''
  88. };
  89. if (state.popSelectYearList.length > 0) {
  90. state.searchForm.gradeYear = state.popSelectYearList[1].id;
  91. }
  92. getList();
  93. setCache({ current: state.searchForm, saveKey: route.path });
  94. };
  95. const removeClass = async () => {
  96. try {
  97. await deleteClass({ ids: state.removeRow.id });
  98. getList();
  99. message.success(`删除成功`);
  100. state.removeVisiable = false;
  101. } catch (e) {
  102. console.log(e);
  103. }
  104. };
  105. const getList = async () => {
  106. // classGroupList
  107. state.loading = true;
  108. try {
  109. const res = await classGroupList({
  110. ...state.searchForm,
  111. ...state.pagination
  112. });
  113. state.tableList = res.data.rows;
  114. state.pagination.pageTotal = res.data.total;
  115. state.loading = false;
  116. setTimeout(() => {
  117. if (state.tableList.length > 0) {
  118. showGuide.value = true;
  119. }
  120. }, 500);
  121. } catch (e) {
  122. state.loading = false;
  123. console.log(e);
  124. }
  125. console.log('getList');
  126. };
  127. const getSubjectList = async () => {
  128. const res = await getSubject({ page: 1, rows: 9999 });
  129. state.subjectList = res.data.rows.map((item: any) => {
  130. return {
  131. value: item.id,
  132. label: item.name
  133. };
  134. });
  135. state.subjectList.unshift({ value: '', label: '全部声部' });
  136. };
  137. const columns = () => {
  138. return [
  139. {
  140. title: '班级名称',
  141. key: 'name'
  142. },
  143. {
  144. title: '学年',
  145. key: 'gradeYear'
  146. },
  147. {
  148. title: '学级',
  149. key: 'gradeLevel',
  150. render(row: any) {
  151. return row.gradeLevel ? `${row.gradeLevel}级` : '';
  152. }
  153. },
  154. {
  155. title: '班级声部',
  156. key: 'subjectName'
  157. },
  158. {
  159. title: '学生人数',
  160. key: 'preStudentNum'
  161. },
  162. {
  163. title: '上次学习',
  164. key: 'lastStudy',
  165. width: '20%',
  166. render(row: any) {
  167. return row.lastStudy ? (
  168. <TheTooltip
  169. maxWidth={300}
  170. showContentWidth={300}
  171. content={row.lastStudy}
  172. />
  173. ) : (
  174. '--'
  175. );
  176. }
  177. },
  178. {
  179. title: '操作',
  180. key: 'id',
  181. render(row: any, index: number) {
  182. return (
  183. <div>
  184. <NSpace>
  185. {index == 0 ? (
  186. <div id="class-0">
  187. <NButton
  188. type="primary"
  189. text
  190. onClick={() => {
  191. router.push({
  192. path: '/classDetail',
  193. query: {
  194. name: row.name,
  195. id: row.id,
  196. gradeYear: row.gradeYear,
  197. upgradeFlag: row.upgradeFlag ? 1 : 0 // 是否为历史班
  198. }
  199. });
  200. }}>
  201. 详情
  202. </NButton>
  203. </div>
  204. ) : (
  205. <NButton
  206. type="primary"
  207. text
  208. onClick={() => {
  209. router.push({
  210. path: '/classDetail',
  211. query: {
  212. name: row.name,
  213. id: row.id,
  214. gradeYear: row.gradeYear,
  215. upgradeFlag: row.upgradeFlag ? 1 : 0 // 是否为历史班
  216. }
  217. });
  218. }}>
  219. 详情
  220. </NButton>
  221. )}
  222. <NButton
  223. type="primary"
  224. disabled={!row.upgradeFlag}
  225. text
  226. onClick={() => resetClassSubject(row)}>
  227. 修改声部
  228. </NButton>
  229. {index == 0 ? (
  230. <NButton
  231. type="primary"
  232. disabled={!row.upgradeFlag}
  233. {...{ id: 'class-1' }}
  234. text
  235. onClick={() => {
  236. startResetStudent(row);
  237. }}>
  238. 学生调整
  239. </NButton>
  240. ) : (
  241. <NButton
  242. type="primary"
  243. disabled={!row.upgradeFlag}
  244. text
  245. onClick={() => {
  246. startResetStudent(row);
  247. }}>
  248. 学生调整
  249. </NButton>
  250. )}
  251. {index == 0 ? (
  252. <NButton
  253. {...{ id: 'class-2' }}
  254. disabled={!row.upgradeFlag}
  255. type="primary"
  256. text
  257. onClick={() => classesBegin(row)}>
  258. 开始上课
  259. </NButton>
  260. ) : (
  261. <NButton
  262. disabled={!row.upgradeFlag}
  263. type="primary"
  264. text
  265. onClick={() => classesBegin(row)}>
  266. 开始上课
  267. </NButton>
  268. )}
  269. {!(row.preStudentNum > 0) ? (
  270. <NButton
  271. disabled={!row.upgradeFlag}
  272. type="error"
  273. color="#EA4132"
  274. text
  275. onClick={() => {
  276. state.removeVisiable = true;
  277. state.removeRow = row;
  278. }}>
  279. 删除
  280. </NButton>
  281. ) : // <p
  282. // style={{ color: '#EA4132', cursor: 'pointer' }}
  283. // onClick={() => {
  284. // state.removeVisiable = true;
  285. // state.removeRow = row;
  286. // }}>
  287. // 删除
  288. // </p>
  289. null}
  290. {row.imGroupId ? null : (
  291. <NButton
  292. type="primary"
  293. disabled={!row.upgradeFlag}
  294. text
  295. onClick={() => {
  296. createImgroup(row);
  297. }}>
  298. 创建群聊
  299. </NButton>
  300. )}
  301. </NSpace>
  302. </div>
  303. );
  304. }
  305. }
  306. ];
  307. };
  308. const startResetStudent = (row: any) => {
  309. state.activeRow = row;
  310. state.studentVisible = true;
  311. };
  312. const classesBegin = async (row: any) => {
  313. try {
  314. // 判断是否有声部
  315. if (row.subjectId) {
  316. //
  317. // 声部先取上次上课的声部,如果没有则取班级上面的声部
  318. router.push({
  319. path: '/prepare-lessons',
  320. query: {
  321. lastUseCoursewareId: row.lessonCoursewareId,
  322. unit: row.lessonCoursewareKnowledgeDetailId,
  323. subjectId: row.subjectId,
  324. courseScheduleSubjectId: row.courseScheduleSubjectId,
  325. preStudentNum: row.preStudentNum,
  326. name: row.name, // 班级名称
  327. classGroupId: row.id // 班级编号
  328. }
  329. });
  330. } else {
  331. state.showSubjectClass = true;
  332. state.activeRow = row;
  333. }
  334. } catch (e) {
  335. console.log(e);
  336. }
  337. };
  338. const resetClassSubject = (row: any) => {
  339. state.activeRow = row;
  340. state.showResetClass = true;
  341. };
  342. const createImgroup = async (row: any) => {
  343. state.activeRow = row;
  344. state.groupVisiable = true;
  345. };
  346. const submitGroup = async () => {
  347. console.log(state.activeRow, 'row');
  348. state.groupBtnLoading = true;
  349. try {
  350. await addGroup({ classGroupId: state.activeRow.id });
  351. message.success('创建成功');
  352. state.groupVisiable = false;
  353. await getList();
  354. } catch (e) {
  355. console.log(e);
  356. }
  357. state.groupBtnLoading = false;
  358. };
  359. // 获取学年
  360. const getYearList = async () => {
  361. try {
  362. const { data } = await getGradeYearList();
  363. const temp = data || [];
  364. temp.forEach((i: any) => {
  365. i.name = i.name + '学年';
  366. });
  367. temp.unshift({
  368. id: '',
  369. name: '全部学年'
  370. });
  371. state.popSelectYearList = temp || [];
  372. if (temp.length > 0 && !state.searchForm.gradeYear) {
  373. state.searchForm.gradeYear = temp[1].id;
  374. }
  375. } catch {
  376. //
  377. }
  378. };
  379. // 获取学级
  380. const getLevelList = async () => {
  381. try {
  382. const { data } = await getGradeLevelList();
  383. const temp = data || [];
  384. temp.forEach((i: any) => {
  385. i.name = i.name + '级';
  386. });
  387. temp.unshift({
  388. id: '',
  389. name: '全部学级'
  390. });
  391. state.popSelectLevelList = temp || [];
  392. if (temp.length > 0 && !state.searchForm.gradeLevel) {
  393. state.searchForm.gradeLevel = temp[0].id;
  394. }
  395. } catch {
  396. //
  397. }
  398. };
  399. initCache({
  400. current: state.searchForm,
  401. callBack: (active: any) => {
  402. state.searchForm = active;
  403. }
  404. });
  405. onMounted(async () => {
  406. state.loading = true;
  407. getSubjectList();
  408. await getYearList();
  409. await getLevelList();
  410. await getList();
  411. state.loading = false;
  412. });
  413. return () => (
  414. <div class={styles.listWrap}>
  415. <div class={styles.searchList}>
  416. <NForm label-placement="left" inline ref={formRef}>
  417. <NFormItem>
  418. <SearchInput
  419. {...{ placeholder: '请输入班级名称' }}
  420. class={styles.searchInput}
  421. searchWord={state.searchForm.keyword}
  422. onChangeValue={(val: string) =>
  423. (state.searchForm.keyword = val)
  424. }></SearchInput>
  425. </NFormItem>
  426. <NFormItem>
  427. <CSelect
  428. {...({
  429. options: state.popSelectYearList,
  430. placeholder: '选择学年',
  431. clearable: true,
  432. inline: true,
  433. labelField: 'name',
  434. valueField: 'id'
  435. } as any)}
  436. v-model:value={state.searchForm.gradeYear}></CSelect>
  437. </NFormItem>
  438. <NFormItem>
  439. <CSelect
  440. {...({
  441. options: state.popSelectLevelList,
  442. placeholder: '选择学级',
  443. clearable: true,
  444. inline: true,
  445. labelField: 'name',
  446. valueField: 'id'
  447. } as any)}
  448. v-model:value={state.searchForm.gradeLevel}></CSelect>
  449. </NFormItem>
  450. <NFormItem>
  451. <CSelect
  452. {...({
  453. options: state.gradeNumList,
  454. placeholder: '选择年级',
  455. clearable: true,
  456. inline: true
  457. } as any)}
  458. v-model:value={state.searchForm.currentGradeNum}></CSelect>
  459. </NFormItem>
  460. <NFormItem>
  461. <CSelect
  462. {...({
  463. options: classArray,
  464. placeholder: '选择班级',
  465. clearable: true,
  466. inline: true
  467. } as any)}
  468. v-model:value={state.searchForm.currentClass}></CSelect>
  469. </NFormItem>
  470. <NFormItem>
  471. <CSelect
  472. {...({
  473. options: state.subjectList,
  474. placeholder: '选择声部',
  475. clearable: true,
  476. inline: true
  477. } as any)}
  478. v-model:value={state.searchForm.subjectId}></CSelect>
  479. </NFormItem>
  480. <NFormItem>
  481. <NSpace justify="end">
  482. <NButton type="primary" class="searchBtn" onClick={search}>
  483. 搜索
  484. </NButton>
  485. <NButton
  486. type="primary"
  487. ghost
  488. class="resetBtn"
  489. onClick={onReset}>
  490. 重置
  491. </NButton>
  492. </NSpace>
  493. </NFormItem>
  494. </NForm>
  495. </div>
  496. <NButton
  497. class={styles.addBtn}
  498. type="primary"
  499. onClick={() => (state.showaddClass = true)}
  500. v-slots={{
  501. icon: () => (
  502. <>
  503. <NImage
  504. class={styles.addBtnIcon}
  505. previewDisabled
  506. src={add}></NImage>
  507. </>
  508. )
  509. }}>
  510. 创建班级
  511. </NButton>
  512. <div class={styles.tableWrap}>
  513. <NDataTable
  514. v-slots={{
  515. empty: () => <TheEmpty></TheEmpty>
  516. }}
  517. class={styles.classTable}
  518. loading={state.loading}
  519. columns={columns()}
  520. data={state.tableList}></NDataTable>
  521. <Pagination
  522. v-model:page={state.pagination.page}
  523. v-model:pageSize={state.pagination.rows}
  524. v-model:pageTotal={state.pagination.pageTotal}
  525. onList={getList}
  526. sync
  527. />
  528. </div>
  529. <NModal
  530. v-model:show={state.studentVisible}
  531. preset="card"
  532. class={['modalTitle background', styles.studentVisible]}
  533. title={'学员调整'}>
  534. <RestStudentBox
  535. activeRow={state.activeRow}
  536. onClose={() => (state.studentVisible = false)}
  537. onGetList={() => getList()}></RestStudentBox>
  538. </NModal>
  539. <NModal
  540. v-model:show={state.showaddClass}
  541. style={{ width: '500px' }}
  542. display-directive="if"
  543. preset="card"
  544. class={['modalTitle background']}
  545. title={'创建班级'}>
  546. <CreateClass
  547. gradeNumList={state.gradeNumList}
  548. classArray={classArray}
  549. subjectList={state.subjectList}
  550. onGetList={() => getList()}
  551. onClose={() => (state.showaddClass = false)}
  552. />
  553. </NModal>
  554. <NModal
  555. v-model:show={state.showResetClass}
  556. style={{ width: '500px' }}
  557. display-directive="if"
  558. preset="card"
  559. class={['modalTitle background']}
  560. title={'修改声部'}>
  561. <ResetSubject
  562. activeRow={state.activeRow}
  563. subjectList={state.subjectList}
  564. onGetList={() => getList()}
  565. onClose={() => (state.showResetClass = false)}
  566. />
  567. </NModal>
  568. <NModal
  569. v-model:show={state.showSubjectClass}
  570. style={{ width: '500px' }}
  571. preset="card"
  572. class={['modalTitle background']}
  573. title={'修改声部'}>
  574. {state.showSubjectClass ? (
  575. <UpdateSubject
  576. activeRow={state.activeRow}
  577. onGetList={() => getList()}
  578. onConfirm={(item: any) => {
  579. //
  580. router.push({
  581. path: '/prepare-lessons',
  582. query: {
  583. ...item
  584. }
  585. });
  586. }}
  587. onClose={() => (state.showSubjectClass = false)}
  588. />
  589. ) : null}
  590. </NModal>
  591. {/* 上课弹窗 */}
  592. <PreviewWindow
  593. v-model:show={state.previewModal}
  594. type="attend"
  595. params={state.previewParams}
  596. />
  597. <NModal
  598. v-model:show={state.removeVisiable}
  599. preset="card"
  600. class={['modalTitle', styles.removeVisiable]}
  601. title={'删除班级'}>
  602. <div class={styles.studentRemove}>
  603. <p>
  604. 确定要删除班级么?
  605. <span>删除班级信息将会清空</span>。
  606. </p>
  607. <NSpace class={styles.btnGroup} justify="center">
  608. <NButton round type="primary" onClick={removeClass}>
  609. 确定
  610. </NButton>
  611. <NButton round onClick={() => (state.removeVisiable = false)}>
  612. 取消
  613. </NButton>
  614. </NSpace>
  615. </div>
  616. </NModal>
  617. <NModal
  618. v-model:show={state.groupVisiable}
  619. preset="card"
  620. class={['modalTitle', styles.removeVisiable]}
  621. title={'创建群聊'}>
  622. <div class={styles.studentRemove}>
  623. <p style={{ textAlign: 'center' }}>是否创建班级群聊</p>
  624. <NSpace class={styles.btnGroup} justify="center">
  625. <NButton
  626. round
  627. type="primary"
  628. onClick={submitGroup}
  629. loading={state.groupBtnLoading}
  630. disabled={state.groupBtnLoading}>
  631. 确定
  632. </NButton>
  633. <NButton round onClick={() => (state.groupVisiable = false)}>
  634. 取消
  635. </NButton>
  636. </NSpace>
  637. </div>
  638. </NModal>
  639. {showGuide.value ? <ClassGuide></ClassGuide> : null}
  640. </div>
  641. );
  642. }
  643. });