index.tsx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  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 { 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. export default defineComponent({
  29. name: 'class-classList',
  30. setup(props, { emit }) {
  31. const state = reactive({
  32. searchForm: {
  33. keyword: null as any,
  34. currentClass: null,
  35. currentGradeNum: null,
  36. subjectId: null
  37. },
  38. orchestraType: null,
  39. courseTypeCode: null,
  40. loading: false,
  41. pagination: {
  42. page: 1,
  43. rows: 10,
  44. pageTotal: 6
  45. },
  46. gradeNumList: [] as any,
  47. tableList: [] as any,
  48. studentVisible: false,
  49. activeRow: null as any,
  50. showaddClass: false,
  51. goCourseVisiable: false,
  52. removeVisiable: false,
  53. removeRow: {} as any,
  54. previewModal: false,
  55. previewParams: {} as any,
  56. lastCourse: null as any,
  57. groupVisiable: false,
  58. groupBtnLoading: false, // 按钮是否在请求中
  59. subjectList: [] as any,
  60. showResetClass: false,
  61. showSubjectClass: false
  62. });
  63. const formRef = ref();
  64. const message = useMessage();
  65. const router = useRouter();
  66. const search = () => {
  67. state.pagination.page = 1;
  68. getList();
  69. console.log('search', state);
  70. };
  71. const showGuide = ref(false);
  72. state.gradeNumList = getgradeNumList();
  73. const onReset = () => {
  74. state.searchForm = {
  75. keyword: null as any,
  76. currentClass: null,
  77. currentGradeNum: null,
  78. subjectId: null
  79. };
  80. getList();
  81. };
  82. const removeClass = async () => {
  83. try {
  84. await deleteClass({ ids: state.removeRow.id });
  85. getList();
  86. message.success(`删除成功`);
  87. state.removeVisiable = false;
  88. } catch (e) {
  89. console.log(e);
  90. }
  91. };
  92. const getList = async () => {
  93. // classGroupList
  94. state.loading = true;
  95. try {
  96. const res = await classGroupList({
  97. ...state.searchForm,
  98. ...state.pagination
  99. });
  100. state.tableList = res.data.rows;
  101. state.pagination.pageTotal = res.data.total;
  102. state.loading = false;
  103. setTimeout(() => {
  104. if (state.tableList.length > 0) {
  105. showGuide.value = true;
  106. }
  107. }, 500);
  108. } catch (e) {
  109. state.loading = false;
  110. console.log(e);
  111. }
  112. console.log('getList');
  113. };
  114. const getSubjectList = async () => {
  115. const res = await getSubject({ page: 1, rows: 9999 });
  116. state.subjectList = res.data.rows.map((item: any) => {
  117. return {
  118. value: item.id,
  119. label: item.name
  120. };
  121. });
  122. state.subjectList.unshift({ value: null, label: '选择声部' });
  123. };
  124. const columns = () => {
  125. return [
  126. {
  127. title: '班级名称',
  128. key: 'name'
  129. },
  130. {
  131. title: '班级声部',
  132. key: 'subjectName'
  133. },
  134. {
  135. title: '学生人数',
  136. key: 'preStudentNum'
  137. },
  138. {
  139. title: '上次学习',
  140. key: 'lastStudy',
  141. width: '20%',
  142. render(row: any) {
  143. return row.lastStudy ? (
  144. <TheTooltip
  145. maxWidth={300}
  146. showContentWidth={300}
  147. content={row.lastStudy}
  148. />
  149. ) : (
  150. '--'
  151. );
  152. }
  153. },
  154. {
  155. title: '操作',
  156. key: 'id',
  157. render(row: any, index: number) {
  158. return (
  159. <div>
  160. <NSpace>
  161. {index == 0 ? (
  162. <div id="class-0">
  163. <NButton
  164. type="primary"
  165. text
  166. onClick={() => {
  167. router.push({
  168. path: '/classDetail',
  169. query: { name: row.name, id: row.id }
  170. });
  171. }}>
  172. 详情
  173. </NButton>
  174. </div>
  175. ) : (
  176. <NButton
  177. type="primary"
  178. text
  179. onClick={() => {
  180. router.push({
  181. path: '/classDetail',
  182. query: { name: row.name, id: row.id }
  183. });
  184. }}>
  185. 详情
  186. </NButton>
  187. )}
  188. <NButton
  189. type="primary"
  190. text
  191. onClick={() => resetClassSubject(row)}>
  192. 修改声部
  193. </NButton>
  194. {index == 0 ? (
  195. <NButton
  196. type="primary"
  197. {...{ id: 'class-1' }}
  198. text
  199. onClick={() => {
  200. startResetStudent(row);
  201. }}>
  202. 学生调整
  203. </NButton>
  204. ) : (
  205. <NButton
  206. type="primary"
  207. text
  208. onClick={() => {
  209. startResetStudent(row);
  210. }}>
  211. 学生调整
  212. </NButton>
  213. )}
  214. {index == 0 ? (
  215. <NButton
  216. {...{ id: 'class-2' }}
  217. // disabled={!(row.preStudentNum > 0)}
  218. type="primary"
  219. text
  220. onClick={() => classesBegin(row)}>
  221. 开始上课
  222. </NButton>
  223. ) : (
  224. <NButton
  225. // disabled={!(row.preStudentNum > 0)}
  226. type="primary"
  227. text
  228. onClick={() => classesBegin(row)}>
  229. 开始上课
  230. </NButton>
  231. )}
  232. {!(row.preStudentNum > 0) ? (
  233. <p
  234. style={{ color: '#EA4132', cursor: 'pointer' }}
  235. onClick={() => {
  236. state.removeVisiable = true;
  237. state.removeRow = row;
  238. }}>
  239. 删除
  240. </p>
  241. ) : null}
  242. {row.imGroupId ? null : (
  243. <NButton
  244. type="primary"
  245. text
  246. onClick={() => {
  247. createImgroup(row);
  248. }}>
  249. 创建群聊
  250. </NButton>
  251. )}
  252. </NSpace>
  253. </div>
  254. );
  255. }
  256. }
  257. ];
  258. };
  259. const startResetStudent = (row: any) => {
  260. state.activeRow = row;
  261. state.studentVisible = true;
  262. };
  263. const classesBegin = async (row: any) => {
  264. try {
  265. console.log(row, 'row');
  266. // 判断是否有声部
  267. if (row.subjectId) {
  268. //
  269. // 声部先取上次上课的声部,如果没有则取班级上面的声部
  270. router.push({
  271. path: '/prepare-lessons',
  272. query: {
  273. lastUseCoursewareId: row.lessonCoursewareId,
  274. unit: row.lessonCoursewareKnowledgeDetailId,
  275. subjectId: row.subjectId,
  276. courseScheduleSubjectId: row.courseScheduleSubjectId,
  277. name: row.name, // 班级名称
  278. classGroupId: row.id // 班级编号
  279. }
  280. });
  281. } else {
  282. state.showSubjectClass = true;
  283. state.activeRow = row;
  284. }
  285. } catch (e) {
  286. console.log(e);
  287. }
  288. };
  289. const resetClassSubject = (row: any) => {
  290. state.activeRow = row;
  291. state.showResetClass = true;
  292. };
  293. const createImgroup = async (row: any) => {
  294. state.activeRow = row;
  295. state.groupVisiable = true;
  296. };
  297. const submitGroup = async () => {
  298. console.log(state.activeRow, 'row');
  299. state.groupBtnLoading = true;
  300. try {
  301. await addGroup({ classGroupId: state.activeRow.id });
  302. message.success('创建成功');
  303. state.groupVisiable = false;
  304. await getList();
  305. } catch (e) {
  306. console.log(e);
  307. }
  308. state.groupBtnLoading = false;
  309. };
  310. onMounted(() => {
  311. getList();
  312. getSubjectList();
  313. });
  314. return () => (
  315. <div class={styles.listWrap}>
  316. <div class={styles.searchList}>
  317. <NForm label-placement="left" inline ref={formRef}>
  318. <NFormItem>
  319. <SearchInput
  320. {...{ placeholder: '请输入班级名称' }}
  321. class={styles.searchInput}
  322. searchWord={state.searchForm.keyword}
  323. onChangeValue={(val: string) =>
  324. (state.searchForm.keyword = val)
  325. }></SearchInput>
  326. </NFormItem>
  327. <NFormItem>
  328. <CSelect
  329. {...({
  330. options: state.gradeNumList,
  331. placeholder: '选择年级',
  332. clearable: true,
  333. inline: true
  334. } as any)}
  335. v-model:value={state.searchForm.currentGradeNum}></CSelect>
  336. </NFormItem>
  337. <NFormItem>
  338. <CSelect
  339. {...({
  340. options: classArray,
  341. placeholder: '选择班级',
  342. clearable: true,
  343. inline: true
  344. } as any)}
  345. v-model:value={state.searchForm.currentClass}></CSelect>
  346. </NFormItem>
  347. <NFormItem>
  348. <CSelect
  349. {...({
  350. options: state.subjectList,
  351. placeholder: '选择声部',
  352. clearable: true,
  353. inline: true
  354. } as any)}
  355. v-model:value={state.searchForm.subjectId}></CSelect>
  356. </NFormItem>
  357. <NFormItem>
  358. <NSpace justify="end">
  359. <NButton type="primary" class="searchBtn" onClick={search}>
  360. 搜索
  361. </NButton>
  362. <NButton
  363. type="primary"
  364. ghost
  365. class="resetBtn"
  366. onClick={onReset}>
  367. 重置
  368. </NButton>
  369. </NSpace>
  370. </NFormItem>
  371. </NForm>
  372. </div>
  373. <NButton
  374. class={styles.addBtn}
  375. type="primary"
  376. onClick={() => (state.showaddClass = true)}
  377. v-slots={{
  378. icon: () => (
  379. <>
  380. <NImage
  381. class={styles.addBtnIcon}
  382. previewDisabled
  383. src={add}></NImage>
  384. </>
  385. )
  386. }}>
  387. 创建班级
  388. </NButton>
  389. <div class={styles.tableWrap}>
  390. <NDataTable
  391. v-slots={{
  392. empty: () => <TheEmpty></TheEmpty>
  393. }}
  394. class={styles.classTable}
  395. loading={state.loading}
  396. columns={columns()}
  397. data={state.tableList}></NDataTable>
  398. <Pagination
  399. v-model:page={state.pagination.page}
  400. v-model:pageSize={state.pagination.rows}
  401. v-model:pageTotal={state.pagination.pageTotal}
  402. onList={getList}
  403. sync
  404. />
  405. </div>
  406. <NModal
  407. v-model:show={state.studentVisible}
  408. preset="card"
  409. class={['modalTitle background', styles.studentVisible]}
  410. title={'学员调整'}>
  411. <RestStudentBox
  412. activeRow={state.activeRow}
  413. onClose={() => (state.studentVisible = false)}
  414. onGetList={() => getList()}></RestStudentBox>
  415. </NModal>
  416. <NModal
  417. v-model:show={state.showaddClass}
  418. style={{ width: '500px' }}
  419. display-directive="if"
  420. preset="card"
  421. class={['modalTitle background']}
  422. title={'创建班级'}>
  423. <CreateClass
  424. gradeNumList={state.gradeNumList}
  425. classArray={classArray}
  426. subjectList={state.subjectList}
  427. onGetList={() => getList()}
  428. onClose={() => (state.showaddClass = false)}
  429. />
  430. </NModal>
  431. <NModal
  432. v-model:show={state.showResetClass}
  433. style={{ width: '500px' }}
  434. display-directive="if"
  435. preset="card"
  436. class={['modalTitle background']}
  437. title={'修改声部'}>
  438. <ResetSubject
  439. activeRow={state.activeRow}
  440. subjectList={state.subjectList}
  441. onGetList={() => getList()}
  442. onClose={() => (state.showResetClass = false)}
  443. />
  444. </NModal>
  445. <NModal
  446. v-model:show={state.showSubjectClass}
  447. style={{ width: '500px' }}
  448. preset="card"
  449. class={['modalTitle background']}
  450. title={'修改声部'}>
  451. {state.showSubjectClass ? (
  452. <UpdateSubject
  453. activeRow={state.activeRow}
  454. onGetList={() => getList()}
  455. onConfirm={(item: any) => {
  456. //
  457. router.push({
  458. path: '/prepare-lessons',
  459. query: {
  460. ...item
  461. }
  462. });
  463. }}
  464. onClose={() => (state.showSubjectClass = false)}
  465. />
  466. ) : null}
  467. </NModal>
  468. {/* 上课弹窗 */}
  469. <PreviewWindow
  470. v-model:show={state.previewModal}
  471. type="attend"
  472. params={state.previewParams}
  473. />
  474. <NModal
  475. v-model:show={state.removeVisiable}
  476. preset="card"
  477. class={['modalTitle', styles.removeVisiable]}
  478. title={'删除班级'}>
  479. <div class={styles.studentRemove}>
  480. <p>
  481. 确定要删除班级么?
  482. <span>删除班级信息将会清空</span>。
  483. </p>
  484. <NSpace class={styles.btnGroup} justify="center">
  485. <NButton round type="primary" onClick={removeClass}>
  486. 确定
  487. </NButton>
  488. <NButton round onClick={() => (state.removeVisiable = false)}>
  489. 取消
  490. </NButton>
  491. </NSpace>
  492. </div>
  493. </NModal>
  494. <NModal
  495. v-model:show={state.groupVisiable}
  496. preset="card"
  497. class={['modalTitle', styles.removeVisiable]}
  498. title={'创建群聊'}>
  499. <div class={styles.studentRemove}>
  500. <p style={{ textAlign: 'center' }}>是否创建班级群聊</p>
  501. <NSpace class={styles.btnGroup} justify="center">
  502. <NButton
  503. round
  504. type="primary"
  505. onClick={submitGroup}
  506. loading={state.groupBtnLoading}
  507. disabled={state.groupBtnLoading}>
  508. 确定
  509. </NButton>
  510. <NButton round onClick={() => (state.groupVisiable = false)}>
  511. 取消
  512. </NButton>
  513. </NSpace>
  514. </div>
  515. </NModal>
  516. {showGuide.value ? <ClassGuide></ClassGuide> : null}
  517. </div>
  518. );
  519. }
  520. });