From 46d66412593e2d2c929a80e2e83672b144aa83b0 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: Wed, 10 Sep 2025 14:08:29 +0800 Subject: [PATCH 1/4] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E4=BA=A7=E7=89=A9=E4=B8=AD=E7=9A=84=E8=B5=84=E6=BA=90?= =?UTF-8?q?=E5=BC=95=E7=94=A8=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新manifest.json和index.html中引用的JS和CSS文件路径,以匹配最新的构建输出 --- Cunkebao/dist/.vite/manifest.json | 4 ++-- Cunkebao/dist/index.html | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cunkebao/dist/.vite/manifest.json b/Cunkebao/dist/.vite/manifest.json index fabab32f..06997412 100644 --- a/Cunkebao/dist/.vite/manifest.json +++ b/Cunkebao/dist/.vite/manifest.json @@ -33,7 +33,7 @@ "name": "vendor" }, "index.html": { - "file": "assets/index-BesOjMPu.js", + "file": "assets/index-DPe1huLQ.js", "name": "index", "src": "index.html", "isEntry": true, @@ -44,7 +44,7 @@ "_charts-BjEBSMrK.js" ], "css": [ - "assets/index-677RgwmW.css" + "assets/index-prcd5sVt.css" ] } } \ No newline at end of file diff --git a/Cunkebao/dist/index.html b/Cunkebao/dist/index.html index 16e6d604..f953a3da 100644 --- a/Cunkebao/dist/index.html +++ b/Cunkebao/dist/index.html @@ -11,13 +11,13 @@ - + - +
From 51b1918f72d587cc803ed6f3c24fdbc23d2e1461 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: Wed, 10 Sep 2025 16:52:28 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat(=E5=BE=AE=E4=BF=A1=E8=81=8A=E5=A4=A9):?= =?UTF-8?q?=20=E6=B7=BB=E5=8A=A0=E8=81=8A=E5=A4=A9=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E5=92=8C=E5=AE=A2=E6=88=B7=E8=BD=AC=E6=8E=A5?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在微信聊天界面新增聊天记录搜索组件,支持按时间和关键词搜索 - 添加客户转接功能组件,支持选择目标客服和添加附言 - 实现一键转回功能 - 添加相关API接口和状态管理 - 配置antd中文语言环境和dayjs本地化 --- Cunkebao/src/main.tsx | 13 +- Cunkebao/src/pages/pc/ckbox/weChat/api.ts | 41 ++++ .../components/chatRecord/index.tsx | 161 +++++++++++++ .../components/toContract/index.tsx | 226 ++++++++++++++++++ .../components/MessageEnter/index.tsx | 28 ++- .../src/store/module/weChat/weChat.data.ts | 7 +- Cunkebao/src/store/module/weChat/weChat.ts | 44 ++++ 7 files changed, 510 insertions(+), 10 deletions(-) create mode 100644 Cunkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageEnter/components/chatRecord/index.tsx create mode 100644 Cunkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageEnter/components/toContract/index.tsx diff --git a/Cunkebao/src/main.tsx b/Cunkebao/src/main.tsx index 813ccaed..e442b9c1 100644 --- a/Cunkebao/src/main.tsx +++ b/Cunkebao/src/main.tsx @@ -1,10 +1,17 @@ // main.tsx import React from "react"; import { createRoot } from "react-dom/client"; +import { ConfigProvider } from "antd"; +import zhCN from "antd/locale/zh_CN"; +import dayjs from "dayjs"; +import "dayjs/locale/zh-cn"; import App from "./App"; import "./styles/global.scss"; import { db } from "@/utils/db"; // 引入数据库实例 +// 设置dayjs为中文 +dayjs.locale("zh-cn"); + // 数据库初始化 async function initializeApp() { try { @@ -26,7 +33,11 @@ async function initializeApp() { // 渲染应用 const root = createRoot(document.getElementById("root")!); - root.render(); + root.render( + + + , + ); } // 启动应用 diff --git a/Cunkebao/src/pages/pc/ckbox/weChat/api.ts b/Cunkebao/src/pages/pc/ckbox/weChat/api.ts index 98bc336a..af476f26 100644 --- a/Cunkebao/src/pages/pc/ckbox/weChat/api.ts +++ b/Cunkebao/src/pages/pc/ckbox/weChat/api.ts @@ -13,7 +13,48 @@ import { //读取聊天信息 //kf.quwanzhi.com:9991/api/WechatFriend/clearUnreadCount +function jsonToQueryString(json) { + const params = new URLSearchParams(); + for (const key in json) { + if (Object.prototype.hasOwnProperty.call(json, key)) { + params.append(key, json[key]); + } + } + return params.toString(); +} +//转移客户 +export function WechatFriendAllot(params: { + wechatFriendId?: number; + wechatChatroomId?: number; + toAccountId: number; + notifyReceiver: boolean; + comment: string; +}) { + return request( + "/api/wechatFriend/allot?" + jsonToQueryString(params), + undefined, + "PUT", + ); +} +//获取可转移客服列表 +export function getTransferableAgentList() { + return request("/api/account/myDepartmentAccountsForTransfer", {}, "GET"); +} + +// 微信好友列表 +export function WechatFriendRebackAllot(params: { + wechatFriendId?: number; + wechatChatroomId?: number; +}) { + return request( + "/api/wechatFriend/rebackAllot?" + jsonToQueryString(params), + undefined, + "PUT", + ); +} + +// 微信群列表 export function WechatGroup(params) { return request("/api/WechatGroup/list", params, "GET"); } diff --git a/Cunkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageEnter/components/chatRecord/index.tsx b/Cunkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageEnter/components/chatRecord/index.tsx new file mode 100644 index 00000000..b7af4596 --- /dev/null +++ b/Cunkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageEnter/components/chatRecord/index.tsx @@ -0,0 +1,161 @@ +import React, { useState } from "react"; +import { Button, Modal, Input, DatePicker, message } from "antd"; +import { MessageOutlined } from "@ant-design/icons"; +import dayjs from "dayjs"; + +const { RangePicker } = DatePicker; + +interface ChatRecordProps { + onSearch?: (data: { dateRange: [string, string]; content: string }) => void; + className?: string; + disabled?: boolean; +} + +const ChatRecord: React.FC = ({ + onSearch, + className, + disabled = false, +}) => { + const [visible, setVisible] = useState(false); + const [searchContent, setSearchContent] = useState(""); + const [dateRange, setDateRange] = useState<[dayjs.Dayjs, dayjs.Dayjs] | null>( + null, + ); + const [loading, setLoading] = useState(false); + + // 打开弹窗 + const openModal = () => { + setVisible(true); + }; + + // 关闭弹窗并重置状态 + const closeModal = () => { + setVisible(false); + setSearchContent(""); + setDateRange(null); + setLoading(false); + }; + + // 执行查找 + const handleSearch = async () => { + if (!dateRange) { + message.warning("请选择时间范围"); + return; + } + + if (!searchContent.trim()) { + message.warning("请输入查找内容"); + return; + } + + try { + setLoading(true); + + const searchData = { + dateRange: [ + dateRange[0].format("YYYY-MM-DD 00:00:00"), + dateRange[1].format("YYYY-MM-DD 23:59:59"), + ] as [string, string], + content: searchContent.trim(), + }; + + // 调用回调函数 + if (onSearch) { + await onSearch(searchData); + } + + message.success("查找完成"); + closeModal(); + } catch (error) { + console.error("查找失败:", error); + message.error("查找失败,请重试"); + } finally { + setLoading(false); + } + }; + + return ( + <> +
+ + 聊天记录 +
+ + + + + , + ]} + > +
+ {/* 时间范围选择 */} +
+
+ 时间范围 +
+ +
+ + {/* 查找内容输入 */} +
+
+ 查找内容 +
+ setSearchContent(e.target.value)} + size="large" + maxLength={100} + showCount + disabled={loading} + /> +
+
+
+ + ); +}; + +export default ChatRecord; diff --git a/Cunkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageEnter/components/toContract/index.tsx b/Cunkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageEnter/components/toContract/index.tsx new file mode 100644 index 00000000..96e95ceb --- /dev/null +++ b/Cunkebao/src/pages/pc/ckbox/weChat/components/ChatWindow/components/MessageEnter/components/toContract/index.tsx @@ -0,0 +1,226 @@ +import React, { useState } from "react"; +import { Button, Modal, Select, Input, message } from "antd"; +import { ShareAltOutlined } from "@ant-design/icons"; +import { + getTransferableAgentList, + WechatFriendAllot, + WechatFriendRebackAllot, +} from "@/pages/pc/ckbox/weChat/api"; +import { useCurrentContact } from "@/store/module/weChat/weChat"; +const { TextArea } = Input; +const { Option } = Select; + +interface ToContractProps { + className?: string; + disabled?: boolean; +} +interface DepartItem { + id: number; + userName: string; + realName: string; + nickname: string; + avatar: string; + memo: string; + departmentId: number; + alive: boolean; +} + +const ToContract: React.FC = ({ + className, + disabled = false, +}) => { + const currentContact = useCurrentContact(); + const [visible, setVisible] = useState(false); + const [selectedTarget, setSelectedTarget] = useState(null); + const [comment, setComment] = useState(""); + const [loading, setLoading] = useState(false); + const [customerServiceList, setCustomerServiceList] = useState( + [], + ); + // 打开弹窗 + const openModal = () => { + setVisible(true); + getTransferableAgentList().then(data => { + setCustomerServiceList(data); + }); + }; + + // 关闭弹窗并重置状态 + const closeModal = () => { + setVisible(false); + setSelectedTarget(null); + setComment(""); + setLoading(false); + }; + + // 确定转给他人 + const handleConfirm = async () => { + if (!selectedTarget) { + message.warning("请选择目标客服"); + return; + } + + try { + setLoading(true); + + console.log(currentContact); + + // 调用转接接口 + if (currentContact) { + if ("chatroomId" in currentContact && currentContact.chatroomId) { + await WechatFriendAllot({ + wechatChatroomId: currentContact.id, + toAccountId: selectedTarget as number, + notifyReceiver: true, + comment: comment.trim(), + }); + } else { + await WechatFriendAllot({ + wechatFriendId: currentContact.id, + toAccountId: selectedTarget as number, + notifyReceiver: true, + comment: comment.trim(), + }); + } + } + + message.success("转接成功"); + closeModal(); + } catch (error) { + console.error("转接失败:", error); + message.error("转接失败,请重试"); + } finally { + setLoading(false); + } + }; + + // 一键转回 + const handleReturn = async () => { + try { + setLoading(true); + + // 调用转回接口 + if (currentContact) { + if ("chatroomId" in currentContact && currentContact.chatroomId) { + await WechatFriendRebackAllot({ + wechatChatroomId: currentContact.id, + }); + } else { + await WechatFriendRebackAllot({ + wechatFriendId: currentContact.id, + }); + } + } + + message.success("转回成功"); + closeModal(); + } catch (error) { + console.error("转回失败:", error); + message.error("转回失败,请重试"); + } finally { + setLoading(false); + } + }; + + return ( + <> +
+ + 转给他人 +
+ + + +
+ + +
+ , + ]} + > +
+ {/* 目标客服选择 */} +
+
+ 目标客服 +
+ +
+ + {/* 附言输入 */} +
+
+ 附言 +
+