新增待辦事項相關API接口及聊天窗口功能:在API中添加待辦事項列表、添加和處理功能,並在聊天窗口中整合好友ID以支持待辦事項管理,提升用戶互動體驗。

This commit is contained in:
超级老白兔
2025-09-26 16:41:48 +08:00
parent 5ea49ef6f1
commit 43209882e4
3 changed files with 143 additions and 51 deletions

View File

@@ -352,3 +352,34 @@ export const addFollowUp = (params: {
export const processFollowUp = (params: { ids?: string }) => {
return request("/v1/kefu/followUp/process", params, "GET");
};
// ============== 待办事项相关接口 ==============
// 待办事项列表
export const getTodoList = (params: {
isProcess?: string;
isRemind?: string;
keyword?: string;
level?: string;
limit?: string;
page?: string;
friendId?: string;
}) => {
return request("/v1/kefu/todo/list", params, "GET");
};
// 待办事项添加
export const addTodo = (params: {
description?: string;
friendId: string;
level?: string; // 0低优先级 1中优先级 2高优先级 3紧急
reminderTime?: string;
title?: string;
}) => {
return request("/v1/kefu/todo/add", params, "POST");
};
// 待办事项处理
export const processTodo = (params: { ids: string }) => {
return request("/v1/kefu/todo/process", params, "GET");
};

View File

@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect, useCallback } from "react";
import {
Modal,
Form,
@@ -11,107 +11,165 @@ import {
Tag,
Space,
Typography,
message,
} from "antd";
import { PlusOutlined, CalendarOutlined } from "@ant-design/icons";
import { getTodoList, addTodo, processTodo } from "@/pages/pc/ckbox/weChat/api";
import styles from "./index.module.scss";
const { Option } = Select;
const { TextArea } = Input;
const { Text } = Typography;
// 优先级映射
const priorityMap: { [key: string]: string } = {
"0": "低",
"1": "中",
"2": "高",
"3": "紧急",
};
interface TodoItem {
id: string;
title: string;
description?: string;
client?: string;
priority: "高" | "中" | "低";
priority: "高" | "中" | "低" | "紧急";
dueDate: string;
completed: boolean;
friendId?: string;
}
interface TodoListModalProps {
visible: boolean;
onClose: () => void;
clientName?: string;
friendId?: string;
}
const TodoListModal: React.FC<TodoListModalProps> = ({
visible,
onClose,
clientName = "客户",
friendId,
}) => {
const [form] = Form.useForm();
const [todos, setTodos] = useState<TodoItem[]>([
{
id: "1",
title: "整理客户需求文档",
description: "汇总本周客户反馈的功能需求",
client: "李先生",
priority: "高",
dueDate: "03/08 18:00",
completed: false,
},
{
id: "2",
title: "准备产品演示PPT",
description: "针对大客户的定制化演示材料",
client: "张总",
priority: "中",
dueDate: "03/09 16:00",
completed: false,
},
{
id: "3",
title: "准备产品演示PPT",
description: "针对大客户的定制化演示材料",
client: "张总",
priority: "中",
dueDate: "03/09 16:00",
completed: false,
},
]);
const [todos, setTodos] = useState<TodoItem[]>([]);
const [loading, setLoading] = useState(false);
const [addLoading, setAddLoading] = useState(false);
// 优先级选项
const priorityOptions = [
{ value: "", label: "高优先级", color: "orange" },
{ value: "", label: "中优先级", color: "blue" },
{ value: "", label: "低优先级", color: "green" },
{ value: "2", label: "高优先级", color: "orange" },
{ value: "1", label: "中优先级", color: "blue" },
{ value: "0", label: "低优先级", color: "green" },
{ value: "3", label: "紧急", color: "red" },
];
// 加载待办事项列表
const loadTodoList = useCallback(async () => {
if (!friendId) return;
setLoading(true);
try {
const response = await getTodoList({
friendId,
limit: "50",
page: "1",
});
if (response && response.list) {
const formattedTodos = response.list.map((item: any) => ({
id: item.id?.toString() || "",
title: item.title || "",
description: item.description || "",
client: clientName,
priority: priorityMap[item.level] || "中",
dueDate: item.reminderTime || "",
completed: item.isProcess === 1,
friendId: item.friendId,
}));
setTodos(formattedTodos);
}
} catch (error) {
console.error("加载待办事项列表失败:", error);
message.error("加载待办事项列表失败");
} finally {
setLoading(false);
}
}, [friendId, clientName]);
// 当模态框打开时加载数据
useEffect(() => {
if (visible && friendId) {
loadTodoList();
}
}, [visible, friendId, loadTodoList]);
// 处理添加任务
const handleAddTask = async () => {
if (!friendId) {
message.error("缺少好友ID无法添加任务");
return;
}
setAddLoading(true);
try {
const values = await form.validateFields();
const newTodo: TodoItem = {
id: Date.now().toString(),
const params = {
friendId,
title: values.title,
description: values.description,
client: clientName,
priority: values.priority,
dueDate: values.dueDate.format("MM/DD HH:mm"),
completed: false,
level: values.priority,
reminderTime: values.dueDate.format("YYYY-MM-DD HH:mm:ss"),
};
setTodos([...todos, newTodo]);
form.resetFields();
const response = await addTodo(params);
if (response) {
message.success("添加待办事项成功");
form.resetFields();
// 重新加载列表
loadTodoList();
}
} catch (error) {
console.error("表单验证失败:", error);
console.error("添加待办事项失败:", error);
message.error("添加待办事项失败");
} finally {
setAddLoading(false);
}
};
// 处理任务完成状态切换
const handleToggleComplete = (id: string) => {
setTodos(
todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo,
),
);
const handleToggleComplete = async (id: string) => {
try {
const response = await processTodo({ ids: id });
if (response) {
message.success("任务状态更新成功");
// 重新加载列表
loadTodoList();
}
} catch (error) {
console.error("更新任务状态失败:", error);
message.error("更新任务状态失败");
}
};
// 获取优先级标签颜色
const getPriorityColor = (priority: string) => {
const option = priorityOptions.find(opt => opt.value === priority);
return option?.color || "default";
switch (priority) {
case "高":
return "orange";
case "中":
return "blue";
case "低":
return "green";
case "紧急":
return "red";
default:
return "default";
}
};
return (
@@ -184,6 +242,7 @@ const TodoListModal: React.FC<TodoListModalProps> = ({
icon={<PlusOutlined />}
onClick={handleAddTask}
className={styles.addButton}
loading={addLoading}
block
>
@@ -195,6 +254,7 @@ const TodoListModal: React.FC<TodoListModalProps> = ({
<div className={styles.todoList}>
<List
dataSource={todos}
loading={loading}
renderItem={todo => (
<List.Item className={styles.todoItem}>
<div className={styles.todoContent}>

View File

@@ -169,6 +169,7 @@ const ChatWindow: React.FC<ChatWindowProps> = ({ contract }) => {
visible={todoModalVisible}
onClose={handleTodoModalClose}
clientName={contract.nickname || contract.name}
friendId={contract.id?.toString()}
/>
</Layout>
);