RemarkPanel.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import { DeleteOutlined, SearchOutlined } from "@ant-design/icons";
  2. import { Button, Input, Form, Popconfirm } from "antd";
  3. import React, { useEffect, useState } from "react";
  4. import CustomColorPicker from "@/components/CustomColorPicker";
  5. import { useModel } from "umi";
  6. import noData from "@/assets/no-data.png";
  7. import { RemarkInfo } from "@/type";
  8. import { useSessionStorageState } from "ahooks";
  9. export default function RemarkPanel() {
  10. const { project, addRemark, deleteRemark, updateRemark } =
  11. useModel("erModel");
  12. const { remarks = [] } = project;
  13. const [search, setSearch] = React.useState("");
  14. const [activeKey, setActiveKey] = useSessionStorageState("remark-active", {
  15. defaultValue: "",
  16. listenStorageChange: true
  17. });
  18. const [remarkList, setRemarkList] = useState(remarks);
  19. useEffect(() => {
  20. setRemarkList(remarks.filter(item => item.name.includes(search)));
  21. }, [remarks, search]);
  22. const handleChange = (index: number, key: keyof RemarkInfo, value: any) => {
  23. const data = remarkList[index];
  24. const newData = { ...data, [key]: value };
  25. updateRemark(newData);
  26. const arr = [...remarkList];
  27. arr[index] = newData;
  28. setRemarkList(arr);
  29. };
  30. return (
  31. <div className="px-12px">
  32. <div className="flex gap-12px">
  33. <Input
  34. placeholder="输入关键字搜索"
  35. className="m-b-10px"
  36. suffix={<SearchOutlined />}
  37. value={search}
  38. onChange={(e) => setSearch(e.target.value)}
  39. />
  40. <Button type="primary" onClick={addRemark}>
  41. 添加注释
  42. </Button>
  43. </div>
  44. {remarkList.map((item, index) => {
  45. return (
  46. <div
  47. key={item.id}
  48. className="
  49. border-b-solid
  50. border-b-[#e4e4e4]
  51. border-b-[1px]"
  52. >
  53. <div
  54. className="
  55. header
  56. flex
  57. items-center
  58. justify-between
  59. leading-[40px]
  60. hover:bg-[#fafafa]
  61. cursor-pointer
  62. m-b-[10px]"
  63. onClick={() => setActiveKey(activeKey === item.id ? "" : item.id)}
  64. >
  65. <div className="font-bold truncate">{item.name}</div>
  66. <div>
  67. <i
  68. className="iconfont icon-open m-r-10px inline-block"
  69. style={{
  70. transform:
  71. activeKey === item.id ? "rotate(180deg)" : "rotate(0deg)",
  72. transition: "all 0.3s",
  73. }}
  74. />
  75. </div>
  76. </div>
  77. <div
  78. className="content overflow-hidden grid"
  79. style={{
  80. gridTemplateRows: activeKey === item.id ? "1fr" : "0fr",
  81. transition: "all 0.3s",
  82. }}
  83. >
  84. <Form layout="vertical" className="overflow-hidden">
  85. <Form.Item label="标题" layout="vertical">
  86. <Input
  87. placeholder="请输入"
  88. defaultValue={item.name}
  89. onChange={(e) =>
  90. handleChange(index, "name", e.target.value)
  91. }
  92. />
  93. </Form.Item>
  94. <Form.Item label="" layout="vertical" wrapperCol={{ span: 24 }}>
  95. <div className="flex gap-12px">
  96. <Input.TextArea
  97. placeholder="内容"
  98. autoSize={false}
  99. style={{ resize: "none" }}
  100. value={item.text}
  101. onChange={(e) =>
  102. handleChange(index, "text", e.target.value)
  103. }
  104. />
  105. <div>
  106. <CustomColorPicker
  107. color={item.style.background}
  108. onChange={(color) => {
  109. handleChange(index, "style", {
  110. ...item.style,
  111. background: color,
  112. });
  113. }}
  114. >
  115. <div
  116. className="rounded-4px cus-btn w-32px h-32px bg-#eee flex-none cursor-pointer shadow-inner"
  117. style={{ background: item.style.background }}
  118. ></div>
  119. </CustomColorPicker>
  120. <Popconfirm
  121. okType="primary"
  122. title="确定删除该注释?"
  123. okText="确定"
  124. cancelText="取消"
  125. onConfirm={() => deleteRemark(item.id)}
  126. >
  127. <div className="rounded-4px cus-btn w-32px h-32px bg-#eee flex-none cursor-pointer text-center leading-32px color-red">
  128. <DeleteOutlined />
  129. </div>
  130. </Popconfirm>
  131. </div>
  132. </div>
  133. </Form.Item>
  134. </Form>
  135. </div>
  136. </div>
  137. );
  138. })}
  139. {remarkList.length === 0 && (
  140. <div className="flex flex-col items-center justify-center h-[300px]">
  141. <img src={noData} alt="暂无数据" className="w-[200px] h-[200px]" />
  142. <div className="text-gray-400">添加额外注释内容!</div>
  143. </div>
  144. )}
  145. </div>
  146. );
  147. }