内容库采集支持链接类型
This commit is contained in:
@@ -68,6 +68,7 @@ export default function ContentForm() {
|
||||
"text",
|
||||
"image",
|
||||
"video",
|
||||
"link",
|
||||
]);
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -126,7 +127,7 @@ export default function ContentForm() {
|
||||
setSelectedFriendsOptions(data.friendsGroupsOptions || []);
|
||||
setKeywordsInclude((data.keywordInclude || []).join(","));
|
||||
setKeywordsExclude((data.keywordExclude || []).join(","));
|
||||
setCatchType(data.catchType || ["text", "image", "video"]);
|
||||
setCatchType(data.catchType || ["text", "image", "video", "link"]);
|
||||
setAIPrompt(data.aiPrompt || "");
|
||||
// aiEnabled 为 AI 提示词开关,1 开启 0 关闭
|
||||
if (typeof data.aiEnabled !== "undefined") {
|
||||
@@ -275,7 +276,7 @@ export default function ContentForm() {
|
||||
来源渠道
|
||||
</label>
|
||||
<Tag color="blue" className={style["source-tag"]}>
|
||||
微信朋友圈
|
||||
微信
|
||||
</Tag>
|
||||
</div>
|
||||
|
||||
@@ -427,7 +428,7 @@ export default function ContentForm() {
|
||||
<span className={style["content-type-title"]}>采集内容类型</span>
|
||||
</div>
|
||||
<div className={style["content-type-buttons"]}>
|
||||
{["text", "image", "video"].map(type => (
|
||||
{["text", "image", "video", "link"].map(type => (
|
||||
<button
|
||||
key={type}
|
||||
className={`${style["content-type-btn"]} ${
|
||||
@@ -445,7 +446,9 @@ export default function ContentForm() {
|
||||
? "文本"
|
||||
: type === "image"
|
||||
? "图片"
|
||||
: "视频"}
|
||||
: type === "video"
|
||||
? "视频"
|
||||
: "链接"}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -182,18 +182,18 @@ class ContentLibraryController extends Controller
|
||||
|
||||
foreach ($list as $item) {
|
||||
$libraryIds[] = $item['id'];
|
||||
|
||||
|
||||
// 解析JSON字段
|
||||
$item['sourceFriends'] = json_decode($item['sourceFriends'] ?: '[]', true);
|
||||
$item['sourceGroups'] = json_decode($item['sourceGroups'] ?: '[]', true);
|
||||
$item['keywordInclude'] = json_decode($item['keywordInclude'] ?: '[]', true);
|
||||
$item['keywordExclude'] = json_decode($item['keywordExclude'] ?: '[]', true);
|
||||
|
||||
|
||||
// 收集好友和群组ID
|
||||
if (!empty($item['sourceFriends']) && $item['sourceType'] == 1) {
|
||||
$friendIdsByLibrary[$item['id']] = $item['sourceFriends'];
|
||||
}
|
||||
|
||||
|
||||
if (!empty($item['sourceGroups']) && $item['sourceType'] == 2) {
|
||||
$groupIdsByLibrary[$item['id']] = $item['sourceGroups'];
|
||||
}
|
||||
@@ -208,12 +208,12 @@ class ContentLibraryController extends Controller
|
||||
->where('isDel', 0)
|
||||
->group('libraryId')
|
||||
->select();
|
||||
|
||||
|
||||
foreach ($counts as $count) {
|
||||
$itemCounts[$count['libraryId']] = $count['count'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 批量查询好友信息
|
||||
$friendsInfoMap = [];
|
||||
$allFriendIds = [];
|
||||
@@ -222,7 +222,7 @@ class ContentLibraryController extends Controller
|
||||
$allFriendIds = array_merge($allFriendIds, $friendIds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!empty($allFriendIds)) {
|
||||
$allFriendIds = array_unique($allFriendIds);
|
||||
$friendsInfo = Db::name('wechat_friendship')->alias('wf')
|
||||
@@ -230,12 +230,12 @@ class ContentLibraryController extends Controller
|
||||
->join('wechat_account wa', 'wf.wechatId = wa.wechatId')
|
||||
->whereIn('wf.id', $allFriendIds)
|
||||
->select();
|
||||
|
||||
|
||||
foreach ($friendsInfo as $friend) {
|
||||
$friendsInfoMap[$friend['id']] = $friend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 批量查询群组信息
|
||||
$groupsInfoMap = [];
|
||||
$allGroupIds = [];
|
||||
@@ -244,14 +244,14 @@ class ContentLibraryController extends Controller
|
||||
$allGroupIds = array_merge($allGroupIds, $groupIds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!empty($allGroupIds)) {
|
||||
$allGroupIds = array_unique($allGroupIds);
|
||||
$groupsInfo = Db::name('wechat_group')->alias('g')
|
||||
->field('g.id, g.chatroomId, g.name, g.avatar, g.ownerWechatId')
|
||||
->whereIn('g.id', $allGroupIds)
|
||||
->select();
|
||||
|
||||
|
||||
foreach ($groupsInfo as $group) {
|
||||
$groupsInfoMap[$group['id']] = $group;
|
||||
}
|
||||
@@ -261,10 +261,10 @@ class ContentLibraryController extends Controller
|
||||
foreach ($list as &$item) {
|
||||
// 添加创建人名称
|
||||
$item['creatorName'] = $item['user']['username'] ?? '';
|
||||
|
||||
|
||||
// 添加内容项数量
|
||||
$item['itemCount'] = $itemCounts[$item['id']] ?? 0;
|
||||
|
||||
|
||||
// 处理好友信息
|
||||
if (!empty($friendIdsByLibrary[$item['id']])) {
|
||||
$selectedFriends = [];
|
||||
@@ -275,7 +275,7 @@ class ContentLibraryController extends Controller
|
||||
}
|
||||
$item['selectedFriends'] = $selectedFriends;
|
||||
}
|
||||
|
||||
|
||||
// 处理群组信息
|
||||
if (!empty($groupIdsByLibrary[$item['id']])) {
|
||||
$selectedGroups = [];
|
||||
@@ -286,7 +286,7 @@ class ContentLibraryController extends Controller
|
||||
}
|
||||
$item['selectedGroups'] = $selectedGroups;
|
||||
}
|
||||
|
||||
|
||||
unset($item['user']); // 移除关联数据
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ class ContentLibraryController extends Controller
|
||||
$companyId = $this->request->userInfo['companyId'];
|
||||
$userId = $this->request->userInfo['id'];
|
||||
$isAdmin = !empty($this->request->userInfo['isAdmin']);
|
||||
|
||||
|
||||
if (empty($id)) {
|
||||
return json(['code' => 400, 'msg' => '参数错误']);
|
||||
}
|
||||
@@ -344,7 +344,7 @@ class ContentLibraryController extends Controller
|
||||
$library['groupMembers'] = json_decode($library['groupMembers'] ?: [], true);
|
||||
$library['catchType'] = json_decode($library['catchType'] ?: [], true);
|
||||
$library['deviceGroups'] = json_decode($library['devices'] ?: [], true);
|
||||
unset($library['sourceFriends'], $library['sourceGroups'],$library['devices']);
|
||||
unset($library['sourceFriends'], $library['sourceGroups'], $library['devices']);
|
||||
|
||||
// 将时间戳转换为日期格式(精确到日)
|
||||
if (!empty($library['timeStart'])) {
|
||||
@@ -358,7 +358,7 @@ class ContentLibraryController extends Controller
|
||||
$library['friendsGroupsOptions'] = [];
|
||||
$library['wechatGroupsOptions'] = [];
|
||||
$library['groupMembersOptions'] = [];
|
||||
|
||||
|
||||
// 批量查询好友信息
|
||||
if (!empty($library['friendsGroups'])) {
|
||||
$friendIds = $library['friendsGroups'];
|
||||
@@ -392,7 +392,7 @@ class ContentLibraryController extends Controller
|
||||
// 键是群组ID,值是成员ID数组
|
||||
$allMemberIds = [];
|
||||
$groupMembersMap = [];
|
||||
|
||||
|
||||
if (is_array($library['groupMembers'])) {
|
||||
foreach ($library['groupMembers'] as $groupId => $memberIds) {
|
||||
if (is_array($memberIds) && !empty($memberIds)) {
|
||||
@@ -402,17 +402,17 @@ class ContentLibraryController extends Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!empty($allMemberIds)) {
|
||||
// 去重
|
||||
$allMemberIds = array_unique($allMemberIds);
|
||||
|
||||
|
||||
// 查询群成员信息
|
||||
$members = Db::table('s2_wechat_chatroom_member')
|
||||
->field('id, chatroomId, wechatId, nickname, avatar, conRemark, alias, friendType, createTime, updateTime')
|
||||
->whereIn('id', $allMemberIds)
|
||||
->select();
|
||||
|
||||
|
||||
// 将成员数据按ID建立索引
|
||||
$membersById = [];
|
||||
foreach ($members as $member) {
|
||||
@@ -421,7 +421,7 @@ class ContentLibraryController extends Controller
|
||||
$member['updateTime'] = !empty($member['updateTime']) ? date('Y-m-d H:i:s', $member['updateTime']) : '';
|
||||
$membersById[$member['id']] = $member;
|
||||
}
|
||||
|
||||
|
||||
// 按照群组ID分组返回
|
||||
$groupMembersOptions = [];
|
||||
foreach ($groupMembersMap as $groupId => $memberIds) {
|
||||
@@ -432,7 +432,7 @@ class ContentLibraryController extends Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$library['groupMembersOptions'] = $groupMembersOptions;
|
||||
} else {
|
||||
$library['groupMembersOptions'] = [];
|
||||
@@ -466,7 +466,6 @@ class ContentLibraryController extends Controller
|
||||
}
|
||||
|
||||
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '获取成功',
|
||||
@@ -616,7 +615,7 @@ class ContentLibraryController extends Controller
|
||||
['isDel', '=', 0]
|
||||
];
|
||||
|
||||
|
||||
|
||||
if (!$isAdmin) {
|
||||
$libraryWhere[] = ['userId', '=', $userId];
|
||||
}
|
||||
@@ -644,7 +643,7 @@ class ContentLibraryController extends Controller
|
||||
// 查询数据
|
||||
$list = ContentItem::where($where)
|
||||
->field('id,libraryId,type,title,content,contentAi,contentType,resUrls,urls,friendId,wechatId,wechatChatroomId,createTime,createMomentTime,createMessageTime,coverImage,ossUrls')
|
||||
->order('createMomentTime DESC,createTime DESC')
|
||||
->order('createTime DESC,createMomentTime DESC')
|
||||
->page($page, $limit)
|
||||
->select();
|
||||
|
||||
@@ -652,7 +651,7 @@ class ContentLibraryController extends Controller
|
||||
$friendIds = [];
|
||||
$chatroomIds = [];
|
||||
$wechatIds = [];
|
||||
|
||||
|
||||
foreach ($list as $item) {
|
||||
if ($item['type'] == 'moment' && !empty($item['friendId'])) {
|
||||
$friendIds[] = $item['friendId'];
|
||||
@@ -663,7 +662,7 @@ class ContentLibraryController extends Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 批量查询好友信息
|
||||
$friendInfoMap = [];
|
||||
if (!empty($friendIds)) {
|
||||
@@ -672,12 +671,12 @@ class ContentLibraryController extends Controller
|
||||
->whereIn('id', $friendIds)
|
||||
->field('id, nickname, avatar')
|
||||
->select();
|
||||
|
||||
|
||||
foreach ($friendInfos as $info) {
|
||||
$friendInfoMap[$info['id']] = $info;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 批量查询群成员信息
|
||||
$memberInfoMap = [];
|
||||
if (!empty($wechatIds)) {
|
||||
@@ -686,7 +685,7 @@ class ContentLibraryController extends Controller
|
||||
->whereIn('wechatId', $wechatIds)
|
||||
->field('wechatId, nickname, avatar')
|
||||
->select();
|
||||
|
||||
|
||||
foreach ($memberInfos as $info) {
|
||||
$memberInfoMap[$info['wechatId']] = $info;
|
||||
}
|
||||
@@ -697,14 +696,14 @@ class ContentLibraryController extends Controller
|
||||
foreach ($list as &$item) {
|
||||
// 使用AI内容(如果有)
|
||||
$item['content'] = !empty($item['contentAi']) ? $item['contentAi'] : $item['content'];
|
||||
|
||||
|
||||
// 处理JSON字段
|
||||
$item['resUrls'] = json_decode($item['resUrls'] ?: [], true);
|
||||
$item['urls'] = json_decode($item['urls'] ?: [], true);
|
||||
$item['ossUrls'] = json_decode($item['ossUrls'] ?: [], true);
|
||||
|
||||
if(!empty($item['ossUrls']) && count($item['ossUrls']) > 0){
|
||||
$item['resUrls'] = $item['ossUrls'];
|
||||
if (!empty($item['ossUrls']) && count($item['ossUrls']) > 0) {
|
||||
$item['resUrls'] = $item['ossUrls'];
|
||||
}
|
||||
|
||||
|
||||
@@ -722,7 +721,7 @@ class ContentLibraryController extends Controller
|
||||
// 设置发送者信息
|
||||
$item['senderNickname'] = '';
|
||||
$item['senderAvatar'] = '';
|
||||
|
||||
|
||||
// 从映射表获取发送者信息
|
||||
if ($item['type'] == 'moment' && !empty($item['friendId'])) {
|
||||
if (isset($friendInfoMap[$item['friendId']])) {
|
||||
@@ -738,7 +737,7 @@ class ContentLibraryController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
unset($item['contentAi'],$item['ossUrls']);
|
||||
unset($item['contentAi'], $item['ossUrls']);
|
||||
}
|
||||
|
||||
return json([
|
||||
@@ -849,8 +848,8 @@ class ContentLibraryController extends Controller
|
||||
['l.companyId', '=', $this->request->userInfo['companyId']]
|
||||
];
|
||||
|
||||
if(empty($this->request->userInfo['isAdmin'])){
|
||||
$where[] = ['l.userId', '=', $this->request->userInfo['id']];
|
||||
if (empty($this->request->userInfo['isAdmin'])) {
|
||||
$where[] = ['l.userId', '=', $this->request->userInfo['id']];
|
||||
}
|
||||
|
||||
// 查询内容项目是否存在并检查权限
|
||||
@@ -860,7 +859,7 @@ class ContentLibraryController extends Controller
|
||||
->find();
|
||||
|
||||
|
||||
if(empty($item)) {
|
||||
if (empty($item)) {
|
||||
return json(['code' => 500, 'msg' => '内容项目不存在或无权限操作']);
|
||||
}
|
||||
|
||||
@@ -887,7 +886,7 @@ class ContentLibraryController extends Controller
|
||||
$id = $this->request->param('id', 0);
|
||||
$userId = $this->request->userInfo['id'];
|
||||
$isAdmin = !empty($this->request->userInfo['isAdmin']);
|
||||
|
||||
|
||||
if (empty($id)) {
|
||||
return json(['code' => 400, 'msg' => '参数错误']);
|
||||
}
|
||||
@@ -897,7 +896,7 @@ class ContentLibraryController extends Controller
|
||||
['i.id', '=', $id],
|
||||
['i.isDel', '=', 0]
|
||||
];
|
||||
|
||||
|
||||
// 非管理员只能查看自己的内容项
|
||||
if (!$isAdmin) {
|
||||
$where[] = ['l.userId', '=', $userId];
|
||||
@@ -951,7 +950,7 @@ class ContentLibraryController extends Controller
|
||||
// 初始化发送者和群组信息
|
||||
$item['senderInfo'] = [];
|
||||
$item['groupInfo'] = [];
|
||||
|
||||
|
||||
// 批量获取关联信息
|
||||
if ($item['type'] == 'moment' && !empty($item['friendId'])) {
|
||||
// 获取朋友圈发送者信息
|
||||
@@ -961,7 +960,7 @@ class ContentLibraryController extends Controller
|
||||
->where('wf.id', $item['friendId'])
|
||||
->field('wf.id, wf.wechatId, wa.nickname, wa.avatar')
|
||||
->find();
|
||||
|
||||
|
||||
if ($friendInfo) {
|
||||
$item['senderInfo'] = $friendInfo;
|
||||
}
|
||||
@@ -971,10 +970,10 @@ class ContentLibraryController extends Controller
|
||||
->where('id', $item['wechatChatroomId'])
|
||||
->field('id, chatroomId, name, avatar, ownerWechatId')
|
||||
->find();
|
||||
|
||||
|
||||
if ($groupInfo) {
|
||||
$item['groupInfo'] = $groupInfo;
|
||||
|
||||
|
||||
// 如果有发送者信息,也获取发送者详情
|
||||
if (!empty($item['wechatId'])) {
|
||||
$senderInfo = Db::table('s2_wechat_chatroom_member')
|
||||
@@ -984,7 +983,7 @@ class ContentLibraryController extends Controller
|
||||
])
|
||||
->field('wechatId, nickname, avatar')
|
||||
->find();
|
||||
|
||||
|
||||
if ($senderInfo) {
|
||||
$item['senderInfo'] = $senderInfo;
|
||||
}
|
||||
@@ -1187,9 +1186,9 @@ class ContentLibraryController extends Controller
|
||||
->select()->toArray();
|
||||
|
||||
if (empty($libraries)) {
|
||||
return json_encode(['code' => 200, 'msg' => '没有可用的内容库配置'],256);
|
||||
return json_encode(['code' => 200, 'msg' => '没有可用的内容库配置'], 256);
|
||||
}
|
||||
|
||||
|
||||
$successCount = 0;
|
||||
$failCount = 0;
|
||||
$results = [];
|
||||
@@ -1212,13 +1211,13 @@ class ContentLibraryController extends Controller
|
||||
foreach ($libraries as $library) {
|
||||
try {
|
||||
$processedLibraries++;
|
||||
|
||||
|
||||
// 根据数据来源类型执行不同的采集逻辑
|
||||
$collectResult = [
|
||||
'status' => 'skipped',
|
||||
'message' => '没有配置数据来源'
|
||||
];
|
||||
|
||||
|
||||
switch ($library['sourceType']) {
|
||||
case 1: // 好友类型
|
||||
if (!empty($library['sourceFriends'])) {
|
||||
@@ -1269,7 +1268,7 @@ class ContentLibraryController extends Controller
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage()
|
||||
];
|
||||
|
||||
|
||||
// 记录错误日志
|
||||
\think\facade\Log::error('内容库采集错误: ' . $e->getMessage() . ' [库ID: ' . $library['id'] . ']');
|
||||
}
|
||||
@@ -1286,7 +1285,7 @@ class ContentLibraryController extends Controller
|
||||
'skipped' => $totalLibraries - $successCount - $failCount,
|
||||
'results' => $results
|
||||
]
|
||||
],256);
|
||||
], 256);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1303,14 +1302,14 @@ class ContentLibraryController extends Controller
|
||||
'message' => '没有指定要采集的好友'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
// 获取API配置
|
||||
$toAccountId = '';
|
||||
$username = Env::get('api.username2', '');
|
||||
$password = Env::get('api.password2', '');
|
||||
$needFetch = false;
|
||||
|
||||
|
||||
// 检查是否需要主动获取朋友圈
|
||||
if (!empty($username) && !empty($password)) {
|
||||
$toAccountId = Db::name('users')->where('account', $username)->value('s2_accountId');
|
||||
@@ -1336,10 +1335,10 @@ class ContentLibraryController extends Controller
|
||||
$totalMomentsCount = 0;
|
||||
$processedFriends = 0;
|
||||
$totalFriends = count($friends);
|
||||
|
||||
|
||||
// 获取采集类型限制
|
||||
$catchTypes = $library['catchType'] ?? [];
|
||||
|
||||
|
||||
foreach ($friends as $friend) {
|
||||
$processedFriends++;
|
||||
|
||||
@@ -1349,16 +1348,16 @@ class ContentLibraryController extends Controller
|
||||
// 执行切换好友命令
|
||||
$automaticAssign = new AutomaticAssign();
|
||||
$automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['id'], 'toAccountId' => $toAccountId], true);
|
||||
|
||||
|
||||
// 存入缓存
|
||||
$friendData = $friend;
|
||||
$friendData['friendId'] = $friend['id'];
|
||||
artificialAllotWechatFriend($friendData);
|
||||
|
||||
|
||||
// 执行采集朋友圈命令
|
||||
$webSocket = new WebSocketController(['userName' => $username, 'password' => $password, 'accountId' => $toAccountId]);
|
||||
$webSocket->getMoments(['wechatFriendId' => $friend['id'], 'wechatAccountId' => $friend['wechatAccountId']]);
|
||||
|
||||
|
||||
// 采集完毕切换回原账号
|
||||
$automaticAssign->allotWechatFriend(['wechatFriendId' => $friend['id'], 'toAccountId' => $friend['accountId']], true);
|
||||
} catch (\Exception $e) {
|
||||
@@ -1375,17 +1374,17 @@ class ContentLibraryController extends Controller
|
||||
])
|
||||
->order('createTime', 'desc')
|
||||
->group('snsId');
|
||||
|
||||
|
||||
// 如果启用了时间限制
|
||||
if ($library['timeEnabled'] && $library['timeStart'] > 0 && $library['timeEnd'] > 0) {
|
||||
$query->whereBetween('createTime', [$library['timeStart'], $library['timeEnd']]);
|
||||
}
|
||||
|
||||
|
||||
// 如果指定了采集类型,进行过滤
|
||||
/*if (!empty($catchTypes)) {
|
||||
$query->whereIn('type', $catchTypes);
|
||||
}*/
|
||||
|
||||
|
||||
// 获取最近20条朋友圈
|
||||
$moments = $query->page(1, 100)->select();
|
||||
if (empty($moments)) {
|
||||
@@ -1400,24 +1399,24 @@ class ContentLibraryController extends Controller
|
||||
foreach ($moments as $moment) {
|
||||
// 处理关键词过滤
|
||||
$content = $moment['content'] ?? '';
|
||||
|
||||
|
||||
// 应用关键词过滤
|
||||
if (!$this->passKeywordFilter($content, $library['keywordInclude'], $library['keywordExclude'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* // 如果启用了AI处理
|
||||
if (!empty($library['aiEnabled']) && !empty($content)) {
|
||||
try {
|
||||
$contentAi = $this->aiRewrite($library, $content);
|
||||
if (!empty($contentAi)) {
|
||||
$moment['contentAi'] = $contentAi;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
\think\facade\Log::error('AI处理失败: ' . $e->getMessage() . ' [朋友圈ID: ' . ($moment['id'] ?? 'unknown') . ']');
|
||||
$moment['contentAi'] = '';
|
||||
}
|
||||
}*/
|
||||
/* // 如果启用了AI处理
|
||||
if (!empty($library['aiEnabled']) && !empty($content)) {
|
||||
try {
|
||||
$contentAi = $this->aiRewrite($library, $content);
|
||||
if (!empty($contentAi)) {
|
||||
$moment['contentAi'] = $contentAi;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
\think\facade\Log::error('AI处理失败: ' . $e->getMessage() . ' [朋友圈ID: ' . ($moment['id'] ?? 'unknown') . ']');
|
||||
$moment['contentAi'] = '';
|
||||
}
|
||||
}*/
|
||||
|
||||
// 保存到内容库的content_item表
|
||||
if ($this->saveMomentToContentItem($moment, $library['id'], $friend, $nickname)) {
|
||||
@@ -1441,7 +1440,7 @@ class ContentLibraryController extends Controller
|
||||
|
||||
$totalMomentsCount += $friendMomentsCount;
|
||||
}
|
||||
|
||||
|
||||
// 每处理5个好友,释放一次内存
|
||||
if ($processedFriends % 5 == 0 && $processedFriends < $totalFriends) {
|
||||
gc_collect_cycles();
|
||||
@@ -1473,7 +1472,7 @@ class ContentLibraryController extends Controller
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 应用关键词过滤规则
|
||||
* @param string $content 内容文本
|
||||
@@ -1487,7 +1486,7 @@ class ContentLibraryController extends Controller
|
||||
if (empty($content)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 检查是否包含必须关键词
|
||||
$includeMatch = empty($includeKeywords);
|
||||
if (!empty($includeKeywords)) {
|
||||
@@ -1512,7 +1511,7 @@ class ContentLibraryController extends Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true; // 通过所有过滤条件
|
||||
}
|
||||
|
||||
@@ -1559,7 +1558,7 @@ class ContentLibraryController extends Controller
|
||||
// groupMembers格式: {"826825": ["413771", "413769"], "840818": ["496300", "496302"]}
|
||||
// 键是群组ID,值是该群组的成员ID数组
|
||||
// 需要按群组分组处理,确保每个群组只采集该群组配置的成员
|
||||
|
||||
|
||||
// 建立群组ID到成员ID数组的映射
|
||||
$groupIdToMemberIds = [];
|
||||
if (is_array($groupMembers)) {
|
||||
@@ -1575,7 +1574,7 @@ class ContentLibraryController extends Controller
|
||||
'message' => '未找到有效的群成员ID'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
// 为每个群组查询成员信息,建立群组ID到成员wechatId数组的映射
|
||||
$groupIdToMemberWechatIds = [];
|
||||
foreach ($groupIdToMemberIds as $groupId => $memberIds) {
|
||||
@@ -1584,14 +1583,14 @@ class ContentLibraryController extends Controller
|
||||
->field('id, wechatId')
|
||||
->whereIn('id', $memberIds)
|
||||
->select();
|
||||
|
||||
|
||||
$wechatIds = [];
|
||||
foreach ($members as $member) {
|
||||
if (!empty($member['wechatId'])) {
|
||||
$wechatIds[] = $member['wechatId'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!empty($wechatIds)) {
|
||||
$groupIdToMemberWechatIds[$groupId] = array_unique($wechatIds);
|
||||
}
|
||||
@@ -1636,7 +1635,7 @@ class ContentLibraryController extends Controller
|
||||
foreach ($groupMessages as $message) {
|
||||
$chatroomId = $message['wechatChatroomId'];
|
||||
$senderWechatId = $message['senderWechatId'] ?? '';
|
||||
|
||||
|
||||
// 找到对应的群组信息
|
||||
$groupInfo = null;
|
||||
foreach ($groups as $group) {
|
||||
@@ -1649,20 +1648,20 @@ class ContentLibraryController extends Controller
|
||||
if (!$groupInfo) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// 检查该消息的发送者是否在该群组的配置成员列表中
|
||||
$groupId = $groupInfo['id'];
|
||||
if (!isset($groupIdToMemberWechatIds[$groupId])) {
|
||||
// 该群组没有配置成员,跳过
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// 检查发送者是否在配置的成员列表中
|
||||
if (!in_array($senderWechatId, $groupIdToMemberWechatIds[$groupId])) {
|
||||
// 发送者不在该群组的配置成员列表中,跳过
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!isset($groupedMessages[$chatroomId])) {
|
||||
$groupedMessages[$chatroomId] = [
|
||||
'count' => 0,
|
||||
@@ -2025,7 +2024,7 @@ class ContentLibraryController extends Controller
|
||||
|
||||
// 如果不存在,则创建新的内容项目
|
||||
|
||||
if(empty($exists)){
|
||||
if (empty($exists)) {
|
||||
$exists = new ContentItem();
|
||||
}
|
||||
|
||||
@@ -2087,7 +2086,8 @@ class ContentLibraryController extends Controller
|
||||
}
|
||||
|
||||
$resUrls = [];
|
||||
|
||||
$links = [];
|
||||
$contentType = 4;
|
||||
$content = '';
|
||||
switch ($message['msgType']) {
|
||||
case 1: // 文字
|
||||
@@ -2110,34 +2110,25 @@ class ContentLibraryController extends Controller
|
||||
break;
|
||||
case 42: //名片
|
||||
return false;
|
||||
case 49: //文件
|
||||
$links = json_decode($message['content'],true);
|
||||
return false;
|
||||
case 49: //文件 链接
|
||||
$link = json_decode($message['content'], true);
|
||||
switch ($link['type']) {
|
||||
case 'link':
|
||||
$links[] = [
|
||||
'desc' => $link['desc'],
|
||||
'image' => $link['thumbPath'],
|
||||
'url' => $link['url'],
|
||||
];
|
||||
$contentType = 2;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*// 提取消息内容中的链接
|
||||
$content = $message['content'] ?? '';
|
||||
$links = [];
|
||||
$pattern = '/https?:\/\/[-A-Za-z0-9+&@#\/%?=~_|!:,.;]+[-A-Za-z0-9+&@#\/%=~_|]/';
|
||||
preg_match_all($pattern, $content, $matches);
|
||||
|
||||
if (!empty($matches[0])) {
|
||||
$links = $matches[0];
|
||||
}
|
||||
|
||||
// 提取可能的图片URL
|
||||
$resUrls = [];
|
||||
if (isset($message['imageUrl']) && !empty($message['imageUrl'])) {
|
||||
$resUrls[] = $message['imageUrl'];
|
||||
}
|
||||
|
||||
// 判断内容类型 (0=未知, 1=图片, 2=链接, 3=视频, 4=文本, 5=小程序, 6=图文)
|
||||
$contentType = $this->determineContentType($content, $resUrls, $links);
|
||||
*/
|
||||
|
||||
|
||||
// 创建新的内容项目
|
||||
$item = new ContentItem();
|
||||
$item->libraryId = $libraryId;
|
||||
@@ -2162,17 +2153,18 @@ class ContentLibraryController extends Controller
|
||||
if (!empty($resUrls[0])) {
|
||||
$item->coverImage = $resUrls[0];
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
$item->resUrls = json_encode([], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
// 处理链接
|
||||
if (!empty($links)) {
|
||||
$item->urls = json_encode($links, JSON_UNESCAPED_UNICODE);
|
||||
}else{
|
||||
} else {
|
||||
$item->urls = json_encode([], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
$item->ossUrls = json_encode([], JSON_UNESCAPED_UNICODE);
|
||||
|
||||
// 设置商品信息(需根据消息内容解析)
|
||||
$this->extractProductInfo($item, $content);
|
||||
|
||||
@@ -2593,7 +2585,7 @@ class ContentLibraryController extends Controller
|
||||
['companyId', '=', $companyId],
|
||||
['isDel', '=', 0]
|
||||
];
|
||||
|
||||
|
||||
if (!$isAdmin) {
|
||||
$libraryWhere[] = ['userId', '=', $userId];
|
||||
}
|
||||
@@ -2623,13 +2615,13 @@ class ContentLibraryController extends Controller
|
||||
// 下载远程文件到临时目录
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'excel_import_') . '.' . $urlExt;
|
||||
$fileContent = @file_get_contents($fileUrl);
|
||||
|
||||
|
||||
if ($fileContent === false) {
|
||||
return json(['code' => 400, 'msg' => '下载远程文件失败,请检查URL是否可访问']);
|
||||
}
|
||||
|
||||
|
||||
file_put_contents($tmpFile, $fileContent);
|
||||
|
||||
|
||||
} elseif ($file) {
|
||||
// 处理上传的文件
|
||||
$ext = strtolower($file->getExtension());
|
||||
@@ -2654,7 +2646,7 @@ class ContentLibraryController extends Controller
|
||||
// 加载Excel文件
|
||||
$excel = PHPExcel_IOFactory::load($tmpFile);
|
||||
$sheet = $excel->getActiveSheet();
|
||||
|
||||
|
||||
// 获取所有图片
|
||||
$images = [];
|
||||
try {
|
||||
@@ -2663,14 +2655,14 @@ class ContentLibraryController extends Controller
|
||||
if ($drawing instanceof \PHPExcel_Worksheet_Drawing) {
|
||||
$coordinates = $drawing->getCoordinates();
|
||||
$imagePath = $drawing->getPath();
|
||||
|
||||
|
||||
// 如果是嵌入的图片(zip://格式),提取到临时文件
|
||||
if (strpos($imagePath, 'zip://') === 0) {
|
||||
$zipEntry = str_replace('zip://', '', $imagePath);
|
||||
$zipEntry = explode('#', $zipEntry);
|
||||
$zipFile = $zipEntry[0];
|
||||
$imageEntry = isset($zipEntry[1]) ? $zipEntry[1] : '';
|
||||
|
||||
|
||||
if (!empty($imageEntry)) {
|
||||
$zip = new \ZipArchive();
|
||||
if ($zip->open($zipFile) === true) {
|
||||
@@ -2691,11 +2683,11 @@ class ContentLibraryController extends Controller
|
||||
// 处理内存中的图片
|
||||
$coordinates = $drawing->getCoordinates();
|
||||
$imageResource = $drawing->getImageResource();
|
||||
|
||||
|
||||
if ($imageResource) {
|
||||
$tempImageFile = tempnam(sys_get_temp_dir(), 'excel_img_') . '.png';
|
||||
$imageType = $drawing->getMimeType();
|
||||
|
||||
|
||||
switch ($imageType) {
|
||||
case 'image/png':
|
||||
imagepng($imageResource, $tempImageFile);
|
||||
@@ -2710,7 +2702,7 @@ class ContentLibraryController extends Controller
|
||||
default:
|
||||
imagepng($imageResource, $tempImageFile);
|
||||
}
|
||||
|
||||
|
||||
$images[$coordinates] = $tempImageFile;
|
||||
}
|
||||
}
|
||||
@@ -2737,7 +2729,7 @@ class ContentLibraryController extends Controller
|
||||
try {
|
||||
foreach ($data as $rowIndex => $row) {
|
||||
$rowNum = $rowIndex + 3; // Excel行号(从3开始,因为前两行是标题和说明)
|
||||
|
||||
|
||||
// 跳过空行
|
||||
if (empty(array_filter($row))) {
|
||||
continue;
|
||||
@@ -2752,7 +2744,7 @@ class ContentLibraryController extends Controller
|
||||
$content = isset($row[3]) ? trim($row[3]) : '';
|
||||
$selfReply = isset($row[4]) ? trim($row[4]) : '';
|
||||
$displayForm = isset($row[5]) ? trim($row[5]) : '';
|
||||
|
||||
|
||||
// 如果没有朋友圈文案,跳过
|
||||
if (empty($content)) {
|
||||
continue;
|
||||
@@ -2763,11 +2755,11 @@ class ContentLibraryController extends Controller
|
||||
for ($colIndex = 6; $colIndex <= 14; $colIndex++) {
|
||||
$columnLetter = $this->columnLetter($colIndex);
|
||||
$cellCoordinate = $columnLetter . $rowNum;
|
||||
|
||||
|
||||
// 检查是否有图片
|
||||
if (isset($images[$cellCoordinate])) {
|
||||
$imagePath = $images[$cellCoordinate];
|
||||
|
||||
|
||||
// 上传图片到OSS
|
||||
$imageExt = 'jpg';
|
||||
if (file_exists($imagePath)) {
|
||||
@@ -2779,10 +2771,10 @@ class ContentLibraryController extends Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$objectName = AliyunOSS::generateObjectName('excel_img_' . $rowNum . '_' . ($colIndex - 5) . '.' . $imageExt);
|
||||
$uploadResult = AliyunOSS::uploadFile($imagePath, $objectName);
|
||||
|
||||
|
||||
if ($uploadResult['success']) {
|
||||
$imageUrls[] = $uploadResult['url'];
|
||||
}
|
||||
@@ -2798,7 +2790,7 @@ class ContentLibraryController extends Controller
|
||||
$year = $matches[1];
|
||||
$month = str_pad($matches[2], 2, '0', STR_PAD_LEFT);
|
||||
$day = str_pad($matches[3], 2, '0', STR_PAD_LEFT);
|
||||
|
||||
|
||||
// 解析时间
|
||||
$hour = 0;
|
||||
$minute = 0;
|
||||
@@ -2806,11 +2798,11 @@ class ContentLibraryController extends Controller
|
||||
$hour = intval($timeMatches[1]);
|
||||
$minute = intval($timeMatches[2]);
|
||||
}
|
||||
|
||||
|
||||
$createMomentTime = strtotime("{$year}-{$month}-{$day} {$hour}:{$minute}:00");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($createMomentTime == 0) {
|
||||
$createMomentTime = time();
|
||||
}
|
||||
@@ -2833,12 +2825,12 @@ class ContentLibraryController extends Controller
|
||||
$item->urls = json_encode([], JSON_UNESCAPED_UNICODE);
|
||||
$item->createMomentTime = $createMomentTime;
|
||||
$item->createTime = time();
|
||||
|
||||
|
||||
// 设置封面图片
|
||||
if (!empty($imageUrls[0])) {
|
||||
$item->coverImage = $imageUrls[0];
|
||||
}
|
||||
|
||||
|
||||
// 保存其他信息到contentData
|
||||
$contentData = [
|
||||
'date' => $date,
|
||||
@@ -2848,7 +2840,7 @@ class ContentLibraryController extends Controller
|
||||
'selfReply' => $selfReply
|
||||
];
|
||||
$item->contentData = json_encode($contentData, JSON_UNESCAPED_UNICODE);
|
||||
|
||||
|
||||
$item->save();
|
||||
$successCount++;
|
||||
|
||||
@@ -2885,7 +2877,7 @@ class ContentLibraryController extends Controller
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
|
||||
|
||||
// 清理临时文件
|
||||
foreach ($images as $imagePath) {
|
||||
if (file_exists($imagePath) && strpos($imagePath, sys_get_temp_dir()) === 0) {
|
||||
@@ -2895,7 +2887,7 @@ class ContentLibraryController extends Controller
|
||||
if (file_exists($tmpFile) && strpos($tmpFile, sys_get_temp_dir()) === 0) {
|
||||
@unlink($tmpFile);
|
||||
}
|
||||
|
||||
|
||||
return json(['code' => 500, 'msg' => '导入失败:' . $e->getMessage()]);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ class MessageFriendsListJob
|
||||
$data = $response['data'];
|
||||
|
||||
// 判断是否有下一页
|
||||
if (!empty($data) && count($data['results']) > 0) {
|
||||
if (!empty($data) && count($data) > 0) {
|
||||
// 有下一页,将下一页任务添加到队列
|
||||
$nextPageIndex = $pageIndex + 1;
|
||||
$this->addNextPageToQueue($nextPageIndex, $pageSize);
|
||||
|
||||
Reference in New Issue
Block a user