index.tsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. import { defineComponent, onMounted, reactive, 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. NSelect,
  11. NSpace,
  12. useMessage
  13. } from 'naive-ui';
  14. import SearchInput from '@/components/searchInput';
  15. import CSelect from '@/components/CSelect';
  16. import Pagination from '@/components/pagination';
  17. import add from './images/add.png';
  18. import { useRoute, useRouter } from 'vue-router';
  19. import { getStudentList, schoolDetail } from './api';
  20. import { classGroupList } from '@/views/classList/api';
  21. import AddStudentModel from './modals/addStudentModel';
  22. import Studentguide from '@/custom-plugins/guide-page/student-guide';
  23. import TheEmpty from '/src/components/TheEmpty';
  24. import NoticeModal from './modals/noticeModal';
  25. import { useUserStore } from '/src/store/modules/users';
  26. export default defineComponent({
  27. name: 'student-studentList',
  28. setup(props, { emit }) {
  29. const userStore = useUserStore();
  30. const state = reactive({
  31. searchForm: {
  32. keyword: '',
  33. gender: null as any,
  34. classGroupId: null as any,
  35. membership: null as any
  36. },
  37. searchWord: '',
  38. orchestraType: null,
  39. courseTypeCode: null,
  40. subjectId: null,
  41. classId: null,
  42. studentType: null,
  43. loading: false,
  44. pagination: {
  45. page: 1,
  46. rows: 10,
  47. pageTotal: 4
  48. },
  49. tableList: [] as any,
  50. classList: [],
  51. addStudentVisible: false,
  52. activeRow: {} as any
  53. });
  54. const route = useRoute();
  55. const router = useRouter();
  56. const showGuide = ref(false);
  57. const message = useMessage();
  58. const search = () => {
  59. state.pagination.page = 1;
  60. getList();
  61. };
  62. const getClasslist = async () => {
  63. try {
  64. const res = await classGroupList({ page: 1, rows: 999 });
  65. state.classList = res.data.rows.map((item: any) => {
  66. return {
  67. label: item.name,
  68. value: item.id
  69. };
  70. });
  71. } catch (e) {
  72. console.log(e);
  73. }
  74. };
  75. const copyTo = (text: string) => {
  76. const input = document.createElement('input');
  77. input.value = text;
  78. document.body.appendChild(input);
  79. input.select();
  80. input.setSelectionRange(0, input.value.length);
  81. document.execCommand('Copy');
  82. document.body.removeChild(input);
  83. message.success('复制成功');
  84. };
  85. const onReset = () => {
  86. state.searchForm = {
  87. keyword: '',
  88. gender: null as any,
  89. classGroupId: null as any,
  90. membership: null as any
  91. };
  92. search();
  93. };
  94. const getList = async () => {
  95. try {
  96. const res = await getStudentList({
  97. ...state.searchForm,
  98. ...state.pagination
  99. });
  100. state.tableList = res.data.rows;
  101. state.pagination.pageTotal = res.data.total;
  102. if (state.tableList.length > 0) {
  103. setTimeout(() => {
  104. showGuide.value = true;
  105. }, 500);
  106. }
  107. } catch (e) {
  108. console.log(e);
  109. }
  110. console.log('getList');
  111. };
  112. onMounted(() => {
  113. getList();
  114. getClasslist();
  115. });
  116. const columns = () => {
  117. return [
  118. {
  119. title: '学生姓名',
  120. key: 'nickname',
  121. render: (row: any) => {
  122. return (
  123. <div
  124. style={{ userSelect: 'all', cursor: 'pointer' }}
  125. onClick={() => copyTo(row.nickname)}>
  126. {row.nickname}
  127. </div>
  128. );
  129. }
  130. },
  131. {
  132. title: '手机号',
  133. key: 'phone',
  134. render: (row: any) => {
  135. return (
  136. <div
  137. style={{ userSelect: 'all', cursor: 'pointer' }}
  138. onClick={() => copyTo(row.phone)}>
  139. {row.phone}
  140. </div>
  141. );
  142. }
  143. },
  144. {
  145. title: '性别',
  146. key: 'gender',
  147. render(row: any) {
  148. return (
  149. <>
  150. {row.gender + '' != 'null'
  151. ? row.gender == '0'
  152. ? '女'
  153. : '男'
  154. : '--'}
  155. </>
  156. );
  157. }
  158. },
  159. {
  160. title: '年级班级',
  161. key: 'classGroupName'
  162. },
  163. {
  164. title: '学生类型',
  165. key: 'vipMember',
  166. render(row: any) {
  167. return <>{row.vipMember ? '会员' : '普通'}</>;
  168. }
  169. },
  170. {
  171. title: '操作',
  172. key: 'id',
  173. width: 300,
  174. render(row: any, index: number) {
  175. return (
  176. <>
  177. {index == 0 ? (
  178. <NButton
  179. {...{ id: 'student-1' }}
  180. text
  181. type="primary"
  182. onClick={() => gotoDetail(row)}>
  183. 详情
  184. </NButton>
  185. ) : (
  186. <NButton text type="primary" onClick={() => gotoDetail(row)}>
  187. 详情
  188. </NButton>
  189. )}
  190. </>
  191. );
  192. }
  193. }
  194. ];
  195. };
  196. const gotoDetail = (row: any) => {
  197. router.push({
  198. path: '/studentDetail',
  199. query: { ...route.query, studentId: row.id, studentName: row.nickname }
  200. });
  201. };
  202. return () => (
  203. <div class={styles.listWrap}>
  204. <div class={styles.searchList}>
  205. <NForm label-placement="left" inline>
  206. <NFormItem>
  207. <SearchInput
  208. {...{ placeholder: '请输入学生姓名' }}
  209. class={styles.searchInput}
  210. searchWord={state.searchForm.keyword}
  211. onChangeValue={(val: string) =>
  212. (state.searchForm.keyword = val)
  213. }></SearchInput>
  214. </NFormItem>
  215. <NFormItem>
  216. <CSelect
  217. {...({
  218. options: [
  219. {
  220. label: '学生性别',
  221. value: null
  222. },
  223. {
  224. label: '男',
  225. value: 1
  226. },
  227. {
  228. label: '女',
  229. value: 0
  230. }
  231. ],
  232. placeholder: '性别',
  233. clearable: true,
  234. inline: true
  235. } as any)}
  236. v-model:value={state.searchForm.gender}></CSelect>
  237. </NFormItem>
  238. <NFormItem>
  239. <CSelect
  240. {...({
  241. options: [
  242. { label: '年级班级', value: null },
  243. ...state.classList
  244. ],
  245. placeholder: '年级班级',
  246. clearable: true,
  247. inline: true
  248. } as any)}
  249. v-model:value={state.searchForm.classGroupId}></CSelect>
  250. </NFormItem>
  251. <NFormItem>
  252. <CSelect
  253. {...({
  254. options: [
  255. {
  256. label: '学生类型',
  257. value: null
  258. },
  259. {
  260. label: '会员',
  261. value: true
  262. },
  263. {
  264. label: '普通',
  265. value: false
  266. }
  267. ],
  268. placeholder: '学生类型',
  269. clearable: true,
  270. inline: true
  271. } as any)}
  272. v-model:value={state.searchForm.membership}></CSelect>
  273. </NFormItem>
  274. <NFormItem>
  275. <NSpace justify="end">
  276. <NButton type="primary" class="searchBtn" onClick={search}>
  277. 搜索
  278. </NButton>
  279. <NButton
  280. type="primary"
  281. ghost
  282. class="resetBtn"
  283. onClick={onReset}>
  284. 重置
  285. </NButton>
  286. </NSpace>
  287. </NFormItem>
  288. </NForm>
  289. </div>
  290. <NButton
  291. {...{ id: 'student-0' }}
  292. onClick={async () => {
  293. // state.addStudentVisible = true;
  294. try {
  295. const { schoolInfos } = userStore.getUserInfo;
  296. const schoolId =
  297. schoolInfos.length > 0 ? schoolInfos[0].id : null;
  298. if (schoolId) {
  299. const { data } = await schoolDetail({ id: schoolId });
  300. state.activeRow = data;
  301. state.addStudentVisible = true;
  302. }
  303. } catch {
  304. //
  305. }
  306. }}
  307. class={styles.addBtn}
  308. type="primary"
  309. v-slots={{
  310. icon: () => (
  311. <>
  312. <NImage
  313. class={styles.addBtnIcon}
  314. previewDisabled
  315. src={add}></NImage>
  316. </>
  317. )
  318. }}>
  319. 邀请学生
  320. </NButton>
  321. <div class={styles.tableWrap}>
  322. <NDataTable
  323. v-slots={{
  324. empty: () => <TheEmpty></TheEmpty>
  325. }}
  326. class={styles.classTable}
  327. loading={state.loading}
  328. columns={columns()}
  329. data={state.tableList}></NDataTable>
  330. <Pagination
  331. v-model:page={state.pagination.page}
  332. v-model:pageSize={state.pagination.rows}
  333. v-model:pageTotal={state.pagination.pageTotal}
  334. onList={getList}
  335. sync
  336. />
  337. </div>
  338. {/* {state.addStudentVisible ? (
  339. <div v-model:show={state.addStudentVisible} class="n-modal-mask">
  340. <AddStudentModel
  341. onClose={() => {
  342. state.addStudentVisible = false;
  343. }}></AddStudentModel>
  344. </div>
  345. ) : null} */}
  346. <NModal
  347. v-model:show={state.addStudentVisible}
  348. showIcon={false}
  349. style={{ width: '400px' }}>
  350. <NoticeModal
  351. data={state.activeRow}
  352. onClose={() => (state.addStudentVisible = false)}
  353. />
  354. </NModal>
  355. {showGuide.value ? <Studentguide></Studentguide> : null}
  356. </div>
  357. );
  358. }
  359. });