index.tsx 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import { toSelectOptions } from '@/common/converter';
  2. import { SuperTable, TabBadge } from '@/components';
  3. import NceePlanController from '@/services/apis/NceePlanController';
  4. import { ExamStatus } from '@/services/enums';
  5. import { PlusOutlined } from '@ant-design/icons';
  6. import { ActionType, PageContainer, ProColumns } from '@ant-design/pro-components';
  7. import { history, useModel } from '@umijs/max';
  8. import { App, Button } from 'antd';
  9. import { useCallback, useRef, useState } from 'react';
  10. import NceePlanEditModal from './components/NceePlanEditModal';
  11. /** 高中分析计划 */
  12. const NceePlanList: React.FC = () => {
  13. const actionRef = useRef<ActionType>();
  14. const currentRef = useRef<Partial<API.NceePlanOutput>>();
  15. const [activeKey, setActiveKey] = useState<React.Key>('0');
  16. const [statusCount, seStatusCount] = useState<Record<number, number>>({});
  17. const [editShow, setEditShow] = useState(false);
  18. const { message, modal } = App.useApp();
  19. const { getDictValueEnum, getDict } = useModel('useDict');
  20. const { baseData } = useModel('useBaseData');
  21. // 加载数量统计
  22. const loadCount = useCallback(async (params: API.NceePlanPageInput) => {
  23. const m = await NceePlanController.queryStatusCount(params);
  24. const tc = m?.reduce((a, b) => a + b.count, 0) ?? 0;
  25. const d: Record<number, number> = { 0: tc };
  26. m?.forEach((t) => { d[t.status] = t.count; });
  27. seStatusCount(d);
  28. }, []);
  29. // 呈现状态 tab
  30. const renderTabItems = useCallback(() => {
  31. let items: { key: string; label: React.ReactNode }[] = [{
  32. key: '0',
  33. label: (<span>全部<TabBadge count={statusCount[0]} active={activeKey === 0} /></span>),
  34. }];
  35. items = items.concat(
  36. getDict('exam_status')?.map((t) => ({
  37. key: `${t.value}`,
  38. label: (
  39. <span>
  40. {t.name}
  41. <TabBadge color={t.antColor} count={statusCount[t.value] ?? 0} active={activeKey === `${t.value}`} />
  42. </span>
  43. ),
  44. })),
  45. );
  46. return items;
  47. }, [activeKey, statusCount]);
  48. // 删除
  49. const handleDelete = useCallback((id: number) => {
  50. modal.confirm({
  51. title: '警告',
  52. content: '确定立即删除吗',
  53. okText: '确定',
  54. cancelText: '取消',
  55. centered: true,
  56. onOk: async () => {
  57. await NceePlanController.del({ id });
  58. message.success('已删除');
  59. actionRef.current?.reload();
  60. },
  61. });
  62. }, []);
  63. const columns: ProColumns<API.NceePlanOutput>[] = [
  64. {
  65. title: '计划全称',
  66. dataIndex: 'fullName',
  67. renderText: (v, r) => <a onClick={() => history.push(`/ncee/plan/detail/${r.id}`)}>{v}</a>,
  68. hideInDescriptions: true,
  69. },
  70. {
  71. title: '计划全称',
  72. dataIndex: 'fullName',
  73. hideInTable: true,
  74. hideInSearch: true,
  75. },
  76. {
  77. title: '计划名称',
  78. dataIndex: 'name',
  79. hideInSearch: true,
  80. hideInTable: true,
  81. },
  82. {
  83. title: '计划简称',
  84. dataIndex: 'shortName',
  85. hideInSearch: true,
  86. hideInTable: true,
  87. },
  88. {
  89. title: '年级',
  90. dataIndex: ['grade', 'shortName'],
  91. align: 'center',
  92. search: {
  93. transform: v => ({ gradeId: v }),
  94. },
  95. hideInSearch: true,
  96. },
  97. {
  98. title: '计划状态',
  99. dataIndex: 'status',
  100. valueEnum: getDictValueEnum('exam_status', true),
  101. width: 80,
  102. align: 'center',
  103. hideInDescriptions: true,
  104. },
  105. {
  106. title: '学期',
  107. dataIndex: ['semester', 'nickShortName'],
  108. search: {
  109. transform: (v) => v ? ({ semesterId: JSON.parse(v) }) : v,
  110. },
  111. valueType: 'select',
  112. fieldProps: {
  113. options: toSelectOptions(baseData?.semesters ?? [], (item) => ({ key: item.id, label: item.nickShortName, value: item.id })),
  114. },
  115. width: 80,
  116. align: 'center',
  117. },
  118. {
  119. title: '开始时间',
  120. dataIndex: 'beginTime',
  121. hideInSearch: true,
  122. hideInTable: true,
  123. },
  124. {
  125. title: '结束时间',
  126. dataIndex: 'endTime',
  127. hideInSearch: true,
  128. hideInTable: true,
  129. },
  130. {
  131. title: '备注说明',
  132. dataIndex: 'remark',
  133. hideInSearch: true,
  134. className: 'minw-120',
  135. },
  136. {
  137. title: '创建人',
  138. dataIndex: ['createSysUser', 'name'],
  139. hideInSearch: true,
  140. hideInTable: true,
  141. },
  142. {
  143. title: '创建时间',
  144. dataIndex: 'createTime',
  145. align: 'center',
  146. width: 144,
  147. valueType: 'dateRange',
  148. colSize: 2,
  149. render: (_, r) => r.createTime,
  150. search: {
  151. transform: (v) => v ? ({
  152. searchBeginTime: v[0],
  153. searchEndTime: v[1],
  154. }) : ({}),
  155. },
  156. },
  157. {
  158. title: '操作',
  159. valueType: 'option',
  160. width: 112,
  161. align: 'center',
  162. fixed: 'right',
  163. render: (_, r) => {
  164. let ops: React.ReactNode[] = [];
  165. if (r.status === ExamStatus.READY) {
  166. ops.push(<Button key="edit" type="link" size="small" onClick={() => { currentRef.current = r; setEditShow(true); }}>修改</Button>);
  167. ops.push(<Button key="del" type="link" size="small" onClick={() => handleDelete(r.id)}>删除</Button>);
  168. }
  169. return <>{ops}</>;
  170. },
  171. },
  172. ];
  173. return (
  174. <PageContainer title={false}>
  175. <SuperTable<API.NceePlanOutput>
  176. actionRef={actionRef}
  177. columns={columns}
  178. scroll={{ x: 'max-content' }}
  179. request={async (params, sort) => {
  180. try {
  181. return SuperTable.requestPageAgent({ params, sort }, async (p) => {
  182. await loadCount(p);
  183. const res = await NceePlanController.queryPageList({
  184. ...p,
  185. status: activeKey !== '0' ? parseInt(activeKey as string) : undefined,
  186. });
  187. return res;
  188. });
  189. }
  190. catch (ex) { return {}; }
  191. }}
  192. toolbar={{
  193. menu: {
  194. type: 'tab',
  195. activeKey: activeKey,
  196. items: renderTabItems(),
  197. onChange: (key) => {
  198. setActiveKey(key as React.Key);
  199. actionRef.current?.reload();
  200. },
  201. },
  202. actions: [
  203. <Button
  204. key="add"
  205. type="primary"
  206. icon={<PlusOutlined />}
  207. onClick={() => { currentRef.current = { id: 0 }; setEditShow(true); }}
  208. >创建分析计划</Button>,
  209. ],
  210. }}
  211. />
  212. {editShow && currentRef.current &&
  213. <NceePlanEditModal
  214. data={currentRef.current}
  215. onFinish={() => actionRef.current?.reload()}
  216. onClose={() => setEditShow(false)}
  217. />
  218. }
  219. </PageContainer>
  220. );
  221. };
  222. export default NceePlanList;