index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. import classNames from "classnames";
  2. import { useCallback, useEffect, useMemo, useRef, useState } from "react";
  3. import { Button, Dropdown, Form, Input, Select, Table } from "antd";
  4. import { PlusOutlined } from "@ant-design/icons";
  5. import { useNavigate } from "react-router-dom";
  6. import { PageContainer } from "@/components";
  7. import { DageTableActions } from "@dage/pc-components";
  8. import style from "./index.module.scss";
  9. import {
  10. PUBLISH_STATUS_MAP,
  11. ASSESSMENT_TYPE_OPTIONS,
  12. PUBLISH_STATUS_OPTIONS,
  13. } from "../../../constants";
  14. import {
  15. deleteManageIndexApi,
  16. getManageIndexListApi,
  17. publishManageIndexApi,
  18. } from "@/api";
  19. import { debounce } from "lodash";
  20. import {
  21. ASS_INDEX_TYPE,
  22. IManageIndexDetail,
  23. PUBLISH_ENUM,
  24. WARNING_TYPE,
  25. } from "@/types";
  26. import { WarningModal } from "./components";
  27. const DEFAULT_PARAMS = {
  28. pageNum: 1,
  29. pageSize: 20,
  30. searchKey: "",
  31. status: "",
  32. type: "",
  33. };
  34. const ManagementIndexPage = () => {
  35. const navigate = useNavigate();
  36. const [form] = Form.useForm();
  37. const [loading, setLoading] = useState(false);
  38. const [params, setParams] = useState({
  39. ...DEFAULT_PARAMS,
  40. });
  41. const [total, setTotal] = useState(0);
  42. const [list, setList] = useState<IManageIndexDetail[]>([]);
  43. const [warningVisible, setWarningVisible] = useState(false);
  44. const [warningType, setWarningType] = useState(WARNING_TYPE.PUBLISH);
  45. const checkedItem = useRef<IManageIndexDetail | null>(null);
  46. const debounceSearch = useMemo(
  47. () =>
  48. debounce((changedVal: unknown, vals: any) => {
  49. setParams({ ...params, ...vals });
  50. }, 500),
  51. [params]
  52. );
  53. const paginationChange = useCallback(
  54. () => (pageNum: number, pageSize: number) => {
  55. setParams({ ...params, pageNum, pageSize });
  56. },
  57. [params]
  58. );
  59. const getList = useCallback(async () => {
  60. setLoading(true);
  61. try {
  62. const data = await getManageIndexListApi(params);
  63. setList(data.records);
  64. setTotal(data.total);
  65. } finally {
  66. setLoading(false);
  67. }
  68. }, [params]);
  69. const handleDelete = async (item: IManageIndexDetail) => {
  70. await deleteManageIndexApi(item.id);
  71. getList();
  72. };
  73. const handlePublish = async (id: number, stop?: boolean) => {
  74. await publishManageIndexApi(
  75. id,
  76. stop ? PUBLISH_ENUM.ENDED : PUBLISH_ENUM.PUBLISHED
  77. );
  78. getList();
  79. };
  80. const handleWarningConfirm = () => {
  81. if (!checkedItem.current) return;
  82. handlePublish(checkedItem.current.id, warningType === WARNING_TYPE.STOP);
  83. setWarningVisible(false);
  84. };
  85. useEffect(() => {
  86. getList();
  87. }, []);
  88. return (
  89. <PageContainer
  90. title="考核管理"
  91. headerSlot={
  92. <div>
  93. <Button
  94. type="primary"
  95. icon={<PlusOutlined />}
  96. size="large"
  97. className="second-button"
  98. onClick={() =>
  99. navigate("/management/index/create/" + ASS_INDEX_TYPE.FIXED)
  100. }
  101. >
  102. 新增定级评估考核
  103. </Button>
  104. <Button
  105. type="primary"
  106. icon={<PlusOutlined />}
  107. size="large"
  108. className="second-button"
  109. onClick={() =>
  110. navigate("/management/index/create/" + ASS_INDEX_TYPE.OPERATION)
  111. }
  112. >
  113. 新增运行评估考核
  114. </Button>
  115. </div>
  116. }
  117. >
  118. <div className={style.filter}>
  119. <Form
  120. form={form}
  121. layout="inline"
  122. className="inline-form"
  123. onValuesChange={debounceSearch}
  124. >
  125. <Form.Item label="考核类别">
  126. <div className="w160">
  127. <Form.Item noStyle name="type">
  128. <Select
  129. allowClear
  130. placeholder="请选择"
  131. options={ASSESSMENT_TYPE_OPTIONS}
  132. />
  133. </Form.Item>
  134. </div>
  135. </Form.Item>
  136. <Form.Item label="发布状态">
  137. <div className="w160">
  138. <Form.Item noStyle name="status">
  139. <Select
  140. allowClear
  141. placeholder="请选择"
  142. options={PUBLISH_STATUS_OPTIONS}
  143. />
  144. </Form.Item>
  145. </div>
  146. </Form.Item>
  147. <Form.Item label="搜索" name="searchKey">
  148. <Input allowClear className="w160" placeholder="请输入考核名称" />
  149. </Form.Item>
  150. <Form.Item>
  151. <Button type="primary" onClick={getList}>
  152. 查询
  153. </Button>
  154. </Form.Item>
  155. </Form>
  156. </div>
  157. <div className={style.table}>
  158. <Table
  159. loading={loading}
  160. className={classNames("cus-table large")}
  161. dataSource={list}
  162. rowKey="id"
  163. scroll={{ x: "max-content" }}
  164. columns={[
  165. {
  166. title: "名称",
  167. dataIndex: "name",
  168. align: "center",
  169. minWidth: 100,
  170. },
  171. {
  172. title: "类别",
  173. align: "center",
  174. minWidth: 100,
  175. render: (item: IManageIndexDetail) => {
  176. return ASSESSMENT_TYPE_OPTIONS.find(
  177. (i) => i.value === item.type
  178. )?.label;
  179. },
  180. },
  181. {
  182. title: "说明",
  183. dataIndex: "remark",
  184. align: "center",
  185. minWidth: 100,
  186. ellipsis: true,
  187. },
  188. {
  189. title: "考核周期",
  190. align: "center",
  191. minWidth: 100,
  192. render: (item: IManageIndexDetail) => {
  193. return `${item.dateStart}-${item.dateEnd}`;
  194. },
  195. },
  196. {
  197. title: "发布状态",
  198. align: "center",
  199. minWidth: 100,
  200. render: (item: IManageIndexDetail) => {
  201. return (
  202. <p style={{ color: PUBLISH_STATUS_MAP[item.status].color }}>
  203. {PUBLISH_STATUS_MAP[item.status].label}
  204. </p>
  205. );
  206. },
  207. },
  208. {
  209. title: "编辑时间",
  210. dataIndex: "updateTime",
  211. align: "center",
  212. minWidth: 160,
  213. },
  214. {
  215. title: "编辑人",
  216. dataIndex: "creatorName",
  217. align: "center",
  218. minWidth: 100,
  219. },
  220. {
  221. title: "操作",
  222. align: "center",
  223. fixed: "right",
  224. render: (item: IManageIndexDetail) => {
  225. const isPending = item.status === PUBLISH_ENUM.PENDING;
  226. const showStopBtn = [
  227. PUBLISH_ENUM.EVALUATED,
  228. PUBLISH_ENUM.PUBLISHED,
  229. ].includes(item.status);
  230. return (
  231. <DageTableActions
  232. showEdit={item.status === PUBLISH_ENUM.PENDING}
  233. onEdit={() =>
  234. navigate(`/management/index/edit/${item.type}/${item.id}`)
  235. }
  236. onDelete={handleDelete.bind(undefined, item)}
  237. renderBefore={
  238. <>
  239. <Button
  240. type="text"
  241. className={style.button}
  242. onClick={() =>
  243. navigate(`/management/index/detail/${item.id}`)
  244. }
  245. >
  246. 查看
  247. </Button>
  248. {isPending && (
  249. <Button
  250. variant="text"
  251. color="primary"
  252. className={style.button}
  253. onClick={() => {
  254. checkedItem.current = item;
  255. setWarningType(WARNING_TYPE.PUBLISH);
  256. setWarningVisible(true);
  257. }}
  258. >
  259. 发布
  260. </Button>
  261. )}
  262. {showStopBtn && (
  263. <Button
  264. variant="text"
  265. color="danger"
  266. className={style.button}
  267. onClick={() => {
  268. checkedItem.current = item;
  269. setWarningType(WARNING_TYPE.STOP);
  270. setWarningVisible(true);
  271. }}
  272. >
  273. 终止
  274. </Button>
  275. )}
  276. {isPending && (
  277. <Dropdown
  278. placement="bottom"
  279. arrow
  280. menu={{
  281. items: [
  282. {
  283. key: 1,
  284. label: (
  285. <p
  286. onClick={() =>
  287. navigate(
  288. `/management/index/setting-index/${item.type}/${item.id}`
  289. )
  290. }
  291. >
  292. 考核指标
  293. </p>
  294. ),
  295. },
  296. {
  297. key: 2,
  298. label: (
  299. <p
  300. onClick={() =>
  301. navigate(
  302. `/management/index/setting-role/${item.type}/${item.id}/${item.status}`
  303. )
  304. }
  305. >
  306. 考核角色
  307. </p>
  308. ),
  309. },
  310. ],
  311. }}
  312. >
  313. <Button type="text" className={style.button}>
  314. 设置
  315. </Button>
  316. </Dropdown>
  317. )}
  318. </>
  319. }
  320. />
  321. );
  322. },
  323. },
  324. ]}
  325. pagination={{
  326. showQuickJumper: true,
  327. position: ["bottomCenter"],
  328. showSizeChanger: true,
  329. current: params.pageNum,
  330. pageSize: params.pageSize,
  331. total,
  332. onChange: paginationChange(),
  333. }}
  334. />
  335. </div>
  336. <WarningModal
  337. type={warningType}
  338. open={warningVisible}
  339. onOk={handleWarningConfirm}
  340. onCancel={() => setWarningVisible(false)}
  341. />
  342. </PageContainer>
  343. );
  344. };
  345. export default ManagementIndexPage;