123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- import React, { useImperativeHandle, forwardRef, useState, useEffect } from "react";
- import { DownOutlined, PlusOutlined, DeleteOutlined } from "@ant-design/icons";
- import type { MenuProps } from "antd";
- import {
- Dropdown,
- Space,
- Drawer,
- Button,
- Checkbox,
- Input,
- Popover,
- Radio,
- Tooltip,
- } from "antd";
- import { useModel } from "umi";
- import { TodoItem } from "@/type";
- import { uuid } from "@repo/utils";
- import noData from "@/assets/no-data.png";
- const TodoDrawer = forwardRef((props: {}, ref) => {
- const [open, setOpen] = React.useState(false);
- const { project, setProject } = useModel("erModel");
- const [activeKey, setActiveKey] = React.useState("");
- const [todoList, setTodoList] = useState<TodoItem[]>(project.todos);
- useEffect(() => {
- setTodoList(project.todos);
- }, [project.todos]);
- useImperativeHandle(ref, () => ({
- open: () => setOpen(true),
- close: () => setOpen(false),
- }));
- const items: MenuProps["items"] = [
- {
- key: "1",
- label: "按优先级排序",
- },
- {
- key: "2",
- label: "按完成时间排序",
- },
- {
- key: "3",
- label: "按创建时间排序",
- },
- ];
- const levelMap = {
- 0: {
- label: "无",
- color: "#1890ff",
- },
- 1: {
- label: "低",
- color: "#52c41a",
- },
- 2: {
- label: "中",
- color: "#d89614",
- },
- 3: {
- label: "高",
- color: "#ff4d4f",
- },
- };
- const handleChange = (index: number, key: string, value: any) => {
- const newTodos = [...todoList];
- newTodos[index] = {
- ...newTodos[index],
- [key]: value,
- };
- setTodoList(newTodos);
- setProject(
- {
- ...project,
- todos: newTodos,
- },
- false,
- false,
- true
- );
- };
- const addToto = () => {
- setProject(
- {
- ...project,
- todos: [
- ...todoList,
- {
- id: uuid(),
- dataModelId: project.id,
- name: "",
- text: "",
- isDone: false,
- level: 1,
- },
- ],
- },
- false,
- false,
- true
- );
- };
- const handleDelete = (index: number) => {
- const newTodos = [...todoList];
- newTodos.splice(index, 1);
- setProject(
- {
- ...project,
- todos: newTodos,
- },
- false,
- false,
- true
- );
- };
- return (
- <Drawer
- open={open}
- placement="right"
- width={400}
- title={<>待办事项</>}
- onClose={() => setOpen(false)}
- >
- <div className="flex justify-between m-b-12px">
- <Dropdown menu={{ items }}>
- <Space>
- 排序方式
- <DownOutlined />
- </Space>
- </Dropdown>
- <Button type="primary" icon={<PlusOutlined />} onClick={addToto}>
- 新建待办
- </Button>
- </div>
- {todoList.map((todo: TodoItem, index: number) => (
- <div
- className="todo-item flex border-b-1 border-b-solid border-#eee p-b-12px m-b-12px"
- key={todo.id}
- onClick={() => setActiveKey(todo.id)}
- >
- <div className="left m-r-12px">
- <Tooltip title="完成"><Checkbox
- checked={todo.isDone}
- onChange={(e) => {
- handleChange(index, "isDone", e.target.checked);
- }}
- /></Tooltip>
- </div>
- <div className="right flex-1">
- <div className="flex m-b-12px">
- <Input
- placeholder="标题..."
- value={todo.name}
- onChange={(e) => handleChange(index, "name", e.target.value)}
- />
- <Popover
- trigger={["click"]}
- placement="bottom"
- content={
- <div className="w-200px">
- <div className="font-bold">优先级:</div>
- <div className="p-l-12px">
- <Radio.Group value={todo.level} onChange={(e) => handleChange(index, "level", e.target.value)}>
- <Space direction="vertical">
- <Radio value={0}>无</Radio>
- <Radio value={1}>低</Radio>
- <Radio value={2}>中</Radio>
- <Radio value={3}>高</Radio>
- </Space>
- </Radio.Group>
- </div>
- <div>
- <Button danger icon={<DeleteOutlined />} className="m-t-12px w-full" onClick={() => {handleDelete(index)}}>删除</Button>
- </div>
- </div>
- }
- >
- <div className="rounded-4px cus-btn w-32px h-32px bg-#eee flex-none text-center leading-32px cursor-pointer hover:bg-#ddd m-l-12px">
- <i className="iconfont icon-gengduo" />
- </div>
- </Popover>
- </div>
- <div
- className="m-b-12px grid"
- style={{
- transition: "all 0.3s",
- gridTemplateRows: activeKey === todo.id ? "1fr" : "0fr",
- }}
- >
- <div className="overflow-hidden">
- <Input.TextArea
- placeholder="描述..."
- value={todo.text}
- onChange={(e) => handleChange(index, "text", e.target.value)}
- />
- </div>
- </div>
- <div>
- 优先级:{" "}
- <span
- className="inline-block w-20px h-20px bg-red-500 color-#fff rounded-4px text-center leading-20px"
- style={{
- background: levelMap[todo.level].color,
- fontSize: "12px",
- }}
- >
- {levelMap[todo.level].label}
- </span>
- </div>
- </div>
- </div>
- ))}
- {project.todos.length === 0 && (
- <div className="flex flex-col items-center justify-center h-[300px]">
- <img src={noData} alt="暂无数据" className="w-[200px] h-[200px]" />
- <div className="text-gray-400">暂无待办项!</div>
- </div>
- )}
- </Drawer>
- );
- });
- export default TodoDrawer;
|