RemarkPanel.tsx 5.0 KB

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