index.tsx 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. import {
  2. MenuOutlined,
  3. AppstoreOutlined,
  4. PlusOutlined,
  5. } from "@ant-design/icons";
  6. import {
  7. PageContainer,
  8. ProCard,
  9. ProConfigProvider,
  10. ProTable
  11. } from "@ant-design/pro-components";
  12. import { css } from "@emotion/css";
  13. import {
  14. Space,
  15. Input,
  16. Button,
  17. Row,
  18. Col,
  19. Card,
  20. ConfigProvider,
  21. Divider,
  22. Popover,
  23. } from "antd";
  24. import React, { useState } from "react";
  25. import { history } from "umi";
  26. import logo from "@/assets/logo.png";
  27. import { Icon } from "umi";
  28. import { createNew } from "@/utils";
  29. const MenuCard = () => {
  30. return (
  31. <div
  32. style={{
  33. display: "flex",
  34. alignItems: "center",
  35. }}
  36. >
  37. <Divider
  38. style={{
  39. height: "1.5em",
  40. }}
  41. type="vertical"
  42. />
  43. </div>
  44. );
  45. };
  46. const basicGraph = [
  47. {
  48. id: "1",
  49. title: "流程图",
  50. subtitle: "图形化表单方式",
  51. color: "#dfecff",
  52. icon: <Icon icon="local:flow" />,
  53. onClick: () => createNew("flow"),
  54. },
  55. {
  56. id: "2",
  57. title: "思维导图",
  58. subtitle: "结构化表单方式",
  59. color: "#dff4ea",
  60. icon: <Icon icon="local:mind" />,
  61. path: "/mindmap",
  62. onClick: () => createNew("flow"),
  63. },
  64. ];
  65. const appList = [
  66. {
  67. id: "1",
  68. title: "UML",
  69. icon: <Icon icon="local:uml" />,
  70. onClick: () => createNew("uml"),
  71. },
  72. {
  73. id: "2",
  74. title: "E-R图",
  75. icon: <Icon icon="local:er" />,
  76. onClick: () => createNew("er"),
  77. },
  78. {
  79. id: "3",
  80. title: "泳道图",
  81. icon: <Icon icon="local:swimlane" />,
  82. onClick: () => createNew("swimlane"),
  83. },
  84. {
  85. id: "4",
  86. title: "BPMN",
  87. icon: <Icon icon="local:bpmn" />,
  88. onClick: () => createNew("bpmn"),
  89. },
  90. {
  91. id: "5",
  92. title: "韦恩图",
  93. icon: <Icon icon="local:we" />,
  94. onClick: () => createNew("we"),
  95. },
  96. {
  97. id: "6",
  98. title: "网络拓扑图",
  99. icon: <Icon icon="local:net" />,
  100. onClick: () => createNew("net"),
  101. },
  102. ];
  103. const handleMenuClick = (item: any) => {
  104. console.log("click", item);
  105. item?.onClick?.();
  106. };
  107. const renderBasicItem = (props: {
  108. title: string;
  109. subtitle: string;
  110. color: string;
  111. id: string;
  112. icon: React.ReactNode;
  113. }) => {
  114. return (
  115. <div
  116. key={props.id}
  117. className={css`
  118. width: 136px;
  119. height: 60px;
  120. padding: 8px;
  121. border-radius: 8px;
  122. display: flex;
  123. align-items: center;
  124. cursor: pointer;
  125. margin-top: 8px;
  126. background: ${props.color + "70"};
  127. &:hover {
  128. background: ${props.color};
  129. }
  130. `}
  131. onClick={() => handleMenuClick(props)}
  132. >
  133. <span className="w-32px h-33px">{props.icon}</span>
  134. <div className="flex flex-col justify-center ml-4px">
  135. <div className="text-14px">{props.title}</div>
  136. <div className="text-12px text-#9aa5b8">{props.subtitle}</div>
  137. </div>
  138. </div>
  139. );
  140. };
  141. const renderProItem = (props: {
  142. id: string;
  143. title: string;
  144. icon: React.ReactNode;
  145. }) => {
  146. return (
  147. <div
  148. key={props.id}
  149. className="w-66px h-70px flex flex-col items-center justify-center mt-8px rounded-lg hover:bg-#f3f5f9 cursor-pointer"
  150. onClick={() => handleMenuClick(props)}
  151. >
  152. {props.icon}
  153. <span className="text-12px">{props.title}</span>
  154. </div>
  155. );
  156. };
  157. const RenderAppList = () => {
  158. return (
  159. <div className="w-460px">
  160. <div className="color-#6c7d8f text-xs">基础图形</div>
  161. <Space>{basicGraph.map((item) => renderBasicItem(item))}</Space>
  162. <div className="color-#6c7d8f text-xs mt-8px">专业图形</div>
  163. <Space>{appList.map((item) => renderProItem(item))}</Space>
  164. </div>
  165. );
  166. };
  167. export default () => {
  168. const [display, setDisplay] = useState<"card" | "list">("card");
  169. const handleToEdit = () => {
  170. history.push("/flow");
  171. };
  172. return (
  173. <div
  174. id="test-pro-layout"
  175. style={{
  176. height: "100vh",
  177. overflow: "auto",
  178. }}
  179. >
  180. <ProConfigProvider hashed={false}>
  181. <ConfigProvider
  182. getTargetContainer={() => {
  183. return document.getElementById("test-pro-layout") || document.body;
  184. }}
  185. >
  186. <PageContainer
  187. extra={[
  188. <Popover key="1" placement="left" content={<RenderAppList />}>
  189. <Button
  190. type="primary"
  191. onClick={() => {}}
  192. icon={<PlusOutlined />}
  193. >
  194. 新建
  195. </Button>
  196. </Popover>,
  197. <Button
  198. key="2"
  199. onClick={() => {
  200. setDisplay(display === "card" ? "list" : "card");
  201. }}
  202. icon={
  203. display === "card" ? <MenuOutlined /> : <AppstoreOutlined />
  204. }
  205. />,
  206. ]}
  207. title={
  208. <span>
  209. <img className="w-24px h-24px mr-8px" src={logo} />
  210. 系统设计
  211. </span>
  212. }
  213. footer={[]}
  214. header={undefined}
  215. >
  216. {display === "card" ? (
  217. <ProCard
  218. style={{
  219. height: "calc(100vh - 140px)",
  220. minHeight: 800,
  221. }}
  222. >
  223. <Row gutter={[8, 16]}>
  224. {new Array(10).fill(0).map((item, index) => {
  225. return (
  226. <Col
  227. xs={8}
  228. sm={8}
  229. md={6}
  230. lg={6}
  231. xl={4}
  232. xxl={3}
  233. key={index}
  234. >
  235. <Card
  236. hoverable
  237. bordered
  238. cover={
  239. <img
  240. style={{ height: 200, objectFit: "cover" }}
  241. alt="example"
  242. src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png"
  243. />
  244. }
  245. onClick={() => handleToEdit()}
  246. >
  247. <Card.Meta
  248. title={<>xx流程图</>}
  249. description="更新于:2024.09.06"
  250. />
  251. </Card>
  252. </Col>
  253. );
  254. })}
  255. </Row>
  256. </ProCard>
  257. ) : <ProTable
  258. columns={[
  259. {
  260. title: "名称",
  261. dataIndex: "name"
  262. },
  263. {
  264. title: "类型",
  265. dataIndex: "type"
  266. },
  267. {
  268. title: "修改时间",
  269. dataIndex: "updateTime",
  270. sorter: (a, b) => a.updateTime - b.updateTime,
  271. },
  272. ]}
  273. request={(params, sorter, filter) => {
  274. // 表单搜索项会从 params 传入,传递给后端接口。
  275. console.log(params, sorter, filter);
  276. return Promise.resolve({
  277. data: new Array(10).fill({
  278. id: 1,
  279. name: "xxx流程图",
  280. type: '流程图',
  281. updateTime: '2024-09-06 14:00:00'
  282. }),
  283. success: true,
  284. });
  285. }}
  286. rowKey={'id'}
  287. search={false}
  288. />}
  289. </PageContainer>
  290. </ConfigProvider>
  291. </ProConfigProvider>
  292. </div>
  293. );
  294. };