index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. import React, {
  2. useCallback,
  3. useEffect,
  4. useMemo,
  5. useRef,
  6. useState,
  7. } from "react";
  8. import styles from "./index.module.scss";
  9. import { Button, Cascader, Input, Select, Table, Tooltip } from "antd";
  10. import { useSelector } from "react-redux";
  11. import { RootState } from "@/store";
  12. import {
  13. A1_APIIdowns,
  14. A1_APIIgetIresList,
  15. A1_APIIgetList,
  16. } from "@/store/action/A1Project";
  17. import { A1ItableType } from "@/types";
  18. import { authFilesLookFu, urlChangeFu } from "@/utils/authFilesLook";
  19. import A1IRemove from "./A1IRemove";
  20. import A1ILack from "./A1ILack";
  21. import A1IAudit from "./A1IAudit";
  22. import A1IupFile from "./A1IupFile";
  23. import { baseUpUrl } from "@/utils/http";
  24. import { A2Tab2Type } from "@/types/api/A2Dict";
  25. import AuthCom from "@/components/AuthCom";
  26. type FromType = {
  27. searchKey: string;
  28. attrId: number | "";
  29. deptId: any;
  30. auditStatus: 0 | 1 | 2 | "";
  31. projectId: number;
  32. };
  33. type Props = {
  34. projectId: number;
  35. myTitle: string;
  36. projectName: string;
  37. };
  38. function A1Inner({ projectId, myTitle, projectName }: Props) {
  39. // 表单数据
  40. const [fromData, setFromData] = useState<FromType>({
  41. searchKey: "",
  42. attrId: "",
  43. deptId: [""],
  44. auditStatus: "",
  45. projectId,
  46. });
  47. // 关于表格的多选
  48. const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
  49. const getListFu = useCallback(async () => {
  50. // 处理级联为最后一级的id
  51. let deptId: "" | number = "";
  52. if (fromData.deptId && fromData.deptId[0]) {
  53. deptId = Number(fromData.deptId[fromData.deptId.length - 1]);
  54. }
  55. const obj = {
  56. ...fromData,
  57. deptId,
  58. };
  59. const res = await A1_APIIgetList(obj);
  60. if (res.code === 0) {
  61. // 清空选中
  62. setSelectedRowKeys([]);
  63. setData(res.data);
  64. }
  65. }, [fromData]);
  66. useEffect(() => {
  67. getListFu();
  68. }, [getListFu]);
  69. const fromTime = useRef(-1);
  70. // 搜索项 的输入
  71. const searchKeyChange = useCallback(
  72. (e: React.ChangeEvent<HTMLInputElement>) => {
  73. clearTimeout(fromTime.current);
  74. fromTime.current = window.setTimeout(() => {
  75. setFromData({
  76. ...fromData,
  77. searchKey: e.target.value,
  78. });
  79. }, 500);
  80. },
  81. [fromData]
  82. );
  83. // 获取 内控文件属性 下拉 数据(已过滤权限)
  84. const [iResList, setIResList] = useState<A2Tab2Type[]>([]);
  85. const getIresListFu = useCallback(async () => {
  86. const res = await A1_APIIgetIresList();
  87. if (res.code === 0) {
  88. setIResList(res.data);
  89. }
  90. }, []);
  91. useEffect(() => {
  92. getIresListFu();
  93. }, [getIresListFu]);
  94. // 从仓库获取部门 级联 信息
  95. const deptList = useSelector((state: RootState) => state.A5Section.tableList);
  96. // 表格信息
  97. const [data, setData] = useState<A1ItableType[]>([]);
  98. // 点击批量下载
  99. const downSelectFu = useCallback(async () => {
  100. const res = await A1_APIIdowns(selectedRowKeys.join(","));
  101. if (res.code === 0) {
  102. // console.log(123,res.data);
  103. urlChangeFu(res.data, true, undefined, projectName + "(内)");
  104. // 清空选中
  105. setSelectedRowKeys([]);
  106. }
  107. }, [projectName, selectedRowKeys]);
  108. // 删除的弹窗数据
  109. const [delInfo, setDelInfo] = useState({ id: 0, name: "" });
  110. // 权限
  111. const authArr = useSelector((state: RootState) => state.A4Role.A4RoleAll);
  112. // 关于 审核
  113. const adidtDom = useCallback(
  114. (item: A1ItableType) => {
  115. const num = item.auditStatus;
  116. const txt = num === 0 ? "待审批" : num === 1 ? "审批通过" : "审批驳回";
  117. const dom =
  118. item.auditDesc && num !== 0 ? (
  119. <Tooltip title={item.auditDesc}>
  120. <div
  121. className="iconHoverTit A1ItablauidtBox"
  122. onClick={() =>
  123. setAuditInfo({
  124. id: item.id,
  125. sta: num,
  126. txt: item.auditDesc || "",
  127. })
  128. }
  129. >
  130. {txt}&nbsp;
  131. <div className="iconHoverTitTxt">?</div>
  132. </div>
  133. </Tooltip>
  134. ) : (
  135. <div
  136. className="A1ItablauidtBox"
  137. onClick={() =>
  138. setAuditInfo({ id: item.id, sta: num, txt: item.auditDesc || "" })
  139. }
  140. >
  141. {txt}
  142. </div>
  143. );
  144. if (authArr.includes("1104")) return dom;
  145. else return txt;
  146. },
  147. [authArr]
  148. );
  149. const columns = useMemo(() => {
  150. return [
  151. {
  152. title: "所属阶段",
  153. dataIndex: "stageName",
  154. },
  155. {
  156. title: "文件类别",
  157. dataIndex: "attrName",
  158. },
  159. {
  160. title: "责任部门",
  161. dataIndex: "deptName",
  162. },
  163. {
  164. title: "文件名称",
  165. render: (item: A1ItableType) =>
  166. item.hasLack === 1 ? (
  167. <>
  168. {item.description === "-未填信息" ? (
  169. "无法提供"
  170. ) : (
  171. <Tooltip title={item.description}>
  172. <div className="iconHoverTit">
  173. 无法提供&nbsp;
  174. <div className="iconHoverTitTxt">?</div>
  175. </div>
  176. </Tooltip>
  177. )}
  178. </>
  179. ) : (
  180. item.fileName
  181. ),
  182. },
  183. {
  184. title: "上传人",
  185. dataIndex: "uploadName",
  186. },
  187. {
  188. title: "上传时间",
  189. dataIndex: "updateTime",
  190. },
  191. {
  192. title: "审批状态",
  193. render: (item: A1ItableType) => adidtDom(item),
  194. },
  195. {
  196. title: "审核人",
  197. render: (item: A1ItableType) =>
  198. item.auditorName ? item.auditorName : "(空)",
  199. },
  200. {
  201. title: "审核时间",
  202. render: (item: A1ItableType) =>
  203. item.auditTime ? item.auditTime : "(空)",
  204. },
  205. {
  206. title: "操作",
  207. render: (item: A1ItableType) =>
  208. item.hasLack === 1 ? (
  209. "-"
  210. ) : (
  211. <>
  212. {authFilesLookFu(item.fileName) ? (
  213. <Button
  214. size="small"
  215. type="text"
  216. onClick={() => authFilesLookFu(item.fileName, item.filePath)}
  217. >
  218. 查看
  219. </Button>
  220. ) : null}
  221. <AuthCom aId="1106">
  222. <Button
  223. size="small"
  224. type="text"
  225. onClick={() =>
  226. urlChangeFu(item.filePath, true, undefined, item.fileName)
  227. }
  228. >
  229. 下载
  230. </Button>
  231. </AuthCom>
  232. <AuthCom aId="1107">
  233. <Button
  234. size="small"
  235. type="text"
  236. danger
  237. onClick={() =>
  238. setDelInfo({ id: item.id, name: item.fileName })
  239. }
  240. >
  241. 删除
  242. </Button>
  243. </AuthCom>
  244. </>
  245. ),
  246. },
  247. ];
  248. }, [adidtDom]);
  249. // 登记缺失文件的开启和关闭
  250. const [lack, setLack] = useState(false);
  251. // 审批状态的开启和关闭
  252. const [auditInfo, setAuditInfo] = useState<{
  253. id: number;
  254. sta: 0 | 1 | 2;
  255. txt: string;
  256. }>({
  257. id: 0,
  258. sta: 0,
  259. txt: "",
  260. });
  261. // 批量上传的弹窗
  262. const [upFileOpen, setUpFileOpen] = useState(false);
  263. return (
  264. <div className={styles.A1Inner}>
  265. <div className="A1Itop">
  266. <div className="A1ItopRow">
  267. <span>搜索项:</span>
  268. <Input
  269. maxLength={30}
  270. style={{ width: 210 }}
  271. placeholder="请输入文件名称,最多30字"
  272. allowClear
  273. onChange={(e) => searchKeyChange(e)}
  274. />
  275. </div>
  276. <div className="A1ItopRow">
  277. <span>文件类别:</span>
  278. <Select
  279. style={{ width: 120 }}
  280. value={fromData.attrId}
  281. onChange={(e) => setFromData({ ...fromData, attrId: e })}
  282. options={[
  283. { value: "", label: "全部" },
  284. ...iResList.map((v) => ({ value: v.id, label: v.name })),
  285. ]}
  286. />
  287. </div>
  288. <div className="A1ItopRow">
  289. <span>审批状态:</span>
  290. <Select
  291. style={{ width: 120 }}
  292. value={fromData.auditStatus}
  293. onChange={(e) => setFromData({ ...fromData, auditStatus: e })}
  294. options={[
  295. { value: "", label: "全部" },
  296. { value: 0, label: "待审批" },
  297. { value: 1, label: "审批通过" },
  298. { value: 2, label: "审批驳回" },
  299. ]}
  300. />
  301. </div>
  302. <div className="A1ItopRow">
  303. <span>责任部门:</span>
  304. <Cascader
  305. allowClear={false}
  306. style={{ width: 200 }}
  307. options={[{ id: "", name: "全部" }, ...deptList]}
  308. value={fromData.deptId}
  309. onChange={(e) => setFromData({ ...fromData, deptId: e })}
  310. fieldNames={{ label: "name", value: "id" }}
  311. placeholder="请选择"
  312. />
  313. </div>
  314. <div className="A1ItopRow A1ItopRow2">
  315. <AuthCom aId="1105">
  316. <Button type="primary" onClick={() => setLack(true)}>
  317. 登记缺失文件
  318. </Button>
  319. </AuthCom>
  320. &emsp;
  321. <AuthCom aId="1103">
  322. <Button type="primary" onClick={() => setUpFileOpen(true)}>
  323. 批量上传
  324. </Button>
  325. </AuthCom>
  326. &emsp;
  327. <AuthCom aId="1102">
  328. <Button
  329. type="primary"
  330. onClick={downSelectFu}
  331. disabled={selectedRowKeys.length <= 0}
  332. >
  333. 批量下载
  334. </Button>
  335. </AuthCom>
  336. </div>
  337. </div>
  338. <div className="A1ItableBox">
  339. <Table
  340. rowSelection={{
  341. type: "checkbox",
  342. selectedRowKeys,
  343. onChange: (selectedRowKeys: React.Key[]) => {
  344. setSelectedRowKeys(selectedRowKeys);
  345. },
  346. // 禁用
  347. getCheckboxProps: (item) => ({
  348. disabled: item.hasLack === 1, // 配置无法勾选的列
  349. }),
  350. }}
  351. scroll={{ y: 610 }}
  352. dataSource={data}
  353. columns={columns}
  354. rowKey="id"
  355. pagination={false}
  356. />
  357. </div>
  358. {/* 点击删除出来的弹窗 */}
  359. {delInfo.id ? (
  360. <A1IRemove
  361. mId={delInfo.id}
  362. name={delInfo.name}
  363. colseFu={() => setDelInfo({ id: 0, name: "" })}
  364. delSuFu={() => getListFu()}
  365. />
  366. ) : null}
  367. {/* 点击登记缺失文件出来的弹窗 */}
  368. {lack ? (
  369. <A1ILack
  370. projectId={projectId}
  371. closeFu={() => setLack(false)}
  372. addSuFu={() => getListFu()}
  373. />
  374. ) : null}
  375. {/* 点击审批出来的弹窗 */}
  376. {auditInfo.id ? (
  377. <A1IAudit
  378. info={auditInfo}
  379. closeFu={() => setAuditInfo({ id: 0, sta: 0, txt: "" })}
  380. editSuFu={() => getListFu()}
  381. />
  382. ) : null}
  383. {upFileOpen ? (
  384. <A1IupFile
  385. myUrl={`${baseUpUrl}cms/inside/upload/${projectId}`}
  386. upFileFu={() => getListFu()}
  387. closeFu={() => setUpFileOpen(false)}
  388. myTitle={myTitle}
  389. projectId={projectId}
  390. typeData={iResList}
  391. />
  392. ) : null}
  393. </div>
  394. );
  395. }
  396. const MemoA1Inner = React.memo(A1Inner);
  397. export default MemoA1Inner;