index.vue 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <template>
  2. <PageWrapper dense fixedHeight contentFullHeight contentClass="flex">
  3. <ClassTree class="w-1/3 xl:w-1/4" @select="handleChange" />
  4. <BasicTable
  5. class="w-3/4 xl:w-4/5"
  6. @register="registerTable"
  7. :row-selection="{ selectedRowKeys: selectedKeys, onChange: onSelectChange }"
  8. :searchInfo="searchInfo"
  9. >
  10. <template #toolbar>
  11. <a-button type="primary" v-auth="'student:add'" @click="handleAdd">新增</a-button>
  12. <Dropdown.Button v-auth="'student:import'">
  13. 数据导入
  14. <template #icon>
  15. <Icon icon="carbon:document-import" :size="16" />
  16. </template>
  17. <template #overlay>
  18. <Menu>
  19. <Menu.Item>
  20. <a-button block type="link" @click="handelDownloadTemplate"> 下载模板 </a-button>
  21. </Menu.Item>
  22. <Menu.Item>
  23. <Upload :showUploadList="false" :before-upload="beforeUpload">
  24. <a-button block type="link"> 导入 </a-button>
  25. </Upload>
  26. </Menu.Item>
  27. </Menu>
  28. </template>
  29. </Dropdown.Button>
  30. <Upload
  31. v-auth="'student:upload'"
  32. :showUploadList="false"
  33. :before-upload="handelBeforeUpload"
  34. accept=".rar,.zip"
  35. >
  36. <a-button block type="primary"> 导入学籍照 </a-button>
  37. </Upload>
  38. <ExportTool
  39. v-auth="'student:export'"
  40. ref="exportToolRef"
  41. type="student"
  42. @click="handelExportClick"
  43. />
  44. </template>
  45. <template #bodyCell="{ column, record }">
  46. <template v-if="column.dataIndex === 'action'">
  47. <TableAction
  48. :actions="[
  49. {
  50. label: '查看',
  51. auth: 'student:view',
  52. onClick: handleView.bind(null, record),
  53. },
  54. {
  55. label: '编辑',
  56. auth: 'student:edit',
  57. onClick: handleEdit.bind(null, record),
  58. },
  59. {
  60. label: '删除',
  61. color: 'error',
  62. auth: 'student:delete',
  63. onClick: handleDelete.bind(null, record),
  64. },
  65. ]"
  66. />
  67. </template>
  68. <template v-if="column.dataIndex === 'avatar'">
  69. <TableImg
  70. v-if="record.avatar"
  71. :size="40"
  72. :simpleShow="true"
  73. :showBadge="false"
  74. :imgList="[record.avatar]"
  75. />
  76. <div v-else></div>
  77. </template>
  78. </template>
  79. </BasicTable>
  80. <stdudentBaseManagerDrawer @register="registerDrawer" @success="handleSuccess" />
  81. </PageWrapper>
  82. </template>
  83. <script lang="ts" setup>
  84. import { computed, createVNode, onMounted, reactive, ref } from 'vue';
  85. import { Modal, Upload, Dropdown, Menu } from 'ant-design-vue';
  86. import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
  87. import { BasicTable, TableAction, useTable, TableImg } from '/@/components/Table';
  88. import { deleteXjrUser, getXjrUserPage } from '/@/api/dev/studentbasemanager';
  89. import { PageWrapper } from '/@/components/Page';
  90. import { useMessage } from '/@/hooks/web/useMessage';
  91. import { useI18n } from '/@/hooks/web/useI18n';
  92. import { useRouter } from 'vue-router';
  93. import { PrintButton } from '/@/enums/printEnum';
  94. import stdudentBaseManagerDrawer from './components/stdudentBaseManagerDrawer.vue';
  95. import { useDrawer } from '/@/components/Drawer';
  96. import { columns, searchFormSchema } from './components/config';
  97. import Icon from '/@/components/Icon/index';
  98. import ClassTree from '/@/views/educational/class/components/ClassGroup.vue';
  99. import {
  100. postStudentmanagerAvatarImport,
  101. postStudentmanagerImport,
  102. } from '/@/services/apis/StudentManagerController';
  103. import { downloadByUrl } from '/@/utils/file/download';
  104. import ExportTool from '/@/views/export/template/components/tool.vue';
  105. import { useLoading } from '/@/components/Loading';
  106. const exportToolRef = ref<ElRef>(null);
  107. const searchInfo = reactive<Recordable>({});
  108. const handelExportClick = (type) => {
  109. // if (searchInfo.treeType !== 4) {
  110. // createMessage.warning('请选择班级');
  111. // return;
  112. // }
  113. const data: Recordable = {
  114. conditions: [],
  115. ids: [],
  116. };
  117. if (type === 'all') {
  118. const formData = getForm().getFieldsValue();
  119. for (const key in formData) {
  120. data.conditions.push({ keyName: key, keyValue: formData[key], keyType: '1' });
  121. }
  122. if (searchInfo.treeId) {
  123. let keyName = '';
  124. switch (searchInfo.treeType) {
  125. case 1:
  126. keyName = 'deptId';
  127. break;
  128. case 2:
  129. keyName = 'majorId';
  130. break;
  131. case 3:
  132. keyName = 'gradeId';
  133. break;
  134. case 4:
  135. keyName = 'classId';
  136. break;
  137. default:
  138. keyName = 'deptId';
  139. break;
  140. }
  141. data.conditions.push({
  142. keyName: keyName,
  143. keyValue: searchInfo.treeId,
  144. keyType: '1',
  145. });
  146. }
  147. } else {
  148. const selectKeys = getSelectRowKeys();
  149. if (selectKeys.length === 0) {
  150. createMessage.warning('请选择需要导入的数据');
  151. return;
  152. }
  153. data.ids = selectKeys;
  154. }
  155. exportToolRef.value?.open(data);
  156. };
  157. onMounted(async () => {});
  158. const { notification, createMessage } = useMessage();
  159. const { t } = useI18n();
  160. defineEmits(['register']);
  161. const { currentRoute } = useRouter();
  162. const formIdComputedRef = computed(() => currentRoute.value.meta.formId as string);
  163. const selectedKeys = ref<string[]>([]);
  164. const selectedRowsData = ref<any[]>([]);
  165. const [registerDrawer, { openDrawer }] = useDrawer();
  166. const [registerTable, { reload, getForm, getSelectRowKeys }] = useTable({
  167. title: '学生信息列表',
  168. api: getXjrUserPage,
  169. rowKey: 'id',
  170. columns: columns,
  171. formConfig: {
  172. rowProps: {
  173. gutter: 16,
  174. },
  175. schemas: searchFormSchema,
  176. fieldMapToTime: [],
  177. },
  178. beforeFetch: (params) => {
  179. return { ...params, FormId: formIdComputedRef.value, PK: 'id' };
  180. },
  181. useSearchForm: true,
  182. showTableSetting: true,
  183. striped: true,
  184. bordered: true,
  185. immediate: true,
  186. actionColumn: {
  187. width: 150,
  188. title: '操作',
  189. dataIndex: 'action',
  190. slots: { customRender: 'action' },
  191. },
  192. customRow,
  193. });
  194. function handleAdd() {
  195. openDrawer(true, {
  196. isUpdate: false,
  197. });
  198. }
  199. function handleEdit(record: Recordable) {
  200. openDrawer(true, {
  201. id: record.id,
  202. isUpdate: true,
  203. });
  204. }
  205. function handleDelete(record: Recordable) {
  206. deleteList([record.id]);
  207. }
  208. const handleChange = (data) => {
  209. searchInfo.treeId = data.id;
  210. searchInfo.treeType = data.type;
  211. reload();
  212. };
  213. function deleteList(ids) {
  214. Modal.confirm({
  215. title: '提示信息',
  216. icon: createVNode(ExclamationCircleOutlined),
  217. content: '是否确认删除?',
  218. okText: '确认',
  219. cancelText: '取消',
  220. onOk() {
  221. deleteXjrUser(ids).then((_) => {
  222. reload();
  223. notification.success({
  224. message: 'Tip',
  225. description: t('删除成功!'),
  226. });
  227. });
  228. },
  229. onCancel() {},
  230. });
  231. }
  232. function onSelectChange(selectedRowKeys: [], selectedRows) {
  233. selectedKeys.value = selectedRowKeys;
  234. selectedRowsData.value = selectedRows;
  235. }
  236. function customRow(record: Recordable) {
  237. return {
  238. onClick: () => {
  239. let selectedRowKeys = [...selectedKeys.value];
  240. if (selectedRowKeys.indexOf(record.id) >= 0) {
  241. let index = selectedRowKeys.indexOf(record.id);
  242. selectedRowKeys.splice(index, 1);
  243. } else {
  244. selectedRowKeys.push(record.id);
  245. }
  246. selectedKeys.value = selectedRowKeys;
  247. },
  248. };
  249. }
  250. function handleSuccess() {
  251. reload();
  252. }
  253. function handleView(record: Recordable) {
  254. openDrawer(true, {
  255. isView: true,
  256. id: record.id,
  257. });
  258. }
  259. function handelDownloadTemplate() {
  260. downloadByUrl({
  261. url: 'https://zhxy.cqtlzjzx.com/minio/static/resources/%E5%AD%A6%E7%94%9F%E6%A8%A1%E6%9D%BF.xlsx',
  262. fileName: '学生信息模板',
  263. });
  264. }
  265. const [openFullLoading, closeFullLoading] = useLoading({
  266. tip: '处理中...',
  267. });
  268. const handelBeforeUpload = async (e) => {
  269. try {
  270. openFullLoading();
  271. await postStudentmanagerAvatarImport({ file: e });
  272. closeFullLoading();
  273. createMessage.success('导入成功');
  274. reload();
  275. } catch {
  276. closeFullLoading();
  277. }
  278. return false;
  279. };
  280. const beforeUpload = async (e) => {
  281. try {
  282. openFullLoading();
  283. await postStudentmanagerImport({ file: e });
  284. closeFullLoading();
  285. createMessage.success('导入成功');
  286. reload();
  287. } catch {
  288. closeFullLoading();
  289. }
  290. return false;
  291. };
  292. </script>
  293. <style lang="less" scoped>
  294. :deep(.ant-table-selection-col) {
  295. width: 50px;
  296. }
  297. </style>