0804标星_复制_删除-网络ajax请求2-react-仿低代码平台项目
文章目录
- 1 标星
- 2 复制
- 3 假删除
- 4 恢复
- 5 彻底删除
- 结语
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}><Linkto={isPublished ? `/question/stat/${_id}` : `/question/edit/${_id}`}><Space>{isStarState && <StarOutlined style={{ color: "red" }} />}{title}</Space></Link></div>// ...<div className={styles.right}><Space><Buttontype="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}`);},});
//...<Popconfirmtitle="确定执行复制吗?"okText="确定"cancelText="取消"onConfirm={duplicate}><Buttontype="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,});}// ...<Buttontype="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><Buttontype="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>
//...<Buttondangerdisabled={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].