0804标星_复制_删除-网络ajax请求2-react-仿低代码平台项目

发布于:2025-05-01 ⋅ 阅读:(20) ⋅ 点赞:(0)

1 标星

操作:标星和取消标星,有2种状态的布尔值。通过更新问卷功能实现。

后端quetion.js添加接口

  {
    // 更新问卷信息
    url: '/api/question/:id',
    method: 'patch',
    response() {
      return {
        errno: 0
      }
    }
  },

前端question.ts添加更新问卷接口

/**
 * 更新问卷信息
 * @param id 问卷id
 * @returns  问卷信息
 */
export async function updateQuestionApi(
  id: string,
  opt: { [key: string]: any }
): Promise<ResDataType> {
  const url = `/api/question/${id}`;
  const data = (await request.patch(url, opt)) as ResDataType;
  return data;
}

问卷卡片页面QuestionCard.tsx代码如下:

import { FC, useState } from "react";
//...
import { useRequest } from "ahooks";
import { updateQuestionApi } from "@/api/question";

type PropsType = {
  _id: string;
  title: string;
  isPublished: boolean;
  isStar: boolean;
  answerCount: number;
  createdAt: string;
};

const { confirm } = Modal;

const QuestionCard: FC<PropsType> = (props: PropsType) => {
  //...
  const [isStarState, setIsStarState] = useState(isStar);

  const { loading: changeStarLoading, run: changeStar } = useRequest(
    async () => {
      await updateQuestionApi(_id, { isStar: !isStarState });
    },
    {
      manual: true,
      onSuccess() {
        setIsStarState(!isStarState);
        message.success("更新成功")
      },
    }
  );

 //...

  return (
    <div className={styles.container}>
      <div className={styles.title}>
        <div className={styles.left}>
          <Link
            to={isPublished ? `/question/stat/${_id}` : `/question/edit/${_id}`}
          >
            <Space>
              {isStarState && <StarOutlined style={{ color: "red" }} />}
              {title}
            </Space>
          </Link>
        </div>
       // ...
        <div className={styles.right}>
          <Space>
            <Button
              type="text"
              size="small"
              icon={<StarOutlined />}
              onClick={changeStar}
              disabled={changeStarLoading}
            >
              {isStarState ? "取消标星" : "标星"}
            </Button>
          //...
          </Space>
        </div>
      </div>
    </div>
  );
};

export default QuestionCard;

如下图所示:在这里插入图片描述

2 复制

操作:点击复制按钮,新增一条问卷,id为新的其他内容和被复制的问卷一致。

后端接口question.js新增代码如下:

  {
    // 复制问卷信息
    url: '/api/question/duplicate/:id',
    method: 'post',
    response() {
      return {
        errno: 0,
        data: {
          id: Random.id(),
        }
      }
    }
  }

前端qutions.ts新增复制接口代码如下:

/**
 * 复制问卷信息
 * @param id 问卷id
 * @returns  问卷信息
 */
export async function duplicateQuestionApi(id: string): Promise<ResDataType> {
  const url = `/api/question/${id}`;
  const data = (await request.post(url)) as ResDataType;
  return data;
}

卡片QuestionCard.tsx页面代码如下:

import { FC, useState } from "react";
//...
import { useRequest } from "ahooks";
import { duplicateQuestionApi, updateQuestionApi } from "@/api/question";
//...

const QuestionCard: FC<PropsType> = (props: PropsType) => {
  const nav = useNavigate();
//...

  const { loading: duplicateLoading, run: duplicate } = useRequest(
    async () => await duplicateQuestionApi(_id),
    {
      manual: true,
      onSuccess(res) {
        message.success("复制成功!");
        nav(`/question/edit/${res.id}`);
      },
    }
  );
//...
            <Popconfirm
              title="确定执行复制吗?"
              okText="确定"
              cancelText="取消"
              onConfirm={duplicate}
            >
              <Button
                type="text"
                size="small"
                icon={<CopyOutlined />}
                disabled={duplicateLoading}
              >
                复制
              </Button>
            </Popconfirm>
// ...
  );
};

export default QuestionCard;

如下图所示:

在这里插入图片描述

3 假删除

操作:改变属性值,布尔值,通过更新问卷实现

QuestionCard.tsx代码如下:

import { FC, useState } from "react";
// ...
import { useRequest } from "ahooks";
import { duplicateQuestionApi, updateQuestionApi } from "@/api/question";

type PropsType = {
  _id: string;
  title: string;
  isPublished: boolean;
  isStar: boolean;
  answerCount: number;
  createdAt: string;
};

const { confirm } = Modal;

