index.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import { FC, useEffect, useRef, useState } from "react";
  2. import { Button } from "antd";
  3. import { useNavigate } from "react-router-dom";
  4. import {
  5. DageLoading,
  6. DageTreeActionData,
  7. DageTreeActions,
  8. } from "@dage/pc-components";
  9. import { PlusOutlined } from "@ant-design/icons";
  10. import { deleteAssIndexApi, getAssIndexTreeApi } from "@/api";
  11. import { AssIndexTreeItemType, ASS_INDEX_TYPE, YES_OR_NO } from "@/types";
  12. import style from "../../index.module.scss";
  13. export interface SidebarProps {
  14. /**
  15. * 勾选模式
  16. */
  17. checkable?: boolean;
  18. type: ASS_INDEX_TYPE;
  19. currentId: null | number;
  20. treeApi?: () => Promise<AssIndexTreeItemType[]>;
  21. setCurrentId: (id: number | null) => void;
  22. }
  23. export const Sidebar: FC<SidebarProps> = ({
  24. checkable,
  25. type,
  26. currentId,
  27. treeApi,
  28. setCurrentId,
  29. }) => {
  30. const navigate = useNavigate();
  31. const [loading, setLoading] = useState(false);
  32. const [treeData, setTreeData] = useState<AssIndexTreeItemType[]>([]);
  33. const [checkedKeys, setCheckedKeys] = useState<number[]>([]);
  34. const lastCheckedItem = useRef<any>(null);
  35. const isFixed = type === ASS_INDEX_TYPE.FIXED;
  36. const transformTreeData = (data: AssIndexTreeItemType[]) => {
  37. return data.map((item) => {
  38. // @ts-ignore
  39. item.hideAddBtn = item.isPoint === YES_OR_NO.YES;
  40. // @ts-ignore
  41. item.hideDeleteBtn = Boolean(item.children.length);
  42. if (item.children && item.children.length > 0) {
  43. item.children = transformTreeData(item.children);
  44. }
  45. return item;
  46. });
  47. };
  48. const getAssIndexTree = async () => {
  49. try {
  50. setLoading(true);
  51. const data = treeApi ? await treeApi() : await getAssIndexTreeApi(type);
  52. if (data.length) {
  53. // 防止再次选择
  54. data[0].disabled = true;
  55. setCurrentId(data[0].id);
  56. setCheckedKeys([data[0].id]);
  57. lastCheckedItem.current = data[0];
  58. setTreeData(transformTreeData(data));
  59. } else {
  60. setCurrentId(null);
  61. setCheckedKeys([]);
  62. setTreeData([]);
  63. lastCheckedItem.current = null;
  64. }
  65. } finally {
  66. setLoading(false);
  67. }
  68. };
  69. const handleAddNode = (item: DageTreeActionData) => {
  70. navigate(`/assessment/index/create/${type}?parentId=${item.id}`);
  71. };
  72. const handleEditNode = (item: DageTreeActionData) => {
  73. navigate(`/assessment/index/edit/${type}/${item.id}`);
  74. };
  75. const handleDeleteNode = async (item: DageTreeActionData) => {
  76. await deleteAssIndexApi(item.id);
  77. getAssIndexTree();
  78. };
  79. useEffect(() => {
  80. setTreeData([]);
  81. getAssIndexTree();
  82. }, [type]);
  83. return (
  84. <div className={style.sidebar}>
  85. <div className={style.sidebarHeader}>
  86. <h4>指标列表</h4>
  87. {!checkable && (
  88. <Button
  89. type="primary"
  90. icon={<PlusOutlined />}
  91. onClick={() => navigate("/assessment/index/create/" + type)}
  92. >
  93. 新增指标
  94. </Button>
  95. )}
  96. </div>
  97. {currentId && treeData.length && (
  98. <DageTreeActions
  99. defaultExpandAll
  100. maxLevel={isFixed ? 5 : 2}
  101. treeData={treeData}
  102. selectedKeys={checkedKeys}
  103. onAdd={checkable ? undefined : handleAddNode}
  104. onEdit={checkable ? undefined : handleEditNode}
  105. onDelete={checkable ? undefined : handleDeleteNode}
  106. onSelect={(keys, { selectedNodes }) => {
  107. const checkedId = keys[keys.length - 1] as number;
  108. lastCheckedItem.current.disabled = false;
  109. selectedNodes[0].disabled = true;
  110. setCurrentId(checkedId);
  111. setCheckedKeys([checkedId]);
  112. lastCheckedItem.current = selectedNodes[0];
  113. }}
  114. />
  115. )}
  116. {loading && <DageLoading />}
  117. </div>
  118. );
  119. };