B1tab2.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. import React, {
  2. useCallback,
  3. useEffect,
  4. useMemo,
  5. useRef,
  6. useState,
  7. } from "react";
  8. import {
  9. Button,
  10. Cascader,
  11. Checkbox,
  12. Input,
  13. Select,
  14. Table,
  15. Tooltip,
  16. } from "antd";
  17. import {
  18. B1options1,
  19. B1options1Obj,
  20. B1options2,
  21. B1options2Obj,
  22. B1options3,
  23. B2FromDataType,
  24. } from "./data";
  25. import {
  26. ExclamationCircleOutlined,
  27. QuestionCircleOutlined,
  28. } from "@ant-design/icons";
  29. import { useDispatch, useSelector } from "react-redux";
  30. import { RootState } from "@/store";
  31. import { B1tableType } from "@/types";
  32. import ExportJsonExcel from "js-export-excel";
  33. import { MessageFu } from "@/utils/message";
  34. import dayjs from "dayjs";
  35. import { mapDataAll1 } from "../C1User/AddUser/city";
  36. import { B1_APIgetlist, B1_APIgetlistAll } from "@/store/action/B1Plan";
  37. import { forwardRef, useImperativeHandle } from "react";
  38. const tableSelectTemp: B2FromDataType = {
  39. // 按机房统计
  40. siteArr: undefined,
  41. isUploadScene: 1,
  42. province: "",
  43. city: "",
  44. region: "",
  45. searchKey: "",
  46. pmUser: "",
  47. auditStatus: "",
  48. pushStatus: "",
  49. jsonStatus: "",
  50. pageSize: 10,
  51. pageNum: 1,
  52. };
  53. const topTypeArr = ["区域", "机房"] as ("机房" | "区域")[];
  54. type Props = {
  55. topType: "区域" | "机房";
  56. setTopType: (val: "区域") => void;
  57. ref: any;
  58. };
  59. function B1tab1({ topType, setTopType }: Props, ref: any) {
  60. // 切换 区域 和 机房
  61. const setTopTypeFu = useCallback(
  62. (value: "机房" | "区域") => {
  63. if (value === "机房") return;
  64. // 传给父组件
  65. setTopType("区域");
  66. },
  67. [setTopType]
  68. );
  69. const dispatch = useDispatch();
  70. // 筛选和分页
  71. const [tableSelect, setTableSelect] = useState<B2FromDataType>({
  72. ...tableSelectTemp,
  73. });
  74. const tableSelectRef = useRef({} as B2FromDataType);
  75. useEffect(() => {
  76. tableSelectRef.current = { ...tableSelect };
  77. }, [tableSelect]);
  78. // 点击搜索的 时间戳
  79. const [timeKey, setTimeKey] = useState(-1);
  80. // 点击搜索
  81. const clickSearch = useCallback(() => {
  82. setTableSelect({ ...tableSelect, pageNum: 1 });
  83. setTimeout(() => {
  84. setTimeKey(Date.now());
  85. }, 50);
  86. }, [tableSelect]);
  87. // 发送接口的函数
  88. const getListFu = useCallback(() => {
  89. const objTemp: any = {};
  90. const temp = tableSelectRef.current.siteArr || [];
  91. objTemp.province = temp[0] || "";
  92. objTemp.city = temp[1] || "";
  93. objTemp.region = temp[2] || "";
  94. const obj = {
  95. ...tableSelectRef.current,
  96. ...objTemp,
  97. };
  98. dispatch(B1_APIgetlist(obj));
  99. }, [dispatch]);
  100. useEffect(() => {
  101. getListFu();
  102. }, [getListFu, timeKey]);
  103. // 输入框的改变
  104. const txtChangeFu = useCallback(
  105. (txt: string, key: "pmUser" | "searchKey") => {
  106. setTableSelect({ ...tableSelect, [key]: txt });
  107. },
  108. [tableSelect]
  109. );
  110. // 点击重置
  111. const [inputKey, setInputKey] = useState(1);
  112. const resetSelectFu = useCallback(() => {
  113. // 把2个输入框和时间选择器清空
  114. setInputKey(Date.now());
  115. setTableSelect({ ...tableSelectTemp });
  116. setTimeout(() => {
  117. setTimeKey(Date.now());
  118. }, 50);
  119. }, []);
  120. // 从仓库获取列表
  121. const B1TableList: any = useSelector(
  122. (state: RootState) => state.B1Plan.B1TableList
  123. );
  124. // 页码变化
  125. const paginationChange = useCallback(
  126. () => (pageNum: number, pageSize: number) => {
  127. setTableSelect({ ...tableSelect, pageNum, pageSize });
  128. setTimeout(() => {
  129. setTimeKey(Date.now());
  130. }, 50);
  131. },
  132. [tableSelect]
  133. );
  134. // 给父组件调用,设置站址地区
  135. const fatherFu = useCallback((obj: any) => {
  136. // 把2个输入框和时间选择器清空
  137. setInputKey(Date.now());
  138. setTableSelect({ ...tableSelectTemp, ...obj });
  139. setTimeout(() => {
  140. setTimeKey(Date.now());
  141. }, 50);
  142. }, []);
  143. // 可以让父组件调用子组件的方法
  144. useImperativeHandle(ref, () => ({
  145. fatherFu,
  146. }));
  147. const columns = useMemo(() => {
  148. return [
  149. {
  150. title: "站址名称",
  151. render: (item: B1tableType) => item.name || "(空)",
  152. },
  153. {
  154. title: "站址编号",
  155. render: (item: B1tableType) => item.siteNum || "(空)",
  156. },
  157. {
  158. title: "站址地区",
  159. render: (item: B1tableType) =>
  160. !item.province && !item.city && !item.region
  161. ? "(空)"
  162. : `${item.province}-${item.city}-${item.region}`,
  163. },
  164. {
  165. title: "机房编码",
  166. dataIndex: "roomNum",
  167. },
  168. {
  169. title: "项目经理",
  170. render: (item: B1tableType) => item.pmName || "(空)",
  171. },
  172. {
  173. title: "场景码",
  174. render: (item: B1tableType) => item.sceneCode || "(空)",
  175. },
  176. {
  177. title: "场景审核状态",
  178. render: (item: B1tableType) =>
  179. Reflect.get(B1options1Obj, item.auditStatus) || "(空)",
  180. },
  181. {
  182. title: "场景推送状态",
  183. render: (item: B1tableType) => (
  184. <>
  185. {Reflect.get(B1options2Obj, item.pushStatus) || "(空)"}
  186. <span style={{ cursor: "pointer" }} hidden={!item.pushDesc}>
  187. <Tooltip title={item.pushDesc}>
  188. &nbsp;
  189. <QuestionCircleOutlined rev={undefined} />
  190. </Tooltip>
  191. </span>
  192. </>
  193. ),
  194. },
  195. {
  196. title: "Json推送状态",
  197. render: (item: B1tableType) =>
  198. Reflect.get(B1options2Obj, item.jsonStatus) || "(空)",
  199. },
  200. ];
  201. }, []);
  202. // 点击导出
  203. const deriveFu = useCallback(async () => {
  204. if (B1TableList.total > 30000)
  205. return MessageFu.warning(
  206. "只支持导出最多30000条数据。请增加筛选条件,并重新尝试"
  207. );
  208. if (B1TableList.list.length === 0)
  209. return MessageFu.warning("当前搜索条件没有数据!");
  210. const name = "进度统计" + dayjs(new Date()).format("YYYY-MM-DD HH:mm");
  211. const objTemp: any = {};
  212. if (tableSelectRef.current.siteArr) {
  213. const temp = tableSelectRef.current.siteArr;
  214. objTemp.province = temp[0] || "";
  215. objTemp.city = temp[1 || ""];
  216. objTemp.region = temp[2] || "";
  217. }
  218. const res = await B1_APIgetlistAll({
  219. ...tableSelectRef.current,
  220. ...objTemp,
  221. pageNum: 1,
  222. pageSize: 99999,
  223. });
  224. if (res.code === 0) {
  225. if (res.data.records.length <= 0)
  226. return MessageFu.warning("当前搜索条件没有数据!");
  227. const option = {
  228. fileName: name,
  229. datas: [
  230. {
  231. sheetData: res.data.records.map((v: B1tableType) => ({
  232. name: v.name || "(空)",
  233. siteNum: v.siteNum || "(空)",
  234. myCity:
  235. !v.province && !v.city && !v.region
  236. ? "(空)"
  237. : `${v.province}-${v.city}-${v.region}`,
  238. roomNum: v.roomNum,
  239. pmName: v.pmName || "(空)",
  240. sceneCode: v.sceneCode || "(空)",
  241. auditStatus:
  242. Reflect.get(B1options1Obj, v.auditStatus) || "(空)",
  243. pushStatus: Reflect.get(B1options2Obj, v.pushStatus) || "(空)",
  244. jsonStatus: Reflect.get(B1options2Obj, v.jsonStatus) || "(空)",
  245. })),
  246. sheetName: name,
  247. sheetFilter: [
  248. "name",
  249. "siteNum",
  250. "myCity",
  251. "roomNum",
  252. "pmName",
  253. "sceneCode",
  254. "auditStatus",
  255. "pushStatus",
  256. "jsonStatus",
  257. ],
  258. sheetHeader: [
  259. "站址名称",
  260. "站址编号",
  261. "站址地区",
  262. "机房编码",
  263. "项目经理",
  264. "场景码",
  265. "场景审核状态",
  266. "场景推送状态",
  267. "Json推送状态",
  268. ],
  269. columnWidths: [10, 10, 10, 10, 10, 10, 10, 10, 10],
  270. },
  271. ],
  272. };
  273. const toExcel = new ExportJsonExcel(option); //new
  274. toExcel.saveExcel(); //保存
  275. }
  276. }, [B1TableList.list.length, B1TableList.total]);
  277. return (
  278. <>
  279. <div className="pageTitle">
  280. 进度统计&emsp;
  281. <ExclamationCircleOutlined rev={undefined} />
  282. <div>
  283. 当存在重复的机房编码时,请在[场景审核]中删除多余场景码后,重新统计
  284. </div>
  285. </div>
  286. {/* 顶部筛选 */}
  287. <div className="B1top">
  288. <div className="B1topSon">
  289. <div className="B1topRow">
  290. {topTypeArr.map((v) => (
  291. <Button
  292. onClick={() => setTopTypeFu(v)}
  293. type={v === topType ? "primary" : "default"}
  294. key={v}
  295. >
  296. 按{v}统计
  297. </Button>
  298. ))}
  299. </div>
  300. <div className="B1topRow">
  301. <span>搜索项:</span>
  302. <Input
  303. key={inputKey}
  304. maxLength={24}
  305. style={{ width: 323 }}
  306. placeholder="请输入站址名称/站置编号/机房编码,最多24字"
  307. allowClear
  308. onChange={(e) => txtChangeFu(e.target.value, "searchKey")}
  309. />
  310. </div>
  311. <div className="B1topRow">
  312. <span>站址地区:</span>
  313. <Cascader
  314. changeOnSelect
  315. value={tableSelect.siteArr}
  316. style={{ width: 160 }}
  317. options={mapDataAll1}
  318. placeholder="全部"
  319. onChange={(e) =>
  320. setTableSelect({
  321. ...tableSelect,
  322. siteArr: e as string[],
  323. })
  324. }
  325. />
  326. </div>
  327. <div className="B1topRow">
  328. <span>项目经理:</span>
  329. <Input
  330. key={inputKey}
  331. maxLength={10}
  332. style={{ width: 200 }}
  333. placeholder="请输入姓名,最多10字"
  334. allowClear
  335. onChange={(e) => txtChangeFu(e.target.value, "pmUser")}
  336. />
  337. </div>
  338. </div>
  339. <div className="B1topSon B1topSon2">
  340. <div>
  341. <div className="B1topRow">
  342. <span>场景审核:</span>
  343. <Select
  344. disabled={!tableSelect.isUploadScene}
  345. style={{ width: 200 }}
  346. value={tableSelect.auditStatus}
  347. onChange={(e) =>
  348. setTableSelect({ ...tableSelect, auditStatus: e })
  349. }
  350. options={B1options1}
  351. />
  352. </div>
  353. <div className="B1topRow">
  354. <span>场景推送:</span>
  355. <Select
  356. disabled={!tableSelect.isUploadScene}
  357. style={{ width: 200 }}
  358. value={tableSelect.pushStatus}
  359. onChange={(e) =>
  360. setTableSelect({ ...tableSelect, pushStatus: e })
  361. }
  362. options={B1options2}
  363. />
  364. </div>
  365. <div className="B1topRow">
  366. <span>Json推送:</span>
  367. <Select
  368. disabled={!tableSelect.isUploadScene}
  369. style={{ width: 200 }}
  370. value={tableSelect.jsonStatus}
  371. onChange={(e) =>
  372. setTableSelect({ ...tableSelect, jsonStatus: e })
  373. }
  374. options={B1options3}
  375. />
  376. </div>
  377. <div className="B1topRowCheck">
  378. <Checkbox
  379. checked={tableSelect.isUploadScene === 0}
  380. onChange={(e) => {
  381. setTableSelect({
  382. ...tableSelect,
  383. isUploadScene: e.target.checked ? 0 : 1,
  384. // 把 场景审核 场景推送 Json推送变成初始值
  385. auditStatus: "",
  386. pushStatus: "",
  387. jsonStatus: "",
  388. });
  389. }}
  390. >
  391. 仅查看未上传的机房
  392. </Checkbox>
  393. </div>
  394. </div>
  395. <div>
  396. <Button onClick={resetSelectFu}>重置</Button>&emsp;
  397. <Button type="primary" onClick={clickSearch}>
  398. 查询
  399. </Button>
  400. &emsp;
  401. <Button type="primary" onClick={deriveFu}>
  402. 导出表格
  403. </Button>
  404. </div>
  405. </div>
  406. </div>
  407. {/* 表格主体 */}
  408. <div className="tableMain">
  409. <Table
  410. scroll={{ y: 578 }}
  411. dataSource={B1TableList.list}
  412. columns={columns}
  413. rowKey="idKey"
  414. pagination={{
  415. showQuickJumper: true,
  416. position: ["bottomCenter"],
  417. showSizeChanger: true,
  418. current: tableSelect.pageNum,
  419. pageSize: tableSelect.pageSize,
  420. total: B1TableList.total,
  421. onChange: paginationChange(),
  422. }}
  423. />
  424. </div>
  425. {/* 右下角的列表数量 */}
  426. <div className="tableNumBox">
  427. 共 <span>{B1TableList.total}</span> 条数据
  428. </div>
  429. </>
  430. );
  431. }
  432. export default forwardRef(B1tab1);