TaskList.tsx 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. import PageContent from '@/components/PageContent';
  2. import PageTitle from '@/components/PageTitle';
  3. import {
  4. IPropsType,
  5. ITopFilter,
  6. IUserType,
  7. } from '@/pages/TaskManage/Detail/TaskList/taskList.types';
  8. import {
  9. MandateClass,
  10. MandateStatus,
  11. MandateType,
  12. OrderStatus,
  13. OrderType,
  14. } from '@/pages/TaskManage/constent';
  15. import { connect, useLocation, useRequest } from '@umijs/max';
  16. import TopFilter from '@/pages/TaskManage/components/TopFilter';
  17. import { IMandateType } from '@/pages/TaskManage/index.types';
  18. import { useNavigate } from '@@/exports';
  19. import { DownOutlined } from '@ant-design/icons';
  20. import { Col, Collapse, CollapseProps, Divider, List, Row } from 'antd';
  21. import ScrollLoading from '@/components/ScrollLoading';
  22. import { getMandateList } from '@/services/TaskManage';
  23. import dayjs from 'dayjs';
  24. import { useEffect, useState } from 'react';
  25. import styles from './taskList.less';
  26. const TaskList: React.FC<IPropsType> = (props) => {
  27. const { userList, loading, dispatch } = props;
  28. const location = useLocation();
  29. const queryParams = new URLSearchParams(location.search);
  30. const project_id = Number(queryParams.get('project_id'));
  31. const mandateType = Number(queryParams.get('mandateType'));
  32. const navigate = useNavigate();
  33. // 顶部选择器配置
  34. const [topFiltersConfig, setTopFiltersConfig] = useState<ITopFilter[]>([]);
  35. const [mandateList, setMandateList] = useState<IMandateType[]>([]);
  36. const [currentParams, setCurrentParams] = useState({
  37. project_id,
  38. mandate_type: mandateType,
  39. pageSize: 20,
  40. currentPage: 1,
  41. });
  42. const [pagination, setPagination] = useState({
  43. current: 1,
  44. total: 0,
  45. pageSize: 20,
  46. });
  47. const { run: getList, loading: loadData } = useRequest(getMandateList, {
  48. defaultParams: [
  49. {
  50. ...currentParams,
  51. },
  52. ],
  53. formatResult: (result) => {
  54. const pageInfo = result.data.pagination;
  55. if (result.data.pagination.current === 1) {
  56. setMandateList(result.data.list);
  57. } else {
  58. if (mandateList.length < pageInfo.total) {
  59. setMandateList([...mandateList, ...result.data.list]);
  60. }
  61. }
  62. setPagination(pageInfo);
  63. },
  64. });
  65. // 获取用户
  66. useEffect(() => {
  67. if (userList.length === 0) {
  68. dispatch({
  69. type: 'taskUser/fetchUserList',
  70. payload: { project_id },
  71. });
  72. }
  73. }, []);
  74. // 配置顶部下拉过滤器
  75. useEffect(() => {
  76. const filters: ITopFilter[] = [];
  77. filters.push({
  78. key: 'mandate_class',
  79. placeholder: '任务类别',
  80. // @ts-ignore
  81. options: MandateClass.map((item) => {
  82. if (item.MandateType === mandateType) {
  83. return {
  84. value: item.value,
  85. label: item.label,
  86. key: item.value + '任务类别',
  87. };
  88. }
  89. return undefined;
  90. }).filter((item) => item),
  91. });
  92. filters.push({
  93. key: 'status',
  94. placeholder: '任务状态',
  95. options: MandateStatus.map((item) => {
  96. return {
  97. ...item,
  98. };
  99. }),
  100. });
  101. setTopFiltersConfig(filters);
  102. }, [mandateType]);
  103. /**
  104. * 处理选择器变化
  105. * @param value 选择的值,当清空时等于null
  106. */
  107. const onTopFilterChange = (value: any) => {
  108. if (topFiltersConfig.length === 0) {
  109. return;
  110. }
  111. const params: any = {
  112. project_id,
  113. mandate_type: mandateType,
  114. pageSize: 20,
  115. currentPage: 1,
  116. };
  117. for (let i = 0; i < value.length; i++) {
  118. if (value[i] !== null && topFiltersConfig[i] !== undefined) {
  119. params[topFiltersConfig[i].key] = value[i];
  120. }
  121. }
  122. setCurrentParams(params);
  123. getList(params);
  124. };
  125. const goTaskDetail = (mandate: IMandateType) => {
  126. navigate(
  127. `/task-manage/list/detail?project_id=${project_id}&mandate_id=${mandate.Id}`,
  128. );
  129. };
  130. const goTaskOrder = (
  131. orderID: number,
  132. orderType: number | undefined,
  133. mandateClass: number,
  134. ) => {
  135. if (orderType === undefined) {
  136. return;
  137. }
  138. navigate(
  139. `/task-manage/list/order-detail?project_id=${project_id}&order_id=${orderID}&order_type=${orderType}&mandate_class=${mandateClass}`,
  140. );
  141. };
  142. const buildTaskList = (item: IMandateType) => {
  143. const formatItem = {
  144. ...item,
  145. Status: MandateStatus.find((status) => status.value === item.Status),
  146. MandateType: MandateType.find((type) => type.value === item.MandateType),
  147. MandateClass: MandateClass.find(
  148. (itemClass) => itemClass.value === item.MandateClass,
  149. ),
  150. ResponsiblePeople: userList.find(
  151. (user) => user.ID === item.ResponsiblePeople,
  152. ),
  153. CreateTime: dayjs(item.CreateTime).format('YYYY-MM-DD HH:mm'),
  154. };
  155. const workOrder = item.Records.map((record) => {
  156. return {
  157. ...record,
  158. key: record.Id,
  159. Status: OrderStatus.find((status) => status.value === record.Status),
  160. RecordType: OrderType.find((type) => type.value === record.RecordType),
  161. Responsible: userList.find((user) => user.ID === record.Responsible),
  162. CreateTime: dayjs(record.CreateTime).format('YYYY-MM-DD HH:mm'),
  163. };
  164. });
  165. const collapseData: CollapseProps['items'] = [
  166. {
  167. key: '1',
  168. label: (
  169. <span style={{ color: '#5697e4' }}>关联工单({workOrder.length})</span>
  170. ),
  171. children: workOrder.map((order) => {
  172. return (
  173. <div key={order.Id} className={styles.workOrderCard}>
  174. <div className={styles.leftInfo}>
  175. <Row style={{ marginBottom: '15px' }}>
  176. <Col className={styles.fontS24} span={12}>
  177. 工单类型:{order.RecordType?.label || '-'}
  178. </Col>
  179. <Col className={styles.fontS24} span={12}>
  180. 时间:{order.CreateTime}
  181. </Col>
  182. </Row>
  183. <Row>
  184. <Col className={styles.fontS24} span={12}>
  185. 工单状态:
  186. <span style={{ color: '#5697e4' }}>
  187. {order.Status?.label}
  188. </span>
  189. </Col>
  190. <Col className={styles.fontS24} span={12}>
  191. 工单负责人:{order.Responsible?.CName}
  192. </Col>
  193. </Row>
  194. </div>
  195. <Divider type="vertical" style={{ height: '40px' }} />
  196. <div
  197. className={styles.rightButton}
  198. style={{ color: '#5697e4' }}
  199. onClick={() => {
  200. goTaskOrder(
  201. order.Id,
  202. order.RecordType?.value,
  203. item.MandateClass,
  204. );
  205. }}
  206. >
  207. 查看工单
  208. </div>
  209. </div>
  210. );
  211. }),
  212. },
  213. ];
  214. return (
  215. <List.Item style={{ borderBottom: '0' }}>
  216. <div className={`${styles.cardContainer} card-box`}>
  217. <Row justify="space-between" style={{ marginBottom: '20px' }}>
  218. <Col className={styles.fontS24}>时间:{formatItem.CreateTime}</Col>
  219. <Col className={styles.fontS24}>
  220. 任务类别:{formatItem.MandateClass?.label}
  221. </Col>
  222. <Col className={styles.fontS24}>
  223. 任务负责人:{formatItem.ResponsiblePeople?.CName || '-'}
  224. </Col>
  225. </Row>
  226. <Row
  227. justify="space-between"
  228. style={{
  229. paddingBottom: '10px',
  230. borderBottom: '1px solid #D5D5D5',
  231. }}
  232. >
  233. <Col className={styles.fontS24}>
  234. 任务状态:{formatItem.Status?.label || '-'}
  235. </Col>
  236. <Col>
  237. <div
  238. className={styles.fontS24}
  239. style={{
  240. backgroundColor: '#f5a623',
  241. color: 'white',
  242. width: '150px',
  243. height: '50px',
  244. display: 'flex',
  245. justifyContent: 'center',
  246. alignItems: 'center',
  247. }}
  248. onClick={() => {
  249. goTaskDetail(item);
  250. }}
  251. >
  252. 任务详情
  253. </div>
  254. </Col>
  255. </Row>
  256. <Row>
  257. <Collapse
  258. className={styles.collapseLabel}
  259. ghost
  260. expandIcon={({ isActive }) => (
  261. <DownOutlined
  262. style={{ color: '#5697e4' }}
  263. rotate={isActive ? 180 : 0}
  264. />
  265. )}
  266. items={collapseData}
  267. />
  268. </Row>
  269. </div>
  270. </List.Item>
  271. );
  272. };
  273. return (
  274. <PageContent closeable={false}>
  275. <PageTitle returnable>
  276. {MandateType.find((item) => item.value === mandateType)?.label}
  277. </PageTitle>
  278. <TopFilter filters={topFiltersConfig} onChange={onTopFilterChange} />
  279. <ScrollLoading
  280. height={180}
  281. loading={loading || loadData}
  282. pagination={pagination}
  283. handleLoadData={(current: number) =>
  284. getList({ ...currentParams, currentPage: current })
  285. }
  286. >
  287. <List
  288. itemLayout="horizontal"
  289. dataSource={mandateList}
  290. renderItem={buildTaskList}
  291. />
  292. </ScrollLoading>
  293. </PageContent>
  294. );
  295. };
  296. export default connect(
  297. ({
  298. taskUser,
  299. mandate,
  300. loading,
  301. }: any): {
  302. userList: IUserType[];
  303. loading: boolean;
  304. } => {
  305. return {
  306. userList: taskUser.userList,
  307. loading: loading.models['taskUser'],
  308. };
  309. },
  310. )(TaskList);