代码提交
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
|||||||
Card,
|
Card,
|
||||||
Tag,
|
Tag,
|
||||||
message,
|
message,
|
||||||
|
Modal,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import {
|
import {
|
||||||
PhoneOutlined,
|
PhoneOutlined,
|
||||||
@@ -22,9 +23,12 @@ import {
|
|||||||
StarOutlined,
|
StarOutlined,
|
||||||
EditOutlined,
|
EditOutlined,
|
||||||
CheckOutlined,
|
CheckOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
NotificationOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
|
import { ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
|
||||||
import { useCkChatStore } from "@/store/module/ckchat/ckchat";
|
import { useCkChatStore } from "@/store/module/ckchat/ckchat";
|
||||||
|
import { useWebSocketStore } from "@/store/module/websocket/websocket";
|
||||||
import styles from "./Person.module.scss";
|
import styles from "./Person.module.scss";
|
||||||
|
|
||||||
const { Sider } = Layout;
|
const { Sider } = Layout;
|
||||||
@@ -47,10 +51,27 @@ const Person: React.FC<PersonProps> = ({
|
|||||||
contract.labels || [],
|
contract.labels || [],
|
||||||
);
|
);
|
||||||
const [allAvailableTags, setAllAvailableTags] = useState<string[]>([]);
|
const [allAvailableTags, setAllAvailableTags] = useState<string[]>([]);
|
||||||
|
const [isAddingTag, setIsAddingTag] = useState(false);
|
||||||
|
const [newTagValue, setNewTagValue] = useState("");
|
||||||
|
|
||||||
|
// 判断是否为群聊
|
||||||
|
const isGroup = 'chatroomId' in contract;
|
||||||
|
|
||||||
|
// 群聊相关状态
|
||||||
|
const [isEditingGroupName, setIsEditingGroupName] = useState(false);
|
||||||
|
const [groupNameValue, setGroupNameValue] = useState(contract.name || '');
|
||||||
|
const [isEditingGroupNotice, setIsEditingGroupNotice] = useState(false);
|
||||||
|
const [groupNoticeValue, setGroupNoticeValue] = useState(contract.notice || '');
|
||||||
|
const [isEditingSelfDisplayName, setIsEditingSelfDisplayName] = useState(false);
|
||||||
|
const [selfDisplayNameValue, setSelfDisplayNameValue] = useState(contract.selfDisplyName || '');
|
||||||
|
const [isGroupNoticeModalVisible, setIsGroupNoticeModalVisible] = useState(false);
|
||||||
|
|
||||||
|
// 构建联系人或群聊详细信息
|
||||||
|
|
||||||
const kfSelectedUser = useCkChatStore(state =>
|
const kfSelectedUser = useCkChatStore(state =>
|
||||||
state.getKfUserInfo(contract.wechatAccountId || 0),
|
state.getKfUserInfo(contract.wechatAccountId || 0),
|
||||||
);
|
);
|
||||||
|
const { sendCommand } = useWebSocketStore();
|
||||||
|
|
||||||
// 获取所有可用标签
|
// 获取所有可用标签
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -68,22 +89,102 @@ const Person: React.FC<PersonProps> = ({
|
|||||||
fetchAvailableTags();
|
fetchAvailableTags();
|
||||||
}, [kfSelectedUser, contract.labels]);
|
}, [kfSelectedUser, contract.labels]);
|
||||||
|
|
||||||
// 当contract变化时更新备注值和标签
|
// 当contract变化时更新各种值
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setRemarkValue(contract.conRemark || "");
|
setRemarkValue(contract.conRemark || "");
|
||||||
setIsEditingRemark(false);
|
setIsEditingRemark(false);
|
||||||
setSelectedTags(contract.labels || []);
|
setSelectedTags(contract.labels || []);
|
||||||
}, [contract.conRemark, contract.labels]);
|
|
||||||
|
if (isGroup) {
|
||||||
|
setGroupNameValue(contract.name || '');
|
||||||
|
setIsEditingGroupName(false);
|
||||||
|
setGroupNoticeValue(contract.notice || '');
|
||||||
|
setIsEditingGroupNotice(false);
|
||||||
|
setSelfDisplayNameValue(contract.selfDisplyName || '');
|
||||||
|
setIsEditingSelfDisplayName(false);
|
||||||
|
}
|
||||||
|
}, [contract.conRemark, contract.labels, contract.name, contract.notice, contract.selfDisplyName, isGroup]);
|
||||||
|
|
||||||
// 处理备注保存
|
// 处理备注保存
|
||||||
const handleSaveRemark = () => {
|
const handleSaveRemark = () => {
|
||||||
// 这里应该调用API保存备注到后端
|
if (isGroup) {
|
||||||
// 暂时只更新本地状态
|
// 群聊备注修改
|
||||||
|
sendCommand("CmdModifyGroupRemark", {
|
||||||
|
wechatAccountId: contract.wechatAccountId,
|
||||||
|
chatroomId: contract.chatroomId,
|
||||||
|
newRemark: remarkValue,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 好友备注修改
|
||||||
|
sendCommand("CmdModifyFriendRemark", {
|
||||||
|
wechatAccountId: contract.wechatAccountId,
|
||||||
|
wechatFriendId: contract.id,
|
||||||
|
newRemark: remarkValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
messageApi.success("备注保存成功");
|
messageApi.success("备注保存成功");
|
||||||
setIsEditingRemark(false);
|
setIsEditingRemark(false);
|
||||||
// 更新contract对象中的备注(实际项目中应该通过props回调或状态管理)
|
// 更新contract对象中的备注(实际项目中应该通过props回调或状态管理)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 处理群名称保存
|
||||||
|
const handleSaveGroupName = () => {
|
||||||
|
sendCommand("CmdChatroomOperate", {
|
||||||
|
wechatAccountId: contract.wechatAccountId,
|
||||||
|
wechatChatroomId: contract.id,
|
||||||
|
chatroomOperateType: 6,
|
||||||
|
extra: `{\"chatroomName\":\"${groupNameValue}\"}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
messageApi.success("群名称修改成功");
|
||||||
|
setIsEditingGroupName(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击编辑群名称按钮
|
||||||
|
const handleEditGroupName = () => {
|
||||||
|
setGroupNameValue(contract.name || '');
|
||||||
|
setIsEditingGroupName(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理群公告保存
|
||||||
|
const handleSaveGroupNotice = () => {
|
||||||
|
sendCommand("CmdChatroomOperate", {
|
||||||
|
wechatAccountId: contract.wechatAccountId,
|
||||||
|
wechatChatroomId: contract.id,
|
||||||
|
chatroomOperateType: 5,
|
||||||
|
extra: `{\"announce\":\"${groupNoticeValue}\"}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
messageApi.success("群公告修改成功");
|
||||||
|
setIsEditingGroupNotice(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击编辑群公告按钮
|
||||||
|
const handleEditGroupNotice = () => {
|
||||||
|
setGroupNoticeValue(contract.notice || '');
|
||||||
|
setIsGroupNoticeModalVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理我在本群中的昵称保存
|
||||||
|
const handleSaveSelfDisplayName = () => {
|
||||||
|
sendCommand("CmdChatroomOperate", {
|
||||||
|
wechatAccountId: contract.wechatAccountId,
|
||||||
|
wechatChatroomId: contract.id,
|
||||||
|
chatroomOperateType: 8,
|
||||||
|
extra: `${selfDisplayNameValue}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
messageApi.success("群昵称修改成功");
|
||||||
|
setIsEditingSelfDisplayName(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击编辑群昵称按钮
|
||||||
|
const handleEditSelfDisplayName = () => {
|
||||||
|
setSelfDisplayNameValue(contract.selfDisplyName || '');
|
||||||
|
setIsEditingSelfDisplayName(true);
|
||||||
|
};
|
||||||
|
|
||||||
// 处理取消编辑
|
// 处理取消编辑
|
||||||
const handleCancelEdit = () => {
|
const handleCancelEdit = () => {
|
||||||
setRemarkValue(contract.conRemark || "");
|
setRemarkValue(contract.conRemark || "");
|
||||||
@@ -98,20 +199,90 @@ const Person: React.FC<PersonProps> = ({
|
|||||||
|
|
||||||
setSelectedTags(newSelectedTags);
|
setSelectedTags(newSelectedTags);
|
||||||
|
|
||||||
// 这里应该调用API保存标签到后端
|
// 使用WebSocket发送修改标签命令
|
||||||
|
if (isGroup) {
|
||||||
|
// 群聊标签修改
|
||||||
|
sendCommand("CmdModifyGroupLabel", {
|
||||||
|
labels: newSelectedTags,
|
||||||
|
seq: +new Date(),
|
||||||
|
wechatAccountId: contract.wechatAccountId,
|
||||||
|
chatroomId: contract.chatroomId,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 好友标签修改
|
||||||
|
sendCommand("CmdModifyFriendLabel", {
|
||||||
|
labels: newSelectedTags,
|
||||||
|
seq: +new Date(),
|
||||||
|
wechatAccountId: contract.wechatAccountId,
|
||||||
|
wechatFriendId: contract.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
messageApi.success(
|
messageApi.success(
|
||||||
`标签"${tagName}"${selectedTags.includes(tagName) ? "已取消" : "已选中"}`,
|
`标签"${tagName}"${selectedTags.includes(tagName) ? "已取消" : "已选中"}`,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 模拟联系人详细信息
|
// 处理新增标签
|
||||||
|
const handleAddTag = () => {
|
||||||
|
if (!newTagValue.trim()) {
|
||||||
|
messageApi.error("请输入标签名称");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allAvailableTags.includes(newTagValue.trim())) {
|
||||||
|
messageApi.error("标签已存在");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newTag = newTagValue.trim();
|
||||||
|
|
||||||
|
// 添加到可用标签列表
|
||||||
|
setAllAvailableTags(prev => [...prev, newTag]);
|
||||||
|
|
||||||
|
// 自动选中新添加的标签
|
||||||
|
setSelectedTags(prev => [...prev, newTag]);
|
||||||
|
|
||||||
|
// 使用WebSocket发送新增标签命令
|
||||||
|
if (isGroup) {
|
||||||
|
// 群聊标签修改
|
||||||
|
sendCommand("CmdModifyGroupLabel", {
|
||||||
|
labels: [...selectedTags, newTag],
|
||||||
|
seq: +new Date(),
|
||||||
|
wechatAccountId: contract.wechatAccountId,
|
||||||
|
chatroomId: contract.chatroomId,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 好友标签修改
|
||||||
|
sendCommand("CmdModifyFriendLabel", {
|
||||||
|
labels: [...selectedTags, newTag],
|
||||||
|
seq: +new Date(),
|
||||||
|
wechatAccountId: contract.wechatAccountId,
|
||||||
|
wechatFriendId: contract.id || contract.wechatId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
messageApi.success(`标签"${newTag}"添加成功`);
|
||||||
|
setNewTagValue("");
|
||||||
|
setIsAddingTag(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理取消新增标签
|
||||||
|
const handleCancelAddTag = () => {
|
||||||
|
setNewTagValue("");
|
||||||
|
setIsAddingTag(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 构建联系人或群聊详细信息
|
||||||
const contractInfo = {
|
const contractInfo = {
|
||||||
name: contract.name,
|
name: contract.name || contract.nickname,
|
||||||
nickname: contract.nickname,
|
nickname: contract.nickname,
|
||||||
conRemark: remarkValue, // 使用当前编辑的备注值
|
conRemark: remarkValue, // 使用当前编辑的备注值
|
||||||
alias: contract.alias,
|
alias: contract.alias,
|
||||||
wechatId: contract.wechatId,
|
wechatId: contract.wechatId,
|
||||||
avatar: contract.avatar,
|
chatroomId: isGroup ? contract.chatroomId : undefined,
|
||||||
|
chatroomOwner: isGroup ? contract.chatroomOwner : undefined,
|
||||||
|
avatar: contract.avatar || contract.chatroomAvatar,
|
||||||
phone: contract.phone || "-",
|
phone: contract.phone || "-",
|
||||||
email: contract.email || "-",
|
email: contract.email || "-",
|
||||||
department: contract.department || "-",
|
department: contract.department || "-",
|
||||||
@@ -119,9 +290,11 @@ const Person: React.FC<PersonProps> = ({
|
|||||||
company: contract.company || "-",
|
company: contract.company || "-",
|
||||||
region: contract.region || "-",
|
region: contract.region || "-",
|
||||||
joinDate: contract.joinDate || "-",
|
joinDate: contract.joinDate || "-",
|
||||||
|
notice: isGroup ? contract.notice : undefined,
|
||||||
|
selfDisplyName: isGroup ? contract.selfDisplyName : undefined,
|
||||||
status: "在线",
|
status: "在线",
|
||||||
tags: selectedTags,
|
tags: selectedTags,
|
||||||
bio: contract.bio || "-",
|
bio: contract.bio || contract.signature || "-",
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!showProfile) {
|
if (!showProfile) {
|
||||||
@@ -151,14 +324,59 @@ const Person: React.FC<PersonProps> = ({
|
|||||||
icon={<UserOutlined />}
|
icon={<UserOutlined />}
|
||||||
/>
|
/>
|
||||||
<div className={styles.profileInfo}>
|
<div className={styles.profileInfo}>
|
||||||
<Tooltip
|
{isGroup && isEditingGroupName ? (
|
||||||
title={contractInfo.nickname || contractInfo.name}
|
<div
|
||||||
placement="top"
|
style={{
|
||||||
>
|
display: "flex",
|
||||||
<h4 className={styles.profileNickname}>
|
alignItems: "center",
|
||||||
{contractInfo.nickname || contractInfo.name}
|
gap: "8px",
|
||||||
</h4>
|
}}
|
||||||
</Tooltip>
|
>
|
||||||
|
<Input
|
||||||
|
value={groupNameValue}
|
||||||
|
onChange={e => setGroupNameValue(e.target.value)}
|
||||||
|
placeholder="请输入群名称"
|
||||||
|
size="small"
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<CheckOutlined />}
|
||||||
|
onClick={handleSaveGroupName}
|
||||||
|
style={{ color: "#52c41a" }}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<CloseOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
setGroupNameValue(contract.name || '');
|
||||||
|
setIsEditingGroupName(false);
|
||||||
|
}}
|
||||||
|
style={{ color: "#ff4d4f" }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Tooltip
|
||||||
|
title={contractInfo.nickname || contractInfo.name}
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<div style={{ display: "flex", alignItems: "center" }}>
|
||||||
|
<h4 className={styles.profileNickname}>
|
||||||
|
{contractInfo.nickname || contractInfo.name}
|
||||||
|
</h4>
|
||||||
|
{isGroup && (
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
onClick={() => setIsEditingGroupName(true)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className={styles.profileStatus}>
|
<div className={styles.profileStatus}>
|
||||||
<span className={styles.statusDot}></span>
|
<span className={styles.statusDot}></span>
|
||||||
@@ -169,58 +387,245 @@ const Person: React.FC<PersonProps> = ({
|
|||||||
|
|
||||||
{/* 详细信息卡片 */}
|
{/* 详细信息卡片 */}
|
||||||
<Card title="详细信息" className={styles.profileCard}>
|
<Card title="详细信息" className={styles.profileCard}>
|
||||||
<div className={styles.infoItem}>
|
{isGroup ? (
|
||||||
<TeamOutlined className={styles.infoIcon} />
|
// 群聊信息
|
||||||
<span className={styles.infoLabel}>微信号:</span>
|
<>
|
||||||
<span className={styles.infoValue}>
|
<div className={styles.infoItem}>
|
||||||
{contractInfo.alias || contractInfo.wechatId}
|
<TeamOutlined className={styles.infoIcon} />
|
||||||
</span>
|
<span className={styles.infoLabel}>群ID:</span>
|
||||||
</div>
|
<span className={styles.infoValue}>
|
||||||
<div className={styles.infoItem}>
|
{contractInfo.chatroomId}
|
||||||
<PhoneOutlined className={styles.infoIcon} />
|
</span>
|
||||||
<span className={styles.infoLabel}>电话:</span>
|
</div>
|
||||||
<span className={styles.infoValue}>{contractInfo.phone}</span>
|
<div className={styles.infoItem}>
|
||||||
</div>
|
<UserOutlined className={styles.infoIcon} />
|
||||||
<div className={styles.infoItem}>
|
<span className={styles.infoLabel}>群主:</span>
|
||||||
<EnvironmentOutlined className={styles.infoIcon} />
|
<span className={styles.infoValue}>{contractInfo.chatroomOwner}</span>
|
||||||
<span className={styles.infoLabel}>地区:</span>
|
</div>
|
||||||
<span className={styles.infoValue}>{contractInfo.region}</span>
|
<div className={styles.infoItem}>
|
||||||
</div>
|
<UserOutlined className={styles.infoIcon} />
|
||||||
<div className={styles.infoItem}>
|
<span className={styles.infoLabel}>群昵称:</span>
|
||||||
<EditOutlined className={styles.infoIcon} />
|
<div className={styles.infoValue}>
|
||||||
<span className={styles.infoLabel}>备注:</span>
|
{isEditingSelfDisplayName ? (
|
||||||
<div className={styles.infoValue}>
|
<div
|
||||||
{isEditingRemark ? (
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "8px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
value={selfDisplayNameValue}
|
||||||
|
onChange={e => setSelfDisplayNameValue(e.target.value)}
|
||||||
|
placeholder="请输入群昵称"
|
||||||
|
size="small"
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<CheckOutlined />}
|
||||||
|
onClick={handleSaveSelfDisplayName}
|
||||||
|
style={{ color: "#52c41a" }}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<CloseOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
setSelfDisplayNameValue(contract.selfDisplyName || '');
|
||||||
|
setIsEditingSelfDisplayName(false);
|
||||||
|
}}
|
||||||
|
style={{ color: "#ff4d4f" }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "8px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>{contractInfo.selfDisplyName || "点击添加群昵称"}</span>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
onClick={() => setIsEditingSelfDisplayName(true)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
// 好友信息
|
||||||
|
<>
|
||||||
|
<div className={styles.infoItem}>
|
||||||
|
<TeamOutlined className={styles.infoIcon} />
|
||||||
|
<span className={styles.infoLabel}>微信号:</span>
|
||||||
|
<span className={styles.infoValue}>
|
||||||
|
{contractInfo.alias || contractInfo.wechatId}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.infoItem}>
|
||||||
|
<PhoneOutlined className={styles.infoIcon} />
|
||||||
|
<span className={styles.infoLabel}>电话:</span>
|
||||||
|
<span className={styles.infoValue}>{contractInfo.phone}</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.infoItem}>
|
||||||
|
<EnvironmentOutlined className={styles.infoIcon} />
|
||||||
|
<span className={styles.infoLabel}>地区:</span>
|
||||||
|
<span className={styles.infoValue}>{contractInfo.region}</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{!isGroup && (
|
||||||
|
<div className={styles.infoItem}>
|
||||||
|
<EditOutlined className={styles.infoIcon} />
|
||||||
|
<span className={styles.infoLabel}>备注:</span>
|
||||||
|
<div className={styles.infoValue}>
|
||||||
|
{isEditingRemark ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "8px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
value={remarkValue}
|
||||||
|
onChange={e => setRemarkValue(e.target.value)}
|
||||||
|
placeholder="请输入备注"
|
||||||
|
size="small"
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<CheckOutlined />}
|
||||||
|
onClick={handleSaveRemark}
|
||||||
|
style={{ color: "#52c41a" }}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<CloseOutlined />}
|
||||||
|
onClick={handleCancelEdit}
|
||||||
|
style={{ color: "#ff4d4f" }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: "8px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>{contractInfo.conRemark || "点击添加备注"}</span>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<EditOutlined />}
|
||||||
|
onClick={() => setIsEditingRemark(true)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* 标签 - 仅在非群聊时显示 */}
|
||||||
|
{!isGroup && (
|
||||||
|
<Card title="标签" className={styles.profileCard}>
|
||||||
|
<div className={styles.tagsContainer}>
|
||||||
|
{/* 渲染所有可用标签,选中的排在前面 */}
|
||||||
|
{[...new Set([...selectedTags, ...allAvailableTags])].map(
|
||||||
|
(tag, index) => {
|
||||||
|
const isSelected = selectedTags.includes(tag);
|
||||||
|
return (
|
||||||
|
<Tag
|
||||||
|
key={index}
|
||||||
|
color={isSelected ? "blue" : "default"}
|
||||||
|
style={{
|
||||||
|
cursor: "pointer",
|
||||||
|
border: isSelected
|
||||||
|
? "1px solid #1890ff"
|
||||||
|
: "1px solid #d9d9d9",
|
||||||
|
backgroundColor: isSelected ? "#e6f7ff" : "#fafafa",
|
||||||
|
}}
|
||||||
|
onClick={() => handleTagToggle(tag)}
|
||||||
|
>
|
||||||
|
{tag}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 新增标签区域 */}
|
||||||
|
{isAddingTag ? (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: "8px",
|
gap: "8px",
|
||||||
|
marginTop: "8px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
value={remarkValue}
|
value={newTagValue}
|
||||||
onChange={e => setRemarkValue(e.target.value)}
|
onChange={e => setNewTagValue(e.target.value)}
|
||||||
placeholder="请输入备注"
|
placeholder="请输入标签名称"
|
||||||
size="small"
|
size="small"
|
||||||
style={{ flex: 1 }}
|
style={{ width: "120px" }}
|
||||||
|
onPressEnter={handleAddTag}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
type="text"
|
type="text"
|
||||||
size="small"
|
size="small"
|
||||||
icon={<CheckOutlined />}
|
icon={<CheckOutlined />}
|
||||||
onClick={handleSaveRemark}
|
onClick={handleAddTag}
|
||||||
style={{ color: "#52c41a" }}
|
style={{ color: "#52c41a" }}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
type="text"
|
type="text"
|
||||||
size="small"
|
size="small"
|
||||||
icon={<CloseOutlined />}
|
icon={<CloseOutlined />}
|
||||||
onClick={handleCancelEdit}
|
onClick={handleCancelAddTag}
|
||||||
style={{ color: "#ff4d4f" }}
|
style={{ color: "#ff4d4f" }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
<Tag
|
||||||
|
style={{
|
||||||
|
cursor: "pointer",
|
||||||
|
border: "1px dashed #d9d9d9",
|
||||||
|
backgroundColor: "#fafafa",
|
||||||
|
}}
|
||||||
|
onClick={() => setIsAddingTag(true)}
|
||||||
|
>
|
||||||
|
<PlusOutlined /> 新增标签
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{allAvailableTags.length === 0 && !isAddingTag && (
|
||||||
|
<span style={{ color: "#999", fontSize: "12px" }}>
|
||||||
|
暂无可用标签
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 个人简介或群公告 */}
|
||||||
|
<Card title={isGroup ? "群公告" : "个人简介"} className={styles.profileCard}>
|
||||||
|
{isGroup ? (
|
||||||
|
// 群聊简介(原群公告)
|
||||||
|
<div className={styles.infoValue}>
|
||||||
|
{isEditingGroupNotice ? (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@@ -228,55 +633,45 @@ const Person: React.FC<PersonProps> = ({
|
|||||||
gap: "8px",
|
gap: "8px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span>{contractInfo.conRemark || "点击添加备注"}</span>
|
<Input.TextArea
|
||||||
|
value={groupNoticeValue}
|
||||||
|
onChange={e => setGroupNoticeValue(e.target.value)}
|
||||||
|
placeholder="请输入内容"
|
||||||
|
rows={6}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "flex-start",
|
||||||
|
gap: "8px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={styles.bioText}
|
||||||
|
style={{
|
||||||
|
maxHeight: "120px", // 约5行文本的高度
|
||||||
|
overflowY: "auto", // 添加垂直滚动条
|
||||||
|
paddingRight: "5px", // 为滚动条留出空间
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{contractInfo.notice || "点击添加群公告"}
|
||||||
|
</div>
|
||||||
<Button
|
<Button
|
||||||
type="text"
|
type="text"
|
||||||
size="small"
|
size="small"
|
||||||
icon={<EditOutlined />}
|
icon={<EditOutlined />}
|
||||||
onClick={() => setIsEditingRemark(true)}
|
onClick={() => setIsEditingGroupNotice(true)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
) : (
|
||||||
</Card>
|
// 个人简介
|
||||||
|
<p className={styles.bioText}>{contractInfo.bio}</p>
|
||||||
{/* 标签 */}
|
)}
|
||||||
<Card title="标签" className={styles.profileCard}>
|
|
||||||
<div className={styles.tagsContainer}>
|
|
||||||
{/* 渲染所有可用标签,选中的排在前面 */}
|
|
||||||
{[...new Set([...selectedTags, ...allAvailableTags])].map(
|
|
||||||
(tag, index) => {
|
|
||||||
const isSelected = selectedTags.includes(tag);
|
|
||||||
return (
|
|
||||||
<Tag
|
|
||||||
key={index}
|
|
||||||
color={isSelected ? "blue" : "default"}
|
|
||||||
style={{
|
|
||||||
cursor: "pointer",
|
|
||||||
border: isSelected
|
|
||||||
? "1px solid #1890ff"
|
|
||||||
: "1px solid #d9d9d9",
|
|
||||||
backgroundColor: isSelected ? "#e6f7ff" : "#fafafa",
|
|
||||||
}}
|
|
||||||
onClick={() => handleTagToggle(tag)}
|
|
||||||
>
|
|
||||||
{tag}
|
|
||||||
</Tag>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)}
|
|
||||||
{allAvailableTags.length === 0 && (
|
|
||||||
<span style={{ color: "#999", fontSize: "12px" }}>
|
|
||||||
暂无可用标签
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
{/* 个人简介 */}
|
|
||||||
<Card title="个人简介" className={styles.profileCard}>
|
|
||||||
<p className={styles.bioText}>{contractInfo.bio}</p>
|
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* 操作按钮 */}
|
{/* 操作按钮 */}
|
||||||
@@ -294,6 +689,36 @@ const Person: React.FC<PersonProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Sider>
|
</Sider>
|
||||||
|
|
||||||
|
{/* 群公告编辑弹窗 */}
|
||||||
|
<Modal
|
||||||
|
title="发布群公告"
|
||||||
|
open={isGroupNoticeModalVisible}
|
||||||
|
onCancel={() => setIsGroupNoticeModalVisible(false)}
|
||||||
|
footer={[
|
||||||
|
<Button key="cancel" onClick={() => setIsGroupNoticeModalVisible(false)}>
|
||||||
|
取消
|
||||||
|
</Button>,
|
||||||
|
<Button
|
||||||
|
key="submit"
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
handleSaveGroupNotice();
|
||||||
|
setIsGroupNoticeModalVisible(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input.TextArea
|
||||||
|
value={groupNoticeValue}
|
||||||
|
onChange={e => setGroupNoticeValue(e.target.value)}
|
||||||
|
placeholder="请输入内容"
|
||||||
|
rows={6}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ class UserController extends BaseController
|
|||||||
* 获取验证码
|
* 获取验证码
|
||||||
* @return \think\response\Json
|
* @return \think\response\Json
|
||||||
*/
|
*/
|
||||||
public function getVerifyCode()
|
public function getVerifyCode($isJson = false)
|
||||||
{
|
{
|
||||||
$headerData = ['client:' . self::CLIENT_TYPE];
|
$headerData = ['client:' . self::CLIENT_TYPE];
|
||||||
$header = setHeader($headerData, '', 'plain');
|
$header = setHeader($headerData, '', 'plain');
|
||||||
@@ -279,17 +279,19 @@ class UserController extends BaseController
|
|||||||
if (is_array($response)) {
|
if (is_array($response)) {
|
||||||
// 如果verifyCodeImage和verifySessionId都不为null,返回它们
|
// 如果verifyCodeImage和verifySessionId都不为null,返回它们
|
||||||
if (!empty($response['verifyCodeImage']) && !empty($response['verifySessionId'])) {
|
if (!empty($response['verifyCodeImage']) && !empty($response['verifySessionId'])) {
|
||||||
return successJson([
|
$returnData = [
|
||||||
'verifyCodeImage' => $response['verifyCodeImage'],
|
'verifyCodeImage' => $response['verifyCodeImage'],
|
||||||
'verifySessionId' => $response['verifySessionId']
|
'verifySessionId' => $response['verifySessionId']
|
||||||
]);
|
];
|
||||||
|
return !empty($isJson) ? json_encode(['code' => 200,'data' => $returnData]) : successJson($returnData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果不是预期的格式,返回原始数据
|
// 如果不是预期的格式,返回原始数据
|
||||||
return successJson($response);
|
return !empty($isJson) ? json_encode(['code' => 500,'data' => $response]) : errorJson('无需验证码');
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return errorJson('获取验证码失败:' . $e->getMessage());
|
$msg = '获取验证码失败'. $e->getMessage();
|
||||||
|
return !empty($isJson) ? json_encode(['code' => 400,'msg' => $msg]) : errorJson($msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,11 +141,16 @@ Route::group('v1/', function () {
|
|||||||
Route::get('friendRequestTaskStats', 'app\cunkebao\controller\StatsController@getFriendRequestTaskStats');
|
Route::get('friendRequestTaskStats', 'app\cunkebao\controller\StatsController@getFriendRequestTaskStats');
|
||||||
Route::get('userInfoStats', 'app\cunkebao\controller\StatsController@userInfoStats');
|
Route::get('userInfoStats', 'app\cunkebao\controller\StatsController@userInfoStats');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
})->middleware(['jwt']);
|
})->middleware(['jwt']);
|
||||||
|
|
||||||
|
|
||||||
|
// 客服登录
|
||||||
|
Route::group('v1/kefu', function () {
|
||||||
|
Route::post('login', 'app\cunkebao\controller\KeFuLoginController@index'); // 获取好友列表
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Route::group('v1/api/scenarios', function () {
|
Route::group('v1/api/scenarios', function () {
|
||||||
Route::any('', 'app\cunkebao\controller\plan\PostExternalApiV1Controller@index');
|
Route::any('', 'app\cunkebao\controller\plan\PostExternalApiV1Controller@index');
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\cunkebao\controller;
|
||||||
|
|
||||||
|
use app\common\controller\BaseController;
|
||||||
|
use Exception;
|
||||||
|
use library\ResponseHelper;
|
||||||
|
use app\api\controller\UserController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 认证控制器
|
||||||
|
* 处理用户登录和身份验证
|
||||||
|
*/
|
||||||
|
class KeFuLoginController extends BaseController
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录
|
||||||
|
*
|
||||||
|
* @return \think\response\Json
|
||||||
|
*/
|
||||||
|
public function index($username = '', $password = '',$verifySessionId = '',$verifyCode = '')
|
||||||
|
{
|
||||||
|
$username = !empty($username) ? $username : $this->request->param('username', '');
|
||||||
|
$password = !empty($password) ? $password : $this->request->param('password', '');
|
||||||
|
|
||||||
|
$verifySessionId =!empty($verifySessionId) ? $verifySessionId : $this->request->param('verifySessionId', '');
|
||||||
|
$verifyCode = !empty($verifyCode) ? $verifyCode : $this->request->param('verifyCode', '');
|
||||||
|
|
||||||
|
|
||||||
|
if (empty($username) || empty($password)) {
|
||||||
|
return ResponseHelper::error('请输入账号密码');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//登录参数
|
||||||
|
$params = [
|
||||||
|
'grant_type' => 'password',
|
||||||
|
'username' => $username,
|
||||||
|
'password' => $password
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!empty($verifySessionId) && !empty($verifyCode)){
|
||||||
|
$params[] = 'verifysessionid:' . $verifySessionId;
|
||||||
|
$params[] = 'verifycode:' . $verifyCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//获取验证码
|
||||||
|
// $UserController = new UserController();
|
||||||
|
// $verifyCode = $UserController->getVerifyCode(true);
|
||||||
|
// $verifyCode = json_decode($verifyCode, true);
|
||||||
|
// if ($verifyCode['code'] != 200) {
|
||||||
|
// exit_data($verifyCode);
|
||||||
|
// }
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 调用登录接口获取token
|
||||||
|
$headerData = ['client:kefu-client'];
|
||||||
|
$header = setHeader($headerData, '', 'plain');
|
||||||
|
$result = requestCurl('https://s2.siyuguanli.com:9991/token', $params, 'POST', $header);
|
||||||
|
$token = handleApiResponse($result);
|
||||||
|
$userData['kefuData']['token'] = $token;
|
||||||
|
if (isset($token['access_token']) && !empty($token['access_token'])) {
|
||||||
|
$headerData = ['client:kefu-client'];
|
||||||
|
$header = setHeader($headerData, $token['access_token']);
|
||||||
|
$result = requestCurl('https://s2.siyuguanli.com:9991/api/account/self', [], 'GET', $header, 'json');
|
||||||
|
$self = handleApiResponse($result);
|
||||||
|
$userData['kefuData']['self'] = $self;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseHelper::success($userData, '登录成功');
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return ResponseHelper::error($e->getMessage(), $e->getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -58,7 +58,7 @@ class WorkbenchGroupPushJob
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// 获取所有工作台
|
// 获取所有工作台
|
||||||
$workbenches = Workbench::where(['status' => 1, 'type' => 3, 'isDel' => 0])->order('id desc')->select();
|
$workbenches = Workbench::where(['status' => 1, 'type' => 3, 'isDel' => 0,'id' => 178])->order('id desc')->select();
|
||||||
foreach ($workbenches as $workbench) {
|
foreach ($workbenches as $workbench) {
|
||||||
// 获取工作台配置
|
// 获取工作台配置
|
||||||
$config = WorkbenchGroupPush::where('workbenchId', $workbench->id)->find();
|
$config = WorkbenchGroupPush::where('workbenchId', $workbench->id)->find();
|
||||||
@@ -87,7 +87,7 @@ class WorkbenchGroupPushJob
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 发微信消息
|
// 发微信个人消息
|
||||||
public function sendMsgToGroup($workbench, $config, $msgConf)
|
public function sendMsgToGroup($workbench, $config, $msgConf)
|
||||||
{
|
{
|
||||||
// 消息拼接 msgType(1:文本 3:图片 43:视频 47:动图表情包(gif、其他表情包) 49:小程序/其他:图文、文件)
|
// 消息拼接 msgType(1:文本 3:图片 43:视频 47:动图表情包(gif、其他表情包) 49:小程序/其他:图文、文件)
|
||||||
@@ -117,7 +117,6 @@ class WorkbenchGroupPushJob
|
|||||||
}
|
}
|
||||||
// 建立WebSocket
|
// 建立WebSocket
|
||||||
$wsController = new WebSocketController(['userName' => $username, 'password' => $password, 'accountId' => $toAccountId]);
|
$wsController = new WebSocketController(['userName' => $username, 'password' => $password, 'accountId' => $toAccountId]);
|
||||||
|
|
||||||
foreach ($msgConf as $content) {
|
foreach ($msgConf as $content) {
|
||||||
$sendData = [];
|
$sendData = [];
|
||||||
$sqlData = [];
|
$sqlData = [];
|
||||||
@@ -294,82 +293,72 @@ class WorkbenchGroupPushJob
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$limit = ($config['pushType'] == 1) ? 10 : 1;
|
if ($config['pushType'] == 1) {
|
||||||
$order = ($config['pushOrder'] == 1) ? 'ci.sendTime desc, ci.id asc' : 'ci.sendTime desc, ci.id desc';
|
$limit = 10;
|
||||||
|
} else {
|
||||||
// 基础查询构建器
|
$limit = 1;
|
||||||
$baseQuery = function() use ($workbench, $contentids) {
|
|
||||||
return Db::name('content_library')->alias('cl')
|
|
||||||
->join('content_item ci', 'ci.libraryId = cl.id')
|
|
||||||
->where(['cl.isDel' => 0, 'ci.isDel' => 0])
|
|
||||||
->where('ci.sendTime <= ' . (time() + 60))
|
|
||||||
->whereIn('cl.id', $contentids)
|
|
||||||
->field('ci.id,ci.libraryId,ci.contentType,ci.title,ci.content,ci.resUrls,ci.urls,ci.comment,ci.sendTime');
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取未发送的内容
|
|
||||||
$unsentContent = $baseQuery()
|
|
||||||
->join('workbench_group_push_item wgpi', 'wgpi.contentId = ci.id and wgpi.workbenchId = ' . $workbench->id, 'left')
|
|
||||||
->where('wgpi.id', 'null')
|
|
||||||
->order($order)
|
|
||||||
->limit($limit)
|
|
||||||
->select();
|
|
||||||
|
|
||||||
if (!empty($unsentContent)) {
|
|
||||||
return $unsentContent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果不允许循环发送,直接返回空
|
|
||||||
if ($config['isLoop'] != 1) {
|
//推送顺序
|
||||||
return [];
|
if ($config['pushOrder'] == 1) {
|
||||||
|
$order = 'ci.sendTime desc, ci.id asc';
|
||||||
|
} else {
|
||||||
|
$order = 'ci.sendTime desc, ci.id desc';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 循环发送逻辑:检查是否需要标记循环完成
|
|
||||||
$this->checkAndResetLoop($workbench->id, $contentids);
|
|
||||||
|
|
||||||
// 获取下一个要发送的内容(从内容库中查询,排除isLoop为0的数据)
|
// 基础查询
|
||||||
$isPushIds = Db::name('workbench_group_push_item')
|
$query = Db::name('content_library')->alias('cl')
|
||||||
->where(['workbenchId' => $workbench->id,'isLoop' => 0])
|
|
||||||
->column('contentId');
|
|
||||||
$nextContent = $baseQuery()
|
|
||||||
->whereNotIn('ci.id', $isPushIds)
|
|
||||||
->group('ci.id')
|
|
||||||
->order('ci.id asc')
|
|
||||||
->limit($limit)
|
|
||||||
->select();
|
|
||||||
return $nextContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查循环状态
|
|
||||||
* @param int $workbenchId
|
|
||||||
* @param array $contentids
|
|
||||||
*/
|
|
||||||
private function checkAndResetLoop($workbenchId, $contentids)
|
|
||||||
{
|
|
||||||
// 统计总内容数
|
|
||||||
$totalCount = Db::name('content_library')->alias('cl')
|
|
||||||
->join('content_item ci', 'ci.libraryId = cl.id')
|
->join('content_item ci', 'ci.libraryId = cl.id')
|
||||||
|
->join('workbench_group_push_item wgpi', 'wgpi.contentId = ci.id and wgpi.workbenchId = ' . $workbench->id, 'left')
|
||||||
->where(['cl.isDel' => 0, 'ci.isDel' => 0])
|
->where(['cl.isDel' => 0, 'ci.isDel' => 0])
|
||||||
->where('ci.sendTime <= ' . (time() + 60))
|
->where('ci.sendTime <= ' . (time() + 60))
|
||||||
->whereIn('cl.id', $contentids)
|
->whereIn('cl.id', $contentids)
|
||||||
->count();
|
->field([
|
||||||
|
'ci.id',
|
||||||
|
'ci.libraryId',
|
||||||
|
'ci.contentType',
|
||||||
|
'ci.title',
|
||||||
|
'ci.content',
|
||||||
|
'ci.resUrls',
|
||||||
|
'ci.urls',
|
||||||
|
'ci.comment',
|
||||||
|
'ci.sendTime'
|
||||||
|
]);
|
||||||
|
// 复制 query
|
||||||
|
$query2 = clone $query;
|
||||||
|
$query3 = clone $query;
|
||||||
|
// 根据accountType处理不同的发送逻辑
|
||||||
|
if ($config['isLoop'] == 1) {
|
||||||
|
// 可以循环发送
|
||||||
|
// 1. 优先获取未发送的内容
|
||||||
|
$unsentContent = $query->where('wgpi.id', 'null')
|
||||||
|
->order($order)
|
||||||
|
->limit(0, $limit)
|
||||||
|
->select();
|
||||||
|
exit_data($unsentContent);
|
||||||
|
if (!empty($unsentContent)) {
|
||||||
|
return $unsentContent;
|
||||||
|
}
|
||||||
|
$lastSendData = Db::name('workbench_group_push_item')->where('workbenchId', $workbench->id)->order('id desc')->find();
|
||||||
|
$fastSendData = Db::name('workbench_group_push_item')->where('workbenchId', $workbench->id)->order('id asc')->find();
|
||||||
|
|
||||||
// 统计已发送内容数(排除isLoop为0的数据)
|
$sentContent = $query2->where('wgpi.contentId', '<', $lastSendData['contentId'])->order('wgpi.id ASC')->group('wgpi.contentId')->limit(0, $limit)->select();
|
||||||
$sentCount = Db::name('workbench_group_push_item')
|
|
||||||
->alias('wgpi')
|
|
||||||
->join('content_item ci', 'ci.id = wgpi.contentId')
|
|
||||||
->join('content_library cl', 'cl.id = ci.libraryId')
|
|
||||||
->where('wgpi.workbenchId', $workbenchId)
|
|
||||||
->where('wgpi.isLoop', 0)
|
|
||||||
->whereIn('cl.id', $contentids)
|
|
||||||
->count('DISTINCT wgpi.contentId');
|
|
||||||
|
|
||||||
// 记录循环状态
|
if (empty($sentContent)) {
|
||||||
if ($sentCount >= $totalCount) {
|
$sentContent = $query3->where('wgpi.contentId', '=', $fastSendData['contentId'])->order('wgpi.id ASC')->group('wgpi.contentId')->limit(0, $limit)->select();
|
||||||
Db::name('workbench_group_push_item')
|
}
|
||||||
->where(['workbenchId' => $workbenchId, 'isLoop' => 0])
|
return $sentContent;
|
||||||
->update(['isLoop' => 1]);
|
} else {
|
||||||
|
// 不能循环发送,只获取未发送的内容
|
||||||
|
$list = $query->where('wgpi.id', 'null')
|
||||||
|
->order($order)
|
||||||
|
->limit(0, $limit)
|
||||||
|
->select();
|
||||||
|
|
||||||
|
exit_data($list);
|
||||||
|
return $list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,4 +411,4 @@ class WorkbenchGroupPushJob
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user