const QuestionCard: FC<PropsType> = (props: PropsType) => {
  // ...
  const { loading: delLoading, run: fakeDel } = useRequest(
    async () => await updateQuestionApi(_id, { isDeleted: true }),
    {
      manual: true,
      onSuccess() {
        message.success("删除成功!");
        // todo重新执行列表请求
      },
    }
  );

  function del() {
    confirm({
      title: "确定要执行删除操作吗?",
      icon: <ExclamationCircleOutlined />,
      onOk: fakeDel,
    });
  }
 
// ...
            <Button
              type="text"
              size="small"
              icon={<DeleteOutlined />}
              onClick={del}
              disabled={delLoading}
            >
              删除
            </Button>
          </Space>
        </div>
      </div>
    </div>
  );
};

export default QuestionCard;

如下图所示:

在这里插入图片描述

4 恢复

操作:回收站批量恢复“假删除”的问卷

后端接口question.js新增接口:

  {
    // 批量恢复问卷
    url: '/api/question/recover',
    method: 'patch',
    response() {
      return {
        errno: 0,
      }
    }
  }

前端question.ts新增接口:

/**
 * 恢复问卷信息
 * @param ids 问卷ids
 * @returns 执行结果
 */
export async function recoverQuestionsApi(ids: string[]): Promise<ResDataType> {
  const url = "/api/question/recover";
  const data = (await request.patch(url, ids)) as ResDataType;
  return data;
}

回收站页面Trash.tsx代码如下:

import { FC, useState } from "react";
import { useRequest, useTitle } from "ahooks";
//...
import { deleteQuestionsApi, recoverQuestionsApi } from "@/api/question";
//...

  // 选择ids集合
  const [selectedIds, setSelectedIds] = useState<string[]>([]);

  const { loading: recoverLoading, run: handleRecover } = useRequest(
    async () => await recoverQuestionsApi(selectedIds),
    {
      manual: true,
      onSuccess() {
        message.success("恢复成功!");
        // todo 查询问卷列表
      },
    }
  );

// ...

  const TableEle = (
    <>
      <div style={{ marginBottom: "10px" }}>
        <Space>
          <Button
            type="primary"
            disabled={selectedIds.length === 0 || recoverLoading}
            onClick={handleRecover}
          >
            恢复
          </Button>
 //...
        </Space>
      </div>
// ...
    </>
  );

  return (
    <>
     // ...
      <div className={styles.content}>
        {loading && (
          <div style={{ textAlign: "center" }}>
            <Spin />
          </div>
        )}
        {!loading && list.length === 0 && <Empty description="暂无数据" />}
        {TableEle}
      </div>
	//...
    </>
  );
};

export default List;

如下图所示:

在这里插入图片描述

5 彻底删除

操作:把数据从数据库彻底删除,危险操作,慎重

后端question.js新增接口:

  {
    // 批量恢复问卷
    url: '/api/question/deleteQuestions',
    method: 'delete',
    response() {
      return {
        errno: 0,
      }
    }
  },

前端question.js新增接口:

/**
 * 彻底删除问卷
 * @param ids 问卷ids
 * @returns 执行结果
 */
export async function deleteQuestionsApi(ids: string[]): Promise<ResDataType> {
  const url = "/api/question/deleteQuestions";
  const data = (await request.delete(url, { data: ids })) as ResDataType;
  return data;
}

回收站Trash.tsx代码如下:

import { FC, useState } from "react";
import { useRequest, useTitle } from "ahooks";
//...
import { deleteQuestionsApi, recoverQuestionsApi } from "@/api/question";
//...

const List: FC = () => {
  useTitle("调查问卷-回收站");
//...

  const { loading: delLoading, run: handleDel } = useRequest(
    async () => await deleteQuestionsApi(selectedIds),
    {
      manual: true,
      onSuccess() {
        message.success("删除成功!");
        // todo 请求问卷列表
      },
    }
  );

  function del() {
    confirm({
      title: "您确定要删除吗?",
      okText: "确定",
      cancelText: "取消",
      content: "删除以后不可找回!",
      icon: <ExclamationCircleOutlined />,
      onOk: handleDel,
    });
  }

  const TableEle = (
    <>
      <div style={{ marginBottom: "10px" }}>
        <Space>
//...
          <Button
            danger
            disabled={selectedIds.length === 0 || delLoading}
            onClick={del}
          >
            彻底删除
          </Button>
        </Space>
      </div>
//...
    </>
  );

  return (
    <>
   //...
      <div className={styles.content}>
        {loading && (
          <div style={{ textAlign: "center" }}>
            <Spin />
          </div>
        )}
        {!loading && list.length === 0 && <Empty description="暂无数据" />}
        {TableEle}
      </div>
//...
    </>
  );
};

export default List;

如下图所示:

在这里插入图片描述

说明

  • 上面所有操作成功后,前面会重新执行请求列表接口(目前只是部分前端模拟)
  • 后端接口只是mock接口

结语

❓QQ:806797785

⭐️仓库地址:https://gitee.com/gaogzhen

⭐️仓库地址:https://github.com/gaogzhen

[1]ahook官网[CP/OL].

[2]mock文档[CP/OL].

[3]Ant Design官网[CP/OL].


网站公告

今日签到

点亮在社区的每一天
去签到