From 43209882e424e2f9c70630259150ed607cd20964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E7=BA=A7=E8=80=81=E7=99=BD=E5=85=94?= Date: Fri, 26 Sep 2025 16:41:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=BE=85=E8=BE=A6=E4=BA=8B?= =?UTF-8?q?=E9=A0=85=E7=9B=B8=E9=97=9CAPI=E6=8E=A5=E5=8F=A3=E5=8F=8A?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E7=AA=97=E5=8F=A3=E5=8A=9F=E8=83=BD=EF=BC=9A?= =?UTF-8?q?=E5=9C=A8API=E4=B8=AD=E6=B7=BB=E5=8A=A0=E5=BE=85=E8=BE=A6?= =?UTF-8?q?=E4=BA=8B=E9=A0=85=E5=88=97=E8=A1=A8=E3=80=81=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=92=8C=E8=99=95=E7=90=86=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=B8=A6?= =?UTF-8?q?=E5=9C=A8=E8=81=8A=E5=A4=A9=E7=AA=97=E5=8F=A3=E4=B8=AD=E6=95=B4?= =?UTF-8?q?=E5=90=88=E5=A5=BD=E5=8F=8BID=E4=BB=A5=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=BE=85=E8=BE=A6=E4=BA=8B=E9=A0=85=E7=AE=A1=E7=90=86=EF=BC=8C?= =?UTF-8?q?=E6=8F=90=E5=8D=87=E7=94=A8=E6=88=B6=E4=BA=92=E5=8B=95=E9=AB=94?= =?UTF-8?q?=E9=A9=97=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Touchkebao/src/pages/pc/ckbox/weChat/api.ts | 31 ++++ .../components/TodoListModal/index.tsx | 162 ++++++++++++------ .../weChat/components/ChatWindow/index.tsx | 1 + 3 files changed, 143 insertions(+), 51 deletions(-) diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/api.ts b/Touchkebao/src/pages/pc/ckbox/weChat/api.ts index dbfa0cc21..d9c137da8 100644 --- a/Touchkebao/src/pages/pc/ckbox/weChat/api.ts +++ b/Touchkebao/src/pages/pc/ckbox/weChat/api.ts @@ -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"); +}; diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/TodoListModal/index.tsx b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/TodoListModal/index.tsx index 97c6f87a8..74ca379fd 100644 --- a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/TodoListModal/index.tsx +++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/TodoListModal/index.tsx @@ -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 = ({ visible, onClose, clientName = "客户", + friendId, }) => { const [form] = Form.useForm(); - const [todos, setTodos] = useState([ - { - 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([]); + 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 = ({ icon={} onClick={handleAddTask} className={styles.addButton} + loading={addLoading} block > 添加任务 @@ -195,6 +254,7 @@ const TodoListModal: React.FC = ({
(
diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/index.tsx b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/index.tsx index 9e5dc383c..9cf35e2d8 100644 --- a/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/index.tsx +++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/index.tsx @@ -169,6 +169,7 @@ const ChatWindow: React.FC = ({ contract }) => { visible={todoModalVisible} onClose={handleTodoModalClose} clientName={contract.nickname || contract.name} + friendId={contract.id?.toString()} /> );